回首頁   上一頁   通用輸出入控制    異常向量與外部中斷控制   計時器控制

 串列埠UART控制    串列埠SPI控制    串列埠I2C控制    RTC控制控制    FLASH記憶體控制    uCOS-II系統程式

/**********************IAP功能測試*****************************************
*檔名︰IAP.C
*功能︰將SRAM的資料燒錄到FLASH,再讀取FLASH內容到LED顯示。
*模擬:開啟Memory視窗,觀察SRAM(0x40003800)及FLASH(0x4000)的內容
* 開啟Watch#1視窗,單步執行觀察參數paramin及paramout的內容
* 開啟GPIO視窗,顯示FLASH的內容
****************************************************************************/
#include "LPC2106.h"
#define IAP_ENTER_ADR 0x7FFFFFF1 // IAP服務程式進入位址(在Bootload內)

/* 定義IAP命令 */
#define IAP_SELSECTOR 50 // 選擇區塊
#define IAP_RAMTOFLASH 51 // 複製RAM的內容到FLASH ROM
#define IAP_ERASESECTOR 52 // 清除區塊
#define IAP_BLANKCHK 53 // 空白檢查
#define IAP_READPARTID 54 // 讀取ID碼
#define IAP_BOOTCODEID 55 // 讀取boot程式碼版本編號
#define IAP_COMPARE 56 // 比較區塊內容

/* 定義IAP返回狀態 */
#define CMD_SUCCESS 0 // 命令已執行成功
#define INVALID_COMMAND 1 // 無效命令
#define SRC_ADDR_ERROR 2 // 來源位址不是以word為單位
#define DST_ADDR_ERROR 3 // 目的位址不是以word為單位
#define SRC_ADDR_NOT_MAPPED 4 // 來源位址不是映射到記憶體中
#define DST_ADDR_NOT_MAPPED 5 // 目的位址不是映射到記憶體中
#define COUNT_ERROR 6 // Byte數錯誤,不是4倍數
#define INVALID_SECTOR 7 // 區塊編號無效或開始區塊>結束區塊
#define SECTOR_NOT_BLANK 8 // 區塊不是空白
#define SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION 9 //準備寫入區塊命令未執行
#define COMPARE_ERROR 10 // 比較錯誤,來源與目的不相符
#define BUSY 11 // Flash燒錄電路忙碌中
#define PARAM_ERROR 12 // 參數錯誤
#define ADDR_ERROR 13 // 位址錯誤
#define ADDR_NOT_MAPPED 14 // 位址不在映射區內
#define CMD_LOCKED 15 // 命令鎖住
#define INVALID_CODE 16 // 無效數碼
#define INVALID_BAUD_RATE 17 // 無效傳輸速率
#define INVALID_STOP_BIT 18 // 無效停止位元

#define IAP_CLK 11059 // 設定IAP工作頻率,以KHz為單位
void (*IAP_Entry)(uint32 param_tab[], uint32 result_tab[]); // 定義函數指標

uint32 paramin[5]; // IAP輸入參數緩衝區
uint32 paramout[4]; // IAP輸出參數緩衝區

/****************************************************************************
* 名稱︰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,命令程式碼5
* 輸入參數︰dst 目的FLASH開始位址
* src 來源SRAM開始位址
* size 複製byte數
* 輸出門參數︰IAP返回值(paramout緩衝區)
****************************************************************************/
void RamToFlash(uint32 dst, uint32 src, uint32 size)
{ paramin[0] = IAP_RAMTOFLASH; // 複製RAM的資料到FLASH命令
paramin[1] = dst; // 設定FLASF目的開始位址
paramin[2] = src; // 設定SRAM來源開始位址
paramin[3] = size; // 複製byte數
paramin[4] = IAP_CLK; // 設定IAP工作頻率
(*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_CLK; // 設定IAP工作頻率
(*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()
* 功能︰讀取ID碼,命令程式碼54
* 輸出參數︰IAP返回值(paramout緩衝區)
********************************************************************/
void ReadParID(void)
{ paramin[0] = IAP_READPARTID; // 讀取ID碼命令
(*IAP_Entry)(paramin, paramout); // 執行IAP服務程式
}
/*********************************************************************
* 名稱︰BootCodeID()
* 功能︰讀取bootload版本編號,命令程式碼55
* 輸出參數︰IAP返回值(paramout緩衝區)
**********************************************************************/
void BootCodeID(void)
{ paramin[0] = IAP_BOOTCODEID; // 讀取bootload版本編號命令
(*IAP_Entry)(paramin, paramout); // 執行IAP服務程式
}
/**********************************************************************
* 名稱︰Compare()
* 功能︰比較資料,命令程式碼56
* 輸入參數︰dst 目的FLASH開始位址
* src 來源SRAM開始位址
* size 比較byte數
* 輸出參數︰IAP返回值(paramout緩衝區)
****************************************************************************/
void Compare(uint32 dst, uint32 src, uint32 size)
{ paramin[0] = IAP_COMPARE; // 比較資料命令
paramin[1] = dst; // 目的FLASH開始位址
paramin[2] = src; // 來源SRAM開始位址
paramin[3] = size; // 比較byte數
(*IAP_Entry)(paramin, paramout); // 執行IAP服務程式
}
/****************************************************************************
* 名稱︰RAM_FILL()
* 功能︰寫入資料到SRAM
* 輸入參數︰src 來源SRAM開始位址
* size 寫入byte數
****************************************************************************/
void RAM_FILL(uint32 src,uint32 size)
{
uint16 i;
uint8 *src_prt=(uint8 *)src; //宣告指標變數的內容為來源位址
for(i=0; i<size ; i++) *src_prt++=i; //寫入0~size資料到SRAM
}
/***************************************************************
* 名稱︰ReadFlash(uint32 src)
* 功能︰讀取FALSH內的資料
* 輸入參數︰dst FALSH位址
* 輸出參數︰i FALSH內的資料
*******************************************************************/
uint8 ReadFlash(uint32 dst)
{
uint8 i;
uint8 *dst_prt=(uint8 *)dst; //宣告指標變數的內容為來源位址
i= *dst_prt; // 讀取FALSH的資料
return(i); // 返回LLASH資料
}
/****************************************************************************
* 名稱︰main()
* 功能︰IAP函數執行,測試。
****************************************************************************/
int main(void)
{
uint32 dst=0x4000; // FLASH目的開始位址 ,必須為區塊開始位址
uint32 src=0x40003800; // SRAM來源開始位址,必須為4的倍數
uint16 size=512; // 複製記憶體byte數,限512/1024/4096/8192
RAM_FILL(src,size); // 寫入資料到SRAM內

IAP_Entry =(void(*)())IAP_ENTER_ADR; // 初始化函數指標IAP_Entry

ReadParID(); // 讀取ID碼-->回應完成(狀態碼=0),ID碼=0xFFF0FF12
BootCodeID(); // 讀取bootload版本-->回應完成(狀態碼=0),版本碼=0x103
SelSector(2,2); // 選擇區塊2(0x4000~0x5FFF)-->回應完成(狀態碼=0)
EraseSector(2,2); // 抹除區塊2-->回應完成(狀態碼=0)
BlankCHK(2,2) ; // 空白檢查區塊2--回應是空白(狀態碼=0)
SelSector(2,2); // 選擇區塊2-->回應完成(狀態碼=0)
RamToFlash(dst, src, size); // 將RAM(0x40000000)資料512-byte複製到區塊2-->回應完成(狀態碼=0)
BlankCHK(2,2) ; // 空白檢查區塊22-->回應不是空白(狀態碼=8),非空白位址及資料
Compare(dst, src, size); // 比較資料-->回應相符(狀態碼=0),不相符(狀態碼=A),

IODIR=LED1+LED2+LED3+LED4; // 設定LED輸出腳
while(1)
{
for(dst=0x4000;dst<0x4016;dst++) // 設定FLASH位址範圍
{
IOCLR=~ReadFlash(dst)<<10;// 讀取FLASH資料低電位由LED輸出
IOSET=ReadFlash(dst)<<10; // 讀取FLASH資料高電位由LED輸出
Delay_ms(500);
}
}
}