From a7e0bb5eb661cfde31c383d605cb9cb8ca568bc7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Jun 2016 17:04:59 -0700 Subject: altos: Block interrupts while waking tasks sleeping on timers. Interrupts may not be blocked in the timer ISR, but they need to be while walking the pending timer list and moving tasks back to the run queue. Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/stm') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 2c017c79..33359857 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -343,6 +343,14 @@ ao_arch_memory_barrier() { asm volatile("" ::: "memory"); } +static inline void +ao_arch_irq_check(void) { + uint32_t primask; + asm("mrs %0,primask" : "=&r" (primask)); + if ((primask & 1) == 0) + ao_panic(AO_PANIC_IRQ); +} + #if HAS_TASK static inline void ao_arch_init_stack(struct ao_task *task, void *start) -- cgit v1.2.3 From 0dec7d0885970a7d73468dd77220bae78e161b40 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Jun 2016 17:11:38 -0700 Subject: altos/stm: remove ao_dma_abort This function isn't used anywhere. Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 3 --- src/stm/ao_dma_stm.c | 7 ------- 2 files changed, 10 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 33359857..25b43587 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -249,9 +249,6 @@ ao_dma_start(uint8_t index); void ao_dma_done_transfer(uint8_t index); -void -ao_dma_abort(uint8_t index); - void ao_dma_alloc(uint8_t index); diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index 8379a1a5..298a15b5 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -105,13 +105,6 @@ ao_dma_done_transfer(uint8_t index) ao_mutex_put(&ao_dma_mutex[index]); } -void -ao_dma_abort(uint8_t index) -{ - stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); - ao_wakeup(&ao_dma_done[index]); -} - void ao_dma_alloc(uint8_t index) { -- cgit v1.2.3 From 785d2697376ebd20531d22441a60c41bd927b42a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Jun 2016 17:12:48 -0700 Subject: altos/stm: use 0xff for dma mutex value for allocated mutexes DMA channels which are 'allocated' can't be shared. Instead of using the value '1' in the related 'mutex', use 0xff which won't match any task. Signed-off-by: Keith Packard --- src/stm/ao_dma_stm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/stm') diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index 298a15b5..93b7fb47 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -64,7 +64,7 @@ ao_dma_set_transfer(uint8_t index, if (ao_dma_allocated[index]) { if (ao_dma_mutex[index]) ao_panic(AO_PANIC_DMA); - ao_dma_mutex[index] = 1; + ao_dma_mutex[index] = 0xff; } else ao_mutex_get(&ao_dma_mutex[index]); ao_arch_critical( -- cgit v1.2.3 From 21a29c7452398e0cca0fb90f99fa42a2a0684668 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Jun 2016 17:15:27 -0700 Subject: altos/stm: Add more SPI status register bits These weren't the original version of the docs that we had. Signed-off-by: Keith Packard --- src/stm/stm32l.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/stm') diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 0b6b2798..352214ff 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1359,10 +1359,13 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3; #define STM_SPI_CR2_TXDMAEN 1 #define STM_SPI_CR2_RXDMAEN 0 +#define STM_SPI_SR_FRE 8 #define STM_SPI_SR_BSY 7 #define STM_SPI_SR_OVR 6 #define STM_SPI_SR_MODF 5 #define STM_SPI_SR_CRCERR 4 +#define STM_SPI_SR_UDR 3 +#define STM_SPI_SR_CHSIDE 2 #define STM_SPI_SR_TXE 1 #define STM_SPI_SR_RXNE 0 -- cgit v1.2.3 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_arch_funcs.h | 2 +- src/stm/ao_spi_stm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/stm') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 25b43587..8393898d 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -80,7 +80,7 @@ void 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); static inline void ao_spi_send_byte(uint8_t byte, uint8_t spi_index) 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 f418584d4d225827e08f56de86055eb3f074f8d1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Jun 2016 17:26:19 -0700 Subject: altos: Add STM DMA debugging This provides a command that shows current DMA operations when compiled with -DDEBUG=1. Without that, this patch has no effect. Signed-off-by: Keith Packard --- src/stm/ao_dma_stm.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'src/stm') diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index 93b7fb47..0135de48 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -113,6 +113,40 @@ ao_dma_alloc(uint8_t index) ao_dma_allocated[index] = 1; } +#if DEBUG +void +ao_dma_dump_cmd(void) +{ + int i; + + ao_arch_critical( + if (ao_dma_active++ == 0) + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); + ); + printf ("isr %08x ifcr%08x\n", stm_dma.isr, stm_dma.ifcr); + for (i = 0; i < NUM_DMA; i++) + printf("%d: done %d allocated %d mutex %2d ccr %04x cndtr %04x cpar %08x cmar %08x isr %08x\n", + i, + ao_dma_done[i], + ao_dma_allocated[i], + ao_dma_mutex[i], + stm_dma.channel[i].ccr, + stm_dma.channel[i].cndtr, + stm_dma.channel[i].cpar, + stm_dma.channel[i].cmar, + ao_dma_config[i].isr); + ao_arch_critical( + if (--ao_dma_active == 0) + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN); + ); +} + +static const struct ao_cmds ao_dma_cmds[] = { + { ao_dma_dump_cmd, "D\0Dump DMA status" }, + { 0, NULL } +}; +#endif + void ao_dma_init(void) { @@ -124,5 +158,7 @@ ao_dma_init(void) ao_dma_allocated[index] = 0; ao_dma_mutex[index] = 0; } - +#if DEBUG + ao_cmd_register(&ao_dma_cmds[0]); +#endif } -- 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') 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') 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') 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') 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 From c6c250711355ae8060e956e786702be250ef4527 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 29 Jun 2016 12:55:30 -0700 Subject: altos/stm: clean up ao_exti_enable Was computing (1 << pin) twice for no good reason. Signed-off-by: Keith Packard --- src/stm/ao_exti_stm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/stm') diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 35958cf8..925f9a22 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -144,7 +144,7 @@ ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) { uint32_t mask = (1 << pin); (void) gpio; stm_exti.pr = mask; - stm_exti.imr |= (1 << pin); + stm_exti.imr |= mask; } void -- cgit v1.2.3