MCAL接口写完FLS后,偶发性出现一直不空闲问题
-
#define FLASH_WRITE_UNIT ( 32 ) // 固定写入单位 #define FLASH_TIMEOUT ( 10000000 ) // 超时时间 bool bsw_fls_write_pflash1_1mb( uint32_t AddrOffset, const uint8_t* data, uint32_t len ) { uint32_t startAddress = 0; uint32_t alignedLen = 0; uint32_t i = 0; uint32_t chunkSize = 0; uint32_t timeout = 0; uint8_t alignedData[ FLASH_WRITE_UNIT ] = { 0xFF }; // 预填充 0xFF uint8_t readBuffer[ FLASH_WRITE_UNIT ] = { 0 }; // 读取缓存初始化 if ( data == NULL || len == 0 ) { return false; } startAddress = Fls_Config.SectorList[ FlsConf_FlsConfigSet_PFLASH1_1MB ].SectorStartAddress + AddrOffset; alignedLen = ( ( len + ( FLASH_WRITE_UNIT - 1 ) ) / FLASH_WRITE_UNIT ) * FLASH_WRITE_UNIT; // 向上取整到 32 字节对齐 // 按 32 字节批量写入 for ( i = 0; i < alignedLen; i += FLASH_WRITE_UNIT ) { chunkSize = ( i + FLASH_WRITE_UNIT <= len ) ? FLASH_WRITE_UNIT : ( len - i ); memset( alignedData, 0xFF, FLASH_WRITE_UNIT ); // 先填充 0xFF memcpy( alignedData, data + i, chunkSize ); // 复制实际数据 // 超时等待 Flash 空闲 timeout = FLASH_TIMEOUT; while ( --timeout > 0 ) { Fls_MainFunction( ); if ( Fls_GetStatus( ) == MEMIF_IDLE ) { break; } if ( timeout == 0 ) { return false; } } // 写入 Flash timeout = 50; while ( --timeout > 0 ) { if ( !Fls_Write( startAddress + i, alignedData, FLASH_WRITE_UNIT ) ) { break; } if ( timeout == 0 ) { return false; // 写入失败 } }; // 超时等待 Flash 空闲 timeout = FLASH_TIMEOUT; while ( --timeout > 0 ) { Fls_MainFunction( ); if ( Fls_GetStatus( ) == MEMIF_IDLE ) { break; } if ( timeout == 0 ) { return false; } } memset( readBuffer, 0, FLASH_WRITE_UNIT ); // 确保读取缓冲区清空 timeout = 50; while ( --timeout > 0 ) { if ( !Fls_Read( startAddress + i, readBuffer, FLASH_WRITE_UNIT ) ) { break; } if ( timeout == 0 ) { return false; // 写入失败 } }; // 等待读取完成 timeout = FLASH_TIMEOUT; while ( --timeout > 0 ) { Fls_MainFunction( ); if ( Fls_GetStatus( ) == MEMIF_IDLE ) { break; } if ( timeout == 0 ) { return false; } } // 进行数据比对 if ( memcmp( readBuffer, alignedData, FLASH_WRITE_UNIT ) != 0 ) { return false; // 校验失败 } } return true; }
以上是我写MCU内部FLS的功能代码,作用是把数据写入1mb的pflash1,以实现A/B SWAP。
现在发现,在调用完Fls_Read后,在等待读取完成代码段中,Fls_GetStatus( )一直不返回MEMIF_IDLE,导致任务卡顿。timeout = 50; while ( --timeout > 0 ) { if ( !Fls_Read( startAddress + i, readBuffer, FLASH_WRITE_UNIT ) ) { break; } if ( timeout == 0 ) { return false; // 写入失败 } }; // 等待读取完成 timeout = FLASH_TIMEOUT; while ( --timeout > 0 ) { Fls_MainFunction( ); if ( Fls_GetStatus( ) == MEMIF_IDLE ) { break; } if ( timeout == 0 ) { return false; } }
请问是我这个函数代码的逻辑有问题吗?
-
正常情况下这个逻辑是没有问题的,但是你们这个写之前有擦除操作吗?代码里面没有体现擦除的动作,这个一定要求有。另外就是你可以在读取之前增加一个GetResult, 检查一下前面一次写的操作是否成功。按照你的现象描述,可能是因为写flash过程掉电,从而产生了ECC错误,上电之后如果没有擦除再写,那么所有写都是失败的,再读到产生ECC错误的位置,就会导致MCU进入busfault.
-
houjun_xiao 每次写之前都有擦除操作,也会判断是否空闲。现在代码逻辑上,读取之前已经有一个GetResult了。这个ECC错误,是只能通过擦除操作来清除吗?
-
单Bit的错误硬件自动纠错;多Bit的ECC错误,只能通过擦除才能清除。你可以先排查是不是因为这个问题导致的,建议在擦除和写完成后都增加一个GetResult判断操作结果。理论上正常的写入或擦除是不会出现ECC错误。
-
houjun_xiao 好的,我们按这个方法试试,谢谢!
发帖前请查看
帮助没办法联网的电脑使用YCT
帮助改进和优化YT CONFIG TOOL,有机会抽取YTM32B1ME0 EVB哦...