diff --git a/components/driver/include/driver/spi_master.h b/components/driver/include/driver/spi_master.h index ca8246889..04f2ba1f2 100644 --- a/components/driver/include/driver/spi_master.h +++ b/components/driver/include/driver/spi_master.h @@ -150,6 +150,10 @@ typedef struct spi_device_t* spi_device_handle_t; ///< Handle for a device on a * @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in * DMA-capable memory. * + * @warning The ISR of SPI is always executed on the core which calls this + * function. Never starve the ISR on this core or the SPI transactions will not + * be handled. + * * @return * - ESP_ERR_INVALID_ARG if configuration is invalid * - ESP_ERR_INVALID_STATE if host already is in use diff --git a/components/driver/include/driver/spi_slave.h b/components/driver/include/driver/spi_slave.h index 9ad4b9126..ba0ce1de6 100644 --- a/components/driver/include/driver/spi_slave.h +++ b/components/driver/include/driver/spi_slave.h @@ -71,10 +71,14 @@ struct spi_slave_transaction_t { * it. The SPI hardware has two DMA channels to share. This parameter indicates which * one to use. * - * @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in + * @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in * DMA-capable memory. * - * @return + * @warning The ISR of SPI is always executed on the core which calls this + * function. Never starve the ISR on this core or the SPI transactions will not + * be handled. + * + * @return * - ESP_ERR_INVALID_ARG if configuration is invalid * - ESP_ERR_INVALID_STATE if host already is in use * - ESP_ERR_NO_MEM if out of memory @@ -86,7 +90,7 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b * @brief Free a SPI bus claimed as a SPI slave interface * * @param host SPI peripheral to free - * @return + * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_ERR_INVALID_STATE if not all devices on the bus are freed * - ESP_OK on success @@ -110,7 +114,7 @@ esp_err_t spi_slave_free(spi_host_device_t host); * into the transaction description. * @param ticks_to_wait Ticks to wait until there's room in the queue; use portMAX_DELAY to * never time out. - * @return + * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_OK on success */ @@ -120,19 +124,19 @@ esp_err_t spi_slave_queue_trans(spi_host_device_t host, const spi_slave_transact /** * @brief Get the result of a SPI transaction queued earlier * - * This routine will wait until a transaction to the given device (queued earlier with + * This routine will wait until a transaction to the given device (queued earlier with * spi_slave_queue_trans) has succesfully completed. It will then return the description of the - * completed transaction so software can inspect the result and e.g. free the memory or + * completed transaction so software can inspect the result and e.g. free the memory or * re-use the buffers. * * It is mandatory to eventually use this function for any transaction queued by ``spi_slave_queue_trans``. * * @param host SPI peripheral to that is acting as a slave - * @param[out] trans_desc Pointer to variable able to contain a pointer to the description of the + * @param[out] trans_desc Pointer to variable able to contain a pointer to the description of the * transaction that is executed * @param ticks_to_wait Ticks to wait until there's a returned item; use portMAX_DELAY to never time * out. - * @return + * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_OK on success */ @@ -143,16 +147,16 @@ esp_err_t spi_slave_get_trans_result(spi_host_device_t host, spi_slave_transacti * @brief Do a SPI transaction * * Essentially does the same as spi_slave_queue_trans followed by spi_slave_get_trans_result. Do - * not use this when there is still a transaction queued that hasn't been finalized + * not use this when there is still a transaction queued that hasn't been finalized * using spi_slave_get_trans_result. * * @param host SPI peripheral to that is acting as a slave - * @param trans_desc Pointer to variable able to contain a pointer to the description of the + * @param trans_desc Pointer to variable able to contain a pointer to the description of the * transaction that is executed. Not const because we may want to write status back * into the transaction description. * @param ticks_to_wait Ticks to wait until there's a returned item; use portMAX_DELAY to never time * out. - * @return + * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_OK on success */ diff --git a/components/driver/spi_master.c b/components/driver/spi_master.c index a29182592..7d8932f5e 100644 --- a/components/driver/spi_master.c +++ b/components/driver/spi_master.c @@ -442,14 +442,14 @@ esp_err_t spi_bus_add_device(spi_host_device_t host, const spi_device_interface_ duty_cycle = (dev_config->duty_cycle_pos==0) ? 128 : dev_config->duty_cycle_pos; eff_clk = spi_cal_clock(apbclk, dev_config->clock_speed_hz, duty_cycle, (uint32_t*)&clk_reg); int freq_limit = spi_get_freq_limit(!(spihost[host]->flags&SPICOMMON_BUSFLAG_NATIVE_PINS), dev_config->input_delay_ns); - //GPIO matrix can only change data at 80Mhz rate, which only allows 40MHz SPI clock. - SPI_CHECK(eff_clk <= 40*1000*1000 || spihost[host]->flags&SPICOMMON_BUSFLAG_NATIVE_PINS, "80MHz only supported on iomux pins", ESP_ERR_INVALID_ARG); + //Speed >=40MHz over GPIO matrix needs a dummy cycle, but these don't work for full-duplex connections. spi_get_timing(!(spihost[host]->flags&SPICOMMON_BUSFLAG_NATIVE_PINS), dev_config->input_delay_ns, eff_clk, &dummy_required, &miso_delay); SPI_CHECK( dev_config->flags & SPI_DEVICE_HALFDUPLEX || dummy_required == 0 || dev_config->flags & SPI_DEVICE_NO_DUMMY, -"When GPIO matrix is used in full-duplex mode at frequency > %.1fMHz, device cannot read correct data.\n\ -Please note the SPI can only work at divisors of 80MHz, and the driver always tries to find the closest frequency to your configuration.\n\ +"When work in full-duplex mode at frequency > %.1fMHz, device cannot read correct data.\n\ +Try to use IOMUX pins to increase the frequency limit, or use the half duplex mode.\n\ +Please note the SPI master can only work at divisors of 80MHz, and the driver always tries to find the closest frequency to your configuration.\n\ Specify ``SPI_DEVICE_NO_DUMMY`` to ignore this checking. Then you can output data at higher speed, or read data at your own risk.", ESP_ERR_INVALID_ARG, freq_limit/1000./1000 );