Просмотр исходного кода

Merge branch 'bugfix/fix_spi_hd_quad_issue_esp32c3' into 'master'

essl_spi: fix wrong dummy cycle under quad spi mode ant add a test to verify spi quad mod

Closes IDF-5182 and IDF-5181

See merge request espressif/esp-idf!18680
Gao Xu 3 лет назад
Родитель
Сommit
0da21aca0d

+ 25 - 0
.gitlab/ci/target-test.yml

@@ -990,6 +990,31 @@ UT_S2_SPI_DUAL:
     - ESP32S2_IDF
     - Example_SPI_Multi_device
 
+UT_S2_SPI_QUAD:
+  extends: .unit_test_esp32s2_template
+  tags:
+    - ESP32S2_IDF
+    - Example_SPI_Quad_Multi_device
+
+UT_S3_SPI_QUAD:
+  extends: .unit_test_esp32s3_template
+  tags:
+    - ESP32S3_IDF
+    - Example_SPI_Quad_Multi_device
+
+UT_C2_SPI_QUAD:
+  extends: .unit_test_esp32c2_template
+  tags:
+    - ESP32C2_IDF
+    - Example_SPI_Quad_Multi_device
+    - xtal_40mhz
+
+UT_C3_SPI_QUAD:
+  extends: .unit_test_esp32c3_template
+  tags:
+    - ESP32C3_IDF
+    - Example_SPI_Quad_Multi_device
+
 UT_S2_SDSPI:
   extends: .unit_test_esp32s2_template
   tags:

+ 7 - 0
components/driver/test/include/test/test_common_spi.h

@@ -298,6 +298,13 @@ void same_pin_func_sel(spi_bus_config_t bus, spi_device_interface_config_t dev,
 
 /**
  * This function is used to get tx_buffer used in dual-board test
+ * `master_send_buf` and `slave_send_buf` will be fulfilled with same random numbers with the seed of `seed`.
+ *
+ * @param seed            Random number seed
+ * @param master_send_buf Master TX buffer
+ * @param slave_send_buf  Slave TX buffer
+ * @param send_buf_size   Buffer size
  */
 void get_tx_buffer(uint32_t seed, uint8_t *master_send_buf, uint8_t *slave_send_buf, int send_buf_size);
+
 #endif  //_TEST_COMMON_SPI_H_

+ 2 - 2
components/driver/test/test_common_spi.c

@@ -245,7 +245,7 @@ void get_tx_buffer(uint32_t seed, uint8_t *master_send_buf, uint8_t *slave_send_
 {
     srand(seed);
     for (int i = 0; i < send_buf_size; i++) {
-        slave_send_buf[i] = rand();
-        master_send_buf[i] = rand();
+        slave_send_buf[i] = rand() % 256;
+        master_send_buf[i] = rand() % 256;
     }
 }

+ 148 - 16
components/driver/test/test_spi_slave_hd.c

@@ -16,16 +16,14 @@
 #include "soc/spi_periph.h"
 #include "driver/spi_master.h"
 #include "esp_serial_slave_link/essl_spi.h"
-
-
-#if (TEST_SPI_PERIPH_NUM >= 2)
-//These will be only enabled on chips with 2 or more SPI peripherals
+#include "test/test_common_spi.h"
 
 #if SOC_SPI_SUPPORT_SLAVE_HD_VER2
 #include "driver/spi_slave_hd.h"
+
+#if (TEST_SPI_PERIPH_NUM >= 2) //These will be only enabled on chips with 2 or more SPI peripherals
+
 #include "esp_rom_gpio.h"
-#include "unity.h"
-#include "test/test_common_spi.h"
 
 #define TEST_DMA_MAX_SIZE    4092
 #define TEST_BUFFER_SIZE 256     ///< buffer size of each wrdma buffer in fifo mode
@@ -57,7 +55,6 @@ typedef struct {
     spi_slave_hd_data_t rx_data;
 } testhd_context_t;
 
-
 static uint32_t get_hd_flags(void)
 {
 #if !defined(SLAVE_SUPPORT_QIO)
@@ -595,13 +592,9 @@ TEST_CASE("test spi slave hd segment mode, master too long", "[spi][spi_slv_hd]"
     master_free_device_bus(spi);
 }
 
-#endif //SOC_SPI_SUPPORT_SLAVE_HD_VER2
 #endif //#if (TEST_SPI_PERIPH_NUM >= 2)
 
-
 #if (TEST_SPI_PERIPH_NUM == 1)
-#if SOC_SPI_SUPPORT_SLAVE_HD_VER2
-#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2)
 //These tests are for chips which only have 1 SPI controller
 /********************************************************************************
  *      Test By Master & Slave (2 boards)
@@ -616,9 +609,6 @@ TEST_CASE("test spi slave hd segment mode, master too long", "[spi][spi_slv_hd]"
  *      GND | GND        | GND        |
  *
  ********************************************************************************/
-#include "driver/spi_slave_hd.h"
-#include "unity.h"
-#include "test/test_common_spi.h"
 
 static void hd_master(void)
 {
@@ -749,6 +739,148 @@ static void hd_slave(void)
 }
 
 TEST_CASE_MULTIPLE_DEVICES("SPI Slave HD: segment mode, master sends too long", "[spi_ms][test_env=Example_SPI_Multi_device]", hd_master, hd_slave);
-#endif //!TEMPORARY_DISABLED_FOR_TARGETS(...)
-#endif  //#if SOC_SPI_SUPPORT_SLAVE_HD_VER2
 #endif  //#if (TEST_SPI_PERIPH_NUM == 1)
+
+/**
+ *  TODO IDF-5483
+ **/
+#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
+
+#define BUF_SIZE 256
+
+static void hd_master_quad(void){
+    spi_bus_config_t bus_cfg = {
+        .miso_io_num = PIN_NUM_MISO,
+        .mosi_io_num = PIN_NUM_MOSI,
+        .sclk_io_num = PIN_NUM_CLK,
+        .quadwp_io_num = PIN_NUM_WP,
+        .quadhd_io_num = PIN_NUM_HD
+    };
+
+    TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &bus_cfg, SPI_DMA_CH_AUTO));
+
+    spi_device_handle_t spi;
+    spi_device_interface_config_t dev_cfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
+    dev_cfg.flags = SPI_DEVICE_HALFDUPLEX;
+    dev_cfg.command_bits = 8;
+    dev_cfg.address_bits = 8;
+    dev_cfg.dummy_bits = 8;
+    dev_cfg.clock_speed_hz = 100 * 1000;
+
+    TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &dev_cfg, &spi));
+
+    WORD_ALIGNED_ATTR uint8_t *master_send_buf = heap_caps_malloc(BUF_SIZE, MALLOC_CAP_DMA);
+    WORD_ALIGNED_ATTR uint8_t *master_recv_buf = heap_caps_calloc(BUF_SIZE, 1, MALLOC_CAP_DMA);
+    //This buffer is used for 2-board test and should be assigned totally the same as the ``hd_slave`` does.
+    WORD_ALIGNED_ATTR uint8_t *slave_send_buf = heap_caps_malloc(BUF_SIZE, MALLOC_CAP_DMA);
+    get_tx_buffer(199, master_send_buf, slave_send_buf, BUF_SIZE);
+
+    unity_wait_for_signal("slave ready");
+    essl_spi_wrdma(spi, master_send_buf, BUF_SIZE / 2, -1, SPI_TRANS_MODE_QIO);
+
+    unity_wait_for_signal("slave ready");
+    essl_spi_wrdma(spi, master_send_buf + BUF_SIZE / 2, BUF_SIZE / 2, -1, SPI_TRANS_MODE_QIO);
+
+    unity_wait_for_signal("slave ready");
+    essl_spi_rddma(spi, master_recv_buf, BUF_SIZE / 2, -1, SPI_TRANS_MODE_QIO);
+
+    unity_wait_for_signal("slave ready");
+    essl_spi_rddma(spi, master_recv_buf+ BUF_SIZE / 2, BUF_SIZE / 2, -1, SPI_TRANS_MODE_QIO);
+
+    ESP_LOG_BUFFER_HEX("slave send", slave_send_buf, BUF_SIZE);
+    ESP_LOG_BUFFER_HEX("master recv", master_recv_buf, BUF_SIZE);
+
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(slave_send_buf, master_recv_buf, BUF_SIZE);
+
+    free(master_recv_buf);
+    free(master_send_buf);
+    free(slave_send_buf);
+
+    master_free_device_bus(spi);
+}
+
+static void hd_slave_quad(void){
+
+    spi_bus_config_t bus_cfg = {
+        .miso_io_num = PIN_NUM_MISO,
+        .mosi_io_num = PIN_NUM_MOSI,
+        .sclk_io_num = PIN_NUM_CLK,
+        .quadwp_io_num = PIN_NUM_WP,
+        .quadhd_io_num = PIN_NUM_HD,
+        .max_transfer_sz = 14000 * 30
+    };
+
+    spi_slave_hd_slot_config_t slave_hd_cfg = {
+        .spics_io_num = PIN_NUM_CS,
+        .dma_chan = SPI_DMA_CH_AUTO,
+        .flags = 0,
+        .mode = 0,
+        .command_bits = 8,
+        .address_bits = 8,
+        .dummy_bits = 8,
+        .queue_size = 10,
+    };
+    TEST_ESP_OK(spi_slave_hd_init(TEST_SLAVE_HOST, &bus_cfg, &slave_hd_cfg));
+
+    WORD_ALIGNED_ATTR uint8_t *slave_send_buf = heap_caps_malloc(BUF_SIZE, MALLOC_CAP_DMA);
+    WORD_ALIGNED_ATTR uint8_t *slave_recv_buf = heap_caps_calloc(BUF_SIZE, 1, MALLOC_CAP_DMA);
+    //This buffer is used for 2-board test and should be assigned totally the same as the ``hd_master`` does.
+    WORD_ALIGNED_ATTR uint8_t *master_send_buf = heap_caps_malloc(BUF_SIZE, MALLOC_CAP_DMA);
+    get_tx_buffer(199, master_send_buf, slave_send_buf, BUF_SIZE);
+
+    int trans_len = BUF_SIZE / 2;
+    spi_slave_hd_data_t slave_trans[4] = {
+        //recv, the buffer size should be aligned to 4
+        {
+            .data = slave_recv_buf,
+            .len = (trans_len + 3) & (~3),
+        },
+        {
+            .data = slave_recv_buf+BUF_SIZE/2,
+            .len = (trans_len + 3) & (~3),
+        },
+        //send
+        {
+            .data = slave_send_buf,
+            .len = (trans_len + 3) & (~3),
+        },
+          {
+            .data = slave_send_buf+BUF_SIZE/2,
+            .len = (trans_len + 3) & (~3),
+        },
+    };
+
+    for (int i = 0; i < 2; i ++) {
+        TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &slave_trans[i], portMAX_DELAY));
+        unity_send_signal("slave ready");
+    }
+    for (int i = 2; i < 4; i ++) {
+        TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &slave_trans[i], portMAX_DELAY));
+        unity_send_signal("slave ready");
+    }
+    for (int i = 0; i < 2; i ++) {
+        spi_slave_hd_data_t *ret_trans;
+        TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &ret_trans, portMAX_DELAY));
+    }
+    for (int i = 2; i < 4; i ++) {
+        spi_slave_hd_data_t *ret_trans;
+        TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY));
+    }
+
+    ESP_LOG_BUFFER_HEX("master send", master_send_buf, BUF_SIZE);
+    ESP_LOG_BUFFER_HEX("slave recv", slave_recv_buf, BUF_SIZE);
+
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(master_send_buf, slave_recv_buf, BUF_SIZE);
+
+    free(slave_recv_buf);
+    free(slave_send_buf);
+    free(master_send_buf);
+
+    spi_slave_hd_deinit(TEST_SLAVE_HOST);
+}
+
+TEST_CASE_MULTIPLE_DEVICES("SPI quad hd test ", "[spi_ms][test_env=Example_SPI_Quad_Multi_device]", hd_master_quad, hd_slave_quad);
+
+#endif  // #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
+
+#endif //SOC_SPI_SUPPORT_SLAVE_HD_VER2

+ 35 - 32
components/esp_serial_slave_link/essl_spi.c

@@ -13,8 +13,8 @@
 #include "esp_private/periph_ctrl.h"
 #include "essl_internal.h"
 #include "essl_spi.h"
-#include "essl_spi/esp32s2_defs.h"
-
+#include "hal/spi_types.h"
+#include "hal/spi_ll.h"
 
 /**
  * Initialise device function list of SPI by this macro.
@@ -51,51 +51,54 @@ typedef struct {
     } master_in;
 } essl_spi_context_t;
 
-
-static uint16_t get_hd_command(uint16_t cmd_i, uint32_t flags)
+static uint16_t get_hd_command(spi_command_t cmd_t, uint32_t flags)
 {
-    //have no prefixes
-    if (cmd_i == CMD_HD_EN_QPI_REG) return cmd_i;
-    //doesn't support 4-line commands
-    if(flags & SPI_TRANS_MODE_QIO && flags & SPI_TRANS_MODE_DIOQIO_ADDR &&
-       (cmd_i == CMD_HD_WR_END_REG || cmd_i == CMD_HD_INT0_REG ||
-       cmd_i == CMD_HD_INT1_REG || cmd_i == CMD_HD_INT2_REG)) {
-           //the transaction will be sent in corresponding 1/2/4 bit mode, without address and data.
-           //the CMD will have no 0xA- prefix
-           return cmd_i;
-    }
+    spi_line_mode_t line_mode = {
+        .cmd_lines = 1,
+    };
 
     if (flags & SPI_TRANS_MODE_DIO) {
+        line_mode.data_lines = 2;
         if (flags & SPI_TRANS_MODE_DIOQIO_ADDR) {
-            return cmd_i | CMD_HD_DIO_MODE;
+            line_mode.addr_lines = 2;
         } else {
-            return cmd_i | CMD_HD_DOUT_MODE;
+            line_mode.addr_lines = 1;
         }
     } else if (flags & SPI_TRANS_MODE_QIO) {
+        line_mode.data_lines = 4;
         if (flags & SPI_TRANS_MODE_DIOQIO_ADDR) {
-            return cmd_i | CMD_HD_QIO_MODE;
+            line_mode.addr_lines = 4;
         } else {
-            return cmd_i | CMD_HD_QOUT_MODE;
+            line_mode.addr_lines = 1;
         }
+    } else {
+        line_mode.data_lines = 1;
+        line_mode.addr_lines = 1;
     }
-    return cmd_i | CMD_HD_ONEBIT_MODE;
+
+    return spi_ll_get_slave_hd_command(cmd_t, line_mode);
 }
 
 static int get_hd_dummy_bits(uint32_t flags)
 {
-    //dummy is always 4 cycles when dual or quad mode is enabled. Otherwise 8 cycles in normal mode.
-    if (flags & (SPI_TRANS_MODE_DIO | SPI_TRANS_MODE_QIO)) {
-        return 4;
+    spi_line_mode_t line_mode = {};
+
+    if (flags & SPI_TRANS_MODE_DIO) {
+        line_mode.data_lines = 2;
+    } else if (flags & SPI_TRANS_MODE_QIO) {
+        line_mode.data_lines = 4;
     } else {
-        return 8;
+        line_mode.data_lines = 1;
     }
+
+    return spi_ll_get_slave_hd_dummy_bits(line_mode);
 }
 
 esp_err_t essl_spi_rdbuf(spi_device_handle_t spi, uint8_t *out_data, int addr, int len, uint32_t flags)
 {
     spi_transaction_ext_t t = {
         .base = {
-            .cmd = get_hd_command(CMD_HD_RDBUF_REG, flags),
+            .cmd = get_hd_command(SPI_CMD_HD_RDBUF, flags),
             .addr = addr % 72,
             .rxlength = len * 8,
             .rx_buffer = out_data,
@@ -111,7 +114,7 @@ esp_err_t essl_spi_rdbuf_polling(spi_device_handle_t spi, uint8_t *out_data, int
 {
     spi_transaction_ext_t t = {
         .base = {
-            .cmd = get_hd_command(CMD_HD_RDBUF_REG, flags),
+            .cmd = get_hd_command(SPI_CMD_HD_RDBUF, flags),
             .addr = addr % 72,
             .rxlength = len * 8,
             .rx_buffer = out_data,
@@ -127,7 +130,7 @@ esp_err_t essl_spi_wrbuf(spi_device_handle_t spi, const uint8_t *data, int addr,
 {
     spi_transaction_ext_t t = {
         .base = {
-            .cmd = get_hd_command(CMD_HD_WRBUF_REG, flags),
+            .cmd = get_hd_command(SPI_CMD_HD_WRBUF, flags),
             .addr = addr % 72,
             .length = len * 8,
             .tx_buffer = data,
@@ -142,7 +145,7 @@ esp_err_t essl_spi_wrbuf_polling(spi_device_handle_t spi, const uint8_t *data, i
 {
     spi_transaction_ext_t t = {
         .base = {
-            .cmd = get_hd_command(CMD_HD_WRBUF_REG, flags),
+            .cmd = get_hd_command(SPI_CMD_HD_WRBUF, flags),
             .addr = addr % 72,
             .length = len * 8,
             .tx_buffer = data,
@@ -157,7 +160,7 @@ esp_err_t essl_spi_rddma_seg(spi_device_handle_t spi, uint8_t *out_data, int seg
 {
     spi_transaction_ext_t t = {
         .base = {
-            .cmd = get_hd_command(CMD_HD_RDDMA_REG, flags),
+            .cmd = get_hd_command(SPI_CMD_HD_RDDMA, flags),
             .rxlength = seg_len * 8,
             .rx_buffer = out_data,
             .flags = flags | SPI_TRANS_VARIABLE_DUMMY,
@@ -170,7 +173,7 @@ esp_err_t essl_spi_rddma_seg(spi_device_handle_t spi, uint8_t *out_data, int seg
 esp_err_t essl_spi_rddma_done(spi_device_handle_t spi, uint32_t flags)
 {
     spi_transaction_t end_t = {
-        .cmd = get_hd_command(CMD_HD_INT0_REG, flags),
+        .cmd = get_hd_command(SPI_CMD_HD_INT0, flags),
         .flags = flags,
     };
     return spi_device_transmit(spi, &end_t);
@@ -201,7 +204,7 @@ esp_err_t essl_spi_wrdma_seg(spi_device_handle_t spi, const uint8_t *data, int s
 {
     spi_transaction_ext_t t = {
         .base = {
-            .cmd = get_hd_command(CMD_HD_WRDMA_REG, flags),
+            .cmd = get_hd_command(SPI_CMD_HD_WRDMA, flags),
             .length = seg_len * 8,
             .tx_buffer = data,
             .flags = flags | SPI_TRANS_VARIABLE_DUMMY,
@@ -214,7 +217,7 @@ esp_err_t essl_spi_wrdma_seg(spi_device_handle_t spi, const uint8_t *data, int s
 esp_err_t essl_spi_wrdma_done(spi_device_handle_t spi, uint32_t flags)
 {
     spi_transaction_t end_t = {
-        .cmd = get_hd_command(CMD_HD_WR_END_REG, flags),
+        .cmd = get_hd_command(SPI_CMD_HD_WR_END, flags),
         .flags = flags,
     };
     return spi_device_transmit(spi, &end_t);
@@ -243,7 +246,7 @@ esp_err_t essl_spi_wrdma(spi_device_handle_t spi, const uint8_t *data, int len,
 esp_err_t essl_spi_int(spi_device_handle_t spi, int int_n, uint32_t flags)
 {
     spi_transaction_t end_t = {
-        .cmd = get_hd_command(CMD_HD_INT0_REG + int_n, flags),
+        .cmd = get_hd_command(SPI_CMD_HD_INT0 + int_n, flags),
         .flags = flags,
     };
     return spi_device_transmit(spi, &end_t);

+ 0 - 30
components/esp_serial_slave_link/include/essl_spi/esp32c2_defs.h

@@ -1,30 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-
-#pragma once
-
-// NOTE: From the view of master
-#define CMD_HD_WRBUF_REG    0x01
-#define CMD_HD_RDBUF_REG    0x02
-#define CMD_HD_WRDMA_REG    0x03
-#define CMD_HD_RDDMA_REG    0x04
-
-#define CMD_HD_ONEBIT_MODE  0x00
-#define CMD_HD_DOUT_MODE    0x10
-#define CMD_HD_QOUT_MODE    0x20
-#define CMD_HD_DIO_MODE     0x50
-#define CMD_HD_QIO_MODE     0xA0
-
-#define CMD_HD_SEG_END_REG  0x05
-#define CMD_HD_EN_QPI_REG   0x06
-#define CMD_HD_WR_END_REG   0x07
-#define CMD_HD_INT0_REG     0x08
-#define CMD_HD_INT1_REG     0x09
-#define CMD_HD_INT2_REG     0x0A
-#define CMD_HD_EX_QPI_REG   0xDD
-
-#define SPI_SLAVE_HD_BUFFER_SIZE 64

+ 0 - 38
components/esp_serial_slave_link/include/essl_spi/esp32c3_defs.h

@@ -1,38 +0,0 @@
-// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-
-#pragma once
-
-// NOTE: From the view of master
-#define CMD_HD_WRBUF_REG    0x01
-#define CMD_HD_RDBUF_REG    0x02
-#define CMD_HD_WRDMA_REG    0x03
-#define CMD_HD_RDDMA_REG    0x04
-
-#define CMD_HD_ONEBIT_MODE  0x00
-#define CMD_HD_DOUT_MODE    0x10
-#define CMD_HD_QOUT_MODE    0x20
-#define CMD_HD_DIO_MODE     0x50
-#define CMD_HD_QIO_MODE     0xA0
-
-#define CMD_HD_SEG_END_REG  0x05
-#define CMD_HD_EN_QPI_REG   0x06
-#define CMD_HD_WR_END_REG   0x07
-#define CMD_HD_INT0_REG     0x08
-#define CMD_HD_INT1_REG     0x09
-#define CMD_HD_INT2_REG     0x0A
-#define CMD_HD_EX_QPI_REG   0xDD
-
-#define SPI_SLAVE_HD_BUFFER_SIZE 64

+ 0 - 30
components/esp_serial_slave_link/include/essl_spi/esp32h2_defs.h

@@ -1,30 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-
-#pragma once
-
-// NOTE: From the view of master
-#define CMD_HD_WRBUF_REG    0x01
-#define CMD_HD_RDBUF_REG    0x02
-#define CMD_HD_WRDMA_REG    0x03
-#define CMD_HD_RDDMA_REG    0x04
-
-#define CMD_HD_ONEBIT_MODE  0x00
-#define CMD_HD_DOUT_MODE    0x10
-#define CMD_HD_QOUT_MODE    0x20
-#define CMD_HD_DIO_MODE     0x50
-#define CMD_HD_QIO_MODE     0xA0
-
-#define CMD_HD_SEG_END_REG  0x05
-#define CMD_HD_EN_QPI_REG   0x06
-#define CMD_HD_WR_END_REG   0x07
-#define CMD_HD_INT0_REG     0x08
-#define CMD_HD_INT1_REG     0x09
-#define CMD_HD_INT2_REG     0x0A
-#define CMD_HD_EX_QPI_REG   0xDD
-
-#define SPI_SLAVE_HD_BUFFER_SIZE 64

+ 0 - 38
components/esp_serial_slave_link/include/essl_spi/esp32s2_defs.h

@@ -1,38 +0,0 @@
-// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-
-#pragma once
-
-// NOTE: From the view of master
-#define CMD_HD_WRBUF_REG    0x01
-#define CMD_HD_RDBUF_REG    0x02
-#define CMD_HD_WRDMA_REG    0x03
-#define CMD_HD_RDDMA_REG    0x04
-
-#define CMD_HD_ONEBIT_MODE  0x00
-#define CMD_HD_DOUT_MODE    0x10
-#define CMD_HD_QOUT_MODE    0x20
-#define CMD_HD_DIO_MODE     0x50
-#define CMD_HD_QIO_MODE     0xA0
-
-#define CMD_HD_SEG_END_REG  0x05
-#define CMD_HD_EN_QPI_REG   0x06
-#define CMD_HD_WR_END_REG   0x07
-#define CMD_HD_INT0_REG     0x08
-#define CMD_HD_INT1_REG     0x09
-#define CMD_HD_INT2_REG     0x0A
-#define CMD_HD_EX_QPI_REG   0xDD
-
-#define SPI_SLAVE_HD_BUFFER_SIZE 72

+ 0 - 38
components/esp_serial_slave_link/include/essl_spi/esp32s3_defs.h

@@ -1,38 +0,0 @@
-// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-
-#pragma once
-
-// NOTE: From the view of master
-#define CMD_HD_WRBUF_REG    0x01
-#define CMD_HD_RDBUF_REG    0x02
-#define CMD_HD_WRDMA_REG    0x03
-#define CMD_HD_RDDMA_REG    0x04
-
-#define CMD_HD_ONEBIT_MODE  0x00
-#define CMD_HD_DOUT_MODE    0x10
-#define CMD_HD_QOUT_MODE    0x20
-#define CMD_HD_DIO_MODE     0x50
-#define CMD_HD_QIO_MODE     0xA0
-
-#define CMD_HD_SEG_END_REG  0x05
-#define CMD_HD_EN_QPI_REG   0x06
-#define CMD_HD_WR_END_REG   0x07
-#define CMD_HD_INT0_REG     0x08
-#define CMD_HD_INT1_REG     0x09
-#define CMD_HD_INT2_REG     0x0A
-#define CMD_HD_EX_QPI_REG   0xDD
-
-#define SPI_SLAVE_HD_BUFFER_SIZE 64

+ 23 - 0
components/hal/esp32/include/hal/spi_ll.h

@@ -1081,6 +1081,29 @@ static inline void spi_dma_ll_enable_out_auto_wrback(spi_dma_dev_t *dma_out, uin
     //does not configure it in ESP32
 }
 
+/**
+ * Get the spi communication command
+ *
+ * @param cmd_t           Base command value
+ * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
+ */
+static inline uint16_t spi_ll_get_slave_hd_command(spi_command_t cmd_t, spi_line_mode_t line_mode)
+{
+    //This is not supported in esp32
+    return 0;
+}
+
+/**
+ * Get the dummy bits
+ *
+ * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
+ */
+static inline int spi_ll_get_slave_hd_dummy_bits(spi_line_mode_t line_mode)
+{
+    //This is not supported in esp32
+    return 0;
+}
+
 #undef SPI_LL_RST_MASK
 #undef SPI_LL_UNUSED_INT_MASK
 

+ 102 - 0
components/hal/esp32c2/include/hal/spi_ll.h

@@ -74,6 +74,21 @@ typedef enum {
 } spi_ll_trans_len_cond_t;
 FLAG_ATTR(spi_ll_trans_len_cond_t)
 
+// SPI base command in esp32c2
+typedef enum {
+     /* Slave HD Only */
+    SPI_LL_BASE_CMD_HD_WRBUF    = 0x01,
+    SPI_LL_BASE_CMD_HD_RDBUF    = 0x02,
+    SPI_LL_BASE_CMD_HD_WRDMA    = 0x03,
+    SPI_LL_BASE_CMD_HD_RDDMA    = 0x04,
+    SPI_LL_BASE_CMD_HD_SEG_END  = 0x05,
+    SPI_LL_BASE_CMD_HD_EN_QPI   = 0x06,
+    SPI_LL_BASE_CMD_HD_WR_END   = 0x07,
+    SPI_LL_BASE_CMD_HD_INT0     = 0x08,
+    SPI_LL_BASE_CMD_HD_INT1     = 0x09,
+    SPI_LL_BASE_CMD_HD_INT2     = 0x0A,
+} spi_ll_base_command_t;
+
 /*------------------------------------------------------------------------------
  * Control
  *----------------------------------------------------------------------------*/
@@ -1073,6 +1088,93 @@ static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw)
     return hw->slave1.last_addr;
 }
 
+/**
+ * Get the base spi command in esp32c2
+ *
+ * @param cmd_t           Command value
+ */
+static inline uint8_t spi_ll_get_slave_hd_base_command(spi_command_t cmd_t)
+{
+    uint8_t cmd_base = 0x00;
+    switch (cmd_t)
+    {
+    case SPI_CMD_HD_WRBUF:
+        cmd_base = SPI_LL_BASE_CMD_HD_WRBUF;
+        break;
+    case SPI_CMD_HD_RDBUF:
+        cmd_base = SPI_LL_BASE_CMD_HD_RDBUF;
+        break;
+    case SPI_CMD_HD_WRDMA:
+        cmd_base = SPI_LL_BASE_CMD_HD_WRDMA;
+        break;
+    case SPI_CMD_HD_RDDMA:
+        cmd_base = SPI_LL_BASE_CMD_HD_RDDMA;
+        break;
+    case SPI_CMD_HD_SEG_END:
+        cmd_base = SPI_LL_BASE_CMD_HD_SEG_END;
+        break;
+    case SPI_CMD_HD_EN_QPI:
+        cmd_base = SPI_LL_BASE_CMD_HD_EN_QPI;
+        break;
+    case SPI_CMD_HD_WR_END:
+        cmd_base = SPI_LL_BASE_CMD_HD_WR_END;
+        break;
+    case SPI_CMD_HD_INT0:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT0;
+        break;
+    case SPI_CMD_HD_INT1:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT1;
+        break;
+    case SPI_CMD_HD_INT2:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT2;
+        break;
+    default:
+        HAL_ASSERT(cmd_base);
+    }
+    return cmd_base;
+}
+
+/**
+ * Get the spi communication command
+ *
+ * @param cmd_t           Base command value
+ * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
+ */
+static inline uint16_t spi_ll_get_slave_hd_command(spi_command_t cmd_t, spi_line_mode_t line_mode)
+{
+    uint8_t cmd_base = spi_ll_get_slave_hd_base_command(cmd_t);
+    uint8_t cmd_mod = 0x00; //CMD:1-bit, ADDR:1-bit, DATA:1-bit
+
+    if (line_mode.data_lines == 2) {
+        if (line_mode.addr_lines == 2) {
+            cmd_mod = 0x50; //CMD:1-bit, ADDR:2-bit, DATA:2-bit
+        } else {
+            cmd_mod = 0x10; //CMD:1-bit, ADDR:1-bit, DATA:2-bit
+        }
+    } else if (line_mode.data_lines == 4) {
+        if (line_mode.addr_lines == 4) {
+            cmd_mod = 0xA0; //CMD:1-bit, ADDR:4-bit, DATA:4-bit
+        } else {
+            cmd_mod = 0x20; //CMD:1-bit, ADDR:1-bit, DATA:4-bit
+        }
+    }
+    if (cmd_base == SPI_LL_BASE_CMD_HD_SEG_END || cmd_base == SPI_LL_BASE_CMD_HD_EN_QPI) {
+        cmd_mod = 0x00;
+    }
+
+    return cmd_base | cmd_mod;
+}
+
+/**
+ * Get the dummy bits
+ *
+ * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
+ */
+static inline int spi_ll_get_slave_hd_dummy_bits(spi_line_mode_t line_mode)
+{
+    return 8;
+}
+
 #undef SPI_LL_RST_MASK
 #undef SPI_LL_UNUSED_INT_MASK
 

+ 102 - 0
components/hal/esp32c3/include/hal/spi_ll.h

@@ -74,6 +74,21 @@ typedef enum {
 } spi_ll_trans_len_cond_t;
 FLAG_ATTR(spi_ll_trans_len_cond_t)
 
+// SPI base command in esp32c3
+typedef enum {
+     /* Slave HD Only */
+    SPI_LL_BASE_CMD_HD_WRBUF    = 0x01,
+    SPI_LL_BASE_CMD_HD_RDBUF    = 0x02,
+    SPI_LL_BASE_CMD_HD_WRDMA    = 0x03,
+    SPI_LL_BASE_CMD_HD_RDDMA    = 0x04,
+    SPI_LL_BASE_CMD_HD_SEG_END  = 0x05,
+    SPI_LL_BASE_CMD_HD_EN_QPI   = 0x06,
+    SPI_LL_BASE_CMD_HD_WR_END   = 0x07,
+    SPI_LL_BASE_CMD_HD_INT0     = 0x08,
+    SPI_LL_BASE_CMD_HD_INT1     = 0x09,
+    SPI_LL_BASE_CMD_HD_INT2     = 0x0A,
+} spi_ll_base_command_t;
+
 /*------------------------------------------------------------------------------
  * Control
  *----------------------------------------------------------------------------*/
@@ -1076,6 +1091,93 @@ static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw)
 #undef SPI_LL_RST_MASK
 #undef SPI_LL_UNUSED_INT_MASK
 
+/**
+ * Get the base spi command in esp32c3
+ *
+ * @param cmd_t           Command value
+ */
+static inline uint8_t spi_ll_get_slave_hd_base_command(spi_command_t cmd_t)
+{
+    uint8_t cmd_base = 0x00;
+    switch (cmd_t)
+    {
+    case SPI_CMD_HD_WRBUF:
+        cmd_base = SPI_LL_BASE_CMD_HD_WRBUF;
+        break;
+    case SPI_CMD_HD_RDBUF:
+        cmd_base = SPI_LL_BASE_CMD_HD_RDBUF;
+        break;
+    case SPI_CMD_HD_WRDMA:
+        cmd_base = SPI_LL_BASE_CMD_HD_WRDMA;
+        break;
+    case SPI_CMD_HD_RDDMA:
+        cmd_base = SPI_LL_BASE_CMD_HD_RDDMA;
+        break;
+    case SPI_CMD_HD_SEG_END:
+        cmd_base = SPI_LL_BASE_CMD_HD_SEG_END;
+        break;
+    case SPI_CMD_HD_EN_QPI:
+        cmd_base = SPI_LL_BASE_CMD_HD_EN_QPI;
+        break;
+    case SPI_CMD_HD_WR_END:
+        cmd_base = SPI_LL_BASE_CMD_HD_WR_END;
+        break;
+    case SPI_CMD_HD_INT0:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT0;
+        break;
+    case SPI_CMD_HD_INT1:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT1;
+        break;
+    case SPI_CMD_HD_INT2:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT2;
+        break;
+    default:
+        HAL_ASSERT(cmd_base);
+    }
+    return cmd_base;
+}
+
+/**
+ * Get the spi communication command
+ *
+ * @param cmd_t           Base command value
+ * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
+ */
+static inline uint16_t spi_ll_get_slave_hd_command(spi_command_t cmd_t, spi_line_mode_t line_mode)
+{
+    uint8_t cmd_base = spi_ll_get_slave_hd_base_command(cmd_t);
+    uint8_t cmd_mod = 0x00; //CMD:1-bit, ADDR:1-bit, DATA:1-bit
+
+    if (line_mode.data_lines == 2) {
+        if (line_mode.addr_lines == 2) {
+            cmd_mod = 0x50; //CMD:1-bit, ADDR:2-bit, DATA:2-bit
+        } else {
+            cmd_mod = 0x10; //CMD:1-bit, ADDR:1-bit, DATA:2-bit
+        }
+    } else if (line_mode.data_lines == 4) {
+        if (line_mode.addr_lines == 4) {
+            cmd_mod = 0xA0; //CMD:1-bit, ADDR:4-bit, DATA:4-bit
+        } else {
+            cmd_mod = 0x20; //CMD:1-bit, ADDR:1-bit, DATA:4-bit
+        }
+    }
+    if (cmd_base == SPI_LL_BASE_CMD_HD_SEG_END || cmd_base == SPI_LL_BASE_CMD_HD_EN_QPI) {
+        cmd_mod = 0x00;
+    }
+
+    return cmd_base | cmd_mod;
+}
+
+/**
+ * Get the dummy bits
+ *
+ * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
+ */
+static inline int spi_ll_get_slave_hd_dummy_bits(spi_line_mode_t line_mode)
+{
+    return 8;
+}
+
 #ifdef __cplusplus
 }
 #endif

+ 102 - 0
components/hal/esp32h2/include/hal/spi_ll.h

@@ -74,6 +74,21 @@ typedef enum {
 } spi_ll_trans_len_cond_t;
 FLAG_ATTR(spi_ll_trans_len_cond_t)
 
+// SPI base command in esp32h2
+typedef enum {
+     /* Slave HD Only */
+    SPI_LL_BASE_CMD_HD_WRBUF    = 0x01,
+    SPI_LL_BASE_CMD_HD_RDBUF    = 0x02,
+    SPI_LL_BASE_CMD_HD_WRDMA    = 0x03,
+    SPI_LL_BASE_CMD_HD_RDDMA    = 0x04,
+    SPI_LL_BASE_CMD_HD_SEG_END  = 0x05,
+    SPI_LL_BASE_CMD_HD_EN_QPI   = 0x06,
+    SPI_LL_BASE_CMD_HD_WR_END   = 0x07,
+    SPI_LL_BASE_CMD_HD_INT0     = 0x08,
+    SPI_LL_BASE_CMD_HD_INT1     = 0x09,
+    SPI_LL_BASE_CMD_HD_INT2     = 0x0A,
+} spi_ll_base_command_t;
+
 /*------------------------------------------------------------------------------
  * Control
  *----------------------------------------------------------------------------*/
@@ -1074,6 +1089,93 @@ static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw)
 #undef SPI_LL_RST_MASK
 #undef SPI_LL_UNUSED_INT_MASK
 
+/**
+ * Get the base spi command in esp32h2
+ *
+ * @param cmd_t           Command value
+ */
+static inline uint8_t spi_ll_get_slave_hd_base_command(spi_command_t cmd_t)
+{
+    uint8_t cmd_base = 0x00;
+    switch (cmd_t)
+    {
+    case SPI_CMD_HD_WRBUF:
+        cmd_base = SPI_LL_BASE_CMD_HD_WRBUF;
+        break;
+    case SPI_CMD_HD_RDBUF:
+        cmd_base = SPI_LL_BASE_CMD_HD_RDBUF;
+        break;
+    case SPI_CMD_HD_WRDMA:
+        cmd_base = SPI_LL_BASE_CMD_HD_WRDMA;
+        break;
+    case SPI_CMD_HD_RDDMA:
+        cmd_base = SPI_LL_BASE_CMD_HD_RDDMA;
+        break;
+    case SPI_CMD_HD_SEG_END:
+        cmd_base = SPI_LL_BASE_CMD_HD_SEG_END;
+        break;
+    case SPI_CMD_HD_EN_QPI:
+        cmd_base = SPI_LL_BASE_CMD_HD_EN_QPI;
+        break;
+    case SPI_CMD_HD_WR_END:
+        cmd_base = SPI_LL_BASE_CMD_HD_WR_END;
+        break;
+    case SPI_CMD_HD_INT0:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT0;
+        break;
+    case SPI_CMD_HD_INT1:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT1;
+        break;
+    case SPI_CMD_HD_INT2:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT2;
+        break;
+    default:
+        HAL_ASSERT(cmd_base);
+    }
+    return cmd_base;
+}
+
+/**
+ * Get the spi communication command
+ *
+ * @param cmd_t           Base command value
+ * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
+ */
+static inline uint16_t spi_ll_get_slave_hd_command(spi_command_t cmd_t, spi_line_mode_t line_mode)
+{
+    uint8_t cmd_base = spi_ll_get_slave_hd_base_command(cmd_t);
+    uint8_t cmd_mod = 0x00; //CMD:1-bit, ADDR:1-bit, DATA:1-bit
+
+    if (line_mode.data_lines == 2) {
+        if (line_mode.addr_lines == 2) {
+            cmd_mod = 0x50; //CMD:1-bit, ADDR:2-bit, DATA:2-bit
+        } else {
+            cmd_mod = 0x10; //CMD:1-bit, ADDR:1-bit, DATA:2-bit
+        }
+    } else if (line_mode.data_lines == 4) {
+        if (line_mode.addr_lines == 4) {
+            cmd_mod = 0xA0; //CMD:1-bit, ADDR:4-bit, DATA:4-bit
+        } else {
+            cmd_mod = 0x20; //CMD:1-bit, ADDR:1-bit, DATA:4-bit
+        }
+    }
+    if (cmd_base == SPI_LL_BASE_CMD_HD_SEG_END || cmd_base == SPI_LL_BASE_CMD_HD_EN_QPI) {
+        cmd_mod = 0x00;
+    }
+
+    return cmd_base | cmd_mod;
+}
+
+/**
+ * Get the dummy bits
+ *
+ * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
+ */
+static inline int spi_ll_get_slave_hd_dummy_bits(spi_line_mode_t line_mode)
+{
+    return 4;
+}
+
 #ifdef __cplusplus
 }
 #endif

+ 113 - 0
components/hal/esp32s2/include/hal/spi_ll.h

@@ -84,6 +84,21 @@ typedef enum {
 } spi_ll_trans_len_cond_t;
 FLAG_ATTR(spi_ll_trans_len_cond_t)
 
+// SPI base command in esp32s2
+typedef enum {
+     /* Slave HD Only */
+    SPI_LL_BASE_CMD_HD_WRBUF    = 0x01,
+    SPI_LL_BASE_CMD_HD_RDBUF    = 0x02,
+    SPI_LL_BASE_CMD_HD_WRDMA    = 0x03,
+    SPI_LL_BASE_CMD_HD_RDDMA    = 0x04,
+    SPI_LL_BASE_CMD_HD_SEG_END  = 0x05,
+    SPI_LL_BASE_CMD_HD_EN_QPI   = 0x06,
+    SPI_LL_BASE_CMD_HD_WR_END   = 0x07,
+    SPI_LL_BASE_CMD_HD_INT0     = 0x08,
+    SPI_LL_BASE_CMD_HD_INT1     = 0x09,
+    SPI_LL_BASE_CMD_HD_INT2     = 0x0A,
+} spi_ll_base_command_t;
+
 /*------------------------------------------------------------------------------
  * Control
  *----------------------------------------------------------------------------*/
@@ -1278,6 +1293,104 @@ static inline bool spi_ll_tx_get_empty_err(spi_dev_t *hw)
 #undef SPI_LL_RST_MASK
 #undef SPI_LL_UNUSED_INT_MASK
 
+/**
+ * Get the base spi command in esp32s2
+ *
+ * @param cmd_t           Command value
+ */
+static inline uint8_t spi_ll_get_slave_hd_base_command(spi_command_t cmd_t)
+{
+    uint8_t cmd_base = 0x00;
+    switch (cmd_t)
+    {
+    case SPI_CMD_HD_WRBUF:
+        cmd_base = SPI_LL_BASE_CMD_HD_WRBUF;
+        break;
+    case SPI_CMD_HD_RDBUF:
+        cmd_base = SPI_LL_BASE_CMD_HD_RDBUF;
+        break;
+    case SPI_CMD_HD_WRDMA:
+        cmd_base = SPI_LL_BASE_CMD_HD_WRDMA;
+        break;
+    case SPI_CMD_HD_RDDMA:
+        cmd_base = SPI_LL_BASE_CMD_HD_RDDMA;
+        break;
+    case SPI_CMD_HD_SEG_END:
+        cmd_base = SPI_LL_BASE_CMD_HD_SEG_END;
+        break;
+    case SPI_CMD_HD_EN_QPI:
+        cmd_base = SPI_LL_BASE_CMD_HD_EN_QPI;
+        break;
+    case SPI_CMD_HD_WR_END:
+        cmd_base = SPI_LL_BASE_CMD_HD_WR_END;
+        break;
+    case SPI_CMD_HD_INT0:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT0;
+        break;
+    case SPI_CMD_HD_INT1:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT1;
+        break;
+    case SPI_CMD_HD_INT2:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT2;
+        break;
+    default:
+        HAL_ASSERT(cmd_base);
+    }
+    return cmd_base;
+}
+
+/**
+ * Get the spi communication command
+ *
+ * @param cmd_t           Base command value
+ * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
+ */
+static inline uint16_t spi_ll_get_slave_hd_command(spi_command_t cmd_t, spi_line_mode_t line_mode)
+{
+    uint8_t cmd_base = spi_ll_get_slave_hd_base_command(cmd_t);
+    uint8_t cmd_mod = 0x00; //CMD:1-bit, ADDR:1-bit, DATA:1-bit
+
+    if (line_mode.data_lines == 2) {
+        if (line_mode.addr_lines == 2) {
+            cmd_mod = 0x50; //CMD:1-bit, ADDR:2-bit, DATA:2-bit
+        } else {
+            cmd_mod = 0x10; //CMD:1-bit, ADDR:1-bit, DATA:2-bit
+        }
+    } else if (line_mode.data_lines == 4) {
+        if (line_mode.addr_lines == 4) {
+            cmd_mod = 0xA0; //CMD:1-bit, ADDR:4-bit, DATA:4-bit
+        } else {
+            cmd_mod = 0x20; //CMD:1-bit, ADDR:1-bit, DATA:4-bit
+        }
+    }
+    if (cmd_base == SPI_LL_BASE_CMD_HD_SEG_END || cmd_base == SPI_LL_BASE_CMD_HD_EN_QPI) {
+        cmd_mod = 0x00;
+    }
+
+    return cmd_base | cmd_mod;
+}
+
+/**
+ * Get the dummy bits
+ *
+ * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
+ */
+static inline int spi_ll_get_slave_hd_dummy_bits(spi_line_mode_t line_mode)
+{
+    uint8_t dummy_bits = 0;
+
+    if (line_mode.data_lines == 2) {
+        dummy_bits = 4;
+    } else if (line_mode.data_lines == 4) {
+        dummy_bits = 4;
+    } else {
+        dummy_bits = 8;
+    }
+
+    HAL_ASSERT(dummy_bits);
+    return dummy_bits;
+}
+
 #ifdef __cplusplus
 }
 #endif

+ 102 - 0
components/hal/esp32s3/include/hal/spi_ll.h

@@ -76,6 +76,21 @@ typedef enum {
 } spi_ll_trans_len_cond_t;
 FLAG_ATTR(spi_ll_trans_len_cond_t)
 
+// SPI base command in esp32s3
+typedef enum {
+     /* Slave HD Only */
+    SPI_LL_BASE_CMD_HD_WRBUF    = 0x01,
+    SPI_LL_BASE_CMD_HD_RDBUF    = 0x02,
+    SPI_LL_BASE_CMD_HD_WRDMA    = 0x03,
+    SPI_LL_BASE_CMD_HD_RDDMA    = 0x04,
+    SPI_LL_BASE_CMD_HD_SEG_END  = 0x05,
+    SPI_LL_BASE_CMD_HD_EN_QPI   = 0x06,
+    SPI_LL_BASE_CMD_HD_WR_END   = 0x07,
+    SPI_LL_BASE_CMD_HD_INT0     = 0x08,
+    SPI_LL_BASE_CMD_HD_INT1     = 0x09,
+    SPI_LL_BASE_CMD_HD_INT2     = 0x0A,
+} spi_ll_base_command_t;
+
 /*------------------------------------------------------------------------------
  * Control
  *----------------------------------------------------------------------------*/
@@ -1091,6 +1106,93 @@ static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw)
 #undef SPI_LL_RST_MASK
 #undef SPI_LL_UNUSED_INT_MASK
 
+/**
+ * Get the base spi command in esp32s3
+ *
+ * @param cmd_t           Command value
+ */
+static inline uint8_t spi_ll_get_slave_hd_base_command(spi_command_t cmd_t)
+{
+    uint8_t cmd_base = 0x00;
+    switch (cmd_t)
+    {
+    case SPI_CMD_HD_WRBUF:
+        cmd_base = SPI_LL_BASE_CMD_HD_WRBUF;
+        break;
+    case SPI_CMD_HD_RDBUF:
+        cmd_base = SPI_LL_BASE_CMD_HD_RDBUF;
+        break;
+    case SPI_CMD_HD_WRDMA:
+        cmd_base = SPI_LL_BASE_CMD_HD_WRDMA;
+        break;
+    case SPI_CMD_HD_RDDMA:
+        cmd_base = SPI_LL_BASE_CMD_HD_RDDMA;
+        break;
+    case SPI_CMD_HD_SEG_END:
+        cmd_base = SPI_LL_BASE_CMD_HD_SEG_END;
+        break;
+    case SPI_CMD_HD_EN_QPI:
+        cmd_base = SPI_LL_BASE_CMD_HD_EN_QPI;
+        break;
+    case SPI_CMD_HD_WR_END:
+        cmd_base = SPI_LL_BASE_CMD_HD_WR_END;
+        break;
+    case SPI_CMD_HD_INT0:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT0;
+        break;
+    case SPI_CMD_HD_INT1:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT1;
+        break;
+    case SPI_CMD_HD_INT2:
+        cmd_base = SPI_LL_BASE_CMD_HD_INT2;
+        break;
+    default:
+        HAL_ASSERT(cmd_base);
+    }
+    return cmd_base;
+}
+
+/**
+ * Get the spi communication command
+ *
+ * @param cmd_t           Base command value
+ * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
+ */
+static inline uint16_t spi_ll_get_slave_hd_command(spi_command_t cmd_t, spi_line_mode_t line_mode)
+{
+    uint8_t cmd_base = spi_ll_get_slave_hd_base_command(cmd_t);
+    uint8_t cmd_mod = 0x00; //CMD:1-bit, ADDR:1-bit, DATA:1-bit
+
+    if (line_mode.data_lines == 2) {
+        if (line_mode.addr_lines == 2) {
+            cmd_mod = 0x50; //CMD:1-bit, ADDR:2-bit, DATA:2-bit
+        } else {
+            cmd_mod = 0x10; //CMD:1-bit, ADDR:1-bit, DATA:2-bit
+        }
+    } else if (line_mode.data_lines == 4) {
+        if (line_mode.addr_lines == 4) {
+            cmd_mod = 0xA0; //CMD:1-bit, ADDR:4-bit, DATA:4-bit
+        } else {
+            cmd_mod = 0x20; //CMD:1-bit, ADDR:1-bit, DATA:4-bit
+        }
+    }
+    if (cmd_base == SPI_LL_BASE_CMD_HD_SEG_END || cmd_base == SPI_LL_BASE_CMD_HD_EN_QPI) {
+        cmd_mod = 0x00;
+    }
+
+    return cmd_base | cmd_mod;
+}
+
+/**
+ * Get the dummy bits
+ *
+ * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
+ */
+static inline int spi_ll_get_slave_hd_dummy_bits(spi_line_mode_t line_mode)
+{
+    return 8;
+}
+
 #ifdef __cplusplus
 }
 #endif

+ 16 - 0
components/hal/include/hal/spi_types.h

@@ -53,6 +53,22 @@ typedef struct {
     uint8_t data_lines;   ///< The line width of data phase, e.g. 4-line-data-phase.
 } spi_line_mode_t;
 
+/**
+ * @brief SPI command.
+ */
+typedef enum {
+     /* Slave HD Only */
+    SPI_CMD_HD_WRBUF    = BIT(0),
+    SPI_CMD_HD_RDBUF    = BIT(1),
+    SPI_CMD_HD_WRDMA    = BIT(2),
+    SPI_CMD_HD_RDDMA    = BIT(3),
+    SPI_CMD_HD_SEG_END  = BIT(4),
+    SPI_CMD_HD_EN_QPI   = BIT(5),
+    SPI_CMD_HD_WR_END   = BIT(6),
+    SPI_CMD_HD_INT0     = BIT(7),
+    SPI_CMD_HD_INT1     = BIT(8),
+    SPI_CMD_HD_INT2     = BIT(9),
+} spi_command_t;
 
 /** @cond */    //Doxy command to hide preprocessor definitions from docs */