summaryrefslogtreecommitdiff
path: root/src/stm
diff options
context:
space:
mode:
Diffstat (limited to 'src/stm')
-rw-r--r--src/stm/Makefile.defs2
-rw-r--r--src/stm/ao_arch_funcs.h44
-rw-r--r--src/stm/ao_dma_stm.c1
-rw-r--r--src/stm/ao_exti.h38
-rw-r--r--src/stm/ao_exti_stm.c109
-rw-r--r--src/stm/ao_spi_stm.c113
-rw-r--r--src/stm/ao_usb_stm.c4
-rw-r--r--src/stm/stm32l.h16
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_ */