X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fstm%2Fao_spi_stm.c;h=547de9e50ca0b887864ecaab28986d923b2ed572;hb=a8ecf3aa4e88d4c76643fb541fb1d5535a454aba;hp=da04302b25d5cfb4fea5f1979542ea952eab88f9;hpb=9b12bc445fe482306e4587ad60c6d2daf65a60f3;p=fw%2Faltos diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index da04302b..547de9e5 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -23,7 +23,7 @@ struct ao_spi_stm_info { struct stm_spi *stm_spi; }; -uint8_t ao_spi_mutex[STM_NUM_SPI]; +uint8_t ao_spi_mutex[STM_NUM_SPI]; static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = { { @@ -47,6 +47,7 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index) uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + /* Set up the transmit DMA to deliver data */ ao_dma_set_transfer(mosi_dma_index, &stm_spi->dr, block, @@ -59,8 +60,14 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index) (0 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); - /* Clear any stale data */ + + /* Clear RXNE */ (void) stm_spi->dr; + + /* Set up the receive DMA -- when this is done, we know the SPI unit + * is idle. Without this, we'd have to poll waiting for the BSY bit to + * be cleared + */ ao_dma_set_transfer(miso_dma_index, &stm_spi->dr, &spi_dev_null, @@ -90,22 +97,69 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index) } void -ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) +ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index) { struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; -#if 0 - uint8_t *d = block; + uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; - while (len--) { - stm_spi->dr = 0xff; - while (!(stm_spi->sr & (1 << STM_SPI_SR_RXNE))); - *d++ = stm_spi->dr; - } - while (stm_spi->sr & (1 << STM_SPI_SR_BSY)); -#else + /* Set up the transmit DMA to deliver data */ + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + &value, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + + /* Clear RXNE */ + (void) stm_spi->dr; + + /* Set up the receive DMA -- when this is done, we know the SPI unit + * is idle. Without this, we'd have to poll waiting for the BSY bit to + * be cleared + */ + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + &spi_dev_null, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +} + +void +ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + /* Set up transmit DMA to make the SPI hardware actually run */ ao_dma_set_transfer(mosi_dma_index, &stm_spi->dr, &spi_dev_null, @@ -118,8 +172,11 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) (0 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); - /* Clear any stale data */ + + /* Clear RXNE */ (void) stm_spi->dr; + + /* Set up the receive DMA to capture data */ ao_dma_set_transfer(miso_dma_index, &stm_spi->dr, block, @@ -132,6 +189,7 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) (0 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | (0 << STM_SPI_CR2_RXNEIE) | (0 << STM_SPI_CR2_ERRIE) | @@ -140,36 +198,112 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) (1 << STM_SPI_CR2_RXDMAEN)); ao_dma_start(miso_dma_index); ao_dma_start(mosi_dma_index); + + /* Wait until the SPI unit is done */ ao_arch_critical( while (!ao_dma_done[miso_dma_index]) ao_sleep(&ao_dma_done[miso_dma_index]); ); + ao_dma_done_transfer(mosi_dma_index); ao_dma_done_transfer(miso_dma_index); -#endif } -static void -ao_spi_channel_init(uint8_t spi_index) +void +ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + + /* Set up transmit DMA to send data */ + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + out, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + + /* Clear RXNE */ + (void) stm_spi->dr; + + /* Set up the receive DMA to capture data */ + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + in, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + + /* Wait until the SPI unit is done */ + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +} + +void +ao_spi_get(uint8_t spi_index, uint32_t speed) { struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; - stm_spi->cr1 = 0; - (void) stm_spi->sr; - stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | + ao_mutex_get(&ao_spi_mutex[spi_index]); + stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */ (0 << STM_SPI_CR1_BIDIOE) | - (0 << STM_SPI_CR1_CRCEN) | + (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */ (0 << STM_SPI_CR1_CRCNEXT) | (0 << STM_SPI_CR1_DFF) | (0 << STM_SPI_CR1_RXONLY) | - (1 << STM_SPI_CR1_SSM) | - (1 << STM_SPI_CR1_SSI) | - (0 << STM_SPI_CR1_LSBFIRST) | - (1 << STM_SPI_CR1_SPE) | - (STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) | + (1 << STM_SPI_CR1_SSM) | /* Software SS handling */ + (1 << STM_SPI_CR1_SSI) | /* ... */ + (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */ + (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ + (speed << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ (1 << STM_SPI_CR1_MSTR) | - (0 << STM_SPI_CR1_CPOL) | + (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ (0 << STM_SPI_CR1_CPHA)); +} + +void +ao_spi_put(uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + + stm_spi->cr1 = 0; + ao_mutex_put(&ao_spi_mutex[spi_index]); +} + +static void +ao_spi_channel_init(uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + + stm_spi->cr1 = 0; + (void) stm_spi->sr; stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | (0 << STM_SPI_CR2_RXNEIE) | (0 << STM_SPI_CR2_ERRIE) | @@ -208,9 +342,6 @@ ao_spi_init(void) stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); ao_spi_channel_init(0); - - stm_nvic_set_enable(STM_ISR_SPI1_POS); - stm_nvic_set_priority(STM_ISR_SPI1_POS, 3); #endif #if HAS_SPI_2 @@ -233,8 +364,5 @@ ao_spi_init(void) stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); ao_spi_channel_init(1); - - stm_nvic_set_enable(STM_ISR_SPI2_POS); - stm_nvic_set_priority(STM_ISR_SPI2_POS, 3); #endif }