diff options
| -rw-r--r-- | ao-bringup/stm/Makefile | 35 | ||||
| -rw-r--r-- | ao-bringup/stm/altos-ram.ld | 69 | ||||
| -rw-r--r-- | ao-bringup/stm/altos.ld | 71 | ||||
| -rw-r--r-- | ao-bringup/stm/bringup.c | 306 | ||||
| -rw-r--r-- | ao-bringup/stm/registers.ld | 46 | 
5 files changed, 527 insertions, 0 deletions
| diff --git a/ao-bringup/stm/Makefile b/ao-bringup/stm/Makefile new file mode 100644 index 00000000..49966a4f --- /dev/null +++ b/ao-bringup/stm/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/ao-bringup/stm/altos-ram.ld b/ao-bringup/stm/altos-ram.ld new file mode 100644 index 00000000..b8fffedc --- /dev/null +++ b/ao-bringup/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/ao-bringup/stm/altos.ld b/ao-bringup/stm/altos.ld new file mode 100644 index 00000000..0a25f853 --- /dev/null +++ b/ao-bringup/stm/altos.ld @@ -0,0 +1,71 @@ +/* + * 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 + +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/ao-bringup/stm/bringup.c b/ao-bringup/stm/bringup.c new file mode 100644 index 00000000..b6fe458d --- /dev/null +++ b/ao-bringup/stm/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/ao-bringup/stm/registers.ld b/ao-bringup/stm/registers.ld new file mode 100644 index 00000000..58204b9f --- /dev/null +++ b/ao-bringup/stm/registers.ld @@ -0,0 +1,46 @@ +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; + | 
