標(biāo)題:
LPC1778的IAP編程源碼
[打印本頁]
作者:
linhang945
時(shí)間:
2018-4-26 09:38
標(biāo)題:
LPC1778的IAP編程源碼
最近在做一個(gè)LPC1778的遠(yuǎn)程燒寫,應(yīng)用到了IAP編程,所以分享一下。
單片機(jī)源程序如下:
#include "IAP.h"
/*********************************************************************************************************
宏定義
*********************************************************************************************************/
#define IAP_ENTER_ADR 0x1FFF1FF1 /* IAP入口地址定義 */
#if defined ( __CC_ARM )
__align(4) INT8U GucIapTmp[1024]; /* 定義4K空間,編程Flash時(shí)使用 */
#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入口地址定義 */
/*
* 定義函數(shù)指針
*/
void (*IAP_Entry) (INT32U param_tab[], INT32U result_tab[]);
INT32U paramin[8]; /* IAP入口參數(shù)緩沖區(qū) */
INT32U paramout[8];
#define UARTBPS 9600 /* 串口通信波特率 */
volatile INT8U GucRcvOver; /* 接收完成標(biāo)志 1:表示完成 */
volatile INT32U GulRcvCount; /* 接收字節(jié)數(shù) */
INT32U *GpulFlagPoint = (INT32U *)UserFlag; /* 用戶程序標(biāo)志指針 */
INT32U *pSECTORADDL1 = (INT32U *)SECTORADDL1; /* 用戶程序標(biāo)志指針 */
INT32U *pSECTORADDL2 = (INT32U *)SECTORADDL2; /* 用戶程序標(biāo)志指針 */
INT32U *pSECTORADDL3 = (INT32U *)SECTORADDL3; /* 用戶程序標(biāo)志指針 */
INT32U *pSECTORADDH1 = (INT32U *)SECTORADDH1; /* 用戶程序標(biāo)志指針 */
INT32U *pSECTORADDH2 = (INT32U *)SECTORADDH2; /* 用戶程序標(biāo)志指針 */
INT32U *pSECTORADDH3 = (INT32U *)SECTORADDH3; /* 用戶程序標(biāo)志指針 */
/* IAP出口參數(shù)緩沖區(qū) */
/*********************************************************************************************************
** Function name: sectorPrepare
** Descriptions: IAP操作扇區(qū)選擇,命令代碼50
** input parameters: sec1: 起始扇區(qū)
** sec2: 終止扇區(qū)
** output parameters: paramout[0]: IAP操作狀態(tài)碼,IAP返回值
** Returned value: paramout[0]: IAP操作狀態(tài)碼,IAP返回值
*********************************************************************************************************/
INT32U sectorPrepare (INT8U sec1, INT8U sec2)
{
paramin[0] = IAP_Prepare; /* 設(shè)置命令字 */
paramin[1] = sec1; /* 設(shè)置參數(shù) */
paramin[2] = sec2;
(*IAP_Entry)(paramin, paramout); /* 調(diào)用IAP服務(wù)程序 */
return (paramout[0]); /* 返回狀態(tài)碼 */
}
/*********************************************************************************************************
** Function name: ramCopy
** Descriptions: 復(fù)制RAM的數(shù)據(jù)到FLASH,命令代碼51
** input parameters: dst: 目標(biāo)地址,即FLASH起始地址。以512字節(jié)為分界
** src: 源地址,即RAM地址。地址必須字對(duì)齊
** no: 復(fù)制字節(jié)個(gè)數(shù),為512/1024/4096/8192
** output parameters: paramout[0]: IAP操作狀態(tài)碼,IAP返回值
** Returned value: paramout[0]: IAP操作狀態(tài)碼,IAP返回值
*********************************************************************************************************/
INT32U ramToFlash (INT32U dst, INT32U src, INT32U no)
{
paramin[0] = IAP_RAMTOFLASH; /* 設(shè)置命令字 */
paramin[1] = dst; /* 設(shè)置參數(shù) */
paramin[2] = src;
paramin[3] = no;
paramin[4] = IAP_FCCLK;
(*IAP_Entry)(paramin, paramout); /* 調(diào)用IAP服務(wù)程序 */
return (paramout[0]); /* 返回狀態(tài)碼 */
}
/*********************************************************************************************************
** Function name: sectorErase
** Descriptions: 扇區(qū)擦除,命令代碼52
** input parameters: sec1 起始扇區(qū)
** sec2 終止扇區(qū)92
** output parameters: paramout[0]: IAP操作狀態(tài)碼,IAP返回值
** Returned value: paramout[0]: IAP操作狀態(tài)碼,IAP返回值
*********************************************************************************************************/
INT32U sectorErase (INT8U sec1, INT8U sec2)
{
paramin[0] = IAP_ERASESECTOR; /* 設(shè)置命令字 */
paramin[1] = sec1; /* 設(shè)置參數(shù) */
paramin[2] = sec2;
paramin[3] = IAP_FCCLK;
(*IAP_Entry)(paramin, paramout); /* 調(diào)用IAP服務(wù)程序 */
return (paramout[0]); /* 返回狀態(tài)碼 */
}
/*********************************************************************************************************
** Function name: blankChk
** Descriptions: 扇區(qū)查空,命令代碼53
** input parameters: sec1: 起始扇區(qū)
** sec2: 終止扇區(qū)92
** output parameters: paramout[0]: IAP操作狀態(tài)碼,IAP返回值
** Returned value: paramout[0]: IAP操作狀態(tài)碼,IAP返回值
*********************************************************************************************************/
INT32U blankChk (INT8U sec1, INT8U sec2)
{
paramin[0] = IAP_BLANKCHK; /* 設(shè)置命令字 */
paramin[1] = sec1; /* 設(shè)置參數(shù) */
paramin[2] = sec2;
(*IAP_Entry)(paramin, paramout); /* 調(diào)用IAP服務(wù)程序 */
return (paramout[0]); /* 返回狀態(tài)碼 */
}
/*********************************************************************************************************
** Function name: parIdRead
** Descriptions: 扇區(qū)查空,命令代碼54
** input parameters: 無
** output parameters: paramout[0]: IAP操作狀態(tài)碼,IAP返回值
** Returned value: paramout[0]: IAP操作狀態(tài)碼,IAP返回值
*********************************************************************************************************/
INT32U parIdRead (void)
{
paramin[0] = IAP_READPARTID; /* 設(shè)置命令字 */
(*IAP_Entry)(paramin, paramout); /* 調(diào)用IAP服務(wù)程序 */
return (paramout[0]); /* 返回狀態(tài)碼 */
}
/*********************************************************************************************************
** Function name: codeIdBoot
** Descriptions: 扇區(qū)查空,命令代碼55
** input parameters: 無
** output parameters: paramout[0]: IAP操作狀態(tài)碼,IAP返回值
** Returned value: paramout[0]: IAP操作狀態(tài)碼,IAP返回值
*********************************************************************************************************/
INT32U codeIdBoot (void)
{
paramin[0] = IAP_BOOTCODEID; /* 設(shè)置命令字 */
(*IAP_Entry)(paramin, paramout); /* 調(diào)用IAP服務(wù)程序 */
return (paramout[0]); /* 返回狀態(tài)碼 */
}
/*********************************************************************************************************
** Function name: dataCompare
** Descriptions: 校驗(yàn)數(shù)據(jù),命令代碼56
** input parameters: dst: 目標(biāo)地址,即RAM/FLASH起始地址。地址必須字對(duì)齊
** src: 源地址,即FLASH/RAM地址。地址必須字對(duì)齊
** no: 復(fù)制字節(jié)個(gè)數(shù),必須能被4整除
** output parameters: paramout[0]: IAP操作狀態(tài)碼,IAP返回值
** Returned value: paramout[0]: IAP操作狀態(tài)碼,IAP返回值
*********************************************************************************************************/
INT32U dataCompare (INT32U dst, INT32U src, INT32U no)
{
paramin[0] = IAP_COMPARE; /* 設(shè)置命令字 */
paramin[1] = dst; /* 設(shè)置參數(shù) */
paramin[2] = src;
paramin[3] = no;
(*IAP_Entry)(paramin, paramout); /* 調(diào)用IAP服務(wù)程序 */
return (paramout[0]); /* 返回狀態(tài)碼 */
}
/*********************************************************************************************************
** 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) /* 當(dāng)前程序運(yùn)行在LOW區(qū),需要 */
{ /* 對(duì)HIGH區(qū)進(jìn)行升級(jí) */
OS_ENTER_CRITICAL();
sectorPrepare(SECTORSNH1, SECTORSNH3); /* 選擇HIGH扇區(qū) */
sectorErase(SECTORSNH1, SECTORSNH3); /* 擦除HIGH扇區(qū) */
OS_EXIT_CRITICAL();
} /* 當(dāng)前程序運(yùn)行在HIGH區(qū)或者固 */
else{ /* 件區(qū),需要對(duì)LOW區(qū)進(jìn)行升級(jí) */
OS_ENTER_CRITICAL();
sectorPrepare(SECTORSNL1, SECTORSNL3); /* 選擇LOW扇區(qū) */
sectorErase(SECTORSNL1, SECTORSNL3); /* 擦除LOW扇區(qū) */
OS_EXIT_CRITICAL();
}
}
/*********************************************************************************************************
** Function name: userFlagUpdate
** Descriptions: 更新用戶程序標(biāo)志區(qū)
** 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; /* 更新用戶程序標(biāo)志空間 */
memset(GucIapTmp, 0xff, 256); /* 臨時(shí)緩沖區(qū)清空 */
pulDataPoint = (INT32U *)GucIapTmp;
if (*GpulFlagPoint==LOWADD){
*pulDataPoint=HIGHADD;
}
else{
*pulDataPoint=LOWADD;
}
OS_ENTER_CRITICAL();
sectorPrepare (SECTORFLAG, SECTORFLAG); /* 扇區(qū)準(zhǔn)備 */
sectorErase (SECTORFLAG, SECTORFLAG); /* 擦除扇區(qū) */
sectorPrepare (SECTORFLAG, SECTORFLAG); /* 選擇扇區(qū) */
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) //扇區(qū)大小
/*********************************************************************************************************
** Function name: userDataProgram
** Descriptions: 編程用戶代碼區(qū)
** 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)(); /* 函數(shù)指針 */
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; // 啟動(dòng)升級(jí)
if (*GpulFlagPoint==LOWADD)
return UPHI;
else
return UPLO;
}
//ANDYDEBUG 20150805
sPTL_104_I_SND.Rson=0x000A;
//ANDYDEBUG 20150805
if(SysUpdateFlag==0) // 未啟動(dòng)升級(jí)
return UPERR0;
if(fnum==fsn && flen==0 && fnum>0) { // 執(zhí)行升級(jí)程序
userFlagUpdate(); // 升級(jí)扇區(qū)標(biāo)識(shí)
zyReset(ZY_HARD_RESET);
return UPOK;
}
if(fnum==0 || fsn ==0 || fsn>fnum) // 序號(hào)排錯(cuò)
return UPERR1;
#ifndef TP1C
if (flen != 256 && flen != 512 && flen != 1024 ) // 幀長歸整
{ // 滿足編程字節(jié)數(shù)的要求,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校驗(yàn)
if(filedatcrc != (*(pdat+6+flen) + *(pdat+7+flen)*256))
return UPERRcrc;
if(fsn!=SysUpdateFsnBak+1) // 幀順序校驗(yàn)
return UPERR2;
SysUpdateFsnBak=fsn;
NPS= SECTORSIZE/flen; // 單個(gè)扇區(qū)幀容量
memcpy(GucIapTmp,pdat+6,flen); // 寫升級(jí)數(shù)據(jù)入緩存
#else
if(flen != 128 && flen != 256 && flen != 512 && flen != 1024 )
{ // 滿足編程字節(jié)數(shù)的要求,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校驗(yàn)
if(filedatcrc != (*(pdat+6+flen) + *(pdat+7+flen)*256))
return UPERRcrc;
if(fsn!=SysUpdateFsnBak+1) // 幀順序校驗(yàn)
return UPERR2;
SysUpdateFsnBak=fsn;
NPS= SECTORSIZE/flen; // 單個(gè)扇區(qū)幀容量
if(flen==128){
if(fsn%2){
if(fsn<fnum){
memcpy(GucIapTmp,pdat+6,flen); // 寫升級(jí)數(shù)據(jù)入緩存
return UPOK;
}
else {
memcpy(GucIapTmp,pdat+6,flen); // 寫升級(jí)數(shù)據(jù)入緩存
memset(GucIapTmp+128,0xff,flen); // 結(jié)束幀補(bǔ)齊256字節(jié)
NPS/=2;
fsn/=2;
fsn++;
flen*=2;
}
}
else {
memcpy(GucIapTmp+128,pdat+6,flen); // 寫升級(jí)數(shù)據(jù)入緩存
NPS/=2;
fsn/=2;
flen*=2;
}
}
else
memcpy(GucIapTmp,pdat+6,flen); // 寫升級(jí)數(shù)據(jù)入緩存
#endif
if (*GpulFlagPoint==LOWADD) /* 當(dāng)前程序運(yùn)行在LOW區(qū),需要 */
{ /* 對(duì)HIGH區(qū)進(jìn)行升級(jí) */
OS_ENTER_CRITICAL();
if(fsn>0 && fsn<=NPS){
sectorPrepare(SECTORSNH1, SECTORSNH1); /* 準(zhǔn)備HIGH扇區(qū) */
ramToFlash(SECTORADDH1 + (fsn-1)*flen,(INT32U)GucIapTmp, flen); /* 寫數(shù)據(jù)到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 /* 當(dāng)前程序運(yùn)行在HIGH區(qū),需要 */
{ /* 對(duì)LOW區(qū)進(jìn)行升級(jí) */
OS_ENTER_CRITICAL();
if(fsn>0 && fsn<=NPS){
sectorPrepare(SECTORSNL1, SECTORSNL1); /* 準(zhǔn)備LOW扇區(qū) */
ramToFlash(SECTORADDL1 + (fsn-1)*flen,(INT32U)GucIapTmp, flen); /* 寫數(shù)據(jù)到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: 系統(tǒng)復(fù)位
** input parameters: uiMode: ZY_POWER_RESET: 上電復(fù)位
** ZY_HARD_RESET: 硬件復(fù)位
** ZY_SOFT_RESET: 軟件復(fù)位
** 其它: 與系統(tǒng)相關(guān)
** 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: /* 此系統(tǒng)上電復(fù)位等同硬件復(fù)位 */
#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: /* 參數(shù)不正確不復(fù)位 */
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
*********************************************************************************************************/
復(fù)制代碼
所有資料51hei提供下載:
LPC1778 IAP燒寫源碼.docx
(23.1 KB, 下載次數(shù): 20)
2018-4-26 09:37 上傳
點(diǎn)擊文件名下載附件
IAP源碼,已經(jīng)過測試
下載積分: 黑幣 -5
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1