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
pull/350/merge
Jeroen Domburg 2017-05-08 17:28:55 +08:00
commit a41ac2d21d
7 zmienionych plików z 36 dodań i 4 usunięć

Wyświetl plik

@ -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
* internal memory. Selecting no DMA channel (by passing the value 0) limits the amount of
* 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
* - ESP_ERR_INVALID_ARG if configuration is invalid
* - ESP_ERR_INVALID_STATE if host already is in use

Wyświetl plik

@ -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
* 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
* DMA-capable memory.
*
* @return
* - ESP_ERR_INVALID_ARG if configuration is invalid
* - ESP_ERR_INVALID_STATE if host already is in use

Wyświetl plik

@ -350,7 +350,7 @@ bool IRAM_ATTR spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t
int otherchan = (dmachan == 1) ? 2 : 1;
bool ret;
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.
dmaworkaround_cb = cb;
dmaworkaround_cb_arg = arg;
@ -374,7 +374,7 @@ bool IRAM_ATTR spicommon_dmaworkaround_reset_in_progress()
void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
{
portENTER_CRITICAL(&dmaworkaround_mux);
dmaworkaround_channels_busy[dmachan] = 0;
dmaworkaround_channels_busy[dmachan-1] = 0;
if (dmaworkaround_waiting_for_chan == dmachan) {
//Reset DMA
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)
{
portENTER_CRITICAL(&dmaworkaround_mux);
dmaworkaround_channels_busy[dmachan] = 1;
dmaworkaround_channels_busy[dmachan-1] = 1;
portEXIT_CRITICAL(&dmaworkaround_mux);
}

Wyświetl plik

@ -177,6 +177,8 @@ esp_err_t spi_bus_free(spi_host_device_t host)
spihost[host]->hw->slave.trans_done=0;
esp_intr_free(spihost[host]->intr);
spicommon_periph_free(host);
free(spihost[host]->dmadesc_tx);
free(spihost[host]->dmadesc_rx);
free(spihost[host]);
spihost[host]=NULL;
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->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(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);
if (!r) return ESP_ERR_TIMEOUT;
esp_intr_enable(handle->host->intr);

Wyświetl plik

@ -202,6 +202,10 @@ esp_err_t spi_slave_queue_trans(spi_host_device_t host, const spi_slave_transact
BaseType_t r;
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]->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);
r = xQueueSend(spihost[host]->trans_queue, (void *)&trans_desc, ticks_to_wait);

Wyświetl plik

@ -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

Wyświetl plik

@ -50,7 +50,8 @@ typedef struct {
uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
} 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},
{0xED, {0x64, 0x03, 0X12, 0X81}, 4},
{0xE8, {0x85, 0x01, 0x79}, 3},