Sort out mapping of virtual <-> flash addresses.

The irom0_flash.bin file gets written to offset 0x40000 in flash. Said file
has the following layout

  | irom0 | text | data | rodata | chksum |

...so the previous approach of having a _flash_used_end symbol at the end of
the irom0 section no longer gives us an accurate view of how much of the flash
is used.
This commit is contained in:
Johny Mattsson 2016-06-24 15:40:48 +10:00
parent afbbeb4566
commit b3e8eddf14
4 changed files with 44 additions and 8 deletions

View File

@ -13,15 +13,22 @@ void cmn_platform_init(void)
// **************************************************************************** // ****************************************************************************
// Internal flash support functions // Internal flash support functions
#if defined(__ESP8266__)
// This symbol must be exported by the linker command file and must reflect the // This symbol must be exported by the linker command file and must reflect the
// TOTAL size of flash used by the eLua image (not only the code and constants, // TOTAL size of flash used by the eLua image (not only the code and constants,
// but also .data and whatever else ends up in the eLua image). FS will start // but also .data and whatever else ends up in the eLua image). FS will start
// at the next usable (aligned to a flash sector boundary) address after // at the next usable (aligned to a flash sector boundary) address after
// flash_used_size. // flash_used_size.
// extern char flash_used_size[];
extern char _flash_used_end[]; extern char _flash_used_end[];
#elif defined(__ESP32__)
/* This symbol must be exported by the linker command file and contain the
* size of all the sections packed into the irom0_flash.bin file, in order
* for us to find the end of used flash.
*/
extern char _irom0_bin_min_sz[];
#endif
// Helper function: find the flash sector in which an address resides // Helper function: find the flash sector in which an address resides
// Return the sector number, as well as the start and end address of the sector // Return the sector number, as well as the start and end address of the sector
static uint32_t flashh_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend ) static uint32_t flashh_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend )
@ -69,6 +76,7 @@ uint32_t platform_flash_get_num_sectors(void)
uint32_t platform_flash_get_first_free_block_address( uint32_t *psect ) uint32_t platform_flash_get_first_free_block_address( uint32_t *psect )
{ {
#if defined(__ESP8266__)
// Round the total used flash size to the closest flash block address // Round the total used flash size to the closest flash block address
uint32_t start, end, sect; uint32_t start, end, sect;
NODE_DBG("_flash_used_end:%08x\n", (uint32_t)_flash_used_end); NODE_DBG("_flash_used_end:%08x\n", (uint32_t)_flash_used_end);
@ -83,6 +91,17 @@ uint32_t platform_flash_get_first_free_block_address( uint32_t *psect )
*psect = sect; *psect = sect;
return start; return start;
} }
#elif defined(__ESP32__)
uint32_t flash_offs = IROM0_START_FLASH_ADDR + (uint32_t)_irom0_bin_min_sz;
uint32_t sect =
(flash_offs + INTERNAL_FLASH_SECTOR_SIZE-1)/INTERNAL_FLASH_SECTOR_SIZE;
++sect; /* compensate for various headers not counted in _irom0_bin_min_sz */
if (psect)
*psect = sect;
return sect * INTERNAL_FLASH_SECTOR_SIZE;
#endif
} }
uint32_t platform_flash_write( const void *from, uint32_t toaddr, uint32_t size ) uint32_t platform_flash_write( const void *from, uint32_t toaddr, uint32_t size )

View File

@ -55,8 +55,11 @@
#define INTERNAL_FLASH_SIZE ( (SYS_PARAM_SEC_START) * INTERNAL_FLASH_SECTOR_SIZE ) #define INTERNAL_FLASH_SIZE ( (SYS_PARAM_SEC_START) * INTERNAL_FLASH_SECTOR_SIZE )
// TODO: double-check flash mapped address /* Note: technically irom0 starts at +0x10, but that's not a page boundary! */
#define INTERNAL_FLASH_MAPPED_ADDRESS 0x40084000 #define IROM0_START_MAPPED_ADDR 0x40080000
#define IROM0_START_FLASH_ADDR 0x40000
// TODO: might need to revamp all this once cache windows fully understood
#define INTERNAL_FLASH_MAPPED_ADDRESS IROM0_START_MAPPED_ADDR
#if defined(FLASH_SAFE_API) #if defined(FLASH_SAFE_API)
#define flash_write flash_safe_write #define flash_write flash_safe_write

View File

@ -853,7 +853,7 @@ int platform_flash_erase_sector( uint32_t sector_id )
uint32_t platform_flash_mapped2phys (uint32_t mapped_addr) uint32_t platform_flash_mapped2phys (uint32_t mapped_addr)
{ {
#ifdef __ESP8266__ #if defined(__ESP8266__)
uint32_t cache_ctrl = READ_PERI_REG(CACHE_FLASH_CTRL_REG); uint32_t cache_ctrl = READ_PERI_REG(CACHE_FLASH_CTRL_REG);
if (!(cache_ctrl & CACHE_FLASH_ACTIVE)) if (!(cache_ctrl & CACHE_FLASH_ACTIVE))
return -1; return -1;
@ -861,8 +861,10 @@ uint32_t platform_flash_mapped2phys (uint32_t mapped_addr)
bool b1 = (cache_ctrl & CACHE_FLASH_MAPPED1) ? 1 : 0; bool b1 = (cache_ctrl & CACHE_FLASH_MAPPED1) ? 1 : 0;
uint32_t meg = (b1 << 1) | b0; uint32_t meg = (b1 << 1) | b0;
return mapped_addr - INTERNAL_FLASH_MAPPED_ADDRESS + meg * 0x100000; return mapped_addr - INTERNAL_FLASH_MAPPED_ADDRESS + meg * 0x100000;
#elif defined(__ESP32__)
// TODO: need to handle drom0 addresses too?
return mapped_addr - IROM0_START_MAPPED_ADDR + IROM0_START_FLASH_ADDR;
#else #else
// FIXME # error "unknown board"
return mapped_addr - INTERNAL_FLASH_MAPPED_ADDRESS;
#endif #endif
} }

View File

@ -278,7 +278,19 @@ SECTIONS
LONG(0) LONG(0) /* Null-terminate the array */ LONG(0) LONG(0) /* Null-terminate the array */
_irom0_text_end = ABSOLUTE(.); _irom0_text_end = ABSOLUTE(.);
_flash_used_end = ABSOLUTE(.);
/* Due to the way the gen_appbin.py script packs the bundle that goes into
* flash, we don't have a convenient _flash_used_end symbol on the ESP32.
* Instead we sum up the three sections we know goes into the
* irom0_flash.bin, so we can use that as a starting point to scan for
* the next free page. We could presumably be even more specific and
* account for the block headers and trailing checksum. Maybe later.
*/
_irom0_bin_min_sz = ABSOLUTE(
_irom0_text_end - _irom0_text_start +
_text_end - _text_start +
_data_end - _data_start);
} >irom0_0_seg :irom0_0_phdr } >irom0_0_seg :irom0_0_phdr
.lit4 : ALIGN(4) .lit4 : ALIGN(4)