📄 rack_iap.c
字号:
/* 移值IAP演示程序 刘国兵 2006-7-4 */
/*
在IAP程序中,应注意以下问题
1. IAP服务代码是Thumb指令,所以调用时要进行处理器状态切换或使用BX指令调用,若使用C程序直接调用,请设置编译参数-apcs /interwork
2. IAP占用片内RAM的最高端的32字节空间,如果用户要使用IAP功能,那么请保留这部分RAM
(此项目中我已修改"Startup.s"文件 " MSR CPSR_c, #0xdf
LDR SP, =StackUsr-32")"
3. 调用IAP功能前,要关闭PLL、MAM部件及所有中断
*/
#include "Rack_PrjHead.h"
/* 定义函数指针 */
//void (*IAP_Entry)(uint32 param_tab[], uint32 result_tab[]);
uint32 paramin[8]; // IAP入口参数缓冲区
uint32 paramout[8]; // IAP出口参数缓冲区
// IAP_Entry = (void(*)())IAP_ENTER_ADR; // 初始化函数指针IAP_Entry
/*
*********************************************************************************************************
** 函数名称:SelSector()
** 函数功能:IAP操作扇区选择,命令代码50。
** 入口参数:sec1 起始扇区
** sec2 终止扇区
** 出口参数:IAP操作状态码
** IAP返回值(paramout缓冲区)
*******************************************************************************************************
*/
uint32 SelSector(uint8 sec1, uint8 sec2)
{
paramin[0] = IAP_SELECTOR; // 设置命令字
paramin[1] = sec1; // 设置参数
paramin[2] = sec2;
iap_entry(paramin, paramout); // 调用IAP服务程序
return(paramout[0]); // 返回状态码
}
/*
*******************************************************************************************************
** 函数名称:RamToFlash()
** 函数功能:复制RAM的数据到FLASH,命令代码51。
** 入口参数:dst 目标地址,即FLASH起始地址。以512字节为分界
** src 源地址,即RAM地址。地址必须字对齐
** no 复制字节个数,为512/1024/4096/8192
** 出口参数:IAP操作状态码
** IAP返回值(paramout缓冲区)
*******************************************************************************************************
*/
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]); // 返回状态码
}
/*
*******************************************************************************************************
** 函数名称:EraseSector()
** 函数功能:扇区擦除,命令代码52。
** 入口参数:sec1 起始扇区
** sec2 终止扇区
** 出口参数:IAP操作状态码
** IAP返回值(paramout缓冲区)
*******************************************************************************************************
*/
uint32 EraseSector(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]); // 返回状态码
}
/*
*******************************************************************************************************
** 函数名称:BlankCHK()
** 函数功能:扇区查空,命令代码53。
** 入口参数:sec1 起始扇区
** sec2 终止扇区
** 出口参数:IAP操作状态码
** IAP返回值(paramout缓冲区)
*******************************************************************************************************
*/
uint32 BlankCHK(uint8 sec1, uint8 sec2)
{
paramin[0] = IAP_BLANKCHK; // 设置命令字
paramin[1] = sec1; // 设置参数
paramin[2] = sec2;
iap_entry(paramin, paramout); // 调用IAP服务程序
return(paramout[0]); // 返回状态码
}
/*
*******************************************************************************************************
** 函数名称:ReadParID()
** 函数功能:扇区查空,命令代码53。
** 入口参数:无
** 出口参数:IAP操作状态码
** IAP返回值(paramout缓冲区)
*******************************************************************************************************
*/
uint32 ReadParID(void)
{
paramin[0] = IAP_READPARTID; // 设置命令字
iap_entry(paramin, paramout); // 调用IAP服务程序
return(paramout[0]); // 返回状态码
}
/*
*******************************************************************************************************
** 函数名称:BootCodeID()
** 函数功能:读取boot代码版本号,命令代码55。
** 入口参数:无
** 出口参数:IAP操作状态码
** IAP返回值(paramout缓冲区)
*******************************************************************************************************
*/
uint32 BootCodeID(void)
{
paramin[0] = IAP_BOOTCODEID; // 设置命令字
iap_entry(paramin, paramout); // 调用IAP服务程序
return(paramout[0]); // 返回状态码
}
/*
*******************************************************************************************************
** 函数名称:Compare()
** 函数功能:校验数据,命令代码56。
** 入口参数:dst 目标地址,即RAM/FLASH起始地址。地址必须字对齐
** src 源地址,即FLASH/RAM地址。地址必须字对齐
** no 复制字节个数,必须能被4整除
** 出口参数:IAP操作状态码
** IAP返回值(paramout缓冲区)
*******************************************************************************************************
*/
uint32 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服务程序
return(paramout[0]); // 返回状态码
}
/*
*******************************************************************************************************
** 函数名称:main()
** 函数功能:IAP函数调用,演示程序
** 因LPC22xx与LPC2132扇区不同,其程序中 IAP_MARK1 与 IAP_MARK2处做适当修改
** 注:LPC2132 flash扇区分布
** 共8个扇区,每扇区4KB
** 如:
** 扇区号 0 0x0000 0000 -> 0x0000 0fff
** 扇区号 7 0x0000 7000 -> 0x0000 7fff
** LPC22xx每扇区8KB(注:当 flash size >= 256KB 时,扇区大小不一至)
*******************************************************************************************************
*/
uint8 Rack_IAP_Ready(void)
{
uint8 err;
//uint32 i;
MAMCR = 0; // 关闭MAM
PLLCON = 0; // 关闭PLL
PLLFEED = 0xaa;
PLLFEED = 0x55;
SelSector(IAP_Sector_Start,IAP_Sector_End); // 选择扇区
EraseSector(IAP_Sector_Start,IAP_Sector_End); // 擦除扇区
BlankCHK(IAP_Sector_Start,IAP_Sector_End) ; // 查空扇区
SelSector(IAP_Sector_Start,IAP_Sector_End); // 选择扇区
//IAP_MARK1 用此句代替下一句可实现用现有开发板实验
//RamToFlash(0x00002000, 0x40001000, 512); // 写数据到扇区1 (LPC2214)
RamToFlash(IAP_RAM_Start, IAP_Flash_Start, IAP_Number); // 写数据到扇区1 (LPC2132)
//IAP_MARK2 用此句代替下一句可实现用现有开发板实验
//err = Compare(0x00002000, 0x40001000, 512); // 比较数据 (LPC2214)
err = Compare(IAP_RAM_Start, IAP_Flash_Start, IAP_Number); // 比较数据 (LPC2132)
// if(err == CMD_SUCCESS)
// { /* 成功,蜂鸣一声 */
// IO0CLR = BEEP;
// for (i=0; i<0x3FFFFF; i++);
// IO0SET = BEEP;
// }
// else
// { /* 失败,一直蜂鸣 */
// IO0CLR = BEEP;
// }
while(1);
return(0);
}
/*
*******************************************************************************************************
** 函数名称:IAP_Write_SADDR()
** 函数功能:IAP函数调用,对flash进行program。
** 因LPC22xx与LPC2132扇区不同,其程序中 IAP_MARK1 与 IAP_MARK2处做适当修改
** 注:LPC2103 flash扇区分布
** 共8个扇区,每扇区4KB
** 如:
** 扇区号 0 0x0000 0000 -> 0x0000 0fff
** 扇区号 7 0x0000 7000 -> 0x0000 7fff
** LPC22xx每扇区8KB(注:当 flash size >= 256KB 时,扇区大小不一至)
*******************************************************************************************************
*/
uint8 IAP_Write_SADDR(void)
{
uint8 err;
uint32 VICIntEnable_bak;
VICIntEnable_bak = VICIntEnable; //屏蔽所有中断
VICIntEnClr = 0xffff;
MAMCR = 0; // 关闭MAM
PLLCON = 0; // 关闭PLL
PLLFEED = 0xaa;
PLLFEED = 0x55;
SelSector(IAP_Sector_Start,IAP_Sector_End); // 选择扇区
EraseSector(IAP_Sector_Start,IAP_Sector_End); // 擦除扇区
BlankCHK(IAP_Sector_Start,IAP_Sector_End) ; // 查空扇区
SelSector(IAP_Sector_Start,IAP_Sector_End); // 选择扇区
//IAP_MARK1 用此句代替下一句可实现用现有开发板实验
//RamToFlash(0x00002000, 0x40001000, 512); // 写数据到扇区1 (LPC2214)
RamToFlash(IAP_Flash_Start, IAP_RAM_Start, IAP_Number); // 写数据到扇区 (LPC2132)
//IAP_MARK2 用此句代替下一句可实现用现有开发板实验
//err = Compare(0x00002000, 0x40001000, 512); // 比较数据 (LPC2214)
err = Compare(IAP_Flash_Start, IAP_RAM_Start, IAP_Number); // 比较数据 (LPC2132)
//重新开启MAM and PLL
// 设置系统各部分时钟
// Set system timers for each component
PLLCON = 1;
#if (Fpclk / (Fcclk / 4)) == 1
VPBDIV = 0;
#endif
#if (Fpclk / (Fcclk / 4)) == 2
VPBDIV = 2;
#endif
#if (Fpclk / (Fcclk / 4)) == 4
VPBDIV = 1;
#endif
#if (Fcco / Fcclk) == 2
PLLCFG = ((Fcclk / Fosc) - 1) | (0 << 5);
#endif
#if (Fcco / Fcclk) == 4
PLLCFG = ((Fcclk / Fosc) - 1) | (1 << 5);
#endif
#if (Fcco / Fcclk) == 8
PLLCFG = ((Fcclk / Fosc) - 1) | (2 << 5);
#endif
#if (Fcco / Fcclk) == 16
PLLCFG = ((Fcclk / Fosc) - 1) | (3 << 5);
#endif
PLLFEED = 0xaa;
PLLFEED = 0x55;
while((PLLSTAT & (1 << 10)) == 0);
PLLCON = 3;
PLLFEED = 0xaa;
PLLFEED = 0x55;
/* 设置存储器加速模块 */
/* Set memory accelerater module*/
MAMCR = 0;
#if Fcclk < 20000000
MAMTIM = 1;
#else
#if Fcclk < 40000000
MAMTIM = 2;
#else
MAMTIM = 3;
#endif
#endif
MAMCR = 2;
VICIntEnable = VICIntEnable_bak;
return(err);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -