16635|36

4996

帖子

19

TA的资源

裸片初长成(初级)

楼主
 

LPC1100处理器通过SD卡实现IAP功能 [复制链接]

随着处理器的发展,IAP升级方式越来越受到欢迎。而IAP升级的方式也由很多,如:通过串口升级、GPRS远程升级、SD卡升级等等。这里详细介绍怎样使用SD卡升级应用程序的方法。

 

 

重映射https://bbs.eeworld.com.cn/viewthread.php?tid=327463&highlight=iap%2Bzhaojun%5C_xf

 

 

 

 

 

 

 

下面先介绍LPC1100处理器IAP的基础知识:

 

 

 

 

1. LPC1100处理器(LPC1114)Flash分配:LPC1114一共有32K Flash,共分为8个扇区,每个扇区的大小为4K,具体如下:

 

 

2.NXP的IAP命令都一样,一共有9条:

 

3.IAP命令是通过寄存器R0和R1进行参数传递的,R0传递参数,R1传递返回值:

 

[ 本帖最后由 zhaojun_xf 于 2013-10-22 14:49 编辑 ]
此帖出自NXP MCU论坛

最新回复

你弄好了吗   详情 回复 发表于 2015-11-23 08:39
点赞 关注(4)
个人签名我的博客
 

回复
举报

4996

帖子

19

TA的资源

裸片初长成(初级)

沙发
 

IAP功能应用:

 

1.定义IAP程序的入口地址

 

  1. #define  IAP_ENTER_ADR 0x1FFF1FF1   /* IAP入口地址定义  */

复制代码

 

2.定义参数

 

  1. uint32  ParamIn[8];         /* IAP入口参数缓冲区            */
    uint32  ParamOut[8];        /* IAP出口参数缓冲区            */

复制代码

 

3.定义函数类型指针

 

  1. void (*IAP_Entry)(uint32 *param_tab, uint32 *result_tab) =

  2. (void(*)())IAP_ENTER_ADR; // 定义函数指针

复制代码

 

4.注意事项:

 

①按照上面函数类型调用IAP函数即可,不过要注意函数的参数。

②由于在擦写操作期间,片上Flash存储器不可访问。IAP代码不能使用或禁止中断。

③Flash编程命令使用片上RAM顶端32字节,用户程序不能使用此空间。

[ 本帖最后由 zhaojun_xf 于 2011-12-25 20:11 编辑 ]
此帖出自NXP MCU论坛
 
个人签名我的博客
 
 

回复

4996

帖子

19

TA的资源

裸片初长成(初级)

板凳
 

IAP命令应用(代码来自周工):

 

IAP有多个命令,这里我们只把编程常用的几个命令函数贴出来,如果网友需要其他代码可以在网络上自行搜索。

 

1.准备写操作扇区

 

 

  1. /*****************************************************************************
    ** Function name:       SectorPrepare
    ** Descriptions:        IAP操作扇区选择,命令代码50
    ** input parameters:    sec1:           起始扇区
    **                      sec2:           终止扇区
    ** output parameters:   ParamOut[0]:    IAP操作状态码,IAP返回值    
    ** Returned value:      ParamOut[0]:    IAP操作状态码,IAP返回值                    
    *******************************************************************************/
    uint32 SectorPrepare(uint8 sec1, uint8 sec2)

        ParamIn[0] = IAP_Prepare;              /* 设置命令字         */
        ParamIn[1] = sec1;                          /* 设置参数            */
        ParamIn[2] = sec2;                           
        (*IAP_Entry)(ParamIn, ParamOut);  /* 调用IAP服务程序 */
      
        return (ParamOut[0]);                      /* 返回状态码        */
    }

复制代码

 

2.将RAM 内容复制到Flash

 

 

  1.  

  2. /*******************************************************************************
    ** Function name:       RamToFlash
    ** Descriptions:        复制RAM的数据到FLASH,命令代码51
    ** input parameters:    dst:            目标地址,即FLASH起始地址。以512字节为分界
    **                      src:            源地址,即RAM地址。地址必须字对齐
    **                      no:             复制字节个数,为512/1024/4096/8192
    ** output parameters:   ParamOut[0]:    IAP操作状态码,IAP返回值    
    ** Returned value:      ParamOut[0]:    IAP操作状态码,IAP返回值                    
    ********************************************************************************/
    uint32 RamToFlash(uint32 dst, uint32 src, uint32 no)

        ParamIn[0] = IAP_RAMTOFLASH;      /* 设置命令字          */
        ParamIn[1] = dst;                                /* 设置参数             */
        ParamIn[2] = src;
        ParamIn[3] = no;
        ParamIn[4] = IAP_FCCLK;
        (*IAP_Entry)(ParamIn, ParamOut);    /* 调用IAP服务程序  */
       
        return (ParamOut[0]);                         /* 返回状态码          */
    }

复制代码

 

3.擦除扇区

 

 

  1. /*******************************************************************************
    ** Function name:       SectorErase
    ** Descriptions:        扇区擦除,命令代码52
    ** input parameters:    sec1            起始扇区
    **                      sec2            终止扇区92
    ** output parameters:   ParamOut[0]:    IAP操作状态码,IAP返回值
    ** Returned value:      ParamOut[0]:    IAP操作状态码,IAP返回值                    
    ********************************************************************************/
    uint32 SectorErase(uint8 sec1, uint8 sec2)

        ParamIn[0] = IAP_ERASESECTOR;         /* 设置命令字         */
        ParamIn[1] = sec1;                                   /* 设置参数            */
        ParamIn[2] = sec2;
        ParamIn[3] = IAP_FCCLK;
        (*IAP_Entry)(ParamIn, ParamOut);          /* 调用IAP服务程序  */
      
        return (ParamOut[0]);                              /* 返回状态码          */
    }

复制代码

 

4.扇区查空

 

 

  1. /**********************************************************************************
    ** Function name:       BlankChk
    ** Descriptions:        扇区查空,命令代码53
    ** input parameters:    sec1:           起始扇区
    **                      sec2:           终止扇区92
    ** output parameters:   ParamOut[0]:    IAP操作状态码,IAP返回值
    ** Returned value:      ParamOut[0]:    IAP操作状态码,IAP返回值                    
    **********************************************************************************/
    uint32 BlankChk(uint8 sec1, uint8 sec2)

        ParamIn[0] = IAP_BLANKCHK;          /* 设置命令字         */
        ParamIn[1] = sec1;                            /* 设置参数            */
        ParamIn[2] = sec2;
        (*IAP_Entry)(ParamIn, ParamOut);    /* 调用IAP服务程序 */

  2.     return (ParamOut[0]);                       /* 返回状态码         */
    }

复制代码

 

5.比较<地址1><地址2><字节数>

 

 

  1. /*******************************************************************************
    ** Function name:       DataCompare
    ** Descriptions:        校验数据,命令代码56
    ** input parameters:    dst:            目标地址,即RAM/FLASH起始地址。地址必须字对齐
    **                      src:            源地址,即FLASH/RAM地址。地址必须字对齐
    **                      no:             复制字节个数,必须能被4整除
    ** output parameters:   ParamOut[0]:    IAP操作状态码,IAP返回值
    ** Returned value:      ParamOut[0]:    IAP操作状态码,IAP返回值                    
    ********************************************************************************/
    uint32 DataCompare(uint32 dst, uint32 src, uint32 no)

        ParamIn[0] = IAP_COMPARE;             /* 设置命令字          */
        ParamIn[1] = dst;                                 /* 设置参数             */
        ParamIn[2] = src;
        ParamIn[3] = no;
        (*IAP_Entry)(ParamIn, ParamOut);     /* 调用IAP服务程序   */

  2.     return (ParamOut[0]);                       /* 返回状态码              */
    }

复制代码

[ 本帖最后由 zhaojun_xf 于 2011-12-26 08:14 编辑 ]
此帖出自NXP MCU论坛
 
个人签名我的博客
 
 

回复

2751

帖子

0

TA的资源

裸片初长成(初级)

4
 

原帖由 zhaojun_xf 于 2011-12-25 19:37 发表 随着处理器的发展,IAP升级方式越来越受到欢迎。而IAP升级的方式也由很多,如:通过串口升级、GPRS远程升级、SD卡升级等等。这里详细介绍怎样使用SD卡升级应用程序的方法。           ...

 

楼主威武

此帖出自NXP MCU论坛
 
 
 

回复

4996

帖子

19

TA的资源

裸片初长成(初级)

5
 

有上面的几个函数后,下面就可以根据需要编写SD卡升级函数了:

 

1.定义用户程序地址

 

定义用户程序的起始地址,用户可以根据自己的实际情况设定,一般都从0x0000 0000开始存放IAP代码,之后的空间才是存放用户代码的。

 

  1. #define APP_CODE_START_ADDR   0x00006000     // 用户程序起始地址

复制代码

 

2.从SD卡中读写bin文件更新升级

 

从SD卡中升级程序很简单。流程是:从SD卡中打开升级文件,每次读取512字节,然后写入Flash,直到编写完成。

 

IAP支持256/512/1024/2048/4096等多字节编程方式,只是SD卡每扇区大小一般都是512字节,所以这里使用512字节为单位进行编程。

 

  1.  

  2. /**********************************************************************************
    * FunctionName   : UCSDCardProgram()
    * Description    : 从SD卡编程
    * EntryParameter : fileName - 应用程序在SD卡中的名字, buf - 缓冲
    * ReturnValue    : None
    *********************************************************************************/
    uint8 UCSDCardProgram(uint8 *fileName, uint8 *buf)
    {
        uint32 addr = 0;
        FATFS fs;               /*Work area (file system object) for logical drive*/
        FIL file;               /*file objects*/
        UINT  br;               /*File R/W count*/
        FRESULT res;

  3.  

  4.     DisableIRQ();              // 禁止中断
        SectorPrepare(6, 6);    // 选择扇区    
        SectorErase(6, 6);        // 擦除扇区         
        EnableIRQ();               // 使能中断

  5.  

  6.     /*Register a work area for logical drive 0*/
        f_mount(0, &fs);

  7.     /*Create file*/
        res = f_open(&file, (const TCHAR *)fileName, FA_OPEN_EXISTING|FA_READ);

  8.     if(res != FR_OK)
        {
             return res;
        }
        else
       {
            while (1)
            {
                 res = f_read(&file, buf, 512, &br);     // 读取数据

  9.              DisableIRQ();
                 SectorPrepare(6, 6);
                 RamToFlash(APP_CODE_START_ADDR + addr, (uint32)buf, 512); // 写数据到FLASH
                 EnableIRQ();
                 addr += 512;

  10.              if ((res != FR_OK) || (br < 512))
                 {
                      break;
                 }
             }
        }

  11.     /*Close all files*/
        f_close(&file);      // 关闭文件,必须和f_open函数成对出现

  12.     /*Unregister a work area before discard it*/
        f_mount(0, 0);

  13.     return FR_OK;
    }

复制代码

 

3.主函数:

 

主函数实现按键扫描,如果有按键,进行SD卡升级,如果没有按键直接跳转到应用程序。

 

代码一开始判断按键,所以一般都是需要按下按键后复位系统,当然也可以适当循环扫描按键的次数。等待一定的时间。。。。。。。

 

  1. /**********************************************************************************
    * FunctionName   : main()
    * Description    : 主函数
    * EntryParameter : None
    * ReturnValue    : None
    *********************************************************************************/
    int main(void)

        void (*userProgram)() = (void (*)())OSInit;     // 函数指针 

  2.  

  3.     OSInit();                // 初始化系统

  4.     while (1)
        {
             if (KeyGetValue())
             {
                 UCSDCardProgram("LPC1114.bin", SDBuf);
             }

  5.          userProgram = (void (*)())(APP_CODE_START_ADDR + 1);
             (*userProgram)();                           // 启动程序 
        }
    }

复制代码

 

到此IAP程序完成了,下面就是编写应用程序了。。。。。。。。。。。。。。。。。。。。。。

[ 本帖最后由 zhaojun_xf 于 2011-12-26 08:03 编辑 ]
此帖出自NXP MCU论坛
 
个人签名我的博客
 
 

回复

4996

帖子

19

TA的资源

裸片初长成(初级)

6
 

应用程序编写:

 

应用程序编写没有什么特殊的,只是需要注意几个地方的设置

 

1.设置编译地址:

   

 设置用户程序的开始地址,根据需要设置,一般都在IAP函数之上,需要适当大于IAP,给IAP自己增加功能提供空间。内存也可以适当设置一下,不过一般应用程都没有完全使用完内存,所以不设置也是可以的。

 

 

 

2.编译设置

 

设置NO_CRP条件编译,否则程序编译会出错,此字段在启动代码中使用,如果要加密代码,此段号也需要设置。

 

 

3.生存bin文件

 

设置bin文件生成命令,具体的设置方法请看<<MDK下生存库(Lib)的方法>>:https://bbs.eeworld.com.cn/thread-314169-1-1.html

 

 

 

4.编写应用程序,并把bin文件存放SD卡中,运行IAP升级程序。

 

 

[ 本帖最后由 zhaojun_xf 于 2011-12-26 08:12 编辑 ]
此帖出自NXP MCU论坛
 
个人签名我的博客
 
 

回复

4996

帖子

19

TA的资源

裸片初长成(初级)

7
 

具体的升级过程:

 

1.把IAP程序下载到板子上。

 

2.编写并编译好应用程序,需要是的bin文件。

 

3.把应用程序的bin文件拷贝到SD卡中。

 

4.在板子上插入SD卡,并按下按键重启系统。

 

5.板子就会自动实现升级并跳转到应用中运行。

 

 

有时升级后,并不能够成功跳转到应用程序中,此时我们并不知道究竟是没有编程成功,还没有跳转成功,为了验证问题,我们可以读取编程后的代码,与原文件进行比较。如果读取数据与原文件一样,那么一定是跳转没有成功,或是没有向量映射;如果编程不一致那么查看一下编程的问题,特别是最后一个扇区,对于编程一般都是256,512,1024,4096等,不能随便编程。

 

么怎么读取芯片中编程后的代码?

 

对于LPC1700芯片并没有IAP读取扇区的函数,所以我们需要直接通过绝对地址读取,方法如下:


     读取ARM代码的方法:
     dat = *(uint8 *)addr;   // 这里可以每次读一字节
  dat = *(uint32 *)addr;   // 这里可以每次读一字
  
  addr-为实际需要读取的地址,dat-为地址中的数据

 

需要注意地址:如果从地址0x4000开始编程,最好就从这里开始读取,直至完成。而且需要注意每次读取的是一字节还是字,地址加的时候加1还是加4.。。。。

[ 本帖最后由 zhaojun_xf 于 2012-3-29 14:17 编辑 ]
此帖出自NXP MCU论坛
 
个人签名我的博客
 
 

回复

14

帖子

0

TA的资源

一粒金砂(中级)

8
 
学习了,感谢楼主分享
此帖出自NXP MCU论坛
 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

9
 

学习了,感谢楼主分享
此帖出自NXP MCU论坛
 
个人签名hj
 
 

回复

194

帖子

0

TA的资源

纯净的硅(中级)

10
 

回复楼主

好贴,好贴!!!
此帖出自NXP MCU论坛
 
 
 

回复

27

帖子

0

TA的资源

一粒金砂(中级)

11
 

楼主好贴,mark下

此帖出自NXP MCU论坛
 
 
 

回复

13

帖子

0

TA的资源

一粒金砂(初级)

12
 

不错

是个好资料
此帖出自NXP MCU论坛
 
 
 

回复

5

帖子

0

TA的资源

一粒金砂(初级)

13
 
学习了,感谢楼主分享
此帖出自NXP MCU论坛
 
 
 

回复

10

帖子

0

TA的资源

一粒金砂(中级)

14
 
请问楼主上面程序是不是有几个问题:1、中断向量表重映射了吗?2、主堆栈MSP初始化了吗。。。3.你的地址+1是不是有问题,是不是应该是+4
此帖出自NXP MCU论坛
 
 
 

回复

4996

帖子

19

TA的资源

裸片初长成(初级)

15
 

回复 14楼 qiuhaomiao 的帖子

LPC1114没有重映射,初始化在启动代码中,地址加没有问题
此帖出自NXP MCU论坛
 
个人签名我的博客
 
 

回复

10

帖子

0

TA的资源

一粒金砂(中级)

16
 
己经验证了楼主的程序,好像启动不了。后来自己写了一些,整了两天算搞明白了。M0没有重映射flash的向量表,只能应用程序启用ram的向量表,那样才能从bootloader跳到用户程序之后还能中断。
此帖出自NXP MCU论坛
 
 
 

回复

4996

帖子

19

TA的资源

裸片初长成(初级)

17
 

回复 16楼 qiuhaomiao 的帖子

代码没有问题,都验证过很多遍了。。。
此帖出自NXP MCU论坛
 
个人签名我的博客
 
 

回复

10

帖子

0

TA的资源

一粒金砂(中级)

18
 
楼主。。。。。我不是开玩笑的。。。。你那样是可以用简单的程序,但中断必定死机。。。。。因为中断向量表不对啊
此帖出自NXP MCU论坛
 
 
 

回复

196

帖子

0

TA的资源

一粒金砂(中级)

19
 
多谢分享!
此帖出自NXP MCU论坛
 
 
 

回复

62

帖子

0

TA的资源

一粒金砂(高级)

20
 

回复 7楼 zhaojun_xf 的帖子

感谢楼主分享,有时间一定试试
此帖出自NXP MCU论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表