From 9279fd42793123784ce83ca151df6f4630487722 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 16 Mar 2012 20:21:09 -0700 Subject: [PATCH] Add STM platform and stm-bringup demo program The stm-bringup doesn't run altos, it just initializes the device and writes stuff over a serial port. Works on the STM32L Discovery board at least, should do stuff on other boards too. Signed-off-by: Keith Packard --- {ao-bringup/stm => src/stm-bringup}/Makefile | 0 {ao-bringup/stm => src/stm-bringup}/bringup.c | 0 src/stm/altos-ram.ld | 69 ++ src/stm/altos.ld | 72 ++ src/stm/ao_arch.h | 129 ++++ src/stm/ao_interrupt.c | 169 +++++ src/stm/ao_led.c | 69 ++ src/stm/ao_serial_stm.c | 184 +++++ src/stm/ao_timer.c | 167 +++++ src/stm/registers.ld | 47 ++ src/stm/stm32l.h | 662 ++++++++++++++++++ 11 files changed, 1568 insertions(+) rename {ao-bringup/stm => src/stm-bringup}/Makefile (100%) rename {ao-bringup/stm => src/stm-bringup}/bringup.c (100%) create mode 100644 src/stm/altos-ram.ld create mode 100644 src/stm/altos.ld create mode 100644 src/stm/ao_arch.h create mode 100644 src/stm/ao_interrupt.c create mode 100644 src/stm/ao_led.c create mode 100644 src/stm/ao_serial_stm.c create mode 100644 src/stm/ao_timer.c create mode 100644 src/stm/registers.ld create mode 100644 src/stm/stm32l.h diff --git a/ao-bringup/stm/Makefile b/src/stm-bringup/Makefile similarity index 100% rename from ao-bringup/stm/Makefile rename to src/stm-bringup/Makefile diff --git a/ao-bringup/stm/bringup.c b/src/stm-bringup/bringup.c similarity index 100% rename from ao-bringup/stm/bringup.c rename to src/stm-bringup/bringup.c diff --git a/src/stm/altos-ram.ld b/src/stm/altos-ram.ld new file mode 100644 index 00000000..b8fffedc --- /dev/null +++ b/src/stm/altos-ram.ld @@ -0,0 +1,69 @@ +/* + * Copyright © 2012 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. + */ + +MEMORY { + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K +} + +C_STACK_SIZE = 512; + +INCLUDE registers.ld + +SECTIONS { + . = ORIGIN(ram); + + /* + * Rom contents + */ + + __text_start__ = .; + + .text : { + *(.interrupt) /* Interrupt vectors */ + *(.text) /* Executable code */ + *(.rodata) /* Constants */ + } > ram + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __text_end__ = .; + } > ram + + __data_start__ = .; + + /* Data -- relocated to RAM, but written to ROM + */ + .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + *(.data) /* initialized data */ + __data_end__ = .; + __bss_start__ = .; + } >ram + + .bss : { + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + + PROVIDE(__stack__ = . + C_STACK_SIZE); + PROVIDE(end = .); + +} + +ENTRY(start); + + diff --git a/src/stm/altos.ld b/src/stm/altos.ld new file mode 100644 index 00000000..4e955666 --- /dev/null +++ b/src/stm/altos.ld @@ -0,0 +1,72 @@ +/* + * Copyright © 2012 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. + */ + +MEMORY { + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (!w) : ORIGIN = 0x20000000, LENGTH = 16K +} + +INCLUDE registers.ld + +EXTERN (stm_interrupt_vector) +C_STACK_SIZE = 512; + +SECTIONS { + . = ORIGIN(rom); + + /* + * Rom contents + */ + + __text_start__ = .; + + .text : { + *(.interrupt) /* Interrupt vectors */ + *(.text) /* Executable code */ + *(.rodata) /* Constants */ + } > rom + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __text_end__ = .; + } > rom + + . = ORIGIN(ram); + __data_start__ = .; + + /* Data -- relocated to RAM, but written to ROM + */ + .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + *(.data) /* initialized data */ + __data_end__ = .; + __bss_start__ = .; + } >ram + + .bss : { + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + + PROVIDE(__stack__ = . + C_STACK_SIZE); + PROVIDE(end = .); + +} + +ENTRY(start); + + diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h new file mode 100644 index 00000000..e6f54fdb --- /dev/null +++ b/src/stm/ao_arch.h @@ -0,0 +1,129 @@ +/* + * Copyright © 2012 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. + */ + +#ifndef _AO_ARCH_H_ +#define _AO_ARCH_H_ + +#include +#include + +/* + * STM32L definitions and code fragments for AltOS + */ + +#define AO_STACK_SIZE 256 + +/* Various definitions to make GCC look more like SDCC */ + +#define ao_arch_naked_declare __attribute__((naked)) +#define ao_arch_naked_define +#define __pdata +#define __data +#define __xdata +#define __code const +#define __reentrant +#define __critical +#define __interrupt(n) +#define __at(n) + +#define ao_arch_reboot() /* XXX */ + +#define ao_arch_nop() asm("nop") + +#define ao_arch_interrupt(n) /* nothing */ + +#undef putchar +#undef getchar +#define putchar(c) ao_putchar(c) +#define getchar ao_getchar + +extern void putchar(char c); +extern char getchar(void); +extern void ao_avr_stdio_init(void); + +extern const uint16_t ao_serial_number; + +#define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) + +#define ao_arch_task_members\ + uint32_t *sp; /* saved stack pointer */ + +#define cli() asm("cpsid i") +#define sei() asm("cpsie i") + +#define ao_arch_init_stack(task, start) do { \ + uint32_t *sp = (uint32_t *) (task->stack + AO_STACK_SIZE); \ + uint16_t a = (uint16_t) start; \ + int i; \ + \ + /* Return address */ \ + ARM_PUSH32(sp, a); \ + \ + /* Invalid link register */ \ + ARM_PUSH32(sp, 0xffffffff); \ + \ + /* Clear register values */ \ + i = 13; \ + while (i--) \ + ARM_PUSH32(sp, 0); \ + \ + /* PSR with interrupts enabled */ \ + ARM_PUSH32(sp, 0x01000000); \ + task->sp = sp; \ +} while (0); + +#define ao_arch_save_regs() do { \ + asm("push {r0-r12,lr}\n"); \ + cli(); \ + asm("mrs r0,psr" "\n\t" "push {r0}"); \ + sei(); \ + } while (0) + +#define ao_arch_save_stack() do { \ + uint32_t sp; \ + asm("mov %0,sp" : "=&r" (sp) ); \ + ao_cur_task->sp = (uint32_t *) (sp); \ + } while (0) + +#define ao_arch_isr_stack() /* nothing */ + +#define ao_arch_cpu_idle() do { \ + asm("wfi"); \ + } while (0) + +#define ao_arch_restore_stack() do { \ + uint32_t sp; \ + sp = (uint32_t) ao_cur_task->sp; \ + cli(); \ + asm("mov sp, %0" : : "r" (sp) ); \ + asm("pop {r0}" "\n\t" "msr psr,r0"); \ + asm("pop {r0-r12,lr}\n"); \ + asm("bx lr"); \ + } while(0) + +#define ao_arch_critical(b) do { cli(); do { b } while (0); sei(); } while (0) + +#define AO_ARM_NUM_ADC 12 + +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + uint16_t adc[AO_ARM_NUM_ADC]; /* samples */ +}; + + +#endif /* _AO_ARCH_H_ */ + diff --git a/src/stm/ao_interrupt.c b/src/stm/ao_interrupt.c new file mode 100644 index 00000000..6b4a9700 --- /dev/null +++ b/src/stm/ao_interrupt.c @@ -0,0 +1,169 @@ +/* + * Copyright © 2012 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 "stm32l.h" +#include + +extern void main(void); +extern char __stack__; +extern char __text_start__, __text_end__; +extern char __data_start__, __data_end__; +extern char __bss_start__, __bss_end__; + +/* Interrupt functions */ + +void stm_halt_isr(void) +{ + for(;;); +} + +void stm_ignore_isr(void) +{ +} + +void start(void) { + memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); + memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); + main(); +} + +#define STRINGIFY(x) #x + +#define isr(name) \ + void __attribute__ ((weak)) stm_ ## name ## _isr(void); \ + _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_ignore_isr)) + +#define isr_halt(name) \ + void __attribute__ ((weak)) stm_ ## name ## _isr(void); \ + _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_halt_isr)) + +isr(nmi) +isr_halt(hardfault) +isr_halt(memmanage) +isr_halt(busfault) +isr_halt(usagefault) +isr(svc) +isr(debugmon) +isr(pendsv) +isr(systick) +isr(wwdg) +isr(pvd) +isr(tamper_stamp) +isr(rtc_wkup) +isr(flash) +isr(rcc) +isr(exti0) +isr(exti1) +isr(exti2) +isr(exti3) +isr(exti4) +isr(dma1_channel1) +isr(dma1_channel2) +isr(dma1_channel3) +isr(dma1_channel4) +isr(dma1_channel5) +isr(dma1_channel6) +isr(dma1_channel7) +isr(adc1) +isr(usb_hp) +isr(usb_lp) +isr(dac) +isr(comp) +isr(exti9_5) +isr(lcd) +isr(tim9) +isr(tim10) +isr(tim11) +isr(tim2) +isr(tim3) +isr(tim4) +isr(i2c1_ev) +isr(i2c1_er) +isr(i2c2_ev) +isr(i2c2_er) +isr(spi1) +isr(spi2) +isr(usart1) +isr(usart2) +isr(usart3) +isr(exti15_10) +isr(rtc_alarm) +isr(usb_fs_wkup) +isr(tim6) +isr(tim7) + +#define i(addr,name) [(addr)/4] = stm_ ## name ## _isr + +__attribute__ ((section(".interrupt"))) +const void *stm_interrupt_vector[] = { + [0] = &__stack__, + [1] = start, + i(0x08, nmi), + i(0x0c, hardfault), + i(0x10, memmanage), + i(0x14, busfault), + i(0x18, usagefault), + i(0x2c, svc), + i(0x30, debugmon), + i(0x38, pendsv), + i(0x3c, systick), + i(0x40, wwdg), + i(0x44, pvd), + i(0x48, tamper_stamp), + i(0x4c, rtc_wkup), + i(0x50, flash), + i(0x54, rcc), + i(0x58, exti0), + i(0x5c, exti1), + i(0x60, exti2), + i(0x64, exti3), + i(0x68, exti4), + i(0x6c, dma1_channel1), + i(0x70, dma1_channel2), + i(0x74, dma1_channel3), + i(0x78, dma1_channel4), + i(0x7c, dma1_channel5), + i(0x80, dma1_channel6), + i(0x84, dma1_channel7), + i(0x88, adc1), + i(0x8c, usb_hp), + i(0x90, usb_lp), + i(0x94, dac), + i(0x98, comp), + i(0x9c, exti9_5), + i(0xa0, lcd), + i(0xa4, tim9), + i(0xa8, tim10), + i(0xac, tim11), + i(0xb0, tim2), + i(0xb4, tim3), + i(0xb8, tim4), + i(0xbc, i2c1_ev), + i(0xc0, i2c1_er), + i(0xc4, i2c2_ev), + i(0xc8, i2c2_er), + i(0xcc, spi1), + i(0xd0, spi2), + i(0xd4, usart1), + i(0xd8, usart2), + i(0xdc, usart3), + i(0xe0, exti15_10), + i(0xe4, rtc_alarm), + i(0xe8, usb_fs_wkup), + i(0xec, tim6), + i(0xf0, tim7), +}; diff --git a/src/stm/ao_led.c b/src/stm/ao_led.c new file mode 100644 index 00000000..db65afdf --- /dev/null +++ b/src/stm/ao_led.c @@ -0,0 +1,69 @@ +/* + * Copyright © 2012 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 "ao.h" + +__pdata uint8_t ao_led_enable; + +#define LED_PORT STM_GPIOD + +void +ao_led_on(uint8_t colors) +{ + LED_PORT->odr |= (colors & ao_led_enable); +} + +void +ao_led_off(uint8_t colors) +{ + LED_PORT->odr &= ~(colors & ao_led_enable); +} + +void +ao_led_set(uint8_t colors) +{ + LED_PORT->odr = (LED_PORT->odr & ~(ao_led_enable)) | (colors & ao_led_enable); +} + +void +ao_led_toggle(uint8_t colors) +{ + LED_PORT->odr ^= (colors & ao_led_enable); +} + +void +ao_led_for(uint8_t colors, uint16_t ticks) __reentrant +{ + ao_led_on(colors); + ao_delay(ticks); + ao_led_off(colors); +} + +void +ao_led_init(uint8_t enable) +{ + int bit; + + ao_led_enable = enable; + LED_PORT->odr &= ~enable; + for (bit = 0; bit < 16; bit++) { + if (enable & (1 << bit)) { + stm_moder_set(LED_PORT, bit, STM_MODER_OUTPUT); + stm_otyper_set(LED_PORT, bit, STM_OTYPER_PUSH_PULL); + } + } +} diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c new file mode 100644 index 00000000..dc446120 --- /dev/null +++ b/src/stm/ao_serial_stm.c @@ -0,0 +1,184 @@ +/* + * Copyright © 2012 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 + +__xdata struct ao_fifo ao_usart1_rx_fifo; +__xdata struct ao_fifo ao_usart1_tx_fifo; + +void +ao_debug_out(char c) +{ + if (c == '\n') + ao_debug_out('\r'); + while (!(STM_USART1->usart_sr & (1 << STM_USART_SR_TXE))); + STM_USART1->usart_dr = c; +} + +#if 0 +static __xdata uint8_t ao_serial_tx1_started; + +static void +ao_serial_tx1_start(void) +{ + if (!ao_fifo_empty(ao_usart1_tx_fifo) && + !ao_serial_tx1_started) + { + ao_serial_tx1_started = 1; + ao_fifo_remove(ao_usart1_tx_fifo, STM_USART1->usart_dr); + } +} + +void usart1_isr(void) +{ + if (STM_USART1->usart_sr & (1 << STM_USART_SR_RXNE)) { + if (!ao_fifo_full(ao_usart1_rx_fifo)) + ao_fifo_insert(ao_usart1_rx_fifo, STM_USART1->usart_dr); + ao_wakeup(&ao_usart1_rx_fifo); +#if USE_SERIAL_STDIN + ao_wakeup(&ao_stdin_ready); +#endif + } + if (STM_USART1->usart_sr & (1 << STM_USART_SR_TXE)) { + ao_serial_tx1_started = 0; + ao_serial_tx1_start(); + ao_wakeup(&ao_usart1_tx_fifo); + } +} + +char +ao_serial_getchar(void) __critical +{ + char c; + cli(); + while (ao_fifo_empty(ao_usart1_rx_fifo)) + ao_sleep(&ao_usart1_rx_fifo); + ao_fifo_remove(ao_usart1_rx_fifo, c); + sei(); + return c; +} + +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical +{ + char c; + cli(); + if (ao_fifo_empty(ao_usart1_rx_fifo)) { + sei(); + return AO_READ_AGAIN; + } + ao_fifo_remove(ao_usart1_rx_fifo,c); + sei(); + return c; +} +#endif + +void +ao_serial_putchar(char c) __critical +{ + cli(); + while (ao_fifo_full(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); + ao_fifo_insert(ao_usart1_tx_fifo, c); + ao_serial_tx1_start(); + sei(); +} + +void +ao_serial_drain(void) __critical +{ + cli(); + while (!ao_fifo_empty(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); + sei(); +} + +#endif + +int _write(int file, char *ptr, int len) +{ + int l = len; + while (l--) + ao_debug_out(*ptr++); + return len; +} + +#define F_CPU 24000000 + +static const struct { + uint32_t usart_brr; +} ao_serial_speeds[] = { + [AO_SERIAL_SPEED_4800] = { + (F_CPU * 16) / (16 * 4800) + }, + [AO_SERIAL_SPEED_9600] = { + (F_CPU * 16) / (16 * 9600) + }, + [AO_SERIAL_SPEED_19200] = { + (F_CPU * 16) / (16 * 19200) + }, + [AO_SERIAL_SPEED_57600] = { + (F_CPU * 16) / (16 * 57600) + }, +}; + +void +ao_serial_set_speed(uint8_t speed) +{ +#if 0 + ao_serial_drain(); +#endif + if (speed > AO_SERIAL_SPEED_57600) + return; + STM_USART1->usart_brr = ao_serial_speeds[speed].usart_brr; +} + +void +ao_serial_init(void) +{ + STM_USART1->usart_cr1 = ((0 << STM_USART_CR1_OVER8) | + (1 << STM_USART_CR1_UE) | + (0 << STM_USART_CR1_M) | + (0 << STM_USART_CR1_WAKE) | + (0 << STM_USART_CR1_PCE) | + (0 << STM_USART_CR1_PS) | + (0 << STM_USART_CR1_PEIE) | + (0 << STM_USART_CR1_TXEIE) | /* XXX enable */ + (0 << STM_USART_CR1_TCIE) | + (0 << STM_USART_CR1_RXNEIE) | /* XXX enable */ + (0 << STM_USART_CR1_IDLEIE) | + (1 << STM_USART_CR1_TE) | + (1 << STM_USART_CR1_RE) | + (0 << STM_USART_CR1_RWU) | + (0 << STM_USART_CR1_SBK)); + + STM_USART1->usart_cr2 = 0; + STM_USART1->usart_cr3 = 0; + + /* Pick a 9600 baud rate */ + ao_serial_set_speed(AO_SERIAL_SPEED_9600); + + printf ("serial initialized\n"); +#if 0 +#if USE_SERIAL_STDIN + ao_add_stdio(ao_serial_pollchar, + ao_serial_putchar, + NULL); +#endif +#endif +} diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c new file mode 100644 index 00000000..f253e0c0 --- /dev/null +++ b/src/stm/ao_timer.c @@ -0,0 +1,167 @@ +/* + * Copyright © 2012 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 "ao.h" + +static volatile __data uint16_t ao_tick_count; + +uint16_t ao_time(void) +{ + uint16_t v; + ao_arch_critical( + v = ao_tick_count; + ); + return v; +} + +static __xdata uint8_t ao_forever; + +void +ao_delay(uint16_t ticks) +{ + ao_alarm(ticks); + ao_sleep(&ao_forever); +} + +#define T2_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ +#define T2_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ + +#if HAS_ADC +volatile __data uint8_t ao_adc_interval = 1; +volatile __data uint8_t ao_adc_count; +#endif + +void +ao_debug_out(char c); + + +void tim2_isr(void) +{ + ++ao_tick_count; +#if HAS_ADC + if (++ao_adc_count == ao_adc_interval) { + ao_adc_count = 0; + ao_adc_poll(); + } +#endif +} + +#if HAS_ADC +void +ao_timer_set_adc_interval(uint8_t interval) __critical +{ + ao_adc_interval = interval; + ao_adc_count = 0; +} +#endif + +void +ao_timer_init(void) +{ +} + +void +ao_clock_init(void) +{ + uint32_t cfgr; + + /* Set flash latency to tolerate 32MHz SYSCLK -> 1 wait state */ + uint32_t acr = STM_FLASH->acr; + + /* Enable 64-bit access and prefetch */ + acr |= (1 << STM_FLASH_ACR_ACC64) | (1 << STM_FLASH_ACR_PRFEN); + STM_FLASH->acr = acr; + + /* Enable 1 wait state so the CPU can run at 32MHz */ + acr |= (1 << STM_FLASH_ACR_LATENCY); + STM_FLASH->acr = acr; + + /* Enable HSI RC clock 16MHz */ + if (!(STM_RCC->cr & (1 << STM_RCC_CR_HSIRDY))) { + STM_RCC->cr |= (1 << STM_RCC_CR_HSION); + while (!(STM_RCC->cr & (1 << STM_RCC_CR_HSIRDY))) + asm("nop"); + } + + /* Switch to direct HSI for SYSCLK */ + if ((STM_RCC->cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) { + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); + cfgr |= (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW); + STM_RCC->cfgr = cfgr; + while ((STM_RCC->cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) + asm("nop"); + } + + /* Disable the PLL */ + STM_RCC->cr &= ~(1 << STM_RCC_CR_PLLON); + while (STM_RCC->cr & (1 << STM_RCC_CR_PLLRDY)) + asm("nop"); + + /* PLLVCO to 96MHz (for USB) -> PLLMUL = 6 */ + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL); + cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); + + /* SYSCLK to 32MHz from PLL clock -> PLLDIV = /3 */ + cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV); + cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV); + + /* PLL source to HSI */ + cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC); + + STM_RCC->cfgr = cfgr; + + /* Enable the PLL and wait for it */ + STM_RCC->cr |= (1 << STM_RCC_CR_PLLON); + while (!(STM_RCC->cr & (1 << STM_RCC_CR_PLLRDY))) + asm("nop"); + + /* Switch to the PLL for the system clock */ + + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); + cfgr |= (STM_RCC_CFGR_SW_PLL << STM_RCC_CFGR_SW); + STM_RCC->cfgr = cfgr; + while ((STM_RCC->cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_PLL << STM_RCC_CFGR_SWS)) + asm("nop"); + + /* HCLK to 32MHz -> AHB prescaler = /1 */ + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE); + cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE); + STM_RCC->cfgr = cfgr; + while ((STM_RCC->cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) != + (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE)) + asm ("nop"); + + /* PCLK1 to 16MHz -> APB1 Prescaler = 2 */ + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1); + cfgr |= (STM_RCC_CFGR_PPRE1_DIV_2 << STM_RCC_CFGR_PPRE1); + STM_RCC->cfgr = cfgr; + + /* PCLK2 to 16MHz -> APB2 Prescaler = 2 */ + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2); + cfgr |= (STM_RCC_CFGR_PPRE2_DIV_2 << STM_RCC_CFGR_PPRE2); + STM_RCC->cfgr = cfgr; + +} diff --git a/src/stm/registers.ld b/src/stm/registers.ld new file mode 100644 index 00000000..51921444 --- /dev/null +++ b/src/stm/registers.ld @@ -0,0 +1,47 @@ +stm_fsmc = 0xa0000000; +stm_aes = 0x50060000; +stm_dma = 0x40026000; +stm_flash = 0x40023c00; +stm_rcc = 0x40023800; +stm_crc = 0x40023000; +stm_gpioh = 0x40021400; +stm_gpioe = 0x40021000; +stm_gpiod = 0x40020c00; +stm_gpioc = 0x40020800; +stm_gpiob = 0x40020400; +stm_gpioa = 0x40020000; +stm_usart1 = 0x40013800; +stm_spi1 = 0x40013000; +stm_sdio = 0x40012c00; +stm_adc = 0x40012400; +stm_tim11 = 0x40011000; +stm_tim10 = 0x40010c00; +stm_tim9 = 0x40010800; +stm_exti = 0x40010400; +stm_syscfg = 0x40010000; +stm_comp = 0x40007c00; +stm_ri = 0x40007c04; +stm_dac = 0x40007400; +stm_pwr = 0x40007000; +stm_usb_sram = 0x40006000; +stm_usb = 0x40005c00; +stm_i2c2 = 0x40005800; +stm_i2c1 = 0x40005400; +stm_usart5 = 0x40005000; +stm_usart4 = 0x40004c00; +stm_usart3 = 0x40004800; +stm_usart2 = 0x40004400; +stm_spi3 = 0x40003c00; /* docs are broken here */ +stm_spi2 = 0x40003800; /* docs are broken here */ +stm_iwdg = 0x40003000; +stm_wwdg = 0x40002c00; +stm_rtc = 0x40002800; +stm_lcd = 0x40002400; +stm_tim7 = 0x40001400; +stm_tim6 = 0x40001000; +stm_tim5 = 0x40000c00; +stm_tim4 = 0x40000800; +stm_tim3 = 0x40000400; +stm_tim2 = 0x40000000; + +stm_nvic = 0xe000e100; \ No newline at end of file diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h new file mode 100644 index 00000000..c5e2a797 --- /dev/null +++ b/src/stm/stm32l.h @@ -0,0 +1,662 @@ +/* + * Copyright © 2012 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. + */ + +#ifndef _STM32L_H_ +#define _STM32L_H_ + +#include + +typedef volatile uint32_t vuint32_t; + +struct stm_gpio { + vuint32_t moder; + vuint32_t otyper; + vuint32_t ospeedr; + vuint32_t pupdr; + + vuint32_t idr; + vuint32_t odr; + vuint32_t bsrr; + vuint32_t lckr; + + vuint32_t afrl; + vuint32_t afrh; +}; + +#define STM_MODER_SHIFT(pin) ((pin) << 1) +#define STM_MODER_MASK 3 +#define STM_MODER_INPUT 0 +#define STM_MODER_OUTPUT 1 +#define STM_MODER_ALTERNATE 2 +#define STM_MODER_ANALOG 3 + +static inline void +stm_moder_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->moder = ((gpio->moder & + ~(STM_MODER_MASK << STM_MODER_SHIFT(pin))) | + value << STM_MODER_SHIFT(pin)); +} + +static inline vuint32_t +stm_moder_get(struct stm_gpio *gpio, int pin) { + return (gpio->moder >> STM_MODER_SHIFT(pin)) & STM_MODER_MASK; +} + +#define STM_OTYPER_SHIFT(pin) (pin) +#define STM_OTYPER_MASK 1 +#define STM_OTYPER_PUSH_PULL 0 +#define STM_OTYPER_OPEN_DRAIN 1 + +static inline void +stm_otyper_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->otyper = ((gpio->otyper & + ~(STM_OTYPER_MASK << STM_OTYPER_SHIFT(pin))) | + value << STM_OTYPER_SHIFT(pin)); +} + +static inline vuint32_t +stm_otyper_get(struct stm_gpio *gpio, int pin) { + return (gpio->otyper >> STM_OTYPER_SHIFT(pin)) & STM_OTYPER_MASK; +} + +#define STM_OSPEEDR_SHIFT(pin) ((pin) << 1) +#define STM_OSPEEDR_MASK 3 +#define STM_OSPEEDR_400kHz 0 +#define STM_OSPEEDR_2MHz 1 +#define STM_OSPEEDR_10MHz 2 +#define STM_OSPEEDR_40MHz 3 + +static inline void +stm_ospeedr_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->ospeedr = ((gpio->ospeedr & + ~(STM_OSPEEDR_MASK << STM_OSPEEDR_SHIFT(pin))) | + value << STM_OSPEEDR_SHIFT(pin)); +} + +static inline vuint32_t +stm_ospeedr_get(struct stm_gpio *gpio, int pin) { + return (gpio->ospeedr >> STM_OSPEEDR_SHIFT(pin)) & STM_OSPEEDR_MASK; +} + +#define STM_PUPDR_SHIFT(pin) ((pin) << 1) +#define STM_PUPDR_MASK 3 +#define STM_PUPDR_NONE 0 +#define STM_PUPDR_PULL_UP 1 +#define STM_PUPDR_PULL_DOWN 2 +#define STM_PUPDR_RESERVED 3 + +static inline void +stm_pupdr_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->pupdr = ((gpio->pupdr & + ~(STM_PUPDR_MASK << STM_PUPDR_SHIFT(pin))) | + value << STM_PUPDR_SHIFT(pin)); +} + +static inline vuint32_t +stm_pupdr_get(struct stm_gpio *gpio, int pin) { + return (gpio->pupdr >> STM_PUPDR_SHIFT(pin)) & STM_PUPDR_MASK; +} + +#define STM_AFR_SHIFT(pin) ((pin) << 2) +#define STM_AFR_MASK 0xf +#define STM_AFR_NONE 0 +#define STM_AFR_AF0 0x0 +#define STM_AFR_AF1 0x1 +#define STM_AFR_AF2 0x2 +#define STM_AFR_AF3 0x3 +#define STM_AFR_AF4 0x4 +#define STM_AFR_AF5 0x5 +#define STM_AFR_AF6 0x6 +#define STM_AFR_AF7 0x7 +#define STM_AFR_AF8 0x8 +#define STM_AFR_AF9 0x9 +#define STM_AFR_AF10 0xa +#define STM_AFR_AF11 0xb +#define STM_AFR_AF12 0xc +#define STM_AFR_AF13 0xd +#define STM_AFR_AF14 0xe +#define STM_AFR_AF15 0xf + +static inline void +stm_afr_set(struct stm_gpio *gpio, int pin, uint32_t value) { + if (pin < 8) + gpio->afrl = ((gpio->afrl & + ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) | + value << STM_AFR_SHIFT(pin)); + else { + pin -= 8; + gpio->afrh = ((gpio->afrh & + ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) | + value << STM_AFR_SHIFT(pin)); + } +} + +static inline uint32_t +stm_afr_get(struct stm_gpio *gpio, int pin) { + if (pin < 8) + return (gpio->afrl >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK; + else { + pin -= 8; + return (gpio->afrh >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK; + } +} + +extern struct stm_gpio stm_gpioa; +extern struct stm_gpio stm_gpiob; +extern struct stm_gpio stm_gpioc; +extern struct stm_gpio stm_gpiod; +extern struct stm_gpio stm_gpioe; +extern struct stm_gpio stm_gpioh; + +struct stm_usart { + vuint32_t sr; /* status register */ + vuint32_t dr; /* data register */ + vuint32_t brr; /* baud rate register */ + vuint32_t cr1; /* control register 1 */ + + vuint32_t cr2; /* control register 2 */ + vuint32_t cr3; /* control register 3 */ + vuint32_t gtpr; /* guard time and prescaler */ +}; + +extern struct stm_usart stm_usart1; + +#define STM_USART_SR_CTS (9) /* CTS flag */ +#define STM_USART_SR_LBD (8) /* LIN break detection flag */ +#define STM_USART_SR_TXE (7) /* Transmit data register empty */ +#define STM_USART_SR_TC (6) /* Transmission complete */ +#define STM_USART_SR_RXNE (5) /* Read data register not empty */ +#define STM_USART_SR_IDLE (4) /* IDLE line detected */ +#define STM_USART_SR_ORE (3) /* Overrun error */ +#define STM_USART_SR_NF (2) /* Noise detected flag */ +#define STM_USART_SR_FE (1) /* Framing error */ +#define STM_USART_SR_PE (0) /* Parity error */ + +#define STM_USART_CR1_OVER8 (15) /* Oversampling mode */ +#define STM_USART_CR1_UE (13) /* USART enable */ +#define STM_USART_CR1_M (12) /* Word length */ +#define STM_USART_CR1_WAKE (11) /* Wakeup method */ +#define STM_USART_CR1_PCE (10) /* Parity control enable */ +#define STM_USART_CR1_PS (9) /* Parity selection */ +#define STM_USART_CR1_PEIE (8) /* PE interrupt enable */ +#define STM_USART_CR1_TXEIE (7) /* TXE interrupt enable */ +#define STM_USART_CR1_TCIE (6) /* Transmission complete interrupt enable */ +#define STM_USART_CR1_RXNEIE (5) /* RXNE interrupt enable */ +#define STM_USART_CR1_IDLEIE (4) /* IDLE interrupt enable */ +#define STM_USART_CR1_TE (3) /* Transmitter enable */ +#define STM_USART_CR1_RE (2) /* Receiver enable */ +#define STM_USART_CR1_RWU (1) /* Receiver wakeup */ +#define STM_USART_CR1_SBK (0) /* Send break */ + +#define STM_USART_CR2_LINEN (14) /* LIN mode enable */ +#define STM_USART_CR2_STOP (12) /* STOP bits */ +#define STM_USART_CR2_STOP_MASK 3 +#define STM_USART_CR2_STOP_1 0 +#define STM_USART_CR2_STOP_0_5 1 +#define STM_USART_CR2_STOP_2 2 +#define STM_USART_CR2_STOP_1_5 3 + +#define STM_USART_CR2_CLKEN (11) /* Clock enable */ +#define STM_USART_CR2_CPOL (10) /* Clock polarity */ +#define STM_USART_CR2_CPHA (9) /* Clock phase */ +#define STM_USART_CR2_LBCL (8) /* Last bit clock pulse */ +#define STM_USART_CR2_LBDIE (6) /* LIN break detection interrupt enable */ +#define STM_USART_CR2_LBDL (5) /* lin break detection length */ +#define STM_USART_CR2_ADD (0) +#define STM_USART_CR2_ADD_MASK 0xf + +#define STM_USART_CR3_ONEBITE (11) /* One sample bit method enable */ +#define STM_USART_CR3_CTSIE (10) /* CTS interrupt enable */ +#define STM_USART_CR3_CTSE (9) /* CTS enable */ +#define STM_USART_CR3_RTSE (8) /* RTS enable */ +#define STM_USART_CR3_DMAT (7) /* DMA enable transmitter */ +#define STM_USART_CR3_DMAR (6) /* DMA enable receiver */ +#define STM_USART_CR3_SCEN (5) /* Smartcard mode enable */ +#define STM_USART_CR3_NACK (4) /* Smartcard NACK enable */ +#define STM_USART_CR3_HDSEL (3) /* Half-duplex selection */ +#define STM_USART_CR3_IRLP (2) /* IrDA low-power */ +#define STM_USART_CR3_IREN (1) /* IrDA mode enable */ +#define STM_USART_CR3_EIE (0) /* Error interrupt enable */ + +struct stm_spi { +}; + +extern struct stm_spi stm_spi1; + +struct stm_tim { +}; + +extern struct stm_tim stm_tim9; +extern struct stm_tim stm_tim10; +extern struct stm_tim stm_tim11; + +/* Flash interface */ + +struct stm_flash { + vuint32_t acr; + vuint32_t pecr; + vuint32_t pdkeyr; + vuint32_t pekeyr; + + vuint32_t prgkeyr; + vuint32_t optkeyr; + vuint32_t sr; + vuint32_t obr; + + vuint32_t wrpr; +}; + +extern struct stm_flash stm_flash; + +#define STM_FLASH_ACR_RUN_PD (4) +#define STM_FLASH_ACR_SLEEP_PD (3) +#define STM_FLASH_ACR_ACC64 (2) +#define STM_FLASH_ACR_PRFEN (1) +#define STM_FLASH_ACR_LATENCY (0) + +struct stm_rcc { + vuint32_t cr; + vuint32_t icscr; + vuint32_t cfgr; + vuint32_t cir; + + vuint32_t ahbrstr; + vuint32_t apb2rstr; + vuint32_t abp1rstr; + vuint32_t ahbenr; + + vuint32_t apb2enr; + vuint32_t apb1enr; + vuint32_t ahblenr; + vuint32_t apb2lpenr; + + vuint32_t apb1lpenr; + vuint32_t csr; +}; + +extern struct stm_rcc stm_rcc; + +#define STM_RCC_CR_RTCPRE (29) +#define STM_RCC_CR_RTCPRE_HSE_DIV_2 0 +#define STM_RCC_CR_RTCPRE_HSE_DIV_4 1 +#define STM_RCC_CR_RTCPRE_HSE_DIV_8 2 +#define STM_RCC_CR_RTCPRE_HSE_DIV_16 3 +#define STM_RCC_CR_RTCPRE_HSE_MASK 3 + +#define STM_RCC_CR_CSSON (28) +#define STM_RCC_CR_PLLRDY (25) +#define STM_RCC_CR_PLLON (24) +#define STM_RCC_CR_HSEBYP (18) +#define STM_RCC_CR_HSERDY (17) +#define STM_RCC_CR_HSEON (16) +#define STM_RCC_CR_MSIRDY (9) +#define STM_RCC_CR_MSION (8) +#define STM_RCC_CR_HSIRDY (1) +#define STM_RCC_CR_HSION (0) + +#define STM_RCC_CFGR_MCOPRE (28) +#define STM_RCC_CFGR_MCOPRE_DIV_1 0 +#define STM_RCC_CFGR_MCOPRE_DIV_2 1 +#define STM_RCC_CFGR_MCOPRE_DIV_4 2 +#define STM_RCC_CFGR_MCOPRE_DIV_8 3 +#define STM_RCC_CFGR_MCOPRE_DIV_16 4 +#define STM_RCC_CFGR_MCOPRE_DIV_MASK 7 + +#define STM_RCC_CFGR_MCOSEL (24) +#define STM_RCC_CFGR_MCOSEL_DISABLE 0 +#define STM_RCC_CFGR_MCOSEL_SYSCLK 1 +#define STM_RCC_CFGR_MCOSEL_HSI 2 +#define STM_RCC_CFGR_MCOSEL_MSI 3 +#define STM_RCC_CFGR_MCOSEL_HSE 4 +#define STM_RCC_CFGR_MCOSEL_PLL 5 +#define STM_RCC_CFGR_MCOSEL_LSI 6 +#define STM_RCC_CFGR_MCOSEL_LSE 7 +#define STM_RCC_CFGR_MCOSEL_MASK 7 + +#define STM_RCC_CFGR_PLLDIV (22) +#define STM_RCC_CFGR_PLLDIV_2 1 +#define STM_RCC_CFGR_PLLDIV_3 2 +#define STM_RCC_CFGR_PLLDIV_4 3 +#define STM_RCC_CFGR_PLLDIV_MASK 3 + +#define STM_RCC_CFGR_PLLMUL (18) +#define STM_RCC_CFGR_PLLMUL_3 0 +#define STM_RCC_CFGR_PLLMUL_4 1 +#define STM_RCC_CFGR_PLLMUL_6 2 +#define STM_RCC_CFGR_PLLMUL_8 3 +#define STM_RCC_CFGR_PLLMUL_12 4 +#define STM_RCC_CFGR_PLLMUL_16 5 +#define STM_RCC_CFGR_PLLMUL_24 6 +#define STM_RCC_CFGR_PLLMUL_32 7 +#define STM_RCC_CFGR_PLLMUL_48 8 +#define STM_RCC_CFGR_PLLMUL_MASK 0xf + +#define STM_RCC_CFGR_PLLSRC (16) + +#define STM_RCC_CFGR_PPRE2 (11) +#define STM_RCC_CFGR_PPRE2_DIV_1 0 +#define STM_RCC_CFGR_PPRE2_DIV_2 4 +#define STM_RCC_CFGR_PPRE2_DIV_4 5 +#define STM_RCC_CFGR_PPRE2_DIV_8 6 +#define STM_RCC_CFGR_PPRE2_DIV_16 7 +#define STM_RCC_CFGR_PPRE2_MASK 7 + +#define STM_RCC_CFGR_PPRE1 (8) +#define STM_RCC_CFGR_PPRE1_DIV_1 0 +#define STM_RCC_CFGR_PPRE1_DIV_2 4 +#define STM_RCC_CFGR_PPRE1_DIV_4 5 +#define STM_RCC_CFGR_PPRE1_DIV_8 6 +#define STM_RCC_CFGR_PPRE1_DIV_16 7 +#define STM_RCC_CFGR_PPRE1_MASK 7 + +#define STM_RCC_CFGR_HPRE (4) +#define STM_RCC_CFGR_HPRE_DIV_1 0 +#define STM_RCC_CFGR_HPRE_DIV_2 8 +#define STM_RCC_CFGR_HPRE_DIV_4 9 +#define STM_RCC_CFGR_HPRE_DIV_8 0xa +#define STM_RCC_CFGR_HPRE_DIV_16 0xb +#define STM_RCC_CFGR_HPRE_DIV_64 0xc +#define STM_RCC_CFGR_HPRE_DIV_128 0xd +#define STM_RCC_CFGR_HPRE_DIV_256 0xe +#define STM_RCC_CFGR_HPRE_DIV_512 0xf +#define STM_RCC_CFGR_HPRE_MASK 0xf + +#define STM_RCC_CFGR_SWS (2) +#define STM_RCC_CFGR_SWS_MSI 0 +#define STM_RCC_CFGR_SWS_HSI 1 +#define STM_RCC_CFGR_SWS_HSE 2 +#define STM_RCC_CFGR_SWS_PLL 3 +#define STM_RCC_CFGR_SWS_MASK 3 + +#define STM_RCC_CFGR_SW (0) +#define STM_RCC_CFGR_SW_MSI 0 +#define STM_RCC_CFGR_SW_HSI 1 +#define STM_RCC_CFGR_SW_HSE 2 +#define STM_RCC_CFGR_SW_PLL 3 +#define STM_RCC_CFGR_SW_MASK 3 + +#define STM_RCC_AHBENR_DMA1EN (24) +#define STM_RCC_AHBENR_FLITFEN (15) +#define STM_RCC_AHBENR_CRCEN (12) +#define STM_RCC_AHBENR_GPIOHEN (5) +#define STM_RCC_AHBENR_GPIOEEN (4) +#define STM_RCC_AHBENR_GPIODEN (3) +#define STM_RCC_AHBENR_GPIOCEN (2) +#define STM_RCC_AHBENR_GPIOBEN (1) +#define STM_RCC_AHBENR_GPIOAEN (0) + +#define STM_RCC_APB2ENR_USART1EN (14) +#define STM_RCC_APB2ENR_SPI1EN (12) +#define STM_RCC_APB2ENR_ADC1EN (9) +#define STM_RCC_APB2ENR_TIM11EN (4) +#define STM_RCC_APB2ENR_TIM10EN (3) +#define STM_RCC_APB2ENR_TIM9EN (2) +#define STM_RCC_APB2ENR_SYSCFGEN (0) + +#define STM_RCC_APB1ENR_COMPEN (31) +#define STM_RCC_APB1ENR_DACEN (29) +#define STM_RCC_APB1ENR_PWREN (28) +#define STM_RCC_APB1ENR_USBEN (23) +#define STM_RCC_APB1ENR_I2C2EN (22) +#define STM_RCC_APB1ENR_I2C1EN (21) +#define STM_RCC_APB1ENR_USART3EN (18) +#define STM_RCC_APB1ENR_USART2EN (17) +#define STM_RCC_APB1ENR_SPI2EN (14) +#define STM_RCC_APB1ENR_WWDGEN (11) +#define STM_RCC_APB1ENR_LCDEN (9) +#define STM_RCC_APB1ENR_TIM7EN (5) +#define STM_RCC_APB1ENR_TIM6EN (4) +#define STM_RCC_APB1ENR_TIM4EN (2) +#define STM_RCC_APB1ENR_TIM3EN (1) +#define STM_RCC_APB1ENR_TIM2EN (0) + +struct stm_pwr { + vuint32_t cr; + vuint32_t csr; +}; + +extern struct stm_pwr stm_pwr; + +#define STM_PWR_CR_LPRUN (14) + +#define STM_PWR_CR_VOS (11) +#define STM_PWR_CR_VOS_1_8 1 +#define STM_PWR_CR_VOS_1_5 2 +#define STM_PWR_CR_VOS_1_2 3 +#define STM_PWR_CR_VOS_MASK 3 + +#define STM_PWR_CR_FWU (10) +#define STM_PWR_CR_ULP (9) +#define STM_PWR_CR_DBP (8) + +#define STM_PWR_CR_PLS (5) +#define STM_PWR_CR_PLS_1_9 0 +#define STM_PWR_CR_PLS_2_1 1 +#define STM_PWR_CR_PLS_2_3 2 +#define STM_PWR_CR_PLS_2_5 3 +#define STM_PWR_CR_PLS_2_7 4 +#define STM_PWR_CR_PLS_2_9 5 +#define STM_PWR_CR_PLS_3_1 6 +#define STM_PWR_CR_PLS_EXT 7 +#define STM_PWR_CR_PLS_MASK 7 + +#define STM_PWR_CR_PVDE (4) +#define STM_PWR_CR_CSBF (3) +#define STM_PWR_CR_CWUF (2) +#define STM_PWR_CR_PDDS (1) +#define STM_PWR_CR_LPSDSR (0) + +#define STM_PWR_CSR_EWUP3 (10) +#define STM_PWR_CSR_EWUP2 (9) +#define STM_PWR_CSR_EWUP1 (8) +#define STM_PWR_CSR_REGLPF (5) +#define STM_PWR_CSR_VOSF (4) +#define STM_PWR_CSR_VREFINTRDYF (3) +#define STM_PWR_CSR_PVDO (2) +#define STM_PWR_CSR_SBF (1) +#define STM_PWR_CSR_WUF (0) + +struct stm_tim67 { + vuint32_t cr1; + vuint32_t cr2; + uint32_t _unused_08; + vuint32_t dier; + + vuint32_t sr; + vuint32_t egr; + uint32_t _unused_18; + uint32_t _unused_1c; + + uint32_t _unused_20; + vuint32_t cnt; + vuint32_t psc; + vuint32_t arr; +}; + +extern struct stm_tim67 stm_tim6; + +#define STM_TIM67_CR1_ARPE (7) +#define STM_TIM67_CR1_OPM (3) +#define STM_TIM67_CR1_URS (2) +#define STM_TIM67_CR1_UDIS (1) +#define STM_TIM67_CR1_CEN (0) + +#define STM_TIM67_CR2_MMS (4) +#define STM_TIM67_CR2_MMS_RESET 0 +#define STM_TIM67_CR2_MMS_ENABLE 1 +#define STM_TIM67_CR2_MMS_UPDATE 2 +#define STM_TIM67_CR2_MMS_MASK 7 + +#define STM_TIM67_DIER_UDE (8) +#define STM_TIM67_DIER_UIE (0) + +#define STM_TIM67_SR_UIF (0) + +#define STM_TIM67_EGR_UG (0) + +struct stm_nvic { + vuint32_t iser[3]; /* 0x000 */ + + uint8_t _unused00c[0x080 - 0x00c]; + + vuint32_t icer[3]; /* 0x080 */ + + uint8_t _unused08c[0x100 - 0x08c]; + + vuint32_t ispr[3]; /* 0x100 */ + + uint8_t _unused10c[0x180 - 0x10c]; + + vuint32_t icpr[3]; /* 0x180 */ + + uint8_t _unused18c[0x200 - 0x18c]; + + vuint32_t iabr[3]; /* 0x200 */ + + uint8_t _unused20c[0x300 - 0x20c]; + + vuint32_t ipr[21]; /* 0x300 */ + + uint8_t _unused324[0xe00 - 0x324]; + + vuint32_t stir; /* 0xe00 */ +}; + +extern struct stm_nvic stm_nvic; + +#define IRQ_REG(irq) ((irq) >> 5) +#define IRQ_BIT(irq) ((irq) & 0x1f) +#define IRQ_MASK(irq) (1 << IRQ_BIT(irq)) +#define IRQ_BOOL(v,irq) (((v) >> IRQ_BIT(irq)) & 1) + +static inline void +stm_nvic_set_enable(int irq) { + stm_nvic.iser[IRQ_REG(irq)] = IRQ_MASK(irq); +} + +static inline void +stm_nvic_clear_enable(int irq) { + stm_nvic.icer[IRQ_REG(irq)] = IRQ_MASK(irq); +} + +static inline int +stm_nvic_enabled(int irq) { + return IRQ_BOOL(stm_nvic.iser[IRQ_REG(irq)], irq); +} + +static inline void +stm_nvic_set_pending(int irq) { + stm_nvic.ispr[IRQ_REG(irq)] = IRQ_MASK(irq); +} + +static inline void +stm_nvic_clear_pending(int irq) { + stm_nvic.icpr[IRQ_REG(irq)] = IRQ_MASK(irq); +} + +static inline int +stm_nvic_pending(int irq) { + return IRQ_BOOL(stm_nvic.ispr[IRQ_REG(irq)], irq); +} + +static inline int +stm_nvic_active(int irq) { + return IRQ_BOOL(stm_nvic.iabr[IRQ_REG(irq)], irq); +} + +#define IRQ_PRIO_REG(irq) ((irq) >> 2) +#define IRQ_PRIO_BIT(irq) (((irq) & 3) << 3) +#define IRQ_PRIO_MASK(irq) (0xff << IRQ_PRIO_BIT(irq)) + +static inline void +stm_nvic_set_priority(int irq, uint8_t prio) { + int n = IRQ_PRIO_REG(irq); + uint32_t v; + + v = stm_nvic.ipr[n]; + v &= ~IRQ_PRIO_MASK(irq); + v |= (prio) << IRQ_PRIO_BIT(irq); + stm_nvic.ipr[n] = v; +} + +static inline uint8_t +stm_nvic_get_priority(int irq) { + return (stm_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0); +} + +#define isr(name) void stm_ ## name ## _isr(void); + +isr(nmi) +isr(hardfault) +isr(memmanage) +isr(busfault) +isr(usagefault) +isr(svc) +isr(debugmon) +isr(pendsv) +isr(systick) +isr(wwdg) +isr(pvd) +isr(tamper_stamp) +isr(rtc_wkup) +isr(flash) +isr(rcc) +isr(exti0) +isr(exti1) +isr(exti2) +isr(exti3) +isr(exti4) +isr(dma1_channel1) +isr(dma1_channel2) +isr(dma1_channel3) +isr(dma1_channel4) +isr(dma1_channel5) +isr(dma1_channel6) +isr(dma1_channel7) +isr(adc1) +isr(usb_hp) +isr(usb_lp) +isr(dac) +isr(comp) +isr(exti9_5) +isr(lcd) +isr(tim9) +isr(tim10) +isr(tim11) +isr(tim2) +isr(tim3) +isr(tim4) +isr(i2c1_ev) +isr(i2c1_er) +isr(i2c2_ev) +isr(i2c2_er) +isr(spi1) +isr(spi2) +isr(usart1) +isr(usart2) +isr(usart3) +isr(exti15_10) +isr(rtc_alarm) +isr(usb_fs_wkup) +isr(tim6) +isr(tim7) + +#define STM_ISR_TIM6_POS 43 + +#undef isr + +#endif /* _STM32L_H_ */ -- 2.30.2