当前,我正在尝试在正在使用的微控制器的闪存上写一个短字符串。目的是使程序将固件版本写入特定的地址,以便引导加载程序可以读取该版本并检查是否有更新。恩智浦提供的驱动程序示例似乎可以正常工作(我可以读写该变量)。但是,当我将此代码放在程序上时,运行kStatus_FTFx_accessError
和下一个函数时出现错误103 flaSH_Erase
。据我了解,这意味着我设置的地址不正确。
这是我的内存映射(链接文件):
MEMORY
{
m_interrupts (RX) : ORIGIN = 0x00000000,LENGTH = 0x00000400
m_flash_config (RX) : ORIGIN = 0x00000400,LENGTH = 0x00002000
m_text (RX) : ORIGIN = 0x00005000,LENGTH = 0x001FFBF0
m_data (RW) : ORIGIN = 0x1FFF0000,LENGTH = 0x00030000
m_data_2 (RW) : ORIGIN = 0x20000000,LENGTH = 0x00030000
}
我正在运行的功能:
#include "flashStorage.h"
#include "fsl_device_registers.h"
#include "fsl_debug_console.h"
#include "board.h"
#include "clock_config.h"
#include "fsl_flash.h"
#if defined(FSL_FEATURE_HAS_L1CACHE) && FSL_FEATURE_HAS_L1CACHE
#include "fsl_cache.h"
#endif /* FSL_FEATURE_HAS_L1CACHE */
#include "pin_mux.h"
#define BUFFER_LEN 4
/*! @brief flash driver Structure */
static flash_config_t s_flashDriver;
/*! @brief flash cache driver Structure */
static ftfx_cache_config_t s_cacheDriver;
/*! @brief Buffer for program */
static uint32_t s_buffer[BUFFER_LEN];
/*! @brief Buffer for readback */
static uint32_t s_buffer_rbc[BUFFER_LEN];
/***********************************************************************/
/* LOCAL FUNCTION PROTOTYPES */
/***********************************************************************/
/***********************************************************************/
/* GLOBAL FUNCTIONS */
/***********************************************************************/
void flaSH_WriteflashMemory(void)
{
ftfx_security_state_t securityStatus = kFTFx_SecurityStateNotSecure; /* Return protection status */
status_t result; /* Return code from each flash driver function */
uint32_t destAdrss; /* Address of the target location */
uint32_t i,failAddr,failDat;
uint32_t pflashBlockBase = 0;
uint32_t pflashTotalSize = 0;
uint32_t pflashSectorSize = 0;
memset(&s_flashDriver,sizeof(flash_config_t));
memset(&s_cacheDriver,sizeof(ftfx_cache_config_t));
result = flaSH_Init(&s_flashDriver);
if (kStatus_FTFx_Success != result)
{
PRINTF("error " ); //error_trap();
//error_trap();
}
/* Setup flash cache driver structure for device and initialize variables. */
result = FTFx_CACHE_Init(&s_cacheDriver);
if (kStatus_FTFx_Success != result)
{
PRINTF("error " ); //error_trap();
//error_trap();
}
/* Get flash properties*/
flaSH_GetProperty(&s_flashDriver,kflaSH_PropertyPflash0BlockBaseAddr,&pflashBlockBase);
flaSH_GetProperty(&s_flashDriver,kflaSH_PropertyPflash0TotalSize,&pflashTotalSize);
flaSH_GetProperty(&s_flashDriver,kflaSH_PropertyPflash0SectorSize,&pflashSectorSize);
/* Check security status. */
result = flaSH_GetSecurityState(&s_flashDriver,&securityStatus);
if (kStatus_FTFx_Success != result)
{
PRINTF("error " ); //error_trap();
//error_trap();
}
/* Test pflash basic opeation only if flash is unsecure. */
if (kFTFx_SecurityStateNotSecure == securityStatus)
{
/* Pre-preparation work about flash Cache/Prefetch/Speculation. */
FTFx_CACHE_ClearCachePrefetchSpeculation(&s_cacheDriver,true);
/* Debug message for user. */
/* Erase several sectors on upper pflash block where there is no code */
PRINTF("\r\n Erase a sector of flash");
/* In case of the protected sectors at the end of the pflash just select
the block from the end of pflash to be used for operations
SECTOR_INDEX_FROM_END = 1 means the last sector,SECTOR_INDEX_FROM_END = 2 means (the last sector - 1) ...
in case of FSL_FEATURE_flaSH_HAS_PflaSH_BLOCK_SWAP it is
SECTOR_INDEX_FROM_END = 1 means the last 2 sectors with width of 2 sectors,SECTOR_INDEX_FROM_END = 2 means the last 4 sectors back
with width of 2 sectors ...
*/
#ifndef SECTOR_INDEX_FROM_END
#define SECTOR_INDEX_FROM_END 1U
#endif
destAdrss = 0x2400 ;
result = flaSH_Erase(&s_flashDriver,destAdrss,pflashSectorSize,kFTFx_ApiEraseKey);
if (kStatus_FTFx_Success != result)
{
PRINTF("error " ); //error_trap();
//error_trap();
}
/* Verify sector if it's been erased. */
result = flaSH_VerifyErase(&s_flashDriver,kFTFx_MarginValueUser);
if (kStatus_FTFx_Success != result)
{
PRINTF("error " ); //error_trap();
//error_trap();
}
/* Print message for user. */
PRINTF("\r\n Successfully Erased Sector 0x%x -> 0x%x\r\n",(destAdrss + pflashSectorSize));
/* Print message for user. */
PRINTF("\r\n Program a buffer to a sector of flash ");
/* Prepare user buffer. */
for (i = 0; i < BUFFER_LEN; i++)
{
s_buffer[i] = 3;
}
/* Program user buffer into flash*/
result = flaSH_Program(&s_flashDriver,(uint8_t *)s_buffer,sizeof(s_buffer));
if (kStatus_FTFx_Success != result)
{
PRINTF("error " ); //error_trap();
//error_trap();
}
/* Verify programming by Program Check command with user margin levels */
result = flaSH_VerifyProgram(&s_flashDriver,sizeof(s_buffer),(const uint8_t *)s_buffer,kFTFx_MarginValueUser,&failAddr,&failDat);
if (kStatus_FTFx_Success != result)
{
PRINTF("error " ); //error_trap();
}
for (uint32_t i = 0; i < BUFFER_LEN; i++)
{
s_buffer_rbc[i] = *(volatile uint32_t *)(destAdrss + i * 4);
if (s_buffer_rbc[i] != s_buffer[i])
{
// error_trap();
}
PRINTF("\r\n VALUES: %d,%d,%d ",s_buffer_rbc[0],s_buffer_rbc[1],s_buffer_rbc[2],s_buffer_rbc[3] );
}
/* Post-preparation work about flash Cache/Prefetch/Speculation. */
FTFx_CACHE_ClearCachePrefetchSpeculation(&s_cacheDriver,false);
#if defined(FSL_FEATURE_HAS_L1CACHE) && FSL_FEATURE_HAS_L1CACHE
L1CACHE_InvalidateCodeCache();
#endif /* FSL_FEATURE_HAS_L1CACHE */
#if defined(__DCACHE_PRESENT) && __DCACHE_PRESENT
/* Clean the D-Cache before reading the flash data*/
SCB_CleanInvalidateDCache();
#endif
}
else
{
PRINTF("\r\n Erase/Program operation will not be executed,as flash is SECURE!");
}
}
如何准备适合写入的存储器?或在哪里写一个合适的地址?我似乎不明白为什么我正在使用的内存地址不正确,因为它没有在内存映射中使用。
硬件和编译器:
- 微控制器:NXP开发的K66F开发板。
- Kinetis设计工作室IDE。
- 用于ARM嵌入式处理器的GNU工具(arm-none-eabi-gcc)