如何利用好MSP430芯片内的information memory 作为掉电数据保存(EEPROM)

          

     受朋友之托,今天第一次给大家发帖子,  把珍藏的成年老窖, 让大家尝尝,  下面是我珍藏多年的代码,我自认为有价值,  如果对你有点点帮助,请个我回个帖子. 

我们用的MSP430时,  内部有几十个字节information memory 可以当EEPROM来用, 无需再外扩EEPROM芯片,  用量保存一下系数的掉电保存的数据. 我一直用这个, 很好用.      

     特别说明:

     1.说明我用的是IAR编译器,  在IAR上一定能通过 

    2. 利用information memory 作为EEPROM 掉电保存数据,这是这段程序第一个亮点;

    3. 写information memory 必须在RAM中运行程序.  将程序从flash 跑到RAM中运行, 很有意思. 这是第二个亮点.

    4. 源文件,下载

 

#include "MSP430x16x.h"
#include "string.h"
#include"stdlib.h"
#include"flash.h"


/************************************************************************************
** 函数名称: flashWrite
** 功能描述: 在MSP430flash中写数据
**
** 输  入: td:写入地址, sd:源数据指针, size:写入字节数
** 输  出: 无
** 返 回 值: 返回需要发送给其他任务处理的数据块的指针。
** 全局变量:
** 调用模块:
** 作  者: 陈文浩
** 日  期: 2010年07月12日
************************************************************************************/
void flashWrite(unsigned char * td, unsigned char *sd, unsigned char size)
{
typedef void(*funp)(unsigned char*,unsigned char *, unsigned char); //定义函数指针类型
funp FLASHBLK;
char ramcode[100]; //ram内程序及数组地址指针
_DINT();
//ramcode=(char *)malloc(sizeof(char)*100); //为放入内存的子程分配空间(需先将heap值设为180)
FLASHBLK = flashWriteBlock; //函数指针赋值
memcpy(ramcode,(char *)FLASHBLK,100); //将块写子程放入ram中已分配空间
FLASHBLK=*(funp)ramcode; //将函数指针指向ram中的块写子程
flashErase(td); //段擦
(FLASHBLK)(td,sd, size); //块写(调用的是ram中的块写子程)
//free(ramcode); //释放空间
_EINT(); //开放中断
}


void flashWriteBlock(unsigned char * td,unsigned char *sd, unsigned char size)
{
int i;

while((FCTL3&BUSY)!=0x00); //检测busy位
FCTL2=FWKEY+FSSEL_1+20; //flash模块时钟源为MCLK 分频2
FCTL3=FWKEY; //解锁
FCTL1=FWKEY+BLKWRT+WRT; //块写
for(i=0;i<size;i++) //写64字节数据
{
*td++=*sd++; //写入
while((FCTL3&WAIT)==0); //检测wait位 是否写入该字
}
FCTL1=FWKEY; //BLKWRT WRT位复位
while((FCTL3&BUSY)!=0x00); //检测BUSY位
FCTL3=FWKEY+LOCK; //锁定

}
/*******************************************************************************/
/* 段擦除子程序 */
/*******************************************************************************/
void flashErase(unsigned char *td)
{
FCTL2=FWKEY+FSSEL_1+10; //flash模块时钟源位MCLK 分频2
FCTL3=FWKEY; //解锁
FCTL1=FWKEY+ERASE; //段擦除
*td=0; //在欲进行操作的段中空写,启动擦除操作
FCTL3=FWKEY+LOCK; //锁定
}

//功能:FLASH操作 BYTE数据写入
//编程时钟:257KHZ~476KHZ
void flashWriteByte(unsigned char * pdata, unsigned char data)
{
//WDTCTL = WDTPW + WDTHOLD; //关闭看门狗
_DINT(); //关闭总中断
FCTL2 = FWKEY+FSSEL1+12; //3686400/300K=12
FCTL3 = FWKEY; //LOCK=0;
FCTL1=FWKEY+WRT; //WRT=1;
*pdata = data;
FCTL3 = FWKEY+LOCK; //
//开通看门狗
_EINT(); //开放中断
}

void flashWriteWord(unsigned short * pdata, unsigned short data)
{
//WDTCTL = WDTPW + WDTHOLD; //关闭看门狗
_DINT(); //关闭总中断
FCTL2 = FWKEY+FSSEL1+12;
FCTL3 = FWKEY; //LOCK=0;
FCTL1=FWKEY+WRT; //WRT=1;
*pdata = data;
FCTL3 = FWKEY+LOCK; //
//开通看门狗
_EINT(); //开放中断
}

进入电子产品设计这个行业, 天就那么大, 今天是同行,明天是朋友, 后天就是老朋友, 我们珍惜每一次机会,展示你我的风采!

11 个回复

  •      受朋友之托,今天第一次给大家发帖子,  把珍藏的成年老窖, 让大家尝尝,  下面是我珍藏多年的代码,我自认为有价值,  如果对你有点点帮助,请个我回个帖子. 

    我们用的MSP430时,  内部有几十个字节information memory 可以当EEPROM来用, 无需再外扩EEPROM芯片,  用量保存一下系数的掉电保存的数据. 我一直用这个, 很好用.      

         特别说明:

         1.说明我用的是IAR编译器,  在IAR上一定能通过 

        2. 利用information memory 作为EEPROM 掉电保存数据,这是这段程序第一个亮点;

        3. 写information memory 必须在RAM中运行程序.  将程序从flash 跑到RAM中运行, 很有意思. 这是第二个亮点.

        4. 源文件,下载

     

    #include "MSP430x16x.h"
    #include "string.h"
    #include"stdlib.h"
    #include"flash.h"


    /************************************************************************************
    ** 函数名称: flashWrite
    ** 功能描述: 在MSP430flash中写数据
    **
    ** 输  入: td:写入地址, sd:源数据指针, size:写入字节数
    ** 输  出: 无
    ** 返 回 值: 返回需要发送给其他任务处理的数据块的指针。
    ** 全局变量: 
    ** 调用模块: 
    ** 作  者: 陈文浩
    ** 日  期: 2010年07月12日
    ************************************************************************************/
    void flashWrite(unsigned char * td, unsigned char *sd, unsigned char size)
    {
    typedef void(*funp)(unsigned char*,unsigned char *, unsigned char); //定义函数指针类型
    funp FLASHBLK; 
    char ramcode[100]; //ram内程序及数组地址指针 
    _DINT(); 
    //ramcode=(char *)malloc(sizeof(char)*100); //为放入内存的子程分配空间(需先将heap值设为180)
    FLASHBLK = flashWriteBlock; //函数指针赋值
    memcpy(ramcode,(char *)FLASHBLK,100); //将块写子程放入ram中已分配空间
    FLASHBLK=*(funp)ramcode; //将函数指针指向ram中的块写子程
    flashErase(td); //段擦
    (FLASHBLK)(td,sd, size); //块写(调用的是ram中的块写子程)
    //free(ramcode); //释放空间
    _EINT(); //开放中断
    }


    void flashWriteBlock(unsigned char * td,unsigned char *sd, unsigned char size)
    {
    int i;

    while((FCTL3&BUSY)!=0x00); //检测busy位
    FCTL2=FWKEY+FSSEL_1+20; //flash模块时钟源为MCLK 分频2
    FCTL3=FWKEY; //解锁
    FCTL1=FWKEY+BLKWRT+WRT; //块写
    for(i=0;i<size;i++) //写64字节数据

    *td++=*sd++; //写入
    while((FCTL3&WAIT)==0); //检测wait位 是否写入该字
    }
    FCTL1=FWKEY; //BLKWRT WRT位复位
    while((FCTL3&BUSY)!=0x00); //检测BUSY位
    FCTL3=FWKEY+LOCK; //锁定

    }
    /*******************************************************************************/ 
    /* 段擦除子程序 */
    /*******************************************************************************/
    void flashErase(unsigned char *td)
    {
    FCTL2=FWKEY+FSSEL_1+10; //flash模块时钟源位MCLK 分频2
    FCTL3=FWKEY; //解锁
    FCTL1=FWKEY+ERASE; //段擦除
    *td=0; //在欲进行操作的段中空写,启动擦除操作
    FCTL3=FWKEY+LOCK; //锁定 
    }

    //功能:FLASH操作 BYTE数据写入
    //编程时钟:257KHZ~476KHZ
    void flashWriteByte(unsigned char * pdata, unsigned char data)
    {
    //WDTCTL = WDTPW + WDTHOLD; //关闭看门狗
    _DINT(); //关闭总中断
    FCTL2 = FWKEY+FSSEL1+12; //3686400/300K=12
    FCTL3 = FWKEY; //LOCK=0;
    FCTL1=FWKEY+WRT; //WRT=1;
    *pdata = data;
    FCTL3 = FWKEY+LOCK; //
    //开通看门狗
    _EINT(); //开放中断
    }

    void flashWriteWord(unsigned short * pdata, unsigned short data)
    {
    //WDTCTL = WDTPW + WDTHOLD; //关闭看门狗
    _DINT(); //关闭总中断
    FCTL2 = FWKEY+FSSEL1+12;
    FCTL3 = FWKEY; //LOCK=0;
    FCTL1=FWKEY+WRT; //WRT=1;
    *pdata = data;
    FCTL3 = FWKEY+LOCK; //
    //开通看门狗
    _EINT(); //开放中断
    }

    进入电子产品设计这个行业, 天就那么大, 今天是同行,明天是朋友, 后天就是老朋友, 我们珍惜每一次机会,展示你我的风采!

    flash.c
  • 探花 12730 points

    非常不错的分享!

    补充一点,部分MSP430中A区中存有部分芯片调校数据,如果需要利用A区,需要仔细看一下DATASHEET. 

    如果您认为此问题已被解答,请在“这是否解答您的问题” 后,点击“”按钮。 感谢您对TI的大力支持!

  • 回复 arm999:

    arm999

         受朋友之托,今天第一次给大家发帖子,  把珍藏的成年老窖, 让大家尝尝,  下面是我珍藏多年的代码,我自认为有价值,  如果对你有点点帮助,请个我回个帖子. 

    我们用的MSP430时,  内部有几十个字节information memory 可以当EEPROM来用, 无需再外扩EEPROM芯片,  用量保存一下系数的掉电保存的数据. 我一直用这个, 很好用.      

         特别说明:

         1.说明我用的是IAR编译器,  在IAR上一定能通过 

        2. 利用information memory 作为EEPROM 掉电保存数据,这是这段程序第一个亮点;

        3. 写information memory 必须在RAM中运行程序.  将程序从flash 跑到RAM中运行, 很有意思. 这是第二个亮点.

        4. 源文件,下载

     

    #include "MSP430x16x.h"
    #include "string.h"
    #include"stdlib.h"
    #include"flash.h"


    /************************************************************************************
    ** 函数名称: flashWrite
    ** 功能描述: 在MSP430flash中写数据
    **
    ** 输  入: td:写入地址, sd:源数据指针, size:写入字节数
    ** 输  出: 无
    ** 返 回 值: 返回需要发送给其他任务处理的数据块的指针。
    ** 全局变量: 
    ** 调用模块: 
    ** 作  者: 陈文浩
    ** 日  期: 2010年07月12日
    ************************************************************************************/
    void flashWrite(unsigned char * td, unsigned char *sd, unsigned char size)
    {
    typedef void(*funp)(unsigned char*,unsigned char *, unsigned char); //定义函数指针类型
    funp FLASHBLK; 
    char ramcode[100]; //ram内程序及数组地址指针 
    _DINT(); 
    //ramcode=(char *)malloc(sizeof(char)*100); //为放入内存的子程分配空间(需先将heap值设为180)
    FLASHBLK = flashWriteBlock; //函数指针赋值
    memcpy(ramcode,(char *)FLASHBLK,100); //将块写子程放入ram中已分配空间
    FLASHBLK=*(funp)ramcode; //将函数指针指向ram中的块写子程
    flashErase(td); //段擦
    (FLASHBLK)(td,sd, size); //块写(调用的是ram中的块写子程)
    //free(ramcode); //释放空间
    _EINT(); //开放中断
    }


    void flashWriteBlock(unsigned char * td,unsigned char *sd, unsigned char size)
    {
    int i;

    while((FCTL3&BUSY)!=0x00); //检测busy位
    FCTL2=FWKEY+FSSEL_1+20; //flash模块时钟源为MCLK 分频2
    FCTL3=FWKEY; //解锁
    FCTL1=FWKEY+BLKWRT+WRT; //块写
    for(i=0;i<size;i++) //写64字节数据

    *td++=*sd++; //写入
    while((FCTL3&WAIT)==0); //检测wait位 是否写入该字
    }
    FCTL1=FWKEY; //BLKWRT WRT位复位
    while((FCTL3&BUSY)!=0x00); //检测BUSY位
    FCTL3=FWKEY+LOCK; //锁定

    }
    /*******************************************************************************/ 
    /* 段擦除子程序 */
    /*******************************************************************************/
    void flashErase(unsigned char *td)
    {
    FCTL2=FWKEY+FSSEL_1+10; //flash模块时钟源位MCLK 分频2
    FCTL3=FWKEY; //解锁
    FCTL1=FWKEY+ERASE; //段擦除
    *td=0; //在欲进行操作的段中空写,启动擦除操作
    FCTL3=FWKEY+LOCK; //锁定 
    }

    //功能:FLASH操作 BYTE数据写入
    //编程时钟:257KHZ~476KHZ
    void flashWriteByte(unsigned char * pdata, unsigned char data)
    {
    //WDTCTL = WDTPW + WDTHOLD; //关闭看门狗
    _DINT(); //关闭总中断
    FCTL2 = FWKEY+FSSEL1+12; //3686400/300K=12
    FCTL3 = FWKEY; //LOCK=0;
    FCTL1=FWKEY+WRT; //WRT=1;
    *pdata = data;
    FCTL3 = FWKEY+LOCK; //
    //开通看门狗
    _EINT(); //开放中断
    }

    void flashWriteWord(unsigned short * pdata, unsigned short data)
    {
    //WDTCTL = WDTPW + WDTHOLD; //关闭看门狗
    _DINT(); //关闭总中断
    FCTL2 = FWKEY+FSSEL1+12;
    FCTL3 = FWKEY; //LOCK=0;
    FCTL1=FWKEY+WRT; //WRT=1;
    *pdata = data;
    FCTL3 = FWKEY+LOCK; //
    //开通看门狗
    _EINT(); //开放中断
    }

    请问,这种方案在MSP430F425里面可以通用吗???

  • 回复 yangfeng he:

    flash 的msp430,在使用(写,擦除)information memory 是程序需要运行在RAM中,因为所有的片上flash 公用一个charge pump。
    FRAM的msp430,由于FRAM在读写上的独特优势,操作information memory 程序不需要运行在RAM中
  • 回复 yangfeng he:

    楼主用的也是msp430fxx系列,这种方法可以用在msp430f425

    昵称:灰小子

    qq:1358611172

  • 回复 arm999:

    谢谢分享,MSP430铁电系列 MSP430FRxxxx片上存储全部为非易失性FRAM铁电存储,轻松解决掉电保护的问题。

    如果您认为此问题已被解答,请在“这是否解答您的问题” 后,点击“”按钮。 感谢您对TI的大力支持!

    Wei,

  • 回复 Wei.Jetim Zhao:

    请在TI.COM上搜索Compute Through Power Loss。这是一个很好的解决方案把FRAM作为EEPROM甚至SRAM使用

  • 回复 Xiaodong LI:

    你好,我现在调试的是MSP430i2041,编译器是IAR,现在需要用info memory保存掉电数据,上电后读出来。IAR只提供了写进info memory的接口,没有提供读出来的接口,根据我在网上找的资料,读info memory的数据是直接操作就可以了。请问有读info memory的例程吗?

    //下面是代码,代码是在FLASHCTL这个demo的基础上小改

    #include "driverlib.h"

    // Address of the beginning of the Flash Information Segment
    #define SEGSTART 0x1060
    // Number of bytes within segment to write
    #define SEG_LEN 16

    // Value to write to segment
    const uint32_t Value = 0xBEEFDEAD;
    uint8_t r_value[4]={0};
    uint8_t r_value1=0;

    void write_InfoSeg(uint32_t value);
    void FlashRead(uint8_t *pc_byte,uint8_t *Dataout,uint8_t count);


    void main(void) {
    // Pointer to beginning of Flash segment
    uint32_t *flashPtr = (uint32_t *)SEGSTART;

    // Stop WDT
    WDT_hold(WDT_BASE);

    // Setting the DCO to use the internal resistor. DCO will be at 16.384MHz
    CS_setupDCO(CS_INTERNAL_RESISTOR);

    // Setting MCLK to DCO / 1. MCLK = 16.384MHz.
    CS_initClockSignal(CS_MCLK, CS_CLOCK_DIVIDER_1);

    // MCLK for Flash Timing Generator
    // Flash clock will run at ~390kHz. Datasheet recommends 257kHz - 476kHz
    FlashCtl_setupClock(390095, 16384000, FLASHCTL_MCLK);

    FlashCtl_unlockInfo();
    FlashCtl_fillMemory32(Value, flashPtr, SEG_LEN / 4);
    FlashCtl_lockInfo();

    while(1)
    {
    // Set breakpoint to view memory
    //__no_operation();
    FlashRead((uint8_t *)SEGSTART,r_value,SEG_LEN / 4);
    r_value1=r_value[0];  //r_value1仿真一直是0
    }
    }

    //从 info memory读一个byte接口

    void FlashRead(uint8_t *pc_byte,uint8_t *Dataout,uint8_t count)
    {

    while(count--)

    {

    *Dataout = *pc_byte;

    Dataout++;

    pc_byte++;

    }

    }

  • 回复 user4937994:

    直接读相应地址的值就行了,还需要示例吗?官方没有专门的示例。

    如果您认为此问题已被解答,请在“这是否解答您的问题” 后,点击“”按钮。 感谢您对TI的大力支持!

    Wei,

  • 非常好的分享。可以利用未使用的这段空间存储掉电不丢失的信息,不用加一片E2PROM,成本降低、减少空间占用。