Skip to content

initial SPI flash #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ if(NOT ESP_TARGET_LIB)
set(ESP_TARGET_LIB ${ESP_TARGET})
endif()

set(ESP_STUB_LIB_IMPL_DIR "${CMAKE_CURRENT_LIST_DIR}/src")

set(srcs
src/flash.c
)
Expand All @@ -34,10 +36,12 @@ target_include_directories(${ESP_STUB_LIB}
INTERFACE include
PRIVATE include/esp-stub-lib
)
# Public within the library
include_directories(include)
include_directories(include/esp-stub-lib)

# STUB_COMPILE_DEFS is optional definitions coming from the parent CMakeLists.txt
target_compile_definitions(${ESP_STUB_LIB} PRIVATE ${STUB_COMPILE_DEFS})
add_compile_definitions(${STUB_COMPILE_DEFS})

add_subdirectory(src/${ESP_TARGET} ${ESP_TARGET_LIB})

Expand Down
4 changes: 4 additions & 0 deletions example/stub_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ int stub_main(int cmd, ...)

stub_lib_flash_init(&flash_state);

stub_lib_flash_info_t info;
stub_lib_flash_get_info(&info);
stub_lib_flash_info_print(&info);

const struct stub_cmd_handler *handler = cmd_handlers;
while (handler->handler) {
if (handler->cmd == cmd) {
Expand Down
55 changes: 55 additions & 0 deletions include/common/flash_impl_get_id_from_rom.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/

#pragma once

#include <stdint.h>

#include <common/target_rom.h>
#include <common/soc_utils.h>
#include <target/rom_impl.h>
#include <target/soc_impl.h>

/**
* @brief Sets the correct flash_id in the flash config from SPI_MEM_FLASH_RDID in ROM code
*
*/
extern void esp_rom_spi_flash_update_id(void);

__attribute__((unused))
__attribute__((always_inline)) inline static
uint32_t flash_impl_get_id_from_rdid_reg(void)
{
WRITE_PERI_REG(PERIPHS_SPI_FLASH_C0, 0);
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, PERIPHS_SPI_FLASH_BITS_RDID);
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0)
;
uint32_t rdid = READ_PERI_REG(PERIPHS_SPI_FLASH_C0) & 0xffffff;
return ((rdid & 0xff) << 16) | (rdid & 0xff00) | ((rdid & 0xff0000) >> 16);;
}

__attribute__((unused))
__attribute__((always_inline)) inline static
uint32_t flash_impl_get_id_from_rom(void)
{
esp_rom_spi_flash_update_id();
return stub_target_rom_get_flash_config()->flash_id;
}

uint32_t stub_target_flash_get_flash_id(void)
{
// TODO: remove dev tracing
STUB_LOG_TRACEF("Uninit ROM's flash_id: 0x%x\n", stub_target_rom_get_flash_config()->flash_id);

// TODO: it's just for development. remove this option then
uint32_t rdid = flash_impl_get_id_from_rdid_reg();
(void)rdid;
STUB_LOG_TRACEF("Flash ID: 0x%x (from SPI RDID)\n", rdid);

uint32_t id = flash_impl_get_id_from_rom();
STUB_LOG_TRACEF("Flash ID: 0x%x (from ROM code)\n", stub_target_rom_get_flash_config()->flash_id);
return id;
}
36 changes: 36 additions & 0 deletions include/common/flash_impl_init_auto_spiconfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/

#pragma once

#include <stdbool.h>
#include <stdint.h>

#include <log.h>

/**
* @brief SPI Flash init
*
* @param spiconfig: 0 - auto from efuse; a special value - for pins
*
* @param legacy: Deprecated compatibility API value, must be false
*
*/
extern void esp_rom_spiflash_attach(uint32_t spiconfig, bool legacy);

__attribute__((always_inline)) inline static
void flash_impl_init_auto_spiconfig(void)
{
STUB_LOG_TRACE();
// Do not call ets_efuse_get_spiconfig here because
// it is called inside of esp_rom_spiflash_attach() when spiconfig=0
esp_rom_spiflash_attach(0, false);
}

void stub_target_flash_init(void)
{
flash_impl_init_auto_spiconfig();
}
34 changes: 34 additions & 0 deletions include/common/flash_impl_init_no_spiconfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/

#pragma once

#include <stdbool.h>
#include <stdint.h>

#include <log.h>

/**
* @brief SPI Flash init. CONFIG SPI is unsupported
*
* @param spiconfig: Deprecated compatibility API value, must be 0
*
* @param legacy: Deprecated compatibility API value, must be false
*
*/
extern void esp_rom_spiflash_attach(uint32_t spiconfig, bool legacy);

__attribute__((always_inline)) inline static
void flash_impl_init_no_spiconfig(void)
{
STUB_LOG_TRACE();
esp_rom_spiflash_attach(0, false);
}

void stub_target_flash_init(void)
{
flash_impl_init_no_spiconfig();
}
17 changes: 17 additions & 0 deletions include/common/rom_impl_flash_config1.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/

#pragma once

#include <common/target_rom.h>

/* ROM's flash config data for some old chips */
extern esp_rom_spiflash_chip_t g_rom_flashchip;

const esp_rom_spiflash_chip_t *stub_target_rom_get_flash_config(void)
{
return &g_rom_flashchip;
}
23 changes: 23 additions & 0 deletions include/common/rom_impl_flash_config2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/

#pragma once

#include <common/target_rom.h>

typedef struct {
esp_rom_spiflash_chip_t chip;
uint8_t dummy_len_plus[3];
uint8_t sig_matrix;
} esp_rom_spiflash_legacy_data_t;

/* ROM's flash config data */
extern esp_rom_spiflash_legacy_data_t *rom_spiflash_legacy_data;

const esp_rom_spiflash_chip_t *stub_target_rom_get_flash_config()
{
return &rom_spiflash_legacy_data->chip;
}
111 changes: 111 additions & 0 deletions include/common/soc_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/

#pragma once

#define BIT(nr) (1UL << (nr))
#define BIT64(nr) (1ULL << (nr))

#define ETS_UNCACHED_ADDR(addr) (addr)
#define ETS_CACHED_ADDR(addr) (addr)

//write value to register
#define REG_WRITE(_r, _v) do { \
(*(volatile uint32_t *)(_r)) = (_v); \
} while(0)

//read value from register
#define REG_READ(_r) ({ \
(*(volatile uint32_t *)(_r)); \
})

//get bit or get bits from register
#define REG_GET_BIT(_r, _b) ({ \
(*(volatile uint32_t*)(_r) & (_b)); \
})

//set bit or set bits to register
#define REG_SET_BIT(_r, _b) do { \
*(volatile uint32_t*)(_r) = (*(volatile uint32_t*)(_r)) | (_b); \
} while(0)

//clear bit or clear bits of register
#define REG_CLR_BIT(_r, _b) do { \
*(volatile uint32_t*)(_r) = (*(volatile uint32_t*)(_r)) & (~(_b)); \
} while(0)

//set bits of register controlled by mask
#define REG_SET_BITS(_r, _b, _m) do { \
*(volatile uint32_t*)(_r) = (*(volatile uint32_t*)(_r) & ~(_m)) | ((_b) & (_m)); \
} while(0)

//get field from register, uses field _S & _V to determine mask
#define REG_GET_FIELD(_r, _f) ({ \
((REG_READ(_r) >> (_f##_S)) & (_f##_V)); \
})

//set field of a register from variable, uses field _S & _V to determine mask
#define REG_SET_FIELD(_r, _f, _v) do { \
REG_WRITE((_r),((REG_READ(_r) & ~((_f##_V) << (_f##_S)))|(((_v) & (_f##_V))<<(_f##_S)))); \
} while(0)

//get field value from a variable, used when _f is not left shifted by _f##_S
#define VALUE_GET_FIELD(_r, _f) (((_r) >> (_f##_S)) & (_f))

//get field value from a variable, used when _f is left shifted by _f##_S
#define VALUE_GET_FIELD2(_r, _f) (((_r) & (_f))>> (_f##_S))

//set field value to a variable, used when _f is not left shifted by _f##_S
#define VALUE_SET_FIELD(_r, _f, _v) ((_r)=(((_r) & ~((_f) << (_f##_S)))|((_v)<<(_f##_S))))

//set field value to a variable, used when _f is left shifted by _f##_S
#define VALUE_SET_FIELD2(_r, _f, _v) ((_r)=(((_r) & ~(_f))|((_v)<<(_f##_S))))

//generate a value from a field value, used when _f is not left shifted by _f##_S
#define FIELD_TO_VALUE(_f, _v) (((_v)&(_f))<<_f##_S)

//generate a value from a field value, used when _f is left shifted by _f##_S
#define FIELD_TO_VALUE2(_f, _v) (((_v)<<_f##_S) & (_f))

//read value from register
#define READ_PERI_REG(addr) ({ \
(*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))); \
})

//write value to register
#define WRITE_PERI_REG(addr, val) do { \
(*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) = (uint32_t)(val); \
} while(0)

//clear bits of register controlled by mask
#define CLEAR_PERI_REG_MASK(reg, mask) do { \
WRITE_PERI_REG((reg), (READ_PERI_REG(reg)&(~(mask)))); \
} while(0)

//set bits of register controlled by mask
#define SET_PERI_REG_MASK(reg, mask) do { \
WRITE_PERI_REG((reg), (READ_PERI_REG(reg)|(mask))); \
} while(0)

//get bits of register controlled by mask
#define GET_PERI_REG_MASK(reg, mask) ({ \
(READ_PERI_REG(reg) & (mask)); \
})

//get bits of register controlled by highest bit and lowest bit
#define GET_PERI_REG_BITS(reg, hipos,lowpos) ({ \
((READ_PERI_REG(reg)>>(lowpos))&((1<<((hipos)-(lowpos)+1))-1)); \
})

//set bits of register controlled by mask and shift
#define SET_PERI_REG_BITS(reg,bit_map,value,shift) do { \
WRITE_PERI_REG((reg),(READ_PERI_REG(reg)&(~((bit_map)<<(shift))))|(((value) & (bit_map))<<(shift)) ); \
} while(0)

//get field of register
#define GET_PERI_REG_BITS2(reg, mask,shift) ({ \
((READ_PERI_REG(reg)>>(shift))&(mask)); \
})
12 changes: 12 additions & 0 deletions include/common/target_flash.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/

#pragma once

#include <stdint.h>

void stub_target_flash_init(void);
uint32_t stub_target_flash_get_flash_id(void);
42 changes: 42 additions & 0 deletions include/common/target_rom.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/

#pragma once

#include <stdint.h>

/* Flash geometry constants */
#define STUB_FLASH_SECTOR_SIZE 0x1000
#define STUB_FLASH_BLOCK_SIZE 0x10000
#define STUB_FLASH_PAGE_SIZE 0x100
#define STUB_FLASH_STATUS_MASK 0xFFFF

typedef struct esp_rom_spiflash_chip {
uint32_t flash_id;
uint32_t chip_size; // chip size in bytes
uint32_t block_size;
uint32_t sector_size;
uint32_t page_size;
uint32_t status_mask;
} esp_rom_spiflash_chip_t;

extern int esp_rom_spiflash_config_param(uint32_t flash_id, uint32_t chip_size,
uint32_t block_size, uint32_t sector_size,
uint32_t page_size, uint32_t status_mask);

__attribute__((always_inline)) inline static
const esp_rom_spiflash_chip_t * stub_target_rom_get_flash_config(void);

__attribute__((always_inline)) inline static
void stub_target_rom_update_flash_config(uint32_t flash_id, uint32_t flash_size)
{
esp_rom_spiflash_config_param(flash_id,
flash_size,
STUB_FLASH_BLOCK_SIZE,
STUB_FLASH_SECTOR_SIZE,
STUB_FLASH_PAGE_SIZE,
STUB_FLASH_STATUS_MASK);
}
File renamed without changes.
2 changes: 2 additions & 0 deletions include/esp-stub-lib/flash.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ typedef struct stub_flash_info {
uint32_t encrypted;
} stub_lib_flash_info_t;

// TODO: error codes
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

void stub_lib_flash_init(void **state);
void stub_lib_flash_deinit(const void *state);
void stub_lib_flash_get_info(stub_lib_flash_info_t *info);
void stub_lib_flash_info_print(const stub_lib_flash_info_t *info);
int stub_lib_flash_read_buff(uint32_t addr, void *buffer, uint32_t size);
int stub_lib_flash_write_buff(uint32_t addr, const void *buffer, uint32_t size, int encrypt);
int stub_lib_flash_erase_area(uint32_t addr, uint32_t size);
Expand Down
4 changes: 2 additions & 2 deletions src/esp32/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
set(srcs
src/uart.c
src/flash.c
src/target_uart.c
src/target_flash.c
)

add_library(${ESP_TARGET_LIB} STATIC ${srcs})
Expand Down
Loading