Merge branch 'feat/spi_std_timing_and_bit_trans_v5.4' into 'release/v5.4'

feat(driver_spi): support adjust master rx to standard timing (v5.4)

See merge request espressif/esp-idf!36399
This commit is contained in:
morris
2025-01-23 10:38:07 +08:00
20 changed files with 313 additions and 16 deletions
@@ -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
@@ -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));
+20 -1
View File
@@ -611,6 +611,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.
*
@@ -648,7 +667,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.
+20 -1
View File
@@ -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.
+20 -1
View File
@@ -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.
+20 -1
View File
@@ -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.
+20 -1
View File
@@ -690,6 +690,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.
*
@@ -727,7 +746,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.
+20 -1
View File
@@ -710,6 +710,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.
*
@@ -747,7 +766,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.
+24 -2
View File
@@ -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" {
@@ -689,6 +691,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.
*
@@ -726,7 +748,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.
+20 -1
View File
@@ -746,6 +746,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.
*
@@ -783,7 +802,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.
+20 -1
View File
@@ -687,6 +687,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.
*
@@ -724,7 +743,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.
+20 -1
View File
@@ -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.
+1
View File
@@ -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;
/**
+8 -2
View File
@@ -76,8 +76,15 @@ typedef enum {
SPI_CMD_HD_INT2 = BIT(9),
} spi_command_t;
/** @cond */ //Doxy command to hide preprocessor definitions from docs */
/**
* @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;
/** @cond */ //Doxy command to hide preprocessor definitions from docs */
//alias for different chips, deprecated for the chips after esp32s2
#ifdef CONFIG_IDF_TARGET_ESP32
#define SPI_HOST SPI1_HOST
@@ -89,7 +96,6 @@ typedef enum {
#define FSPI_HOST SPI2_HOST
#define HSPI_HOST SPI3_HOST
#endif
/** @endcond */
#ifdef __cplusplus
+2 -1
View File
@@ -5,7 +5,7 @@
*/
// The HAL layer for SPI (common part, in iram)
// make these functions in a seperate file to make sure all LL functions are in the IRAM.
// make these functions in a separate file to make sure all LL functions are in the IRAM.
#include "hal/spi_hal.h"
#include "hal/assert.h"
@@ -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);
@@ -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.