diff options
Diffstat (limited to 'src')
50 files changed, 1201 insertions, 86 deletions
| diff --git a/src/Makefile b/src/Makefile index 90a74166..5ae61a00 100644 --- a/src/Makefile +++ b/src/Makefile @@ -29,7 +29,12 @@ AVRDIRS=\  	telescience-v0.1 telescience-pwm telepyro-v0.1 micropeak  ARMDIRS=\ -	telemega-v0.1 telemega-v0.3 megadongle-v0.1 stm-bringup stm-demo telelco-v0.1 \ +	telemega-v0.1 telemega-v0.1/flash-loader \ +	telemega-v0.3 telemega-v0.3/flash-loader \ +	megadongle-v0.1 megadongle-v0.1/flash-loader \ +	telegps-v0.1 telegps-v0.1/flash-loader \ +	stm-bringup stm-demo telelco-v0.1 \ +	telelco-v0.2 telelco-v0.2/flash-loader \  	telescience-v0.2  ifneq ($(shell which sdcc),) diff --git a/src/attiny/ao_arch.h b/src/attiny/ao_arch.h index 52bed981..8140dd30 100644 --- a/src/attiny/ao_arch.h +++ b/src/attiny/ao_arch.h @@ -55,7 +55,7 @@  #define putchar(c)	ao_putchar(c)  #define getchar		ao_getchar -#define ao_arch_cpu_idle() do {			\ +#define ao_arch_wait_interrupt() do {		\  		sleep_enable();			\  		sei();				\  		sleep_cpu();			\ diff --git a/src/avr/ao_avr_stdio.c b/src/avr/ao_avr_stdio.c index 2765853a..f9c0f88c 100644 --- a/src/avr/ao_avr_stdio.c +++ b/src/avr/ao_avr_stdio.c @@ -20,16 +20,7 @@  int  stdio_put(char c, FILE *stream)  { -	if (ao_cur_task && ao_num_stdios) -		putchar(c); -	else -	{ -		if (c == '\n') -			stdio_put('\r', stream); -		loop_until_bit_is_set(UCSR1A, UDRE1); -		UDR1 = c; -	} - +	putchar(c);  	return 0;  } diff --git a/src/core/ao.h b/src/core/ao.h index 6bcb3664..0ad3e4aa 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -45,6 +45,8 @@  #if HAS_TASK  #include <ao_task.h> +#else +#include <ao_notask.h>  #endif  /* diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 6eed08d9..188b8bb4 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -16,6 +16,7 @@   */  #include "ao.h" +#include "ao_task.h"  __pdata uint16_t ao_cmd_lex_i;  __pdata uint32_t ao_cmd_lex_u32; @@ -262,6 +263,11 @@ ao_reboot(void)  	ao_panic(AO_PANIC_REBOOT);  } +#ifndef HAS_VERSION +#define HAS_VERSION 1 +#endif + +#if HAS_VERSION  static void  version(void)  { @@ -289,6 +295,7 @@ version(void)  #endif  	printf("software-version %s\n", ao_version);  } +#endif  #ifndef NUM_CMDS  #define NUM_CMDS	11 @@ -378,14 +385,33 @@ ao_cmd(void)  	}  } +#if HAS_BOOT_LOADER + +#include <ao_boot.h> + +static void +ao_loader(void) +{ +	flush(); +	ao_boot_loader(); +} +#endif +  __xdata struct ao_task ao_cmd_task;  __code struct ao_cmds	ao_base_cmds[] = {  	{ help,		"?\0Help" }, +#if HAS_TASK_INFO  	{ ao_task_info,	"T\0Tasks" }, +#endif  	{ echo,		"E <0 off, 1 on>\0Echo" },  	{ ao_reboot,	"r eboot\0Reboot" }, +#if HAS_VERSION  	{ version,	"v\0Version" }, +#endif +#if HAS_BOOT_LOADER +	{ ao_loader,	"X\0Switch to boot loader" }, +#endif  	{ 0,	NULL },  }; diff --git a/src/micropeak/ao_notask.c b/src/core/ao_notask.c index 0aef9cf3..a41712d2 100644 --- a/src/micropeak/ao_notask.c +++ b/src/core/ao_notask.c @@ -24,7 +24,7 @@ ao_sleep(__xdata void *wchan)  {  #if 1  	ao_wchan = wchan; -	ao_arch_cpu_idle(); +	ao_arch_wait_interrupt();  #else  	uint8_t	sreg; diff --git a/src/core/ao_notask.h b/src/core/ao_notask.h new file mode 100644 index 00000000..6b6b5bb8 --- /dev/null +++ b/src/core/ao_notask.h @@ -0,0 +1,27 @@ +/* + * 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_NOTASK_H_ +#define _AO_NOTASK_H_ + +uint8_t +ao_sleep(__xdata void *wchan); + +void +ao_wakeup(__xdata void *wchan); + +#endif /* _AO_NOTASK_H_ */ diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index 977d74b1..cd144d6b 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -66,8 +66,15 @@  #define AO_NUM_STDIOS	(HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN)  __xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS]; + +#if AO_NUM_STDIOS > 1  __pdata int8_t ao_cur_stdio;  __pdata int8_t ao_num_stdios; +#else +__pdata int8_t ao_cur_stdio; +#define ao_cur_stdio	0 +#define ao_num_stdios	0 +#endif  void  putchar(char c) @@ -107,12 +114,16 @@ getchar(void) __reentrant  		c = ao_stdios[stdio]._pollchar();  		if (c != AO_READ_AGAIN)  			break; +#if AO_NUM_STDIOS > 1  		if (++stdio == ao_num_stdios)  			stdio = 0;  		if (stdio == ao_cur_stdio) +#endif  			ao_sleep(&ao_stdin_ready);  	} +#if AO_NUM_STDIOS > 1  	ao_cur_stdio = stdio; +#endif  	ao_arch_release_interrupts();  	return c;  } @@ -128,11 +139,17 @@ ao_add_stdio(int (*_pollchar)(void),  	     void (*putchar)(char),  	     void (*flush)(void)) __reentrant  { +#if AO_NUM_STDIOS > 1  	if (ao_num_stdios == AO_NUM_STDIOS)  		ao_panic(AO_PANIC_STDIO); +#endif  	ao_stdios[ao_num_stdios]._pollchar = _pollchar;  	ao_stdios[ao_num_stdios].putchar = putchar;  	ao_stdios[ao_num_stdios].flush = flush;  	ao_stdios[ao_num_stdios].echo = 1; +#if AO_NUM_STDIOS > 1  	return ao_num_stdios++; +#else +	return 0; +#endif  } diff --git a/src/core/ao_task.c b/src/core/ao_task.c index c24c9929..0aad6508 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -512,6 +512,7 @@ ao_exit(void)  	/* we'll never get back here */  } +#if HAS_TASK_INFO  void  ao_task_info(void)  { @@ -528,6 +529,7 @@ ao_task_info(void)  	ao_task_validate();  #endif  } +#endif  void  ao_start_scheduler(void) diff --git a/src/core/ao_task.h b/src/core/ao_task.h index 50bfb220..1a4b5b6b 100644 --- a/src/core/ao_task.h +++ b/src/core/ao_task.h @@ -21,6 +21,10 @@  #include <ao_list.h>  #endif +#ifndef HAS_TASK_INFO +#define HAS_TASK_INFO 1 +#endif +  /* An AltOS task */  struct ao_task {  	__xdata void *wchan;		/* current wait channel (NULL if running) */ diff --git a/src/megadongle-v0.1/Makefile b/src/megadongle-v0.1/Makefile index fe392ce1..7f12963f 100644 --- a/src/megadongle-v0.1/Makefile +++ b/src/megadongle-v0.1/Makefile @@ -28,6 +28,7 @@ INC = \  #STACK_GUARD_DEF=-DHAS_STACK_GUARD=1  ALTOS_SRC = \ +	ao_boot_chain.c \  	ao_interrupt.c \  	ao_product.c \  	ao_romconfig.c \ diff --git a/src/megadongle-v0.1/flash-loader/Makefile b/src/megadongle-v0.1/flash-loader/Makefile new file mode 100644 index 00000000..adea5786 --- /dev/null +++ b/src/megadongle-v0.1/flash-loader/Makefile @@ -0,0 +1,7 @@ +# +# AltOS flash loader build +# + +TOPDIR=../.. +HARDWARE=megadongle-v0.1 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/megadongle-v0.1/flash-loader/ao_pins.h b/src/megadongle-v0.1/flash-loader/ao_pins.h new file mode 100644 index 00000000..1af92f13 --- /dev/null +++ b/src/megadongle-v0.1/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 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_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE		8000000 + +#include <ao_flash_stm_pins.h> + +/* Companion port cs_companion0 PD0 */ + +#define AO_BOOT_PIN		1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpiod +#define AO_BOOT_APPLICATION_PIN		0 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ diff --git a/src/product/ao_flash_pins.h b/src/product/ao_flash_pins.h new file mode 100644 index 00000000..b774df6d --- /dev/null +++ b/src/product/ao_flash_pins.h @@ -0,0 +1,40 @@ +/* + * Copyright © 2013 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_FLASH_PINS_H_ +#define _AO_FLASH_PINS_H_ + +/* Common definitions for the USB flash loader */ + +#define HAS_TASK_QUEUE		0 + +#define HAS_USB			1 +#define USE_USB_STDIO		0 +#define HAS_BEEP		0 +#define HAS_TASK		0 +#define HAS_ECHO		0 +#define HAS_TICK		0 + +#define PACKET_HAS_SLAVE	0 + +#define HAS_TASK_INFO		0 +#define HAS_VERSION		0 + +#define AO_BOOT_CHAIN		1 +#define AO_BOOT_PIN		1 + +#endif /* _AO_FLASH_PINS_H_ */ diff --git a/src/stm-flash/ao_stm_flash.c b/src/product/ao_flash_task.c index df466d85..fdc4d0aa 100644 --- a/src/stm-flash/ao_stm_flash.c +++ b/src/product/ao_flash_task.c @@ -1,5 +1,5 @@  /* - * Copyright © 2011 Keith Packard <keithp@keithp.com> + * Copyright © 2013 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 @@ -18,54 +18,70 @@  #include "ao.h"  #include <ao_exti.h>  #include <ao_boot.h> -#include <ao_flash_stm.h> +#include <ao_flash.h> +#include <ao_flash_task.h>  void  ao_panic(uint8_t reason)  { -	for (;;);  }  void +ao_put_string(__code char *s) +{ +	char	c; +	while ((c = *s++)) { +		if (c == '\n') +			ao_usb_putchar('\r'); +		ao_usb_putchar(c); +	} +} + +static void  ao_application(void)  {  	ao_boot_reboot(AO_BOOT_APPLICATION_BASE);  }  static uint32_t -ao_cmd_hex32(void) +ao_get_hex32(void)  { -	__pdata uint8_t	r = ao_cmd_lex_error;  	int8_t	n;  	uint32_t v = 0; -	ao_cmd_white(); +	for (;;) { +		n = ao_usb_getchar(); +		if (n != ' ') +			break; +	}  	for(;;) { -		n = ao_cmd_hexchar(ao_cmd_lex_c); -		if (n < 0) +		if ('0' <= n && n <= '9') +			n = n - '0'; +		else if ('a' <= n && n <= 'f') +			n = n - ('a' - 10); +		else if ('A' <= n && n <= 'F') +			n = n - ('A' - 10); +		else  			break;  		v = (v << 4) | n; -		r = ao_cmd_success; -		ao_cmd_lex(); +		n = ao_usb_getchar();  	} -	if (r != ao_cmd_success) -		ao_cmd_status = r;  	return v;  } -void +static void  ao_block_erase(void)  { -	uint32_t	addr = ao_cmd_hex32(); +	uint32_t	addr = ao_get_hex32();  	uint32_t	*p = (uint32_t *) addr;  	ao_flash_erase_page(p);  } -void +static void  ao_block_write(void)  { -	uint32_t	addr = ao_cmd_hex32(); +	uint32_t	addr = ao_get_hex32();  	uint32_t	*p = (uint32_t *) addr;  	union {  		uint8_t		data8[256]; @@ -73,65 +89,49 @@ ao_block_write(void)  	} u;  	uint16_t	i; -	if (addr < 0x08002000 || 0x08200000 <= addr) { -		puts("Invalid address"); +	if (addr < (uint32_t) AO_BOOT_APPLICATION_BASE) { +		ao_put_string("Invalid address\n");  		return;  	}  	for (i = 0; i < 256; i++) -		u.data8[i] = i; +		u.data8[i] = ao_usb_getchar();  	ao_flash_page(p, u.data32);  }  static void -puthex(uint8_t c) -{ -	c &= 0xf; -	if (c < 10) -		c += '0'; -	else -		c += 'a' - 10; -	putchar (c); -} - -void  ao_block_read(void)  { -	uint32_t	addr = ao_cmd_hex32(); +	uint32_t	addr = ao_get_hex32();  	uint8_t		*p = (uint8_t *) addr;  	uint16_t	i;  	uint8_t		c;  	for (i = 0; i < 256; i++) {  		c = *p++; -		puthex(c); -		puthex(c>>4); -		if ((i & 0xf) == 0xf) -			putchar('\n'); +		ao_usb_putchar(c);  	}  } -__code struct ao_cmds ao_flash_cmds[] = { -	{ ao_application, "a\0Switch to application" }, -	{ ao_block_erase, "e <addr>\0Erase block." }, -	{ ao_block_write, "W <addr>\0Write block. 256 binary bytes follow newline" }, -	{ ao_block_read, "R <addr>\0Read block. Returns 256 bytes" }, -	{ 0, NULL }, -}; - -int -main(void) +static void +ao_show_version(void)  { -	ao_clock_init(); - -	ao_task_init(); - -	ao_timer_init(); -//	ao_dma_init(); -	ao_cmd_init(); -//	ao_exti_init(); -	ao_usb_init(); +	ao_put_string("altos-loader"); +	ao_put_string("\nmanufacturer     "); ao_put_string(ao_manufacturer); +	ao_put_string("\nproduct          "); ao_put_string(ao_product); +	ao_put_string("\nsoftware-version "); ao_put_string(ao_version); +	ao_put_string("\n"); +} -	ao_cmd_register(&ao_flash_cmds[0]); -	ao_start_scheduler(); -	return 0; +void +ao_flash_task(void) { +	for (;;) { +		ao_usb_flush(); +		switch (ao_usb_getchar()) { +		case 'v': ao_show_version(); break; +		case 'a': ao_application(); break; +		case 'X': ao_block_erase(); break; +		case 'W': ao_block_write(); break; +		case 'R': ao_block_read(); break; +		} +	}  } diff --git a/src/product/ao_flash_task.h b/src/product/ao_flash_task.h new file mode 100644 index 00000000..0a2fbb35 --- /dev/null +++ b/src/product/ao_flash_task.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2013 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_FLASH_TASK_H_ +#define _AO_FLASH_TASK_H_ + +void +ao_flash_task(void); + +#endif /* _AO_FLASH_TASK_H_ */ diff --git a/src/stm-bringup/ao.h b/src/stm-bringup/ao.h index 27204fae..2c7d5282 100644 --- a/src/stm-bringup/ao.h +++ b/src/stm-bringup/ao.h @@ -16,3 +16,5 @@   */  #define ao_panic(n)	for(;;); + +#define AO_BOOT_LOADER_BASE               ((uint32_t *) 0x0) diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 3b1b671b..d1f825db 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -17,6 +17,7 @@ INC = \  #  ALTOS_SRC = \  	ao_interrupt.c \ +	ao_boot_chain.c \  	ao_product.c \  	ao_romconfig.c \  	ao_cmd.c \ @@ -46,17 +47,19 @@ IDPRODUCT=0x000a  CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os -PROG=stm-demo +PROG=stm-demo-$(VERSION) +ELF=$(PROG).elf +IHX=$(PROG).ihx  SRC=$(ALTOS_SRC) ao_demo.c  OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(ELF) $(IHX)  LDFLAGS=-L../stm -Wl,-Taltos.ld -$(PROG): Makefile $(OBJ) -	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc +$(ELF): Makefile $(OBJ) +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJ) $(SAT_CLIB) -lgcc  ao_product.h: ao-make-product.5c ../Version  	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 9ee0be03..5677cdf4 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -20,6 +20,7 @@  #include <ao_event.h>  #include <ao_quadrature.h>  #include <ao_button.h> +#include <ao_boot.h>  struct ao_task demo_task; diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 07b4a19d..40e48a36 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -68,6 +68,8 @@  #define HAS_BEEP		0  #define PACKET_HAS_SLAVE	0 +#define AO_BOOT_CHAIN		1 +  #define LOW_LEVEL_DEBUG		1  #define LED_PORT_ENABLE		STM_RCC_AHBENR_GPIOBEN diff --git a/src/stm-flash/Makefile b/src/stm-flash/Makefile new file mode 100644 index 00000000..1ea35581 --- /dev/null +++ b/src/stm-flash/Makefile @@ -0,0 +1,59 @@ +# +# AltOS build +# +# + +include ../stm/Makefile.defs + +INC = \ +	ao.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_pins.h \ +	ao_product.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ +	ao_interrupt.c \ +	ao_boot_chain.c \ +	ao_boot_pin.c \ +	ao_product.c \ +	ao_notask.c \ +	ao_timer.c \ +	ao_usb_stm.c \ +	ao_flash_stm.c + +PRODUCT=AltosFlash-$(VERSION) +PRODUCT_DEF=-DALTOS_FLASH +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os + +PROG=altos-flash-$(VERSION).elf + +SRC=$(ALTOS_SRC) ao_stm_flash.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) + +LDFLAGS=-L../stm -Wl,-Taltos-loader.ld + +$(PROG): Makefile $(OBJ) +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +$(OBJ): $(INC) + +distclean:	clean + +clean: +	rm -f *.o $(PROG) +	rm -f ao_product.h + +install: + +uninstall: diff --git a/src/stm-flash/ao_pins.h b/src/stm-flash/ao_pins.h new file mode 100644 index 00000000..d6c72653 --- /dev/null +++ b/src/stm-flash/ao_pins.h @@ -0,0 +1,79 @@ +/* + * Copyright © 2013 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_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_TASK_QUEUE		0 + +/* Bridge SB17 on the board and use the MCO from the other chip */ +#define AO_HSE		8000000 +#define AO_HSE_BYPASS		1 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL		12 +#define AO_RCC_CFGR_PLLMUL	(STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz */ +#define AO_PLLDIV		3 +#define AO_RCC_CFGR_PLLDIV	(STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHZ (CPU clock) */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at HCLK/1 */ +#define AO_APB1_PRESCALER	1 +#define AO_RCC_CFGR_PPRE1_DIV	STM_RCC_CFGR_PPRE2_DIV_1 + +/* Run APB2 at HCLK/1 */ +#define AO_APB2_PRESCALER      	1 +#define AO_RCC_CFGR_PPRE2_DIV	STM_RCC_CFGR_PPRE2_DIV_1 + +#define HAS_USB			1 +#define USE_USB_STDIO		0 +#define HAS_BEEP		0 +#define HAS_TASK		0 +#define HAS_ECHO		0 +#define HAS_TICK		0 + +#define PACKET_HAS_SLAVE	0 + +#define LED_PORT_ENABLE		STM_RCC_AHBENR_GPIOCEN +#define LED_PORT		(&stm_gpiob) +#define LED_PIN_RED		6 +#define LED_PIN_GREEN		7 +#define AO_LED_RED		(1 << LED_PIN_RED) +#define AO_LED_GREEN		(1 << LED_PIN_GREEN) + +#define LEDS_AVAILABLE		(AO_LED_RED | AO_LED_GREEN) + +#define AO_TICK_TYPE		uint32_t +#define AO_TICK_SIGNED		int32_t + +#define HAS_TASK_INFO		0 +#define HAS_VERSION		0 + +#define AO_BOOT_CHAIN		1 +#define AO_BOOT_PIN		1 + +#define AO_BOOT_APPLICATION_GPIO	stm_gpiod +#define AO_BOOT_APPLICATION_PIN		2 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ diff --git a/src/stm/Makefile-flash.defs b/src/stm/Makefile-flash.defs new file mode 100644 index 00000000..016bb7e7 --- /dev/null +++ b/src/stm/Makefile-flash.defs @@ -0,0 +1,92 @@ +vpath % $(TOPDIR)/stm:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/core:$(TOPDIR)/util:$(TOPDIR) +vpath ao-make-product.5c $(TOPDIR)/util + +.SUFFIXES: .elf .ihx + +.elf.ihx: +	objcopy -O ihex $*.elf $@ + +CC=arm-none-eabi-gcc +SAT=/opt/cortex +SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a +SAT_CFLAGS=-I$(SAT)/include + +ifndef VERSION +include $(TOPDIR)/Version +endif + +AO_CFLAGS=-I. -I$(TOPDIR)/stm -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) +STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) + +LDFLAGS=-L$(TOPDIR)/stm -Wl,-Taltos-loader.ld + +NICKLE=nickle + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf "  $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +.c.o: +	$(call quiet,CC) -c $(CFLAGS) -o $@ $< + +INC = \ +	ao.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_flash_pins.h \ +	ao_flash_stm_pins.h \ +	ao_flash_task.h \ +	ao_pins.h \ +	ao_product.h \ +	Makefile + +# +# Common AltOS sources +# +SRC = \ +	ao_interrupt.c \ +	ao_romconfig.c \ +	ao_boot_chain.c \ +	ao_boot_pin.c \ +	ao_product.c \ +	ao_notask.c \ +	ao_timer.c \ +	ao_usb_stm.c \ +	ao_flash_stm.c \ +	ao_flash_task.c \ +	ao_flash_loader_stm.c + +OBJ=$(SRC:.c=.o) + +PRODUCT=AltosFlash-$(VERSION) +PRODUCT_DEF=-DALTOS_FLASH +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os + +PROGNAME=altos-flash +PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf + +$(PROG): Makefile $(OBJ) altos-loader.ld +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +ao_product.h: ao-make-product.5c $(TOPDIR)/Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +$(OBJ): $(INC) + +all: $(PROG) + +distclean:	clean + +clean: +	rm -f *.o $(PROG) +	rm -f ao_product.h + +install: + +uninstall: diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 1480f0b3..c8bb7d70 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -7,6 +7,11 @@ vpath load_csv.5c ../kalman  vpath matrix.5c ../kalman  vpath ao-make-product.5c ../util +.SUFFIXES: .elf .ihx + +.elf.ihx: +	objcopy -O ihex $*.elf $@ +  CC=arm-none-eabi-gcc  SAT=/opt/cortex  SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a diff --git a/src/stm/altos-loader.ld b/src/stm/altos-loader.ld new file mode 100644 index 00000000..2be964f2 --- /dev/null +++ b/src/stm/altos-loader.ld @@ -0,0 +1,94 @@ +/* + * 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 : ORIGIN = 0x08000000, LENGTH = 4K +	ram : ORIGIN = 0x20000000, LENGTH = 16K +} + +INCLUDE registers.ld + +EXTERN (stm_interrupt_vector) + +SECTIONS { +	/* +	 * Rom contents +	 */ + +	.text : { +		__text_start__ = .; +		*(.interrupt)	/* Interrupt vectors */ + +		. = ORIGIN(rom) + 0x100; + +		ao_romconfig.o(.romconfig*) +		ao_product.o(.romconfig*) +		*(.text)	/* Executable code */ +		*(.ARM.exidx* .gnu.linkonce.armexidx.*) +		*(.rodata*)	/* Constants */ +		__text_end__ = .; +	} > rom + +	/* Boot data which must live at the start of ram so that +	 * the application and bootloader share the same addresses. +	 * This must be all uninitialized data +	 */ +	.boot (NOLOAD) : { +		__boot_start__ = .; +		*(.boot) +		__boot_end__ = .; +	} >ram + +	/* Functions placed in RAM (required for flashing) +	 * +	 * Align to 8 bytes as that's what the ARM likes text +	 * segment alignments to be, and if we don't, then +	 * we end up with a mismatch between the location in +	 * ROM and the desired location in RAM. I don't +	 * entirely understand this, but at least this appears +	 * to work... +	 */ + +	.textram BLOCK(8): { +		__data_start__ = .; +		__text_ram_start__ = .; +		*(.text.ram) +		__text_ram_end = .; +	} >ram AT>rom + +	/* Data -- relocated to RAM, but written to ROM +	 */ +	.data : { +		*(.data)	/* initialized data */ +		__data_end__ = .; +	} >ram AT>rom + + +	.bss : { +		__bss_start__ = .; +		*(.bss) +		*(COMMON) +		__bss_end__ = .; +	} >ram + +	PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); +	PROVIDE(end = .); +} + +ENTRY(start); + + diff --git a/src/stm/altos.ld b/src/stm/altos.ld index d218e992..3106cc3b 100644 --- a/src/stm/altos.ld +++ b/src/stm/altos.ld @@ -16,7 +16,7 @@   */  MEMORY { -	rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K +	rom (rx) : ORIGIN = 0x08001000, LENGTH = 124K  	ram (!w) : ORIGIN = 0x20000000, LENGTH = 15872  	stack (!w) : ORIGIN = 0x20003e00, LENGTH = 512  } @@ -36,9 +36,19 @@ SECTIONS {  		. = ORIGIN(rom) + 0x100; + +		/* Ick. What I want is to specify the +		 * addresses of some global constants so +		 * that I can find them across versions +		 * of the application. I can't figure out +		 * how to make gnu ld do that, so instead +		 * we just load the two files that include +		 * these defines in the right order here and +		 * expect things to 'just work'. Don't change +		 * the contents of those files, ok? +		 */  		ao_romconfig.o(.romconfig*)  		ao_product.o(.romconfig*) -  		*(.text*)	/* Executable code */  		*(.rodata*)	/* Constants */ @@ -46,21 +56,34 @@ SECTIONS {  	.ARM.exidx : {  		*(.ARM.exidx* .gnu.linkonce.armexidx.*) -		__text_end__ = .;  	} > rom +	__text_end__ = .; + +	/* Boot data which must live at the start of ram so that +	 * the application and bootloader share the same addresses. +	 * This must be all uninitialized data +	 */ +	.boot (NOLOAD) : { +		__boot_start__ = .; +		*(.boot) +		. = ALIGN(4); +		__boot_end__ = .; +	} >ram  	/* Data -- relocated to RAM, but written to ROM  	 */ -	.data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { +	.data : {  		__data_start__ = .;  		*(.data)	/* initialized data */ +		. = ALIGN(4);  		__data_end__ = .; -		__bss_start__ = .; -	} >ram +	} >ram AT>rom  	.bss : { +		__bss_start__ = .;  		*(.bss)  		*(COMMON) +		. = ALIGN(4);  		__bss_end__ = .;  	} >ram diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 27a942f2..adc288c3 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -88,6 +88,10 @@ extern const uint32_t ao_radio_cal;   * For now, we're running at a weird frequency   */ +#ifndef AO_HSE +#error High speed frequency undefined +#endif +  #if AO_HSE  #define AO_PLLSRC	AO_HSE  #else @@ -129,5 +133,10 @@ extern const uint32_t	ao_radio_cal;  void  ao_adc_init(); +#define AO_BOOT_APPLICATION_BASE	((uint32_t *) 0x08001000) +#define AO_BOOT_LOADER_BASE		((uint32_t *) 0x0) +#define HAS_BOOT_LOADER			1 +  #endif /* _AO_ARCH_H_ */ + diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index f3d68202..1e78cabc 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -113,6 +113,19 @@ ao_spi_init(void);  			stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN); \  	} while (0) +#define ao_disable_port(port) do {					\ +		if ((port) == &stm_gpioa)				\ +			stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOAEN); \ +		else if ((port) == &stm_gpiob)				\ +			stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOBEN); \ +		else if ((port) == &stm_gpioc)				\ +			stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOCEN); \ +		else if ((port) == &stm_gpiod)				\ +			stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIODEN); \ +		else if ((port) == &stm_gpioe)				\ +			stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOEEN); \ +	} while (0) +  #define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v) @@ -124,9 +137,7 @@ ao_spi_init(void);  		stm_moder_set(port, bit, STM_MODER_OUTPUT);\  	} while (0) -#define ao_enable_input(port,bit,mode) do {				\ -		ao_enable_port(port);					\ -		stm_moder_set(port, bit, STM_MODER_INPUT);		\ +#define ao_gpio_set_mode(port,bit,mode) do {				\  		if (mode == AO_EXTI_MODE_PULL_UP)			\  			stm_pupdr_set(port, bit, STM_PUPDR_PULL_UP);	\  		else if (mode == AO_EXTI_MODE_PULL_DOWN)		\ @@ -134,6 +145,12 @@ ao_spi_init(void);  		else							\  			stm_pupdr_set(port, bit, STM_PUPDR_NONE);	\  	} while (0) +	 +#define ao_enable_input(port,bit,mode) do {				\ +		ao_enable_port(port);					\ +		stm_moder_set(port, bit, STM_MODER_INPUT);		\ +		ao_gpio_set_mode(port, bit, mode);			\ +	} while (0)  #define ao_enable_cs(port,bit) do {				\  		stm_gpio_set((port), bit, 1);			\ @@ -250,6 +267,7 @@ ao_arch_memory_barrier() {  	asm volatile("" ::: "memory");  } +#if HAS_TASK  static inline void  ao_arch_init_stack(struct ao_task *task, void *start)  { @@ -332,6 +350,8 @@ static inline void ao_arch_start_scheduler(void) {  #define ao_arch_isr_stack() +#endif +  #define ao_arch_wait_interrupt() do {			\  		asm(".global ao_idle_loc\n\twfi\nao_idle_loc:");	\  		ao_arch_release_interrupts();				\ diff --git a/src/stm/ao_boot.h b/src/stm/ao_boot.h new file mode 100644 index 00000000..e0ed4de7 --- /dev/null +++ b/src/stm/ao_boot.h @@ -0,0 +1,39 @@ +/* + * Copyright © 2013 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_BOOT_H_ +#define _AO_BOOT_H_ + +void +ao_boot_chain(uint32_t *base); + +void +ao_boot_check_pin(void); + +/* Return true to switch to application (if present) */ +int +ao_boot_check_chain(void); + +void +ao_boot_reboot(uint32_t *base); + +static inline void +ao_boot_loader(void) { +	ao_boot_reboot(AO_BOOT_LOADER_BASE); +} + +#endif /* _AO_BOOT_H_ */ diff --git a/src/stm/ao_boot_chain.c b/src/stm/ao_boot_chain.c new file mode 100644 index 00000000..6a3864a7 --- /dev/null +++ b/src/stm/ao_boot_chain.c @@ -0,0 +1,67 @@ +/* + * Copyright © 2013 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> +#include <ao_boot.h> + +void +ao_boot_chain(uint32_t *base) +{ +	uint32_t	sp; +	uint32_t	pc; + +	sp = base[0]; +	pc = base[1]; +	if (0x08000100 <= pc && pc <= 0x08200000 && (pc & 1) == 1) { +		asm ("mov sp, %0" : : "r" (sp)); +		asm ("mov lr, %0" : : "r" (pc)); +		asm ("bx lr"); +	} +} + +#define AO_BOOT_SIGNAL	0x5a5aa5a5 +#define AO_BOOT_CHECK	0xc3c33c3c + +struct ao_boot { +	uint32_t	*base; +	uint32_t	signal; +	uint32_t	check; +}; + +static struct ao_boot __attribute__ ((section(".boot"))) ao_boot; +	 +int +ao_boot_check_chain(void) +{ +	if (ao_boot.signal == AO_BOOT_SIGNAL && ao_boot.check == AO_BOOT_CHECK) { +		ao_boot.signal = 0; +		ao_boot.check = 0; +		if (ao_boot.base == 0) +			return 0; +		ao_boot_chain(ao_boot.base); +	} +	return 1; +} + +void +ao_boot_reboot(uint32_t *base) +{ +	ao_boot.base = base; +	ao_boot.signal = AO_BOOT_SIGNAL; +	ao_boot.check = AO_BOOT_CHECK; +	ao_arch_reboot(); +} diff --git a/src/stm/ao_boot_pin.c b/src/stm/ao_boot_pin.c new file mode 100644 index 00000000..1000a65a --- /dev/null +++ b/src/stm/ao_boot_pin.c @@ -0,0 +1,46 @@ +/* + * Copyright © 2013 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> +#include <ao_boot.h> +#include <ao_exti.h> + +void +ao_boot_check_pin(void) +{ +	uint16_t v; + +	/* Enable power interface clock */ +	stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); +	 +	/* Enable the input pin */ +	ao_enable_input(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, +			AO_BOOT_APPLICATION_MODE); + +	for (v = 0; v < 100; v++) +		ao_arch_nop(); + +	/* Read the value */ +	v = stm_gpio_get(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN); + +	/* Reset the chip to turn off the port and the power interface clock */ +	ao_gpio_set_mode(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, 0); +	ao_disable_port(&AO_BOOT_APPLICATION_GPIO); +	stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_PWREN); +	if (v == AO_BOOT_APPLICATION_VALUE) +		ao_boot_chain(AO_BOOT_APPLICATION_BASE); +} diff --git a/src/stm/ao_flash.h b/src/stm/ao_flash.h new file mode 100644 index 00000000..09ca5ac1 --- /dev/null +++ b/src/stm/ao_flash.h @@ -0,0 +1,27 @@ +/* + * Copyright © 2013 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_FLASH_STM_H_ +#define _AO_FLASH_STM_H_ + +void +ao_flash_erase_page(uint32_t *page); + +void +ao_flash_page(uint32_t *page, uint32_t *src); + +#endif /* _AO_FLASH_STM_H_ */ diff --git a/src/stm/ao_flash_loader_stm.c b/src/stm/ao_flash_loader_stm.c new file mode 100644 index 00000000..2ab548cf --- /dev/null +++ b/src/stm/ao_flash_loader_stm.c @@ -0,0 +1,32 @@ +/* + * Copyright © 2013 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" +#include <ao_exti.h> +#include <ao_boot.h> +#include <ao_flash_task.h> + +int +main(void) +{ +	ao_clock_init(); + +	ao_usb_init(); + +	ao_flash_task(); +	return 0; +} diff --git a/src/stm/ao_flash_stm.c b/src/stm/ao_flash_stm.c new file mode 100644 index 00000000..d7a85582 --- /dev/null +++ b/src/stm/ao_flash_stm.c @@ -0,0 +1,127 @@ +/* + * Copyright © 2013 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> +#include <ao_flash.h> + +static uint8_t +ao_flash_pecr_is_locked(void) +{ +	return (stm_flash.pecr & (1 << STM_FLASH_PECR_PELOCK)) != 0; +} + +static uint8_t +ao_flash_pgr_is_locked(void) +{ +	return (stm_flash.pecr & (1 << STM_FLASH_PECR_PRGLOCK)) != 0; +} + +static void +ao_flash_pecr_unlock(void) +{ +	if (!ao_flash_pecr_is_locked()) +		return; + +	/* Unlock Data EEPROM and FLASH_PECR register */ +	stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY1; +	stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY2; +	if (ao_flash_pecr_is_locked()) +		ao_panic(AO_PANIC_FLASH); +} + +static void +ao_flash_pgr_unlock(void) +{ +	if (!ao_flash_pgr_is_locked()) +		return; + +	/* Unlock program memory */ +	stm_flash.prgkeyr = STM_FLASH_PRGKEYR_PRGKEY1; +	stm_flash.prgkeyr = STM_FLASH_PRGKEYR_PRGKEY2; +	if (ao_flash_pgr_is_locked()) +		ao_panic(AO_PANIC_FLASH); +} + +static void +ao_flash_lock(void) +{ +	stm_flash.pecr |= (1 << STM_FLASH_PECR_OPTLOCK) | (1 << STM_FLASH_PECR_PRGLOCK) | (1 << STM_FLASH_PECR_PELOCK); +} + +static void +ao_flash_wait_bsy(void) +{ +	while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) +		; +} + +static void __attribute__ ((section(".text.ram"),noinline)) +_ao_flash_erase_page(uint32_t *page) +{ +	stm_flash.pecr |= (1 << STM_FLASH_PECR_ERASE) | (1 << STM_FLASH_PECR_PROG); +	 +	*page = 0x00000000; + +	while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) +		; +} + +void +ao_flash_erase_page(uint32_t *page) +{ +	ao_flash_pecr_unlock(); +	ao_flash_pgr_unlock(); + +	_ao_flash_erase_page(page); + +	ao_flash_lock(); +} + +static void __attribute__ ((section(".text.ram"), noinline)) +_ao_flash_half_page(uint32_t *dst, uint32_t *src) +{ +	uint8_t		i; + +	stm_flash.pecr |= (1 << STM_FLASH_PECR_FPRG); +	stm_flash.pecr |= (1 << STM_FLASH_PECR_PROG); +	 +	while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) +		; + +	for (i = 0; i < 32; i++) { +		*dst++ = *src++; +	} + +	while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) +		; +} + +void +ao_flash_page(uint32_t *page, uint32_t *src) +{ +	uint8_t		h; + +	ao_flash_erase_page(page); +	ao_flash_pecr_unlock(); +	ao_flash_pgr_unlock(); +	for (h = 0; h < 2; h++) { +		_ao_flash_half_page(page, src); +		page += 32; +		src += 32; +	} +	ao_flash_lock(); +} diff --git a/src/stm/ao_flash_stm_pins.h b/src/stm/ao_flash_stm_pins.h new file mode 100644 index 00000000..d157a226 --- /dev/null +++ b/src/stm/ao_flash_stm_pins.h @@ -0,0 +1,43 @@ +/* + * Copyright © 2013 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_FLASH_STM_PINS_H_ +#define _AO_FLASH_STM_PINS_H_ + +#include <ao_flash_pins.h> + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL		12 +#define AO_RCC_CFGR_PLLMUL	(STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz */ +#define AO_PLLDIV		3 +#define AO_RCC_CFGR_PLLDIV	(STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHZ (CPU clock) */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at HCLK/1 */ +#define AO_APB1_PRESCALER	1 +#define AO_RCC_CFGR_PPRE1_DIV	STM_RCC_CFGR_PPRE2_DIV_1 + +/* Run APB2 at HCLK/1 */ +#define AO_APB2_PRESCALER      	1 +#define AO_RCC_CFGR_PPRE2_DIV	STM_RCC_CFGR_PPRE2_DIV_1 + +#endif /* _AO_FLASH_STM_PINS_H_ */ diff --git a/src/stm/ao_interrupt.c b/src/stm/ao_interrupt.c index a423d8b1..969e6a0f 100644 --- a/src/stm/ao_interrupt.c +++ b/src/stm/ao_interrupt.c @@ -18,6 +18,7 @@  #include <ao.h>  #include "stm32l.h"  #include <string.h> +#include <ao_boot.h>  extern void main(void);  extern char __stack__; @@ -36,7 +37,19 @@ void stm_ignore_isr(void)  {  } -void start(void) { +const void *stm_interrupt_vector[]; + +void start(void) +{ +#ifdef AO_BOOT_CHAIN +	if (ao_boot_check_chain()) { +#ifdef AO_BOOT_PIN +		ao_boot_check_pin(); +#endif +	} +#endif +	/* Set interrupt vector table offset */ +	stm_nvic.vto = (uint32_t) &stm_interrupt_vector;  	memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__);  	memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__);  	main(); diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 5976eb3f..daf2f400 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -18,6 +18,11 @@  #include "ao.h"  #include <ao_task.h> +#ifndef HAS_TICK +#define HAS_TICK 1 +#endif + +#if HAS_TICK  volatile AO_TICK_TYPE ao_tick_count;  AO_TICK_TYPE @@ -88,6 +93,8 @@ ao_timer_init(void)  			   (STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 << STM_SYSTICK_CSR_CLKSOURCE));  } +#endif +  void  ao_clock_init(void)  { diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index e484cd22..11dde92e 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -23,6 +23,16 @@  #define USB_DEBUG_DATA	0  #define USB_ECHO	0 +#ifndef USE_USB_STDIO +#define USE_USB_STDIO	1 +#endif + +#if USE_USB_STDIO +#define AO_USB_OUT_SLEEP_ADDR	(&ao_stdin_ready) +#else +#define AO_USB_OUT_SLEEP_ADDR	(&ao_usb_out_avail) +#endif +  #if USB_DEBUG  #define debug(format, args...)	printf(format, ## args);  #else @@ -770,7 +780,7 @@ stm_usb_lp_isr(void)  				_rx_dbg1("RX ISR", epr);  				ao_usb_out_avail = 1;  				_rx_dbg0("out avail set"); -				ao_wakeup(&ao_stdin_ready); +				ao_wakeup(AO_USB_OUT_SLEEP_ADDR);  				_rx_dbg0("stdin awoken");  			}  			break; @@ -936,7 +946,7 @@ ao_usb_getchar(void)  	ao_arch_block_interrupts();  	while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) -		ao_sleep(&ao_stdin_ready); +		ao_sleep(AO_USB_OUT_SLEEP_ADDR);  	ao_arch_release_interrupts();  	return c;  } @@ -1064,8 +1074,10 @@ ao_usb_init(void)  	ao_cmd_register(&ao_usb_cmds[0]);  #endif  #if !USB_ECHO +#if USE_USB_STDIO  	ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush);  #endif +#endif  }  #if TX_DBG || RX_DBG diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 5c0748a6..63bde0f8 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -435,6 +435,9 @@ extern struct stm_flash	stm_flash;  #define STM_FLASH_PEKEYR_PEKEY1	0x89ABCDEF  #define STM_FLASH_PEKEYR_PEKEY2 0x02030405 +#define STM_FLASH_PRGKEYR_PRGKEY1 0x8C9DAEBF +#define STM_FLASH_PRGKEYR_PRGKEY2 0x13141516 +  struct stm_rcc {  	vuint32_t	cr;  	vuint32_t	icscr; diff --git a/src/telegps-v0.1/Makefile b/src/telegps-v0.1/Makefile index aae37660..2c41235b 100644 --- a/src/telegps-v0.1/Makefile +++ b/src/telegps-v0.1/Makefile @@ -33,6 +33,7 @@ INC = \  #STACK_GUARD_DEF=-DHAS_STACK_GUARD=1  ALTOS_SRC = \ +	ao_boot_chain.c \  	ao_interrupt.c \  	ao_product.c \  	ao_romconfig.c \ diff --git a/src/telegps-v0.1/flash-loader/Makefile b/src/telegps-v0.1/flash-loader/Makefile new file mode 100644 index 00000000..efc98d14 --- /dev/null +++ b/src/telegps-v0.1/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telegps-v0.1 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telegps-v0.1/flash-loader/ao_pins.h b/src/telegps-v0.1/flash-loader/ao_pins.h new file mode 100644 index 00000000..564e84de --- /dev/null +++ b/src/telegps-v0.1/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 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_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE		8000000 + +#include <ao_flash_stm_pins.h> + +/* Telemetry TX pin PB6 */ + +#define AO_BOOT_PIN			1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpiob +#define AO_BOOT_APPLICATION_PIN		6 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ diff --git a/src/telelco-v0.1/Makefile b/src/telelco-v0.1/Makefile index a4a83d02..24083308 100644 --- a/src/telelco-v0.1/Makefile +++ b/src/telelco-v0.1/Makefile @@ -30,6 +30,7 @@ INC = \  #PROFILE_DEF=-DAO_PROFILE=1  ALTOS_SRC = \ +	ao_boot_chain.c \  	ao_interrupt.c \  	ao_product.c \  	ao_romconfig.c \ diff --git a/src/telemega-v0.1/Makefile b/src/telemega-v0.1/Makefile index 16393ea0..a72d08f2 100644 --- a/src/telemega-v0.1/Makefile +++ b/src/telemega-v0.1/Makefile @@ -45,6 +45,7 @@ INC = \  #STACK_GUARD_DEF=-DHAS_STACK_GUARD=1  ALTOS_SRC = \ +	ao_boot_chain.c \  	ao_interrupt.c \  	ao_product.c \  	ao_romconfig.c \ diff --git a/src/telemega-v0.1/flash-loader/Makefile b/src/telemega-v0.1/flash-loader/Makefile new file mode 100644 index 00000000..7aa8549f --- /dev/null +++ b/src/telemega-v0.1/flash-loader/Makefile @@ -0,0 +1,7 @@ +# +# AltOS flash loader build +# + +TOPDIR=../.. +HARDWARE=telemega-v0.1 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telemega-v0.1/flash-loader/ao_pins.h b/src/telemega-v0.1/flash-loader/ao_pins.h new file mode 100644 index 00000000..1af92f13 --- /dev/null +++ b/src/telemega-v0.1/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 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_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE		8000000 + +#include <ao_flash_stm_pins.h> + +/* Companion port cs_companion0 PD0 */ + +#define AO_BOOT_PIN		1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpiod +#define AO_BOOT_APPLICATION_PIN		0 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ diff --git a/src/telemega-v0.3/Makefile b/src/telemega-v0.3/Makefile index 42ea53fc..a5fdd86b 100644 --- a/src/telemega-v0.3/Makefile +++ b/src/telemega-v0.3/Makefile @@ -45,6 +45,7 @@ INC = \  #STACK_GUARD_DEF=-DHAS_STACK_GUARD=1  ALTOS_SRC = \ +	ao_boot_chain.c \  	ao_interrupt.c \  	ao_product.c \  	ao_romconfig.c \ diff --git a/src/telemega-v0.3/flash-loader/Makefile b/src/telemega-v0.3/flash-loader/Makefile new file mode 100644 index 00000000..8fda18cd --- /dev/null +++ b/src/telemega-v0.3/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telemega-v0.3 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telemega-v0.3/flash-loader/ao_pins.h b/src/telemega-v0.3/flash-loader/ao_pins.h new file mode 100644 index 00000000..1af92f13 --- /dev/null +++ b/src/telemega-v0.3/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 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_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE		8000000 + +#include <ao_flash_stm_pins.h> + +/* Companion port cs_companion0 PD0 */ + +#define AO_BOOT_PIN		1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpiod +#define AO_BOOT_APPLICATION_PIN		0 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ diff --git a/src/telescience-v0.2/Makefile b/src/telescience-v0.2/Makefile index fbeeb75c..f16ef268 100644 --- a/src/telescience-v0.2/Makefile +++ b/src/telescience-v0.2/Makefile @@ -28,6 +28,7 @@ INC = \  #STACK_GUARD_DEF=-DHAS_STACK_GUARD=1  ALTOS_SRC = \ +	ao_boot_chain.c \  	ao_interrupt.c \  	ao_product.c \  	ao_romconfig.c \ | 
