在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 andapplication 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);
}
審核編輯:湯梓紅
-
FlaSh
+關注
關注
10文章
1644瀏覽量
148755 -
中斷
+關注
關注
5文章
900瀏覽量
41792 -
程序
+關注
關注
117文章
3798瀏覽量
81457 -
函數
+關注
關注
3文章
4346瀏覽量
63012 -
FreeRTOS
+關注
關注
12文章
484瀏覽量
62414
原文標題:I.MXRT FreeRTOS 環境下擦寫外部 Flash
文章出處:【微信號:嵌入式 MCU,微信公眾號:嵌入式 MCU】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
為i.MXRT設計更新Segger J-Link Flash下載算法文件
i.MXRT系列FlexSPI驅動Flash頁編程執行時間
i.MXRT上使能NOR Flash的Continuous read模式在軟復位后無法正常啟動怎么解決?
IAR開發環境下i.MXRT的串行NOR Flash下載算法設計
i.MXRT上使能NOR Flash的Continuous read模式在軟復位后無法正常啟動問題的解決
使用PTPD/FreeRTOS和WIP-TCP/IP堆棧在i.MXRT上實現IEEE1588v2是我教程
淺析Keil MDK下串行Flash的下載算法設計
J-Link工具下i.MXRT的串行NOR Flash下載算法設計
Flash不支持SFDP,如何下載適用i.MXRT
痞子衡嵌入式:MCUXpresso IDE下使用J-Link下載算法在Flash調試注意事項(i.MXRT500為例)...
![痞子衡嵌入式:MCUXpresso IDE<b class='flag-5'>下</b>使用J-Link下載算法在<b class='flag-5'>Flash</b>調試注意事項(<b class='flag-5'>i.MXRT</b>500為例)...](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
痞子衡嵌入式:串行NOR Flash的Continuous read模式下軟復位后i.MXRT無法啟動問題解決方案之SW Reset...
![痞子衡嵌入式:串行NOR <b class='flag-5'>Flash</b>的Continuous read模式<b class='flag-5'>下</b>軟復位后<b class='flag-5'>i.MXRT</b>無法啟動問題解決方案之SW Reset...](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
i.MXRT上提升代碼執行性能的十八般武藝
擦寫Flash時一定不能開啟系統全局中斷嗎?
深入i.MXRT1050系列ROM中串行NOR Flash啟動初始化流程
![深入<b class='flag-5'>i.MXRT</b>1050系列ROM中串行NOR <b class='flag-5'>Flash</b>啟動初始化流程](https://file1.elecfans.com/web2/M00/89/26/wKgZomR5uauAK9srAAGCOI6Hoz4352.jpg)
評論