diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/stm-bringup/Makefile | 35 | ||||
| -rw-r--r-- | src/stm-bringup/bringup.c | 306 | ||||
| -rw-r--r-- | src/stm/altos-ram.ld | 69 | ||||
| -rw-r--r-- | src/stm/altos.ld | 72 | ||||
| -rw-r--r-- | src/stm/ao_arch.h | 129 | ||||
| -rw-r--r-- | src/stm/ao_interrupt.c | 169 | ||||
| -rw-r--r-- | src/stm/ao_led.c | 69 | ||||
| -rw-r--r-- | src/stm/ao_serial_stm.c | 184 | ||||
| -rw-r--r-- | src/stm/ao_timer.c | 167 | ||||
| -rw-r--r-- | src/stm/registers.ld | 47 | ||||
| -rw-r--r-- | src/stm/stm32l.h | 662 | 
11 files changed, 1909 insertions, 0 deletions
diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile new file mode 100644 index 00000000..49966a4f --- /dev/null +++ b/src/stm-bringup/Makefile @@ -0,0 +1,35 @@ +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 diff --git a/src/stm-bringup/bringup.c b/src/stm-bringup/bringup.c new file mode 100644 index 00000000..b6fe458d --- /dev/null +++ b/src/stm-bringup/bringup.c @@ -0,0 +1,306 @@ +/* + * 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, +}; 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 <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); + + 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 <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); + + 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 <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_ */ + 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 <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), +}; 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 <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); +		} +	} +} 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 <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 +} 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 <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; + +} 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 <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_ */  | 
