Skip to content

Commit 9be8dcc

Browse files
committed
feat(psram): psram support on h4
1 parent 90d3d65 commit 9be8dcc

File tree

21 files changed

+1075
-62
lines changed

21 files changed

+1075
-62
lines changed

components/esp_common/test_apps/.build-test-rules.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ components/esp_common/test_apps/esp_common:
44
disable:
55
- if: CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1
66
- if: CONFIG_NAME == "psram_noinit" and SOC_SPIRAM_SUPPORTED != 1
7+
- if: CONFIG_NAME == "xip_psram" and SOC_SPIRAM_XIP_SUPPORTED != 1

components/esp_common/test_apps/esp_common/pytest_esp_common.py

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import pytest
66
from pytest_embedded import Dut
77
from pytest_embedded_idf.utils import idf_parametrize
8+
from pytest_embedded_idf.utils import soc_filtered_targets
89

910

1011
@pytest.mark.generic
@@ -27,7 +28,7 @@ def test_esp_common(dut: Dut) -> None:
2728
],
2829
indirect=True,
2930
)
30-
@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32p4', 'esp32c5'], indirect=['target'])
31+
@idf_parametrize('target', soc_filtered_targets('SOC_SPIRAM_SUPPORTED == 1'), indirect=['target'])
3132
def test_esp_attr_psram_noinit(dut: Dut) -> None:
3233
dut.run_all_single_board_cases()
3334

@@ -39,7 +40,7 @@ def test_esp_attr_psram_noinit(dut: Dut) -> None:
3940
['psram_noinit'],
4041
indirect=True,
4142
)
42-
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
43+
@idf_parametrize('target', soc_filtered_targets('SOC_SPIRAM_SUPPORTED == 1'), indirect=['target'])
4344
def test_esp_attr_psram_noinit_multiple_stages(case_tester: Any) -> None:
4445
case_tester.run_all_multi_stage_cases()
4546

@@ -53,7 +54,7 @@ def test_esp_attr_psram_noinit_multiple_stages(case_tester: Any) -> None:
5354
],
5455
indirect=True,
5556
)
56-
@idf_parametrize('target', ['esp32', 'esp32s2', 'esp32s3', 'esp32p4', 'esp32c5'], indirect=['target'])
57+
@idf_parametrize('target', soc_filtered_targets('SOC_SPIRAM_SUPPORTED == 1'), indirect=['target'])
5758
def test_esp_attr_psram(dut: Dut) -> None:
5859
dut.run_all_single_board_cases()
5960

@@ -62,33 +63,9 @@ def test_esp_attr_psram(dut: Dut) -> None:
6263
@pytest.mark.generic
6364
@pytest.mark.parametrize(
6465
'config',
65-
['xip_psram_esp32s2'],
66-
indirect=True,
67-
)
68-
@idf_parametrize('target', ['esp32s2'], indirect=['target'])
69-
def test_esp_attr_xip_psram_esp32s2(dut: Dut) -> None:
70-
dut.run_all_single_board_cases()
71-
72-
73-
# psram attr tests with xip_psram
74-
@pytest.mark.generic
75-
@pytest.mark.parametrize(
76-
'config',
77-
['xip_psram_esp32s3'],
78-
indirect=True,
79-
)
80-
@idf_parametrize('target', ['esp32s3'], indirect=['target'])
81-
def test_esp_attr_xip_psram_esp32s3(dut: Dut) -> None:
82-
dut.run_all_single_board_cases()
83-
84-
85-
# psram attr tests with xip_psram
86-
@pytest.mark.generic
87-
@pytest.mark.parametrize(
88-
'config',
89-
['xip_psram_esp32p4'],
66+
['xip_psram'],
9067
indirect=True,
9168
)
92-
@idf_parametrize('target', ['esp32p4'], indirect=['target'])
93-
def test_esp_attr_xip_psram_esp32p4(dut: Dut) -> None:
69+
@idf_parametrize('target', soc_filtered_targets('SOC_SPIRAM_XIP_SUPPORTED == 1'), indirect=['target'])
70+
def test_esp_attr_xip_psram(dut: Dut) -> None:
9471
dut.run_all_single_board_cases()

components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32p4 renamed to components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# For XiP PSRAM EXT_RAM_BSS_ATTR
22

3-
CONFIG_IDF_TARGET="esp32p4"
43
CONFIG_SPIRAM=y
54
CONFIG_SPIRAM_XIP_FROM_PSRAM=y
65
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y

components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s2

Lines changed: 0 additions & 8 deletions
This file was deleted.

components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s3

Lines changed: 0 additions & 8 deletions
This file was deleted.

components/esp_psram/device/esp_psram_impl_ap_quad.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include "esp_log.h"
1010
#include "esp_private/esp_psram_impl.h"
1111
#include "rom/spi_flash.h"
12-
#include "rom/opi_flash.h"
1312
#include "esp_rom_gpio.h"
1413
#include "esp_rom_efuse.h"
1514
#include "hal/gpio_hal.h"
@@ -294,7 +293,8 @@ static void s_config_psram_clock(bool init_state)
294293
} else {
295294
// This function can be extended if we have other psram frequency
296295

297-
#if (CONFIG_SPIRAM_SPEED == 80)
296+
#if (CONFIG_SPIRAM_SPEED == 80) || (CONFIG_SPIRAM_SPEED == 48)
297+
// IDF-13632, update 48M to 64M
298298
clock_conf = psram_ctrlr_ll_calculate_clock_reg(1);
299299
#elif (CONFIG_SPIRAM_SPEED == 40)
300300
clock_conf = psram_ctrlr_ll_calculate_clock_reg(2);
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
config SPIRAM
2+
bool "Support for external, SPI-connected RAM"
3+
default "n"
4+
help
5+
This enables support for an external SPI RAM chip, connected in parallel with the
6+
main SPI flash chip.
7+
8+
menu "SPI RAM config"
9+
depends on SPIRAM
10+
11+
choice SPIRAM_MODE
12+
prompt "Mode of SPI RAM chip in use"
13+
default SPIRAM_MODE_QUAD
14+
15+
config SPIRAM_MODE_QUAD
16+
bool "Quad Mode PSRAM"
17+
18+
endchoice
19+
20+
choice SPIRAM_SPEED
21+
prompt "Set RAM clock speed"
22+
default SPIRAM_SPEED_48M
23+
help
24+
Select the speed for the SPI RAM chip.
25+
26+
config SPIRAM_SPEED_48M
27+
bool "48Mhz clock speed"
28+
endchoice
29+
30+
config SPIRAM_SPEED
31+
int
32+
default 48 if SPIRAM_SPEED_48M
33+
default 64 if SPIRAM_SPEED_64M
34+
35+
config SPIRAM_FETCH_INSTRUCTIONS
36+
bool
37+
help
38+
Enable this option allows moving application's instruction segment from the SPI Flash to PSRAM
39+
40+
config SPIRAM_RODATA
41+
bool
42+
help
43+
Enable this option allows moving application's rodata segment from the SPI Flash to
44+
PSRAM
45+
46+
config SPIRAM_XIP_FROM_PSRAM
47+
bool "Enable Executable in place from (XiP) from PSRAM feature (READ HELP)"
48+
default n
49+
select SPIRAM_FETCH_INSTRUCTIONS
50+
select SPIRAM_RODATA
51+
select SPIRAM_FLASH_LOAD_TO_PSRAM
52+
help
53+
If enabled, firmware in flash including instructions and data will be moved into PSRAM on startup,
54+
firmware code will execute directly from PSRAM.
55+
56+
With this option enabled, code that requires execution during an MSPI1 Flash operation
57+
does not have to be placed in IRAM. Therefore codes that need to be executing during Flash
58+
operations can continue working normally.
59+
60+
This feature is useful for high throughput peripheral involved applications to improve
61+
the performance during MSPI1 flash operations.
62+
63+
config SPIRAM_FLASH_LOAD_TO_PSRAM
64+
bool
65+
help
66+
This is a helper indicating this condition:
67+
`CONFIG_SPIRAM_XIP_FROM_PSRAM && CONFIG_IDF_TARGET_ESP32H4`
68+
69+
config SPIRAM_ECC_ENABLE
70+
bool "Enable PSRAM ECC"
71+
default n
72+
help
73+
Enable MSPI Error-Correcting Code function when accessing PSRAM.
74+
75+
If enabled, 1/8 of the PSRAM total size will be reserved for error-correcting code.
76+
77+
source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common" # insert non-chip-specific items here
78+
endmenu
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
| Supported Targets | ESP32 | ESP32-C5 | ESP32-C61 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
2-
| ----------------- | ----- | -------- | --------- | -------- | -------- | -------- |
1+
| Supported Targets | ESP32 | ESP32-C5 | ESP32-C61 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
2+
| ----------------- | ----- | -------- | --------- | -------- | -------- | -------- | -------- |
33

44
This test app is used to test PSRAM

components/esp_rom/esp32h4/include/esp32h4/rom/spi_flash.h

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,124 @@ uint16_t esp_rom_spiflash_common_cmd(esp_rom_spiflash_common_cmd_t *cmd);
455455

456456
extern const spiflash_legacy_funcs_t *rom_spiflash_legacy_funcs;
457457

458+
typedef struct {
459+
uint16_t cmd; /*!< Command value */
460+
uint16_t cmdBitLen; /*!< Command byte length*/
461+
uint32_t *addr; /*!< Point to address value*/
462+
uint32_t addrBitLen; /*!< Address byte length*/
463+
uint32_t *txData; /*!< Point to send data buffer*/
464+
uint32_t txDataBitLen; /*!< Send data byte length.*/
465+
uint32_t *rxData; /*!< Point to receive data buffer*/
466+
uint32_t rxDataBitLen; /*!< Receive Data byte length.*/
467+
uint32_t dummyBitLen;
468+
} esp_rom_spi_cmd_t;
469+
470+
// Definition of MX25UM25645G Octa Flash
471+
// SPI status register
472+
#define ESP_ROM_SPIFLASH_BUSY_FLAG BIT0
473+
#define ESP_ROM_SPIFLASH_WRENABLE_FLAG BIT1
474+
#define ESP_ROM_SPIFLASH_BP0 BIT2
475+
#define ESP_ROM_SPIFLASH_BP1 BIT3
476+
#define ESP_ROM_SPIFLASH_BP2 BIT4
477+
#define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2)
478+
#define ESP_ROM_SPIFLASH_QE BIT9
479+
480+
#define FLASH_OP_MODE_RDCMD_DOUT 0x3B
481+
#define ESP_ROM_FLASH_SECTOR_SIZE 0x1000
482+
#define ESP_ROM_FLASH_BLOCK_SIZE_64K 0x10000
483+
#define ESP_ROM_FLASH_PAGE_SIZE 256
484+
485+
// FLASH commands
486+
#define ROM_FLASH_CMD_RDID 0x9F
487+
#define ROM_FLASH_CMD_WRSR 0x01
488+
#define ROM_FLASH_CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
489+
#define ROM_FLASH_CMD_WREN 0x06
490+
#define ROM_FLASH_CMD_WRDI 0x04
491+
#define ROM_FLASH_CMD_RDSR 0x05
492+
#define ROM_FLASH_CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
493+
#define ROM_FLASH_CMD_ERASE_SEC 0x20
494+
#define ROM_FLASH_CMD_ERASE_BLK_32K 0x52
495+
#define ROM_FLASH_CMD_ERASE_BLK_64K 0xD8
496+
#define ROM_FLASH_CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */
497+
#define ROM_FLASH_CMD_RSTEN 0x66
498+
#define ROM_FLASH_CMD_RST 0x99
499+
500+
#define ROM_FLASH_CMD_SE4B 0x21
501+
#define ROM_FLASH_CMD_SE4B_OCT 0xDE21
502+
#define ROM_FLASH_CMD_BE4B 0xDC
503+
#define ROM_FLASH_CMD_BE4B_OCT 0x23DC
504+
#define ROM_FLASH_CMD_RSTEN_OCT 0x9966
505+
#define ROM_FLASH_CMD_RST_OCT 0x6699
506+
507+
#define ROM_FLASH_CMD_FSTRD4B_STR 0x13EC
508+
#define ROM_FLASH_CMD_FSTRD4B_DTR 0x11EE
509+
#define ROM_FLASH_CMD_FSTRD4B 0x0C
510+
#define ROM_FLASH_CMD_PP4B 0x12
511+
#define ROM_FLASH_CMD_PP4B_OCT 0xED12
512+
513+
#define ROM_FLASH_CMD_RDID_OCT 0x609F
514+
#define ROM_FLASH_CMD_WREN_OCT 0xF906
515+
#define ROM_FLASH_CMD_RDSR_OCT 0xFA05
516+
#define ROM_FLASH_CMD_RDCR2 0x71
517+
#define ROM_FLASH_CMD_RDCR2_OCT 0x8E71
518+
#define ROM_FLASH_CMD_WRCR2 0x72
519+
#define ROM_FLASH_CMD_WRCR2_OCT 0x8D72
520+
521+
// Definitions for GigaDevice GD25LX256E Flash
522+
#define ROM_FLASH_CMD_RDFSR_GD 0x70
523+
#define ROM_FLASH_CMD_RD_GD 0x03
524+
#define ROM_FLASH_CMD_RD4B_GD 0x13
525+
#define ROM_FLASH_CMD_FSTRD_GD 0x0B
526+
#define ROM_FLASH_CMD_FSTRD4B_GD 0x0C
527+
#define ROM_FLASH_CMD_FSTRD_OOUT_GD 0x8B
528+
#define ROM_FLASH_CMD_FSTRD4B_OOUT_GD 0x7C
529+
#define ROM_FLASH_CMD_FSTRD_OIOSTR_GD 0xCB
530+
#define ROM_FLASH_CMD_FSTRD4B_OIOSTR_GD 0xCC
531+
#define ROM_FLASH_CMD_FSTRD4B_OIODTR_GD 0xFD
532+
533+
#define ROM_FLASH_CMD_PP_GD 0x02
534+
#define ROM_FLASH_CMD_PP4B_GD 0x12
535+
#define ROM_FLASH_CMD_PP_OOUT_GD 0x82
536+
#define ROM_FLASH_CMD_PP4B_OOUT_GD 0x84
537+
#define ROM_FLASH_CMD_PP_OIO_GD 0xC2
538+
#define ROM_FLASH_CMD_PP4B_OIOSTR_GD 0x8E
539+
540+
#define ROM_FLASH_CMD_SE_GD 0x20
541+
#define ROM_FLASH_CMD_SE4B_GD 0x21
542+
#define ROM_FLASH_CMD_BE32K_GD 0x52
543+
#define ROM_FLASH_CMD_BE32K4B_GD 0x5C
544+
#define ROM_FLASH_CMD_BE64K_GD 0xD8
545+
#define ROM_FLASH_CMD_BE64K4B_GD 0xDC
546+
547+
#define ROM_FLASH_CMD_EN4B_GD 0xB7
548+
#define ROM_FLASH_CMD_DIS4B_GD 0xE9
549+
550+
// spi user mode command config
551+
/**
552+
* @brief Config the spi user command
553+
* @param spi_num spi port
554+
* @param pcmd pointer to accept the spi command struct
555+
*/
556+
void esp_rom_spi_cmd_config(int spi_num, esp_rom_spi_cmd_t* pcmd);
557+
558+
/**
559+
* @brief Start a spi user command sequence
560+
* @param spi_num spi port
561+
* @param rx_buf buffer pointer to receive data
562+
* @param rx_len receive data length in byte
563+
* @param cs_en_mask decide which cs to use, 0 for cs0, 1 for cs1
564+
* @param is_write_erase to indicate whether this is a write or erase operation, since the CPU would check permission
565+
*/
566+
void esp_rom_spi_cmd_start(int spi_num, uint8_t* rx_buf, uint16_t rx_len, uint8_t cs_en_mask, bool is_write_erase);
567+
568+
// set SPI read/write mode
569+
/**
570+
* @brief Set SPI operation mode
571+
* @param spi_num spi port
572+
* @param mode Flash Read Mode
573+
*/
574+
void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode);
575+
458576
#ifdef __cplusplus
459577
}
460578
#endif

components/esp_system/ld/esp32h4/memory.ld.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ MEMORY
6464
/* (See irom_seg for meaning of 0x20 offset in the above.) */
6565
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
6666

67+
/**
68+
* `extern_ram_seg` and `drom_seg` / `irom_seg` share the same bus and the address region.
69+
* A dummy section is used to avoid overlap. See `.ext_ram.dummy` in `sections.ld.in`
70+
*/
71+
extern_ram_seg(RWX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20
6772
}
6873

6974
/* Heap ends at top of sram_seg */

0 commit comments

Comments
 (0)