summaryrefslogtreecommitdiff
path: root/src/stmf0
diff options
context:
space:
mode:
Diffstat (limited to 'src/stmf0')
-rw-r--r--src/stmf0/ao_arch.h13
-rw-r--r--src/stmf0/ao_arch_funcs.h21
-rw-r--r--src/stmf0/ao_beep_stm.c6
-rw-r--r--src/stmf0/ao_exti.h1
-rw-r--r--src/stmf0/ao_serial_stm.c102
-rw-r--r--src/stmf0/ao_storage_stm.c191
-rw-r--r--src/stmf0/ao_timer.c1
-rw-r--r--src/stmf0/ao_usb_stm.c2
-rw-r--r--src/stmf0/stm32f0.h4
9 files changed, 272 insertions, 69 deletions
diff --git a/src/stmf0/ao_arch.h b/src/stmf0/ao_arch.h
index c5f451f5..5c5085d9 100644
--- a/src/stmf0/ao_arch.h
+++ b/src/stmf0/ao_arch.h
@@ -94,12 +94,17 @@ extern const uint32_t ao_radio_cal;
* For the stm32f042, we want to use the USB-based HSI48 clock
*/
-#if AO_HSI48
+#ifndef AO_SYSCLK
+#if AO_HSI
+#define AO_SYSCLK STM_HSI_FREQ
+#endif
+#if AO_HSI48
#define AO_SYSCLK 48000000
-#define AO_HCLK (AO_SYSCLK / AO_AHB_PRESCALER)
-
#endif
+#endif
+
+#define AO_HCLK (AO_SYSCLK / AO_AHB_PRESCALER)
#if AO_HSE || AO_HSI
@@ -150,7 +155,9 @@ ao_adc_init();
#if HAS_BOOT_LOADER
#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x08001000)
+#ifndef AO_BOOT_APPLICATION_BOUND
#define AO_BOOT_APPLICATION_BOUND ((uint32_t *) (0x08000000 + stm_flash_size()))
+#endif
#define AO_BOOT_LOADER_BASE ((uint32_t *) 0x08000000)
#endif
diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h
index c38ce41a..01d51f90 100644
--- a/src/stmf0/ao_arch_funcs.h
+++ b/src/stmf0/ao_arch_funcs.h
@@ -310,6 +310,27 @@ void
ao_i2c_init(void);
/* ao_serial_stm.c */
+
+#if USE_SERIAL_1_FLOW && USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_FLOW && USE_SERIAL_2_SW_FLOW
+#define HAS_SERIAL_SW_FLOW 1
+#else
+#define HAS_SERIAL_SW_FLOW 0
+#endif
+
+#if USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW
+#define USE_SERIAL_2_HW_FLOW 1
+#endif
+
+#if USE_SERIAL_1_FLOW && !USE_SERIAL_1_SW_FLOW
+#define USE_SERIAL_1_HW_FLOW 1
+#endif
+
+#if USE_SERIAL_1_HW_FLOW || USE_SERIAL_2_HW_FLOW
+#define HAS_SERIAL_HW_FLOW 1
+#else
+#define HAS_SERIAL_HW_FLOW 0
+#endif
+
struct ao_stm_usart {
struct ao_fifo rx_fifo;
struct ao_fifo tx_fifo;
diff --git a/src/stmf0/ao_beep_stm.c b/src/stmf0/ao_beep_stm.c
index 610f4a31..15137230 100644
--- a/src/stmf0/ao_beep_stm.c
+++ b/src/stmf0/ao_beep_stm.c
@@ -25,6 +25,10 @@
#define BEEPER_TIMER 1
#endif
+#ifndef BEEPER_AFR
+#define BEEPER_AFR STM_AFR_AF2
+#endif
+
#if BEEPER_TIMER == 1
#define timer stm_tim1
#define STM_RCC_TIMER STM_RCC_APB2ENR_TIM1EN
@@ -366,7 +370,7 @@ ao_beep(uint8_t beep)
timer.egr = (1 << STM_TIM23_EGR_UG);
/* Hook the timer up to the beeper pin */
- stm_afr_set(BEEPER_PORT, BEEPER_PIN, STM_AFR_AF2);
+ stm_afr_set(BEEPER_PORT, BEEPER_PIN, BEEPER_AFR);
#endif
}
}
diff --git a/src/stmf0/ao_exti.h b/src/stmf0/ao_exti.h
index 7452af8e..36c3f7ca 100644
--- a/src/stmf0/ao_exti.h
+++ b/src/stmf0/ao_exti.h
@@ -21,6 +21,7 @@
#define AO_EXTI_MODE_RISING 1
#define AO_EXTI_MODE_FALLING 2
+#define AO_EXTI_MODE_PULL_NONE 0
#define AO_EXTI_MODE_PULL_UP 4
#define AO_EXTI_MODE_PULL_DOWN 8
#define AO_EXTI_PRIORITY_LOW 16
diff --git a/src/stmf0/ao_serial_stm.c b/src/stmf0/ao_serial_stm.c
index 30b0dbd2..59cfde2e 100644
--- a/src/stmf0/ao_serial_stm.c
+++ b/src/stmf0/ao_serial_stm.c
@@ -163,24 +163,12 @@ ao_usart_drain(struct ao_stm_usart *usart)
ao_arch_release_interrupts();
}
-static const struct {
- uint32_t brr;
-} ao_usart_speeds[] = {
- [AO_SERIAL_SPEED_4800] = {
- AO_PCLK / 4800
- },
- [AO_SERIAL_SPEED_9600] = {
- AO_PCLK / 9600
- },
- [AO_SERIAL_SPEED_19200] = {
- AO_PCLK / 19200
- },
- [AO_SERIAL_SPEED_57600] = {
- AO_PCLK / 57600
- },
- [AO_SERIAL_SPEED_115200] = {
- AO_PCLK / 115200
- },
+static const uint32_t ao_usart_speeds[] = {
+ [AO_SERIAL_SPEED_4800] = 4800,
+ [AO_SERIAL_SPEED_9600] = 9600,
+ [AO_SERIAL_SPEED_19200] = 19200,
+ [AO_SERIAL_SPEED_57600] = 57600,
+ [AO_SERIAL_SPEED_115200] = 115200,
};
static void
@@ -188,11 +176,11 @@ ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed)
{
if (speed > AO_SERIAL_SPEED_115200)
return;
- usart->reg->brr = ao_usart_speeds[speed].brr;
+ usart->reg->brr = AO_PCLK / ao_usart_speeds[speed];
}
static void
-ao_usart_init(struct ao_stm_usart *usart)
+ao_usart_init(struct ao_stm_usart *usart, int hw_flow)
{
usart->reg->cr1 = ((0 << STM_USART_CR1_M1) |
(0 << STM_USART_CR1_EOBIE) |
@@ -235,44 +223,39 @@ ao_usart_init(struct ao_stm_usart *usart)
(0 << STM_USART_CR2_LBDL) |
(0 << STM_USART_CR2_ADDM7));
- usart->reg->cr3 = ((0 << STM_USART_CR3_WUFIE) |
- (0 << STM_USART_CR3_WUS) |
- (0 << STM_USART_CR3_SCARCNT) |
- (0 << STM_USART_CR3_DEP) |
- (0 << STM_USART_CR3_DEM) |
- (0 << STM_USART_CR3_DDRE) |
- (0 << STM_USART_CR3_OVRDIS) |
- (0 << STM_USART_CR3_ONEBIT) |
- (0 << STM_USART_CR3_CTIIE) |
- (0 << STM_USART_CR3_CTSE) |
- (0 << STM_USART_CR3_RTSE) |
- (0 << STM_USART_CR3_DMAT) |
- (0 << STM_USART_CR3_DMAR) |
- (0 << STM_USART_CR3_SCEN) |
- (0 << STM_USART_CR3_NACK) |
- (0 << STM_USART_CR3_HDSEL) |
- (0 << STM_USART_CR3_IRLP) |
- (0 << STM_USART_CR3_IREN) |
- (0 << STM_USART_CR3_EIE));
-
+ uint32_t cr3 = ((0 << STM_USART_CR3_WUFIE) |
+ (0 << STM_USART_CR3_WUS) |
+ (0 << STM_USART_CR3_SCARCNT) |
+ (0 << STM_USART_CR3_DEP) |
+ (0 << STM_USART_CR3_DEM) |
+ (0 << STM_USART_CR3_DDRE) |
+ (0 << STM_USART_CR3_OVRDIS) |
+ (0 << STM_USART_CR3_ONEBIT) |
+ (0 << STM_USART_CR3_CTIIE) |
+ (0 << STM_USART_CR3_CTSE) |
+ (0 << STM_USART_CR3_RTSE) |
+ (0 << STM_USART_CR3_DMAT) |
+ (0 << STM_USART_CR3_DMAR) |
+ (0 << STM_USART_CR3_SCEN) |
+ (0 << STM_USART_CR3_NACK) |
+ (0 << STM_USART_CR3_HDSEL) |
+ (0 << STM_USART_CR3_IRLP) |
+ (0 << STM_USART_CR3_IREN) |
+ (0 << STM_USART_CR3_EIE));
+
+ if (hw_flow)
+ cr3 |= ((1 << STM_USART_CR3_CTSE) |
+ (1 << STM_USART_CR3_RTSE));
+
+ usart->reg->cr3 = cr3;
/* Pick a 9600 baud rate */
ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600);
/* Enable the usart */
usart->reg->cr1 |= (1 << STM_USART_CR1_UE);
-
}
-#if HAS_SERIAL_HW_FLOW
-static void
-ao_usart_set_flow(struct ao_stm_usart *usart)
-{
- usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) |
- (1 << STM_USART_CR3_RTSE));
-}
-#endif
-
#if HAS_SERIAL_1
struct ao_stm_usart ao_stm_usart1;
@@ -360,7 +343,7 @@ ao_serial2_set_speed(uint8_t speed)
ao_usart_set_speed(&ao_stm_usart2, speed);
}
-#if HAS_SERIAL_SW_FLOW
+#if USE_SERIAL_2_FLOW && USE_SERIAL_2_SW_FLOW
void
ao_serial2_cts(void)
{
@@ -403,13 +386,13 @@ ao_serial_init(void)
*/
#if SERIAL_1_PA9_PA10
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN);
+ ao_enable_port(&stm_gpioa);
stm_afr_set(&stm_gpioa, 9, STM_AFR_AF1);
stm_afr_set(&stm_gpioa, 10, STM_AFR_AF1);
#else
#if SERIAL_1_PB6_PB7
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+ ao_enable_port(&stm_gpiob);
stm_afr_set(&stm_gpiob, 6, STM_AFR_AF0);
stm_afr_set(&stm_gpiob, 7, STM_AFR_AF0);
@@ -421,7 +404,7 @@ ao_serial_init(void)
stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN);
ao_stm_usart1.reg = &stm_usart1;
- ao_usart_init(&ao_stm_usart1);
+ ao_usart_init(&ao_stm_usart1, 0);
stm_nvic_set_enable(STM_ISR_USART1_POS);
stm_nvic_set_priority(STM_ISR_USART1_POS, 4);
@@ -440,8 +423,7 @@ ao_serial_init(void)
*/
# if SERIAL_2_PA2_PA3
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN);
-
+ ao_enable_port(&stm_gpioa);
stm_afr_set(&stm_gpioa, 2, STM_AFR_AF1);
stm_afr_set(&stm_gpioa, 3, STM_AFR_AF1);
# if USE_SERIAL_2_FLOW
@@ -459,8 +441,7 @@ ao_serial_init(void)
# endif
# else
# if SERIAL_2_PA14_PA15
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN);
-
+ ao_enable_port(&stm_gpioa);
stm_afr_set(&stm_gpioa, 14, STM_AFR_AF1);
stm_afr_set(&stm_gpioa, 15, STM_AFR_AF1);
# if USE_SERIAL_2_FLOW
@@ -484,10 +465,7 @@ ao_serial_init(void)
stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN);
ao_stm_usart2.reg = &stm_usart2;
- ao_usart_init(&ao_stm_usart2);
-# if USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW
- ao_usart_set_flow(&ao_stm_usart2);
-# endif
+ ao_usart_init(&ao_stm_usart2, USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW);
stm_nvic_set_enable(STM_ISR_USART2_POS);
stm_nvic_set_priority(STM_ISR_USART2_POS, 4);
diff --git a/src/stmf0/ao_storage_stm.c b/src/stmf0/ao_storage_stm.c
new file mode 100644
index 00000000..1a6198a7
--- /dev/null
+++ b/src/stmf0/ao_storage_stm.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright © 2017 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, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include <ao.h>
+#include <ao_storage.h>
+
+uint32_t ao_storage_block;
+ao_pos_t ao_storage_total;
+uint16_t ao_storage_unit;
+
+/* Note that the HSI clock must be running for this code to work.
+ * Also, special care must be taken with the linker to ensure that the
+ * functions marked 'ramtext' land in ram and not rom. An example of that
+ * can be found in altos-loader.ld
+ */
+
+static uint8_t
+ao_flash_is_locked(void)
+{
+ return (stm_flash.cr & (1 << STM_FLASH_CR_LOCK)) != 0;
+}
+
+static void
+ao_flash_unlock(void)
+{
+ if (!ao_flash_is_locked())
+ return;
+
+ /* Unlock FLASH_CR register */
+ stm_flash.keyr = STM_FLASH_KEYR_KEY1;
+ stm_flash.keyr = STM_FLASH_KEYR_KEY2;
+ if (ao_flash_is_locked())
+ ao_panic(AO_PANIC_FLASH);
+}
+
+static void
+ao_flash_lock(void)
+{
+ stm_flash.cr |= (1 << STM_FLASH_CR_LOCK);
+}
+
+static uint32_t
+stm_flash_page_size(void)
+{
+ uint16_t dev_id = stm_dev_id();
+
+ switch (dev_id) {
+ case 0x440: /* stm32f05x */
+ case 0x444: /* stm32f03x */
+ case 0x445: /* stm32f04x */
+ return 1024;
+ case 0x442: /* stm32f09x */
+ case 0x448: /* stm32f07x */
+ return 2048;
+ }
+ ao_panic(AO_PANIC_FLASH);
+ return 0;
+}
+
+#define ao_flash_wait_bsy() do { while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)); } while (0)
+
+static void __attribute__ ((section(".ramtext"),noinline))
+_ao_flash_erase_page(uint16_t *page)
+{
+ stm_flash.cr |= (1 << STM_FLASH_CR_PER);
+
+ stm_flash.ar = (uintptr_t) page;
+
+ stm_flash.cr |= (1 << STM_FLASH_CR_STRT);
+
+ ao_flash_wait_bsy();
+
+ stm_flash.cr &= ~(1 << STM_FLASH_CR_PER);
+}
+
+#define _ao_flash_addr(pos) ((uint16_t *) (void *) ((uint8_t *) __flash__ + (pos)))
+
+static void __attribute ((section(".ramtext"), noinline)) _ao_flash_byte(uint32_t pos, uint8_t b)
+{
+ uint16_t v;
+ uint16_t *a = _ao_flash_addr(pos & ~1);
+
+ if (pos & 1)
+ v = (*a & 0xff) | (b << 8);
+ else
+ v = (*a & 0xff00) | b;
+ *a = v;
+ ao_flash_wait_bsy();
+}
+
+static void __attribute__ ((section(".ramtext"), noinline))
+_ao_flash_write(uint32_t pos, void *sv, uint16_t len)
+{
+ uint8_t *s = sv;
+ uint16_t *f16;
+ uint16_t v;
+
+ stm_flash.cr |= (1 << STM_FLASH_CR_PG);
+
+ if (pos & 1) {
+ _ao_flash_byte(pos++, *s++);
+ len--;
+ }
+ f16 = _ao_flash_addr(pos);
+ while(len > 1) {
+ v = s[0] | (s[1] << 8);
+ s += 2;
+ *f16++ = v;
+ ao_flash_wait_bsy();
+ len -= 2;
+ pos += 2;
+ }
+ if (len)
+ _ao_flash_byte(pos, *s++);
+
+ stm_flash.cr &= ~(1 << STM_FLASH_CR_PG);
+}
+
+uint8_t
+ao_storage_erase(uint32_t pos)
+{
+ ao_arch_block_interrupts();
+ ao_flash_unlock();
+
+ _ao_flash_erase_page(_ao_flash_addr(pos));
+
+ ao_flash_lock();
+ ao_arch_release_interrupts();
+ return 1;
+}
+
+uint8_t
+ao_storage_device_write(uint32_t pos, void *v, uint16_t len)
+{
+ if (len == 0)
+ return 1;
+
+ ao_arch_block_interrupts();
+ ao_flash_unlock();
+
+ _ao_flash_write(pos, v, len);
+
+ ao_flash_lock();
+ ao_arch_release_interrupts();
+ return 1;
+}
+
+uint8_t
+ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant
+{
+ if (pos >= ao_storage_total || pos + len > ao_storage_total)
+ return 0;
+ memcpy(d, _ao_flash_addr(pos), len);
+ return 1;
+}
+
+void
+ao_storage_flush(void) __reentrant
+{
+}
+
+void
+ao_storage_setup(void)
+{
+ ao_storage_block = stm_flash_page_size();
+ ao_storage_total = ((uint8_t *) __flash_end__) - ((uint8_t *) __flash__);
+ ao_storage_unit = ao_storage_total;
+}
+
+void
+ao_storage_device_info(void) __reentrant
+{
+ printf ("Using internal flash, page %d bytes, total %d bytes\n",
+ ao_storage_block, ao_storage_total);
+}
+
+void
+ao_storage_device_init(void)
+{
+}
diff --git a/src/stmf0/ao_timer.c b/src/stmf0/ao_timer.c
index 5c05e4f1..50fd67b8 100644
--- a/src/stmf0/ao_timer.c
+++ b/src/stmf0/ao_timer.c
@@ -86,6 +86,7 @@ ao_timer_set_adc_interval(uint8_t interval)
void
ao_timer_init(void)
{
+ stm_systick.csr = 0;
stm_systick.rvr = SYSTICK_RELOAD;
stm_systick.cvr = 0;
stm_systick.csr = ((1 << STM_SYSTICK_CSR_ENABLE) |
diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c
index 652b3b6c..59aed3aa 100644
--- a/src/stmf0/ao_usb_stm.c
+++ b/src/stmf0/ao_usb_stm.c
@@ -655,7 +655,7 @@ ao_usb_ep0_in_start(uint16_t max)
ao_usb_ep0_flush();
}
-static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};
+struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};
#if AO_USB_DEVICE_ID_SERIAL
static uint8_t ao_usb_serial[2 + 48];
diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h
index e53a5dfd..61faf2e4 100644
--- a/src/stmf0/stm32f0.h
+++ b/src/stmf0/stm32f0.h
@@ -282,8 +282,8 @@ struct stm_rcc {
extern struct stm_rcc stm_rcc;
-/* Nominal high speed internal oscillator frequency is 16MHz */
-#define STM_HSI_FREQ 16000000
+/* Nominal high speed internal oscillator frequency is 8MHz */
+#define STM_HSI_FREQ 8000000
#define STM_RCC_CR_PLLRDY (25)
#define STM_RCC_CR_PLLON (24)