打印
[DemoCode下载]

从芯片的Flash中划出一块作为DATAFlash并读写数据

[复制链接]
1719|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Jessicakjdsl|  楼主 | 2016-3-17 13:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
之前接手了一个项目,它有个操作是将一些初始化数据写入DATAFlash区。
其做法是使用ICP下载工具在下载时配置ISD9160芯片的CONFIG[1:0],并下载DATAFlash和APROM。
这个做法繁琐、而且工厂生产时、生产人员去配置下载工具时可能会出错,所以又做了一个下载配置文件,也就是生产时需要3个文件才能完成对芯片的烧录:下载配置文件、DATAFlash.bin、APROM.bin。

现在用新方法将芯片配置过程和初始化数据一起包含于APROM.bin。
具体操作有2步:
1、配置芯片、从Flash中划出1K作为DATAFlash
// DATAFlash配置
#define CONFIG0_TEST_CODE   0xFFFFFFFE  // 使能DATAFlash
#define CONFIG1_TEST_CODE   0x00023000  // DATAFlash基地址(对应1K)

// 灯的模式和亮度参数存放于DATAFlash区,地址为0x23000开头的3个位置
#define LAMP_DATA_ADDR      CONFIG1_TEST_CODE

void config_init(void)
{
    int32_t  i32Err;
    uint32_t u32Data;
    uint32_t config0Bak, config1Bak;

    // 开始操作
    UNLOCKREG();

    // 开启ISP模块
    SYSCLK->AHBCLK.ISP_EN = 1;
    DrvFMC_EnableISP(1);

    // 检查boot源
    LOG(("Boot Source ................................ "));
    if(DrvFMC_GetBootSelect() == LDROM) {
        printf("[LDROM]\n");
        printf("WARNING: This code should be in AP mode but it is in LD mode now.\n\n");
        while(1){}
    } else {
        printf("[APROM]\n");
    }

    // 读取IC配置CONFIG[1:0]
    printf("Read config0 ............................... ");
    DrvFMC_Read(CONFIG_BASE, &config0Bak);
    printf("[0xx]\n", config0Bak);
    printf("Read config1 ............................... ");
    DrvFMC_Read(CONFIG_BASE+4, &config1Bak);
    printf("[0xx]\n", config1Bak);

    // 检查CONFIG[1:0]是否已经配置好
    printf("Configuration .............................. ");
    i32Err = 0;   
    if((config0Bak != CONFIG0_TEST_CODE) || (config1Bak != CONFIG1_TEST_CODE)) {
        i32Err = 1;
        printf("[NOT MATCH]\n");
    } else {
        printf("[MATCH]\n");
        printf("CONFIG0 .................................... [0x%x]\n",CONFIG0_TEST_CODE);
        printf("DataFlash BASE ADDR ........................ [0x%x]\n",CONFIG1_TEST_CODE);
    }

    // IC配置不对或未配置、则修改配置
    if(i32Err) {
        // 擦除CONFIG[1:0]
        printf("Erase config region ........................ ");
        DrvFMC_EnableConfigUpdate(TRUE);
        DrvFMC_Erase(CONFIG_BASE);
        DrvFMC_Read(CONFIG_BASE, &u32Data);
        if(u32Data != 0xFFFFFFFF) { printf("[FAIL]\n"); }
        else                      { printf("[OK]\n");   }

        // 修改CONFIG[1:0]
        printf("Program config region ...................... ");
        DrvFMC_Write(CONFIG_BASE, CONFIG0_TEST_CODE);
        DrvFMC_Write(CONFIG_BASE+4, CONFIG1_TEST_CODE);

        // 检查CONFIG[1:0]是否修改成功
        i32Err = 0;   
        DrvFMC_Read(CONFIG_BASE, &u32Data);
        if(u32Data != CONFIG0_TEST_CODE) { i32Err = 1; }
        DrvFMC_Read(CONFIG_BASE+4, &u32Data);
        if(u32Data != CONFIG1_TEST_CODE) { i32Err = 1; }
        if(i32Err) {
            printf("[FAIL]\n");
        } else {
            printf("[OK]\n");
            printf("CONFIG0 .................................... [0x%x]\n",CONFIG0_TEST_CODE);
            printf("DataFlash BASE ADDR ........................ [0x%x]\n",CONFIG1_TEST_CODE);
        }
    }

    // 关闭ISP模块
    DrvFMC_EnableISP(0);
    SYSCLK->AHBCLK.ISP_EN = 0;

    // 结束操作
    LOCKREG();
}


沙发
Jessicakjdsl|  楼主 | 2016-3-17 13:28 | 只看该作者
2、保存数据、这个例程只保存2个数据到DATAFlash区,地址为0x23000开头的2个位置。
   如果需要将专门的一组初始化数据写入DATAFlash,可以将这些数据添加到一个数组,然后将数组放在一个专门的头文件里面。通过修改下面的保存函数,将其写入DATAFlash即可。
void store_lamp_param(void)
{
    int32_t  i32Err  = 0;
    uint32_t u32Data = 0;

    static uint32_t mode  = 0;   // 模式
    static uint32_t level = 0;   // 亮度等级

    // 参数都没变化,则不用存储这些参数
    if( (g_lamp_ctrl.mode == mode) && (g_lamp_ctrl.level == level) ) {
        return ;
    }

    mode  = g_lamp_ctrl.mode;
    level = g_lamp_ctrl.level;

    printf("Store lamp param ...........................\r\n");

    // 开始操作
    UNLOCKREG();

    // 开启ISP模块
    SYSCLK->AHBCLK.ISP_EN = 1;
    DrvFMC_EnableISP(1);

    // 擦除数据
    printf("Erase lamp param data ...................... ");
    DrvFMC_Erase(LAMP_DATA_ADDR);
    i32Err = 0;   
    DrvFMC_Read(LAMP_DATA_ADDR + 0, &u32Data);
    if(u32Data != 0xFFFFFFFF) { i32Err = 1; }
    DrvFMC_Read(LAMP_DATA_ADDR + 4, &u32Data);
    if(u32Data != 0xFFFFFFFF) { i32Err = 1; }
    if(i32Err) { printf("[FAIL]\n"); goto ISP_OP_END;}
    else       { printf("[OK]\n");                   }

    // 修改数据
    printf("Program lamp param data .................... ");
    DrvFMC_Write(LAMP_DATA_ADDR + 0, g_lamp_ctrl.mode);
    DrvFMC_Write(LAMP_DATA_ADDR + 4, g_lamp_ctrl.level);

    // 检查数据是否修改成功
    i32Err = 0;   
    DrvFMC_Read(LAMP_DATA_ADDR + 0, &u32Data);
    if(u32Data != g_lamp_ctrl.mode)  { i32Err = 1; }
    DrvFMC_Read(LAMP_DATA_ADDR + 4, &u32Data);
    if(u32Data != g_lamp_ctrl.level) { i32Err = 1; }
    if(i32Err) {
        printf("[FAIL]\n");
    } else {
        printf("[OK]");
        printf("[mode = %d]",g_lamp_ctrl.mode);
        printf("[level = %d]\n",g_lamp_ctrl.level);
    }

ISP_OP_END:
    // 关闭ISP模块
    DrvFMC_EnableISP(0);
    SYSCLK->AHBCLK.ISP_EN = 0;

    // 结束操作
    LOCKREG();
}

还有一个方法待测试:在.scatter文件中可以直接将初始化数据的头文件规划在指定的DATAFlash区:
ROM_EXEC 0x23000 0x23400
    {
        Init_Data.o
    }



使用特权

评论回复
板凳
gejigeji521| | 2016-3-17 13:56 | 只看该作者
好久没有看到谁用GOTO语句了,这个语句用好了就是神来一笔。

使用特权

评论回复
地板
RAYINGPX| | 2019-9-12 14:02 | 只看该作者
MARK

使用特权

评论回复
5
dongnanxibei| | 2019-9-12 18:10 | 只看该作者
宝贵的经验。

使用特权

评论回复
6
643757107| | 2019-9-15 21:27 | 只看该作者
经验不错,发现大家的经验,比官方例子还靠谱

使用特权

评论回复
7
天灵灵地灵灵| | 2019-9-15 23:58 | 只看该作者
存储的顺序是从前到后按顺序就好办。

使用特权

评论回复
8
mintspring| | 2019-9-16 00:21 | 只看该作者
是不是很方便

使用特权

评论回复
9
zhuomuniao110| | 2019-9-16 20:51 | 只看该作者
多谢分享,原来可以这么利用

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

116

帖子

1

粉丝