📄 iaptest.c
字号:
/****************************************************************************
* 文件名:IAPTEST.C
* 功能:LPC2100的IAP功能测试。
* 说明:调用IAP服务程序,完成FLASH编程操作。
* 将paramout添加到Watch窗口,观察返回值。
****************************************************************************/
#include "config.h"
#include "C:\keil\adsv1_2\Include\stdlib.h"
#define RdCode (*((volatile unsigned long *) 0x00002000))
/* 定义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 Led1 (1<<22)
typedef struct UartMode
{
uint8 datab;
uint8 stopb;
uint8 parity;
} UARTMODE;
uint32 paramin[8]; // IAP入口参数缓冲区
uint32 paramout[8]; // IAP出口参数缓冲区;
unsigned char tmp[512];
uint16 Rx;
uint8 wrFlash_Flag=0;
unsigned char *Rx_Buff;
unsigned char *Piap=(unsigned char *) 0x00002000;
extern void TargetResetInit(void);
void delay()
{
uint8 i;
for(i=0;i<10;i++);
}
void DelayNS(uint32 dly)
{
uint32 i;
for(;dly>0;dly--)
for(i=0;i<50000;i++);
}
/****************************************************************************
* 名称: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] = Fosc/1000; // 当不使用PLL功能时,Fcclk=Fosc
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] = Fosc/1000; // 当不使用PLL功能时,Fcclk=Fosc
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 Disable_Int()
{
VICVectAddr=0x00;
VICIntEnable=0x00000000;
}
uint8 UART0_Ini(uint32 baud,UARTMODE set)
{
uint32 bak;
if((0==baud)||(baud>115200)) return(0);
if((set.datab<5)||(set.datab>8)) return(0);
if((0==set.stopb)||(set.stopb>2)) return(0);
if(set.parity>4) return(0);
U0LCR=0x80;
bak=(Fpclk>>4)/baud;
U0DLM=bak>>8;
U0DLL=bak&0xff;
bak=set.datab-5;
if(2==set.stopb)bak|=0x04;
if(0!=set.parity)
{
set.parity=set.parity-1;
bak|=0x08;
}
bak|=set.parity<<4;
U0LCR=bak;
U0FCR=0x01;
U0IER=0x01;
return(1);
}
void UART0_SendByte(uint8 dat)
{
U0THR=dat;
while((U0LSR&0x20)==0);
}
void Uart0_SendString(char *str)
{
while(1)
{
if(*str=='\0')break;
UART0_SendByte(*str++);
}
}
void Uart0_Rx(void)
{
*Rx_Buff++=U0RBR;
Rx++;
if(Rx==32)
{
wrFlash_Flag=1;
Disable_Int();
}
// UART0_SendByte(Rx);
}
void __irq IRQ_UART0(void)
{
if( 0x04==(U0IIR&0x0F) )
{
Uart0_Rx();
}
VICVectAddr=0x00;
}
void System_Ini(void)
{
UARTMODE uart0_set;
PINSEL0=0x00000005; //使能UART0 和UART1 为零Modem
uart0_set.datab=8;
uart0_set.stopb=1;
uart0_set.parity=0;
UART0_Ini(115200,uart0_set);
VICIntSelect=0x00000000;
VICVectCntl0=0x26;
VICVectAddr0=(int)IRQ_UART0;
VICIntEnable=0x00000040;
Rx=0;
wrFlash_Flag=0;
}
void Enable_Int()
{
VICIntEnable=0x00000040;
}
/****************************************************************************
* 名称:main()
* 功能:IAP函数调用,测试。通过观察IAP出口参数来判断操作是否成功。
* 说明:程序没有进行出错处理。
* 要设置编译参数-apcs /interwork,因为IAP为Thumb指令。
* 使用IAP功能时,片内RAM的顶端的32字节保留给IAP操作使用,所以在STARTUP.S文件中
* 初始化系统模式堆栈为StackUsr-20*4,以保证IAP正常操作。
****************************************************************************/
int main(void)
{
uint16 i;
unsigned long wrBuff;
Rx_Buff=malloc(512);
wrBuff=(unsigned long)Rx_Buff;
if(Rx_Buff==NULL) return (0);
System_Ini();
IO0DIR=Led1;
IO0CLR=Led1;
DelayNS(100);
IO0SET=Led1;
DelayNS(100);
do{
/*
while(1)
{
delay();
if(wrFlash_Flag==1) break;
}
*/
for(i=0;i<512;i++)
*Rx_Buff++=i;
Uart0_SendString("Recieve finish!");
Disable_Int();
MAMCR = 0; // 关闭MAM
PLLCON = 0; // 关闭PLL
PLLFEED = 0xaa;
PLLFEED = 0x55;
ReadParID();
BootCodeID();
SelSector(1,1); // 选择扇区1
EraseSector(1,1); // 擦除扇区1
BlankCHK(1,1) ; // 查空扇区1
SelSector(1,1);
Rx_Buff--;
RamToFlash(0x00002000,wrBuff, 256); // 写数据到扇区1
// BlankCHK(1,1) ;
// Compare(0x00002000, 0x40000300, 512); // 比较数据
for(i=0;i<512;i++)
tmp[i]=*Piap++;
TargetResetInit();
/*
free(Rx_Buff);
Rx_Buff=malloc(512);
wrBuff=(unsigned long)Rx_Buff;
if(Rx_Buff==NULL) return (0);
*/
// Rx_Buff-=513;
System_Ini();
for(i=0;i<5;i++)
{
IO0CLR=Led1;
DelayNS(100);
IO0SET=Led1;
DelayNS(100);
}
}while(1);
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -