我正在STM32 G431Rb内部闪存上移植LittleFS。当我在主功能上读写文件时,一切都还可以。但当我在任务中写一些东西时,系统会被困在osdlelay上。
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
int i = 0;
for(;;)
{
ULOG_TRACE("Trace count = %d",i);
i++;
osDelay(5);
}
/* USER CODE END 5 */
}
在ULOG_TRACE函数中,我调用了lfs_fs_write函数。lfs_fs_write函数调用HAL_FLASHEx_Erase和HAL_FLASH_Prog。
static FLASH_EraseInitTypeDef EraseInitStruct;
int stm32_interl_flash_block_erase(const struct lfs_config *c, lfs_block_t block)
{
uint32_t PageError;
__disable_irq();
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP |
FLASH_FLAG_OPERR |
FLASH_FLAG_PROGERR |
FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR |
FLASH_FLAG_SIZERR |
FLASH_FLAG_PGSERR |
FLASH_FLAG_MISERR );
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.Banks = FLASH_BANK_1;
EraseInitStruct.Page = FS_BASE_PAGE_START + block;
EraseInitStruct.NbPages = 1;
if (HAL_FLASHEx_Erase(&EraseInitStruct,&PageError)!= HAL_OK){
__enable_irq();
return HAL_FLASH_GetError();
}
HAL_FLASH_Lock();
__enable_irq();
return 0;
}
int stm32_interl_flash_block_prog(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size)
{
__disable_irq();
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP |
FLASH_FLAG_OPERR |
FLASH_FLAG_PROGERR |
FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR |
FLASH_FLAG_SIZERR |
FLASH_FLAG_PGSERR |
FLASH_FLAG_MISERR );
uint32_t dest_addr = FS_BASE_ADDR + c->block_size*block +off;
uint64_t *pSrc = (uint64_t*)buffer;
uint32_t write_size = 0;
while(write_size < size){
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,dest_addr,*(pSrc)) != HAL_OK){
HAL_FLASH_Lock();
__enable_irq();
return HAL_FLASH_GetError();
}
pSrc++;
dest_addr += 8;
write_size += 8;
}
HAL_FLASH_Lock();
__enable_irq();
return 0;
}
我在谷歌上搜索了这些问题,有些人说问题是当我擦除或编程内部闪存时,任务计划中断。但我添加了disable_irq,它也有问题。
使用osKernelSuspend((和osKernelResume((停止并继续线程调度。
进一步检查所有返回代码,同样来自HAL_FLASH_Unlock。
闪存外设在STM32控制器系列上有点令人讨厌。如果出现问题,要么是访问地址不对齐、越界,要么是简单的访问顺序不正确——外围设备设置了错误位,HAL函数不再运行。您已经清除了错误标志。我曾经体验过在HAL_FLASH_Program之后检查和清除错误标志总是一个好主意。
PS:如果你的代码真的卡在osDelay中,那么你的cmsis os调度程序中断没有运行,或者调度程序被禁用/停止。
您没有指定代码被阻塞的时间,也没有指定为什么您认为它被阻塞在osDelay中,但这里有一个猜测:
如果在执行代码的同一闪存库中写入或擦除,则代码将停止,直到操作完成。这将阻止所有任务和所有中断,无论它们是打开还是关闭。这是因为在闪存写入或擦除时,无法从中提取任何指令。如果一些指令已经被预取,则它们可能仍在执行。
如果你能够使用双库模式,你可以在从另一个库执行的同时写入一个库,但我认为128kB部分可能只支持单库闪存,其他部分可能默认禁用双库。