From 2e60cd22f6789c94343e6432822cedab028dc1ba Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Jun 2016 18:25:44 -0700 Subject: altos/stm: Change ao_spi_send_sync definition to take const source Provides for a bit better error checking. Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/stm/ao_spi_stm.c') diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 7eaa3924..8ed820eb 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -154,7 +154,7 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index) } void -ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index) +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; -- cgit v1.2.3 From 69791ef235161fef404f682fd6955e7eed8dc125 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Jun 2016 23:26:20 -0700 Subject: altos: Add STM SPI debugging This dumps out the SPI hardware state and history of SPI operations when compiled with -DDEBUG=1. Without that, this patch does nothing. Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) (limited to 'src/stm/ao_spi_stm.c') diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 8ed820eb..3b5773b6 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -41,6 +41,49 @@ static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = { static uint8_t spi_dev_null; +#if DEBUG +static struct { + uint8_t task; + uint8_t which; + AO_TICK_TYPE tick; + uint16_t len; +} spi_tasks[64]; +static uint8_t spi_task_index; + +static void +validate_spi(struct stm_spi *stm_spi, int which, uint16_t len) +{ + uint32_t sr = stm_spi->sr; + + if (stm_spi != &stm_spi2) + return; + spi_tasks[spi_task_index].task = ao_cur_task ? ao_cur_task->task_id : 0; + spi_tasks[spi_task_index].which = which; + spi_tasks[spi_task_index].tick = ao_time(); + spi_tasks[spi_task_index].len = len; + spi_task_index = (spi_task_index + 1) & (63); + if (sr & (1 << STM_SPI_SR_FRE)) + ao_panic(0x40 | 1); + if (sr & (1 << STM_SPI_SR_BSY)) + ao_panic(0x40 | 2); + if (sr & (1 << STM_SPI_SR_OVR)) + ao_panic(0x40 | 3); + if (sr & (1 << STM_SPI_SR_MODF)) + ao_panic(0x40 | 4); + if (sr & (1 << STM_SPI_SR_UDR)) + ao_panic(0x40 | 5); + if ((sr & (1 << STM_SPI_SR_TXE)) == 0) + ao_panic(0x40 | 6); + if (sr & (1 << STM_SPI_SR_RXNE)) + ao_panic(0x40 | 7); + if (which != 5 && which != 6 && which != 13) + if (ao_cur_task->task_id != ao_spi_mutex[1]) + ao_panic(0x40 | 8); +} +#else +#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) { @@ -460,6 +503,50 @@ ao_spi_channel_init(uint8_t spi_index) (0 << STM_SPI_CR2_RXDMAEN)); } +#if DEBUG +void +ao_spi_dump_cmd(void) +{ + int s; + + for (s = 0; s < 64; s++) { + int i = (spi_task_index + s) & 63; + if (spi_tasks[i].which) { + int t; + const char *name = "(none)"; + for (t = 0; t < ao_num_tasks; t++) + if (ao_tasks[t]->task_id == spi_tasks[i].task) { + name = ao_tasks[t]->name; + break; + } + printf("%2d: %5d task %2d which %2d len %5d %s\n", + s, + spi_tasks[i].tick, + spi_tasks[i].task, + spi_tasks[i].which, + spi_tasks[i].len, + name); + } + } + for (s = 0; s < STM_NUM_SPI; s++) { + struct stm_spi *spi = ao_spi_stm_info[s].stm_spi; + + printf("%1d: mutex %2d index %3d miso dma %3d mosi dma %3d", + s, ao_spi_mutex[s], ao_spi_index[s], + ao_spi_stm_info[s].miso_dma_index, + ao_spi_stm_info[s].mosi_dma_index); + printf(" cr1 %04x cr2 %02x sr %03x\n", + spi->cr1, spi->cr2, spi->sr); + } + +} + +static const struct ao_cmds ao_spi_cmds[] = { + { ao_spi_dump_cmd, "S\0Dump SPI status" }, + { 0, NULL } +}; +#endif + void ao_spi_init(void) { @@ -504,4 +591,7 @@ ao_spi_init(void) ao_spi_index[1] = AO_SPI_CONFIG_NONE; ao_spi_channel_init(1); #endif +#if DEBUG + ao_cmd_register(&ao_spi_cmds[0]); +#endif } -- cgit v1.2.3 From 5ab4a8b911e254dc829b61cb0abc9fd0b46b84b3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Jun 2016 23:25:01 -0700 Subject: altos/stm: move spi execution to common ao_spi_run This regularizes SPI hardware use and ensures that the device is turned off after it has been used and that the status register is back to 'normal' the next time through. Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 198 +++++++++++++++++++++++---------------------------- 1 file changed, 90 insertions(+), 108 deletions(-) (limited to 'src/stm/ao_spi_stm.c') diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 3b5773b6..2b6834fd 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -84,12 +84,48 @@ validate_spi(struct stm_spi *stm_spi, int which, uint16_t len) #define validate_spi(stm_spi, which, len) do { (void) (which); (void) (len); } while (0) #endif +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(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); + 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; /* Set up the transmit DMA to deliver data */ ao_dma_set_transfer(mosi_dma_index, @@ -105,9 +141,6 @@ ao_spi_send(const void *block, uint16_t len, uint8_t spi_index) (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 @@ -124,28 +157,17 @@ ao_spi_send(const 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) | - (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); + + ao_spi_run(id, 1, len); } void ao_spi_send_fixed(uint8_t value, 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); + 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; /* Set up the transmit DMA to deliver data */ ao_dma_set_transfer(mosi_dma_index, @@ -161,9 +183,6 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index) (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 @@ -180,27 +199,16 @@ ao_spi_send_fixed(uint8_t value, 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) | - (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); + + ao_spi_run(id, 3, len); } 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) | @@ -208,22 +216,28 @@ ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index) (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); + 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; spi_dev_null = 0xff; @@ -241,9 +255,6 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) (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, @@ -258,31 +269,16 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) (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); + ao_spi_run(id, 9, len); } void ao_spi_duplex(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); + 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; /* Set up transmit DMA to send data */ ao_dma_set_transfer(mosi_dma_index, @@ -298,9 +294,6 @@ ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index) (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, @@ -314,24 +307,7 @@ ao_spi_duplex(void *out, void *in, 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) | - (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 @@ -426,20 +402,7 @@ ao_spi_config(uint8_t spi_index, uint32_t speed) { 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]) { /* Disable old config @@ -454,6 +417,21 @@ ao_spi_config(uint8_t spi_index, uint32_t speed) */ ao_spi_index[id] = spi_index; } + 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)); + validate_spi(stm_spi, 13, 0); } uint8_t @@ -471,6 +449,7 @@ void 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); } @@ -494,13 +473,16 @@ ao_spi_channel_init(uint8_t spi_index) ao_spi_disable_index(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 -- cgit v1.2.3 From 5866d191cee56949ccab4c154a14604e83163d42 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Jun 2016 18:37:49 -0700 Subject: altos/stm: Clean up spi_enable/disable_index functions These had an extra level of switch nesting for no good reason. Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 124 +++++++++++++++++++++++---------------------------- 1 file changed, 55 insertions(+), 69 deletions(-) (limited to 'src/stm/ao_spi_stm.c') diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 2b6834fd..e69c2d7b 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -315,44 +315,36 @@ ao_spi_disable_index(uint8_t spi_index) { /* 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_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 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; } } @@ -360,39 +352,33 @@ ao_spi_disable_index(uint8_t spi_index) static void ao_spi_enable_index(uint8_t spi_index) { - 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_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 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; } } -- cgit v1.2.3 From 61ad8e5bf428246ac89cad7cb9a1edf2ef735fd5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Jun 2016 18:39:31 -0700 Subject: altos/stm: Add better byte-level SPI api This provides inline functions for sending and receiving individual bytes, and setup/finish functions to wrap them in. This make the byte sending respect the SPI hardware interface requirements. Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 42 ++++++++++++++++++++++++++++++++---------- src/stm/ao_spi_stm.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 10 deletions(-) (limited to 'src/stm/ao_spi_stm.c') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 8393898d..a796891d 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -82,6 +82,12 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index); void ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index); +void +ao_spi_start_bytes(uint8_t spi_index); + +void +ao_spi_stop_bytes(uint8_t spi_index); + static inline void ao_spi_send_byte(uint8_t byte, uint8_t spi_index) { @@ -96,18 +102,34 @@ ao_spi_send_byte(uint8_t byte, uint8_t spi_index) break; } - 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 RXNE */ + while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE))) + ; + stm_spi->dr = byte; + while (!(stm_spi->sr & (1 << STM_SPI_SR_RXNE))) + ; (void) stm_spi->dr; +} - while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE))); - stm_spi->dr = byte; +static inline uint8_t +ao_spi_recv_byte(uint8_t spi_index) +{ + struct stm_spi *stm_spi; + + switch (AO_SPI_INDEX(spi_index)) { + case 0: + stm_spi = &stm_spi1; + break; + case 1: + stm_spi = &stm_spi2; + break; + } + + while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE))) + ; + stm_spi->dr = 0xff; + while (!(stm_spi->sr & (1 << STM_SPI_SR_RXNE))) + ; + return stm_spi->dr; } void diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index e69c2d7b..214092f6 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -203,6 +203,38 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index) 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) | + (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) { -- cgit v1.2.3