diff options
Diffstat (limited to 'src/stm')
| -rw-r--r-- | src/stm/Makefile.defs | 2 | ||||
| -rw-r--r-- | src/stm/ao_arch_funcs.h | 44 | ||||
| -rw-r--r-- | src/stm/ao_dma_stm.c | 1 | ||||
| -rw-r--r-- | src/stm/ao_exti.h | 38 | ||||
| -rw-r--r-- | src/stm/ao_exti_stm.c | 109 | ||||
| -rw-r--r-- | src/stm/ao_spi_stm.c | 113 | ||||
| -rw-r--r-- | src/stm/ao_usb_stm.c | 4 | ||||
| -rw-r--r-- | src/stm/stm32l.h | 16 |
8 files changed, 305 insertions, 22 deletions
diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 76962a3e..3edfa41d 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -16,7 +16,7 @@ ifndef VERSION include ../Version endif -AO_CFLAGS=-I. -I../stm -I../core -I.. +AO_CFLAGS=-I. -I../stm -I../core -I../drivers -I.. STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) LDFLAGS=-L../stm -Wl,-Taltos.ld diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 309937d5..05bb7784 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -32,9 +32,15 @@ void ao_spi_send(void *block, uint16_t len, uint8_t spi_index); void +ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index); + +void ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void +ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index); + +void ao_spi_init(void); #define ao_spi_get_mask(reg,mask,bus) do { \ @@ -47,7 +53,7 @@ ao_spi_init(void); ao_spi_put(bus); \ } while (0) -#define ao_stm_enable_port(port) do { \ +#define ao_enable_port(port) do { \ if (&(port) == &stm_gpioa) \ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); \ else if (&(port) == &stm_gpiob) \ @@ -61,29 +67,29 @@ ao_spi_init(void); } while (0) -#define ao_stm_enable_cs(port,bit) do { \ +#define ao_enable_cs(port,bit) do { \ stm_gpio_set(&(port), bit, 1); \ stm_moder_set(&(port), bit, STM_MODER_OUTPUT); \ } while (0) #define ao_spi_init_cs(port, mask) do { \ - ao_stm_enable_port(port); \ - if (mask & 0x0001) ao_stm_enable_cs(port, 0); \ - if (mask & 0x0002) ao_stm_enable_cs(port, 1); \ - if (mask & 0x0004) ao_stm_enable_cs(port, 2); \ - if (mask & 0x0008) ao_stm_enable_cs(port, 3); \ - if (mask & 0x0010) ao_stm_enable_cs(port, 4); \ - if (mask & 0x0020) ao_stm_enable_cs(port, 5); \ - if (mask & 0x0040) ao_stm_enable_cs(port, 6); \ - if (mask & 0x0080) ao_stm_enable_cs(port, 7); \ - if (mask & 0x0100) ao_stm_enable_cs(port, 8); \ - if (mask & 0x0200) ao_stm_enable_cs(port, 9); \ - if (mask & 0x0400) ao_stm_enable_cs(port, 10); \ - if (mask & 0x0800) ao_stm_enable_cs(port, 11); \ - if (mask & 0x1000) ao_stm_enable_cs(port, 12); \ - if (mask & 0x2000) ao_stm_enable_cs(port, 13); \ - if (mask & 0x4000) ao_stm_enable_cs(port, 14); \ - if (mask & 0x8000) ao_stm_enable_cs(port, 15); \ + ao_enable_port(port); \ + if ((mask) & 0x0001) ao_enable_cs(port, 0); \ + if ((mask) & 0x0002) ao_enable_cs(port, 1); \ + if ((mask) & 0x0004) ao_enable_cs(port, 2); \ + if ((mask) & 0x0008) ao_enable_cs(port, 3); \ + if ((mask) & 0x0010) ao_enable_cs(port, 4); \ + if ((mask) & 0x0020) ao_enable_cs(port, 5); \ + if ((mask) & 0x0040) ao_enable_cs(port, 6); \ + if ((mask) & 0x0080) ao_enable_cs(port, 7); \ + if ((mask) & 0x0100) ao_enable_cs(port, 8); \ + if ((mask) & 0x0200) ao_enable_cs(port, 9); \ + if ((mask) & 0x0400) ao_enable_cs(port, 10);\ + if ((mask) & 0x0800) ao_enable_cs(port, 11);\ + if ((mask) & 0x1000) ao_enable_cs(port, 12);\ + if ((mask) & 0x2000) ao_enable_cs(port, 13);\ + if ((mask) & 0x4000) ao_enable_cs(port, 14);\ + if ((mask) & 0x8000) ao_enable_cs(port, 15);\ } while (0) /* ao_dma_stm.c diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index 21390748..e76c8e8c 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -109,6 +109,7 @@ void ao_dma_abort(uint8_t index) { stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); + ao_wakeup(&ao_dma_done[index]); } void diff --git a/src/stm/ao_exti.h b/src/stm/ao_exti.h new file mode 100644 index 00000000..43eaa52f --- /dev/null +++ b/src/stm/ao_exti.h @@ -0,0 +1,38 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * 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. + */ + +#ifndef _AO_EXTI_H_ +#define _AO_EXTI_H_ + +#define AO_EXTI_MODE_RISING 1 +#define AO_EXTI_MODE_FALLING 2 +#define AO_EXTI_MODE_PULL_UP 4 +#define AO_EXTI_MODE_PULL_DOWN 8 + +void +ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)()); + +void +ao_exti_enable(struct stm_gpio *gpio, uint8_t pin); + +void +ao_exti_disable(struct stm_gpio *gpio, uint8_t pin); + +void +ao_exti_init(void); + +#endif /* _AO_EXTI_H_ */ diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c new file mode 100644 index 00000000..013d453b --- /dev/null +++ b/src/stm/ao_exti_stm.c @@ -0,0 +1,109 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * 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 <ao.h> +#include <ao_exti.h> + +static void (*ao_exti_callback[16])(void); + +static void +ao_exti_isr(void) { + uint32_t pending = stm_exti.pr; + uint8_t pin; + + /* Clear pending interrupts */ + stm_exti.pr = pending; + for (pin = 0; pin < 16 && pending; pin++) { + uint32_t mask = (1 << pin); + + if (pending & mask) { + pending &= ~mask; + if (ao_exti_callback[pin]) + (*ao_exti_callback[pin])(); + } + } +} + +void stm_exti0_isr(void) { ao_exti_isr(); } +void stm_exti1_isr(void) { ao_exti_isr(); } +void stm_exti2_isr(void) { ao_exti_isr(); } +void stm_exti3_isr(void) { ao_exti_isr(); } +void stm_exti4_isr(void) { ao_exti_isr(); } +void stm_exti9_5_isr(void) { ao_exti_isr(); } +void stm_exti15_10_isr(void) { ao_exti_isr(); } + +void +ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) { + uint32_t mask = 1 << pin; + uint32_t pupdr; + uint8_t irq; + + ao_exti_callback[pin] = callback; + /* configure pin as input, setting selected pull-up/down mode */ + stm_moder_set(gpio, pin, STM_MODER_INPUT); + switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) { + case 0: + default: + pupdr = STM_PUPDR_NONE; + break; + case AO_EXTI_MODE_PULL_UP: + pupdr = STM_PUPDR_PULL_UP; + break; + case AO_EXTI_MODE_PULL_DOWN: + pupdr = STM_PUPDR_PULL_DOWN; + break; + } + stm_pupdr_set(gpio, pin, pupdr); + + /* Set interrupt mask and rising/falling mode */ + stm_exti.imr &= ~mask; + stm_exti.rtsr |= mask; + if (mode & AO_EXTI_MODE_RISING) + stm_exti.rtsr |= mask; + if (mode & AO_EXTI_MODE_FALLING) + stm_exti.ftsr |= mask; + + if (pin <= 4) + irq = STM_ISR_EXTI0_POS + pin; + else if (pin <= 9) + irq = STM_ISR_EXTI9_5_POS; + else + irq = STM_ISR_EXTI15_10_POS; + stm_nvic_set_priority(irq, 10); + stm_nvic_set_enable(irq); +} + +void +ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) { + stm_exti.imr |= (1 << pin); +} + +void +ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) { + stm_exti.imr &= ~(1 << pin); +} + +void +ao_exti_init(void) +{ + stm_nvic_set_priority(STM_ISR_EXTI1_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI2_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI3_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI4_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI9_5_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI15_10_POS, 10); +} diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index be24ebcf..8bb0d8e8 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -97,6 +97,62 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_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[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 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; @@ -154,6 +210,63 @@ ao_spi_recv(void *block, uint16_t len, 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; diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 223fdeaa..71bf1bc7 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -1005,6 +1005,7 @@ ao_usb_echo(void) } #endif +#if USB_DEBUG static void ao_usb_irq(void) { @@ -1016,6 +1017,7 @@ __code struct ao_cmds ao_usb_cmds[] = { { ao_usb_irq, "I\0Show USB interrupt counts" }, { 0, NULL } }; +#endif void ao_usb_init(void) @@ -1027,7 +1029,9 @@ ao_usb_init(void) #if USB_ECHO ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); #endif +#if USB_DEBUG ao_cmd_register(&ao_usb_cmds[0]); +#endif #if !USB_ECHO ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); #endif diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index e884ef04..10a53a47 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -101,13 +101,13 @@ stm_ospeedr_get(struct stm_gpio *gpio, int pin) { #define STM_PUPDR_RESERVED 3 static inline void -stm_pupdr_set(struct stm_gpio *gpio, int pin, vuint32_t value) { +stm_pupdr_set(struct stm_gpio *gpio, int pin, uint32_t value) { gpio->pupdr = ((gpio->pupdr & ~(STM_PUPDR_MASK << STM_PUPDR_SHIFT(pin))) | value << STM_PUPDR_SHIFT(pin)); } -static inline vuint32_t +static inline uint32_t stm_pupdr_get(struct stm_gpio *gpio, int pin) { return (gpio->pupdr >> STM_PUPDR_SHIFT(pin)) & STM_PUPDR_MASK; } @@ -1589,4 +1589,16 @@ union stm_usb_bdt { extern uint8_t stm_usb_sram[]; +struct stm_exti { + vuint32_t imr; + vuint32_t emr; + vuint32_t rtsr; + vuint32_t ftsr; + + vuint32_t swier; + vuint32_t pr; +}; + +extern struct stm_exti stm_exti; + #endif /* _STM32L_H_ */ |
