本文摘要:本文章介绍如何使用NXP官方软件S32KDS中的flash组件(操作FLASH)
开发平台:S32 Design Studio for ARM Version 2.2
SDK版本:S32_SDK_S32K1xx_RTM_3.0.0
使用芯片:S32K148
组件例程免费下载方式在文末!!!
1. 添加flash组件到工程
2. 打开flash配置页面
3. 配置flash参数(无特殊要求则采用默认配置)
一些参数的介绍:
P-Flash:存放程序代码的地方,即ROM
D-Flash:存放数据的地方,即RAM
FlexRAM:灵活配置的RAM,提供给用户以实现不同需求
S32K1XX系列的FTFC模块中断事件共有以下三个:
FTFC命令和CSEc命令完成中断事件;
FTFC读冲突错误中断事件;
FTFC ECC错误检测中断事件。
4. 配置好参数后点击如下图按钮或选项即可将配置数据更新至代码
5. 在代码中加入flash初始化的代码即可操作flash
#include "main.h"
//#define FLASH_test
// flash操作的返回结果
static uint8_t flashResult = 0;
// 系统参数
flash_ssd_config_t flashSSDConfig;
// 使用EEPROM存储用户数据
#define EEPROM
// EEPROM基地址
uint32_t EEPROM_BaseAddress = 0;
// EEPROM当前存储大小
uint32_t EEPROM_Size = 0;
void Flash_Init(void)
{
// /* Disable cache to ensure that all flash operations will take effect instantly, this is device dependent */
MSCM->OCMDR[0u] |= MSCM_OCMDR_OCM1(0x3u);
MSCM->OCMDR[1u] |= MSCM_OCMDR_OCM1(0x3u);
flashResult = FLASH_DRV_Init(&Flash1_InitConfig0, &flashSSDConfig);
#ifdef LOG_printf
SEGGER_RTT_printf(0,"["__FILE__":%d]flash init T(0)/F(!0) %d.\n", __LINE__, flashResult);
#endif
// 将flexRAM配置为EEPROM用于保存用户数据
#ifdef EEPROM
if(flashSSDConfig.EEESize == 0u)
{
/*
* 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 S32K148:
* - EEEDataSizeCode = 0x02u: EEPROM size = 4 Kbytes
* - DEPartitionCode = 0x04u: EEPROM backup size = 64 Kbytes
* */
flashResult = FLASH_DRV_DEFlashPartition(&flashSSDConfig, 0x02u, 0x04u, 0x0u, false, true);
#ifdef LOG_printf
SEGGER_RTT_printf(0,"["__FILE__":%d]DEFlashPartition T(0)/F(!0) %d.\n", __LINE__, flashResult);
#endif
/* Re-initialize the driver to update the new EEPROM configuration */
flashResult = FLASH_DRV_Init(&Flash1_InitConfig0, &flashSSDConfig);
#ifdef LOG_printf
SEGGER_RTT_printf(0,"["__FILE__":%d]flash init T(0)/F(!0) %d.\n", __LINE__, flashResult);
#endif
/* Make FlexRAM available for EEPROM */
flashResult = FLASH_DRV_SetFlexRamFunction(&flashSSDConfig, EEE_ENABLE, 0x00u, NULL);
#ifdef LOG_printf
SEGGER_RTT_printf(0,"["__FILE__":%d]SetFlexRamFunction T(0)/F(!0) %d.\n", __LINE__, flashResult);
#endif
}
else /* FLexRAM is already configured as EEPROM */
{
/* Make FlexRAM available for EEPROM, make sure that FlexNVM and FlexRAM
* are already partitioned successfully before */
flashResult = FLASH_DRV_SetFlexRamFunction(&flashSSDConfig, EEE_ENABLE, 0x00u, NULL);
#ifdef LOG_printf
SEGGER_RTT_printf(0,"["__FILE__":%d]SetFlexRamFunction T(0)/F(!0) %d.\n", __LINE__, flashResult);
#endif
}
EEPROM_BaseAddress = flashSSDConfig.EERAMBase;
#endif
#ifdef FLASH_test
// 擦除flash
INT_SYS_DisableIRQGlobal();
// S32K148的FLASH_DRV_EraseSector最小擦除扇区大小是 4KB
flashResult = FLASH_DRV_EraseSector(&flashSSDConfig, 0x160000, 4096);
#ifdef DEBUG_printf
SEGGER_RTT_printf(0,"flash erase T(0)/F(!0) %d.\n",flashResult);
#endif
// 验证擦除
flashResult = FLASH_DRV_VerifySection(&flashSSDConfig, 0x160000, 4096 / 16, 1u);
#ifdef DEBUG_printf
SEGGER_RTT_printf(0,"flash verify T(0)/F(!0) %d.\n",flashResult);
#endif
uint8_t data[8] = {0x07,0x77,0,0,0,0,0,0};
// S32K148的FLASH_DRV_Program最小可写大小是8B
flashResult = FLASH_DRV_Program(&flashSSDConfig, 0x160000, 8, data);
// S32K148的FLASH_DRV_ProgramSection最小可写大小是1KB
//flashResult = FLASH_DRV_ProgramSection(&flashSSDConfig, CANID_private_addr, 4096 / 16);
#ifdef DEBUG_printf
SEGGER_RTT_printf(0,"flash write T(0)/F(!0) %d.\n",flashResult);
#endif
uint32_t failAddr = 0;
// 验证写数据
flashResult = FLASH_DRV_ProgramCheck(&flashSSDConfig, 0x160000, 8, data, &failAddr, 1u);
#ifdef DEBUG_printf
SEGGER_RTT_printf(0,"check write T(0)/F(!0) %d, fail address %x.\n", flashResult, failAddr);
#endif
INT_SYS_EnableIRQGlobal();
#endif
}
/**
* @brief 向EEPROM写数据
* @param *data: 要写入的数据
* @param addrOffset: 要写入的地址偏移,基于EEPROM的基地址的偏移
* @param size: 要写入的数据的大小,以字节为单位
* @retval flashResult: 0为成功 非0为失败
* @note 写入数据大小最小1Byte
*/
uint8_t writeDataToEEPROM(uint8_t *data, uint32_t addrOffset, uint32_t size)
{
flashResult = FLASH_DRV_EEEWrite(&flashSSDConfig, EEPROM_BaseAddress + addrOffset, size, data);
#ifdef DEBUG_printf
uint8_t i = 0;
for(i = 0; i < size; i++)
{
SEGGER_RTT_printf(0,"(flash)write EEPROM Byte %d : 0x%02x\n", i, data[i]);
}
SEGGER_RTT_printf(0,"(flash)write EEPROM T(0)/F(!0) %d\n", flashResult);
#endif
return flashResult;
}
/**
* @brief 从EEPROM读数据
* @param *read: 数据存放地址
* @param addrOffset: 要读出的地址偏移,基于EEPROM的基地址的偏移
* @param size: 要读出的数据的大小,以字节为单位
* @retval None
* @note 读出数据大小最小1Byte
*/
void readDataFromEEPROM(uint8_t *read, uint32_t addrOffset, uint32_t size)
{
uint8_t i = 0;
for(i = 0; i < size; i++)
{
read[i] = *((uint32_t *)(EEPROM_BaseAddress + addrOffset + i));
#ifdef DEBUG_printf
SEGGER_RTT_printf(0,"(flash)read EEPROM byte %d : 0x%02x\n", i, read[i]);
#endif
}
}
6. 部分函数介绍
6.0 S32K1XXMCU字节对齐要求
6.1 FLASH_DRV_EraseSector()
该函数是扇区擦除flash,S32K14X系列最小擦除扇区大小是 4KB
uint32_t address = 0x1000;
uint32_t size = 4096;
// address 注意字节对齐,S32K148为16字节对齐,其他参见手册
// size 必须为4096的倍数,最小为4096
// 具体参数含义参见手册
FLASH_DRV_EraseSector(&flashSSDConfig, address, size);
6.2 FLASH_DRV_VerifySection()
该函数是校验扇区擦除,一般配合扇区擦除函数使用,用以校验擦除
uint32_t address = 0x1000;
uint32_t size = 4096;
// address 注意字节对齐,S32K148为16字节对齐,其他参见手册
// size 必须为4096的倍数,最小为4096
// 具体参数含义参见手册
FLASH_DRV_VerifySection(&flashSSDConfig, address, size / 16, 1u);
6.3 FLASH_DRV_Program()
该函数是写入flash,S32K148的最小可写大小是 8B
uint32_t address = 0x1000;
uint32_t size = 8;
uint8_t data[8] = {0};
// address 注意字节对齐,S32K148为16字节对齐,其他参见手册
// size 必须为8的倍数,最小为8
// data 要写的内容
// 具体参数含义参见手册
FLASH_DRV_Program(&flashSSDConfig, address, size, data);
6.4 FLASH_DRV_ProgramCheck()
该函数是校验写入flash,一般配合写入flash函数使用,用以校验写入
uint32_t address = 0x1000;
uint32_t size = 8;
uint8_t data[8] = {0};
Uint32_t failAddr = 0;
// address 注意字节对齐,S32K148为16字节对齐,其他参见手册
// size 必须为8的倍数,最小为8
// data 校验的内容
// failAddr 出错的地址,为0则校验通过
// 具体参数含义参见手册
FLASH_DRV_ProgramCheck(&flashSSDConfig, address, size, data, &failAddr, 1u);
7. 特别注意事项
7.1 flash操作函数返回结果为0即为成功
7.2 flash地址必须按要求对齐(分区不同对齐要求不同)
7.3 flash操作前要关闭全局中断,操作后再开启
INT_SYS_DisableIRQGlobal();
FLASH_DRV_EraseSector(&flashSSDConfig, address, size);
INT_SYS_EnableIRQGlobal();
7.4 flash操作时间较长,如果启动了看门狗,必须倍频看门狗频率延长复位时间,防止在操作flash时复位;或者FTFC的Callback回调函数,以便在Flash驱动API调用过程中重置看门狗,防止复位
// __attribute__((section (".code_ram")))”将此函数重映射到SRAM中运行,防止操作flash时意外修改此部分内容
void __attribute__((section (".code_ram"))) Flash_Command_Callback(void)
{
/* refresh the WDOG watchdog to avoid timeout reset */
WDOG->CNT = 0xB480A602U;
}
7.5 flash操作时一般不操作当前程序所处地址范围,如果意外操作了当前程序地址,则可能会造成运行出错,程序跑飞
组件例程下载地址:
https://download.csdn.net/download/m0_50669075/85051862
S32K148更多例程和源码以及最新内容下载地址:
END