天天看點

S32K模拟EEPROM實作單位元組和多位元組的寫入,并實作在一個位址處更新刷寫次數

最近打算寫EEPROM,本着單使用官方手冊就搞定這個模拟EEPROM,最後還是借鑒了官方的例程

一、先來看一下我們要操作的記憶體空間的大小和可操作的位址在哪裡?

S32K模拟EEPROM實作單位元組和多位元組的寫入,并實作在一個位址處更新刷寫次數

 1)從上圖可知S32K148的FlexRAM 的最大空間為4k,是以說他可模拟的EEPROM最大為4k(S32K的EEPROM按位元組讀取的是由FlexRAM模拟最大4K,S32K的EEPROM按最小扇區2K讀取的是由FlexNvm模拟最大64K)

S32K模拟EEPROM實作單位元組和多位元組的寫入,并實作在一個位址處更新刷寫次數
S32K模拟EEPROM實作單位元組和多位元組的寫入,并實作在一個位址處更新刷寫次數

2)從上面兩張圖可以看出來我們要操作的EEPROM的首位址是在0X14000000

二、了解最基本的記憶體知識後,下來我們看一下操作FLASH寄存器的具體步驟

S32K模拟EEPROM實作單位元組和多位元組的寫入,并實作在一個位址處更新刷寫次數

這個流程圖是關于Flash操作寄存器的通用步驟,這個你可以仔細看S32DS生成的驅動代碼,都是按照這個流程圖。

三、基本常識就是這些,然後借鑒一下Main.c代碼對Flash的操作流程

/* Including necessary module. Cpu.h contains other modules needed for compiling.*/
#include "Cpu.h"

  volatile int exit_code = 0;

/* User includes (#include below this line is not maintained by Processor Expert) */

  /*
   * Flash選配記憶體空間分段
   * */

#define  BUFFER_SIZE         0x20u                   /* Size of data source */
#define  FLASHaddNUM_ERASE   0

#define bool	_Bool
#define true	1
#define false	0

#define _Bool	bool

 flash_ssd_config_t   flashSSDConfig;
 uint8_t sourceBuffer[BUFFER_SIZE]={1,2,3,4,0,0,7};
 uint8_t sourceReadBuffer[BUFFER_SIZE]={1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0};
/*!
  \brief The main function for the project.
  \details The startup initialization sequence is the following:
 * - startup asm routine
 * - main()
*/
  void CCIF_Handler(void);


  START_FUNCTION_DECLARATION_RAMSECTION

  void CCIF_Callback(void)

  END_FUNCTION_DECLARATION_RAMSECTION
 /* 2020.03.17
  * 使用FlexRAM模仿EEPROM
  * 可以最大分區出4k的EEPROM空間,并且記憶體可按照單個位元組進行讀取
  *
  * */
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;

   flash_callback_t pCallBack;



  /*** 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);


  /* Install interrupt for Flash Command Complete event */
      INT_SYS_InstallHandler(FTFC_IRQn, CCIF_Handler, (isr_t*) 0);     //CCIF_Handler代表了一個形參為void,傳回值為void的函數
      INT_SYS_EnableIRQ(FTFC_IRQn);


  /* Enable global interrupt */
      INT_SYS_EnableIRQGlobal();


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


#if 0
      /*檫除EEPROM的存儲空間*/
      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(ret == STATUS_SUCCESS );



      FLASH_DRV_Init(&Flash1_InitConfig0,&flashSSDConfig);
#endif


    /* 2020.03.17 分區這個函數必須使用
     * 選配分出記憶體分區段
     * uEEEDataSizeCode              FCCOB4  0X2選擇4K 的EEPROM空間
     * uDEPartitionCode              FCCOB5  0x8選擇64K 的EEPROM空間
     * uCSEcKeySize                  FCCOB1  CSEc加密服務選項  無
     * uSFE                          FCCOB2  僅驗證屬性關閉
     * flexRamEnableLoadEEEData      FCCOB3  0 複位期間是否加載資料  加載
     * */
     ret=FLASH_DRV_DEFlashPartition(&flashSSDConfig,0x2,0x4,0x0,false,true);
      DEV_ASSERT(STATUS_SUCCESS==ret);

      FLASH_DRV_Init(&Flash1_InitConfig0,&flashSSDConfig);

      /* 2020.03.17
           * 選配分出記憶體分區段
           * flexRamFuncCode   FCCOB1   EEE_ENABLE 使能FlexRAM 模拟EEPROM
           * byteOfQuickWrite  FCCOB4 FCCOB5
           * pEEPROMStatus     EEPROM狀态  結構體中三個狀态
           * */
      FLASH_DRV_SetFlexRamFunction(&flashSSDConfig,EEE_ENABLE,0x00,NULL);
      DEV_ASSERT(STATUS_SUCCESS==ret);


#if 1

       /**嘗試寫單個位元組到EEPROM的記憶體中**/
      /* Try to write data to EEPROM if FlexRAM is configured as EEPROM */
          if (flashSSDConfig.EEESize != 0u)
          {
              address = flashSSDConfig.EERAMBase;     //1400 0000
              size = sizeof(uint32_t);
              //sourceBuffer[0u] = 0x01;
              ret = FLASH_DRV_EEEWrite(&flashSSDConfig, address, 1, sourceBuffer);
              DEV_ASSERT(STATUS_SUCCESS == ret);


#if 1
              /* Verify the written data */
              if(sourceBuffer[0] != *((uint8_t *)address))
              {
                  /* Failed to write data to EEPROM */
                  exit_code = 1u;
                  return exit_code;
              }
#endif

#if 0
              /* Try to update one byte in an EEPROM address which isn't aligned */
              address = flashSSDConfig.EERAMBase + 1u;
              size = sizeof(uint8_t);
              //sourceBuffer[1u] = 0x11u;
              ret = FLASH_DRV_EEEWrite(&flashSSDConfig, address, 1, sourceBuffer+1);
              DEV_ASSERT(STATUS_SUCCESS == ret);



              /* Then verify */
              if (sourceBuffer[1u] != *(uint8_t *)address)
              {
                  /* Failed to update data to EEPROM */
                  exit_code = 1u;
                  return exit_code;
              }
#endif

              /**實作向FlexRAM模拟EEPROM的第四個位元組實作刷寫更新**/

              address = flashSSDConfig.EERAMBase+4;     //1400 0000
              size = sizeof(uint32_t);
              //sourceBuffer[2u] = 0x22u;
              /*如果位址讀出的資料   不等于sourceBuffer5的資料 則更新資料*/
              if (sourceBuffer[4u] != *(uint8_t *)address)
              {
            	  sourceBuffer[4u]=(*(uint8_t *)address)+1;
            	  sourceReadBuffer[4]=sourceBuffer[4u];
              }
              else if(0==*(uint8_t *)address)
              {
            	  sourceBuffer[4u]=(*(uint8_t *)address)+1;
            	  sourceReadBuffer[4]=sourceBuffer[4u];
              }

              ret = FLASH_DRV_EEEWrite(&flashSSDConfig, address, 1, sourceBuffer+4);
              DEV_ASSERT(STATUS_SUCCESS == ret);

#if 1
              /* Verify the written data */
              if (sourceReadBuffer[4] != *(uint8_t *)address)
              {
                  /* Failed to write data to EEPROM */
                  exit_code = 1u;
                  return exit_code;
              }
#endif

              /**嘗試寫多個位元組到EEPROM的記憶體中**/
#if 1
              address = flashSSDConfig.EERAMBase+0x10;     //1400 0000
              size = sizeof(sourceReadBuffer)/sizeof(sourceReadBuffer[0]);
              ret = FLASH_DRV_EEEWrite(&flashSSDConfig, address, size, sourceReadBuffer);
              DEV_ASSERT(STATUS_SUCCESS == ret);


              /* Verify the written data */
              if (sourceReadBuffer[0u] != *(uint8_t *)address)
              {
                  /* Failed to write data to EEPROM */
                  exit_code = 1u;
                  return exit_code;
              }
#endif
          }
#endif



  /* Write your code here */


  /* For example: for(;;) { } */

  /*** Don't write any code pass this line, or it will be deleted during code generation. ***/
  /*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/
  #ifdef PEX_RTOS_START
    PEX_RTOS_START();                  /* Startup of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of RTOS startup code.  ***/
  /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
  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!!! ***/


START_FUNCTION_DEFINITION_RAMSECTION
  void CCIF_Callback(void)
  {
      /* Enable interrupt for Flash Command Complete */
      if ((FTFx_FCNFG & FTFx_FCNFG_CCIE_MASK) == 0u)
      {
          FTFx_FCNFG |= FTFx_FCNFG_CCIE_MASK;
      }
  }
  END_FUNCTION_DEFINITION_RAMSECTION


void CCIF_Handler(void)
{
    /* Disable Flash Command Complete interrupt */  // 禁用 flash指令完成中斷
    FTFx_FCNFG &= (~FTFx_FCNFG_CCIE_MASK);

    return;
}
/* END main */
/*!
** @}
*/
           

主要還是借鑒了S32KDS生成的Demo例程中的具體操作流程。然後就可以實作指定的記憶體讀寫,效果如下。

第一次刷寫   可以看到0x14000005 資料為00  (這個記憶體空間的讀取是從右往左,低位元組到高位元組)

S32K模拟EEPROM實作單位元組和多位元組的寫入,并實作在一個位址處更新刷寫次數

第二次刷寫  可以看到0x14000005 資料為01

S32K模拟EEPROM實作單位元組和多位元組的寫入,并實作在一個位址處更新刷寫次數