1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00
Earle F. Philhower, III 52d84b1ead
Add a CRC32 over progmem and ESP.checkFlashCRC (#6566)
* Add a CRC32 over progmem and ESP.checkFlashCRC

Automatically embed a CRC32 of the program memory (including bootloader
but excluding any filesystems) in all images in unused space in the
bootloader block.

Add a call, ESP.checkFlashCRC() which returns false if the calculated
CRC doesn't match the one stored in the image (i.e. flash corruption).

Fixes #4165

* Add example that corrupts itself, comments

Show CRC checking catch a 1-bit error in program code by corrupting a
large array, and then return it to clean and verify the CRC matches once
again.

Add comments to the CRC check routine

Clean up pylint complaints on crc32bin.py

* Check linker script for CRC space in bootsector

Add an assertion in the eboot linker file to guarantee that we have at
least 8 bytes of unused space at the end of the boot sector to patch in
the CRC.  If not, the eboot link will fail.

* Add note about what to do if CRC check fails

Per discussion with @d-a-v.

When the CRC check fails, you could *try* to do certain things (but may
not succeed since there is known flash corruption at that point).  List
a few ideas for application authors.

* Only single, flash/ram friendly crc32() function

* Combine the CRC calc and bin generation in 1 step

Per discussion w/@mcspr, combine the CRC calculation with the binary
generation, removing the additional build step.
2019-12-20 14:38:35 -08:00

46 lines
1.6 KiB
C++

/*
Demonstrate CRC check passing and failing by simulating a bit flip in flash.
WARNING!!! You would never want to actually do this in a real application!
Released to the Public Domain by Earle F. Philhower, III <earlephilhower@yahoo.com>
*/
extern "C" {
#include "spi_flash.h"
}
// Artificially create a space in PROGMEM that fills multipe sectors so
// we can corrupt one without crashing the system
const int corruptme[SPI_FLASH_SEC_SIZE * 4] PROGMEM = { 0 };
void setup() {
Serial.begin(115200);
Serial.printf("Starting\n");
Serial.printf("CRC check: %s\n", ESP.checkFlashCRC() ? "OK" : "ERROR");
Serial.printf("...Corrupting a portion of flash in the array...\n");
uint32_t ptr = (uint32_t)corruptme;
// Find a page aligned spot inside the array
ptr += 2 * SPI_FLASH_SEC_SIZE;
ptr &= ~(SPI_FLASH_SEC_SIZE - 1); // Sectoralign
uint32_t sector = ((((uint32_t)ptr - 0x40200000) / SPI_FLASH_SEC_SIZE));
// Create a sector with 1 bit set (i.e. fake corruption)
uint32_t *space = (uint32_t*)calloc(SPI_FLASH_SEC_SIZE, 1);
space[42] = 64;
// Write it into flash at the spot in question
spi_flash_erase_sector(sector);
spi_flash_write(sector * SPI_FLASH_SEC_SIZE, (uint32_t*)space, SPI_FLASH_SEC_SIZE);
Serial.printf("CRC check: %s\n", ESP.checkFlashCRC() ? "OK" : "ERROR");
Serial.printf("...Correcting the flash...\n");
memset(space, 0, SPI_FLASH_SEC_SIZE);
spi_flash_erase_sector(sector);
spi_flash_write(sector * SPI_FLASH_SEC_SIZE, (uint32_t*)space, SPI_FLASH_SEC_SIZE);
Serial.printf("CRC check: %s\n", ESP.checkFlashCRC() ? "OK" : "ERROR");
}
void loop() {
}