在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 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);
}
长电科技实现4nm工艺制程手机芯片封装
LED舞台误区方案
HTC因侵犯Ipcom专利被禁止在英国销售手机
奎芯科技获超亿元首轮融资 莱迪思加入OPC基金会
一期性价比高,音质好的蓝牙耳机,实测好评推荐
I.MXRT FreeRTOS环境下擦写外部Flash
干货 | 氮化镓GaN驱动器的PCB设计策略概要
电源滤波器有用吗?该怎么选择呢?
热处理生产线淬火技术策略的设计与通讯
晶圆制造重镇遇地震,对半导体产业影响几何?
无可替代的封装技术LTCC——工艺及设备篇
PLC工控组态软件有哪些?
巡检机器人替代消防工作势在必行!
浅析2012年下半年LED背光市场
iOS11测试版正式首发:苹果iOS11预览版Beta1固件下载大全,iOS10.3.3公测版推送只为阻拦iOS10.2越狱和iOS10.3越狱?
关于中兴通讯推出的中兴骐骥系列Wi-Fi 6路由器浅解
线路板加工技术简介
3.7v升压5v电路图分享
华为Watch GT 2搭载全新麒麟A1芯片即将在印度出售
变频器凝露的危害_变频器凝露的处理办法