嵌入式開(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ě)固件和OTP的方法有多種,如ISP,SWD或者Jtag等。
今天就為大家介紹下,如何讓離線編程器利用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依賴的第三方庫(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ě)OTP。該項(xiàng)目預(yù)計(jì)明年初會(huì)以應(yīng)用筆記的方式發(fā)布在恩智浦官網(wǎng)。
限于篇幅,腳本中有些和flash相關(guān)的域我沒(méi)有刪掉,相信聰明的讀者可以自行完成。
審核編輯:湯梓紅出處。
-
NXP
+關(guān)注
關(guān)注
60文章
1285瀏覽量
184784 -
FlaSh
+關(guān)注
關(guān)注
10文章
1640瀏覽量
148293 -
OTP
+關(guān)注
關(guān)注
4文章
218瀏覽量
47232 -
燒寫(xiě)
+關(guān)注
關(guān)注
0文章
57瀏覽量
14322 -
SWD
+關(guān)注
關(guān)注
1文章
57瀏覽量
11869
原文標(biāo)題:基于SWD離線燒寫(xiě)OTP
文章出處:【微信號(hào):NXP_SMART_HARDWARE,微信公眾號(hào):恩智浦MCU加油站】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論