struct stm_spi *stm_spi;
};
-uint8_t ao_spi_mutex[STM_NUM_SPI];
+uint8_t ao_spi_mutex[STM_NUM_SPI];
+uint16_t ao_spi_speed[STM_NUM_SPI];
static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_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 the transmit DMA to deliver data */
ao_dma_set_transfer(mosi_dma_index,
&stm_spi->dr,
block,
(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,
}
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,
(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,
(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) |
(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)
{
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 */
+ (ao_spi_speed[spi_index] << 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) |
(0 << STM_SPI_CR2_SSOE) |
(0 << STM_SPI_CR2_TXDMAEN) |
(0 << STM_SPI_CR2_RXDMAEN));
+ ao_spi_speed[spi_index] = AO_SPI_SPEED_FAST;
}
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
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
}