From 9f9d77b6d025d8285e362e53a8f728ec47adb234 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Apr 2016 19:42:44 -0700 Subject: [PATCH] altos/stmf0: Add SPI driver. This also changes the DMA interface a bit so we can select for interrupts on only the interesting channels. Signed-off-by: Keith Packard --- src/stmf0/ao_adc_fast.c | 4 +- src/stmf0/ao_dma_stm.c | 34 ++- src/stmf0/ao_spi_stm.c | 478 ++++++++++++++++++++++++++++++++++++++++ src/stmf0/stm32f0.h | 34 ++- 4 files changed, 535 insertions(+), 15 deletions(-) create mode 100644 src/stmf0/ao_spi_stm.c diff --git a/src/stmf0/ao_adc_fast.c b/src/stmf0/ao_adc_fast.c index f6740b0e..0a2e2c5c 100644 --- a/src/stmf0/ao_adc_fast.c +++ b/src/stmf0/ao_adc_fast.c @@ -72,7 +72,9 @@ _ao_adc_start(void) (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_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) | + (1 << STM_DMA_CCR_TCIE)); + ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), ao_adc_dma_done); ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1)); diff --git a/src/stmf0/ao_dma_stm.c b/src/stmf0/ao_dma_stm.c index 78fabe18..e90c6bf8 100644 --- a/src/stmf0/ao_dma_stm.c +++ b/src/stmf0/ao_dma_stm.c @@ -28,9 +28,7 @@ static uint8_t ao_dma_allocated[STM_NUM_DMA]; static uint8_t ao_dma_mutex[STM_NUM_DMA]; static uint8_t ao_dma_active; -#define id(ch) STM_DMA_INDEX(ch) -#define id_mask(id) (STM_DMA_ISR_MASK << (id)) -#define ch_mask(ch) id_mask(id(ch)) +#define ch_mask(id) (STM_DMA_ISR_MASK << STM_DMA_ISR(id)) static void ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) { @@ -41,7 +39,7 @@ ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) { /* Ack them */ stm_dma.ifcr = isr; for (index = low_index; index <= high_index; index++) { - if (isr & id_mask(index)) { + if (isr & ch_mask(index)) { if (ao_dma_config[index].isr) (*ao_dma_config[index].isr)(index); else { @@ -52,9 +50,25 @@ ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) { } } -void stm_dma_ch1_isr(void) { ao_dma_isr(id(1), id(1), ch_mask(1)); } -void stm_dma_ch2_3_isr(void) { ao_dma_isr(id(2), id(3), ch_mask(2) | ch_mask(3)); } -void stm_dma1_ch4_5_6_isr(void) { ao_dma_isr(id(4), id(6), ch_mask(4) | ch_mask(5) | ch_mask(6)); } +void stm_dma_ch1_isr(void) { + ao_dma_isr(STM_DMA_INDEX(1), + STM_DMA_INDEX(1), + ch_mask(STM_DMA_INDEX(1))); +} + +void stm_dma_ch2_3_isr(void) { + ao_dma_isr(STM_DMA_INDEX(2), + STM_DMA_INDEX(3), + ch_mask(STM_DMA_INDEX(2)) | + ch_mask(STM_DMA_INDEX(3))); +} + +void stm_dma1_ch4_5_6_isr(void) { + ao_dma_isr(STM_DMA_INDEX(4), STM_DMA_INDEX(6), + ch_mask(STM_DMA_INDEX(4)) | + ch_mask(STM_DMA_INDEX(5)) | + ch_mask(STM_DMA_INDEX(6))); +} void ao_dma_set_transfer(uint8_t index, @@ -73,11 +87,12 @@ ao_dma_set_transfer(uint8_t index, if (ao_dma_active++ == 0) stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMAEN); ); - stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE); + ao_dma_config[index].isr = NULL; + ao_dma_done[index] = 0; stm_dma.channel[index].cndtr = count; stm_dma.channel[index].cpar = peripheral; stm_dma.channel[index].cmar = memory; - ao_dma_config[index].isr = NULL; + stm_dma.channel[index].ccr = ccr; } void @@ -89,7 +104,6 @@ ao_dma_set_isr(uint8_t index, void (*isr)(int)) void ao_dma_start(uint8_t index) { - ao_dma_done[index] = 0; stm_dma.channel[index].ccr |= (1 << STM_DMA_CCR_EN); } diff --git a/src/stmf0/ao_spi_stm.c b/src/stmf0/ao_spi_stm.c new file mode 100644 index 00000000..55bf59d2 --- /dev/null +++ b/src/stmf0/ao_spi_stm.c @@ -0,0 +1,478 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +struct ao_spi_stm_info { + uint8_t miso_dma_index; + uint8_t mosi_dma_index; + struct stm_spi *stm_spi; +}; + +static uint8_t ao_spi_mutex[STM_NUM_SPI]; +static uint8_t ao_spi_index[STM_NUM_SPI]; + +static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = { + { + .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_RX), + .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_TX), + &stm_spi1 + }, + { + .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_RX), + .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_TX), + &stm_spi2 + } +}; + +static uint8_t spi_dev_null; + + + +#define SPI_CR2 ((0 << STM_SPI_CR2_LDMA_TX) | \ + (0 << STM_SPI_CR2_LDMA_RX) | \ + (1 << STM_SPI_CR2_FRXTH) | \ + (STM_SPI_CR2_DS_8 << STM_SPI_CR2_DS) | \ + (0 << STM_SPI_CR2_TXEIE) | \ + (0 << STM_SPI_CR2_RXNEIE) | \ + (0 << STM_SPI_CR2_ERRIE) | \ + (STM_SPI_CR2_FRF_MOTOROLA << STM_SPI_CR2_FRF) | \ + (0 << STM_SPI_CR2_NSSP) | \ + (0 << STM_SPI_CR2_SSOE)) + +#define SPI_CR2_DMA (SPI_CR2 | \ + (1 << STM_SPI_CR2_TXDMAEN) | \ + (1 << STM_SPI_CR2_RXDMAEN)) + +#define SPI_CR2_SYNC (SPI_CR2 | \ + (0 << STM_SPI_CR2_TXDMAEN) | \ + (0 << STM_SPI_CR2_RXDMAEN)) + +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; + + /* Set up the transmit DMA to deliver data */ + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + (void *) 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_MEM_TO_PER << STM_DMA_CCR_DIR) | + (0 << STM_DMA_CCR_TCIE)); + + /* 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) | + (1 << STM_DMA_CCR_TCIE)); + + stm_spi->cr2 = SPI_CR2_DMA; + + 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_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; + + /* 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) | + (0 << STM_DMA_CCR_TCIE)); + + /* 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) | + (1 << STM_DMA_CCR_TCIE)); + + stm_spi->cr2 = SPI_CR2_DMA; + 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_send_sync(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; + + stm_spi->cr2 = SPI_CR2_SYNC; + + /* Clear RXNE */ + (void) stm_spi->dr; + + while (len--) { + while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE))); + stm_spi->dr = *b++; + } +} + +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; + + 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) | + (0 << STM_DMA_CCR_TCIE)); + + /* 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, + 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) | + (1 << STM_DMA_CCR_TCIE)); + + stm_spi->cr2 = SPI_CR2_DMA; + 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_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; + + /* 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) | + (0 << STM_DMA_CCR_TCIE)); + + /* 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) | + (1 << STM_DMA_CCR_TCIE)); + + stm_spi->cr2 = SPI_CR2_DMA; + 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); +} + +static void +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; + } + 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; + } + break; + } +} + +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_AF0); + stm_afr_set(&stm_gpioa, 6, STM_AFR_AF0); + stm_afr_set(&stm_gpioa, 7, STM_AFR_AF0); + break; + case AO_SPI_1_PB3_PB4_PB5: + stm_afr_set(&stm_gpiob, 3, STM_AFR_AF0); + stm_afr_set(&stm_gpiob, 4, STM_AFR_AF0); + stm_afr_set(&stm_gpiob, 5, STM_AFR_AF0); + break; + } + break; + case STM_SPI_INDEX(2): + switch (spi_index) { + case AO_SPI_2_PB13_PB14_PB15: + stm_afr_set(&stm_gpiob, 13, STM_AFR_AF0); + stm_afr_set(&stm_gpiob, 14, STM_AFR_AF0); + stm_afr_set(&stm_gpiob, 15, STM_AFR_AF0); + break; + } + break; + } +} + +static void +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->cr2 = SPI_CR2; + 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_CRCL) | + (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 + */ + ao_spi_disable_index(ao_spi_index[id]); + + /* Enable new config + */ + ao_spi_enable_index(spi_index); + + /* Remember current config + */ + ao_spi_index[id] = spi_index; + } +} + +uint8_t +ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id) +{ + uint8_t id = AO_SPI_INDEX(spi_index); + + if (!ao_mutex_try(&ao_spi_mutex[id], task_id)) + return 0; + ao_spi_config(spi_index, speed); + return 1; +} + +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); +} + +void +ao_spi_put(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->cr1 = 0; + ao_mutex_put(&ao_spi_mutex[id]); +} + +static void +ao_spi_channel_init(uint8_t spi_index) +{ + 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); + + stm_spi->cr1 = 0; + (void) stm_spi->sr; + stm_spi->cr2 = SPI_CR2_SYNC; +} + +void +ao_spi_init(void) +{ +#if HAS_SPI_1 +# if SPI_1_PA5_PA6_PA7 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); + stm_ospeedr_set(&stm_gpioa, 5, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpioa, 6, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpioa, 7, SPI_1_OSPEEDR); +# endif +# if SPI_1_PB3_PB4_PB5 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); + stm_ospeedr_set(&stm_gpiob, 3, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpiob, 4, SPI_1_OSPEEDR); + stm_ospeedr_set(&stm_gpiob, 5, SPI_1_OSPEEDR); +# endif + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); + ao_spi_index[0] = AO_SPI_CONFIG_NONE; + ao_spi_channel_init(STM_SPI_INDEX(1)); +#endif + +#if HAS_SPI_2 +# if SPI_2_PB10_PB13_PB14 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); + stm_ospeedr_set(&stm_gpiob, 13, SPI_2_OSPEEDR); + stm_ospeedr_set(&stm_gpiob, 14, SPI_2_OSPEEDR); + stm_ospeedr_set(&stm_gpiob, 15, SPI_2_OSPEEDR); +# endif + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); + ao_spi_index[1] = AO_SPI_CONFIG_NONE; + ao_spi_channel_init(STM_SPI_INDEX(2)); +#endif +} diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h index ce8ca456..14be5fbb 100644 --- a/src/stmf0/stm32f0.h +++ b/src/stmf0/stm32f0.h @@ -795,7 +795,7 @@ isr(tim7) #define STM_ISR_TSC_POS 8 #define STM_ISR_DMA_CH1_POS 9 #define STM_ISR_DMA_CH2_3_DMA2_CH1_2_POS 10 -#define STM_ISR_DMA_CH44_5_6_7_DMA2_CH3_4_5_POS 11 +#define STM_ISR_DMA_CH4_5_6_7_DMA2_CH3_4_5_POS 11 #define STM_ISR_ADC_COMP_POS 12 #define STM_ISR_TIM1_BRK_UP_TRG_COM_POS 13 #define STM_ISR_TIM1_CC_POS 14 @@ -890,7 +890,7 @@ struct stm_dma_channel { vuint32_t reserved; }; -#define STM_NUM_DMA 6 +#define STM_NUM_DMA 5 struct stm_dma { vuint32_t isr; @@ -900,7 +900,7 @@ struct stm_dma { extern struct stm_dma stm_dma; -/* DMA channels go from 1 to 6, instead of 0 to 5 (sigh) +/* DMA channels go from 1 to 5, instead of 0 to 4 (sigh) */ #define STM_DMA_INDEX(channel) ((channel) - 1) @@ -1042,7 +1042,7 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3; #define STM_SPI_CR1_BIDIOE 14 #define STM_SPI_CR1_CRCEN 13 #define STM_SPI_CR1_CRCNEXT 12 -#define STM_SPI_CR1_DFF 11 +#define STM_SPI_CR1_CRCL 11 #define STM_SPI_CR1_RXONLY 10 #define STM_SPI_CR1_SSM 9 #define STM_SPI_CR1_SSI 8 @@ -1063,17 +1063,43 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3; #define STM_SPI_CR1_CPOL 1 #define STM_SPI_CR1_CPHA 0 +#define STM_SPI_CR2_LDMA_TX 14 +#define STM_SPI_CR2_LDMA_RX 13 +#define STM_SPI_CR2_FRXTH 12 +#define STM_SPI_CR2_DS 8 +#define STM_SPI_CR2_DS_4 0x3 +#define STM_SPI_CR2_DS_5 0x4 +#define STM_SPI_CR2_DS_6 0x5 +#define STM_SPI_CR2_DS_7 0x6 +#define STM_SPI_CR2_DS_8 0x7 +#define STM_SPI_CR2_DS_9 0x8 +#define STM_SPI_CR2_DS_10 0x9 +#define STM_SPI_CR2_DS_11 0xa +#define STM_SPI_CR2_DS_12 0xb +#define STM_SPI_CR2_DS_13 0xc +#define STM_SPI_CR2_DS_14 0xd +#define STM_SPI_CR2_DS_15 0xe +#define STM_SPI_CR2_DS_16 0xf #define STM_SPI_CR2_TXEIE 7 #define STM_SPI_CR2_RXNEIE 6 #define STM_SPI_CR2_ERRIE 5 +#define STM_SPI_CR2_FRF 4 +# define STM_SPI_CR2_FRF_MOTOROLA 0 +# define STM_SPI_CR2_FRF_TI 1 +#define STM_SPI_CR2_NSSP 3 #define STM_SPI_CR2_SSOE 2 #define STM_SPI_CR2_TXDMAEN 1 #define STM_SPI_CR2_RXDMAEN 0 +#define STM_SPI_SR_FTLVL 11 +#define STM_SPI_SR_FRLVL 9 +#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 -- 2.30.2