@@ -417,12 +417,23 @@ void set_flashchip_and_check_erase_config(void) {
417
417
PRINT_FLASHCHIP ();
418
418
/* Since Flash code has been mapped for execution, we can just address the
419
419
flash image header located at the beginning of flash as iCACHE like memory. */
420
- /* the tool chain update is optomizing out my 32-bit access to an 8-bit
421
- unless I use volatile */
422
- const uint32_t imghdr_4bytes = *((const uint32_t volatile *)0x40200000 );
423
- const image_header_t *partial_imghdr = (const image_header_t *)&imghdr_4bytes;
420
+ const uint32_t *icache_flash = (const uint32_t *)0x40200000u ;
421
+ union { // to comply with strict-aliasing rules
422
+ image_header_t hdr; // total size 8 bytes
423
+ uint32_t u32; // we only need the 1st 4 bytets
424
+ } imghdr_4bytes;
425
+ // read first 4 byte (magic byte + flash config)
426
+ imghdr_4bytes.u32 = *icache_flash;
424
427
uint32_t old_flash_size = flashchip->chip_size ;
425
- flashchip->chip_size = esp_c_magic_flash_chip_size ((partial_imghdr->flash_size_freq >> 4 ) & 0x0F );
428
+ /*
429
+ ICACHE memory read requires aligned word transfers. Because
430
+ imghdr_4bytes.hdr.flash_size_freq is a byte value, the GCC 10.3 compiler
431
+ tends to optimize out our 32-bit access for 8-bit access. If we reference
432
+ the 32-bit word from Extended ASM, this persuades the compiler to keep the
433
+ 32-bit register load and extract the 8-bit value later.
434
+ */
435
+ asm volatile (" # imghdr_4bytes.u32 => %0" ::" r" (imghdr_4bytes.u32 ));
436
+ flashchip->chip_size = esp_c_magic_flash_chip_size (imghdr_4bytes.hdr .flash_size_freq >> 4 );
426
437
PRINT_FLASHCHIP ();
427
438
if (flashchip->chip_size ) {
428
439
check_and_erase_config ();
0 commit comments