嵌入式開(kāi)發(fā)的最后階段是要將成果產(chǎn)品化,要交付工廠量產(chǎn)。對(duì)于NXP i.MXRT系列的芯片來(lái)說(shuō),除了要交付給工廠項(xiàng)目固件外,還需要工廠寫(xiě)OTP區(qū)域來(lái)配置芯片啟動(dòng)方式或者開(kāi)啟芯片的安全功能。離線(xiàn)編程器燒寫(xiě)固件和OTP的方法有多種,如ISP,SWD或者Jtag等。
今天就為大家介紹下,如何讓離線(xiàn)編程器利用SWD接口燒寫(xiě)OTP。
編寫(xiě)OTP燒寫(xiě)算法
直接操作寄存器來(lái)寫(xiě)OTP的過(guò)程很繁瑣。很多編程器借助Flash燒寫(xiě)算法來(lái)燒寫(xiě)Flash,我們也可以借助燒寫(xiě)Flash的方法來(lái)燒寫(xiě)OTP。 本加油站曾經(jīng)有一篇《編寫(xiě)Keil的自定義Flash燒寫(xiě)算法FLM》,在這篇文章中,作者介紹了如何利用Keil來(lái)編寫(xiě)Flash燒寫(xiě)算法。 編寫(xiě)OTP燒寫(xiě)算法的方法和編寫(xiě)Flash燒寫(xiě)算法的方法一樣,只需要復(fù)用接口函數(shù)Init和UnInit,新增接口OTPWrite。和Flash相關(guān)的操作函數(shù)可以直接刪掉。OTP的燒寫(xiě)算法接口聲明如下:
int Init (unsigned long adr, unsigned long clk, unsigned long fnc); int UnInit (unsigned long fnc); int OTPWrite (unsigned long idx, unsigned long value);每個(gè)燒寫(xiě)算法接口函數(shù)都是對(duì)應(yīng)OTP驅(qū)動(dòng)函數(shù)的封裝。下面是這3個(gè)接口函數(shù)的參考實(shí)現(xiàn):
int Init (unsigned long adr, unsigned long clk, unsigned long fnc) {
BOARD_BootClockRUN();
#if (defined(FSL_FEATURE_OCOTP_HAS_TIMING_CTRL) && FSL_FEATURE_OCOTP_HAS_TIMING_CTRL)
OCOTP_Init(OCOTP, CLOCK_GetFreq(kCLOCK_IpgClk));
#else
OCOTP_Init(OCOTP, 0U);
#endif
return (0);
}
int OTPWrite (unsigned long idx, unsigned long value) {
status_t status = kStatus_Success;
status = OCOTP_WriteFuseShadowRegister(OCOTP, idx, value);
return (kStatus_Success == status) ? (0) : (1);
}
int UnInit (unsigned long fnc) {
OCOTP_Deinit(OCOTP);
return (0);
}
以O(shè)COTP_開(kāi)頭的函數(shù)是OTP driver接口。函數(shù)BOARD_BootClockRUN的具體實(shí)現(xiàn)請(qǐng)查看SDK內(nèi)OTP driver的示例。
提取算法代碼
Keil MDK生成的后綴為FLM的算法文件實(shí)質(zhì)上是一段與地址無(wú)關(guān)的代碼。對(duì)于下載器來(lái)說(shuō),一種簡(jiǎn)單的使用方法是把文件內(nèi)的相關(guān)函數(shù)指令提取出來(lái)。這里需要用到開(kāi)源項(xiàng)目pyocd里的python腳本FlashAlgo。該項(xiàng)目github地址為:
https://github.com/pyocd/FlashAlgo
FlashAlgo默認(rèn)會(huì)從符號(hào)表里查找EraseSector等函數(shù)名。所以我們需要做一點(diǎn)改動(dòng),把flash相關(guān)操作的函數(shù)名換成OTP相關(guān)操作的函數(shù)名。
文件flash_algo.py中集合REQUIRED_SYMBOLS改動(dòng)如下:
REQUIRED_SYMBOLS = set([
"Init",
"UnInit",
"OTPWrite", # EraseSector
])
文件generate_blobs.py中列表TEMPLATES改動(dòng)如下:
TEMPLATES = [
("c_blob.tmpl", "c_blob.c"),
]
c_blob.tmpl在文件夾templates中,將program_target_t改名為program_ocotp_t,并將其中和flash相關(guān)的Erase、Program等項(xiàng)刪掉,新增OTPWrite,新增項(xiàng)如下:
static const program_ocotp_t ocotp = {
[...]
{{'0x%08x' % (algo.symbols['OTPWrite'] + header_size + entry)}}, // OTPWrite
[...]
}
在執(zhí)行腳本之前,先安裝python依賴(lài)的第三方庫(kù),命令行如下:
pip install requirements.txt
執(zhí)行腳本的命令行如下:
python generate_blobs.py --blob_start 0x20000000otp_prog.FLM
這里的0x20000000是將要運(yùn)行算法的目標(biāo)RAM地址,讀者可以根據(jù)芯片RAM位置配置。otp_prog.FLM為上一小節(jié)Keil MDK編譯出來(lái)的FLM文件。c_blob.c是生成的包含燒寫(xiě)算法及相關(guān)信息的文件。
燒寫(xiě)OTP
要通過(guò)SWD燒寫(xiě)OTP,就需要實(shí)現(xiàn)一個(gè)SWD時(shí)序協(xié)議。ARM公司的開(kāi)源項(xiàng)目DAPLINK實(shí)現(xiàn)了支持arm cortex系列MCU的SWD時(shí)序協(xié)議。具體的實(shí)現(xiàn)在文件swd_host.c內(nèi)。
該項(xiàng)目地址是https://github.com/armmbed/daplink
這里我們使用swd_host.c中的接口來(lái)演示如何燒寫(xiě)OTP。和OTP相關(guān)的操作接口函數(shù)主要有兩個(gè):
uint8_t swd_write_memory(uint32_t address, uint8_t *data, uint32_t size); uint32_t swd_flash_syscall_exec(const program_syscall_t *sysCallParam, uint32_t entry, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, flash_algo_return_t return_type);
調(diào)用OTP算法需要的主要參數(shù)在文件c_blob.c中的結(jié)構(gòu)體program_ocotp_t。我們仿照DAPLINK中program_target_t給出program_ocotp_t的聲明:
typedef struct {
const uint32_t init;
const uint32_t uninit;
const uint32_t OCOTPWrite;
const program_syscall_t sys_call_s;
const uint32_t program_buffer;
const uint32_t algo_start;
const uint32_t algo_size;
const uint32_t *algo_blob;
const uint32_t program_buffer_size;
} program_ocotp_t;
調(diào)用swd_write_memory來(lái)下載燒寫(xiě)算法到目標(biāo)地址的示例代碼如下:
swd_write_memory(ocotp.algo_start, (uint8_t *)ocotp.algo_blob, ocotp.algo_size);
調(diào)用OTP模塊初始化函數(shù)的示例代碼如下:
swd_flash_syscall_exec(&ocotp.sys_call_s, ocotp.init, 0, 0, 0, 0, FLASHALGO_RETURN_BOOL) ;
調(diào)用OTP模塊寫(xiě)fuse函數(shù)的示例代碼如下:
swd_flash_syscall_exec(&ocotp.sys_call_s, ocotp.OTPWrite, fuse_idx, fuse_value, 0, 0, FLASHALGO_RETURN_BOOL);
到此,利用SWD燒寫(xiě)OTP就介紹完了。
如果讀者熟悉燒寫(xiě)flash的流程,會(huì)發(fā)現(xiàn)燒寫(xiě)OTP和燒寫(xiě)flash沒(méi)有差別。
OTP的值可以放在編程器的配置文件中,和固件存儲(chǔ)在一起。要想保護(hù)OTP的值,可以將它們存儲(chǔ)在硬件安全模塊(HSM)中。筆者參與的基于RT1020的離線(xiàn)編程器采用了文章中描述的方法燒寫(xiě)OTP。該項(xiàng)目預(yù)計(jì)明年初會(huì)以應(yīng)用筆記的方式發(fā)布在恩智浦官網(wǎng)。
限于篇幅,腳本中有些和flash相關(guān)的域我沒(méi)有刪掉,相信聰明的讀者可以自行完成。
審核編輯:湯梓紅出處。
-
NXP
+關(guān)注
關(guān)注
61文章
1369瀏覽量
192678 -
FlaSh
+關(guān)注
關(guān)注
10文章
1702瀏覽量
154249 -
OTP
+關(guān)注
關(guān)注
4文章
237瀏覽量
49008 -
燒寫(xiě)
+關(guān)注
關(guān)注
0文章
58瀏覽量
14795 -
SWD
+關(guān)注
關(guān)注
1文章
57瀏覽量
12529
原文標(biāo)題:基于SWD離線(xiàn)燒寫(xiě)OTP
文章出處:【微信號(hào):NXP_SMART_HARDWARE,微信公眾號(hào):恩智浦MCU加油站】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
KEIL+SWD+JLINK仿真不能燒寫(xiě)
SWD離線(xiàn)燒寫(xiě)器
CH573量產(chǎn)燒寫(xiě)是留串口呢還是SWC、SWD呢?
NXP PMIC芯片燒寫(xiě)步驟
什么是單片機(jī)燒寫(xiě)軟件?如何燒寫(xiě)
升壓型STC離線(xiàn)程序燒寫(xiě)器設(shè)計(jì)方案
STM32 MCU 的軟件燒寫(xiě)方法探討
ALTERA CPLD離線(xiàn)燒寫(xiě)方案設(shè)計(jì)(MCU模擬JTAG)
PIC OTP 單片機(jī)程序燒寫(xiě)方法
JTAG/SWD/ISP/SWIM詳解單片機(jī)的四種燒寫(xiě)方式
STM32:程序燒寫(xiě)方式

基于SWD離線(xiàn)燒寫(xiě)OTP
評(píng)論