Skip to content

Commit 6ead06c

Browse files
committed
feat(spi_flash): Add XMC chip 32-bits address support
1 parent 0dbce72 commit 6ead06c

File tree

6 files changed

+78
-15
lines changed

6 files changed

+78
-15
lines changed

components/spi_flash/esp_flash_spi_init.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ __attribute__((unused)) static const char TAG[] = "spi_flash";
3434
#error "CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM cannot be disabled when CONFIG_SPI_FLASH_AUTO_SUSPEND is disabled."
3535
#endif
3636

37+
#if CONFIG_SPI_FLASH_ROM_IMPL && (CONFIG_ESPTOOLPY_FLASHSIZE_32MB || CONFIG_ESPTOOLPY_FLASHSIZE_64MB || CONFIG_ESPTOOLPY_FLASHSIZE_128MB)
38+
#error "Flash chip size equal or over 32MB memory cannot use driver in ROM"
39+
#endif
40+
3741
/* This pointer is defined in ROM and extern-ed on targets where CONFIG_SPI_FLASH_ROM_IMPL = y*/
3842
#if !CONFIG_SPI_FLASH_ROM_IMPL
3943
esp_flash_t *esp_flash_default_chip = NULL;

components/spi_flash/spi_flash_chip_generic.c

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#include "esp_private/spi_flash_os.h"
1616
#include "esp_rom_caps.h"
1717

18+
#define IS_REGION_32BIT(start, len) ((start) + (len) > (1<<24))
19+
#define IS_ADDR_32BIT(addr) (addr >= (1<<24))
20+
1821
typedef struct flash_chip_dummy {
1922
uint8_t dio_dummy_bitlen;
2023
uint8_t qio_dummy_bitlen;
@@ -112,6 +115,41 @@ esp_err_t spi_flash_chip_generic_detect_size(esp_flash_t *chip, uint32_t *size)
112115

113116
#ifndef CONFIG_SPI_FLASH_ROM_IMPL
114117

118+
static esp_err_t spi_flash_command_generic_program_4B(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length)
119+
{
120+
spi_flash_trans_t t = {
121+
.command = CMD_PROGRAM_PAGE_4B,
122+
.address_bitlen = 32,
123+
.address = address,
124+
.mosi_len = length,
125+
.mosi_data = buffer,
126+
.flags = SPI_FLASH_TRANS_FLAG_PE_CMD,
127+
};
128+
return chip->host->driver->common_command(chip->host, &t);
129+
}
130+
131+
static esp_err_t spi_flash_command_generic_erase_sector_4B(esp_flash_t *chip, uint32_t start_address)
132+
{
133+
spi_flash_trans_t t = {
134+
.command = CMD_SECTOR_ERASE_4B,
135+
.address_bitlen = 32,
136+
.address = start_address,
137+
.flags = SPI_FLASH_TRANS_FLAG_PE_CMD,
138+
};
139+
return chip->host->driver->common_command(chip->host, &t);
140+
}
141+
142+
static esp_err_t spi_flash_command_generic_erase_block_4B(esp_flash_t *chip, uint32_t start_address)
143+
{
144+
spi_flash_trans_t t = {
145+
.command = CMD_LARGE_BLOCK_ERASE_4B,
146+
.address_bitlen = 32,
147+
.address = start_address,
148+
.flags = SPI_FLASH_TRANS_FLAG_PE_CMD,
149+
};
150+
return chip->host->driver->common_command(chip->host, &t);
151+
}
152+
115153
esp_err_t spi_flash_chip_generic_probe(esp_flash_t *chip, uint32_t flash_id)
116154
{
117155
// This is the catch-all probe function, claim the chip always if nothing
@@ -173,14 +211,19 @@ esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip)
173211

174212
esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_address)
175213
{
214+
bool addr_32b = IS_ADDR_32BIT(start_address);
176215
esp_err_t err = chip->chip_drv->set_chip_write_protect(chip, false);
177216
if (err == ESP_OK) {
178217
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout);
179218
}
180219
//The chip didn't accept the previous write command. Ignore this in preparationstage.
181220
if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
182221
SET_FLASH_ERASE_STATUS(chip, SPI_FLASH_OS_IS_ERASING_STATUS_FLAG);
183-
chip->host->driver->erase_sector(chip->host, start_address);
222+
if (addr_32b) {
223+
spi_flash_command_generic_erase_sector_4B(chip, start_address);
224+
} else {
225+
chip->host->driver->erase_sector(chip->host, start_address);
226+
}
184227
chip->busy = 1;
185228
#ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED
186229
err = chip->chip_drv->wait_idle(chip, ESP_FLASH_CHIP_GENERIC_NO_TIMEOUT);
@@ -199,14 +242,19 @@ esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_
199242

200243
esp_err_t spi_flash_chip_generic_erase_block(esp_flash_t *chip, uint32_t start_address)
201244
{
245+
bool addr_32b = IS_ADDR_32BIT(start_address);
202246
esp_err_t err = chip->chip_drv->set_chip_write_protect(chip, false);
203247
if (err == ESP_OK) {
204248
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout);
205249
}
206250
//The chip didn't accept the previous write command. Ignore this in preparationstage.
207251
if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
208252
SET_FLASH_ERASE_STATUS(chip, SPI_FLASH_OS_IS_ERASING_STATUS_FLAG);
209-
chip->host->driver->erase_block(chip->host, start_address);
253+
if (addr_32b) {
254+
spi_flash_command_generic_erase_block_4B(chip, start_address);
255+
} else {
256+
chip->host->driver->erase_block(chip->host, start_address);
257+
}
210258
chip->busy = 1;
211259
#ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED
212260
err = chip->chip_drv->wait_idle(chip, ESP_FLASH_CHIP_GENERIC_NO_TIMEOUT);
@@ -232,6 +280,9 @@ esp_err_t spi_flash_chip_generic_read(esp_flash_t *chip, void *buffer, uint32_t
232280
uint32_t config_io_flags = 0;
233281

234282
// Configure the host, and return
283+
if (IS_REGION_32BIT(address, length)) {
284+
config_io_flags |= SPI_FLASH_CONFIG_IO_MODE_32B_ADDR;
285+
}
235286
err = chip->chip_drv->config_host_io_mode(chip, config_io_flags);
236287

237288
if (err == ESP_ERR_NOT_SUPPORTED) {
@@ -259,12 +310,16 @@ esp_err_t spi_flash_chip_generic_read(esp_flash_t *chip, void *buffer, uint32_t
259310
esp_err_t spi_flash_chip_generic_page_program(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length)
260311
{
261312
esp_err_t err;
262-
313+
bool addr_32b = IS_ADDR_32BIT(address);
263314
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout);
264-
//The chip didn't accept the previous write command. Ignore this in preparationstage.
315+
//The chip didn't accept the previous write command. Ignore this in preparation stage.
265316
if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
266317
// Perform the actual Page Program command
267-
chip->host->driver->program_page(chip->host, buffer, address, length);
318+
if (addr_32b) {
319+
spi_flash_command_generic_program_4B(chip, buffer, address, length);
320+
} else {
321+
chip->host->driver->program_page(chip->host, buffer, address, length);
322+
}
268323
chip->busy = 1;
269324

270325
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->page_program_timeout);
@@ -433,48 +488,48 @@ esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, uint32_t
433488
uint32_t read_command;
434489
bool conf_required = false;
435490
esp_flash_io_mode_t read_mode = chip->read_mode;
436-
bool addr_32bit = (flags & SPI_FLASH_CONFIG_IO_MODE_32B_ADDR);
491+
bool is_addr_32bit = (flags & SPI_FLASH_CONFIG_IO_MODE_32B_ADDR);
437492

438493
switch (read_mode & 0xFFFF) {
439494
case SPI_FLASH_QIO:
440495
//for QIO mode, the 4 bit right after the address are used for continuous mode, should be set to 0 to avoid that.
441496
addr_bitlen = SPI_FLASH_QIO_ADDR_BITLEN;
442497
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->qio_dummy_bitlen : rom_flash_chip_dummy->qio_dummy_bitlen);
443-
read_command = (addr_32bit? CMD_FASTRD_QIO_4B: CMD_FASTRD_QIO);
498+
read_command = (is_addr_32bit? CMD_FASTRD_QIO_4B: CMD_FASTRD_QIO);
444499
conf_required = true;
445500
break;
446501
case SPI_FLASH_QOUT:
447502
addr_bitlen = SPI_FLASH_QOUT_ADDR_BITLEN;
448503
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->qout_dummy_bitlen : rom_flash_chip_dummy->qout_dummy_bitlen);
449-
read_command = (addr_32bit? CMD_FASTRD_QUAD_4B: CMD_FASTRD_QUAD);
504+
read_command = (is_addr_32bit? CMD_FASTRD_QUAD_4B: CMD_FASTRD_QUAD);
450505
break;
451506
case SPI_FLASH_DIO:
452507
//for DIO mode, the 4 bit right after the address are used for continuous mode, should be set to 0 to avoid that.
453508
addr_bitlen = SPI_FLASH_DIO_ADDR_BITLEN;
454509
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->dio_dummy_bitlen : rom_flash_chip_dummy->dio_dummy_bitlen);
455-
read_command = (addr_32bit? CMD_FASTRD_DIO_4B: CMD_FASTRD_DIO);
510+
read_command = (is_addr_32bit? CMD_FASTRD_DIO_4B: CMD_FASTRD_DIO);
456511
conf_required = true;
457512
break;
458513
case SPI_FLASH_DOUT:
459514
addr_bitlen = SPI_FLASH_DOUT_ADDR_BITLEN;
460515
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->dout_dummy_bitlen : rom_flash_chip_dummy->dout_dummy_bitlen);
461-
read_command = (addr_32bit? CMD_FASTRD_DUAL_4B: CMD_FASTRD_DUAL);
516+
read_command = (is_addr_32bit? CMD_FASTRD_DUAL_4B: CMD_FASTRD_DUAL);
462517
break;
463518
case SPI_FLASH_FASTRD:
464519
addr_bitlen = SPI_FLASH_FASTRD_ADDR_BITLEN;
465520
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->fastrd_dummy_bitlen : rom_flash_chip_dummy->fastrd_dummy_bitlen);
466-
read_command = (addr_32bit? CMD_FASTRD_4B: CMD_FASTRD);
521+
read_command = (is_addr_32bit? CMD_FASTRD_4B: CMD_FASTRD);
467522
break;
468523
case SPI_FLASH_SLOWRD:
469524
addr_bitlen = SPI_FLASH_SLOWRD_ADDR_BITLEN;
470525
dummy_cyclelen_base = (chip->hpm_dummy_ena ? rom_flash_chip_dummy_hpm->slowrd_dummy_bitlen : rom_flash_chip_dummy->slowrd_dummy_bitlen);
471-
read_command = (addr_32bit? CMD_READ_4B: CMD_READ);
526+
read_command = (is_addr_32bit? CMD_READ_4B: CMD_READ);
472527
break;
473528
default:
474529
return ESP_ERR_FLASH_NOT_INITIALISED;
475530
}
476531
//For W25Q256 chip, the only difference between 4-Byte address command and 3-Byte version is the command value and the address bit length.
477-
if (addr_32bit) {
532+
if (is_addr_32bit) {
478533
addr_bitlen += 8;
479534
}
480535

@@ -619,6 +674,7 @@ spi_flash_caps_t spi_flash_chip_generic_get_caps(esp_flash_t *chip)
619674
// XMC-D support suspend
620675
if (chip->chip_id >> 16 == 0x46) {
621676
caps_flags |= SPI_FLASH_CHIP_CAP_SUSPEND;
677+
caps_flags |= SPI_FLASH_CHIP_CAP_32MB_SUPPORT;
622678
}
623679

624680
// XMC-D support suspend (some D series flash chip begin with 0x20, difference checked by SFDP)
@@ -637,6 +693,7 @@ spi_flash_caps_t spi_flash_chip_generic_get_caps(esp_flash_t *chip)
637693
chip->host->driver->common_command(chip->host, &t);
638694
if((data & 0x8) == 0x8) {
639695
caps_flags |= SPI_FLASH_CHIP_CAP_SUSPEND;
696+
caps_flags |= SPI_FLASH_CHIP_CAP_32MB_SUPPORT;
640697
}
641698
}
642699

docs/en/api-reference/peripherals/spi_flash/spi_flash_idf_vs_rom.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Feature Supported by ESP-IDF but Not in Chip-ROM
1515
.. list::
1616

1717
- Octal flash chip support. See :ref:`oct-flash-doc` for details.
18-
- 32-bit-address support for GD25Q256. Note that this feature is an optional feature, please do read :ref:`32-bit-flash-doc` for details.
18+
- 32-bit-address support on flash chips. Note that this feature is an optional feature, please do read :ref:`32-bit-flash-doc` for details.
1919
- TH flash chip support.
2020
- Kconfig option :ref:`CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED`.
2121
- :ref:`CONFIG_SPI_FLASH_VERIFY_WRITE`, enabling this option helps you detect bad writing.

docs/en/api-reference/peripherals/spi_flash/spi_flash_optional_feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ List of Flash chips that support this feature:
155155

156156
1. W25Q256
157157
2. GD25Q256
158+
3. XM25QH256D
158159

159160
Restrictions
160161
^^^^^^^^^^^^

docs/zh_CN/api-reference/peripherals/spi_flash/spi_flash_idf_vs_rom.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ ESP-IDF 支持但不包含在芯片 ROM 中的功能
1515
.. list::
1616

1717
- 八线 flash 芯片。详情请参阅 :ref:`oct-flash-doc`。
18-
- GD25Q256 32 位地址。请注意,此功能为可选功能,详情请参阅 :ref:`32-bit-flash-doc`。
18+
- Flash 的 32 位地址。请注意,此功能为可选功能,详情请参阅 :ref:`32-bit-flash-doc`。
1919
- TH flash 芯片。
2020
- Kconfig 选项 :ref:`CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED`。
2121
- :ref:`CONFIG_SPI_FLASH_VERIFY_WRITE`,启用此选项可检测错误写入。

docs/zh_CN/api-reference/peripherals/spi_flash/spi_flash_optional_feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ QSPI flash 芯片的 32 位地址支持
155155

156156
1. W25Q256
157157
2. GD25Q256
158+
3. XM25QH256D
158159

159160
限制
160161
^^^^

0 commit comments

Comments
 (0)