Skip to content

Commit

Permalink
Refactor spi flash code (#2810)
Browse files Browse the repository at this point in the history
This PR tidies up the flash memory code and adds the `flash_addr_t` and `flash_sector_t` types. In paricular, `flash_addr_t` defines flash addresses as `uintptr_t` rather than `uint32_t`. The primary reason for this is that host builds emulate flash addresses using memory pointers.

The main flash interface definitions are in `Sming/Components/arch_driver/src/include/flashmem.h`. The arch header files `esp_spi_flash.h` include this after any arch-specific definitions.

Other changes:

- Deprecate `flashmem_get_first_free_block_address` - serves no purpose since partitions were introduced.
- Return enumerated value from `flashmem_get_size_type()`
- The `SPIFlashInfo` structure returned from `flashmem_get_info()` is now common to all architectures, although the fields within may have different values. This means it no longer reflects the actual in-flash structure for Esp8266. Applications should never rely on this anyway, so not considered a breaking change.
  • Loading branch information
mikee47 authored Jun 18, 2024
1 parent ac79a44 commit 2709614
Show file tree
Hide file tree
Showing 13 changed files with 341 additions and 451 deletions.
32 changes: 8 additions & 24 deletions Sming/Arch/Esp32/Components/spi_flash/flashmem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include <rom/cache.h>
#include <esp_systemapi.h>

uint32_t flashmem_write(const void* from, uint32_t toaddr, uint32_t size)
uint32_t flashmem_write(const void* from, flash_addr_t toaddr, uint32_t size)
{
esp_err_t r = esp_flash_write(esp_flash_default_chip, from, toaddr, size);
if(r != ESP_OK) {
Expand All @@ -27,7 +27,7 @@ uint32_t flashmem_write(const void* from, uint32_t toaddr, uint32_t size)
return size;
}

uint32_t flashmem_read(void* to, uint32_t fromaddr, uint32_t size)
uint32_t flashmem_read(void* to, flash_addr_t fromaddr, uint32_t size)
{
esp_err_t r = esp_flash_read(esp_flash_default_chip, to, fromaddr, size);
if(r != ESP_OK) {
Expand All @@ -38,7 +38,7 @@ uint32_t flashmem_read(void* to, uint32_t fromaddr, uint32_t size)
return size;
}

bool flashmem_erase_sector(uint32_t sector_id)
bool flashmem_erase_sector(flash_sector_t sector_id)
{
esp_task_wdt_reset();

Expand All @@ -61,36 +61,20 @@ SPIFlashInfo flashmem_get_info()
return info;
}

uint8_t flashmem_get_size_type()
SPIFlashSize flashmem_get_size_type()
{
return flashmem_get_info().size;
}

uint32_t flashmem_get_size_bytes()
flash_addr_t flashmem_get_size_bytes()
{
return g_rom_flashchip.chip_size;
}

uint16_t flashmem_get_size_sectors()
flash_addr_t flashmem_get_address(const void* memptr)
{
return flashmem_get_size_bytes() / SPI_FLASH_SEC_SIZE;
}

uint32_t flashmem_find_sector(uint32_t address, uint32_t* pstart, uint32_t* pend)
{
// All the sectors in the flash have the same size, so just align the address
uint32_t sect_id = address / INTERNAL_FLASH_SECTOR_SIZE;

if(pstart)
*pstart = sect_id * INTERNAL_FLASH_SECTOR_SIZE;
if(pend)
*pend = (sect_id + 1) * INTERNAL_FLASH_SECTOR_SIZE - 1;
return sect_id;
}

uint32_t flashmem_get_sector_of_address(uint32_t addr)
{
return flashmem_find_sector(addr, NULL, NULL);
auto phys = spi_flash_cache2phys(memptr);
return (phys == SPI_FLASH_CACHE2PHYS_FAIL) ? 0 : phys;
}

uint32_t spi_flash_get_id(void)
Expand Down
110 changes: 2 additions & 108 deletions Sming/Arch/Esp32/Components/spi_flash/include/esp_spi_flash.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,7 @@
extern "C" {
#endif

/**
* @defgroup flash Flash Memory Support
* @defgroup spi_flash SPI Flash API
* @ingroup flash
* @{
*/

/// Flash memory access must be aligned and in multiples of 4-byte words
#define INTERNAL_FLASH_WRITE_UNIT_SIZE 4
#define INTERNAL_FLASH_READ_UNIT_SIZE 4

#define FLASH_TOTAL_SEC_COUNT (flashmem_get_size_sectors())

/// Number of flash sectors reserved for system parameters at start
#define SYS_PARAM_SEC_COUNT 4
#define FLASH_WORK_SEC_COUNT (FLASH_TOTAL_SEC_COUNT - SYS_PARAM_SEC_COUNT)

#define INTERNAL_FLASH_SECTOR_SIZE SPI_FLASH_SEC_SIZE
#define INTERNAL_FLASH_SIZE ((FLASH_WORK_SEC_COUNT)*INTERNAL_FLASH_SECTOR_SIZE)

typedef enum {
MODE_QIO = ESP_IMAGE_SPI_MODE_QIO,
Expand All @@ -69,96 +51,8 @@ typedef enum {
SIZE_32MBIT = 0xFF, ///< Not listed
} SPIFlashSize;

/**
* @brief SPI Flash memory information block.
* Copied from bootloader header.
* See `esp_image_header_t`.
*/
typedef struct {
SPIFlashMode mode;
SPIFlashSpeed speed;
SPIFlashSize size;
} SPIFlashInfo;

/** @brief Obtain the flash memory address for a memory pointer
* @param memptr
* @retval uint32_t Offset from start of flash memory
* @note If memptr is not in valid flash memory it will return an offset which exceeds
* the internal flash memory size.
* @note The flash location is dependent on where rBoot has mapped the firmware.
*/
static inline uint32_t flashmem_get_address(const void* memptr)
{
auto phys = spi_flash_cache2phys(memptr);
return (phys == SPI_FLASH_CACHE2PHYS_FAIL) ? 0 : phys;
}

/** @brief Write a block of data to flash
* @param from Buffer to obtain data from
* @param toaddr Flash location to start writing
* @param size Number of bytes to write
* @retval uint32_t Number of bytes written
* @note None of the parameters need to be aligned
*/
uint32_t flashmem_write(const void* from, uint32_t toaddr, uint32_t size);

/** @brief Read a block of data from flash
* @param to Buffer to store data
* @param fromaddr Flash location to start reading
* @param size Number of bytes to read
* @retval uint32_t Number of bytes written
* @note none of the parameters need to be aligned
*/
uint32_t flashmem_read(void* to, uint32_t fromaddr, uint32_t size);

/** @brief Erase a single flash sector
* @param sector_id the sector to erase
* @retval true on success
*/
bool flashmem_erase_sector(uint32_t sector_id);

/** @brief Get flash memory information block
* @retval SPIFlashInfo Information block
*/
SPIFlashInfo flashmem_get_info();

/** @brief Returns a number indicating the size of flash memory chip
* @retval uint8_t See SpiFlashInfo.size field for possible values
*/
uint8_t flashmem_get_size_type();

/** @brief get the total flash memory size
* @retval uint32_t Size in bytes
*/
uint32_t flashmem_get_size_bytes();

/** @brief Get the total number of flash sectors
* @retval uint16_t Sector count
*/
uint16_t flashmem_get_size_sectors();

/** @brief Helper function: find the flash sector in which an address resides
* @param address
* @param pstart OUT/OPTIONAL: Start of sector containing the given address
* @param pend OUT/OPTIONAL: Last address in sector
* @retval uint32_t Sector number for the given address
* @note Optional parameters may be null
*/
uint32_t flashmem_find_sector(uint32_t address, uint32_t* pstart, uint32_t* pend);

/** @brief Get sector number containing the given address
* @param addr
* @retval uint32_t sector number
*/
uint32_t flashmem_get_sector_of_address(uint32_t addr);

/*
* @brief Get unique 32-bit flash identification code
*/
uint32_t spi_flash_get_id(void);

/** @} */

#ifdef __cplusplus
}
#endif

#include <flashmem.h>
68 changes: 24 additions & 44 deletions Sming/Arch/Esp8266/Components/spi_flash/flashmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*
****/

#include "include/esp_spi_flash.h"
#include <esp_spi_flash.h>
#include <esp_systemapi.h>

extern char _flash_code_end[];
Expand All @@ -40,7 +40,7 @@ static inline uint32_t min(uint32_t a, uint32_t b)
return (a < b) ? a : b;
}

uint32_t flashmem_get_address(const void* memptr)
flash_addr_t flashmem_get_address(const void* memptr)
{
uint32_t addr = (uint32_t)memptr - INTERNAL_FLASH_START_ADDRESS;
// Determine which 1MB memory bank is mapped
Expand All @@ -54,7 +54,7 @@ uint32_t flashmem_get_address(const void* memptr)
return addr;
}

uint32_t flashmem_write(const void* from, uint32_t toaddr, uint32_t size)
uint32_t flashmem_write(const void* from, flash_addr_t toaddr, uint32_t size)
{
if(IS_ALIGNED(from) && IS_ALIGNED(toaddr) && IS_ALIGNED(size))
return flashmem_write_internal(from, toaddr, size);
Expand Down Expand Up @@ -126,7 +126,7 @@ uint32_t flashmem_write(const void* from, uint32_t toaddr, uint32_t size)
return size;
}

uint32_t flashmem_read(void* to, uint32_t fromaddr, uint32_t size)
uint32_t flashmem_read(void* to, flash_addr_t fromaddr, uint32_t size)
{
if(IS_ALIGNED(to) && IS_ALIGNED(fromaddr) && IS_ALIGNED(size))
return flashmem_read_internal(to, fromaddr, size);
Expand Down Expand Up @@ -186,27 +186,39 @@ uint32_t flashmem_read(void* to, uint32_t fromaddr, uint32_t size)
return size;
}

bool flashmem_erase_sector(uint32_t sector_id)
bool flashmem_erase_sector(flash_sector_t sector_id)
{
WDT_FEED();
return spi_flash_erase_sector(sector_id) == SPI_FLASH_RESULT_OK;
}

SPIFlashInfo flashmem_get_info()
{
SPIFlashInfo spi_flash_info STORE_ATTR;
if(flashmem_read_internal(&spi_flash_info, 0x00000000, sizeof(spi_flash_info)) == 0) {
memset(&spi_flash_info, 0, sizeof(spi_flash_info));
}
return spi_flash_info;
struct {
uint8_t unknown0;
uint8_t unknown1;
uint8_t mode : 8; ///< SPIFlashMode
uint8_t speed : 4; ///< SPIFlashSpeed
uint8_t size : 4; ///< SPIFlashSize
} raw_info;
if(flashmem_read_internal(&raw_info, 0x00000000, sizeof(raw_info)) == 0) {
SPIFlashInfo nil = {};
return nil;
}
SPIFlashInfo info = {
.mode = raw_info.mode,
.speed = raw_info.speed,
.size = raw_info.size,
};
return info;
}

uint8_t flashmem_get_size_type()
SPIFlashSize flashmem_get_size_type()
{
return flashmem_get_info().size;
}

uint32_t flashmem_get_size_bytes()
flash_addr_t flashmem_get_size_bytes()
{
uint32_t flash_size = 0;
switch (flashmem_get_info().size)
Expand Down Expand Up @@ -239,30 +251,6 @@ uint32_t flashmem_get_size_bytes()
return flash_size;
}

uint16_t flashmem_get_size_sectors()
{
return flashmem_get_size_bytes() / SPI_FLASH_SEC_SIZE;
}

uint32_t flashmem_find_sector(uint32_t address, uint32_t *pstart, uint32_t *pend)
{
// All the sectors in the flash have the same size, so just align the address
uint32_t sect_id = address / INTERNAL_FLASH_SECTOR_SIZE;

if( pstart )
*pstart = sect_id * INTERNAL_FLASH_SECTOR_SIZE;
if( pend )
*pend = ( sect_id + 1 ) * INTERNAL_FLASH_SECTOR_SIZE - 1;
return sect_id;
}

uint32_t flashmem_get_sector_of_address( uint32_t addr )
{
return flashmem_find_sector( addr, NULL, NULL );
}

/////////////////////////////////////////////////////

uint32_t flashmem_write_internal( const void *from, uint32_t toaddr, uint32_t size )
{
assert(IS_ALIGNED(from) && IS_ALIGNED(toaddr) && IS_ALIGNED(size));
Expand All @@ -288,11 +276,3 @@ uint32_t flashmem_read_internal( void *to, uint32_t fromaddr, uint32_t size )
return 0;
}
}

uint32_t flashmem_get_first_free_block_address()
{
// Round the total used flash size to the closest flash block address
uint32_t end;
flashmem_find_sector( ( uint32_t )_flash_code_end - INTERNAL_FLASH_START_ADDRESS - 1, NULL, &end);
return end + 1;
}
Loading

0 comments on commit 2709614

Please sign in to comment.