fix(spi_master): this fix the SPI MOSI output missing bug.

This commit is contained in:
michael 2017-08-31 19:59:30 +08:00 committed by Ivan Grokhotkov
parent f254555a41
commit b834fcf78a
5 changed files with 82 additions and 7 deletions

View file

@ -44,6 +44,7 @@ typedef enum {
PERIPH_SPI_MODULE, PERIPH_SPI_MODULE,
PERIPH_HSPI_MODULE, PERIPH_HSPI_MODULE,
PERIPH_VSPI_MODULE, PERIPH_VSPI_MODULE,
PERIPH_SPI_DMA_MODULE,
} periph_module_t; } periph_module_t;
/** /**

View file

@ -74,11 +74,30 @@ bool spicommon_periph_claim(spi_host_device_t host);
/** /**
* @brief Return the SPI peripheral so another driver can claim it. * @brief Return the SPI peripheral so another driver can claim it.
* *
* @param host Peripheral to claim * @param host Peripheral to return
* @return True if peripheral is returned successfully; false if peripheral was free to claim already. * @return True if peripheral is returned successfully; false if peripheral was free to claim already.
*/ */
bool spicommon_periph_free(spi_host_device_t host); bool spicommon_periph_free(spi_host_device_t host);
/**
* @brief Try to claim a SPI DMA channel
*
* Call this if your driver wants to use SPI with a DMA channnel.
*
* @param dma_chan channel to claim
*
* @return True if success; false otherwise.
*/
bool spicommon_dma_chan_claim(int dma_chan);
/**
* @brief Return the SPI DMA channel so other driver can claim it, or just to power down DMA.
*
* @param dma_chan channel to return
*
* @return True if success; false otherwise.
*/
bool spicommon_dma_chan_free(int dma_chan);
#define SPICOMMON_BUSFLAG_SLAVE 0 ///< Initialize I/O in slave mode #define SPICOMMON_BUSFLAG_SLAVE 0 ///< Initialize I/O in slave mode
#define SPICOMMON_BUSFLAG_MASTER (1<<0) ///< Initialize I/O in master mode #define SPICOMMON_BUSFLAG_MASTER (1<<0) ///< Initialize I/O in master mode
@ -170,9 +189,6 @@ spi_dev_t *spicommon_hw_for_host(spi_host_device_t host);
*/ */
int spicommon_irqsource_for_host(spi_host_device_t host); int spicommon_irqsource_for_host(spi_host_device_t host);
/** /**
* Callback, to be called when a DMA engine reset is completed * Callback, to be called when a DMA engine reset is completed
*/ */

View file

@ -109,6 +109,10 @@ void periph_module_enable(periph_module_t periph)
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_2); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_2);
break; break;
case PERIPH_SPI_DMA_MODULE:
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_DMA_CLK_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_DMA_RST );
break;
default: default:
break; break;
} }
@ -202,6 +206,9 @@ void periph_module_disable(periph_module_t periph)
case PERIPH_VSPI_MODULE: case PERIPH_VSPI_MODULE:
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_2); DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_2);
case PERIPH_SPI_DMA_MODULE:
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_DMA_CLK_EN);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_DMA_RST);
break; break;
default: default:
break; break;

View file

@ -150,8 +150,13 @@ static const spi_signal_conn_t io_signal[3] = {
} }
}; };
#define DMA_CHANNEL_ENABLED(dma_chan) (BIT(dma_chan-1))
//Periph 1 is 'claimed' by SPI flash code. //Periph 1 is 'claimed' by SPI flash code.
static bool spi_periph_claimed[3] = {true, false, false}; static bool spi_periph_claimed[3] = {true, false, false};
static uint8_t spi_dma_chan_enabled = 0;
static portMUX_TYPE spi_dma_spinlock = portMUX_INITIALIZER_UNLOCKED;
//Returns true if this peripheral is successfully claimed, false if otherwise. //Returns true if this peripheral is successfully claimed, false if otherwise.
bool spicommon_periph_claim(spi_host_device_t host) bool spicommon_periph_claim(spi_host_device_t host)
@ -180,6 +185,39 @@ spi_dev_t *spicommon_hw_for_host(spi_host_device_t host)
return io_signal[host].hw; return io_signal[host].hw;
} }
bool spicommon_dma_chan_claim (int dma_chan)
{
bool ret = false;
assert( dma_chan == 1 || dma_chan == 2 );
portENTER_CRITICAL(&spi_dma_spinlock);
if ( !(spi_dma_chan_enabled & DMA_CHANNEL_ENABLED(dma_chan)) ) {
// get the channel only when it's not claimed yet.
spi_dma_chan_enabled |= DMA_CHANNEL_ENABLED(dma_chan);
ret = true;
}
periph_module_enable( PERIPH_SPI_DMA_MODULE );
portEXIT_CRITICAL(&spi_dma_spinlock);
return ret;
}
bool spicommon_dma_chan_free(int dma_chan)
{
assert( dma_chan == 1 || dma_chan == 2 );
assert( spi_dma_chan_enabled & DMA_CHANNEL_ENABLED(dma_chan) );
portENTER_CRITICAL(&spi_dma_spinlock);
spi_dma_chan_enabled &= ~DMA_CHANNEL_ENABLED(dma_chan);
if ( spi_dma_chan_enabled == 0 ) {
//disable the DMA only when all the channels are freed.
periph_module_disable( PERIPH_SPI_DMA_MODULE );
}
portEXIT_CRITICAL(&spi_dma_spinlock);
return true;
}
/* /*
Do the common stuff to hook up a SPI host to a bus defined by a bunch of GPIO pins. Feed it a host number and a Do the common stuff to hook up a SPI host to a bus defined by a bunch of GPIO pins. Feed it a host number and a
bus config struct and it'll set up the GPIO matrix and enable the device. It will set is_native to 1 if the bus bus config struct and it'll set up the GPIO matrix and enable the device. It will set is_native to 1 if the bus

View file

@ -108,14 +108,23 @@ static void spi_intr(void *arg);
esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan) esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan)
{ {
bool native, claimed; bool native, spi_chan_claimed, dma_chan_claimed;
/* ToDo: remove this when we have flash operations cooperating with this */ /* ToDo: remove this when we have flash operations cooperating with this */
SPI_CHECK(host!=SPI_HOST, "SPI1 is not supported", ESP_ERR_NOT_SUPPORTED); SPI_CHECK(host!=SPI_HOST, "SPI1 is not supported", ESP_ERR_NOT_SUPPORTED);
SPI_CHECK(host>=SPI_HOST && host<=VSPI_HOST, "invalid host", ESP_ERR_INVALID_ARG); SPI_CHECK(host>=SPI_HOST && host<=VSPI_HOST, "invalid host", ESP_ERR_INVALID_ARG);
SPI_CHECK( dma_chan >= 0 && dma_chan <= 2, "invalid dma channel", ESP_ERR_INVALID_ARG );
claimed=spicommon_periph_claim(host); spi_chan_claimed=spicommon_periph_claim(host);
SPI_CHECK(claimed, "host already in use", ESP_ERR_INVALID_STATE); SPI_CHECK(spi_chan_claimed, "host already in use", ESP_ERR_INVALID_STATE);
if ( dma_chan != 0 ) {
dma_chan_claimed=spicommon_dma_chan_claim(dma_chan);
if ( !dma_chan_claimed ) {
spicommon_periph_free( host );
SPI_CHECK(dma_chan_claimed, "dma channel already in use", ESP_ERR_INVALID_STATE);
}
}
spihost[host]=malloc(sizeof(spi_host_t)); spihost[host]=malloc(sizeof(spi_host_t));
if (spihost[host]==NULL) goto nomem; if (spihost[host]==NULL) goto nomem;
@ -185,6 +194,10 @@ esp_err_t spi_bus_free(spi_host_device_t host)
for (x=0; x<NO_CS; x++) { for (x=0; x<NO_CS; x++) {
SPI_CHECK(spihost[host]->device[x]==NULL, "not all CSses freed", ESP_ERR_INVALID_STATE); SPI_CHECK(spihost[host]->device[x]==NULL, "not all CSses freed", ESP_ERR_INVALID_STATE);
} }
if ( spihost[host]->dma_chan > 0 ) {
spicommon_dma_chan_free ( spihost[host]->dma_chan );
}
spihost[host]->hw->slave.trans_inten=0; spihost[host]->hw->slave.trans_inten=0;
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);