前言
最近在做的一個(gè)項(xiàng)目中,需要經(jīng)常把一些參數(shù)下載到I2C EEPROM中,然后MCU上電去讀取。如果在產(chǎn)品量產(chǎn)過程中,可以使用燒錄治具往EEPROM寫入一次即可。但是在調(diào)試開發(fā)階段,需要經(jīng)常修改這些數(shù)據(jù),調(diào)試起來非常不方便。
我調(diào)試的環(huán)境是MDK-Keil,于是網(wǎng)上了解了下如何制作Keil的下載算法,下面介紹下基于APM32F407如何制作I2C EEPROM(AT24C02型號(hào))的Keil下載算法,這樣在我們下載代碼時(shí)可以一鍵把數(shù)據(jù)燒錄到EEPROM中。
對(duì)于 Keil 的下載算法文件相關(guān)的詳細(xì)介紹可以到官方在線文檔進(jìn)行了解,這些文檔詳細(xì)介紹了下載算法的實(shí)現(xiàn)細(xì)節(jié)。文檔鏈接如下:
https://open-cmsis-pack.github.io/Open-CMSIS-Pack-Spec/main/html/flashAlgorithm.html
1. Keil如何調(diào)用下載算法
Keil的下載算法,我的理解就是可以通過Keil去調(diào)用該下載算法,然后可以去編程各種存儲(chǔ)設(shè)備,比如MCU內(nèi)部的Flash,通過MCU外設(shè)連接外擴(kuò)的SPI Flash或者I2C EEPROM等器件。
要想通過Keil IDE的下載按鈕一鍵編程這些存儲(chǔ)設(shè)備,那么需要有對(duì)應(yīng)器件的下載算法才能去編程。對(duì)于Keil來說通過調(diào)試界面指定相應(yīng)的下載算法 xxx.FLM 文件,然后就可以被調(diào)用了,如下圖:
??Keil 在調(diào)試下載階段,會(huì)把算法文件加載到芯片的內(nèi)部 RAM 里面,加載的芯片內(nèi)部的RAM地址和大小可以在上面的配置截圖進(jìn)行設(shè)置。然后就可以在 RAM 中執(zhí)行這個(gè)下載算法文件的擦除、編程等函數(shù),從而實(shí)現(xiàn)對(duì)存儲(chǔ)設(shè)備下載程序或者在調(diào)試階段讀取數(shù)據(jù)等操作。
大致流程如下圖:??
主要是分為兩步:
通過SWD/JTAG調(diào)試接口,把下載算法加載到RAM。
執(zhí)行下載算法的擦除、編程等函數(shù),從而對(duì)內(nèi)部Flash進(jìn)行編程或者通過MCU的片上外設(shè)對(duì)外擴(kuò)的SPI FLASH/I2C EEPROM執(zhí)行編程操作。
另外,前面說到會(huì)把下載算法文件加載到 RAM 運(yùn)行,而且我們可以設(shè)置加載到任何的 RAM 地址運(yùn)行,那么對(duì)下載算法生成的代碼必須是與位置無關(guān)的代碼,這樣才能加載到任意 RAM 地址運(yùn)行。
2.Keil下載算法函數(shù)和執(zhí)行流程
2.1 下載算法需要實(shí)現(xiàn)哪些函數(shù)
根據(jù)官方文檔介紹,要制作一個(gè)新的下載算法需要實(shí)現(xiàn)函數(shù)有:
一共有7個(gè)函數(shù),而且這些函數(shù)的原型已經(jīng)規(guī)定好了的,只需要我們根據(jù)不同的存儲(chǔ)設(shè)備實(shí)現(xiàn)具體的功能即可。
其中有 mandatory 修飾的函數(shù),是制作一個(gè)新的下載算法必須要實(shí)現(xiàn)的函數(shù)是,而 optional 修飾的函數(shù)則可根據(jù)需要實(shí)現(xiàn)還是不實(shí)現(xiàn)。
2.2 擦除流程
加載算法到芯片 RAM。
執(zhí)行初始化函數(shù) Init。
執(zhí)行擦除操作。其中擦除操作會(huì)根據(jù)Keil的配置選項(xiàng),選擇是擦除整個(gè)芯片還是扇區(qū)擦除。
執(zhí)行 Uinit 函數(shù)。
擦除完成。
2.3 編程流程
編程流程,就是把編譯出來的可執(zhí)行程序下載到Flash或者其他存儲(chǔ)器。
對(duì)于所有 AXF 文件內(nèi)容,執(zhí)行 Init 初始化函數(shù)
判斷 Flash 算法是否在FLM文件中。不在則編程結(jié)束,返回失敗。如果編程算法存在,則執(zhí)行下面操作:
(1)加載算法到RAM
(2)執(zhí)行Init函數(shù)
(3)加載應(yīng)用程序(待編程的數(shù)據(jù))到RAM Buffer中
(4)執(zhí)行Program Page編程函數(shù)
(5)執(zhí)行Uninit函數(shù)
編程完成。
2.4 校驗(yàn)流程
校驗(yàn)就是把 AXF 文件中需要下載到Flash的數(shù)據(jù),與實(shí)際下載到Flash的數(shù)據(jù)讀出來進(jìn)行比較。
判斷 Flash 算法是否在FLM文件中,不在則操作失敗。如果編程算法存在,則執(zhí)行下面操作:
(1)加載算法到RAM
(2)執(zhí)行Init函數(shù)
(3)判斷FLM文件是否存在校驗(yàn)算法。
存在則加載應(yīng)用程序到RAM,然后執(zhí)行FLM文件中的校驗(yàn)算法
不存在則計(jì)算和比較CRC值。把下載到Flash的數(shù)據(jù)讀出來計(jì)算的CRC值,與 加載 axf 文件的數(shù)據(jù)到RAM中計(jì)算的CRC值進(jìn)行比較。
執(zhí)行Uninit函數(shù)
執(zhí)行完 Uninit 函數(shù)后面的步驟,不是很理解,這后面的步驟是不是和調(diào)試有關(guān)的,在下載代碼時(shí)并沒有關(guān)系?
3. 制作Keil環(huán)境的I2C EEPROM下載算法
下面我基于APM32F407,制作AT24C02 EEPROM存儲(chǔ)芯片的下載算法。
對(duì)于下載算法的制作流程,官網(wǎng)已經(jīng)給出了詳細(xì)的步驟,下面的步驟是從官網(wǎng)翻譯過來的。一個(gè)新的下載算法制作步驟:
將ARM:CMSIS Pack文件夾(通常為 C:KeilARMPackARMCMSIS version Device_Template_Flash)中的內(nèi)容復(fù)制到新文件夾。
重命名項(xiàng)目文件NewDevice.uvprojx以表示新的閃存 ROM 設(shè)備名稱,例如MyDevice.uvprojx。
使用 uVision 打開項(xiàng)目。從工具欄中,使用下拉菜單“選擇目標(biāo)”來定義處理器架構(gòu)。Cortex-M適用于所有 Cortex-M0/M0+、M3 和 M4 設(shè)備。該配置假定采用小端微控制器。如果是大端微控制器,請(qǐng)使用Project - Options for Target - Device選擇正確的處理器內(nèi)核。
打開對(duì)話框“項(xiàng)目-目標(biāo)選項(xiàng)-輸出” ,然后更改“可執(zhí)行文件名稱”字段的內(nèi)容以表示設(shè)備,例如MyDevice。
調(diào)整文件FlashPrg中的編程算法。
調(diào)整文件FlashDev中的設(shè)備參數(shù)。
使用Project - Build Target生成新的Flash 編程算法。輸出文件(例如MyDevice.FLM)必須添加到DFP中。
上面的步驟就是官網(wǎng)給出的,下面我們就根據(jù)官網(wǎng)給出的步驟制作一個(gè)新的下載算法。
3.1 準(zhǔn)備下載算法模板
下載算法的模板,我們?cè)诎惭bKeil的時(shí)候就有了的。官網(wǎng)說在 keil 的安裝目錄下能找到,但是我安裝的是 5.36 版本,Keil安裝目錄沒有找到,而是在C:Users你的用戶名目錄AppDataLocalArmPacksARMCMSIS5.8.0Device_Template_Flash 這個(gè)目錄找的的下載算法模板。
我們把該目錄復(fù)制一份備用,然后記得把該文件夾的只讀屬性去掉。
3.2 Keil環(huán)境設(shè)置
1、把復(fù)制的模板工程的工程名,可以根據(jù)我們基于什么芯片制作下載算法修改一下工程名稱,這樣更具有辨識(shí)度。
2、修改選擇的目標(biāo)芯片。
我是基于APM32F407制作下載算法文件,所以選擇M4內(nèi)核就行。
3、修改編譯生成的下載算法文件的名稱。
4、添加APM32F407的外設(shè)驅(qū)動(dòng)庫以及I2C EEPROM的讀寫驅(qū)動(dòng)文件
由于我們是要實(shí)現(xiàn) I2C EEPROM 的下載算法,在編寫這些下載算法函數(shù)之前,我們必須要先確保I2C EEPROM 的驅(qū)動(dòng)可以正常讀寫。I2C EEPROM 的驅(qū)動(dòng)可以從我們實(shí)現(xiàn)的例程驗(yàn)證可行之后,然后挪過來使用即可。
3.3 修改FlashPrg.c文件中的編程算法函數(shù)
這一步是最重要的,我們實(shí)現(xiàn)Keil編程算法主要就是要實(shí)現(xiàn) FlashPrg.c 文件中的各個(gè)下載算法函數(shù)。根據(jù)前面的介紹,一個(gè)新的下載算法必須要實(shí)現(xiàn)的函數(shù)有:Init/EraseSector/ProgramPage/Uninit這4個(gè)函數(shù),其他函數(shù)可以根據(jù)需要是否實(shí)現(xiàn)。下面我們來一一實(shí)現(xiàn)這些函數(shù)。
1、Init函數(shù)的實(shí)現(xiàn)
/*
* Initialize Flash Programming Functions
* Parameter: adr: Device Base Address
* clk: Clock Frequency (Hz)
* fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify)
* Return Value: 0 - OK, 1 - Failed
*/
int Init (unsigned long adr, unsigned long clk, unsigned long fnc)
{
/* 系統(tǒng)初始化 */
//SystemInit(); // 如果使用了庫文件的該函數(shù)會(huì)導(dǎo)致下載是0x08000000地址校驗(yàn)失敗,但是實(shí)際測(cè)試又是下載進(jìn)去了。不知道什么原因
I2C_Init();
return 0;
}
在該函數(shù)中,我們可以初始化編程存儲(chǔ)器的一些操作,比如配置時(shí)鐘,GPIO的初始化等等。
2、扇區(qū)擦除和整片芯片擦除函數(shù)
/*
* Erase complete Flash Memory
* Return Value: 0 - OK, 1 - Failed
*/
int EraseChip (void)
{
volatile int i = 0;
unsigned char tmepbuf[EE_PAGE_SIZE];
unsigned char adr = 0;
for(i = 0; i < EE_PAGE_SIZE; i++)
{
tmepbuf[i] = 0xFF;
}
for (i = 0; i < EE_SIZE / EE_PAGE_SIZE; i++)
{
ee_WriteBytes(tmepbuf, adr, EE_PAGE_SIZE);
adr += EE_PAGE_SIZE;
}
return 0;
}
/*
* Erase Sector in Flash Memory
* Parameter: adr: Sector Address
* Return Value: 0 - OK, 1 - Failed
*/
int EraseSector (unsigned long adr)
{
volatile int i = 0;
unsigned char tmepbuf[EE_PAGE_SIZE];
adr -= I2C_EEPROM_ADDR;
for(i = 0; i < EE_PAGE_SIZE; i++)
{
tmepbuf[i] = 0xFF;
}
ee_WriteBytes(tmepbuf, adr, EE_PAGE_SIZE);
return 0;
}
實(shí)際上對(duì)于EEPROM芯片,不需要擦除就能寫入數(shù)據(jù)的。不過為了示例,我們也實(shí)現(xiàn)這兩個(gè)擦除函數(shù)好了。對(duì)于EERPOM來說,擦除就是往它寫入0xFF數(shù)據(jù)即可。
3、ProgramPage 頁編程函數(shù)實(shí)現(xiàn)
#define I2C_EEPROM_ADDR 0x01000000
/*
* Program Page in Flash Memory
* Parameter: adr: Page Start Address
* sz: Page Size
* buf: Page Data
* Return Value: 0 - OK, 1 - Failed
*/
int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf)
{
volatile int i = 0;
adr -= I2C_EEPROM_ADDR;
for(i = 0; i < sz/EE_PAGE_SIZE; i++)
{
ee_WriteBytes(buf+EE_PAGE_SIZE*i, adr+EE_PAGE_SIZE*i, EE_PAGE_SIZE);
}
if(sz%EE_PAGE_SIZE)
{
ee_WriteBytes(buf+EE_PAGE_SIZE*i, adr+EE_PAGE_SIZE*i, sz%EE_PAGE_SIZE);
}
return (0);
}
直接調(diào)用EEPROM的驅(qū)動(dòng)寫函數(shù)即可。另外 I2C_EEPROM_ADDR 這個(gè)宏定義,是為了在我們的應(yīng)用代碼中,定義數(shù)據(jù)時(shí)選擇哪一塊區(qū)域存儲(chǔ)EEPROM的數(shù)據(jù),地址是我們可以隨意定義的。但是不能與MCU的外設(shè)地址,以及Flash、RAM等地址重合就行。
4、Uninit函數(shù)實(shí)現(xiàn)
該函數(shù)根據(jù)前面的Keil執(zhí)行各編程流程,一般是退出編程時(shí)會(huì)被調(diào)用的,我們可以在該函數(shù)進(jìn)行恢復(fù)的操作。該函數(shù)是必須實(shí)現(xiàn)的,如果不需要做任何動(dòng)作,那么我們保持該函數(shù)為空函數(shù)就行。
/*
* De-Initialize Flash Programming Functions
* Parameter: fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify)
* Return Value: 0 - OK, 1 - Failed
*/
int UnInit (unsigned long fnc) {
/* Add your Code */
return (0); // Finished without Errors
}
3.4 修改FlashDev.c文件的設(shè)備參數(shù)
在FlashDev.c文件中有一個(gè)名為FlashDevice的結(jié)構(gòu)體常量,這個(gè)結(jié)構(gòu)體的信息是給 Keil 提供編程設(shè)備的信息的,比如編程的起始地址,總大小,一個(gè)扇區(qū)的大小,設(shè)備類型等等信息。我們根據(jù)自己的需要編程的設(shè)備類型修改即可。
struct FlashDevice const FlashDevice = {
FLASH_DRV_VERS, // Driver Version, do not modify!
"APM32F407_I2C_EEPROM_AT24C02", // Device Name
EXTSPI, // Device Type
0x01000000, // Device Start Address. EEPROM的編程地址。
0x00000100, // Device Size in Bytes
8, // Programming Page Size
0, // Reserved, must be 0
0xFF, // Initial Content of Erased Memory
6000, // Program Page Timeout 6000 mSec
6000, // Erase Sector Timeout 6000 mSec
// Specify Size and Address of Sectors
0x000008, 0x000000, // Sector Size 8B (32 Sectors)
// 0x010000, 0x010000, // Sector Size 64kB (2 Sectors)
// 0x002000, 0x030000, // Sector Size 8kB (8 Sectors)
SECTOR_END
};
3.5 生成算法文件
我們實(shí)現(xiàn)了 FlashPrg.c 文件的編程算法函數(shù)之后,直接編譯就可以生成 xxx.FLM 算法文件了。
在編譯之前,我們需要檢查生成的代碼是位置無關(guān)碼。在Keil設(shè)置如下:
C/C++和Asm選項(xiàng)卡都要檢查是否已經(jīng)勾選了上面的配置。
點(diǎn)擊編譯即可生成Keil下載算法文件。
4. 新制作的下載算法文件使用和測(cè)試
1、把生成的下載算法文件放置到Keil安裝的目錄 C:Keil_v5ARMFlash 下待使用
2、Keil環(huán)境配置下載算法
3、APM32F407_I2C_EEPROM算法測(cè)試驗(yàn)證。
我們使用下載算法下載數(shù)據(jù)到EERPOM,然后再通過應(yīng)用程序讀出來進(jìn)行對(duì)比寫進(jìn)去的數(shù)據(jù)是否一致,就可以知道EEPROM下載算法是否起作用。
我們找一個(gè) APM32F407 EEPROM 的例程進(jìn)行測(cè)試。
(1)首先在例程里面定義下面待燒錄到EEPROM的數(shù)據(jù):
const uint8_t EEPROM_FLM_Test1[16] __attribute__((at(0x01000000))) = {
0xCB,0xFF,0x01,0x02,0x03,0xAA,0x06,0x07,
0x08,0x09,0x10,0xA1,0xA2,0xA3,0xA4,0xBB
};
const uint8_t EEPROM_FLM_Test2[16] __attribute__((at(0x010000A0))) = {
0x12,0x34,0x01,0x02,0x03,0xAA,0x06,0x07,
0x08,0x09,0x10,0xA1,0xA2,0xA3,0xA4,0xBB
};
其中我們規(guī)定這些數(shù)組必須鏈接到 0x01000000 起始的地址,這是因?yàn)槲覀冎谱鞯?EEPROM 的下載算法編程地址就是在該范圍,這個(gè)地址會(huì)在下載算法內(nèi)部轉(zhuǎn)換為EEPROM 編程的 0 地址,比如說 0x01000000 起始地址,對(duì)應(yīng)的就算EEPROM的0地址。
(2)然后編譯下載代碼到Flash和EEPROM即可。
下載代碼時(shí),檢測(cè)的0x01000000地址需要下載數(shù)據(jù),Keil就會(huì)自動(dòng)調(diào)用EEPROM的下載算法把數(shù)據(jù)編程到EEPROM了。
如下在下載程序沒有報(bào)錯(cuò),下載完成。
然后運(yùn)行代碼,把EEPROM的數(shù)據(jù)讀出來,對(duì)比是否一致。
《APM32芯得》系列內(nèi)容為用戶使用APM32系列產(chǎn)品的經(jīng)驗(yàn)總結(jié),來自21ic論壇極海半導(dǎo)體專區(qū)。在此特別鳴謝!
-
算法
+關(guān)注
關(guān)注
23文章
4699瀏覽量
94747 -
EEPROM
+關(guān)注
關(guān)注
9文章
1082瀏覽量
83282 -
I2C
+關(guān)注
關(guān)注
28文章
1534瀏覽量
127029 -
keil
+關(guān)注
關(guān)注
69文章
1223瀏覽量
169011 -
極海半導(dǎo)體
+關(guān)注
關(guān)注
0文章
152瀏覽量
4825
原文標(biāo)題:APM32芯得 EP.51 | 基于APM32F407制作I2C EEPROM的MDK-Keil下載算法
文章出處:【微信號(hào):geehysemi,微信公眾號(hào):Geehy極海半導(dǎo)體】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
國產(chǎn)優(yōu)秀替代_APM32F407替代STM32F407記錄

APM32F407工具鏈?zhǔn)褂媒坛?/a>

《電子發(fā)燒友電子設(shè)計(jì)周報(bào)》聚焦硬科技領(lǐng)域核心價(jià)值 第7期:2025.04.7--2025.04.11
I2C—讀寫EEPROM
AT24C02與單片機(jī)連接的電路圖免費(fèi)下載

EEPROM存儲(chǔ)芯片AT24C02芯片手冊(cè)

【STM32Cube_13】使用硬件I2C讀寫EEPROM(AT24C02)

STM32單片機(jī)基礎(chǔ)13——使用硬件I2C讀寫EEPROM(AT24C02)

使用APM32F407替代STM32F407制作的demo
Linux驅(qū)動(dòng)開發(fā)-編寫(EEPROM)AT24C02驅(qū)動(dòng)

APM32F103XE_I2C_加入六軸傳感器后,I2C通訊EEPROM會(huì)掛

評(píng)論