*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
};
static uint8_t ao_spi_mutex[STM_NUM_SPI];
-static uint8_t ao_spi_index[STM_NUM_SPI];
+static uint8_t ao_spi_pin_config[STM_NUM_SPI];
static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = {
{
#define validate_spi(stm_spi, which, len) do { (void) (which); (void) (len); } while (0)
#endif
-void
-ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
+static void
+ao_spi_set_dma_mosi(uint8_t id, const void *data, uint16_t len, uint32_t minc)
{
- struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
- uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
- uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
- /* Set up the transmit DMA to deliver data */
ao_dma_set_transfer(mosi_dma_index,
&stm_spi->dr,
- (void *) block,
+ (void *) data,
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) |
+ (minc << 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;
+static void
+ao_spi_set_dma_miso(uint8_t id, void *data, uint16_t len, uint32_t minc)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+ uint8_t miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
- /* 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,
+ data,
len,
(0 << STM_DMA_CCR_MEM2MEM) |
- (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_PL_HIGH << 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) |
+ (minc << 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));
+}
+
+static void
+ao_spi_run(uint8_t id, uint8_t which, uint16_t len)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
+
+ validate_spi(stm_spi, which, len);
+
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]);
);
+
+ while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0);
+ while (stm_spi->sr & (1 << STM_SPI_SR_BSY));
+
+ validate_spi(stm_spi, which+1, len);
+
+ stm_spi->cr2 = 0;
+
ao_dma_done_transfer(mosi_dma_index);
ao_dma_done_transfer(miso_dma_index);
}
void
-ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
+ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
{
- struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
- uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
- uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+ uint8_t id = AO_SPI_INDEX(spi_index);
/* 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));
+ ao_spi_set_dma_mosi(id, block, len, 1);
- /* 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_spi_set_dma_miso(id, &spi_dev_null, len, 0);
+
+ ao_spi_run(id, 1, len);
+}
+
+void
+ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+
+ /* Set up the transmit DMA to deliver data */
+ ao_spi_set_dma_mosi(id, &value, len, 0);
/* 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));
+ ao_spi_set_dma_miso(id, &spi_dev_null, len, 0);
+
+ ao_spi_run(id, 3, len);
+}
+
+void
+ao_spi_start_bytes(uint8_t spi_index)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+
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);
+ (0 << STM_SPI_CR2_TXDMAEN) |
+ (0 << STM_SPI_CR2_RXDMAEN));
+ validate_spi(stm_spi, 5, 0xffff);
+}
+
+void
+ao_spi_stop_bytes(uint8_t spi_index)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+
+ while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0)
+ ;
+ while (stm_spi->sr & (1 << STM_SPI_SR_BSY))
+ ;
+ /* Clear the OVR flag */
+ (void) stm_spi->dr;
+ (void) stm_spi->sr;
+ validate_spi(stm_spi, 6, 0xffff);
+ stm_spi->cr2 = 0;
}
void
ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index)
{
- uint8_t *b = block;
- struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ const uint8_t *b = block;
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
(0 << STM_SPI_CR2_RXNEIE) |
(0 << STM_SPI_CR2_SSOE) |
(0 << STM_SPI_CR2_TXDMAEN) |
(0 << STM_SPI_CR2_RXDMAEN));
-
- /* Clear RXNE */
- (void) stm_spi->dr;
-
+ validate_spi(stm_spi, 7, len);
while (len--) {
while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
stm_spi->dr = *b++;
}
+ while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0)
+ ;
+ while (stm_spi->sr & (1 << STM_SPI_SR_BSY))
+ ;
+ /* Clear the OVR flag */
+ (void) stm_spi->dr;
+ (void) stm_spi->sr;
+ validate_spi(stm_spi, 8, len);
}
void
ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
{
- struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
- uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
- uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+ uint8_t id = AO_SPI_INDEX(spi_index);
spi_dev_null = 0xff;
/* Set up transmit DMA to make the SPI hardware actually run */
- ao_dma_set_transfer(mosi_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_MEM_TO_PER << STM_DMA_CCR_DIR));
-
- /* Clear RXNE */
- (void) stm_spi->dr;
+ ao_spi_set_dma_mosi(id, &spi_dev_null, len, 0);
/* Set up the receive DMA to capture data */
- ao_dma_set_transfer(miso_dma_index,
- &stm_spi->dr,
- block,
- 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));
+ ao_spi_set_dma_miso(id, block, len, 1);
- 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);
+ ao_spi_run(id, 9, len);
}
void
-ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)
+ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index)
{
- struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
- uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
- uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+ uint8_t id = AO_SPI_INDEX(spi_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;
+ ao_spi_set_dma_mosi(id, out, len, 1);
/* 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));
+ ao_spi_set_dma_miso(id, in, len, 1);
- 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);
+ ao_spi_run(id, 11, len);
}
static void
-ao_spi_disable_index(uint8_t spi_index)
+ao_spi_disable_pin_config(uint8_t spi_pin_config)
{
/* Disable current config
*/
- switch (AO_SPI_INDEX(spi_index)) {
- case STM_SPI_INDEX(1):
- switch (spi_index) {
- case AO_SPI_1_PA5_PA6_PA7:
- stm_gpio_set(&stm_gpioa, 5, 1);
- stm_moder_set(&stm_gpioa, 5, STM_MODER_OUTPUT);
- stm_moder_set(&stm_gpioa, 6, STM_MODER_INPUT);
- stm_moder_set(&stm_gpioa, 7, STM_MODER_OUTPUT);
- break;
- case AO_SPI_1_PB3_PB4_PB5:
- stm_gpio_set(&stm_gpiob, 3, 1);
- stm_moder_set(&stm_gpiob, 3, STM_MODER_OUTPUT);
- stm_moder_set(&stm_gpiob, 4, STM_MODER_INPUT);
- stm_moder_set(&stm_gpiob, 5, STM_MODER_OUTPUT);
- break;
- case AO_SPI_1_PE13_PE14_PE15:
- stm_gpio_set(&stm_gpioe, 13, 1);
- stm_moder_set(&stm_gpioe, 13, STM_MODER_OUTPUT);
- stm_moder_set(&stm_gpioe, 14, STM_MODER_INPUT);
- stm_moder_set(&stm_gpioe, 15, STM_MODER_OUTPUT);
- break;
- }
+ switch (spi_pin_config) {
+ case AO_SPI_1_PA5_PA6_PA7:
+ stm_gpio_set(&stm_gpioa, 5, 1);
+ stm_moder_set(&stm_gpioa, 5, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpioa, 6, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpioa, 7, STM_MODER_OUTPUT);
break;
- case STM_SPI_INDEX(2):
- switch (spi_index) {
- case AO_SPI_2_PB13_PB14_PB15:
- stm_gpio_set(&stm_gpiob, 13, 1);
- stm_moder_set(&stm_gpiob, 13, STM_MODER_OUTPUT);
- stm_moder_set(&stm_gpiob, 14, STM_MODER_INPUT);
- stm_moder_set(&stm_gpiob, 15, STM_MODER_OUTPUT);
- break;
- case AO_SPI_2_PD1_PD3_PD4:
- stm_gpio_set(&stm_gpiod, 1, 1);
- stm_moder_set(&stm_gpiod, 1, STM_MODER_OUTPUT);
- stm_moder_set(&stm_gpiod, 3, STM_MODER_INPUT);
- stm_moder_set(&stm_gpiod, 4, STM_MODER_OUTPUT);
- break;
- }
+ case AO_SPI_1_PB3_PB4_PB5:
+ stm_gpio_set(&stm_gpiob, 3, 1);
+ stm_moder_set(&stm_gpiob, 3, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpiob, 4, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpiob, 5, STM_MODER_OUTPUT);
+ break;
+ case AO_SPI_1_PE13_PE14_PE15:
+ stm_gpio_set(&stm_gpioe, 13, 1);
+ stm_moder_set(&stm_gpioe, 13, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpioe, 14, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpioe, 15, STM_MODER_OUTPUT);
+ break;
+ case AO_SPI_2_PB13_PB14_PB15:
+ stm_gpio_set(&stm_gpiob, 13, 1);
+ stm_moder_set(&stm_gpiob, 13, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpiob, 14, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpiob, 15, STM_MODER_OUTPUT);
+ break;
+ case AO_SPI_2_PD1_PD3_PD4:
+ stm_gpio_set(&stm_gpiod, 1, 1);
+ stm_moder_set(&stm_gpiod, 1, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpiod, 3, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpiod, 4, STM_MODER_OUTPUT);
break;
}
}
static void
-ao_spi_enable_index(uint8_t spi_index)
+ao_spi_enable_pin_config(uint8_t spi_pin_config)
{
- switch (AO_SPI_INDEX(spi_index)) {
- case STM_SPI_INDEX(1):
- switch (spi_index) {
- case AO_SPI_1_PA5_PA6_PA7:
- stm_afr_set(&stm_gpioa, 5, STM_AFR_AF5);
- stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5);
- stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5);
- break;
- case AO_SPI_1_PB3_PB4_PB5:
- stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5);
- stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5);
- stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5);
- break;
- case AO_SPI_1_PE13_PE14_PE15:
- stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5);
- stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5);
- stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5);
- break;
- }
+ /* Enable new config
+ */
+ switch (spi_pin_config) {
+ case AO_SPI_1_PA5_PA6_PA7:
+ stm_afr_set(&stm_gpioa, 5, STM_AFR_AF5);
+ stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5);
+ stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5);
break;
- case STM_SPI_INDEX(2):
- switch (spi_index) {
- case AO_SPI_2_PB13_PB14_PB15:
- stm_afr_set(&stm_gpiob, 13, STM_AFR_AF5);
- stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5);
- stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5);
- break;
- case AO_SPI_2_PD1_PD3_PD4:
- stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5);
- stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5);
- stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5);
- break;
- }
+ case AO_SPI_1_PB3_PB4_PB5:
+ stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5);
+ stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5);
+ stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5);
+ break;
+ case AO_SPI_1_PE13_PE14_PE15:
+ stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5);
+ stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5);
+ stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5);
+ break;
+ case AO_SPI_2_PB13_PB14_PB15:
+ stm_afr_set(&stm_gpiob, 13, STM_AFR_AF5);
+ stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5);
+ stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5);
+ break;
+ case AO_SPI_2_PD1_PD3_PD4:
+ stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5);
+ stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5);
+ stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5);
break;
}
}
static void
ao_spi_config(uint8_t spi_index, uint32_t speed)
{
+ uint8_t spi_pin_config = AO_SPI_PIN_CONFIG(spi_index);
uint8_t id = AO_SPI_INDEX(spi_index);
struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
- stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */
- (0 << STM_SPI_CR1_BIDIOE) |
- (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) | /* 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) | /* Format 0 */
- (0 << STM_SPI_CR1_CPHA));
- if (spi_index != ao_spi_index[id]) {
+
+ if (spi_pin_config != ao_spi_pin_config[id]) {
/* Disable old config
*/
- ao_spi_disable_index(ao_spi_index[id]);
+ ao_spi_disable_pin_config(ao_spi_pin_config[id]);
/* Enable new config
*/
- ao_spi_enable_index(spi_index);
+ ao_spi_enable_pin_config(spi_pin_config);
/* Remember current config
*/
- ao_spi_index[id] = spi_index;
+ ao_spi_pin_config[id] = spi_pin_config;
}
+
+ /* Turn the SPI transceiver on and set the mode */
+ stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */
+ (0 << STM_SPI_CR1_BIDIOE) |
+ (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) | /* 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) |
+ (AO_SPI_CPOL(spi_index) << STM_SPI_CR1_CPOL) | /* Format */
+ (AO_SPI_CPHA(spi_index) << STM_SPI_CR1_CPHA));
+ validate_spi(stm_spi, 13, 0);
}
uint8_t
ao_spi_get(uint8_t spi_index, uint32_t speed)
{
uint8_t id = AO_SPI_INDEX(spi_index);
+
ao_mutex_get(&ao_spi_mutex[id]);
ao_spi_config(spi_index, speed);
}
uint8_t id = AO_SPI_INDEX(spi_index);
struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
- ao_spi_disable_index(spi_index);
+ ao_spi_disable_pin_config(AO_SPI_PIN_CONFIG(spi_index));
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));
+
+ /* Clear any pending data and error flags */
+ (void) stm_spi->dr;
+ (void) stm_spi->sr;
}
#if DEBUG
stm_ospeedr_set(&stm_gpioe, 15, SPI_1_OSPEEDR);
# endif
stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN);
- ao_spi_index[0] = AO_SPI_CONFIG_NONE;
+ ao_spi_pin_config[0] = AO_SPI_CONFIG_NONE;
ao_spi_channel_init(0);
#endif
stm_ospeedr_set(&stm_gpiod, 4, SPI_2_OSPEEDR);
# endif
stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN);
- ao_spi_index[1] = AO_SPI_CONFIG_NONE;
+ ao_spi_pin_config[1] = AO_SPI_CONFIG_NONE;
ao_spi_channel_init(1);
#endif
#if DEBUG