mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/spi_example' into 'master'
SPI: Various fixes (examples, mem leak, arg check) - Fix SPI master example to use DMA-capable memory for display initialization. Fixes https://github.com/espressif/esp-idf/issues/551 - SPI master: Do not leak DMA descriptor pointer array on free - SPI Master/Slave: Check if DMA'ed buffers actually live in DMA-capable memory See merge request !735
This commit is contained in:
commit
a41ac2d21d
@ -100,6 +100,10 @@ typedef struct spi_device_t* spi_device_handle_t; ///< Handle for a device on a
|
|||||||
* for a SPI bus allows transfers on the bus to have sizes only limited by the amount of
|
* for a SPI bus allows transfers on the bus to have sizes only limited by the amount of
|
||||||
* internal memory. Selecting no DMA channel (by passing the value 0) limits the amount of
|
* internal memory. Selecting no DMA channel (by passing the value 0) limits the amount of
|
||||||
* bytes transfered to a maximum of 32.
|
* bytes transfered to a maximum of 32.
|
||||||
|
*
|
||||||
|
* @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in
|
||||||
|
* DMA-capable memory.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* - ESP_ERR_INVALID_ARG if configuration is invalid
|
* - ESP_ERR_INVALID_ARG if configuration is invalid
|
||||||
* - ESP_ERR_INVALID_STATE if host already is in use
|
* - ESP_ERR_INVALID_STATE if host already is in use
|
||||||
|
@ -69,6 +69,10 @@ struct spi_slave_transaction_t {
|
|||||||
* @param dma_chan Either 1 or 2. A SPI bus used by this driver must have a DMA channel associated with
|
* @param dma_chan Either 1 or 2. A SPI bus used by this driver must have a DMA channel associated with
|
||||||
* it. The SPI hardware has two DMA channels to share. This parameter indicates which
|
* it. The SPI hardware has two DMA channels to share. This parameter indicates which
|
||||||
* one to use.
|
* one to use.
|
||||||
|
*
|
||||||
|
* @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in
|
||||||
|
* DMA-capable memory.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* - ESP_ERR_INVALID_ARG if configuration is invalid
|
* - ESP_ERR_INVALID_ARG if configuration is invalid
|
||||||
* - ESP_ERR_INVALID_STATE if host already is in use
|
* - ESP_ERR_INVALID_STATE if host already is in use
|
||||||
|
@ -350,7 +350,7 @@ bool IRAM_ATTR spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t
|
|||||||
int otherchan = (dmachan == 1) ? 2 : 1;
|
int otherchan = (dmachan == 1) ? 2 : 1;
|
||||||
bool ret;
|
bool ret;
|
||||||
portENTER_CRITICAL(&dmaworkaround_mux);
|
portENTER_CRITICAL(&dmaworkaround_mux);
|
||||||
if (dmaworkaround_channels_busy[otherchan]) {
|
if (dmaworkaround_channels_busy[otherchan-1]) {
|
||||||
//Other channel is busy. Call back when it's done.
|
//Other channel is busy. Call back when it's done.
|
||||||
dmaworkaround_cb = cb;
|
dmaworkaround_cb = cb;
|
||||||
dmaworkaround_cb_arg = arg;
|
dmaworkaround_cb_arg = arg;
|
||||||
@ -374,7 +374,7 @@ bool IRAM_ATTR spicommon_dmaworkaround_reset_in_progress()
|
|||||||
void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
|
void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
|
||||||
{
|
{
|
||||||
portENTER_CRITICAL(&dmaworkaround_mux);
|
portENTER_CRITICAL(&dmaworkaround_mux);
|
||||||
dmaworkaround_channels_busy[dmachan] = 0;
|
dmaworkaround_channels_busy[dmachan-1] = 0;
|
||||||
if (dmaworkaround_waiting_for_chan == dmachan) {
|
if (dmaworkaround_waiting_for_chan == dmachan) {
|
||||||
//Reset DMA
|
//Reset DMA
|
||||||
SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_DMA_RST);
|
SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_DMA_RST);
|
||||||
@ -390,7 +390,7 @@ void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
|
|||||||
void IRAM_ATTR spicommon_dmaworkaround_transfer_active(int dmachan)
|
void IRAM_ATTR spicommon_dmaworkaround_transfer_active(int dmachan)
|
||||||
{
|
{
|
||||||
portENTER_CRITICAL(&dmaworkaround_mux);
|
portENTER_CRITICAL(&dmaworkaround_mux);
|
||||||
dmaworkaround_channels_busy[dmachan] = 1;
|
dmaworkaround_channels_busy[dmachan-1] = 1;
|
||||||
portEXIT_CRITICAL(&dmaworkaround_mux);
|
portEXIT_CRITICAL(&dmaworkaround_mux);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,6 +177,8 @@ esp_err_t spi_bus_free(spi_host_device_t host)
|
|||||||
spihost[host]->hw->slave.trans_done=0;
|
spihost[host]->hw->slave.trans_done=0;
|
||||||
esp_intr_free(spihost[host]->intr);
|
esp_intr_free(spihost[host]->intr);
|
||||||
spicommon_periph_free(host);
|
spicommon_periph_free(host);
|
||||||
|
free(spihost[host]->dmadesc_tx);
|
||||||
|
free(spihost[host]->dmadesc_rx);
|
||||||
free(spihost[host]);
|
free(spihost[host]);
|
||||||
spihost[host]=NULL;
|
spihost[host]=NULL;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
@ -573,6 +575,10 @@ esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *
|
|||||||
SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && (!(handle->cfg.flags & SPI_DEVICE_HALFDUPLEX))), "incompatible iface params", ESP_ERR_INVALID_ARG);
|
SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && (!(handle->cfg.flags & SPI_DEVICE_HALFDUPLEX))), "incompatible iface params", ESP_ERR_INVALID_ARG);
|
||||||
SPI_CHECK(trans_desc->length <= handle->host->max_transfer_sz*8, "txdata transfer > host maximum", ESP_ERR_INVALID_ARG);
|
SPI_CHECK(trans_desc->length <= handle->host->max_transfer_sz*8, "txdata transfer > host maximum", ESP_ERR_INVALID_ARG);
|
||||||
SPI_CHECK(trans_desc->rxlength <= handle->host->max_transfer_sz*8, "rxdata transfer > host maximum", ESP_ERR_INVALID_ARG);
|
SPI_CHECK(trans_desc->rxlength <= handle->host->max_transfer_sz*8, "rxdata transfer > host maximum", ESP_ERR_INVALID_ARG);
|
||||||
|
SPI_CHECK(handle->host->dma_chan == 0 || (trans_desc->flags & SPI_TRANS_USE_TXDATA) ||
|
||||||
|
trans_desc->tx_buffer==NULL || esp_ptr_dma_capable(trans_desc->tx_buffer), "txdata not in DMA-capable memory", ESP_ERR_INVALID_ARG);
|
||||||
|
SPI_CHECK(handle->host->dma_chan == 0 || (trans_desc->flags & SPI_TRANS_USE_RXDATA) ||
|
||||||
|
trans_desc->rx_buffer==NULL || esp_ptr_dma_capable(trans_desc->rx_buffer), "rxdata not in DMA-capable memory", ESP_ERR_INVALID_ARG);
|
||||||
r=xQueueSend(handle->trans_queue, (void*)&trans_desc, ticks_to_wait);
|
r=xQueueSend(handle->trans_queue, (void*)&trans_desc, ticks_to_wait);
|
||||||
if (!r) return ESP_ERR_TIMEOUT;
|
if (!r) return ESP_ERR_TIMEOUT;
|
||||||
esp_intr_enable(handle->host->intr);
|
esp_intr_enable(handle->host->intr);
|
||||||
|
@ -202,6 +202,10 @@ esp_err_t spi_slave_queue_trans(spi_host_device_t host, const spi_slave_transact
|
|||||||
BaseType_t r;
|
BaseType_t r;
|
||||||
SPI_CHECK(VALID_HOST(host), "invalid host", ESP_ERR_INVALID_ARG);
|
SPI_CHECK(VALID_HOST(host), "invalid host", ESP_ERR_INVALID_ARG);
|
||||||
SPI_CHECK(spihost[host], "host not slave", ESP_ERR_INVALID_ARG);
|
SPI_CHECK(spihost[host], "host not slave", ESP_ERR_INVALID_ARG);
|
||||||
|
SPI_CHECK(spihost[host]->dma_chan == 0 || trans_desc->tx_buffer==NULL || esp_ptr_dma_capable(trans_desc->tx_buffer),
|
||||||
|
"txdata not in DMA-capable memory", ESP_ERR_INVALID_ARG);
|
||||||
|
SPI_CHECK(spihost[host]->dma_chan == 0 || trans_desc->rx_buffer==NULL || esp_ptr_dma_capable(trans_desc->rx_buffer),
|
||||||
|
"rxdata not in DMA-capable memory", ESP_ERR_INVALID_ARG);
|
||||||
|
|
||||||
SPI_CHECK(trans_desc->length <= spihost[host]->max_transfer_sz * 8, "data transfer > host maximum", ESP_ERR_INVALID_ARG);
|
SPI_CHECK(trans_desc->length <= spihost[host]->max_transfer_sz * 8, "data transfer > host maximum", ESP_ERR_INVALID_ARG);
|
||||||
r = xQueueSend(spihost[host]->trans_queue, (void *)&trans_desc, ticks_to_wait);
|
r = xQueueSend(spihost[host]->trans_queue, (void *)&trans_desc, ticks_to_wait);
|
||||||
|
@ -87,4 +87,17 @@ size_t xPortGetMinimumEverFreeHeapSizeCaps( uint32_t caps );
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convenience function to check if a pointer is DMA-capable.
|
||||||
|
*
|
||||||
|
* @param ptr Pointer to check
|
||||||
|
*
|
||||||
|
* @return True if DMA-capable, false if not.
|
||||||
|
*/
|
||||||
|
static inline bool esp_ptr_dma_capable( const void *ptr )
|
||||||
|
{
|
||||||
|
return ( (int)ptr >= 0x3FFAE000 && (int)ptr < 0x40000000 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -50,7 +50,8 @@ typedef struct {
|
|||||||
uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
|
uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
|
||||||
} ili_init_cmd_t;
|
} ili_init_cmd_t;
|
||||||
|
|
||||||
static const ili_init_cmd_t ili_init_cmds[]={
|
//Place data into DRAM. Constant data gets placed into DROM by default, which is not accessible by DMA.
|
||||||
|
DRAM_ATTR static const ili_init_cmd_t ili_init_cmds[]={
|
||||||
{0xCF, {0x00, 0x83, 0X30}, 3},
|
{0xCF, {0x00, 0x83, 0X30}, 3},
|
||||||
{0xED, {0x64, 0x03, 0X12, 0X81}, 4},
|
{0xED, {0x64, 0x03, 0X12, 0X81}, 4},
|
||||||
{0xE8, {0x85, 0x01, 0x79}, 3},
|
{0xE8, {0x85, 0x01, 0x79}, 3},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user