搜索
bottom↓
回复: 4

LPC1100处理器通过SD卡实现IAP功能

[复制链接]

出0入0汤圆

发表于 2012-3-27 14:25:02 | 显示全部楼层 |阅读模式
本帖最后由 huashai 于 2012-3-27 14:24 编辑

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

下面先介绍LPC1100处理器IAP的基础知识:
1. LPC1100处理器(LPC1114)Flash分配:LPC1114一共有32K Flash,共分为8个扇区,每个扇区的大小为4K,具体如下:


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


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


IAP功能应用:
1.定义IAP程序的入口地址
#define  IAP_ENTER_ADR 0x1FFF1FF1   /* IAP入口地址定义  */

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

3.定义函数类型指针
void (*IAP_Entry)(uint32 *param_tab, uint32 *result_tab) = (void(*)())IAP_ENTER_ADR; // 定义函数指针

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

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

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



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

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

/*******************************************************************************
** 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.擦除扇区

/*******************************************************************************
** 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.扇区查空


/**********************************************************************************
** 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服务程序 */

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



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


/*******************************************************************************
** 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服务程序   */

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


----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
有上面的几个函数后,下面就可以根据需要编写SD卡升级函数了:
1.定义用户程序地址
定义用户程序的起始地址,用户可以根据自己的实际情况设定,一般都从0x0000 0000开始存放IAP代码,之后的空间才是存放用户代码的。

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

2.从SD卡中读写bin文件更新升级
从SD卡中升级程序很简单。流程是:从SD卡中打开升级文件,每次读取512字节,然后写入Flash,直到编写完成。
IAP支持256/512/1024/2048/4096等多字节编程方式,只是SD卡每扇区大小一般都是512字节,所以这里使用512字节为单位进行编程。


/**********************************************************************************
* 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;



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



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

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

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

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

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

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

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

    return FR_OK;
}



3.主函数:
主函数实现按键扫描,如果有按键,进行SD卡升级,如果没有按键直接跳转到应用程序。
代码一开始判断按键,所以一般都是需要按下按键后复位系统,当然也可以适当循环扫描按键的次数。等待一定的时间。。。。。。。


/**********************************************************************************
* FunctionName   : main()
* Description    : 主函数
* EntryParameter : None
* ReturnValue    : None
*********************************************************************************/
int main(void)
{
    void (*userProgram)() = (void (*)())OSInit;     // 函数指针  



    OSInit();                // 初始化系统

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

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


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

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

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





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



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



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

具体的升级过程:
1.把IAP程序下载到板子上。
2.编写并编译好应用程序,需要是的bin文件。
3.把应用程序的bin文件拷贝到SD卡中。
4.在板子上插入SD卡,并按下按键重启系统。
5.板子就会自动实现升级并跳转到应用中运行。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2012-3-29 10:41:54 | 显示全部楼层
有空测试一下啊,先谢谢

出0入0汤圆

发表于 2013-7-18 16:26:46 | 显示全部楼层
马上使用到,学习一下

出0入0汤圆

发表于 2014-6-11 15:21:30 | 显示全部楼层
mark学习了

出0入0汤圆

发表于 2015-11-3 16:46:52 | 显示全部楼层
IAP mark.
ZLG的例程感觉复杂了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-27 12:43

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表