?? 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 + -