📄 iapboot.c
字号:
/****************************************************************************
* File:IAPTEST.C
* 功能:LPC210x的IAP功能测试。
* 说明:调用IAP服务程序,完成FLASH编程操作。
****************************************************************************/
#include <string.h>
#include <stdlib.h>
//#include "basic.h"
#include "config.h"
#include "smartcard.h"
#define APP_MAIN_ADDRESS 0X00004000 //主程序入口地址
#define LAMP 0x01000000 //P0.24 状态指示灯
#define Bright IO1CLR = LAMP; //
#define Drown IO1SET = LAMP;
#define IAP_ENTER_ADR 0x7FFFFFF1 /* IAP入口地址定义 */
/* 定义IAP命令字 */
#define IAP_SELSECTOR 50
#define IAP_RAMTOFLASH 51
#define IAP_ERASESECTOR 52
#define IAP_BLANKCHK 53
#define IAP_READPARTID 54
#define IAP_BOOTCODEID 55
#define IAP_COMPARE 56
/* 定义IAP返回状态字 */
#define CMD_SUCCESS 0
#define INVALID_COMMAND 1
#define SRC_ADDR_ERROR 2
#define DST_ADDR_ERROR 3
#define SRC_ADDR_NOT_MAPPED 4
#define DST_ADDR_NOT_MAPPED 5
#define COUNT_ERROR 6
#define INVALID_SECTOR 7
#define SECTOR_NOT_BLANK 8
#define SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION 9
#define COMPARE_ERROR 10
#define BUSY 11
#define PARAM_ERROR 12 /* Insufficient number of parameters */
#define ADDR_ERROR 13 /* Address not on word boundary */
#define ADDR_NOT_MAPPED 14
#define CMD_LOCKED 15 /* Command is locked */
#define INVALID_CODE 16 /* Unlock code is invalid */
#define INVALID_BAUD_RATE 17
#define INVALID_STOP_BIT 18
#define IAP_ERR -1 /*自定义错误值*/
/* 定义CCLK值大小,单位为KHz */
#define IAP_FCCLK 11059
//定义用户应用程序所用扇区范围
#define EE_SEC_L 4
#define EE_SEC_H 10
#define ICFileBlockSize 0x8000;
//升级应用程序的
int32 FileSumNum = 0; //应用程序文件的总块数
int32 LastFileSize = 0; //最后一个文件的大小
/* 定义函数指针 */
void (*IAP_Entry)(uint32 param_tab[], uint32 result_tab[]);
//应用程序入口
void (*run_app)(void)=(void (*)(void))APP_MAIN_ADDRESS;
uint32 paramin[8]; // IAP入口参数缓冲区
uint32 paramout[8]; // IAP出口参数缓冲区
uint8 psData[520]; // 升级数据
/****************************************************************************
* 名称:SelSector()
* 功能:IAP操作扇区选择,命令代码50。
* 入口参数:sec1 起始扇区
* sec2 终止扇区
* 出口参数:IAP返回值(paramout缓冲区)
****************************************************************************/
void SelSector(uint8 sec1, uint8 sec2)
{ paramin[0] = IAP_SELSECTOR; // 设置命令字
paramin[1] = sec1; // 设置参数
paramin[2] = sec2;
(*IAP_Entry)(paramin, paramout); // 调用IAP服务程序
}
/****************************************************************************
* 名称:RamToFlash()
* 功能:复制RAM的数据到FLASH,命令代码51。
* 入口参数:dst 目标地址,即FLASH起始地址。以512字节为分界
* src 源地址,即RAM地址。地址必须字对齐
* no 复制字节个数,为512/1024/4096/8192
* 出口参数:IAP返回值(paramout缓冲区)
****************************************************************************/
void 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服务程序
}
/****************************************************************************
* 名称:EraseSector()
* 功能:扇区擦除,命令代码52。
* 入口参数:sec1 起始扇区
* sec2 终止扇区
* 出口参数:IAP返回值(paramout缓冲区)
****************************************************************************/
void EraseSector(uint8 sec1, uint8 sec2)
{ paramin[0] = IAP_ERASESECTOR; // 设置命令字
paramin[1] = sec1; // 设置参数
paramin[2] = sec2;
paramin[3] = IAP_FCCLK;
(*IAP_Entry)(paramin, paramout); // 调用IAP服务程序
}
/****************************************************************************
* 名称:BlankCHK()
* 功能:扇区查空,命令代码53。
* 入口参数:sec1 起始扇区
* sec2 终止扇区
* 出口参数:IAP返回值(paramout缓冲区)
****************************************************************************/
void BlankCHK(uint8 sec1, uint8 sec2)
{ paramin[0] = IAP_BLANKCHK; // 设置命令字
paramin[1] = sec1; // 设置参数
paramin[2] = sec2;
(*IAP_Entry)(paramin, paramout); // 调用IAP服务程序
}
/****************************************************************************
* 名称:ReadParID()
* 功能:扇区查空,命令代码53。
* 入口参数:无
* 出口参数:IAP返回值(paramout缓冲区)
****************************************************************************/
void ReadParID(void)
{ paramin[0] = IAP_READPARTID; // 设置命令字
(*IAP_Entry)(paramin, paramout); // 调用IAP服务程序
}
/****************************************************************************
* 名称:BootCodeID()
* 功能:读取boot代码版本号,命令代码55。
* 入口参数:无
* 出口参数:IAP返回值(paramout缓冲区)
****************************************************************************/
void BootCodeID(void)
{ paramin[0] = IAP_BOOTCODEID; // 设置命令字
(*IAP_Entry)(paramin, paramout); // 调用IAP服务程序
}
/****************************************************************************
* 名称:Compare()
* 功能:校验数据,命令代码56。
* 入口参数:dst 目标地址,即RAM/FLASH起始地址。地址必须字对齐
* src 源地址,即FLASH/RAM地址。地址必须字对齐
* no 复制字节个数,必须能被4整除
* 出口参数:IAP返回值(paramout缓冲区)
****************************************************************************/
void Compare(uint32 dst, uint32 src, uint32 no)
{ paramin[0] = IAP_COMPARE; // 设置命令字
paramin[1] = dst; // 设置参数
paramin[2] = src;
paramin[3] = no;
(*IAP_Entry)(paramin, paramout); // 调用IAP服务程序
}
void delay()
{
volatile uint32 i = 0x4ffff;
while(i--){};
}
//擦除整个应用程序存储FLASH
int iap_entire_erase()
{
SelSector(EE_SEC_L,EE_SEC_H);
EraseSector(EE_SEC_L,EE_SEC_H); // 擦除扇区1
BlankCHK(EE_SEC_L,EE_SEC_H);
if(paramout[0] != CMD_SUCCESS){
return IAP_ERR;
}
return 0;
}
//写入数据到ROM FLASH
int32 iap_copyto(uint32 dst, uint8 *src, uint32 len)
{
int start, end;
if((uint32) dst < 0x8000){
start = (uint32) dst >> 12;
if(((uint32) dst & 0xfff) + len > 0x1000){
end = start + 1;
}else{
end = start;
}
}else if((uint32) dst < 0x78000){
start = ((uint32) dst >> 15) + 7;
if(((uint32) dst & 0x7fff) + len > 0x8000){
end = start + 1;
}else{
end = start;
}
}else if((uint32) dst < 0x7d000){
start = ((uint32) dst >> 12) - 0x62;
if(((uint32) dst & 0xfff) + len > 0x1000){
end = start + 1;
if(end > 26) return IAP_ERR;
}else{
end = start;
}
}else{
return IAP_ERR;
}
SelSector(start,end);
if(paramout[0] != CMD_SUCCESS){
return IAP_ERR;
}
if(len < 256)
len = 256;
RamToFlash(dst, (uint32)src, len);
if(paramout[0] != CMD_SUCCESS){
return IAP_ERR;
}
return 0;
}
void LampStateFlash(int time)
{
while(time --){
Bright;
delay();
Drown;
delay();
}
}
int CheckUpdateFlag()
{
char cTemp[8];
if( UserCardStart() )
return 0;
if( UserCardSelect(0x01, 0x00) )//选择USER卡分户编号文件
return 0;
if( UserCardReadBin(0, 75, psData) )//读USER卡分户编号文件
return 0;
memset(cTemp, 0, 8);
memcpy(cTemp, psData+68, 2);
FileSumNum = atoi(cTemp)-1;
memset(cTemp, 0, 8);
memcpy(cTemp, psData+70, 5);
LastFileSize = atoi(cTemp);
if(FileSumNum <= 0)
return 0;
return 1;
}
int UpdateDataFromIC( )
{
int i;
int offset = 0;
int filelen = 0;
int readlen;
int offsetrom = 0;
for(i=0; i<FileSumNum; i++)
{
if(i == FileSumNum-1)
filelen = LastFileSize;
else
filelen = ICFileBlockSize;
if( UserCardSelect(i+2, 0x00) )//选择USER卡分户编号文件
return -1;
offset = 0;
//写入一个文件块
while(offset < filelen)
{
memset(psData, 0xFF, 512);
//读入512个字节,写入一次ROM
while(1)
{
if( (filelen - offset) < 128)
readlen = (filelen - offset);
else
readlen = 128;
if( UserCardReadBin(offset, readlen, psData+(offset & 0x1FF) ) )//读USER卡分户编号文件
return -1;
offset += readlen;
if( (offset & 0x1FF) == 0x00 || filelen == offset)
break;
}
//执行IAP写入flash
if( iap_copyto(APP_MAIN_ADDRESS+offsetrom, psData, 512) != 0)
return -1;
LampStateFlash(1);
offsetrom += 512;
}
}
return 0;
}
/****************************************************************************
* 名称:main()
* 功能:IAP函数调用,测试。
****************************************************************************/
int main(void)
{
PINSEL0 = 0x000A0055; // 设置I/O连接到UART0,使用I2C口,pwm4,pwm6
IO1DIR |= LAMP; //指示灯信号输出
SMARTCARD_Ini(); // 初始化智能卡端口
IAP_Entry = (void(*)())IAP_ENTER_ADR; // 初始化函数指针IAP_Entry
//读取升级标志
//读取用户卡检测升级标志
if(CheckUpdateFlag() == 0)
{
//不需要升级转入应用程序入口
Useoff();
run_app();
}
//擦除应用存储FLASH
if(iap_entire_erase() != 0)
goto ERR;
//读取升级数据
if( UpdateDataFromIC() != 0)
goto ERR;
//读取文件总长度和校验和
//检查校验和
//转入应用程序入口
Useoff();
run_app();
while(1);
ERR:
Useoff();
while(1)
{
LampStateFlash(1);
}
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -