mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-01 19:54:32 +02:00
spi: fix iomux, timing and address phase issues for esp32s2beta
This commit is contained in:
@@ -85,6 +85,9 @@ static inline void spi_ll_master_init(spi_dev_t *hw)
|
||||
|
||||
//Disable unneeded ints
|
||||
hw->slave.val &= ~SPI_LL_UNUSED_INT_MASK;
|
||||
|
||||
//disable a feature may cause transaction to be too long
|
||||
hw->user.usr_prep_hold = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -781,21 +784,27 @@ static inline void spi_ll_set_address(spi_dev_t *hw, uint64_t addr, int addrlen,
|
||||
* addr[24] -> addr[31]
|
||||
* ...
|
||||
* addr[0] -> addr[7]
|
||||
* slv_wr_status[24] -> slv_wr_status[31]
|
||||
* ...
|
||||
* slv_wr_status[0] -> slv_wr_status[7]
|
||||
* So swap the byte order to let the LSB sent first.
|
||||
*/
|
||||
addr = HAL_SWAP64(addr);
|
||||
if (addrlen > 32) {
|
||||
//The slv_wr_status register bits are sent first, then
|
||||
//bits in addr register is sent.
|
||||
hw->slv_wr_status = addr >> 32;
|
||||
hw->addr = addr;
|
||||
} else {
|
||||
//otherwise only addr register is sent
|
||||
hw->addr = addr >> 32;
|
||||
hw->slv_wr_status = addr;
|
||||
}
|
||||
} else {
|
||||
// shift the address to MSB of addr (and maybe slv_wr_status) register.
|
||||
// output address will be sent from MSB to LSB of addr register, then comes the MSB to LSB of slv_wr_status register.
|
||||
if (addrlen > 32) {
|
||||
hw->addr = addr >> (addrlen - 32);
|
||||
hw->slv_wr_status = addr << (64 - addrlen);
|
||||
// output address will be sent from MSB to LSB of slv_wr_status register, then comes the MSB to
|
||||
// LSB of addr register.
|
||||
hw->addr = addr << (64 - addrlen);
|
||||
hw->slv_wr_status = addr >> (addrlen - 32);
|
||||
} else {
|
||||
// output address will be sent from MSB to LSB of addr register
|
||||
hw->addr = addr << (32 - addrlen);
|
||||
}
|
||||
}
|
||||
|
@@ -168,7 +168,7 @@
|
||||
#define APB_CLK_FREQ_ROM ( 40*1000000 )
|
||||
#define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM
|
||||
#define UART_CLK_FREQ_ROM APB_CLK_FREQ_ROM
|
||||
#define CPU_CLK_FREQ APB_CLK_FREQ
|
||||
#define CPU_CLK_FREQ APB_CLK_FREQ //this may be incorrect, please refer to ESP32_DEFAULT_CPU_FREQ_MHZ
|
||||
#define APB_CLK_FREQ ( 80*1000000 ) //unit: Hz
|
||||
#define REF_CLK_FREQ ( 1000000 )
|
||||
#define UART_CLK_FREQ APB_CLK_FREQ
|
||||
|
@@ -17,7 +17,7 @@
|
||||
#define SOC_SPI_PERIPH_NUM 4
|
||||
#define SOC_SPI_DMA_CHAN_NUM 3
|
||||
|
||||
#define SPI_FUNC_NUM 2
|
||||
#define SPI_FUNC_NUM 0
|
||||
#define SPI_IOMUX_PIN_NUM_HD 27
|
||||
#define SPI_IOMUX_PIN_NUM_CS 29
|
||||
#define SPI_IOMUX_PIN_NUM_MOSI 32
|
||||
|
@@ -87,32 +87,32 @@ int spi_hal_master_cal_clock(int fapb, int hz, int duty_cycle)
|
||||
void spi_hal_cal_timing(int eff_clk, bool gpio_is_used, int input_delay_ns, int *dummy_n, int *miso_delay_n)
|
||||
{
|
||||
const int apbclk_kHz = APB_CLK_FREQ / 1000;
|
||||
//calculate how many apb clocks a period has
|
||||
const int apbclk_n = APB_CLK_FREQ / eff_clk;
|
||||
//how many apb clocks a period has
|
||||
const int spiclk_apb_n = APB_CLK_FREQ / eff_clk;
|
||||
const int gpio_delay_ns = gpio_is_used ? GPIO_MATRIX_DELAY_NS : 0;
|
||||
|
||||
//calculate how many apb clocks the delay is, the 1 is to compensate in case ``input_delay_ns`` is rounded off.
|
||||
int apb_period_n = (1 + input_delay_ns + gpio_delay_ns) * apbclk_kHz / 1000 / 1000;
|
||||
if (apb_period_n < 0) {
|
||||
apb_period_n = 0;
|
||||
//how many apb clocks the delay is, the 1 is to compensate in case ``input_delay_ns`` is rounded off.
|
||||
int delay_apb_n = (1 + input_delay_ns + gpio_delay_ns) * apbclk_kHz / 1000 / 1000;
|
||||
if (delay_apb_n < 0) {
|
||||
delay_apb_n = 0;
|
||||
}
|
||||
|
||||
int dummy_required = apb_period_n / apbclk_n;
|
||||
int dummy_required = delay_apb_n / spiclk_apb_n;
|
||||
|
||||
int miso_delay = 0;
|
||||
if (dummy_required > 0) {
|
||||
//due to the clock delay between master and slave, there's a range in which data is random
|
||||
//give MISO a delay if needed to make sure we sample at the time MISO is stable
|
||||
miso_delay = (dummy_required + 1) * apbclk_n - apb_period_n - 1;
|
||||
miso_delay = (dummy_required + 1) * spiclk_apb_n - delay_apb_n - 1;
|
||||
} else {
|
||||
//if the dummy is not required, maybe we should also delay half a SPI clock if the data comes too early
|
||||
if (apb_period_n * 4 <= apbclk_n) {
|
||||
if (delay_apb_n * 4 <= spiclk_apb_n) {
|
||||
miso_delay = -1;
|
||||
}
|
||||
}
|
||||
*dummy_n = dummy_required;
|
||||
*miso_delay_n = miso_delay;
|
||||
HAL_LOGD(SPI_HAL_TAG, "eff: %d, limit: %dk(/%d), %d dummy, %d delay", eff_clk / 1000, apbclk_kHz / (apb_period_n + 1), apb_period_n, dummy_required, miso_delay);
|
||||
HAL_LOGD(SPI_HAL_TAG, "eff: %d, limit: %dk(/%d), %d dummy, %d delay", eff_clk / 1000, apbclk_kHz / (delay_apb_n + 1), delay_apb_n, dummy_required, miso_delay);
|
||||
}
|
||||
|
||||
int spi_hal_get_freq_limit(bool gpio_is_used, int input_delay_ns)
|
||||
@@ -120,11 +120,11 @@ int spi_hal_get_freq_limit(bool gpio_is_used, int input_delay_ns)
|
||||
const int apbclk_kHz = APB_CLK_FREQ / 1000;
|
||||
const int gpio_delay_ns = gpio_is_used ? GPIO_MATRIX_DELAY_NS : 0;
|
||||
|
||||
//calculate how many apb clocks the delay is, the 1 is to compensate in case ``input_delay_ns`` is rounded off.
|
||||
int apb_period_n = (1 + input_delay_ns + gpio_delay_ns) * apbclk_kHz / 1000 / 1000;
|
||||
if (apb_period_n < 0) {
|
||||
apb_period_n = 0;
|
||||
//how many apb clocks the delay is, the 1 is to compensate in case ``input_delay_ns`` is rounded off.
|
||||
int delay_apb_n = (1 + input_delay_ns + gpio_delay_ns) * apbclk_kHz / 1000 / 1000;
|
||||
if (delay_apb_n < 0) {
|
||||
delay_apb_n = 0;
|
||||
}
|
||||
|
||||
return APB_CLK_FREQ / (apb_period_n + 1);
|
||||
return APB_CLK_FREQ / (delay_apb_n + 1);
|
||||
}
|
Reference in New Issue
Block a user