reading flash with ECC errors
Posted: Sat Feb 09, 2019 1:00 am
I hope nobody minds me posting so much here ...
I've finally got my bootloader working correctly on the H743. I ran across a really interesting issue that I thought I'd share in case it bites anyone else.
The H743 flash has ECC, and also has a restriction that you can only program on 32 byte boundaries with exactly 32 bytes at a time. The ref manual discusses a way to get around that, using the FLASH_CR_FW bit to force a write of a partial line, although it gives some (vague) information about why this isn't a good idea. I discovered that it *really* is a bad idea.
My (USB based) bootloader keeps back the first word of the firmware when flashing, then writes the first word once the CRC passes. This is used to prevent trying to boot a partially flashed fw, in case the user unplugs USB while flashing. I used the CR_FW bit to implement this partial line write.
The problem is that you can end up with the 32 byte line having an ECC error, and that ECC error persists across power cycles. Even worse, when you try to read from that line you get a "double ECC error" and a hard fault.
So when this went bad the board went into a hard fault on startup, as at startup it reads the first words of the fw. Even if you re-flash you get a hard fault as the bootloader tries to read the flash words to check if it can skip a sector erase (if all words in the sector are 0xffffffff).
What I'd really like to do is have a function which probes a word in flash and checks if it would give an ECC error if you read it, or asks if a particular line has an ECC error. I haven't worked out a way to do that yet (although I suspect there is a way).
For now I've re-jigged the bootloader to only ever do 32 byte aligned writes, using a different strategy for checking for partial flash. It's working nicely, but this cost me a lot more time to understand than I would have liked.
Here is out (rather ugly, sorry) flash driver in case anyone is interested:
https://github.com/tridge/ardupilot/blo ... on/flash.c
and the bootloader is here:
https://github.com/tridge/ardupilot/tre ... Bootloader
I've finally got my bootloader working correctly on the H743. I ran across a really interesting issue that I thought I'd share in case it bites anyone else.
The H743 flash has ECC, and also has a restriction that you can only program on 32 byte boundaries with exactly 32 bytes at a time. The ref manual discusses a way to get around that, using the FLASH_CR_FW bit to force a write of a partial line, although it gives some (vague) information about why this isn't a good idea. I discovered that it *really* is a bad idea.
My (USB based) bootloader keeps back the first word of the firmware when flashing, then writes the first word once the CRC passes. This is used to prevent trying to boot a partially flashed fw, in case the user unplugs USB while flashing. I used the CR_FW bit to implement this partial line write.
The problem is that you can end up with the 32 byte line having an ECC error, and that ECC error persists across power cycles. Even worse, when you try to read from that line you get a "double ECC error" and a hard fault.
So when this went bad the board went into a hard fault on startup, as at startup it reads the first words of the fw. Even if you re-flash you get a hard fault as the bootloader tries to read the flash words to check if it can skip a sector erase (if all words in the sector are 0xffffffff).
What I'd really like to do is have a function which probes a word in flash and checks if it would give an ECC error if you read it, or asks if a particular line has an ECC error. I haven't worked out a way to do that yet (although I suspect there is a way).
For now I've re-jigged the bootloader to only ever do 32 byte aligned writes, using a different strategy for checking for partial flash. It's working nicely, but this cost me a lot more time to understand than I would have liked.
Here is out (rather ugly, sorry) flash driver in case anyone is interested:
https://github.com/tridge/ardupilot/blo ... on/flash.c
and the bootloader is here:
https://github.com/tridge/ardupilot/tre ... Bootloader