最近在做一个LPC1778的远程烧写,应用到了IAP编程,所以分享一下。
单片机源程序如下:
- #include "IAP.h"
- /*********************************************************************************************************
- 宏定义
- *********************************************************************************************************/
- #define IAP_ENTER_ADR 0x1FFF1FF1 /* IAP入口地址定义 */
- #if defined ( __CC_ARM )
- __align(4) INT8U GucIapTmp[1024]; /* 定义4K空间,编程Flash时使用 */
- #elif defined ( __ICCARM__ )
- #pragma pack(push)
- #pragma pack(4)
- INT8U GucIapTmp[1024];
- #pragma pack(pop)
- #endif
- /*
- * 定义CCLK值大小,单位为KHz
- */
- #define IAP_FCCLK (96000)
- #define IAP_ENTER_ADR 0x1FFF1FF1 /* IAP入口地址定义 */
- /*
- * 定义函数指针
- */
- void (*IAP_Entry) (INT32U param_tab[], INT32U result_tab[]);
- INT32U paramin[8]; /* IAP入口参数缓冲区 */
- INT32U paramout[8];
- #define UARTBPS 9600 /* 串口通信波特率 */
- volatile INT8U GucRcvOver; /* 接收完成标志 1:表示完成 */
- volatile INT32U GulRcvCount; /* 接收字节数 */
- INT32U *GpulFlagPoint = (INT32U *)UserFlag; /* 用户程序标志指针 */
- INT32U *pSECTORADDL1 = (INT32U *)SECTORADDL1; /* 用户程序标志指针 */
- INT32U *pSECTORADDL2 = (INT32U *)SECTORADDL2; /* 用户程序标志指针 */
- INT32U *pSECTORADDL3 = (INT32U *)SECTORADDL3; /* 用户程序标志指针 */
- INT32U *pSECTORADDH1 = (INT32U *)SECTORADDH1; /* 用户程序标志指针 */
- INT32U *pSECTORADDH2 = (INT32U *)SECTORADDH2; /* 用户程序标志指针 */
- INT32U *pSECTORADDH3 = (INT32U *)SECTORADDH3; /* 用户程序标志指针 */
- /* IAP出口参数缓冲区 */
- /*********************************************************************************************************
- ** Function name: sectorPrepare
- ** Descriptions: IAP操作扇区选择,命令代码50
- ** input parameters: sec1: 起始扇区
- ** sec2: 终止扇区
- ** output parameters: paramout[0]: IAP操作状态码,IAP返回值
- ** Returned value: paramout[0]: IAP操作状态码,IAP返回值
- *********************************************************************************************************/
- INT32U sectorPrepare (INT8U sec1, INT8U sec2)
- {
- paramin[0] = IAP_Prepare; /* 设置命令字 */
- paramin[1] = sec1; /* 设置参数 */
- paramin[2] = sec2;
- (*IAP_Entry)(paramin, paramout); /* 调用IAP服务程序 */
- return (paramout[0]); /* 返回状态码 */
- }
- /*********************************************************************************************************
- ** Function name: ramCopy
- ** 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返回值
- *********************************************************************************************************/
- INT32U ramToFlash (INT32U dst, INT32U src, INT32U 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]); /* 返回状态码 */
- }
- /*********************************************************************************************************
- ** Function name: sectorErase
- ** Descriptions: 扇区擦除,命令代码52
- ** input parameters: sec1 起始扇区
- ** sec2 终止扇区92
- ** output parameters: paramout[0]: IAP操作状态码,IAP返回值
- ** Returned value: paramout[0]: IAP操作状态码,IAP返回值
- *********************************************************************************************************/
- INT32U sectorErase (INT8U sec1, INT8U sec2)
- {
- paramin[0] = IAP_ERASESECTOR; /* 设置命令字 */
- paramin[1] = sec1; /* 设置参数 */
- paramin[2] = sec2;
- paramin[3] = IAP_FCCLK;
- (*IAP_Entry)(paramin, paramout); /* 调用IAP服务程序 */
- return (paramout[0]); /* 返回状态码 */
- }
- /*********************************************************************************************************
- ** Function name: blankChk
- ** Descriptions: 扇区查空,命令代码53
- ** input parameters: sec1: 起始扇区
- ** sec2: 终止扇区92
- ** output parameters: paramout[0]: IAP操作状态码,IAP返回值
- ** Returned value: paramout[0]: IAP操作状态码,IAP返回值
- *********************************************************************************************************/
- INT32U blankChk (INT8U sec1, INT8U sec2)
- {
- paramin[0] = IAP_BLANKCHK; /* 设置命令字 */
- paramin[1] = sec1; /* 设置参数 */
- paramin[2] = sec2;
- (*IAP_Entry)(paramin, paramout); /* 调用IAP服务程序 */
- return (paramout[0]); /* 返回状态码 */
- }
- /*********************************************************************************************************
- ** Function name: parIdRead
- ** Descriptions: 扇区查空,命令代码54
- ** input parameters: 无
- ** output parameters: paramout[0]: IAP操作状态码,IAP返回值
- ** Returned value: paramout[0]: IAP操作状态码,IAP返回值
- *********************************************************************************************************/
- INT32U parIdRead (void)
- {
- paramin[0] = IAP_READPARTID; /* 设置命令字 */
- (*IAP_Entry)(paramin, paramout); /* 调用IAP服务程序 */
- return (paramout[0]); /* 返回状态码 */
- }
- /*********************************************************************************************************
- ** Function name: codeIdBoot
- ** Descriptions: 扇区查空,命令代码55
- ** input parameters: 无
- ** output parameters: paramout[0]: IAP操作状态码,IAP返回值
- ** Returned value: paramout[0]: IAP操作状态码,IAP返回值
- *********************************************************************************************************/
- INT32U codeIdBoot (void)
- {
- paramin[0] = IAP_BOOTCODEID; /* 设置命令字 */
- (*IAP_Entry)(paramin, paramout); /* 调用IAP服务程序 */
- return (paramout[0]); /* 返回状态码 */
- }
- /*********************************************************************************************************
- ** 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返回值
- *********************************************************************************************************/
- INT32U dataCompare (INT32U dst, INT32U src, INT32U no)
- {
- paramin[0] = IAP_COMPARE; /* 设置命令字 */
- paramin[1] = dst; /* 设置参数 */
- paramin[2] = src;
- paramin[3] = no;
- (*IAP_Entry)(paramin, paramout); /* 调用IAP服务程序 */
- return (paramout[0]); /* 返回状态码 */
- }
- /*********************************************************************************************************
- ** Function name: u16CRC_Calc16
- ** Descriptions: crc16
- ** input parameters: 无
- ** output parameters: 无
- ** Returned value: 无
- *********************************************************************************************************/
- uint16_t u16CRC_Calc16(const uint8_t *pu8Data, int32_t i32Len)
- {
- uint8_t i;
- uint16_t u16CRC = 0;
- while(--i32Len >= 0)
- {
- i = 8;
- u16CRC = u16CRC ^ (((uint16_t)*pu8Data++) << 8);
- do
- {
- if (u16CRC & 0x8000)
- {
- u16CRC = u16CRC << 1 ^ 0x1021;
- }
- else
- {
- u16CRC = u16CRC << 1;
- }
- }
- while(--i);
- }
- return u16CRC;
- }
- /*********************************************************************************************************
- ** Function name: PrepareUpdate
- ** Descriptions:
- ** input parameters: 无
- ** output parameters: 无
- ** Returned value: 无
- *********************************************************************************************************/
- void PrepareUpdate (void )
- {
- #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
- OS_CPU_SR cpu_sr;
- #endif
- IAP_Entry = (void(*)())IAP_ENTER_ADR;
- if (*GpulFlagPoint==LOWADD) /* 当前程序运行在LOW区,需要 */
- { /* 对HIGH区进行升级 */
- OS_ENTER_CRITICAL();
- sectorPrepare(SECTORSNH1, SECTORSNH3); /* 选择HIGH扇区 */
- sectorErase(SECTORSNH1, SECTORSNH3); /* 擦除HIGH扇区 */
- OS_EXIT_CRITICAL();
- } /* 当前程序运行在HIGH区或者固 */
- else{ /* 件区,需要对LOW区进行升级 */
- OS_ENTER_CRITICAL();
- sectorPrepare(SECTORSNL1, SECTORSNL3); /* 选择LOW扇区 */
- sectorErase(SECTORSNL1, SECTORSNL3); /* 擦除LOW扇区 */
- OS_EXIT_CRITICAL();
- }
- }
- /*********************************************************************************************************
- ** Function name: userFlagUpdate
- ** Descriptions: 更新用户程序标志区
- ** input parameters: 无
- ** output parameters: 无
- ** Returned value: 无
- *********************************************************************************************************/
- void userFlagUpdate (void)
- {
- #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
- OS_CPU_SR cpu_sr;
- #endif
- INT32U *pulDataPoint; /* 更新用户程序标志空间 */
- memset(GucIapTmp, 0xff, 256); /* 临时缓冲区清空 */
- pulDataPoint = (INT32U *)GucIapTmp;
- if (*GpulFlagPoint==LOWADD){
- *pulDataPoint=HIGHADD;
- }
- else{
- *pulDataPoint=LOWADD;
- }
- OS_ENTER_CRITICAL();
- sectorPrepare (SECTORFLAG, SECTORFLAG); /* 扇区准备 */
- sectorErase (SECTORFLAG, SECTORFLAG); /* 擦除扇区 */
- sectorPrepare (SECTORFLAG, SECTORFLAG); /* 选择扇区 */
- ramToFlash(UserFlag,(INT32U)GucIapTmp, 256); /* 编程FLASH */
- OS_EXIT_CRITICAL();
- }
- /*********************************************************************************************************
- ** Function name: userDataProgram
- ** Descriptions:
- ** input parameters: 无
- ** output parameters: 无
- ** Returned value: 无
- *********************************************************************************************************/
- void user(void)
- {
- defaultVectorHandle();
- }
- #define SECTORSIZE (32*1024) //扇区大小
- /*********************************************************************************************************
- ** Function name: userDataProgram
- ** Descriptions: 编程用户代码区
- ** input parameters: 无
- ** output parameters: 无
- ** Returned value: 无
- *********************************************************************************************************/
- uint8_t userDataProgram (uint8_t *pdat)
- {
- #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
- OS_CPU_SR cpu_sr;
- #endif
- uint16_t filedatcrc;
- uint16_t fnum,fsn,flen;
- // void (*userProgram)(); /* 函数指针 */
- uint16_t NPS;
- // userProgram = (void (*)()) user; /* 避免编译警告 */
- fnum = *pdat + *(pdat+1)*256;
- fsn = *(pdat+2) + *(pdat+3)*256;
- flen = *(pdat+4) + *(pdat+5)*256;
- if(fnum==0 && fsn==0 && flen==0){
- //ANDYDEBUG 20150805
- sPTL_104_I_SND.Rson=0x0007;
- //ANDYDEBUG 20150805
- PrepareUpdate();
- SysUpdateFsnBak = fsn;
- SysUpdateFlag = 1; // 启动升级
- if (*GpulFlagPoint==LOWADD)
- return UPHI;
- else
- return UPLO;
- }
- //ANDYDEBUG 20150805
- sPTL_104_I_SND.Rson=0x000A;
- //ANDYDEBUG 20150805
- if(SysUpdateFlag==0) // 未启动升级
- return UPERR0;
- if(fnum==fsn && flen==0 && fnum>0) { // 执行升级程序
- userFlagUpdate(); // 升级扇区标识
- zyReset(ZY_HARD_RESET);
- return UPOK;
- }
- if(fnum==0 || fsn ==0 || fsn>fnum) // 序号排错
- return UPERR1;
- #ifndef TP1C
- if (flen != 256 && flen != 512 && flen != 1024 ) // 帧长归整
- { // 满足编程字节数的要求,256、512、1024等
- if (flen < 256)
- flen = 256;
- else if (flen < 512)
- flen = 512;
- else if (flen < 1024)
- flen = 1024;
- else
- return UPERR3;
- }
- filedatcrc = u16CRC_Calc16(pdat+6,flen); // CRC16校验
- if(filedatcrc != (*(pdat+6+flen) + *(pdat+7+flen)*256))
- return UPERRcrc;
- if(fsn!=SysUpdateFsnBak+1) // 帧顺序校验
- return UPERR2;
- SysUpdateFsnBak=fsn;
- NPS= SECTORSIZE/flen; // 单个扇区帧容量
- memcpy(GucIapTmp,pdat+6,flen); // 写升级数据入缓存
- #else
- if(flen != 128 && flen != 256 && flen != 512 && flen != 1024 )
- { // 满足编程字节数的要求,256、512、1024等 // 帧长归整
- if (flen < 128)
- flen = 128;
- else if (flen < 256)
- flen = 256;
- else if (flen < 512)
- flen = 512;
- else if (flen < 1024)
- flen = 1024;
- else
- return UPERR3;
- }
- filedatcrc = u16CRC_Calc16(pdat+6,flen); // CRC16校验
- if(filedatcrc != (*(pdat+6+flen) + *(pdat+7+flen)*256))
- return UPERRcrc;
- if(fsn!=SysUpdateFsnBak+1) // 帧顺序校验
- return UPERR2;
- SysUpdateFsnBak=fsn;
- NPS= SECTORSIZE/flen; // 单个扇区帧容量
- if(flen==128){
- if(fsn%2){
- if(fsn memcpy(GucIapTmp,pdat+6,flen); // 写升级数据入缓存
- return UPOK;
- }
- else {
- memcpy(GucIapTmp,pdat+6,flen); // 写升级数据入缓存
- memset(GucIapTmp+128,0xff,flen); // 结束帧补齐256字节
- NPS/=2;
- fsn/=2;
- fsn++;
- flen*=2;
- }
- }
- else {
- memcpy(GucIapTmp+128,pdat+6,flen); // 写升级数据入缓存
- NPS/=2;
- fsn/=2;
- flen*=2;
- }
- }
- else
- memcpy(GucIapTmp,pdat+6,flen); // 写升级数据入缓存
- #endif
- if (*GpulFlagPoint==LOWADD) /* 当前程序运行在LOW区,需要 */
- { /* 对HIGH区进行升级 */
- OS_ENTER_CRITICAL();
- if(fsn>0 && fsn<=NPS){
- sectorPrepare(SECTORSNH1, SECTORSNH1); /* 准备HIGH扇区 */
- ramToFlash(SECTORADDH1 + (fsn-1)*flen,(INT32U)GucIapTmp, flen); /* 写数据到FLASH */
- if(CMD_SUCCESS != dataCompare((INT32U)GucIapTmp,SECTORADDH1+(fsn-1)*flen,flen))
- return UPERRwrt;
- }
- if(fsn>NPS && fsn<=NPS*2){
- sectorPrepare(SECTORSNH2, SECTORSNH2);
- ramToFlash(SECTORADDH2 + (fsn-NPS-1)*flen,(INT32U)GucIapTmp, flen);
- if(CMD_SUCCESS != dataCompare((INT32U)GucIapTmp,SECTORADDH2+(fsn-NPS-1)*flen,flen))
- return UPERRwrt;
- }
- if(fsn>NPS*2 && fsn<=NPS*3){
- sectorPrepare(SECTORSNH3, SECTORSNH3);
- ramToFlash(SECTORADDH3 + (fsn-NPS*2-1)*flen,(INT32U)GucIapTmp, flen);
- if(CMD_SUCCESS != dataCompare((INT32U)GucIapTmp,SECTORADDH3+(fsn-NPS*2-1)*flen, flen))
- return UPERRwrt;
- }
- OS_EXIT_CRITICAL();
- }
- else /* 当前程序运行在HIGH区,需要 */
- { /* 对LOW区进行升级 */
- OS_ENTER_CRITICAL();
- if(fsn>0 && fsn<=NPS){
- sectorPrepare(SECTORSNL1, SECTORSNL1); /* 准备LOW扇区 */
- ramToFlash(SECTORADDL1 + (fsn-1)*flen,(INT32U)GucIapTmp, flen); /* 写数据到FLASH */
- if(CMD_SUCCESS != dataCompare((INT32U)GucIapTmp,SECTORADDL1+(fsn-1)*flen,flen))
- return UPERRwrt;
- }
- if(fsn>NPS && fsn<=NPS*2){
- sectorPrepare(SECTORSNL2, SECTORSNL2);
- ramToFlash(SECTORADDL2 + (fsn-NPS-1) * flen,(INT32U)GucIapTmp, flen);
- if(CMD_SUCCESS != dataCompare((INT32U)GucIapTmp,SECTORADDL2+(fsn-NPS-1)*flen,flen))
- return UPERRwrt;
- }
- if(fsn>NPS*2 && fsn<=NPS*3){
- sectorPrepare(SECTORSNL3, SECTORSNL3);
- ramToFlash(SECTORADDL3 + (fsn-NPS*2-1)*flen,(INT32U)GucIapTmp, flen);
- if(CMD_SUCCESS != dataCompare((INT32U)GucIapTmp,SECTORADDL3+(fsn-NPS*2-1)*flen,flen))
- return UPERRwrt;
- }
- OS_EXIT_CRITICAL();
- }
- return UPOK;
- }
- /*********************************************************************************************************
- ** Function name: zyReset
- ** Descriptions: 系统复位
- ** input parameters: uiMode: ZY_POWER_RESET: 上电复位
- ** ZY_HARD_RESET: 硬件复位
- ** ZY_SOFT_RESET: 软件复位
- ** 其它: 与系统相关
- ** output parameters: none
- ** Returned value: none
- ** Created by: Chenmingji
- ** Created Date: 2009-07-23
- **--------------------------------------------------------------------------------------------------------
- ** Modified by:
- ** Modified date:
- *********************************************************************************************************/
- void zyReset (unsigned int uiMode)
- {
- switch (uiMode) {
- case ZY_POWER_RESET: /* 此系统上电复位等同硬件复位 */
- #if 0
- break;
- #endif /* 0 */
- case ZY_HARD_RESET:
- //changeToSYSMode();
- //AITCR = (0x05fa << 16) + 4;
- wdt_entry();
- break;
- case ZY_SOFT_RESET:
- //changeToSYSMode();
- //AITCR = (0x05fa << 16) + 1;
- wdt_entry();
- break;
- default: /* 参数不正确不复位 */
- break;
- }
- }
- /*********************************************************************************************************
- ** Function name: defaultVectorHandle
- ** Descriptions: ????????
- ** input parameters: none
- ** output parameters: none
- ** Returned value: none
- *********************************************************************************************************/
- void defaultVectorHandle (void)
- {
- #ifdef DEBUG
- while (1);
- #else
- zyReset(ZY_HARD_RESET);
- #endif /* DEBUG */
- }
- /*********************************************************************************************************
- End Of File
- *********************************************************************************************************/
所有资料51hei提供下载:
LPC1778 IAP烧写源码.docx
|
0
|
|
|
|