电子说
在FreeRTOS环境下,如果外部擦写 Flash,禁用指令缓存以避免在多个任务中使用来自Flash 的分支预测和应用程序同步操作 Flash的缓存预加载指令。因为代码是XIP,所以向量表也在Flash 中。所以,当发生中断时,内核将读取此中断向量表。如果同时,Flash闪存被编程写入,读取操作将失败。用户通过禁用中断来保护关键代码,以避免这种情况。
使用 "taskENTER/EXIT_CRITICAL()" 函数,最后它会调用如下图这个函数vPortRaiseBASEPRI。该函数只能禁用优先级低于configMAX_SYSCALL_INTERRUPT_priority的中断,这可以确保系统仍然可以工作。因此,需要检查所有其他外设中断的优先级,比如LCDIPv2_IRQn,LPUART,LPSPI 等等。要确保优先级低于configMAX_SYSCALL_INTERRUPT_priority,或将configMAX_SYSCALL_INTERROPT_priority配置为更高的优先级。
不需要逐一禁用所有IRQ。因此,如果使用上述方式还有问题,请尝试如下API:
__set_PRIMASK(1);//关闭总中断
//擦,写,读 Flash//
__set_PRIMASK(0);//开启总中断
参考示例代码:
/* FreeRTOS kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
/* Freescale includes. */
#include "fsl_device_registers.h"
#include "fsl_debug_console.h"
#include "fsl_flexspi.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "app.h"
#include "fsl_common.h"
/* Task priorities. */
#define hello_task_PRIORITY (configMAX_PRIORITIES - 2)
#define flash_operation_task_PRIORITY (configMAX_PRIORITIES - 1)
static void hello_task(void *pvParameters);
static void flash_operation_task(void *pvParameters);
status_t flexspi_nor_flash_read_sector(FLEXSPI_Type *base, uint32_t address, const uint32_t *src, size_t leng);
extern status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address);
extern status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src);
extern status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint8_t *vendorId);
extern status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base);
extern void flexspi_nor_flash_init(FLEXSPI_Type *base);
extern void flexspi_clear_buffer(FLEXSPI_Type *base);
flexspi_device_config_t deviceconfig = {
.flexspiRootClk = 12000000,
.flashSize = FLASH_SIZE,
.CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle,
.CSInterval = 2,
.CSHoldTime = 3,
.CSSetupTime = 3,
.dataValidTime = 0,
.columnspace = 0,
.enableWordAddress = 0,
.AWRSeqIndex = 0,
.AWRSeqNumber = 0,
.ARDSeqIndex = NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD,
.ARDSeqNumber = 1,
.AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,
.AHBWriteWaitInterval = 0,
};
constuint32_tcustomLUT[CUSTOM_LUT_LENGTH]={
/* Normal read mode -SDR */
[4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x03, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
[4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL + 1] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
/* Fast read mode - SDR */
[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x0B, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST + 1] = FLEXSPI_LUT_SEQ(
kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_1PAD, 0x08, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
/* Fast read quad mode - SDR */
[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xEB, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_4PAD, 0x18),
[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD + 1] = FLEXSPI_LUT_SEQ(
kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_4PAD, 0x06, kFLEXSPI_Command_READ_SDR, kFLEXSPI_4PAD, 0x04),
/* Read extend parameters */
[4 * NOR_CMD_LUT_SEQ_IDX_READSTATUS] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x81, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
/* Write Enable */
[4 * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x06, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
/* Erase Sector */
[4 * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xD7, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
/* Page Program - single mode */
[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x02, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE + 1] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
/* Page Program - quad mode */
[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x32, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD + 1] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_4PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
/* Read ID */
[4 * NOR_CMD_LUT_SEQ_IDX_READID] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x9F, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
/* Enable Quad mode */
[4 * NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x01, kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04),
/* Enter QPI mode */
[4 * NOR_CMD_LUT_SEQ_IDX_ENTERQPI] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x35, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
/* Exit QPI mode */
[4 * NOR_CMD_LUT_SEQ_IDX_EXITQPI] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_4PAD, 0xF5, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
/* Read status register */
[4 * NOR_CMD_LUT_SEQ_IDX_READSTATUSREG] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x05, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
/* Erase whole chip */
[4 * NOR_CMD_LUT_SEQ_IDX_ERASECHIP] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xC7, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
};
int main(void)
{
/* Init board hardware. */
BOARD_ConfigMPU();
BOARD_InitPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
PRINTF("Flash Operation on FreeRTOS in XIP Mode! ");
if (xTaskCreate(hello_task, "Hello_task", configMINIMAL_STACK_SIZE + 100, NULL, hello_task_PRIORITY, NULL) !=
pdPASS)
{
PRINTF("Task creation failed!. ");
while (1)
;
}
if (xTaskCreate(flash_operation_task, "flash_operation_task", configMINIMAL_STACK_SIZE + 800, NULL,
flash_operation_task_PRIORITY, NULL) != pdPASS)
{
PRINTF("Task creation failed!. ");
while (1)
;
}
vTaskStartScheduler();
for (;;)
;
}
static void hello_task(void *pvParameters)
{
for (;;)
{
PRINTF("Hello world. ");
/* delay 2s */
vTaskDelay(2 * configTICK_RATE_HZ);
}
}
static void flash_operation_task(void *pvParameters)
{
status_t status;
uint8_t vendorID = 0;
/*Programe Buffer must be 4 and 4's multiplier bytes alignment */
uint8_t *nor_program_buffer = pvPortMalloc(256);
if (NULL == nor_program_buffer)
{
PRINTF("nor_program_buffer memory allocation failed! ");
configASSERT(NULL);
}
uint8_t *nor_read_buffer = pvPortMalloc(256);
if (NULL == nor_read_buffer)
{
PRINTF("nor_read_buffer memory allocation failed! ");
configASSERT(NULL);
}
taskENTER_CRITICAL();
flexspi_nor_flash_init(EXAMPLE_FLEXSPI);
taskEXIT_CRITICAL();
/* Get vendor ID. */
status = flexspi_nor_get_vendor_id(EXAMPLE_FLEXSPI, &vendorID);
if (status != kStatus_Success)
{
PRINTF("Get Vendor ID Failure!");
configASSERT(NULL);
}
PRINTF("Flash Vendor ID: 0x%x ", vendorID);
/* Disable I cache to avoid cache pre-fatch instruction with branch prediction from flash and application operate flash synchronously in multi-tasks. */
#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
volatile bool ICacheEnableFlag = false;
/* Disable I cache. */
if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR))
{
SCB_DisableICache();
ICacheEnableFlag = true;
}
#endif /* __ICACHE_PRESENT */
/* Enter quad mode. */
taskENTER_CRITICAL();
status = flexspi_nor_enable_quad_mode(EXAMPLE_FLEXSPI);
taskEXIT_CRITICAL();
#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
if (ICacheEnableFlag)
{
/* Enable I cache. */
SCB_EnableICache();
ICacheEnableFlag = false;
}
#endif /* __ICACHE_PRESENT */
if (status != kStatus_Success)
{
configASSERT(NULL);
}
/* Erase sectors. */
PRINTF("Erasing Serial NOR over FlexSPI... ");
/* Disable I cache to avoid cache pre-fatch instruction with branch prediction from flash and application operae flash synchronously inmulti-tasks.*/
#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
/* Disable I cache. */
if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR))
{
SCB_DisableICache();
ICacheEnableFlag = true;
}
#endif /* __ICACHE_PRESENT */
taskENTER_CRITICAL();
status = flexspi_nor_flash_erase_sector(EXAMPLE_FLEXSPI, EXAMPLE_SECTOR * SECTOR_SIZE);
taskEXIT_CRITICAL();
#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
if (ICacheEnableFlag)
{
/* Enable I cache. */
SCB_EnableICache();
ICacheEnableFlag = false;
}
#endif /* __ICACHE_PRESENT */
if (status != kStatus_Success)
{
PRINTF("Erase sector failure ! ");
configASSERT(NULL);
}
/* Invalidate the D cache before reading data from QSPI Flash */
#if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN
DCACHE_InvalidateByRange(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE, FLASH_PAGE_SIZE);
#endif
memcpy(nor_read_buffer, (void *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE), FLASH_PAGE_SIZE);
for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++)
{
if (0xFF != nor_read_buffer[i])
{
PRINTF("Erase data - read out data value incorrect ! ");
configASSERT(NULL);
}
}
PRINTF("Sector Erase successfully ! ");
/* Program Sector */
for (uint16_t i = 0U; i < FLASH_PAGE_SIZE; i++)
{
nor_program_buffer[i] = i;
}
/* Clean program buffer to maker sure program data is valid before program execution for SDRAM target, because heap is cacheabe in SDRAM target.*/
#if defined(USE_SDRAM) && USE_SDRAM
#if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN
DCACHE_CleanByRange((uint32_t)nor_program_buffer, FLASH_PAGE_SIZE);
#endif
#endif
/* Disable I cache to avoid cache pre-fatch instruction with branch prediction from flash and application operate flash synchronously inmulti-tasks.*/
#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
/* Disable I cache. */
if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR))
{
SCB_DisableICache();
ICacheEnableFlag = true;
}
#endif /* __ICACHE_PRESENT */
taskENTER_CRITICAL();
status = flexspi_nor_flash_page_program(EXAMPLE_FLEXSPI, EXAMPLE_SECTOR * SECTOR_SIZE, (void *)nor_program_buffer);
taskEXIT_CRITICAL();
#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
if (ICacheEnableFlag)
{
/* Enable I cache. */
SCB_EnableICache();
ICacheEnableFlag = false;
}
#endif /* __ICACHE_PRESENT */
if (status != kStatus_Success)
{
PRINTF("Page program failure ! ");
configASSERT(NULL);
}
PRINTF("Page program successfully ! ");
/* clean the D cache before reading data from QSPI Flash */
#if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN
DCACHE_InvalidateByRange(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE, FLASH_PAGE_SIZE);
#endif
/* the below read sector API can be used in both Code in QSPI mode and Code in SRAM mode */
taskENTER_CRITICAL();
memcpy(nor_read_buffer, (void *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE), FLASH_PAGE_SIZE);
taskEXIT_CRITICAL();
PRINTF("Read Sector Content: ");
for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++)
{
PRINTF("%d, ", nor_read_buffer[i]);
}
PRINTF(" Flash operation done, suspend this task now. ");
/* Suspend itself */
vTaskSuspend(NULL);
}
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !