mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 10:40:47 +03:00
Merge branch 'fix/spi_encryption_test_and_guide' into 'master'
fix(driver_spi): add flash encryption test and guide Closes IDF-15060 See merge request espressif/esp-idf!51261
This commit is contained in:
@@ -483,7 +483,9 @@ esp_err_t SPI_COMMON_ISR_ATTR spicommon_dma_setup_priv_buffer(spi_host_device_t
|
||||
need_malloc |= (use_psram || bus_attr->cache_align_int > 1) ? (((uint32_t)buffer | len) & (alignment - 1)) : (((uint32_t)buffer) & (alignment - 1));
|
||||
uint32_t align_len = (len + alignment - 1) & (~(alignment - 1)); // up align alignment
|
||||
ESP_EARLY_LOGV(SPI_TAG, "SPI%d %s %p, len %d, is_ptr_ext %d, use_psram: %d, alignment: %d, need_malloc: %d from %s", host_id + 1, is_tx ? "TX" : "RX", buffer, len, is_ptr_ext, use_psram, alignment, need_malloc, (mem_cap & MALLOC_CAP_SPIRAM) ? "psram" : "internal");
|
||||
|
||||
#if CONFIG_SECURE_FLASH_ENC_ENABLED || CONFIG_SPIRAM_ECC_ENABLE
|
||||
ESP_RETURN_ON_FALSE_ISR(!(use_psram && (len & (alignment - 1))), ESP_ERR_INVALID_ARG, SPI_TAG, "len %d must align to alignment %d when using psram buffer with encryption or ECC", len, alignment);
|
||||
#endif
|
||||
if (need_malloc) {
|
||||
ESP_RETURN_ON_FALSE_ISR(auto_malloc, ESP_ERR_INVALID_STATE, SPI_TAG, "%s addr&len not align to %d, or not dma_capable, suggest use 'heap_caps_malloc' or enable auto_align", is_tx ? "TX" : "RX", alignment);
|
||||
uint32_t *temp = heap_caps_aligned_alloc(alignment, align_len, mem_cap);
|
||||
|
||||
@@ -430,12 +430,14 @@ static esp_err_t SPI_SLAVE_ATTR spi_slave_setup_priv_trans(spi_host_device_t hos
|
||||
}
|
||||
|
||||
bool auto_malloc = (trans->flags & SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO);
|
||||
esp_err_t ret = spicommon_dma_setup_priv_buffer(spihost[host]->id, (uint32_t *)trans->tx_buffer, ((trans->length ? trans->length : trans->tx_length) + 7) / 8, true, true, auto_malloc, &priv_trans->tx_buffer);
|
||||
size_t tx_bytes_len = ((trans->length ? trans->length : trans->tx_length) + 7) / 8;
|
||||
size_t rx_bytes_len = ((trans->length ? trans->length : trans->rx_length) + 7) / 8;
|
||||
esp_err_t ret = spicommon_dma_setup_priv_buffer(spihost[host]->id, (uint32_t *)trans->tx_buffer, tx_bytes_len, true, true, auto_malloc, &priv_trans->tx_buffer);
|
||||
if (ret != ESP_OK) {
|
||||
spi_slave_uninstall_priv_trans(host, priv_trans);
|
||||
return ret;
|
||||
}
|
||||
ret = spicommon_dma_setup_priv_buffer(spihost[host]->id, (uint32_t *)trans->rx_buffer, ((trans->length ? trans->length : trans->rx_length) + 7) / 8, false, true, auto_malloc, &priv_trans->rx_buffer);
|
||||
ret = spicommon_dma_setup_priv_buffer(spihost[host]->id, (uint32_t *)trans->rx_buffer, rx_bytes_len, false, true, auto_malloc, &priv_trans->rx_buffer);
|
||||
if (ret != ESP_OK) {
|
||||
spi_slave_uninstall_priv_trans(host, priv_trans);
|
||||
}
|
||||
|
||||
@@ -2151,7 +2151,7 @@ TEST_CASE("test_spi_master_auto_sleep_retention", "[spi]")
|
||||
|
||||
#if CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE
|
||||
#define TEST_EDMA_PSRAM_TRANS_NUM 5
|
||||
#define TEST_EDMA_TRANS_LEN 20000
|
||||
#define TEST_EDMA_TRANS_LEN 20480
|
||||
#define TEST_EDMA_BUFFER_SZ (TEST_EDMA_PSRAM_TRANS_NUM * TEST_EDMA_TRANS_LEN)
|
||||
|
||||
void test_spi_psram_trans(spi_device_handle_t dev_handle, void *tx, void *rx)
|
||||
@@ -2163,6 +2163,9 @@ void test_spi_psram_trans(spi_device_handle_t dev_handle, void *tx, void *rx)
|
||||
|
||||
int trans_len = TEST_EDMA_TRANS_LEN - TEST_EDMA_PSRAM_TRANS_NUM / 2;
|
||||
for (uint8_t cnt = 0; cnt < TEST_EDMA_PSRAM_TRANS_NUM; cnt ++) {
|
||||
#if CONFIG_SECURE_FLASH_ENC_ENABLED
|
||||
trans_len = TEST_EDMA_TRANS_LEN; // encrypted chip don't support unaligned psram transfer
|
||||
#endif
|
||||
trans_cfg.length = trans_len * 8;
|
||||
trans_cfg.rxlength = trans_len * 8;
|
||||
trans_cfg.flags = (cnt % 2) ? 0 : SPI_TRANS_DMA_USE_PSRAM;
|
||||
@@ -2211,11 +2214,13 @@ TEST_CASE("SPI_Master: PSRAM buffer transaction via EDMA", "[spi]")
|
||||
printf("\n==== %s ====\n", i ? "EDMA" : "Auto Malloc");
|
||||
trans_cfg.flags = i ? SPI_TRANS_DMA_USE_PSRAM : 0;
|
||||
uint32_t before = esp_get_free_heap_size();
|
||||
spi_device_polling_start(dev_handle, &trans_cfg, portMAX_DELAY);
|
||||
TEST_ESP_OK(spi_device_polling_start(dev_handle, &trans_cfg, portMAX_DELAY));
|
||||
uint32_t after = esp_get_free_heap_size();
|
||||
printf("mem_diff: %ld, trans_len: %d\n", after - before, TEST_EDMA_TRANS_LEN);
|
||||
#if !CONFIG_SECURE_FLASH_ENC_ENABLED
|
||||
// rx buffer still potential re-malloc from psram even if SPI_TRANS_DMA_USE_PSRAM is set
|
||||
TEST_ASSERT(i ? (before - after) < 2 * TEST_EDMA_TRANS_LEN : (before - after) > 2 * TEST_EDMA_TRANS_LEN);
|
||||
#endif
|
||||
spi_device_polling_end(dev_handle, portMAX_DELAY);
|
||||
printf("TX fail: %d, RX fail: %d\n", !!(trans_cfg.flags & SPI_TRANS_DMA_TX_FAIL), !!(trans_cfg.flags & SPI_TRANS_DMA_RX_FAIL));
|
||||
if (!i) { // data should be correct if using auto malloc
|
||||
|
||||
@@ -57,6 +57,27 @@ def test_master_single_dev_esp32c5_rev1(case_tester) -> None: # type: ignore
|
||||
case_tester.run_normal_case(case=case, reset=True)
|
||||
|
||||
|
||||
def get_runner_psram_marks(target: str) -> tuple[pytest.MarkDecorator, ...]:
|
||||
if target == 'esp32s3':
|
||||
return (pytest.mark.flash_encryption_f8r8,)
|
||||
return (pytest.mark.flash_encryption,)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'config, target',
|
||||
[
|
||||
pytest.param('flash_enc', target, marks=get_runner_psram_marks(target))
|
||||
for target in soc_filtered_targets('SOC_PSRAM_DMA_CAPABLE == 1 and SOC_GPSPI_SUPPORTED == 1')
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
def test_spi_master_flash_encryption(case_tester) -> None: # type: ignore
|
||||
for case in case_tester.test_menu:
|
||||
if 'test_env' in case.attributes:
|
||||
continue # If `test_env` is defined, should not run on generic runner
|
||||
case_tester.run_normal_case(case=case, reset=True)
|
||||
|
||||
|
||||
# Job for test_env `external_flash` just for esp32 only
|
||||
@pytest.mark.flash_multi
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0x9000
|
||||
CONFIG_SECURE_FLASH_ENC_ENABLED=y
|
||||
CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT=y
|
||||
CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC=y
|
||||
CONFIG_SECURE_BOOT_ALLOW_JTAG=y
|
||||
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC=y
|
||||
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC=y
|
||||
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE=y
|
||||
CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED=y
|
||||
@@ -0,0 +1 @@
|
||||
CONFIG_SPIRAM_MODE_OCT=y
|
||||
@@ -282,8 +282,8 @@ TEST_CASE("test slave using external ram", "[spi]")
|
||||
{
|
||||
custom_setup((TEST_SPI_PERIPH_NUM >= 2) ? TEST_SLAVE_HOST : 0, TEST_SPI_HOST);
|
||||
|
||||
uint8_t *slave_ext_tx = heap_caps_aligned_calloc(32, 1, PSRAM_TRANS_LEN, MALLOC_CAP_SPIRAM);
|
||||
uint8_t *slave_ext_rx = heap_caps_aligned_calloc(32, 1, PSRAM_TRANS_LEN, MALLOC_CAP_SPIRAM);
|
||||
uint8_t *slave_ext_tx = heap_caps_calloc(1, PSRAM_TRANS_LEN, MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA);
|
||||
uint8_t *slave_ext_rx = heap_caps_calloc(1, PSRAM_TRANS_LEN, MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA);
|
||||
uint8_t *master_tx = heap_caps_malloc(PSRAM_TRANS_LEN, MALLOC_CAP_DMA);
|
||||
uint8_t *master_rx = heap_caps_malloc(PSRAM_TRANS_LEN, MALLOC_CAP_DMA);
|
||||
|
||||
@@ -300,7 +300,9 @@ TEST_CASE("test slave using external ram", "[spi]")
|
||||
|
||||
for (int i = 0; i < 6; i ++) {
|
||||
test_fill_random_to_buffers_dualboard(7 + i, master_tx, slave_ext_tx, PSRAM_TRANS_LEN);
|
||||
#if !CONFIG_SECURE_FLASH_ENC_ENABLED // encrypted chip don't support unaligned psram transfer
|
||||
slave_tans.length -= i * 8;
|
||||
#endif
|
||||
master_tans.length = slave_tans.length;
|
||||
master_tans.rxlength = slave_tans.length;
|
||||
ESP_LOGI(SLAVE_TAG, "Test freq: %ld, tx: %p, rx: %p, len: %d", master_tans.override_freq_hz, slave_tans.tx_buffer, slave_tans.rx_buffer, slave_tans.length / 8);
|
||||
@@ -315,7 +317,9 @@ TEST_CASE("test slave using external ram", "[spi]")
|
||||
spi_master_trans_impl_gpio(buscfg, PIN_NUM_CS, 0, (uint8_t *)master_tans.tx_buffer, master_tans.rx_buffer, master_tans.length / 8, false);
|
||||
#endif
|
||||
ESP_LOGI(SLAVE_TAG, "slave malloc: %ld", after - before);
|
||||
#if !CONFIG_SECURE_FLASH_ENC_ENABLED
|
||||
TEST_ASSERT(i ? (before - after) > PSRAM_TRANS_LEN : (before - after) < PSRAM_TRANS_LEN);
|
||||
#endif
|
||||
TEST_ESP_OK(spi_slave_get_trans_result(TEST_SPI_HOST, &out_trans, portMAX_DELAY));
|
||||
|
||||
TEST_ASSERT_EQUAL(master_tans.length, slave_tans.trans_len);
|
||||
|
||||
@@ -31,6 +31,24 @@ def test_slave_single_dev_esp32c5_rev1(case_tester) -> None: # type: ignore
|
||||
case_tester.run_all_normal_cases(reset=True)
|
||||
|
||||
|
||||
def get_runner_psram_marks(target: str) -> tuple[pytest.MarkDecorator, ...]:
|
||||
if target == 'esp32s3':
|
||||
return (pytest.mark.flash_encryption_f8r8,)
|
||||
return (pytest.mark.flash_encryption,)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'config, target',
|
||||
[
|
||||
pytest.param('flash_enc', target, marks=get_runner_psram_marks(target))
|
||||
for target in soc_filtered_targets('SOC_PSRAM_DMA_CAPABLE == 1 and SOC_GPSPI_SUPPORTED == 1')
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
def test_spi_slave_flash_encryption(case_tester) -> None: # type: ignore
|
||||
case_tester.run_all_normal_cases(reset=True)
|
||||
|
||||
|
||||
@pytest.mark.generic_multi_device
|
||||
@pytest.mark.parametrize('count, config', [(2, 'release'), (2, 'iram_safe')], indirect=True)
|
||||
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0x9000
|
||||
CONFIG_SECURE_FLASH_ENC_ENABLED=y
|
||||
CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT=y
|
||||
CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC=y
|
||||
CONFIG_SECURE_BOOT_ALLOW_JTAG=y
|
||||
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC=y
|
||||
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC=y
|
||||
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE=y
|
||||
CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED=y
|
||||
@@ -0,0 +1,3 @@
|
||||
# don't enable s3 psram in default because s3 burger runner don't has psram
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_MODE_OCT=y
|
||||
@@ -6,3 +6,6 @@ CONFIG_COMPILER_OPTIMIZATION_NONE=y
|
||||
CONFIG_ESP_IPC_TASK_STACK_SIZE=2048
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
|
||||
# ESP32-P4 PSRAM halfsleep code/data is placed in SPM, which overflows with -O0 in this config.
|
||||
CONFIG_PM_SLP_SPIRAM_HALFSLEEP_ENABLED=n
|
||||
|
||||
@@ -532,10 +532,10 @@ TEST_CASE("test spi slave hd segment mode, master too long", "[spi][spi_slv_hd]"
|
||||
same_pin_func_sel(0, TEST_SLAVE_HOST, bus_cfg, slave_hd_cfg.spics_io_num);
|
||||
|
||||
const int send_buf_size = 1024;
|
||||
WORD_ALIGNED_ATTR uint8_t* slave_send_buf = malloc(send_buf_size * 2);
|
||||
WORD_ALIGNED_ATTR uint8_t* master_send_buf = malloc(send_buf_size * 2);
|
||||
WORD_ALIGNED_ATTR uint8_t* slave_recv_buf = malloc(send_buf_size * 2);
|
||||
WORD_ALIGNED_ATTR uint8_t* master_recv_buf = malloc(send_buf_size * 2);
|
||||
uint8_t* slave_send_buf = heap_caps_malloc(send_buf_size * 2, MALLOC_CAP_DMA);
|
||||
uint8_t* master_send_buf = heap_caps_malloc(send_buf_size * 2, MALLOC_CAP_DMA);
|
||||
uint8_t* slave_recv_buf = heap_caps_malloc(send_buf_size * 2, MALLOC_CAP_DMA);
|
||||
uint8_t* master_recv_buf = heap_caps_malloc(send_buf_size * 2, MALLOC_CAP_DMA);
|
||||
|
||||
memset(slave_recv_buf, 0xcc, send_buf_size * 2);
|
||||
memset(master_recv_buf, 0xcc, send_buf_size * 2);
|
||||
@@ -1095,16 +1095,19 @@ static esp_err_t (*hd_get_trans_res[2])(spi_host_device_t host_id, spi_slave_cha
|
||||
spi_slave_hd_get_trans_res, spi_slave_hd_get_append_trans_res
|
||||
};
|
||||
|
||||
#define TEST_PSRAM_TRANS_LEN 1000
|
||||
#define TEST_PSRAM_TRANS_LEN 1600
|
||||
TEST_CASE("test slave hd edma segment and append mode", "[spi]")
|
||||
{
|
||||
uint8_t *mst_tx = heap_caps_malloc(TEST_PSRAM_TRANS_LEN, MALLOC_CAP_DEFAULT);
|
||||
uint8_t *mst_rx = heap_caps_malloc(TEST_PSRAM_TRANS_LEN, MALLOC_CAP_DEFAULT);
|
||||
uint8_t *slv_tx = heap_caps_malloc(TEST_PSRAM_TRANS_LEN, MALLOC_CAP_SPIRAM);
|
||||
uint8_t *slv_rx = heap_caps_malloc(TEST_PSRAM_TRANS_LEN, MALLOC_CAP_SPIRAM);
|
||||
uint8_t *slv_tx = heap_caps_malloc(TEST_PSRAM_TRANS_LEN, MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA);
|
||||
uint8_t *slv_rx = heap_caps_malloc(TEST_PSRAM_TRANS_LEN, MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA);
|
||||
spi_slave_hd_data_t *ret_trans, tx_data = {
|
||||
.data = slv_tx,
|
||||
.len = TEST_PSRAM_TRANS_LEN,
|
||||
#if CONFIG_SECURE_FLASH_ENC_ENABLED
|
||||
.flags = SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO, // encrypted chip has different alignment
|
||||
#endif
|
||||
}, rx_data = {
|
||||
.data = slv_rx,
|
||||
.len = TEST_PSRAM_TRANS_LEN,
|
||||
@@ -1120,26 +1123,26 @@ TEST_CASE("test slave hd edma segment and append mode", "[spi]")
|
||||
bus_cfg.flags |= SPICOMMON_BUSFLAG_GPIO_PINS;
|
||||
spi_slave_hd_slot_config_t slave_hd_cfg = SPI_SLOT_TEST_DEFAULT_CONFIG();
|
||||
slave_hd_cfg.flags |= i ? SPI_SLAVE_HD_APPEND_MODE : 0;
|
||||
TEST_ESP_OK(spi_slave_hd_init(TEST_SLAVE_HOST, &bus_cfg, &slave_hd_cfg));
|
||||
same_pin_func_sel(0, TEST_SLAVE_HOST, bus_cfg, slave_hd_cfg.spics_io_num);
|
||||
TEST_ESP_OK(spi_slave_hd_init(TEST_SPI_HOST, &bus_cfg, &slave_hd_cfg));
|
||||
same_pin_func_sel(0, TEST_SPI_HOST, bus_cfg, slave_hd_cfg.spics_io_num);
|
||||
vTaskDelay(1);
|
||||
|
||||
TEST_ESP_OK(hd_trans[i](TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &tx_data, portMAX_DELAY));
|
||||
TEST_ESP_OK(hd_trans[i](TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &rx_data, portMAX_DELAY));
|
||||
TEST_ESP_OK(hd_trans[i](TEST_SPI_HOST, SPI_SLAVE_CHAN_TX, &tx_data, portMAX_DELAY));
|
||||
TEST_ESP_OK(hd_trans[i](TEST_SPI_HOST, SPI_SLAVE_CHAN_RX, &rx_data, portMAX_DELAY));
|
||||
|
||||
// tx append transaction
|
||||
printf("tx %d bytes\n", TEST_PSRAM_TRANS_LEN);
|
||||
essl_sspi_hd_dma_trans_seg(bus_cfg, slave_hd_cfg.spics_io_num, 0, false, mst_tx, TEST_PSRAM_TRANS_LEN, -1);
|
||||
TEST_ESP_OK(hd_get_trans_res[i](TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &ret_trans, portMAX_DELAY));
|
||||
TEST_ESP_OK(hd_get_trans_res[i](TEST_SPI_HOST, SPI_SLAVE_CHAN_RX, &ret_trans, portMAX_DELAY));
|
||||
|
||||
// rx append transaction
|
||||
printf("rx %d bytes\n", TEST_PSRAM_TRANS_LEN);
|
||||
essl_sspi_hd_dma_trans_seg(bus_cfg, slave_hd_cfg.spics_io_num, 0, true, mst_rx, TEST_PSRAM_TRANS_LEN, -1);
|
||||
TEST_ESP_OK(hd_get_trans_res[i](TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY));
|
||||
TEST_ESP_OK(hd_get_trans_res[i](TEST_SPI_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY));
|
||||
|
||||
spitest_cmp_or_dump(slv_rx, mst_tx, TEST_PSRAM_TRANS_LEN);
|
||||
spitest_cmp_or_dump(mst_rx, slv_tx, TEST_PSRAM_TRANS_LEN);
|
||||
spi_slave_hd_deinit(TEST_SLAVE_HOST);
|
||||
spi_slave_hd_deinit(TEST_SPI_HOST);
|
||||
printf("test done\n");
|
||||
}
|
||||
free(mst_tx);
|
||||
|
||||
@@ -25,6 +25,24 @@ def test_slave_hd_single_dev_esp32c5_rev1(case_tester) -> None: # type: ignore
|
||||
case_tester.run_all_normal_cases(reset=True, timeout=180)
|
||||
|
||||
|
||||
def get_runner_psram_marks(target: str) -> tuple[pytest.MarkDecorator, ...]:
|
||||
if target == 'esp32s3':
|
||||
return (pytest.mark.flash_encryption_f8r8,)
|
||||
return (pytest.mark.flash_encryption,)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'config, target',
|
||||
[
|
||||
pytest.param('flash_enc', target, marks=get_runner_psram_marks(target))
|
||||
for target in soc_filtered_targets('SOC_PSRAM_DMA_CAPABLE == 1 and SOC_SPI_SUPPORT_SLAVE_HD_VER2 == 1')
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
def test_spi_slave_hd_flash_encryption(case_tester) -> None: # type: ignore
|
||||
case_tester.run_all_normal_cases(reset=True, timeout=180)
|
||||
|
||||
|
||||
@pytest.mark.generic_multi_device
|
||||
@pytest.mark.parametrize('count, config', [(2, 'release')], indirect=True)
|
||||
@idf_parametrize('target', soc_filtered_targets('SOC_SPI_SUPPORT_SLAVE_HD_VER2 == 1'), indirect=['target'])
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0x9000
|
||||
CONFIG_SECURE_FLASH_ENC_ENABLED=y
|
||||
CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT=y
|
||||
CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC=y
|
||||
CONFIG_SECURE_BOOT_ALLOW_JTAG=y
|
||||
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC=y
|
||||
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC=y
|
||||
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE=y
|
||||
CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED=y
|
||||
@@ -0,0 +1,3 @@
|
||||
# don't enable s3 psram in default because s3 burger runner don't has psram
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_MODE_OCT=y
|
||||
@@ -0,0 +1,2 @@
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0
|
||||
@@ -0,0 +1 @@
|
||||
CONFIG_SPIRAM=y
|
||||
@@ -0,0 +1 @@
|
||||
CONFIG_SPIRAM=y
|
||||
@@ -0,0 +1 @@
|
||||
CONFIG_SPIRAM=y
|
||||
@@ -0,0 +1 @@
|
||||
CONFIG_SPIRAM=y
|
||||
@@ -0,0 +1 @@
|
||||
CONFIG_SPIRAM=y
|
||||
@@ -369,6 +369,10 @@ The example code for the SPI Master driver can be found in the :example:`periphe
|
||||
|
||||
Note that this feature shares bandwidth (bus frequency * bus bits width) with MSPI bus, so GPSPI transfer bandwidth should be less than PSRAM bandwidth, **otherwise transmission data may be lost**. You can check the return value or :c:macro:`SPI_TRANS_DMA_RX_FAIL` and :c:macro:`SPI_TRANS_DMA_TX_FAIL` flags after the transaction is finished to check if error occurs during the transmission. If the transaction returns :c:macro:`ESP_ERR_INVALID_STATE` error, the transaction fails.
|
||||
|
||||
.. note::
|
||||
|
||||
When encryption is enabled, there are stricter alignment requirements for PSRAM buffer transfers, usually only supporting 16-byte alignment. For unaligned transfers, :c:macro:`ESP_ERR_INVALID_ARG` error will be returned. You can switch to internal memory or remove the :c:macro:`SPI_TRANS_DMA_USE_PSRAM` flag.
|
||||
|
||||
Transactions with Data Not Exceeding 32 Bits
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -88,6 +88,10 @@ As not every transaction requires both writing and reading data, you can choose
|
||||
|
||||
Note that this feature shares the MSPI bus bandwidth (bus frequency * bus width), so the transmission bandwidth of the host to this device should be less than the PSRAM bandwidth, otherwise **data may be lost**, and the ``spi_slave_transmit`` function will return the :c:macro:`ESP_ERR_INVALID_STATE` error.
|
||||
|
||||
.. note::
|
||||
|
||||
When encryption is enabled, there are stricter alignment requirements for PSRAM buffer transfers, usually only supporting 16-byte alignment. For unaligned transfers, :c:macro:`ESP_ERR_INVALID_ARG` error will be returned.
|
||||
|
||||
Driver Usage
|
||||
------------
|
||||
|
||||
|
||||
@@ -71,6 +71,10 @@ To send data to the master through the sending DMA channel, the application shou
|
||||
|
||||
Note that this feature shares the MSPI bus bandwidth (bus frequency * bus width), so the transmission bandwidth of the host to this device should be less than the PSRAM bandwidth, otherwise **data may be lost**, and then getting the transmission result will return the :c:macro:`ESP_ERR_INVALID_STATE` error.
|
||||
|
||||
.. note::
|
||||
|
||||
When encryption is enabled, there are stricter alignment requirements for PSRAM buffer transfers, usually only supporting 16-byte alignment. For unaligned transfers, :c:macro:`ESP_ERR_INVALID_ARG` error will be returned.
|
||||
|
||||
The application should check the result of data sending by calling :cpp:func:`spi_slave_hd_get_trans_res` with the channel set as :cpp:enumerator:`SPI_SLAVE_CHAN_TX`. This function blocks until the transaction with the command ``Rd_DMA`` from the master successfully completes (or timeout). The ``out_trans`` argument of the function outputs the pointer of the data descriptor which is just finished, providing information about the sending.
|
||||
|
||||
Receiving data from the master through the receiving DMA channel is quite similar. The application calls :cpp:func:`spi_slave_hd_queue_trans` with proper data descriptor and the channel argument of :cpp:enumerator:`SPI_SLAVE_CHAN_RX`. And the application calls the :cpp:func:`spi_slave_hd_get_trans_res` later to get the descriptor to the receiving buffer before it handles the data in the receiving buffer.
|
||||
|
||||
@@ -365,10 +365,14 @@ SPI 主机驱动程序的示例代码存放在 ESP-IDF 示例项目的 :example:
|
||||
使用 PSRAM 的传输事务
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
{IDF_TARGET_NAME} 支持 GPSPI Master 通过 DMA 直接传输 PSRAM 存储的数据而不用内部额外的零时拷贝,应此可以节省内存,在传输配置中添加 :c:macro:`SPI_TRANS_DMA_USE_PSRAM` 标志信号即可使用。
|
||||
{IDF_TARGET_NAME} 支持 GPSPI Master 通过 DMA 直接传输 PSRAM 存储的数据而不用内部额外的零时拷贝,因此可以节省内存,在传输配置中添加 :c:macro:`SPI_TRANS_DMA_USE_PSRAM` 标志信号即可使用。
|
||||
|
||||
请注意该功能共享 MSPI 总线带宽(总线频率 * 总线位宽),因此 GPSPI 传输带宽应小于 PSRAM 带宽,否则 **可能会丢失传输数据**。可通过在传输结束时检查返回值或 :c:macro:`SPI_TRANS_DMA_RX_FAIL` 和 :c:macro:`SPI_TRANS_DMA_TX_FAIL` 标志信号来判断传输是否发生了错误。若传输事务返回 :c:macro:`ESP_ERR_INVALID_STATE` 错误,则传输事务失败。
|
||||
|
||||
.. note::
|
||||
|
||||
当开启加密功能时,使用 PSRAM Buffer 的传输有更严格的对齐要求,通常为仅支持 16 字节对齐的传输。对于不对齐的传输,会返回 :c:macro:`ESP_ERR_INVALID_ARG` 错误。可改为使用内部内存,或取消 :c:macro:`SPI_TRANS_DMA_USE_PSRAM` 标志。
|
||||
|
||||
传输数据小于 32 位的传输事务
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -88,6 +88,10 @@ SPI 传输事务
|
||||
|
||||
请注意该功能共享 MSPI 总线带宽(总线频率 * 总线位宽),因此主机对该设备的传输带宽应小于 PSRAM 带宽,否则 **可能会丢失传输数据**,此时 ``spi_slave_transmit`` 函数将会返回 :c:macro:`ESP_ERR_INVALID_STATE` 错误。
|
||||
|
||||
.. note::
|
||||
|
||||
当开启加密功能时,使用 PSRAM Buffer 的传输有更严格的对齐要求,通常为仅支持 16 字节对齐的传输。对于不对齐的传输,会返回 :c:macro:`ESP_ERR_INVALID_ARG` 错误。
|
||||
|
||||
使用驱动程序
|
||||
------------
|
||||
|
||||
|
||||
@@ -71,6 +71,10 @@ SPI 从机半双工模式
|
||||
|
||||
请注意该功能共享 MSPI 总线带宽(总线频率 * 总线位宽),因此主机对该设备的传输带宽应小于 PSRAM 带宽,否则 **可能会丢失传输数据**,此时获取传输结果会返回 :c:macro:`ESP_ERR_INVALID_STATE` 错误。
|
||||
|
||||
.. note::
|
||||
|
||||
当开启加密功能时,使用 PSRAM Buffer 的传输有更严格的对齐要求,通常为仅支持 16 字节对齐的传输。对于不对齐的传输,会返回 :c:macro:`ESP_ERR_INVALID_ARG` 错误。
|
||||
|
||||
应用程序需要检查数据发送的结果。为此,应用程序可以调用 :cpp:func:`spi_slave_hd_get_trans_res`,并将通道参数设置为 :cpp:enumerator:`SPI_SLAVE_CHAN_TX`。该函数将阻塞程序,直到主设备发起的 Rd_DMA 命令事务成功完成或超时。函数中的参数 ``out_trans`` 将输出刚刚完成的数据描述符的指针,从而提供有关已完成的发送操作的信息。
|
||||
|
||||
通过 DMA 通道从主设备接收数据的操作与发送数据类似。应用程序需要使用正确的数据描述符调用 :cpp:func:`spi_slave_hd_queue_trans`,并将通道参数设置为 :cpp:enumerator:`SPI_SLAVE_CHAN_RX`。随后,应用程序调用 :cpp:func:`spi_slave_hd_get_trans_res` 获取接收 buffer 的描述符,然后处理接收 buffer 中的数据。
|
||||
|
||||
Reference in New Issue
Block a user