-
Notifications
You must be signed in to change notification settings - Fork 3
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
base: master
Are you sure you want to change the base?
Changes from all commits
73a2d80
4992d16
6d6a0f9
cd2f0b3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 OR MIT | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <stdint.h> | ||
#include <target/flash.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; | ||
|
||
inline static | ||
const esp_rom_spiflash_chip_t *flash_impl_get_config_from_rom() | ||
{ | ||
return &rom_spiflash_legacy_data->chip; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 OR MIT | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <target/flash.h> | ||
|
||
/* ROM's flash config data for some old chips */ | ||
extern esp_rom_spiflash_chip_t g_rom_flashchip; | ||
|
||
inline static | ||
const esp_rom_spiflash_chip_t *flash_impl_get_config_from_rom_old(void) | ||
{ | ||
return &g_rom_flashchip; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 OR MIT | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <stdint.h> | ||
|
||
#include <log.h> | ||
#include <target/flash.h> | ||
#include <private/soc_utils.h> | ||
|
||
#include <target_spec/periph_defs.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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. candidate to be mnoved to ROM header |
||
|
||
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);; | ||
} | ||
|
||
inline static | ||
uint32_t flash_impl_get_id_from_config(void) | ||
{ | ||
|
||
esp_rom_spi_flash_update_id(); | ||
return stub_target_flash_get_config()->flash_id; | ||
} | ||
|
||
inline static | ||
uint32_t flash_impl_get_id_from_rom(void) | ||
{ | ||
// TODO: remove dev tracing | ||
STUB_LOG_TRACEF("Uninit ROM's flash_id: 0x%x\n", stub_target_flash_get_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_config(); | ||
STUB_LOG_TRACEF("Flash ID: 0x%x (from ROM code)\n", stub_target_flash_get_config()->flash_id); | ||
return id; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
* 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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you have this externs in several files? In this case It would be better to put ROM functions declarations to header file and include it. |
||
|
||
inline static | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Contents of this file are the same as for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is not good style to have function implementations in headers files. Please avoid this. Otherwise every change in such functions will trigger rebuild for all files which include such header. I do not see a big sense to have this as inline and be in headers. |
||
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); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* 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); | ||
|
||
inline static | ||
void flash_impl_init_no_spiconfig(void) | ||
{ | ||
STUB_LOG_TRACE(); | ||
esp_rom_spiflash_attach(0, false); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,16 +4,157 @@ | |
* SPDX-License-Identifier: Apache-2.0 OR MIT | ||
*/ | ||
|
||
#include <stdbool.h> | ||
#include <stddef.h> | ||
|
||
#include <log.h> | ||
#include <bit_utils.h> | ||
#include <private/soc_utils.h> | ||
#include <target/flash.h> | ||
#include <target/impl/flash_get_config_from_rom_old.h> | ||
|
||
#include "soc/reg_base.h" | ||
#include "soc/spi_reg.h" | ||
|
||
#define SPI_FLASH_CMD_RDID 0x9F | ||
#define ESP_ROM_SPIFLASH_BUSY_FLAG BIT(0) | ||
|
||
#define GPIO_STRAP_REG (DR_REG_GPIO_BASE + 0x0038) | ||
#define PERIPHS_SPI_FLASH_CMD SPI_CMD_REG(1) | ||
#define PERIPHS_SPI_FLASH_STATUS SPI_RD_STATUS_REG(1) | ||
#define PERIPHS_SPI_FLASH_USRREG SPI_USER_REG(1) | ||
#define PERIPHS_SPI_FLASH_USRREG2 SPI_USER2_REG(1) | ||
#define PERIPHS_SPI_FLASH_C0 SPI_W0_REG(1) | ||
#define PERIPHS_SPI_MOSI_DLEN_REG SPI_MOSI_DLEN_REG(1) | ||
#define PERIPHS_SPI_MISO_DLEN_REG SPI_MISO_DLEN_REG(1) | ||
|
||
/* XXX0_10XX */ | ||
#define IS_HSPI_BOOT(strap_val) (((strap_val)&0x1c)==0x08) | ||
|
||
/* ROM */ | ||
|
||
/** | ||
* @brief Read spi flash pin configuration from Efuse | ||
* | ||
* @return | ||
* - 0 for default SPI pins. | ||
* - 1 for default HSPI pins. | ||
* - Other values define a custom pin configuration mask. Pins are encoded as per the EFUSE_SPICONFIG_RET_SPICLK, | ||
* EFUSE_SPICONFIG_RET_SPIQ, EFUSE_SPICONFIG_RET_SPID, EFUSE_SPICONFIG_RET_SPICS0, EFUSE_SPICONFIG_RET_SPIHD macros. | ||
* WP pin (for quad I/O modes) is not saved in efuse and not returned by this function. | ||
*/ | ||
extern uint32_t ets_efuse_get_spiconfig(void); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is also candidate to be in ROM functions header file. Please have a look at IDF. This function is declared in header file of |
||
/** | ||
* @brief SPI Flash init, clock divisor is 4, use 1 line Slow read mode. | ||
* Please do not call this function in SDK. | ||
* | ||
* @param uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping | ||
* else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid, bit[23:18] spics0, bit[29:24] spihd | ||
* | ||
* @param uint8_t legacy: always keeping false. | ||
* | ||
* @return None | ||
*/ | ||
extern void esp_rom_spiflash_attach(uint32_t ishspi, bool legacy); | ||
|
||
// TODO: avoid common code and update execute_command() | ||
static uint32_t flash_exec_usr_cmd(uint32_t cmd) | ||
{ | ||
uint32_t status_value = ESP_ROM_SPIFLASH_BUSY_FLAG; | ||
|
||
while (ESP_ROM_SPIFLASH_BUSY_FLAG == (status_value & ESP_ROM_SPIFLASH_BUSY_FLAG)) { | ||
WRITE_PERI_REG(PERIPHS_SPI_FLASH_STATUS, 0); /* clear register */ | ||
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_USR | cmd); //TODO cmd is bit(0), this is a useless bit | ||
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0) | ||
; | ||
status_value = READ_PERI_REG(PERIPHS_SPI_FLASH_STATUS) & stub_target_flash_get_config()->status_mask; | ||
} | ||
|
||
return status_value; | ||
} | ||
|
||
static void flash_spi_wait_ready(void) | ||
{ | ||
uint32_t status_value = ESP_ROM_SPIFLASH_BUSY_FLAG; | ||
|
||
while (ESP_ROM_SPIFLASH_BUSY_FLAG == (status_value & ESP_ROM_SPIFLASH_BUSY_FLAG)) { | ||
WRITE_PERI_REG(PERIPHS_SPI_FLASH_STATUS, 0); /* clear register */ | ||
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_RDSR); | ||
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0) | ||
; | ||
status_value = READ_PERI_REG(PERIPHS_SPI_FLASH_STATUS) & stub_target_flash_get_config()->status_mask; | ||
} | ||
} | ||
|
||
static uint32_t flash_spi_cmd_run(uint32_t cmd, | ||
uint8_t data_bits[], | ||
uint32_t data_bits_num, | ||
uint32_t read_bits_num) | ||
{ | ||
uint32_t old_spi_usr = READ_PERI_REG(PERIPHS_SPI_FLASH_USRREG); | ||
uint32_t old_spi_usr2 = READ_PERI_REG(PERIPHS_SPI_FLASH_USRREG2); | ||
uint32_t flags = SPI_USR_COMMAND; | ||
|
||
flash_spi_wait_ready(); | ||
|
||
if (read_bits_num > 0) { | ||
flags |= SPI_USR_MISO; | ||
WRITE_PERI_REG(PERIPHS_SPI_MISO_DLEN_REG, read_bits_num - 1); | ||
} | ||
if (data_bits_num > 0) { | ||
flags |= SPI_USR_MOSI; | ||
WRITE_PERI_REG(PERIPHS_SPI_MOSI_DLEN_REG, data_bits_num - 1); | ||
} | ||
|
||
WRITE_PERI_REG(PERIPHS_SPI_FLASH_USRREG, flags); | ||
WRITE_PERI_REG(PERIPHS_SPI_FLASH_USRREG2, (7 << SPI_USR_COMMAND_BITLEN_S) | cmd); | ||
if (data_bits_num == 0) { | ||
WRITE_PERI_REG(PERIPHS_SPI_FLASH_C0, 0); | ||
} else { | ||
for (uint32_t i = 0; i <= data_bits_num / 32; i += 32) { | ||
WRITE_PERI_REG(PERIPHS_SPI_FLASH_C0 + i / 8, *((uint32_t *)&data_bits[i / 8])); | ||
} | ||
} | ||
flash_exec_usr_cmd(0); | ||
uint32_t status = READ_PERI_REG(PERIPHS_SPI_FLASH_C0); | ||
/* restore some SPI controller registers */ | ||
WRITE_PERI_REG(PERIPHS_SPI_FLASH_USRREG, old_spi_usr); | ||
WRITE_PERI_REG(PERIPHS_SPI_FLASH_USRREG2, old_spi_usr2); | ||
|
||
return status; | ||
} | ||
|
||
static inline uint32_t get_id_from_rdid_cmd(void) | ||
{ | ||
uint32_t rdid = flash_spi_cmd_run(SPI_FLASH_CMD_RDID, NULL, 0, 24); | ||
return ((rdid & 0xff) << 16) | (rdid & 0xff00) | ((rdid & 0xff0000) >> 16); | ||
} | ||
|
||
void stub_target_flash_init(void) | ||
{ | ||
STUB_LOG_TRACE(); | ||
uint32_t ishspi = 0; | ||
uint32_t spiconfig = ets_efuse_get_spiconfig(); | ||
const uint32_t strapping = REG_READ(GPIO_STRAP_REG); | ||
if (IS_HSPI_BOOT(strapping)) { | ||
ishspi = 1; | ||
} | ||
if (spiconfig) { | ||
ishspi = spiconfig; | ||
} | ||
esp_rom_spiflash_attach(ishspi, false); | ||
} | ||
|
||
void stub_target_flash_init(void *state) | ||
uint32_t stub_target_flash_get_flash_id(void) | ||
{ | ||
(void)state; | ||
// TODO: Implement | ||
// TODO: remove dev tracing | ||
STUB_LOG_TRACEF("Uninit ROM's flash_id: 0x%x\n", stub_target_flash_get_config()->flash_id); | ||
uint32_t id = get_id_from_rdid_cmd(); | ||
STUB_LOG_TRACEF("Flash ID: 0x%x (from SPI RDID)\n", id); | ||
return id; | ||
} | ||
|
||
void stub_target_flash_deinit(const void *state) | ||
const esp_rom_spiflash_chip_t * stub_target_flash_get_config(void) | ||
{ | ||
(void)state; | ||
// TODO: Implement | ||
return flash_impl_get_config_from_rom_old(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 OR MIT | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <soc/spi_mem_reg.h> | ||
|
||
#define PERIPHS_SPI_FLASH_CMD SPI_MEM_CMD_REG(1) | ||
#define PERIPHS_SPI_FLASH_C0 SPI_MEM_W0_REG(1) | ||
|
||
#define PERIPHS_SPI_FLASH_BITS_RDID SPI_MEM_FLASH_RDID |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need separate headers for this functions?
How about have it like macro and keep it with
flash_impl_get_config_from_rom
and other similar ROM related staff in one header?