I have an old, very used SD card that occasionally fails. When this happens, my I/O Manager’s fnWriteBlocks returns FF_ERR_IOMAN_DRIVER_FATAL_ERROR | FF_ERRFLAG. This often leads to a HardFault. Chasing down this error path, I think I see a problem in FF_WritePartial:
pxFile->pucBufferis allocated inprvAllocFileHandle:
pxFile->pucBuffer = ( uint8_t * ) ffconfigMALLOC( pxIOManager->usSectorSize );
where pxIOManager->usSectorSize is 512.
FF_WritePartialis called withulCount4096FF_WritePartialdoes
memcpy( pxFile->pucBuffer + ulRelBlockPos, pucBuffer, ulCount );
which winds up clobbering various things on the heap.
In this scenario, FF_WritePartial() at ff_file.c:2,166 has:
pxFile FF_FILE * 0x2000c988 <ucHeap+47644>
pxFile@entry FF_FILE * 0x2000c988 <ucHeap+47644>
pxIOManager FF_IOManager_t * 0x2000a5b8 <ucHeap+38476>
ulFileSize uint32_t 16384
ulObjectCluster uint32_t 113548
ulChainLength uint32_t 1
ulCurrentCluster uint32_t 0
ulAddrCurrentCluster uint32_t 113548
ulEndOfChain uint32_t 268435455
ulFilePointer uint32_t 16384
ulDirCluster uint32_t 106017
ulValidFlags uint32_t 0
pucBuffer uint8_t * 0x2000c9c8 <ucHeap+47708> ""
ucState uint8_t 0 '\0'
ucMode uint8_t 26 '\032'
usDirEntry uint16_t 83
pxNext struct _FF_FILE * 0x0
ulItemLBA uint32_t 7282794
ulRelBlockPos uint32_t 0
ulRelBlockPos@entry uint32_t 0
ulCount uint32_t 4096
ulCount@entry uint32_t 4096
It is called from FF_Write() at ff_file.c:2,465 with:
ulBytesLeft uint32_t 4096
nBytesWritten uint32_t 0
pxIOManager FF_IOManager_t * 0x2000a5b8 <ucHeap+38476>
xError FF_Error_t 0
pxFile FF_FILE * 0x2000c988 <ucHeap+47644>
ulElementSize uint32_t 1
ulElementSize@entry uint32_t 1
ulCount uint32_t 4096
ulCount@entry uint32_t 4096
which is called from ff_fwrite() at ff_stdio.c:398 with:
xSize size_t 1
xSize@entry size_t 1
xItems size_t 4096
xItems@entry size_t 4096
The problem is easy to recreate simply by modifying fnWriteBlocks to occasionally return an error.