+++ /dev/null
-CC=arm-none-eabi-gcc
-OBJCOPY=arm-none-eabi-objcopy
-
-C_LIB=/local/src/pdclib/pdclib.a
-C_INC=-I/local/src/pdclib/includes -I/local/src/pdclib/internals
-
-DEF_CFLAGS=-g -std=gnu99 -O0 -mlittle-endian -mthumb -ffreestanding -nostdlib -I../../src/stm $(C_INC)
-
-# to run from SRAM
-LD_FLAGS_RAM=-Wl,-Taltos-ram.ld
-LD_FLAGS=-Wl,-Taltos.ld
-
-CFLAGS=$(DEF_CFLAGS) -mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY
-
-OBJS=bringup.o
-
-all: bringup-ram.elf bringup.elf
-
-%.bin: %.elf
- $(OBJCOPY) -O binary $^ $@
-
-bringup.elf: $(OBJS) $(C_LIB) altos.ld
- $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $(OBJS) $(C_LIB) -lgcc
-
-bringup-ram.elf: $(OBJS) $(C_LIB) altos-ram.ld
- $(CC) $(CFLAGS) $(LD_FLAGS_RAM) -o $@ $(OBJS) $(C_LIB) -lgcc
-
-bringup.o: bringup.c
- $(CC) -c $(CFLAGS) bringup.c
-
-clean:
- rm -rf *.elf
- rm -rf *.bin
-
-.PHONY: all clean
+++ /dev/null
-/*
- * 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 <string.h>
-
-#include <stdio.h>
-#include "stm32l.h"
-
-void delay(void);
-
-static void
-set_clock(void)
-{
- uint32_t cfgr;
- uint32_t cr;
-
- /* 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 */
- /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */
- acr |= (1 << STM_FLASH_ACR_LATENCY);
- stm_flash.acr = acr;
-
- /* HCLK to 16MHz -> 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");
-#define STM_AHB_PRESCALER 1
-
- /* PCLK1 to 16MHz -> APB1 Prescaler = 1 */
- cfgr = stm_rcc.cfgr;
- cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1);
- cfgr |= (STM_RCC_CFGR_PPRE1_DIV_1 << STM_RCC_CFGR_PPRE1);
- stm_rcc.cfgr = cfgr;
-#define STM_APB1_PRESCALER 1
-
- /* PCLK2 to 16MHz -> APB2 Prescaler = 1 */
- cfgr = stm_rcc.cfgr;
- cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2);
- cfgr |= (STM_RCC_CFGR_PPRE2_DIV_1 << STM_RCC_CFGR_PPRE2);
- stm_rcc.cfgr = cfgr;
-#define STM_APB2_PRESCALER 1
-
- /* Enable power interface clock */
- stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
-
- /* Set voltage range to 1.8V */
-
- /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */
- while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0)
- asm("nop");
-
- /* Configure voltage scaling range */
- cr = stm_pwr.cr;
- cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS);
- cr |= (STM_PWR_CR_VOS_1_8 << STM_PWR_CR_VOS);
- stm_pwr.cr = cr;
-
- /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */
- while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0)
- asm("nop");
-
- /* 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");
- }
-#define STM_HSI 16000000
-
- /* 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, PLLDIV = 4 */
- cfgr = stm_rcc.cfgr;
- cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL);
- cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV);
-
-// cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL);
-// cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV);
-
- cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL);
- cfgr |= (STM_RCC_CFGR_PLLDIV_4 << STM_RCC_CFGR_PLLDIV);
-
-#define STM_PLLMUL 6
-#define STM_PLLDIV 4
-
- /* PLL source to HSI */
- cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC);
-
-#define STM_PLLSRC STM_HSI
-
- 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;
- for (;;) {
- uint32_t c, part, mask, val;
-
- c = stm_rcc.cfgr;
- mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS);
- val = (STM_RCC_CFGR_SWS_PLL << STM_RCC_CFGR_SWS);
- part = c & mask;
- if (part == val)
- break;
- }
-}
-
-#define STM_PLLVCO (STM_PLLSRC * STM_PLLMUL)
-#define STM_SYSCLK (STM_PLLVCO / STM_PLLDIV)
-#define STM_HCLK (STM_SYSCLK / STM_AHB_PRESCALER)
-#define STM_APB1 (STM_HCLK / STM_APB1_PRESCALER)
-#define STM_APB2 (STM_HCLK / STM_APB2_PRESCALER)
-
-#define BAUD_9600 (STM_APB2 / 9600)
-
-void
-set_serial()
-{
- uint32_t moder, afr;
-
- /* Enable GPIOA */
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN);
-
- /* Hook PA9, PA10 to USART1 (AFIO7) */
- stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE);
- stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE);
- stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7);
- stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7);
-
- /* Enable USART1 */
- stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN);
-
- /* 9.6KBps. PCLK1 = 16MHz. OVER8 = 0 */
-
- /* USARTDIV = PCLK1 / (16 * 9600) = 104.1{6}
- * round to 104.1875 (1667 / 16)
- *
- * actual baud rate = 16e6 / (16 * 104.1875) = 9598Bps
- */
-
- stm_usart1.brr = BAUD_9600;
-
- stm_usart1.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) |
- (0 << STM_USART_CR1_TCIE) |
- (0 << STM_USART_CR1_RXNEIE) |
- (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.cr2 = ((0 << STM_USART_CR2_LINEN) |
- (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) |
- (0 << STM_USART_CR2_CLKEN) |
- (0 << STM_USART_CR2_CPOL) |
- (0 << STM_USART_CR2_CPHA) |
- (0 << STM_USART_CR2_LBCL) |
- (0 << STM_USART_CR2_LBDIE) |
- (0 << STM_USART_CR2_LBDL) |
- (0 << STM_USART_CR2_ADD));
-
- stm_usart1.cr3 = ((0 << STM_USART_CR3_ONEBITE) |
- (0 << STM_USART_CR3_CTSIE) |
- (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));
-}
-
-void
-outbyte(char c)
-{
- if (c == '\n')
- outbyte('\r');
- while (!(stm_usart1.sr & (1 << STM_USART_SR_TXE)))
- ;
- stm_usart1.dr = c;
-}
-
-int putc( int c, FILE * stream ) {
- outbyte(c);
-}
-
-void
-serial_string(char *string)
-{
- char c;
-
- while (c = *string++)
- outbyte(c);
-}
-
-void
-set_timer6(void)
-{
- /* Turn on timer 6 */
- stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN);
-
-
-}
-
-void
-main (void)
-{
- set_clock();
- set_serial();
- set_timer6();
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN);
- stm_moder_set(&stm_gpiob, 7, STM_MODER_OUTPUT);
- stm_moder_set(&stm_gpiob, 6, STM_MODER_OUTPUT);
- for (;;) {
- stm_gpiob.odr = (1 << 7);
- printf ("hello, ");
- delay();
- stm_gpiob.odr = (1 << 6);
- printf ("world\n");
- delay();
- }
-}
-
-void
-delay(void)
-{
- int i;
- for (i = 0; i < 1000000; i++)
- __asm__ __volatile__ ("nop\n\t":::"memory");
-}
-
-static int x = 7;
-
-extern char __stack__;
-extern char __text_start__, __text_end__;
-extern char __data_start__, __data_end__;
-extern char __bss_start__, __bss_end__;
-
-void start(void) {
- memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__);
- memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__);
- main();
-}
-
-__attribute__ ((section(".interrupt")))
-static const void *interrupt[] = {
- &__stack__,
- start,
-};
--- /dev/null
+CC=arm-none-eabi-gcc
+OBJCOPY=arm-none-eabi-objcopy
+
+C_LIB=/local/src/pdclib/pdclib.a
+C_INC=-I/local/src/pdclib/includes -I/local/src/pdclib/internals
+
+DEF_CFLAGS=-g -std=gnu99 -O0 -mlittle-endian -mthumb -ffreestanding -nostdlib -I../../src/stm $(C_INC)
+
+# to run from SRAM
+LD_FLAGS_RAM=-Wl,-Taltos-ram.ld
+LD_FLAGS=-Wl,-Taltos.ld
+
+CFLAGS=$(DEF_CFLAGS) -mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY
+
+OBJS=bringup.o
+
+all: bringup-ram.elf bringup.elf
+
+%.bin: %.elf
+ $(OBJCOPY) -O binary $^ $@
+
+bringup.elf: $(OBJS) $(C_LIB) altos.ld
+ $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $(OBJS) $(C_LIB) -lgcc
+
+bringup-ram.elf: $(OBJS) $(C_LIB) altos-ram.ld
+ $(CC) $(CFLAGS) $(LD_FLAGS_RAM) -o $@ $(OBJS) $(C_LIB) -lgcc
+
+bringup.o: bringup.c
+ $(CC) -c $(CFLAGS) bringup.c
+
+clean:
+ rm -rf *.elf
+ rm -rf *.bin
+
+.PHONY: all clean
--- /dev/null
+/*
+ * 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 <string.h>
+
+#include <stdio.h>
+#include "stm32l.h"
+
+void delay(void);
+
+static void
+set_clock(void)
+{
+ uint32_t cfgr;
+ uint32_t cr;
+
+ /* 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 */
+ /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */
+ acr |= (1 << STM_FLASH_ACR_LATENCY);
+ stm_flash.acr = acr;
+
+ /* HCLK to 16MHz -> 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");
+#define STM_AHB_PRESCALER 1
+
+ /* PCLK1 to 16MHz -> APB1 Prescaler = 1 */
+ cfgr = stm_rcc.cfgr;
+ cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1);
+ cfgr |= (STM_RCC_CFGR_PPRE1_DIV_1 << STM_RCC_CFGR_PPRE1);
+ stm_rcc.cfgr = cfgr;
+#define STM_APB1_PRESCALER 1
+
+ /* PCLK2 to 16MHz -> APB2 Prescaler = 1 */
+ cfgr = stm_rcc.cfgr;
+ cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2);
+ cfgr |= (STM_RCC_CFGR_PPRE2_DIV_1 << STM_RCC_CFGR_PPRE2);
+ stm_rcc.cfgr = cfgr;
+#define STM_APB2_PRESCALER 1
+
+ /* Enable power interface clock */
+ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
+
+ /* Set voltage range to 1.8V */
+
+ /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */
+ while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0)
+ asm("nop");
+
+ /* Configure voltage scaling range */
+ cr = stm_pwr.cr;
+ cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS);
+ cr |= (STM_PWR_CR_VOS_1_8 << STM_PWR_CR_VOS);
+ stm_pwr.cr = cr;
+
+ /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */
+ while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0)
+ asm("nop");
+
+ /* 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");
+ }
+#define STM_HSI 16000000
+
+ /* 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, PLLDIV = 4 */
+ cfgr = stm_rcc.cfgr;
+ cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL);
+ cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV);
+
+// cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL);
+// cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV);
+
+ cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL);
+ cfgr |= (STM_RCC_CFGR_PLLDIV_4 << STM_RCC_CFGR_PLLDIV);
+
+#define STM_PLLMUL 6
+#define STM_PLLDIV 4
+
+ /* PLL source to HSI */
+ cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC);
+
+#define STM_PLLSRC STM_HSI
+
+ 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;
+ for (;;) {
+ uint32_t c, part, mask, val;
+
+ c = stm_rcc.cfgr;
+ mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS);
+ val = (STM_RCC_CFGR_SWS_PLL << STM_RCC_CFGR_SWS);
+ part = c & mask;
+ if (part == val)
+ break;
+ }
+}
+
+#define STM_PLLVCO (STM_PLLSRC * STM_PLLMUL)
+#define STM_SYSCLK (STM_PLLVCO / STM_PLLDIV)
+#define STM_HCLK (STM_SYSCLK / STM_AHB_PRESCALER)
+#define STM_APB1 (STM_HCLK / STM_APB1_PRESCALER)
+#define STM_APB2 (STM_HCLK / STM_APB2_PRESCALER)
+
+#define BAUD_9600 (STM_APB2 / 9600)
+
+void
+set_serial()
+{
+ uint32_t moder, afr;
+
+ /* Enable GPIOA */
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN);
+
+ /* Hook PA9, PA10 to USART1 (AFIO7) */
+ stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE);
+ stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE);
+ stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7);
+ stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7);
+
+ /* Enable USART1 */
+ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN);
+
+ /* 9.6KBps. PCLK1 = 16MHz. OVER8 = 0 */
+
+ /* USARTDIV = PCLK1 / (16 * 9600) = 104.1{6}
+ * round to 104.1875 (1667 / 16)
+ *
+ * actual baud rate = 16e6 / (16 * 104.1875) = 9598Bps
+ */
+
+ stm_usart1.brr = BAUD_9600;
+
+ stm_usart1.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) |
+ (0 << STM_USART_CR1_TCIE) |
+ (0 << STM_USART_CR1_RXNEIE) |
+ (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.cr2 = ((0 << STM_USART_CR2_LINEN) |
+ (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) |
+ (0 << STM_USART_CR2_CLKEN) |
+ (0 << STM_USART_CR2_CPOL) |
+ (0 << STM_USART_CR2_CPHA) |
+ (0 << STM_USART_CR2_LBCL) |
+ (0 << STM_USART_CR2_LBDIE) |
+ (0 << STM_USART_CR2_LBDL) |
+ (0 << STM_USART_CR2_ADD));
+
+ stm_usart1.cr3 = ((0 << STM_USART_CR3_ONEBITE) |
+ (0 << STM_USART_CR3_CTSIE) |
+ (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));
+}
+
+void
+outbyte(char c)
+{
+ if (c == '\n')
+ outbyte('\r');
+ while (!(stm_usart1.sr & (1 << STM_USART_SR_TXE)))
+ ;
+ stm_usart1.dr = c;
+}
+
+int putc( int c, FILE * stream ) {
+ outbyte(c);
+}
+
+void
+serial_string(char *string)
+{
+ char c;
+
+ while (c = *string++)
+ outbyte(c);
+}
+
+void
+set_timer6(void)
+{
+ /* Turn on timer 6 */
+ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN);
+
+
+}
+
+void
+main (void)
+{
+ set_clock();
+ set_serial();
+ set_timer6();
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN);
+ stm_moder_set(&stm_gpiob, 7, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpiob, 6, STM_MODER_OUTPUT);
+ for (;;) {
+ stm_gpiob.odr = (1 << 7);
+ printf ("hello, ");
+ delay();
+ stm_gpiob.odr = (1 << 6);
+ printf ("world\n");
+ delay();
+ }
+}
+
+void
+delay(void)
+{
+ int i;
+ for (i = 0; i < 1000000; i++)
+ __asm__ __volatile__ ("nop\n\t":::"memory");
+}
+
+static int x = 7;
+
+extern char __stack__;
+extern char __text_start__, __text_end__;
+extern char __data_start__, __data_end__;
+extern char __bss_start__, __bss_end__;
+
+void start(void) {
+ memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__);
+ memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__);
+ main();
+}
+
+__attribute__ ((section(".interrupt")))
+static const void *interrupt[] = {
+ &__stack__,
+ start,
+};
--- /dev/null
+/*
+ * 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.
+ */
+
+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);
+
+
--- /dev/null
+/*
+ * 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.
+ */
+
+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);
+
+
--- /dev/null
+/*
+ * 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_ARCH_H_
+#define _AO_ARCH_H_
+
+#include <stdio.h>
+#include <stm32l.h>
+
+/*
+ * 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_ */
+
--- /dev/null
+/*
+ * 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 "stm32l.h"
+#include <string.h>
+
+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),
+};
--- /dev/null
+/*
+ * 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"
+
+__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);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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>
+
+__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
+}
--- /dev/null
+/*
+ * 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"
+
+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;
+
+}
--- /dev/null
+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
--- /dev/null
+/*
+ * 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 _STM32L_H_
+#define _STM32L_H_
+
+#include <stdint.h>
+
+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_ */