1. 4kB EERAM上的CSEc密鑰和用戶數(shù)據(jù)
使用S32K148,將啟用CSE模塊進(jìn)行安全引導(dǎo)。根據(jù)應(yīng)用說(shuō)明(“使用S32K148 FlexNVM存儲(chǔ)器”,AN12003,版本0,2017年7月),在第3.3節(jié)中,64 kB的FlexNVM用作閃存(EEPROM備份和密鑰存儲(chǔ)在一起),CSEc使用最多512字節(jié)的密鑰存儲(chǔ),剩下的3.5 kB EERAM用于EEPROM和啟用CSEc。在這種用法中,用戶數(shù)據(jù)是否以某種方式通過(guò)覆蓋或刪除注冊(cè)密鑰而保留。簡(jiǎn)而言之,記錄密鑰的512字節(jié)是隨機(jī)記錄在EERAM中,還是記錄在特定位置,如4KB FlexRAM的開(kāi)始/結(jié)束位置?
-> 如果分配的CSEc空間為512B,則FlexRAM(EEPROM)中將無(wú)法訪問(wèn)空間0x14000E00-0x14000FFF。對(duì)該區(qū)域的任何訪問(wèn)都會(huì)生成總線故障異常。
2. 關(guān)于CSEc安全引導(dǎo)和順序引導(dǎo)模式的問(wèn)題。
測(cè)量從復(fù)位引腳釋放到高電平的安全啟動(dòng)時(shí)間,不同boot_SIZE和Clock時(shí)鐘對(duì)于安全啟動(dòng)時(shí)間有所不同。當(dāng)安全啟動(dòng)開(kāi)始啟動(dòng)時(shí)(即CSEc正在計(jì)算CMAC),MCU內(nèi)核保持在復(fù)位狀態(tài),復(fù)位引腳也保持在低電平狀態(tài),直到CMAC計(jì)算完成。
3. 實(shí)現(xiàn) SHA256
在S32K1上面的CSEc 模塊支持 AES128 引擎,但不支持 SHA256。但是用戶可以參考如下代碼實(shí)現(xiàn)它。
https://github.com/ARMmbed/mbedtls/blob/v2.16.8/library/sha256.c
4. 當(dāng)在 S32K146中使用 CSEc模塊的時(shí)候,程序訪問(wèn) CSE_PRAM 空間,在調(diào)試模式下它將進(jìn)入異常中斷。
#define REG_WRITE32(address, value) ((*(volatile uint32*)(address))= (value))
#define CRYPTO_PRAM_HDR_ADDR32 (0x14001000u)
REG_WRITE32(CRYPTO_PRAM_HDR_ADDR32, u32CommandHeader);
上述代碼高亮部分表示寫入 PRAM命令,會(huì)導(dǎo)致程序進(jìn)入異常中斷。
->通過(guò)檢查SIM_SDID[FEATURES]寄存器,判斷S32K芯片是否支持 CSEc。為了使能 CSEc 模塊,內(nèi)存需要分區(qū)用于EEPROM,F(xiàn)TFC寄存器需要編程。
5.CSEC模塊PRAM格式
在應(yīng)用筆記 AN5401中,有的是通過(guò) PRAM 頁(yè)1讀取數(shù)據(jù),而有的是通過(guò) PRAM頁(yè)2輸出數(shù)據(jù),這兩種方法有什么不同的嗎?
-> 參考手冊(cè)里面的 CSEc命令
https://www.nxp.com/docs/en/reference-manual/S32K-RM.pdf
這是CMD_GET_ID命令的描述,可以在其中看到使用了哪些頁(yè)及其目的是什么:
如下是 AN5401文檔中的參考代碼部分。
6. CSEc不能恢復(fù)到工廠模式
通過(guò) CSEC_DRV_DbgChal恢復(fù)到工廠模式失敗,返回"STATUS_SEC_KEY_WRITE_PROTECTED"。這里Keys不能被配置為寫保護(hù),否則將不能被擦除。
https://www.nxp.com/docs/en/application-note/AN12130.pdf
7.S32K144閃存分區(qū)問(wèn)題
使用S32K144EVB-Q100和SDK3.0.0以及S32DS進(jìn)行ARM調(diào)試。當(dāng)使用OpenSDA工具調(diào)試閃存時(shí),可以擦除閃存并完成分區(qū)閃存,但當(dāng)使用J-Link調(diào)試閃存時(shí)無(wú)法再次擦除閃存和分區(qū)閃存,必須先使用類似J-Flash的工具擦除閃存。如何使用J-Link擦除閃存和分區(qū)閃存。是否有調(diào)試配置的任何設(shè)置?
->在使用SDK API對(duì)FlexNVM進(jìn)行分區(qū)時(shí),由于啟用了CSEc。
如果啟用CSEc,則無(wú)法通過(guò)命令“全部擦除”或其他FTFC命令擦除FlexNVM。如果要擦除FlexNVM,唯一的方法是使用CSEc命令將FlexNVM復(fù)位為出廠狀態(tài)。有關(guān)更多信息,請(qǐng)參閱AN5401。
https://www.nxp.com/webapp/Download?colCode=AN5401
https://www.nxp.com/webapp/Download?colCode=AN5401SW&docLang=en
#include "CSEc_functions.h"
#include "CSEc_macros.h"
#include "CSEc_keys.h"
uint32_t dbg_challenge_out[4] = {0,0,0,0};
int main(void)
{
uint16_t __attribute__((unused)) csec_error = 0; //1 means No Error
csec_error = INIT_RNG(); /* Initialize the Random Number Generator before generating challenge */
//To Erase all keys and reset the part to the factory state
csec_error = DBG_CHAL(dbg_challenge_out); /* Generate the Challenge */
csec_error = DBG_AUTH(dbg_challenge_out); /* Issue the Authorization */
while(1);
/* to avoid the warning message for GHS and IAR: statement is unreachable*/
#if defined (__ghs__)
#pragma ghs nowarning 111
#endif
#if defined (__ICCARM__)
#pragma diag_suppress=Pe111
#endif
return 0;
}
由于 CSEc 模塊所有密鑰都只能 CSEc 模塊管理,這樣才能確保密鑰安全的安全性。雖然密鑰實(shí)際存儲(chǔ)區(qū)域是在模擬 EEPROM 中,但由于這段區(qū)域是由 CSEc 管理并且對(duì)用戶是不可見(jiàn)的,所以也無(wú)法通過(guò)直接對(duì) DFlash 編程的方式寫入密鑰。在量產(chǎn)時(shí),可以使用一份專用于寫入密鑰的程序,通過(guò)先刷寫這份程序,等寫入密鑰后,再刷寫正式的應(yīng)用程序即可。需要注意的時(shí),兩份程序需要有一致的 D-Flash 分區(qū)策略。當(dāng)然也可以通過(guò)診斷服務(wù)的方式加載密鑰。先脫機(jī)計(jì)算出密鑰的 M1~M5 值,然后通過(guò)診斷服務(wù)(如 2Eh服務(wù))將 M1~M3 加載至 CSEc 模塊中,并通過(guò) M4 和 M5 驗(yàn)證是否加載成功。由于不能通過(guò) M1~M3 值逆推算出密鑰值,所以這種方式也是安全的。由于使能 CSEc 模塊后,只能通過(guò) CSEc 模塊的恢復(fù)命令(使用調(diào)試器也不行)才能擦除 D-Flash 數(shù)據(jù)并恢復(fù) D-Flash 至出廠狀態(tài),所以如果在量產(chǎn)后需要再次擦除 D-Flash,或者重新對(duì) D-Flash 進(jìn)行分區(qū)等,可以在用戶代碼中加入相關(guān)程序,通過(guò)觸發(fā)這段程序來(lái)使用 CSEc 模塊的命令擦除 D-Flash。CSEc 模塊對(duì) P-Flash的重新編程沒(méi)有影響。
7. 為CSEc操作分配密鑰大小后,需要按照AN5401 4.5中列出的步驟將閃存重置為出廠狀態(tài)。此外,還提供了一些連接/擦除/編程到S32K器件的提示。
(https://www.nxp.com/docs/en/application-note/AN12130.pdf )
如果沒(méi)有按照正確的步驟在分配密鑰后擦除Flash,器件可能會(huì)被鎖定,并且無(wú)法解鎖。
如參考手冊(cè)所述,分區(qū)操作在整個(gè)產(chǎn)品周期中最好只執(zhí)行一次。
可以通過(guò)DBG_CHAL 和 DBG_AUTH 銷毀分區(qū),不用擦除Flash。
當(dāng)未分配CSEc時(shí),沒(méi)有辦法在不擦除所有鍵的情況下刪除分區(qū)?因?yàn)橹恍枰脸龜?shù)據(jù)Flash 以及Flash IFR。但是,一旦數(shù)據(jù)Flash 已經(jīng)為EEPROM分區(qū),F(xiàn)TFC擦除Flash 塊命令就不能擦除數(shù)據(jù)Flash。
運(yùn)行DBG_CHAL和DBG_ AUTH命令會(huì)擦除所有密鑰,包括BOOT_MAC和BOOT_ MAC_KEY。在沒(méi)有這兩個(gè)參數(shù)的情況下,不會(huì)執(zhí)行安全引導(dǎo)過(guò)程,因此應(yīng)用程序可以自由執(zhí)行,并且MCU 不會(huì)處于復(fù)位狀態(tài)。
DBG_CHAL/DBG_ AUTH即使在嚴(yán)格啟動(dòng)模式處于活動(dòng)狀態(tài)時(shí)也可以工作,假設(shè)所有密鑰都沒(méi)有寫保護(hù)。這不會(huì)鎖定 MCU。
成功執(zhí)行DBG_CHAL/DBG_ AUTH后,所有密鑰將被擦除,安全引導(dǎo)處于非活動(dòng)狀態(tài)。可以使用任何方式(串行、并行、嚴(yán)格順序)再次激活安全引導(dǎo)。
注意:對(duì)于嚴(yán)格順序模式,自動(dòng)MAC計(jì)算是不可能的。在激活嚴(yán)格順序引導(dǎo)之前,必須計(jì)算并存儲(chǔ)BOOT_MAC。否則將鎖定器件。MAC可通過(guò)CSEc本身或PC離線計(jì)算。有關(guān)更多詳細(xì)信息和代碼示例,請(qǐng)參閱 AN5401。
8. 當(dāng)執(zhí)行FLASH_DRV_DEFlashPartition 函數(shù)的時(shí)候, FTFx_FSTAT 是FTFx_FSTAT_ACCERR_MASK。
While((FTFC->FSTAT&FTFC_FSTAT_CCIF_MASK)==0U)
FTFC_FSTAT – 異常時(shí),F(xiàn)lash狀態(tài)寄存器是 160, Flash Access Error
Flag 標(biāo)志是 '1',但是正常狀態(tài)是 128。Flash已經(jīng)分區(qū),有如下原因?qū)е?ACCERR位被置位。
已通過(guò)分區(qū)命令啟用CSEc,則此時(shí)擦除所有塊命令將無(wú)效(它也應(yīng)返回ACCERR)。是否加載了密鑰并不重要。一旦Flash 分區(qū),并且密鑰大小不是 0,則需要使用CMD_DBG_CHAL和CMD_ DBG_ AUTH命令來(lái)銷毀分區(qū)。為此,需要知道MASTER_ECU_KEY。如果尚未加載MASTER_ECU_KEY,則需要加載,然后可以使用CMD_DBG_CHAL和CMD_ DBG_ AUTH命令,別無(wú)選擇。可以檢查SIM模塊中的閃存配置寄存器1(FCFG1),查看器件是否已分區(qū)。
如果Flash已經(jīng)分區(qū)、CSEc已經(jīng)使能,F(xiàn)LASH_DRV_EraseAllBlock不能工作。唯一的方案是在了解MASTER_ECU_KEY的情況下使用DBG_CHAL 和 DBG_AUTH 命令恢復(fù)。
可以參考如下例子中的 eraseKeys()函數(shù)。S32DS.3.4S32DSsoftwareS32SDK_S32K1XX_RTM_4.0.2examplesS32K144driver_examplessystemcsec_keyconfig
在HSRUN模式(112MHz下),CSEc (安全) 或者 EEPROM 擦寫將觸發(fā)錯(cuò)誤標(biāo)志。因?yàn)樵谶@種情況下不允許同時(shí)使用。器件需要切回到 RUN模式(80 Mhz) 來(lái)執(zhí)行 CSEc(安全) 或者 EEPROM 寫/擦除。
Flash 內(nèi)存安全在 CSEc 和non-CSEc 器件上都支持,SIM_SDID[7]表示 CSEc 是否在器件上支持。CSEc 和non CSEc 用戶需要運(yùn)行 PGMPART 命令來(lái)配置 KeySize。針對(duì) non CSEc 用戶,Key Size 必須配置為 0。
整個(gè) EEERAM的空間是減小,為了存儲(chǔ)用戶 Keys的需要。用戶密鑰空間實(shí)際上成為EEERAM中的不可尋址空間。針對(duì)具有 CSEc或者沒(méi)有 CSEc的器件,如果 Key size為0,則CSEc_PRAM訪問(wèn)是不允許的。Keysize為零時(shí),是普通EEPROM分區(qū)么,直接mass erase就恢復(fù)了。通過(guò)操作 FLASH_DRV_EraseAllBlockUnsecure函數(shù)恢復(fù),或者硬件將Reset引腳短接,然后通過(guò)JLINK等外部工具擦除MCU內(nèi)部的 Flash。
如果S32K146板默認(rèn)存在分區(qū),通過(guò)判斷(SIM->FCFG1[FEATURE])確定分區(qū),如果要使用新的分區(qū)操作,需要擦除舊的分區(qū),如果不擦,在調(diào)試CSEc init_rng或者erase all key的時(shí)候會(huì)進(jìn)入defaultISR中斷,可以通過(guò)上述mass erase方式恢復(fù)(keysize為零的情況)。然后重新分區(qū)使能 CSEc模塊,操作初始化隨機(jī)數(shù)以及加解密,預(yù)置秘鑰操作。
程序分區(qū)命令準(zhǔn)備FlexNVM塊用作數(shù)據(jù)閃存、模擬EEPROM備份或兩者的組合,并初始化FlexRAM。程序分區(qū)命令不能從Flash 啟動(dòng),因?yàn)樵诔绦蚍謪^(qū)命令執(zhí)行期間無(wú)法訪問(wèn)Flash 資源。與程序分區(qū)命令的執(zhí)行相關(guān)的更改在下次復(fù)位后生效。在啟動(dòng)其他FTFC和CSEc命令之前,預(yù)計(jì)將為新器件運(yùn)行程序分區(qū)命令。
注意:雖然FlexNVM可以用不同分區(qū),但其目的是在給定應(yīng)用程序的整個(gè)生命周期中使用一次分區(qū)選擇。FlexNVM分區(qū)代碼選擇影響器件的耐久性和數(shù)據(jù)保留特性。中斷程序分區(qū)操作(由于斷電、復(fù)位、電源超出指定的操作范圍或任何其他原因)會(huì)使分區(qū)代碼處于不確定狀態(tài)。用戶必須采取適當(dāng)?shù)膽?yīng)對(duì)措施,以防止程序分區(qū)操作中斷時(shí)數(shù)據(jù)丟失。
對(duì)于未啟用CSEc的部件,F(xiàn)lash KeySize的數(shù)量必須配置為2'b00。對(duì)于啟用CSEc的器件,F(xiàn)lash密鑰的數(shù)量是用戶可配置的,但該空間將假設(shè)存在MASTER_ECU_KEY、BOOT_MAC_KEY和BOOT_ MAC(如果啟用了任何密鑰),因此將占用可用20個(gè)密鑰槽空間中的3個(gè)密鑰槽。這導(dǎo)致在1到17個(gè)用戶keys的范圍內(nèi)留下鍵槽。對(duì)于未啟用CSEc的部件,密鑰分配必須設(shè)置為零密鑰(2'b00),否則該命令將返回錯(cuò)誤。
注:對(duì)于具有CSEc的器件,一旦分配了Flash密鑰(無(wú)論是否初始化),SHE規(guī)范中不帶認(rèn)證將不能擦除Flash 密鑰的要求將適用。這意味著在擦除數(shù)據(jù)Flash(所有Flash 密鑰都備份在數(shù)據(jù)Flash中的模擬EEPROM中)之前,必須運(yùn)行并通過(guò)身份驗(yàn)證(DBG_CHAL和DBG_ AUTH)命令(刪除所有 Flash密鑰)。因此,擦除所有塊和擦除所有塊解鎖將不起作用,如果所選塊/扇區(qū)包括存儲(chǔ)密鑰,則擦除Flash 塊或扇區(qū)也不起作用。此外,如果任何 Flash密鑰受寫保護(hù),則無(wú)法擦除/刪除它們,因此無(wú)法擦除數(shù)據(jù) Flash,身份驗(yàn)證過(guò)程也不會(huì)通過(guò)。
9. 在S32DS環(huán)境下,使用如下 RTM3.0.0的example flash_partitioning_s32k144的例子,在debug RAM下運(yùn)行就可以擦除以前老的 EEPROM分區(qū)。(如果keysize為零,沒(méi)有使用 CSEc的情況下)
/* Including needed modules to compile this module/procedure */
#include "Cpu.h"
#include "clockMan1.h"
#include "Flash.h"
volatile int exit_code = 0;
/* User includes (#include below this line is not maintained by Processor Expert) */
#include
#include
/* Declare a FLASH config struct which initialized by FlashInit, and will be used by all flash operations */
flash_ssd_config_t flashSSDConfig;
/* Data source for program operation */
#define BUFFER_SIZE 0x100u /* Size of data source */
#define FLASH_TARGET1
uint8_t sourceBuffer[BUFFER_SIZE];
/* Function declarations */
void CCIF_Handler(void);
/* If target is flash, insert this macro to locate callback function into RAM */
void CCIF_Callback(void)
int main(void)
{
/* Write your local variable definition here */
status_t ret; /* Store the driver APIs return code */
uint32_t address;
uint32_t size;
uint32_t failAddr;
uint32_t i;
flash_callback_t pCallBack;
#if (FEATURE_FLS_HAS_PROGRAM_PHRASE_CMD == 1u)
#ifndef FLASH_TARGET
uint8_t unsecure_key[FTFx_PHRASE_SIZE] = {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFEu, 0xFFu, 0xFFu, 0xFFu};
#endif
#else /* FEATURE_FLASH_HAS_PROGRAM_LONGWORD_CMD */
uint8_t unsecure_key[FTFx_LONGWORD_SIZE] = {0xFEu, 0xFFu, 0xFFu, 0xFFu};
#endif /* FEATURE_FLS_HAS_PROGRAM_PHRASE_CMD */
/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
#ifdef PEX_RTOS_INIT
PEX_RTOS_INIT(); /* Initialization of the selected RTOS. Macro is defined by the RTOS component. */
#endif
/*** End of Processor Expert internal initialization. ***/
CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT,
g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);
/* Init source data */
for (i = 0u; i < BUFFER_SIZE; i++)
{
sourceBuffer[i] = i;
}
/* Disable cache to ensure that all flash operations will take effect instantly,
* this is device dependent */
#ifndef FLASH_TARGET
#ifdef S32K144_SERIES
MSCM->OCMDR[0u] |= MSCM_OCMDR_OCM1(0x3u);
MSCM->OCMDR[1u] |= MSCM_OCMDR_OCM1(0x3u);
#endif /* S32K144_SERIES */
#endif /* FLASH_TARGET */
/* Install interrupt for Flash Command Complete event */
INT_SYS_InstallHandler(FTFC_IRQn, CCIF_Handler, (isr_t*) 0);
INT_SYS_EnableIRQ(FTFC_IRQn);
/* Enable global interrupt */
INT_SYS_EnableIRQGlobal();
/* Always initialize the driver before calling other functions */
ret = FLASH_DRV_Init(&Flash_InitConfig0, &flashSSDConfig);
DEV_ASSERT(STATUS_SUCCESS == ret);
#if ((FEATURE_FLS_HAS_FLEX_NVM == 1u) & (FEATURE_FLS_HAS_FLEX_RAM == 1u))
/* Config FlexRAM as EEPROM if it is currently used as traditional RAM */
if (flashSSDConfig.EEESize == 0u)
{
#ifndef FLASH_TARGET
/* First, erase all Flash blocks if code is placed in RAM to ensure
* the IFR region is blank before partitioning FLexNVM and FlexRAM */
ret = FLASH_DRV_EraseAllBlock(&flashSSDConfig);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Verify the erase operation at margin level value of 1 */
ret = FLASH_DRV_VerifyAllBlock(&flashSSDConfig, 1u);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Reprogram secure byte in Flash configuration field */
#if (FEATURE_FLS_HAS_PROGRAM_PHRASE_CMD == 1u)
address = 0x408u;
size = FTFx_PHRASE_SIZE;
#else /* FEATURE_FLASH_HAS_PROGRAM_LONGWORD_CMD == 1u */
address = 0x40Cu;
size = FTFx_LONGWORD_SIZE;
#endif /* FEATURE_FLS_HAS_PROGRAM_PHRASE_CMD */
ret = FLASH_DRV_Program(&flashSSDConfig, address, size, unsecure_key);
DEV_ASSERT(STATUS_SUCCESS == ret);
#endif /* FLASH_TARGET */
/* Configure FlexRAM as EEPROM and FlexNVM as EEPROM backup region,
* DEFlashPartition will be failed if the IFR region isn't blank.
* Refer to the device document for valid EEPROM Data Size Code
* and FlexNVM Partition Code. For example on S32K144:
* - EEEDataSizeCode = 0x02u: EEPROM size = 4 Kbytes
* - DEPartitionCode = 0x08u: EEPROM backup size = 64 Kbytes */
ret = FLASH_DRV_DEFlashPartition(&flashSSDConfig, 0x02u, 0x08u, 0x0u, false, true);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Re-initialize the driver to update the new EEPROM configuration */
ret = FLASH_DRV_Init(&Flash_InitConfig0, &flashSSDConfig);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Make FlexRAM available for EEPROM */
ret = FLASH_DRV_SetFlexRamFunction(&flashSSDConfig, EEE_ENABLE, 0x00u, NULL);
DEV_ASSERT(STATUS_SUCCESS == ret);
}
else /* FLexRAM is already configured as EEPROM */
{
ret = FLASH_DRV_EraseAllBlockUnsecure(&flashSSDConfig);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Re-initialize the driver to update the new EEPROM configuration */
ret = FLASH_DRV_Init(&Flash_InitConfig0, &flashSSDConfig);
DEV_ASSERT(STATUS_SUCCESS == ret);
}
#endif /* (FEATURE_FLS_HAS_FLEX_NVM == 1u) & (FEATURE_FLS_HAS_FLEX_RAM == 1u) */
/* Set callback function before a long time consuming flash operation
* (ex: erasing) to let the application code do other tasks while flash
* in operation. In this case we use it to enable interrupt for
* Flash Command Complete event */
pCallBack = (flash_callback_t)CCIF_Callback;
flashSSDConfig.CallBack = pCallBack;
/* Erase the last PFlash sector */
address = FEATURE_FLS_PF_BLOCK_SIZE - FEATURE_FLS_PF_BLOCK_SECTOR_SIZE;
size = FEATURE_FLS_PF_BLOCK_SECTOR_SIZE;
ret = FLASH_DRV_EraseSector(&flashSSDConfig, address, size);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Disable Callback */
flashSSDConfig.CallBack = NULL_CALLBACK;
/* Verify the erase operation at margin level value of 1, user read */
ret = FLASH_DRV_VerifySection(&flashSSDConfig, address, size / FTFx_DPHRASE_SIZE, 1u);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Write some data to the erased PFlash sector */
size = BUFFER_SIZE;
ret = FLASH_DRV_Program(&flashSSDConfig, address, size, sourceBuffer);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Verify the program operation at margin level value of 1, user margin */
ret = FLASH_DRV_ProgramCheck(&flashSSDConfig, address, size, sourceBuffer, &failAddr, 1u);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Try to write data to EEPROM if FlexRAM is configured as EEPROM */
if (flashSSDConfig.EEESize != 0u)
{
address = flashSSDConfig.EERAMBase;
size = sizeof(uint32_t);
ret = FLASH_DRV_EEEWrite(&flashSSDConfig, address, size, sourceBuffer);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Verify the written data */
if (*((uint32_t *)sourceBuffer) != *((uint32_t *)address))
{
/* Failed to write data to EEPROM */
exit_code = 1u;
return exit_code;
}
/* Try to update one byte in an EEPROM address which isn't aligned */
address = flashSSDConfig.EERAMBase + 1u;
size = sizeof(uint8_t);
sourceBuffer[0u] = 0xFFu;
ret = FLASH_DRV_EEEWrite(&flashSSDConfig, address, size, sourceBuffer);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Then verify */
if (sourceBuffer[0u] != *((uint8_t *)address))
{
/* Failed to update data to EEPROM */
exit_code = 1u;
return exit_code;
}
}
else
{
#if (FEATURE_FLS_HAS_FLEX_NVM == 1u)
/* Erase a sector in DFlash */
address = flashSSDConfig.DFlashBase;
size = FEATURE_FLS_DF_BLOCK_SECTOR_SIZE;
ret = FLASH_DRV_EraseSector(&flashSSDConfig, address, size);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Verify the erase operation at margin level value of 1, user read */
ret = FLASH_DRV_VerifySection(&flashSSDConfig, address, size / FTFx_PHRASE_SIZE, 1u);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Write some data to the erased DFlash sector */
address = flashSSDConfig.DFlashBase;
size = BUFFER_SIZE;
ret = FLASH_DRV_Program(&flashSSDConfig, address, size, sourceBuffer);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Verify the program operation at margin level value of 1, user margin */
ret = FLASH_DRV_ProgramCheck(&flashSSDConfig, address, size, sourceBuffer, &failAddr, 1u);
DEV_ASSERT(STATUS_SUCCESS == ret);
#endif /* FEATURE_FLS_HAS_FLEX_NVM */
}
#ifdef PEX_RTOS_START
PEX_RTOS_START(); /* Startup of the selected RTOS. Macro is defined by the RTOS component. */
#endif
for(;;) {
if(exit_code != 0) {
break;
}
}
return exit_code;
/*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/
void CCIF_Handler(void)
{
/* Disable Flash Command Complete interrupt */
FTFx_FCNFG &= (~FTFx_FCNFG_CCIE_MASK);
return;
}
void CCIF_Callback(void)
{
/* Enable interrupt for Flash Command Complete */
if ((FTFx_FCNFG & FTFx_FCNFG_CCIE_MASK) == 0u)
{
FTFx_FCNFG |= FTFx_FCNFG_CCIE_MASK;
}
}
運(yùn)行調(diào)試模式,停止,然后再次運(yùn)行會(huì)進(jìn)入FLASH_DRV_EraseAllBlockUnsecure,關(guān)于 Flash組件配置如下。
-
mcu
+關(guān)注
關(guān)注
146文章
17123瀏覽量
350990 -
寄存器
+關(guān)注
關(guān)注
31文章
5336瀏覽量
120230 -
SHA256
+關(guān)注
關(guān)注
0文章
5瀏覽量
10035 -
EERAM
+關(guān)注
關(guān)注
0文章
9瀏覽量
4559
原文標(biāo)題:S32K CSEc
文章出處:【微信號(hào):嵌入式 MCU,微信公眾號(hào):嵌入式 MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論