diff --git a/components/esp_driver_spi/include/driver/spi_master.h b/components/esp_driver_spi/include/driver/spi_master.h index f225d2b109..ecc5debb1d 100644 --- a/components/esp_driver_spi/include/driver/spi_master.h +++ b/components/esp_driver_spi/include/driver/spi_master.h @@ -78,6 +78,7 @@ typedef struct { delay before the MISO is ready on the line. Leave at 0 unless you know you need a delay. For better timing performance at high frequency (over 8MHz), it's suggest to have the right value. */ + spi_sampling_point_t sample_point; ///< Sample point tuning of spi master receiving bit. int spics_io_num; ///< CS GPIO pin for this device, or -1 if not used uint32_t flags; ///< Bitwise OR of SPI_DEVICE_* flags int queue_size; ///< Transaction queue size. This sets how many transactions can be 'in the air' (queued using spi_device_queue_trans but not yet finished using spi_device_get_trans_result) at the same time diff --git a/components/esp_driver_spi/src/gpspi/spi_master.c b/components/esp_driver_spi/src/gpspi/spi_master.c index d02426f0aa..47cd38262f 100644 --- a/components/esp_driver_spi/src/gpspi/spi_master.c +++ b/components/esp_driver_spi/src/gpspi/spi_master.c @@ -487,6 +487,10 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa SPI_CHECK(ret == ESP_OK, "assigned clock speed not supported", ret); temp_timing_conf.clock_source = clk_src; temp_timing_conf.source_pre_div = clock_source_div; + temp_timing_conf.rx_sample_point = dev_config->sample_point; + if (temp_timing_conf.rx_sample_point == SPI_SAMPLING_POINT_PHASE_1) { + SPI_CHECK(spi_ll_master_is_rx_std_sample_supported(), "SPI_SAMPLING_POINT_PHASE_1 is not supported on this chip", ESP_ERR_NOT_SUPPORTED); + } //Allocate memory for device dev = malloc(sizeof(spi_device_t)); diff --git a/components/hal/esp32/include/hal/spi_ll.h b/components/hal/esp32/include/hal/spi_ll.h index 39f8ad744c..50b43a70cb 100644 --- a/components/hal/esp32/include/hal/spi_ll.h +++ b/components/hal/esp32/include/hal/spi_ll.h @@ -613,6 +613,25 @@ static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) /*------------------------------------------------------------------------------ * Configs: parameters *----------------------------------------------------------------------------*/ +/** + * Set the standard clock mode for master. + * + * @param hw Beginning address of the peripheral registers. + * @param enable_std True for std timing, False for half cycle delay sampling. + */ +static inline void spi_ll_master_set_rx_timing_mode(spi_dev_t *hw, spi_sampling_point_t sample_point) +{ + //This is not supported +} + +/** + * Get if standard clock mode is supported. + */ +static inline bool spi_ll_master_is_rx_std_sample_supported(void) +{ + return false; +} + /** * Set the clock for master by stored value. * @@ -650,7 +669,7 @@ static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n) */ static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ll_clock_val_t *out_reg) { - typeof(SPI1.clock) reg; + typeof(SPI1.clock) reg = {.val = 0}; int eff_clk; //In hw, n, h and l are 1-64, pre is 1-8K. Value written to register is one lower than used value. diff --git a/components/hal/esp32c2/include/hal/spi_ll.h b/components/hal/esp32c2/include/hal/spi_ll.h index 7b83802588..0247195561 100644 --- a/components/hal/esp32c2/include/hal/spi_ll.h +++ b/components/hal/esp32c2/include/hal/spi_ll.h @@ -696,6 +696,25 @@ static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) /*------------------------------------------------------------------------------ * Configs: parameters *----------------------------------------------------------------------------*/ +/** + * Set the standard clock mode for master. + * + * @param hw Beginning address of the peripheral registers. + * @param enable_std True for std timing, False for half cycle delay sampling. + */ +static inline void spi_ll_master_set_rx_timing_mode(spi_dev_t *hw, spi_sampling_point_t sample_point) +{ + //This is not supported +} + +/** + * Get if standard clock mode is supported. + */ +static inline bool spi_ll_master_is_rx_std_sample_supported(void) +{ + return false; +} + /** * Set the clock for master by stored value. * @@ -733,7 +752,7 @@ static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n) */ static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ll_clock_val_t *out_reg) { - typeof(GPSPI2.clock) reg; + typeof(GPSPI2.clock) reg = {.val = 0}; int eff_clk; //In hw, n, h and l are 1-64, pre is 1-8K. Value written to register is one lower than used value. diff --git a/components/hal/esp32c3/include/hal/spi_ll.h b/components/hal/esp32c3/include/hal/spi_ll.h index ae25e2a7eb..df01a819b8 100644 --- a/components/hal/esp32c3/include/hal/spi_ll.h +++ b/components/hal/esp32c3/include/hal/spi_ll.h @@ -698,6 +698,25 @@ static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) /*------------------------------------------------------------------------------ * Configs: parameters *----------------------------------------------------------------------------*/ +/** + * Set the standard clock mode for master. + * + * @param hw Beginning address of the peripheral registers. + * @param enable_std True for std timing, False for half cycle delay sampling. + */ +static inline void spi_ll_master_set_rx_timing_mode(spi_dev_t *hw, spi_sampling_point_t sample_point) +{ + //This is not supported +} + +/** + * Get if standard clock mode is supported. + */ +static inline bool spi_ll_master_is_rx_std_sample_supported(void) +{ + return false; +} + /** * Set the clock for master by stored value. * @@ -735,7 +754,7 @@ static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n) */ static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ll_clock_val_t *out_reg) { - typeof(GPSPI2.clock) reg; + typeof(GPSPI2.clock) reg = {.val = 0}; int eff_clk; //In hw, n, h and l are 1-64, pre is 1-8K. Value written to register is one lower than used value. diff --git a/components/hal/esp32c5/include/hal/spi_ll.h b/components/hal/esp32c5/include/hal/spi_ll.h index d65a2ae2df..943143f3f4 100644 --- a/components/hal/esp32c5/include/hal/spi_ll.h +++ b/components/hal/esp32c5/include/hal/spi_ll.h @@ -696,6 +696,25 @@ static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) /*------------------------------------------------------------------------------ * Configs: parameters *----------------------------------------------------------------------------*/ +/** + * Set the standard clock mode for master. + * + * @param hw Beginning address of the peripheral registers. + * @param enable_std True for std timing, False for half cycle delay sampling. + */ +static inline void spi_ll_master_set_rx_timing_mode(spi_dev_t *hw, spi_sampling_point_t sample_point) +{ + //This is not supported +} + +/** + * Get if standard clock mode is supported. + */ +static inline bool spi_ll_master_is_rx_std_sample_supported(void) +{ + return false; +} + /** * Set the clock for master by stored value. * @@ -733,7 +752,7 @@ static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n) */ static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ll_clock_val_t *out_reg) { - typeof(GPSPI2.clock) reg; + typeof(GPSPI2.clock) reg = {.val = 0}; int eff_clk; //In hw, n, h and l are 1-64, pre is 1-8K. Value written to register is one lower than used value. diff --git a/components/hal/esp32c6/include/hal/spi_ll.h b/components/hal/esp32c6/include/hal/spi_ll.h index 7e3bdc0bd8..2eaa037b27 100644 --- a/components/hal/esp32c6/include/hal/spi_ll.h +++ b/components/hal/esp32c6/include/hal/spi_ll.h @@ -689,6 +689,25 @@ static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) /*------------------------------------------------------------------------------ * Configs: parameters *----------------------------------------------------------------------------*/ +/** + * Set the standard clock mode for master. + * + * @param hw Beginning address of the peripheral registers. + * @param enable_std True for std timing, False for half cycle delay sampling. + */ +static inline void spi_ll_master_set_rx_timing_mode(spi_dev_t *hw, spi_sampling_point_t sample_point) +{ + //This is not supported +} + +/** + * Get if standard clock mode is supported. + */ +static inline bool spi_ll_master_is_rx_std_sample_supported(void) +{ + return false; +} + /** * Set the clock for master by stored value. * @@ -726,7 +745,7 @@ static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n) */ static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ll_clock_val_t *out_reg) { - typeof(GPSPI2.clock) reg; + typeof(GPSPI2.clock) reg = {.val = 0}; int eff_clk; //In hw, n, h and l are 1-64, pre is 1-8K. Value written to register is one lower than used value. diff --git a/components/hal/esp32c61/include/hal/spi_ll.h b/components/hal/esp32c61/include/hal/spi_ll.h index c71bbb2125..7b5c03332e 100644 --- a/components/hal/esp32c61/include/hal/spi_ll.h +++ b/components/hal/esp32c61/include/hal/spi_ll.h @@ -709,6 +709,25 @@ static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) /*------------------------------------------------------------------------------ * Configs: parameters *----------------------------------------------------------------------------*/ +/** + * Set the standard clock mode for master. + * + * @param hw Beginning address of the peripheral registers. + * @param enable_std True for std timing, False for half cycle delay sampling. + */ +static inline void spi_ll_master_set_rx_timing_mode(spi_dev_t *hw, spi_sampling_point_t sample_point) +{ + //This is not supported +} + +/** + * Get if standard clock mode is supported. + */ +static inline bool spi_ll_master_is_rx_std_sample_supported(void) +{ + return false; +} + /** * Set the clock for master by stored value. * @@ -746,7 +765,7 @@ static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n) */ static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ll_clock_val_t *out_reg) { - typeof(GPSPI2.clock) reg; + typeof(GPSPI2.clock) reg = {.val = 0}; int eff_clk; //In hw, n, h and l are 1-64, pre is 1-8K. Value written to register is one lower than used value. diff --git a/components/hal/esp32h2/include/hal/spi_ll.h b/components/hal/esp32h2/include/hal/spi_ll.h index ed4dec39e7..ab8712ff3b 100644 --- a/components/hal/esp32h2/include/hal/spi_ll.h +++ b/components/hal/esp32h2/include/hal/spi_ll.h @@ -20,11 +20,13 @@ #include "esp_types.h" #include "soc/spi_periph.h" #include "soc/spi_struct.h" +#include "soc/chip_revision.h" +#include "soc/pcr_struct.h" #include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" +#include "hal/efuse_hal.h" #include "hal/spi_types.h" -#include "soc/pcr_struct.h" #ifdef __cplusplus extern "C" { @@ -688,6 +690,26 @@ static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) /*------------------------------------------------------------------------------ * Configs: parameters *----------------------------------------------------------------------------*/ +/** + * Set the standard clock mode for master. + * This config take effect only when SPI_CLK (pre-div before periph) div >=2 + * + * @param hw Beginning address of the peripheral registers. + * @param enable_std True for std timing, False for half cycle delay sampling. + */ +static inline void spi_ll_master_set_rx_timing_mode(spi_dev_t *hw, spi_sampling_point_t sample_point) +{ + hw->clock.clk_edge_sel = (sample_point == SPI_SAMPLING_POINT_PHASE_1); +} + +/** + * Get if standard clock mode is supported. + */ +static inline bool spi_ll_master_is_rx_std_sample_supported(void) +{ + return ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 102); +} + /** * Set the clock for master by stored value. * @@ -725,7 +747,7 @@ static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n) */ static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ll_clock_val_t *out_reg) { - typeof(GPSPI2.clock) reg; + typeof(GPSPI2.clock) reg = {.val = 0}; int eff_clk; //In hw, n, h and l are 1-64, pre is 1-8K. Value written to register is one lower than used value. diff --git a/components/hal/esp32p4/include/hal/spi_ll.h b/components/hal/esp32p4/include/hal/spi_ll.h index 955c7f63a6..2b7211f4d6 100644 --- a/components/hal/esp32p4/include/hal/spi_ll.h +++ b/components/hal/esp32p4/include/hal/spi_ll.h @@ -745,6 +745,25 @@ static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) /*------------------------------------------------------------------------------ * Configs: parameters *----------------------------------------------------------------------------*/ +/** + * Set the standard clock mode for master. + * + * @param hw Beginning address of the peripheral registers. + * @param enable_std True for std timing, False for half cycle delay sampling. + */ +static inline void spi_ll_master_set_rx_timing_mode(spi_dev_t *hw, spi_sampling_point_t sample_point) +{ + //This is not supported +} + +/** + * Get if standard clock mode is supported. + */ +static inline bool spi_ll_master_is_rx_std_sample_supported(void) +{ + return false; +} + /** * Set the clock for master by stored value. * @@ -782,7 +801,7 @@ static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n) */ static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ll_clock_val_t *out_reg) { - typeof(GPSPI2.clock) reg; + typeof(GPSPI2.clock) reg = {.val = 0}; int eff_clk; //In hw, n, h and l are 1-64, pre is 1-8K. Value written to register is one lower than used value. diff --git a/components/hal/esp32s2/include/hal/spi_ll.h b/components/hal/esp32s2/include/hal/spi_ll.h index 9b208b78d3..235770ab03 100644 --- a/components/hal/esp32s2/include/hal/spi_ll.h +++ b/components/hal/esp32s2/include/hal/spi_ll.h @@ -688,6 +688,25 @@ static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) /*------------------------------------------------------------------------------ * Configs: parameters *----------------------------------------------------------------------------*/ +/** + * Set the standard clock mode for master. + * + * @param hw Beginning address of the peripheral registers. + * @param enable_std True for std timing, False for half cycle delay sampling. + */ +static inline void spi_ll_master_set_rx_timing_mode(spi_dev_t *hw, spi_sampling_point_t sample_point) +{ + //This is not supported +} + +/** + * Get if standard clock mode is supported. + */ +static inline bool spi_ll_master_is_rx_std_sample_supported(void) +{ + return false; +} + /** * Set the clock for master by stored value. * @@ -725,7 +744,7 @@ static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n) */ static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ll_clock_val_t *out_reg) { - typeof(GPSPI2.clock) reg; + typeof(GPSPI2.clock) reg = {.val = 0}; int eff_clk; //In hw, n, h and l are 1-64, pre is 1-8K. Value written to register is one lower than used value. diff --git a/components/hal/esp32s3/include/hal/spi_ll.h b/components/hal/esp32s3/include/hal/spi_ll.h index 29f69048d2..5427bf6c68 100644 --- a/components/hal/esp32s3/include/hal/spi_ll.h +++ b/components/hal/esp32s3/include/hal/spi_ll.h @@ -717,6 +717,25 @@ static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) /*------------------------------------------------------------------------------ * Configs: parameters *----------------------------------------------------------------------------*/ +/** + * Set the standard clock mode for master. + * + * @param hw Beginning address of the peripheral registers. + * @param enable_std True for std timing, False for half cycle delay sampling. + */ +static inline void spi_ll_master_set_rx_timing_mode(spi_dev_t *hw, spi_sampling_point_t sample_point) +{ + //This is not supported +} + +/** + * Get if standard clock mode is supported. + */ +static inline bool spi_ll_master_is_rx_std_sample_supported(void) +{ + return false; +} + /** * Set the clock for master by stored value. * @@ -754,7 +773,7 @@ static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n) */ static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ll_clock_val_t *out_reg) { - typeof(GPSPI2.clock) reg; + typeof(GPSPI2.clock) reg = {.val = 0}; int eff_clk; //In hw, n, h and l are 1-64, pre is 1-8K. Value written to register is one lower than used value. diff --git a/components/hal/include/hal/spi_hal.h b/components/hal/include/hal/spi_hal.h index 553142682f..c984f9dc19 100644 --- a/components/hal/include/hal/spi_hal.h +++ b/components/hal/include/hal/spi_hal.h @@ -76,6 +76,7 @@ typedef struct { int real_freq; ///< Output of the actual frequency int timing_dummy; ///< Extra dummy needed to compensate the timing int timing_miso_delay; ///< Extra miso delay clocks to compensate the timing + spi_sampling_point_t rx_sample_point;///< Sample data follow standard SPI timing in master mode } spi_hal_timing_conf_t; /** diff --git a/components/hal/include/hal/spi_types.h b/components/hal/include/hal/spi_types.h index 9e41494566..0269259c17 100644 --- a/components/hal/include/hal/spi_types.h +++ b/components/hal/include/hal/spi_types.h @@ -73,6 +73,14 @@ typedef enum { SPI_CMD_HD_INT2 = BIT(9), } spi_command_t; +/** + * @brief SPI master RX sample point mode configuration + */ +typedef enum { + SPI_SAMPLING_POINT_PHASE_0, ///< Data sampling point at 50% cycle delayed then standard timing, (default). + SPI_SAMPLING_POINT_PHASE_1, ///< Data sampling point follows standard SPI timing in master mode +} spi_sampling_point_t; + #ifdef __cplusplus } #endif diff --git a/components/hal/spi_hal_iram.c b/components/hal/spi_hal_iram.c index 9d8ea71c98..90d0f072d0 100644 --- a/components/hal/spi_hal_iram.c +++ b/components/hal/spi_hal_iram.c @@ -21,6 +21,7 @@ void spi_hal_setup_device(spi_hal_context_t *hal, const spi_hal_dev_config_t *de #endif spi_ll_master_set_pos_cs(hw, dev->cs_pin_id, dev->positive_cs); spi_ll_master_set_clock_by_reg(hw, &dev->timing_conf.clock_reg); + spi_ll_master_set_rx_timing_mode(hw, dev->timing_conf.rx_sample_point); //Configure bit order spi_ll_set_rx_lsbfirst(hw, dev->rx_lsbfirst); spi_ll_set_tx_lsbfirst(hw, dev->tx_lsbfirst); diff --git a/components/soc/esp32h2/register/soc/spi_struct.h b/components/soc/esp32h2/register/soc/spi_struct.h index 76644890a5..87368af9eb 100644 --- a/components/soc/esp32h2/register/soc/spi_struct.h +++ b/components/soc/esp32h2/register/soc/spi_struct.h @@ -622,7 +622,15 @@ typedef union { * In the master mode it is pre-divider of spi_clk. Can be configured in CONF state. */ uint32_t clkdiv_pre:4; - uint32_t reserved_22:9; + uint32_t reserved_22:8; + /** clk_edge_sel : R/W; bitpos: [30]; default: 0; + * Configures use standard clock sampling edge or delay the sampling edge by half a + * cycle in master transfer. + * 0: clock sampling edge is delayed by half a cycle. + * 1: clock sampling edge is standard. + * Can be configured in CONF state. Only support on chip version >= 1.2 + */ + uint32_t clk_edge_sel:1; /** clk_equ_sysclk : R/W; bitpos: [31]; default: 1; * In the master mode 1: spi_clk is equal to system 0: spi_clk is divided from system * clock. Can be configured in CONF state. diff --git a/docs/_static/diagrams/spi/spi_mode0_delay.json b/docs/_static/diagrams/spi/spi_mode0_delay.json new file mode 100644 index 0000000000..231f3a90b0 --- /dev/null +++ b/docs/_static/diagrams/spi/spi_mode0_delay.json @@ -0,0 +1,21 @@ +{ + "signal": [ + { + "name": "CS", + "wave": "10.......1" + }, + { + "name": "CLK", + "wave": "lnN......l", + }, + { + "name": "MISO", + "wave": "x22222222x", + "phase": 0, + "data": "7 6 5 4 3 2 1 0" + } + ], + "foot": { + "text": "SPI delayed mode 0" + } +} diff --git a/docs/_static/diagrams/spi/spi_mode0_std.json b/docs/_static/diagrams/spi/spi_mode0_std.json new file mode 100644 index 0000000000..5363745a18 --- /dev/null +++ b/docs/_static/diagrams/spi/spi_mode0_std.json @@ -0,0 +1,22 @@ +{ + "signal": [ + { + "name": "CS", + "wave": "10.......1" + }, + { + "name": "CLK", + "wave": "l.P.......l", + "phase": 0.5 + }, + { + "name": "MISO", + "wave": "x22222222x", + "phase": 0, + "data": "7 6 5 4 3 2 1 0" + } + ], + "foot": { + "text": "SPI normal mode 0" + } +} diff --git a/docs/en/api-reference/peripherals/spi_master.rst b/docs/en/api-reference/peripherals/spi_master.rst index ea9ab65d5e..09da799736 100644 --- a/docs/en/api-reference/peripherals/spi_master.rst +++ b/docs/en/api-reference/peripherals/spi_master.rst @@ -653,6 +653,26 @@ When a transaction length is short, the cost of the transaction interval is high Please note that the ISR is disabled during flash operation by default. To keep sending transactions during flash operations, enable :ref:`CONFIG_SPI_MASTER_ISR_IN_IRAM` and set :c:macro:`ESP_INTR_FLAG_IRAM` in the member :cpp:member:`spi_bus_config_t::intr_flags`. In this case, all the transactions queued before starting flash operations are handled by the ISR in parallel. Also note that the callback of each Device and their ``callee`` functions should be in IRAM, or your callback will crash due to cache missing. For more details, see :ref:`iram-safe-interrupt-handlers`. +.. only:: esp32h2 + + Timing Tuning + ------------- + + .. only:: esp32h2 + + This feature is supported only on chip revision v1.2 or later. + + To accommodate the timing requirements of different slave devices and improve signal stability, GP-SPI controllers support two sampling modes when receiving data: Sample Phase 0 and Sample Phase 1. These can be configured via :cpp:member:`spi_device_interface_config_t::sample_point`. + + Sample Phase 0 (SPI mode 0): + + .. wavedrom:: /../_static/diagrams/spi/spi_mode0_delay.json + + Sample Phase 1 (SPI mode 0): + + .. wavedrom:: /../_static/diagrams/spi/spi_mode0_std.json + + By default, the driver uses sample phase 0, when the slave device adheres to standard SPI timing specifications, sample phase 0 provides more stable data reception at high clock frequencies. .. only:: esp32 diff --git a/docs/zh_CN/api-reference/peripherals/spi_master.rst b/docs/zh_CN/api-reference/peripherals/spi_master.rst index 582ea08617..e647f015bb 100644 --- a/docs/zh_CN/api-reference/peripherals/spi_master.rst +++ b/docs/zh_CN/api-reference/peripherals/spi_master.rst @@ -653,6 +653,26 @@ GPSPI 外设的时钟源可以通过设置 :cpp:member:`spi_device_handle_t::cfg 注意,ISR 在 flash 操作期间默认处于禁用状态。要在 flash 操作期间继续发送传输事务,请启用 :ref:`CONFIG_SPI_MASTER_ISR_IN_IRAM`,并在 :cpp:member:`spi_bus_config_t::intr_flags` 中设置 :c:macro:`ESP_INTR_FLAG_IRAM`。此时,flash 操作前列队的传输事务将由 ISR 并行处理。此外,每个设备的回调和它们的 ``callee`` 函数都应该在 IRAM 中,避免回调因缓存丢失而崩溃。详情请参阅 :ref:`iram-safe-interrupt-handlers`。 +.. only:: esp32h2 + + 时序调整 + -------- + + .. only:: esp32h2 + + 该功能只在芯片版本 v1.2 及以上中支持。 + + 为了适应不同从设备的时序要求,以及提高信号稳定性, GP-SPI 控制器在接收数据时支持两种采样模式:采样模式 0 和采样模式 1 ,可通过 :cpp:member:`spi_device_interface_config_t::sample_point` 进行配置。 + + 采样模式 0 ( SPI mode 0 ): + + .. wavedrom:: /../_static/diagrams/spi/spi_mode0_delay.json + + 采样模式 1 ( SPI mode 0 ): + + .. wavedrom:: /../_static/diagrams/spi/spi_mode0_std.json + + 默认情况下,驱动使用采样模式 0 ,当从设备遵守 SPI 标准时序时,采样模式 0 可以在高时钟频率时更稳定的接收数据。 .. only:: esp32 @@ -661,7 +681,7 @@ GPSPI 外设的时钟源可以通过设置 :cpp:member:`spi_device_handle_t::cfg 时序影响因素 --------------------- - 如图所示,SCLK 发射沿之后、信号被内部寄存器锁存之前,MISO 线存在延迟。因此,MISO 管脚的设置时间是 SPI 时钟速度的限制因素。当延迟过长时,设置松弛度 < 0,违反了设置时序要求,读取可能有误。 + 如图所示, SCLK 发射沿之后、信号被内部寄存器锁存之前, MISO 线存在延迟。因此, MISO 管脚的设置时间是 SPI 时钟速度的限制因素。当延迟过长时,设置松弛度 < 0 ,违反了设置时序要求,读取可能有误。 .. image:: /../_static/spi_miso.png :scale: 40 %