【S32K144】使用Flash模拟EEPROM

前言

1、为什么要使用EEPROM?
为了提高效率。
嵌入式开发中,一些数据只需要读取一次就不再进行操作,断电后数据依旧存在,上电后自动读取。这部分数据应该存放在特定存储器内。
只读存储器(ROM)有以下几类

  • MROM掩膜编程只读存储器(制造过程中只写入一次)
  • PROM
  • EPROM
  • EEPROM
  • Flash

2、如何使用EEPROM?

  • MCU内部集成EEPROM
  • 通过I2C/SPI接口扩展外部EEPROM芯片,例如AT24C02/04
  • 使用MCU内部集成的Flash模拟EEPROM
  • 硬件电路(状态机)RAM映射EEE

S32K144没有集成EEPROM,本次使用Flash模拟EEPROM。
提供一些官方链接如下:

https://www.nxp.com.cn/docs/zh/application-note/AN11983.pdf 使用 S32K1xx EEPROM 功能
https://www.nxp.com.cn/docs/zh/application-note/AN12003.pdf 使用 S32K148 FlexNVM 内存
https://community.nxp.com/t5/S32-Design-Studio/read-and-write-data-of-EEPROM-of-S32K144/m-p/1016128 官网论坛帖子

简介

EEPROM(Electrically Erasable Programmable Read-Only Memory)全称“电可擦除可编程只读存储器”。
硬件信息请参考官方文档,本文将记录如何用Flash模拟EEPROM(SDK版)及调试过程。

步骤

1、添加flash组件

在这里插入图片描述
这里我使用了默认配置,没有进行更改

2、初始化flash

初始化函数我参考了官方例程“ flash_partitioning_s32k144 ”。但是有一些小问题,我只是把例程里的过程搬过来了,其中有一些是不必要的、某些操作还会引起错误。

//以下是出错的代码
void EEPROM_Init(void)
{
	MSCM->OCMDR[0u] |= MSCM_OCMDR_OCM1(0x3u);//配置flash性能和访问权限
	MSCM->OCMDR[1u] |= MSCM_OCMDR_OCM1(0x3u);

	ret = FLASH_DRV_Init(&Flash1_InitConfig0,&flashSSDConfig);
   	DEV_ASSERT(STATUS_SUCCESS == ret);

   if (flashSSDConfig.EEESize == 0u) //检查FlexRAM是否已配置为EEPROM,为0表示目前是传统RAM
   {
#ifndef FLASH_TARGET
       /* First, erase all Flash blocks if code is placed in RAM to ensure */
       ret = FLASH_DRV_EraseAllBlock(&flashSSDConfig); //配置FlexSNVM和FlexRAM之前需要确保Flash内部的配置区域是空白的,擦除
       DEV_ASSERT(STATUS_SUCCESS == ret);

       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)
       uint32_t address = 0x408u;
       eepromsize = FTFx_PHRASE_SIZE;
		uint8_t unsecure_key[FTFx_PHRASE_SIZE] = {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFEu, 0xFFu, 0xFFu, 0xFFu};
#else   /* FEATURE_FLASH_HAS_PROGRAM_LONGWORD_CMD == 1u */
       uint32_t address = 0x40Cu;
       eepromsize = FTFx_LONGWORD_SIZE;
		uint8_t unsecure_key[FTFx_LONGWORD_SIZE] = {0xFEu, 0xFFu, 0xFFu, 0xFFu};
#endif /* FEATURE_FLS_HAS_PROGRAM_PHRASE_CMD */
       ret = FLASH_DRV_Program(&flashSSDConfig, address, eepromsize, unsecure_key);
       DEV_ASSERT(STATUS_SUCCESS == ret);
#endif /* FLASH_TARGET */
		/*
		* 将 FlexRAM 配置为 EEPROM,将 FlexNVM 配置为 EEPROM 备份区域,
		* EEEDataSizeCode = 0x02u:EEPROM 大小 = 4 KB
		* DEPartitionCode = 0x08u:EEPROM 备份大小 = 64 KB */
       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(&Flash1_InitConfig0,&flashSSDConfig);
       DEV_ASSERT(STATUS_SUCCESS == ret);

       ret = FLASH_DRV_SetFlexRamFunction(&flashSSDConfig, EEE_ENABLE, 0x00u, NULL); //传递参数EEE_ENABLE启用EEPROM
       DEV_ASSERT(STATUS_SUCCESS == ret);
   }
   else    /* FLexRAM is already configured as EEPROM */
   {
       ret = FLASH_DRV_SetFlexRamFunction(&flashSSDConfig, EEE_ENABLE, 0x00u, NULL);
       DEV_ASSERT(STATUS_SUCCESS == ret);
   }
}

正确的初始化步骤只需要,在启用EEE后调用函数FLASH_DRV_Init()
首先调用此函数FLASH_DRV_DEFlashPartition进行分区,分区后进行初始化,初始化后调用此函数FLASH_DRV_SetFlexRamFunction启用EEE功能即可。改进后如下

void EEPROM_Init(void)
{
	//ret定义为全局变量
	ret = FLASH_DRV_Init(&Flash1_InitConfig0,&flashSSDConfig);
   	DEV_ASSERT(STATUS_SUCCESS == ret);

   if (flashSSDConfig.EEESize == 0u) //检查FlexRAM是否已配置为EEPROM,为0表示目前是传统RAM
   {
		/*
		* 将 FlexRAM 配置为 EEPROM,将 FlexNVM 配置为 EEPROM 备份区域,
		* EEEDataSizeCode = 0x02u:EEPROM 大小 = 4 KB
		* DEPartitionCode = 0x08u:EEPROM 备份大小 = 64 KB */
       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(&Flash1_InitConfig0,&flashSSDConfig);
       DEV_ASSERT(STATUS_SUCCESS == ret);

       ret = FLASH_DRV_SetFlexRamFunction(&flashSSDConfig, EEE_ENABLE, 0x00u, NULL);
       DEV_ASSERT(STATUS_SUCCESS == ret);
   }
   else    /* FLexRAM is already configured as EEPROM */
   {
       ret = FLASH_DRV_SetFlexRamFunction(&flashSSDConfig, EEE_ENABLE, 0x00u, NULL);
       DEV_ASSERT(STATUS_SUCCESS == ret);
   }
}

3、写EEPROM

只需调用函数FLASH_DRV_EEEWrite()

void EEPROM_Write()
{
	eepromaddress = flashSSDConfig.EERAMBase;
	eepromsize = sizeof(/*我存放数据的结构体*/);
	uint8_t *ptr = 
	for (eepbuf = 0u; eepbuf < eepromsize; eepbuf++)
	{
		sourceBuffer[eepbuf] = *ptr;
	 	ptr++;
	}
	ret = FLASH_DRV_EEEWrite(&flashSSDConfig, eepromaddress, eepromsize, sourceBuffer);
	DEV_ASSERT(STATUS_SUCCESS == ret);
}

4、读EEPROM

flash组件没有提供读函数,直接使用指针操作即可。

uint8_t testeepromread[EEPROM_BUFFER_SIZE]; //用来存放测试读到的数据
/**
  * @brief  从EEPROM读数据
  * @param  size 要读出的数据的大小,以字节为单位
  * @param  pData 存放读取的数据
  */
status_t EEPROM_read(uint32_t size,uint8_t *pData)
{
}

完成以上步骤,理论上就可以对模拟后的EEPROM进行操作了。

测试

我的测试思路是:
第一次正常烧写程序。
第二次烧写注释掉写函数的程序,上电单步调试查看读出的数据,与“ memory ”窗口里看到的数据是否一致。

在测试中我出现了一些小问题如下:
1、(!顺利的)将程序写入板子后,没有读出数据,原因很简单。一开始我的写操作直接在初始化后进行,我将初始化函数注释掉了,读的地址就出错了。自然读不到数据
2、在尝试解决问题的过程中看到有其它帖子有如下操作

 /* Flex_RAM */
  m_flexram             (RW)  : ORIGIN = 0x14000000, LENGTH = 0x00001000
/*****/
  .eeprom :
  {
    KEEP(*(.eeprom))    /*  */
  } > m_flexram

这应该是在分区,我们前面使用函数FLASH_DRV_DEFlashPartition分过区了,不明白在链接文件里手动分区这个操作必不必要,但试了发现没什么影响。
3、我前面为啥说“顺利写入”,因为还有不顺利的情况。
操作不当的情况下,很可能出现以下报错(在S32DS或Jlink),然后程序会烧不进去。
Protection bytes in flash at addr. 0x400 - 0x40F indicate that readout protection is set.For debugger connection the dewice needs to be unsecured.Note: Unsecurins will trigser a mass erase of the internal flashDo you want to unsecure the device?if "do not show this messene anain" is selected, your choice will be remembered and be performed automatically in thefutureRemember selected action (will be done automatically in the future)

在这里插入图片描述
根据提示,0x400-0x40F这段内存的内容被更改,我出现此报错的原因有:一开始的初始化函数中有不合适的操作。
又发现写完EEPROM后未注释写函数,第二次烧写程序也会有此报错。
出现此报错Jlink又连接不上,芯片被锁了,需要解锁芯片。解锁方法下面这个帖子说得很详细。
【S32K 进阶之旅】S32K 芯片的解锁
此链接是论坛里看到别人遇到的问题,供参考https://www.nxpic.org.cn/module/forum/thread-612138-1-1.html
解锁过程可能有些麻烦,一次没解锁成功重复几次应该没大问题。
在这里插入图片描述

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值