Skip to content

Instantly share code, notes, and snippets.

@ossicode
Created January 16, 2013 08:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ossicode/4545556 to your computer and use it in GitHub Desktop.
Save ossicode/4545556 to your computer and use it in GitHub Desktop.
2132 Flash Test
/*
* clock.c
*
* Created on: 2013. 1. 16.
* Author: OSSI
*/
#include "clock.h"
// main clock will be shared via system
static volatile uint8_t clockMode;
uint8_t clock_getMode(void)
{
return clockMode;
}
uint8_t clock_setup(void)
{
// after POR: MCLK = SMCLK = DCO ~ 1.2MHz
// set DCO speed to calibrated 8MHz
// NO VLOCLK use
BCSCTL1 = CALBC1_8MHZ;
DCOCTL = CALDCO_8MHZ;
// TODO: Capacitor setting for ACLK
return CLOCK_DCO_LFXT1;
}
void clock_dividerSetup(uint8_t MCLKDividerSelect, uint8_t SMCLKDividerSelect, uint8_t ACLKDividerSelect)
{
// reset divider first
// reset ACLK divider
BCSCTL1 &= 0xCF; // Clear BIT5 and BIT4
// select ACLK Divider
BCSCTL1 |= ACLKDividerSelect;
// reset MCLK, SMCLK divider
BCSCTL2 &= 0x00; // Clear BIT5,BIT4, BIT2, BIT1 and reset as 2132 only use DCO
// select MCLK Divider
BCSCTL2 |= MCLKDividerSelect;
// select SMCLK Divider
BCSCTL2 |= SMCLKDividerSelect;
}
/*
* clock.h
*
* Created on: 2013. 1. 16.
* Author: OSSI
*/
/* Clock setting for OSSI MSP430F2132
*
* default: CLOCK_DCO_LFXT1
* DCO Calibrated 8MHz
* LFXT1 Low Power Mode: 32.768 kHz
* MCLK = DCOCLK / SMCLK = DCOCLK / ACLK = LFXT1
*
* TODO: LFXT1 to VLO switching?
*
*/
#ifndef CLOCK_H_
#define CLOCK_H_
#include "msp430x21x2.h"
#include "ossitypes.h"
#include "debug.h"
#define CLOCK_DCO_LFXT1 (1)
#define MCLK_DIVIDED_BY_1 DIVM_0 /* MCLK Divider 0: /1 */
#define MCLK_DIVIDED_BY_2 DIVM_1 /* MCLK Divider 1: /2 */
#define MCLK_DIVIDED_BY_4 DIVM_2 /* MCLK Divider 2: /4 */
#define MCLK_DIVIDED_BY_8 DIVM_3 /* MCLK Divider 3: /8 */
#define SMCLK_DIVIDED_BY_1 DIVS_0 /* SMCLK Divider 0: /1 */
#define SMCLK_DIVIDED_BY_2 DIVS_1 /* SMCLK Divider 1: /2 */
#define SMCLK_DIVIDED_BY_4 DIVS_2 /* SMCLK Divider 2: /4 */
#define SMCLK_DIVIDED_BY_8 DIVS_3 /* SMCLK Divider 3: /8 */
#define ACLK_DIVIDED_BY_1 DIVA_0 /* ACLK Divider 0: /1 */
#define ACLK_DIVIDED_BY_2 DIVA_1 /* ACLK Divider 1: /2 */
#define ACLK_DIVIDED_BY_4 DIVA_2 /* ACLK Divider 2: /4 */
#define ACLK_DIVIDED_BY_8 DIVA_3 /* ACLK Divider 3: /8 */
uint8_t clock_getMode(void);
uint8_t clock_setup(void);
void clock_dividerSetup(uint8_t MCLKDividerSelect, uint8_t SMCLKDividerSelect, uint8_t ACLKDividerSelect);
#endif /* CLOCK_H_ */
/* --COPYRIGHT--,BSD
* Copyright (c) 2012, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --/COPYRIGHT--*/
//*****************************************************************************
//
//debug.h - Macros for assisting debug of the driver library.
//
//
//This is part of revision 0001 of the MSP430 Peripheral Driver Library.
//
//*****************************************************************************
#ifndef __DEBUG_H__
#define __DEBUG_H__
//*****************************************************************************
//
//Prototype for the function that is called when an invalid argument is passed
//to an API. This is only used when doing a DEBUG build.
//
//*****************************************************************************
extern void __error__ (char *pcFilename, unsigned long ulLine);
//*****************************************************************************
//
//The ASSERT macro, which does the actual assertion checking. Typically, this
//will be for procedure arguments.
//
//*****************************************************************************
#ifdef DEBUG
#define ASSERT(expr) { \
if (!(expr)) \
{ \
__error__(__FILE__, __LINE__); \
} \
}
#else
#define ASSERT(expr)
#endif
#endif //__DEBUG_H__
/*
* flash.c
*
* Created on: 2013. 1. 16.
* Author: OSSI
*/
#include "flash.h"
static volatile uint8_t flashStatus;
uint8_t flash_writeBegin(uint8_t flashClockSelect, uint8_t flashClockDivider)
{
// TODO: check boundary for the below
// flashClockSelect value 0~3
// flashClockDivider value 0~63
// Set flash timing frequency from 257kHz to 476kHz.
// TODO: how to act when clock system is changed????
// Stop Watchdog timer
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
FCTL2 = FWKEY + flashClockSelect + flashClockDivider;
// FCTL2 = FWKEY + FSSEL0 + FN0; // MCLK/2 for Flash Timing Generator
return 1;
}
uint8_t flash_writeEnd(void)
{
// TODO: Enable WDT if system needs
return 1;
}
uint8_t flash_writeData(uint8_t address, uint8_t byteCount, uint8_t *data)
{
// Erase D
// Copy C to D Except data we want to modify
// Erase C
// write data we want to modify
// copy D data to C except modified data position
// TODO: check boundary condition
// address 0 ~ 63 / byteCount 1 ~ 64
if((FLASH_SEG_C_START_ADDR + address + byteCount -1 ) > FLASH_SEG_C_LAST_ADDR )
{
return 0;
}
// TODO: check system voltage
// We don't check system voltage separately as we use TPS3838 voltage supervisor externally
_DINT();
uint8_t *Flash_ptrC;
uint8_t *default_ptrC;
uint8_t *Flash_ptrD;
uint8_t *default_ptrD;
uint8_t *data_ptr;
volatile uint8_t i;
Flash_ptrC =default_ptrC= (uint8_t *) (FLASH_SEG_C_START_ADDR);
Flash_ptrD =default_ptrD= (uint8_t *)(FLASH_SEG_D_START_ADDR);
data_ptr = data;
// Erase D
FCTL1 = FWKEY + ERASE; // Set Erase bit
FCTL3 = FWKEY; // Clear Lock bit
*Flash_ptrD = 0;
FCTL1 = FWKEY; // Clear WRT bit
FCTL3 = FWKEY + LOCK;
// Copy C to D Except data we want to modify
FCTL1 = FWKEY + WRT; // Set WRT bit for write operation
FCTL3 = FWKEY; // Clear Lock bit
for (i=0; i < FLASH_SEG_D_SIZE; i++)
{
if((Flash_ptrC < default_ptrC+ address) || (Flash_ptrC > default_ptrC + address + byteCount-1))
{
*Flash_ptrD = *Flash_ptrC; // Write value to flash
}
Flash_ptrD++;
Flash_ptrC++;
}
FCTL1 = FWKEY; // Clear WRT bit
FCTL3 = FWKEY + LOCK; // Set LOCK bit
Flash_ptrC = default_ptrC; // Initialize Flash pointer
Flash_ptrD =default_ptrD; // Initialize Flash segment B pointer
// Erase C
FCTL1 = FWKEY + ERASE; // Set Erase bit
FCTL3 = FWKEY; // Clear Lock bit
*Flash_ptrC = 0;
FCTL1 = FWKEY; // Clear WRT bit
FCTL3 = FWKEY + LOCK; // Set LOCK bit
// Write Data We want to modify
Flash_ptrC = (uint8_t *)(FLASH_SEG_C_START_ADDR + address); // Initialize Flash pointer
FCTL1 = FWKEY + WRT; // Set WRT bit for write operation
FCTL3 = FWKEY; // Clear Lock bit
for (i=0; i < byteCount; i++)
{
*Flash_ptrC++ = *data_ptr++; // Write value to flash
}
Flash_ptrC = default_ptrC; // Initialize Flash pointer
Flash_ptrD =default_ptrD; // Initialize Flash segment B pointer
// Copy D to C except modified data position
for (i=0; i < FLASH_SEG_C_SIZE; i++)
{
if((Flash_ptrD < default_ptrD + address) || (Flash_ptrD > default_ptrD + address + byteCount-1))
{
*Flash_ptrC = *Flash_ptrD; // Write value to flash
}
Flash_ptrD++;
Flash_ptrC++;
}
FCTL1 = FWKEY; // Clear WRT bit
FCTL3 = FWKEY + LOCK;
_EINT();
return 1;
}
uint8_t flash_readData(uint8_t address, uint8_t byteCount, uint8_t *data)
{
uint8_t* flash_ptr;
uint8_t* data_ptr;
volatile uint8_t i;
if((FLASH_SEG_C_START_ADDR + address + byteCount -1 ) > FLASH_SEG_C_LAST_ADDR )
{
return 0;
}
flash_ptr = (uint8_t *)(FLASH_SEG_C_START_ADDR + address);
data_ptr = (uint8_t *)data;
for(i = 0; i < byteCount; i++)
{
*data_ptr = *flash_ptr;
flash_ptr++;
data_ptr++;
}
return 1;
}
/*
* flash.h
*
* Created on: 2013. 1. 16.
* Author: OSSI
*/
#ifndef FLASH_H_
#define FLASH_H_
#include "ossibeacon.h"
// This flash module use Segment C as main
// and Segment D for buffering
// So All result are stored to Segment C
// And read from Segment D
// DO NOT CHANGE THIS!!!
// Using Information Memory Section
// To store system status
// SEG C 64 Bytes
// SEG D 64 Bytes
//
// DO NOT USE SEG A as SEG A contains calibration data!!!!!
//
// Use below address for boundary check
#define FLASH_SEG_C_START_ADDR (0x1040)
#define FLASH_SEG_C_LAST_ADDR (0x107F)
#define FLASH_SEG_D_START_ADDR (0x1000)
#define FLASH_SEG_D_LAST_ADDR (0x103F)
#define FLASH_SEG_C_SIZE (64)
#define FLASH_SEG_D_SIZE (64)
#define FLASH_ACLK FSSEL_0 /* Flash clock select: 0 - ACLK */
#define FLASH_MCLK FSSEL_1 /* Flash clock select: 1 - MCLK */
#define FLASH_SMCLK FSSEL_2 /* Flash clock select: 2 - SMCLK */
#define FLASH_SMCLK2 FSSEL_3 /* Flash clock select: 3 - SMCLK */
uint8_t flash_writeBegin(uint8_t flashClockSelect, uint8_t flashClockDivider);
uint8_t flash_writeData(uint8_t address, uint8_t byteCount, uint8_t *data);
uint8_t flash_writeEnd(void);
uint8_t flash_readData(uint8_t address, uint8_t byteCount, uint8_t *data);
#endif /* FLASH_H_ */
#include "ossibeacon.h"
#include "flash.h"
/*
* main.c
*/
uint8_t data[64] ={0};
uint8_t flashData[64] ={0};
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
// to check timing
IO_DIRECTION(LED,OUTPUT);
IO_SET(LED,LOW);
clock_setup();
while(1)
{
volatile uint8_t i;
for(i =0;i < 64;i++)
{
data[i]=22;
}
// set divider for flash write
clock_dividerSetup(MCLK_DIVIDED_BY_1, SMCLK_DIVIDED_BY_8, ACLK_DIVIDED_BY_1);
// 8MHz / 8 / (2+1) = 333 kHz
IO_SET(LED,TOGGLE);
flash_writeBegin(FLASH_SMCLK,2);
flash_writeData(0,64,data);
flash_writeEnd();
IO_SET(LED,TOGGLE);
flash_readData(0,64,flashData);
// restore divider for the system
clock_dividerSetup(MCLK_DIVIDED_BY_1, SMCLK_DIVIDED_BY_1, ACLK_DIVIDED_BY_1);
// _NOP() for break point
_NOP();
// when debugging flash module, make sure you go to LPM
// other wise flash might be hard..
LPM3;
}
}
/*
* ossibeacon.h
*
* Created on: 2012. 12. 22.
* Author: OSSI
*/
#ifndef OSSIBEACON_H_
#define OSSIBEACON_H_
#include "msp430x21x2.h"
#include "debug.h"
#include "system.h"
#include "clock.h"
#include "ossitypes.h"
#include "util.h"
#endif /* OSSIBEACON_H_ */
/*
* ossitypes.h
*
* Created on: 2012. 12. 22.
* Author: OSSI
*/
#ifndef OSSITYPES_H_
#define OSSITYPES_H_
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short int uint16_t;
typedef signed short int int16_t;
typedef unsigned long int uint32_t;
typedef signed long int int32_t;
#endif /* OSSITYPES_H_ */
/*
* setup2132.c
*
* Created on: 2012. 12. 19.
* Author: OSSI
*/
#include "system.h"
void int_wdt_disable(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
}
void IO_setup(void)
{
// general IO init
// TODO: set unused pins!!!
IO_DIRECTION(LED,OUTPUT);
IO_SET(LED,LOW);
}
void ext_wdt_setup(void)
{
IO_DIRECTION(EXTWDT,OUTPUT);
}
void ext_wdt_rst(void)
{
//LOW-HIGH-LOW
IO_SET(EXTWDT,LOW);
delay_ms(1);
IO_SET(EXTWDT,HIGH);
delay_ms(1);
IO_SET(EXTWDT,LOW);
}
/*
* setup2132.h
*
* Created on: 2012. 12. 19.
* Author: OSSI
*/
#ifndef SETUP2132_H_
#define SETUP2132_H_
#include "msp430x21x2.h"
#include "ossitypes.h"
#include "util.h"
// System IO Define
#define LED_PORT 3
#define LED_PIN 0
#define EXTWDT_PORT 2
#define EXTWDT_PIN 2
void int_wdt_disable(void);
void IO_setup(void);
void ext_wdt_setup(void);
void ext_wdt_rst(void);
#endif /* SETUP2132_H_ */
/*
* util.c
*
* Created on: 2012. 12. 19.
* Author: OSSI
*/
#include "util.h"
void delay_ms(uint16_t delay)
{
volatile uint16_t i;
for (i=0; i<delay;i++)
{
__delay_cycles(8000); // @ DCO 8MHz
}
}
void min_max(uint8_t min, uint8_t max, uint8_t value)
{
if (value <= min)
{
value = min;
}
if (value > max)
{
value = max;
}
}
/*
* global.h
*
* Created on: 2012. 6. 3.
* Author: donghee
*/
#ifndef GLOBAL_H_
#define GLOBAL_H_
#include "ossitypes.h"
// Macros for turning on and off the LEDs (for testing only)
enum {FALSE = 0, TRUE = 1};
#define _BV(bit) (1<<(bit))
//macros for IO config (with preprocessor abuse)
#define st(x) do{x} while(__LINE__ == -1)
enum IoState {LOW = 0, HIGH = 1, TOGGLE = 2};
#define IO_SET(name,val) _IO_SET(name##_PORT,name##_PIN,val)
#define _IO_SET(port,pin,val) st(__IO_SET(port,pin,val);)
#define __IO_SET(port,pin,val) if (val == TOGGLE)\
{\
st((P##port##OUT ^= _BV(pin)););\
}\
else if (val == HIGH)\
{\
st((P##port##OUT |= _BV(pin)););\
}\
else\
{\
st((P##port##OUT &= ~_BV(pin)););\
}
enum IoDirection {INPUT = 0, OUTPUT = 1};
#define IO_DIRECTION(name,dir) _IO_DIRECTION(name##_PORT,name##_PIN,dir)
#define _IO_DIRECTION(port,pin,dir) st(__IO_DIRECTION(port,pin,dir);)
#define __IO_DIRECTION(port,pin,dir) if (dir)\
{\
st((P##port##DIR |= _BV(pin)););\
}\
else\
{\
st((P##port##DIR &= ~_BV(pin)););\
}
void delay_ms(uint16_t delay);
void min_max(uint8_t min, uint8_t max, uint8_t value);
#endif /* GLOBAL_H_ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment