From b119e19604aa557a40e848c60d98a67b5f259bbd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Oct 2012 22:17:49 -0700 Subject: altos: profiling on STM32L Add sample-based profiling, using a 1kHz timer Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/stm/ao_arch.h') diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 87eda18b..f2de719c 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -143,7 +143,7 @@ extern const uint32_t ao_radio_cal; #define ao_arch_cpu_idle() do { \ - asm("wfi"); \ + asm(".global ao_idle_loc\n\twfi\nao_idle_loc:"); \ } while (0) #define ao_arch_restore_stack() do { \ -- cgit v1.2.3 From e80fa6de4ccc5c4851eab9fb941f9282d2e3eb16 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Oct 2012 22:35:32 -0700 Subject: altos: Replace __critical usage with ao_arch_critical as needed sdcc offers __critical as a machine-independent way to block interrupts, but as gcc doesn't, we need to use a compiler-independent construct instead. ao_arch_critical has been around since the AVR port, but some old __critical usages remained. This fixes a bunch of random hangs when communicating with MM over USB or the radio as the various stdio loops were running without interrupts blocked between the test and the sleep. Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- src/core/ao_ignite.c | 10 ++++++---- src/core/ao_mutex.c | 8 ++++---- src/core/ao_packet.h | 2 +- src/core/ao_panic.c | 3 ++- src/core/ao_stdio.c | 26 ++++++++++++++------------ src/drivers/ao_btm.c | 24 +++++++++++++----------- src/drivers/ao_packet.c | 8 +++++++- src/drivers/ao_packet_master.c | 2 +- src/stm/ao_arch.h | 26 +++++++++++++++++++++++--- src/stm/ao_timer.c | 8 +++++--- src/stm/ao_usb_stm.c | 38 ++++++++++++++++++++++---------------- 12 files changed, 99 insertions(+), 58 deletions(-) (limited to 'src/stm/ao_arch.h') diff --git a/src/core/ao.h b/src/core/ao.h index e559e876..2b375cfd 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -101,7 +101,7 @@ ao_delay(uint16_t ticks); /* Set the ADC interval */ void -ao_timer_set_adc_interval(uint8_t interval) __critical; +ao_timer_set_adc_interval(uint8_t interval); /* Timer interrupt */ void diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c index c7829fc3..693b7c7a 100644 --- a/src/core/ao_ignite.c +++ b/src/core/ao_ignite.c @@ -21,10 +21,12 @@ __xdata struct ao_ignition ao_ignition[2]; void -ao_ignite(enum ao_igniter igniter) __critical +ao_ignite(enum ao_igniter igniter) { + cli(); ao_ignition[igniter].request = 1; ao_wakeup(&ao_ignition); + sei(); } #ifndef AO_SENSE_DROGUE @@ -39,12 +41,12 @@ ao_igniter_status(enum ao_igniter igniter) __pdata int16_t value; __pdata uint8_t request, firing, fired; - __critical { + ao_arch_critical( ao_data_get(&packet); request = ao_ignition[igniter].request; fired = ao_ignition[igniter].fired; firing = ao_ignition[igniter].firing; - } + ); if (firing || (request && !fired)) return ao_igniter_active; @@ -79,7 +81,7 @@ ao_igniter_status(enum ao_igniter igniter) #endif void -ao_igniter_fire(enum ao_igniter igniter) __critical +ao_igniter_fire(enum ao_igniter igniter) { ao_ignition[igniter].firing = 1; switch(ao_config.ignite_mode) { diff --git a/src/core/ao_mutex.c b/src/core/ao_mutex.c index c82a7d57..952ff462 100644 --- a/src/core/ao_mutex.c +++ b/src/core/ao_mutex.c @@ -22,11 +22,11 @@ ao_mutex_get(__xdata uint8_t *mutex) __reentrant { if (*mutex == ao_cur_task->task_id) ao_panic(AO_PANIC_MUTEX); - __critical { + ao_arch_critical( while (*mutex) ao_sleep(mutex); *mutex = ao_cur_task->task_id; - } + ); } void @@ -34,8 +34,8 @@ ao_mutex_put(__xdata uint8_t *mutex) __reentrant { if (*mutex != ao_cur_task->task_id) ao_panic(AO_PANIC_MUTEX); - __critical { + ao_arch_critical( *mutex = 0; ao_wakeup(mutex); - } + ); } diff --git a/src/core/ao_packet.h b/src/core/ao_packet.h index 9058c347..0eafd3b2 100644 --- a/src/core/ao_packet.h +++ b/src/core/ao_packet.h @@ -63,7 +63,7 @@ void ao_packet_putchar(char c) __reentrant; char -ao_packet_pollchar(void) __critical; +ao_packet_pollchar(void); #if PACKET_HAS_MASTER /* ao_packet_master.c */ diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index 3c0b471e..c29cd8fe 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -53,7 +53,8 @@ ao_panic(uint8_t reason) ao_cur_task = NULL; printf ("panic %d\n", reason); #endif - __critical for (;;) { + ao_arch_block_interrupts(); + for (;;) { ao_panic_delay(20); for (n = 0; n < 5; n++) { ao_led_on(AO_LED_PANIC); diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index 656b23c9..8cf66a23 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -96,21 +96,23 @@ flush(void) __xdata uint8_t ao_stdin_ready; char -getchar(void) __reentrant __critical +getchar(void) __reentrant { char c; - int8_t stdio = ao_cur_stdio; + ao_arch_critical( + int8_t stdio = ao_cur_stdio; - for (;;) { - c = ao_stdios[stdio].pollchar(); - if (c != AO_READ_AGAIN) - break; - if (++stdio == ao_num_stdios) - stdio = 0; - if (stdio == ao_cur_stdio) - ao_sleep(&ao_stdin_ready); - } - ao_cur_stdio = stdio; + for (;;) { + c = ao_stdios[stdio].pollchar(); + if (c != AO_READ_AGAIN) + break; + if (++stdio == ao_num_stdios) + stdio = 0; + if (stdio == ao_cur_stdio) + ao_sleep(&ao_stdin_ready); + } + ao_cur_stdio = stdio; + ); return c; } diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index f193ac8e..f3816047 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -312,18 +312,20 @@ __xdata struct ao_task ao_btm_task; #endif void -ao_btm_check_link() __critical +ao_btm_check_link() { - /* Check the pin and configure the interrupt detector to wait for the - * pin to flip the other way - */ - if (BT_LINK_PIN) { - ao_btm_connected = 0; - PICTL |= BT_PICTL_ICON; - } else { - ao_btm_connected = 1; - PICTL &= ~BT_PICTL_ICON; - } + ao_arch_critical( + /* Check the pin and configure the interrupt detector to wait for the + * pin to flip the other way + */ + if (BT_LINK_PIN) { + ao_btm_connected = 0; + PICTL |= BT_PICTL_ICON; + } else { + ao_btm_connected = 1; + PICTL &= ~BT_PICTL_ICON; + } + ); } void diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 2bada949..3c1e7a18 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -155,6 +155,9 @@ ao_packet_flush(void) void ao_packet_putchar(char c) __reentrant { + /* No need to block interrupts, all variables here + * are only manipulated in task context + */ while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) { #if PACKET_HAS_MASTER ao_packet_flush(); @@ -167,8 +170,11 @@ ao_packet_putchar(char c) __reentrant } char -ao_packet_pollchar(void) __critical +ao_packet_pollchar(void) { + /* No need to block interrupts, all variables here + * are only manipulated in task context + */ if (!ao_packet_enable) return AO_READ_AGAIN; diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c index e97a6648..481232df 100644 --- a/src/drivers/ao_packet_master.c +++ b/src/drivers/ao_packet_master.c @@ -18,7 +18,7 @@ #include "ao.h" static char -ao_packet_getchar(void) __critical +ao_packet_getchar(void) { char c; while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) { diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index f2de719c..0c3cfc91 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -43,7 +43,6 @@ #define __xdata #define __code const #define __reentrant -#define __critical #define __interrupt(n) #define __at(n) @@ -83,8 +82,29 @@ extern const uint32_t ao_radio_cal; #define ao_arch_task_members\ uint32_t *sp; /* saved stack pointer */ -#define cli() asm("cpsid i") -#define sei() asm("cpsie i") +#define ao_arch_block_interrupts() asm("cpsid i") +#define ao_arch_release_interrupts() asm("cpsie i") + +#define cli() ao_arch_block_interrupts() +#define sei() ao_arch_release_interrupts() + +static uint32_t +ao_arch_irqsave(void) { + uint32_t primask; + asm("mrs %0,primask" : "=&r" (primask)); + ao_arch_block_interrupts(); + return primask; +} + +static void +ao_arch_irqrestore(uint32_t primask) { + asm("msr primask,%0" : : "r" (primask)); +} + +static void +ao_arch_memory_barrier() { + asm volatile("" ::: "memory"); +} #define ao_arch_init_stack(task, start) do { \ uint32_t *sp = (uint32_t *) (task->stack + AO_STACK_SIZE); \ diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index f3011d3f..d82a803e 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -56,10 +56,12 @@ void stm_tim6_isr(void) #if HAS_ADC void -ao_timer_set_adc_interval(uint8_t interval) __critical +ao_timer_set_adc_interval(uint8_t interval) { - ao_data_interval = interval; - ao_data_count = 0; + ao_arch_critical( + ao_data_interval = interval; + ao_data_count = 0; + ); } #endif diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 4f37a7d9..8e7dacc5 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -799,25 +799,23 @@ ao_usb_in_send(void) ao_usb_tx_count = 0; } -/* Wait for a free IN buffer */ +/* Wait for a free IN buffer. Interrupts are blocked */ static void -ao_usb_in_wait(void) +_ao_usb_in_wait(void) { for (;;) { /* Check if the current buffer is writable */ if (ao_usb_tx_count < AO_USB_IN_SIZE) break; - cli(); /* Wait for an IN buffer to be ready */ while (ao_usb_in_pending) ao_sleep(&ao_usb_in_pending); - sei(); } } void -ao_usb_flush(void) __critical +ao_usb_flush(void) { if (!ao_usb_running) return; @@ -829,24 +827,25 @@ ao_usb_flush(void) __critical * packet was full, in which case we now * want to send an empty packet */ + ao_arch_block_interrupts(); if (!ao_usb_in_flushed) { ao_usb_in_flushed = 1; - cli(); /* Wait for an IN buffer to be ready */ while (ao_usb_in_pending) ao_sleep(&ao_usb_in_pending); - sei(); ao_usb_in_send(); } + ao_arch_release_interrupts(); } void -ao_usb_putchar(char c) __critical __reentrant +ao_usb_putchar(char c) { if (!ao_usb_running) return; - ao_usb_in_wait(); + ao_arch_block_interrupts(); + _ao_usb_in_wait(); ao_usb_in_flushed = 0; ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c; @@ -854,10 +853,11 @@ ao_usb_putchar(char c) __critical __reentrant /* Send the packet when full */ if (ao_usb_tx_count == AO_USB_IN_SIZE) ao_usb_in_send(); + ao_arch_release_interrupts(); } static void -ao_usb_out_recv(void) +_ao_usb_out_recv(void) { ao_usb_out_avail = 0; @@ -888,7 +888,7 @@ _ao_usb_pollchar(void) /* Check to see if a packet has arrived */ if (!ao_usb_out_avail) return AO_READ_AGAIN; - ao_usb_out_recv(); + _ao_usb_out_recv(); } /* Pull a character out of the fifo */ @@ -900,27 +900,28 @@ char ao_usb_pollchar(void) { char c; - cli(); + ao_arch_block_interrupts(); c = _ao_usb_pollchar(); - sei(); + ao_arch_release_interrupts(); return c; } char -ao_usb_getchar(void) __critical +ao_usb_getchar(void) { char c; - cli(); + ao_arch_block_interrupts(); while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) ao_sleep(&ao_stdin_ready); - sei(); + ao_arch_release_interrupts(); return c; } void ao_usb_disable(void) { + ao_arch_block_interrupts(); stm_usb.cntr = (1 << STM_USB_CNTR_FRES); stm_usb.istr = 0; @@ -932,6 +933,7 @@ ao_usb_disable(void) /* Disable the interface */ stm_rcc.apb1enr &+ ~(1 << STM_RCC_APB1ENR_USBEN); + ao_arch_release_interrupts(); } void @@ -954,6 +956,8 @@ ao_usb_enable(void) * pulled low and doesn't work at all */ + ao_arch_block_interrupts(); + /* Route interrupts */ stm_nvic_set_priority(STM_ISR_USB_LP_POS, 3); stm_nvic_set_enable(STM_ISR_USB_LP_POS); @@ -985,6 +989,8 @@ ao_usb_enable(void) (0 << STM_USB_CNTR_PDWN) | (0 << STM_USB_CNTR_FRES)); + ao_arch_release_interrupts(); + for (t = 0; t < 1000; t++) ao_arch_nop(); /* Enable USB pull-up */ -- cgit v1.2.3 From 9b978cd467f9128f3069765dd8fbf8abad3459a4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Oct 2012 13:38:13 -0700 Subject: altos: Clean up stm arch macros a bit. Turn a bunch of the macros into inline functions. Clean up the reboot method to use the stm_scb structure. Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 112 ++---------------------------------------------- src/stm/ao_arch_funcs.h | 99 ++++++++++++++++++++++++++++++++++++++++++ src/stm/registers.ld | 2 + src/stm/stm32l.h | 30 +++++++++++++ 4 files changed, 134 insertions(+), 109 deletions(-) (limited to 'src/stm/ao_arch.h') diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 0c3cfc91..e270199e 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -46,9 +46,9 @@ #define __interrupt(n) #define __at(n) -#define CORTEX_M3_AIRCR ((uint32_t *) 0xe000ed0c) - -#define ao_arch_reboot() (*((uint32_t *) 0xe000ed0c) = 0x05fa0004) +#define ao_arch_reboot() \ + (stm_scb.aircr = ((STM_SCB_AIRCR_VECTKEY_KEY << STM_SCB_AIRCR_VECTKEY) | \ + (1 << STM_SCB_AIRCR_SYSRESETREQ))) #define ao_arch_nop() asm("nop") @@ -77,118 +77,12 @@ extern const uint16_t ao_romconfig_check; extern const uint16_t ao_serial_number; extern const uint32_t ao_radio_cal; -#define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) - #define ao_arch_task_members\ uint32_t *sp; /* saved stack pointer */ #define ao_arch_block_interrupts() asm("cpsid i") #define ao_arch_release_interrupts() asm("cpsie i") -#define cli() ao_arch_block_interrupts() -#define sei() ao_arch_release_interrupts() - -static uint32_t -ao_arch_irqsave(void) { - uint32_t primask; - asm("mrs %0,primask" : "=&r" (primask)); - ao_arch_block_interrupts(); - return primask; -} - -static void -ao_arch_irqrestore(uint32_t primask) { - asm("msr primask,%0" : : "r" (primask)); -} - -static void -ao_arch_memory_barrier() { - asm volatile("" ::: "memory"); -} - -#define ao_arch_init_stack(task, start) do { \ - uint32_t *sp = (uint32_t *) (task->stack + AO_STACK_SIZE); \ - uint32_t a = (uint32_t) start; \ - int i; \ - \ - /* Return address (goes into LR) */ \ - ARM_PUSH32(sp, a); \ - \ - /* Clear register values r0-r12 */ \ - i = 13; \ - while (i--) \ - ARM_PUSH32(sp, 0); \ - \ - /* APSR */ \ - ARM_PUSH32(sp, 0); \ - \ - /* PRIMASK with interrupts enabled */ \ - ARM_PUSH32(sp, 0); \ - \ - task->sp = sp; \ -} while (0); - -#define ao_arch_save_regs() do { \ - /* Save general registers */ \ - asm("push {r0-r12,lr}\n"); \ - \ - /* Save APSR */ \ - asm("mrs r0,apsr"); \ - asm("push {r0}"); \ - \ - /* Save PRIMASK */ \ - asm("mrs r0,primask"); \ - asm("push {r0}"); \ - \ - /* Enable interrupts */ \ - sei(); \ - } while (0) - -#define ao_arch_save_stack() do { \ - uint32_t *sp; \ - asm("mov %0,sp" : "=&r" (sp) ); \ - ao_cur_task->sp = (sp); \ - if ((uint8_t *) sp < &ao_cur_task->stack[0]) \ - ao_panic (AO_PANIC_STACK); \ - } while (0) - -#if 0 -#define ao_arch_isr_stack() do { \ - uint32_t *sp = (uint32_t *) 0x20004000; \ - asm("mov %0,sp" : "=&r" (sp) ); \ - } while (0) -#else -#define ao_arch_isr_stack() -#endif - - -#define ao_arch_cpu_idle() do { \ - asm(".global ao_idle_loc\n\twfi\nao_idle_loc:"); \ - } while (0) - -#define ao_arch_restore_stack() do { \ - uint32_t sp; \ - sp = (uint32_t) ao_cur_task->sp; \ - \ - /* Switch stacks */ \ - asm("mov sp, %0" : : "r" (sp) ); \ - \ - /* Restore PRIMASK */ \ - asm("pop {r0}"); \ - asm("msr primask,r0"); \ - \ - /* Restore APSR */ \ - asm("pop {r0}"); \ - asm("msr apsr,r0"); \ - \ - /* Restore general registers */ \ - asm("pop {r0-r12,lr}\n"); \ - \ - /* Return to calling function */ \ - asm("bx lr"); \ - } while(0) - -#define ao_arch_critical(b) do { cli(); do { b } while (0); sei(); } while (0) /* * For now, we're running at a weird frequency diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index e66d20d7..ca451a53 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -210,4 +210,103 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop); void ao_i2c_init(void); +#define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) + +static inline uint32_t +ao_arch_irqsave(void) { + uint32_t primask; + asm("mrs %0,primask" : "=&r" (primask)); + ao_arch_block_interrupts(); + return primask; +} + +static inline void +ao_arch_irqrestore(uint32_t primask) { + asm("msr primask,%0" : : "r" (primask)); +} + +static inline void +ao_arch_memory_barrier() { + asm volatile("" ::: "memory"); +} + +static inline void +ao_arch_init_stack(struct ao_task *task, void *start) +{ + uint32_t *sp = (uint32_t *) (task->stack + AO_STACK_SIZE); + uint32_t a = (uint32_t) start; + int i; + + /* Return address (goes into LR) */ + ARM_PUSH32(sp, a); + + /* Clear register values r0-r12 */ + i = 13; + while (i--) + ARM_PUSH32(sp, 0); + + /* APSR */ + ARM_PUSH32(sp, 0); + + /* PRIMASK with interrupts enabled */ + ARM_PUSH32(sp, 0); + + task->sp = sp; +} + +static inline void ao_arch_save_regs(void) { + /* Save general registers */ + asm("push {r0-r12,lr}\n"); + + /* Save APSR */ + asm("mrs r0,apsr"); + asm("push {r0}"); + + /* Save PRIMASK */ + asm("mrs r0,primask"); + asm("push {r0}"); +} + +static inline void ao_arch_save_stack(void) { + uint32_t *sp; + asm("mov %0,sp" : "=&r" (sp) ); + ao_cur_task->sp = (sp); + if ((uint8_t *) sp < &ao_cur_task->stack[0]) + ao_panic (AO_PANIC_STACK); +} + +static inline void ao_arch_restore_stack(void) { + uint32_t sp; + sp = (uint32_t) ao_cur_task->sp; + + /* Switch stacks */ + asm("mov sp, %0" : : "r" (sp) ); + + /* Restore PRIMASK */ + asm("pop {r0}"); + asm("msr primask,r0"); + + /* Restore APSR */ + asm("pop {r0}"); + asm("msr apsr,r0"); + + /* Restore general registers */ + asm("pop {r0-r12,lr}\n"); + + /* Return to calling function */ + asm("bx lr"); +} + +#define ao_arch_isr_stack() + +#define ao_arch_cpu_idle() do { \ + asm(".global ao_idle_loc\n\twfi\nao_idle_loc:"); \ + } while (0) + +#define ao_arch_critical(b) do { \ + ao_arch_block_interrupts(); \ + do { b } while (0); \ + ao_arch_release_interrupts(); \ + } while (0) + #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stm/registers.ld b/src/stm/registers.ld index f8b224a2..95a86e35 100644 --- a/src/stm/registers.ld +++ b/src/stm/registers.ld @@ -46,6 +46,8 @@ stm_tim2 = 0x40000000; stm_nvic = 0xe000e100; +stm_scb = 0xe000ed00; + stm_mpu = 0xe000ed90; /* calibration data in system memory */ diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index d953aee4..0dbfae39 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -901,6 +901,36 @@ stm_nvic_get_priority(int irq) { return (stm_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0); } +struct stm_scb { + vuint32_t cpuid; + vuint32_t icsr; + vuint32_t vtor; + vuint32_t aircr; + + vuint32_t scr; + vuint32_t ccr; + vuint32_t shpr1; + vuint32_t shpr2; + + vuint32_t shpr3; + vuint32_t shcrs; + vuint32_t cfsr; + vuint32_t hfsr; + + uint32_t unused_30; + vuint32_t mmfar; + vuint32_t bfar; +}; + +extern struct stm_scb stm_scb; + +#define STM_SCB_AIRCR_VECTKEY 16 +#define STM_SCB_AIRCR_VECTKEY_KEY 0x05fa +#define STM_SCB_AIRCR_PRIGROUP 8 +#define STM_SCB_AIRCR_SYSRESETREQ 2 +#define STM_SCB_AIRCR_VECTCLRACTIVE 1 +#define STM_SCB_AIRCR_VECTRESET 0 + struct stm_mpu { vuint32_t typer; vuint32_t cr; -- cgit v1.2.3 From 0b65402361f36a0c722977bcb63edb26fda0db28 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Nov 2012 16:01:07 -0800 Subject: altos: Make stdio 8-bit clean by making pollchar return int We were stealing one value (0xff) in the return value from pollchar to indicate 'not ready yet'. Instead of doing that, use the integer value -1 and have pollchar return an int instead of a char. That necessitated cleaning a few other bits to make sure that 0xff wouldn't get promoted to -1 on accident. Signed-off-by: Keith Packard --- src/avr/ao_usb_avr.c | 10 +++++----- src/cc1111/ao_serial.c | 8 ++++---- src/cc1111/ao_usb.c | 12 ++++++------ src/core/ao.h | 6 +++--- src/core/ao_packet.h | 2 +- src/core/ao_serial.h | 28 ++++++++++++++++++++++++++-- src/core/ao_stdio.c | 2 +- src/core/ao_usb.h | 2 +- src/drivers/ao_packet.c | 6 +++--- src/stm/ao_arch.h | 36 ------------------------------------ src/stm/ao_arch_funcs.h | 20 ++++++++++++++++++++ src/stm/ao_serial_stm.c | 24 ++++++++++-------------- src/stm/ao_usb_stm.c | 10 +++++----- 13 files changed, 85 insertions(+), 81 deletions(-) (limited to 'src/stm/ao_arch.h') diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c index 9ba407af..2ef546c9 100644 --- a/src/avr/ao_usb_avr.c +++ b/src/avr/ao_usb_avr.c @@ -480,10 +480,10 @@ ao_usb_putchar(char c) __critical __reentrant ao_usb_in_flushed = 0; } -static char +static int _ao_usb_pollchar(void) { - char c; + uint8_t c; uint8_t intx; if (!ao_usb_running) @@ -517,10 +517,10 @@ _ao_usb_pollchar(void) return c; } -char +int ao_usb_pollchar(void) { - char c; + int c; cli(); c = _ao_usb_pollchar(); sei(); @@ -530,7 +530,7 @@ ao_usb_pollchar(void) char ao_usb_getchar(void) __critical { - char c; + int c; cli(); while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c index 48383802..2a93bf52 100644 --- a/src/cc1111/ao_serial.c +++ b/src/cc1111/ao_serial.c @@ -85,10 +85,10 @@ ao_serial0_getchar(void) __critical } #if USE_SERIAL_0_STDIN -char +int ao_serial0_pollchar(void) __critical { - char c; + uint8_t c; if (ao_fifo_empty(ao_serial0_rx_fifo)) return AO_READ_AGAIN; ao_fifo_remove(ao_serial0_rx_fifo,c); @@ -173,10 +173,10 @@ ao_serial1_getchar(void) __critical } #if USE_SERIAL_1_STDIN -char +int ao_serial1_pollchar(void) __critical { - char c; + uint8_t c; if (ao_fifo_empty(ao_serial1_rx_fifo)) return AO_READ_AGAIN; ao_fifo_remove(ao_serial1_rx_fifo,c); diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c index ce26e808..81e9074e 100644 --- a/src/cc1111/ao_usb.c +++ b/src/cc1111/ao_usb.c @@ -382,19 +382,19 @@ ao_usb_putchar(char c) __critical __reentrant ao_usb_in_send(); } -char +int ao_usb_pollchar(void) __critical { - char c; + uint8_t c; if (ao_usb_out_bytes == 0) { USBINDEX = AO_USB_OUT_EP; if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0) - return AO_READ_AGAIN; + return -1; ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL; if (ao_usb_out_bytes == 0) { USBINDEX = AO_USB_OUT_EP; USBCSOL &= ~USBCSOL_OUTPKT_RDY; - return AO_READ_AGAIN; + return -1; } } --ao_usb_out_bytes; @@ -409,9 +409,9 @@ ao_usb_pollchar(void) __critical char ao_usb_getchar(void) __critical { - char c; + int c; - while ((c = ao_usb_pollchar()) == AO_READ_AGAIN) + while ((c = ao_usb_pollchar()) == -1) ao_sleep(&ao_stdin_ready); return c; } diff --git a/src/core/ao.h b/src/core/ao.h index 1aff3d49..54018b37 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -599,10 +599,10 @@ ao_monitor_init(void) __reentrant; * ao_stdio.c */ -#define AO_READ_AGAIN ((char) -1) +#define AO_READ_AGAIN (-1) struct ao_stdio { - char (*pollchar)(void); + int (*pollchar)(void); void (*putchar)(char c) __reentrant; void (*flush)(void); uint8_t echo; @@ -621,7 +621,7 @@ uint8_t ao_echo(void); int8_t -ao_add_stdio(char (*pollchar)(void), +ao_add_stdio(int (*pollchar)(void), void (*putchar)(char) __reentrant, void (*flush)(void)) __reentrant; diff --git a/src/core/ao_packet.h b/src/core/ao_packet.h index 0eafd3b2..08b184d6 100644 --- a/src/core/ao_packet.h +++ b/src/core/ao_packet.h @@ -62,7 +62,7 @@ ao_packet_flush(void); void ao_packet_putchar(char c) __reentrant; -char +int ao_packet_pollchar(void); #if PACKET_HAS_MASTER diff --git a/src/core/ao_serial.h b/src/core/ao_serial.h index 53aa8a89..a799bf2c 100644 --- a/src/core/ao_serial.h +++ b/src/core/ao_serial.h @@ -22,6 +22,7 @@ #define AO_SERIAL_SPEED_9600 1 #define AO_SERIAL_SPEED_19200 2 #define AO_SERIAL_SPEED_57600 3 +#define AO_SERIAL_SPEED_115200 4 #if HAS_SERIAL_0 extern volatile __xdata struct ao_fifo ao_serial0_rx_fifo; @@ -30,6 +31,9 @@ extern volatile __xdata struct ao_fifo ao_serial0_tx_fifo; char ao_serial0_getchar(void); +int +ao_serial0_pollchar(void); + void ao_serial0_putchar(char c); @@ -47,7 +51,7 @@ extern volatile __xdata struct ao_fifo ao_serial1_tx_fifo; char ao_serial1_getchar(void); -char +int ao_serial1_pollchar(void); void @@ -67,7 +71,7 @@ extern volatile __xdata struct ao_fifo ao_serial2_tx_fifo; char ao_serial2_getchar(void); -char +int ao_serial2_pollchar(void); void @@ -80,6 +84,26 @@ void ao_serial2_set_speed(uint8_t speed); #endif +#if HAS_SERIAL_3 +extern volatile __xdata struct ao_fifo ao_serial3_rx_fifo; +extern volatile __xdata struct ao_fifo ao_serial3_tx_fifo; + +char +ao_serial3_getchar(void); + +int +ao_serial3_pollchar(void); + +void +ao_serial3_putchar(char c); + +void +ao_serial3_drain(void); + +void +ao_serial3_set_speed(uint8_t speed); +#endif + void ao_serial_init(void); diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index 8cf66a23..4a832487 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -123,7 +123,7 @@ ao_echo(void) } int8_t -ao_add_stdio(char (*pollchar)(void), +ao_add_stdio(int (*pollchar)(void), void (*putchar)(char), void (*flush)(void)) __reentrant { diff --git a/src/core/ao_usb.h b/src/core/ao_usb.h index e051db93..4476ee6b 100644 --- a/src/core/ao_usb.h +++ b/src/core/ao_usb.h @@ -33,7 +33,7 @@ ao_usb_getchar(void); /* Poll for a charcter on the USB input queue. * returns AO_READ_AGAIN if none are available */ -char +int ao_usb_pollchar(void); /* Flush the USB output queue */ diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 3c1e7a18..91319923 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -21,8 +21,8 @@ __xdata struct ao_packet_recv ao_rx_packet; __xdata struct ao_packet ao_tx_packet; __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; -static __xdata char tx_data[AO_PACKET_MAX]; -static __xdata char rx_data[AO_PACKET_MAX]; +static __xdata uint8_t tx_data[AO_PACKET_MAX]; +static __xdata uint8_t rx_data[AO_PACKET_MAX]; static __pdata uint8_t rx_seq; __xdata struct ao_task ao_packet_task; @@ -169,7 +169,7 @@ ao_packet_putchar(char c) __reentrant tx_data[ao_packet_tx_used++] = c; } -char +int ao_packet_pollchar(void) { /* No need to block interrupts, all variables here diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index e270199e..007f7e2e 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -123,42 +123,6 @@ void ao_lcd_font_init(void); void ao_lcd_font_string(char *s); -char -ao_serial1_getchar(void); - -void -ao_serial1_putchar(char c); - -char -ao_serial1_pollchar(void); - -void -ao_serial1_set_speed(uint8_t speed); - -char -ao_serial2_getchar(void); - -void -ao_serial2_putchar(char c); - -char -ao_serial2_pollchar(void); - -void -ao_serial2_set_speed(uint8_t speed); - -char -ao_serial3_getchar(void); - -void -ao_serial3_putchar(char c); - -char -ao_serial3_pollchar(void); - -void -ao_serial3_set_speed(uint8_t speed); - extern const uint32_t ao_radio_cal; void diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index d6ab1465..87bbe73e 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -210,6 +210,26 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop); void ao_i2c_init(void); +/* ao_serial_stm.c */ +struct ao_stm_usart { + struct ao_fifo rx_fifo; + struct ao_fifo tx_fifo; + struct stm_usart *reg; + uint8_t tx_started; +}; + +#if HAS_SERIAL_1 +extern struct ao_stm_usart ao_stm_usart1; +#endif + +#if HAS_SERIAL_2 +extern struct ao_stm_usart ao_stm_usart2; +#endif + +#if HAS_SERIAL_3 +extern struct ao_stm_usart ao_stm_usart3; +#endif + #define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) static inline uint32_t diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 00409f4a..94138edc 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -17,13 +17,6 @@ #include -struct ao_stm_usart { - struct ao_fifo rx_fifo; - struct ao_fifo tx_fifo; - struct stm_usart *reg; - uint8_t tx_started; -}; - void ao_debug_out(char c) { @@ -78,16 +71,19 @@ ao_usart_getchar(struct ao_stm_usart *usart) return c; } -char +int ao_usart_pollchar(struct ao_stm_usart *usart) { - char c; + int c; ao_arch_block_interrupts(); if (ao_fifo_empty(usart->rx_fifo)) c = AO_READ_AGAIN; - else - ao_fifo_remove(usart->rx_fifo,c); + else { + uint8_t u; + ao_fifo_remove(usart->rx_fifo,u); + c = u; + } ao_arch_release_interrupts(); return c; } @@ -201,7 +197,7 @@ ao_serial1_putchar(char c) ao_usart_putchar(&ao_stm_usart1, c); } -char +int ao_serial1_pollchar(void) { return ao_usart_pollchar(&ao_stm_usart1); @@ -232,7 +228,7 @@ ao_serial2_putchar(char c) ao_usart_putchar(&ao_stm_usart2, c); } -char +int ao_serial2_pollchar(void) { return ao_usart_pollchar(&ao_stm_usart2); @@ -263,7 +259,7 @@ ao_serial3_putchar(char c) ao_usart_putchar(&ao_stm_usart3, c); } -char +int ao_serial3_pollchar(void) { return ao_usart_pollchar(&ao_stm_usart3); diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index d93a0c17..9379e5cd 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -873,10 +873,10 @@ _ao_usb_out_recv(void) ao_usb_set_stat_rx(AO_USB_OUT_EPR, STM_USB_EPR_STAT_RX_VALID); } -static char +static int _ao_usb_pollchar(void) { - char c; + uint8_t c; if (!ao_usb_running) return AO_READ_AGAIN; @@ -896,10 +896,10 @@ _ao_usb_pollchar(void) return c; } -char +int ao_usb_pollchar(void) { - char c; + int c; ao_arch_block_interrupts(); c = _ao_usb_pollchar(); ao_arch_release_interrupts(); @@ -909,7 +909,7 @@ ao_usb_pollchar(void) char ao_usb_getchar(void) { - char c; + int c; ao_arch_block_interrupts(); while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) -- cgit v1.2.3 From 091582c446319fe4a79154153ece5372b2faec83 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 1 May 2013 08:58:17 -0700 Subject: altos: Use SYSTICK on STM32L It's probably more power efficient than using one of the timers, and it's certainly easier to configure. Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 1 + src/stm/ao_timer.c | 40 +++++++++------------------------------- src/stm/registers.ld | 2 ++ src/stm/stm32l.h | 18 ++++++++++++++++++ 4 files changed, 30 insertions(+), 31 deletions(-) (limited to 'src/stm/ao_arch.h') diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 007f7e2e..27a942f2 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -99,6 +99,7 @@ extern const uint32_t ao_radio_cal; #define AO_HCLK (AO_SYSCLK / AO_AHB_PRESCALER) #define AO_PCLK1 (AO_HCLK / AO_APB1_PRESCALER) #define AO_PCLK2 (AO_HCLK / AO_APB2_PRESCALER) +#define AO_SYSTICK (AO_HCLK / 8) #if AO_APB1_PRESCALER == 1 #define AO_TIM23467_CLK AO_PCLK1 diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 8b7c2327..5976eb3f 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -31,14 +31,9 @@ volatile __data uint8_t ao_data_interval = 1; volatile __data uint8_t ao_data_count; #endif -void -ao_debug_out(char c); - - -void stm_tim6_isr(void) +void stm_systick_isr(void) { - if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) { - stm_tim6.sr = 0; + if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) { ++ao_tick_count; #if HAS_TASK_QUEUE if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0) @@ -81,33 +76,16 @@ ao_timer_set_adc_interval(uint8_t interval) #define TIMER_10kHz ((AO_PCLK1 * TIMER_23467_SCALER) / 10000) +#define SYSTICK_RELOAD (AO_SYSTICK / 100 - 1) + void ao_timer_init(void) { - stm_nvic_set_enable(STM_ISR_TIM6_POS); - stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY); - - /* Turn on timer 6 */ - stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); - - stm_tim6.psc = TIMER_10kHz; - stm_tim6.arr = 99; - stm_tim6.cnt = 0; - - /* Enable update interrupt */ - stm_tim6.dier = (1 << STM_TIM67_DIER_UIE); - - /* Poke timer to reload values */ - stm_tim6.egr |= (1 << STM_TIM67_EGR_UG); - - stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS); - - /* And turn it on */ - stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | - (0 << STM_TIM67_CR1_OPM) | - (1 << STM_TIM67_CR1_URS) | - (0 << STM_TIM67_CR1_UDIS) | - (1 << STM_TIM67_CR1_CEN)); + stm_systick.rvr = SYSTICK_RELOAD; + stm_systick.cvr = 0; + stm_systick.csr = ((1 << STM_SYSTICK_CSR_ENABLE) | + (1 << STM_SYSTICK_CSR_TICKINT) | + (STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 << STM_SYSTICK_CSR_CLKSOURCE)); } void diff --git a/src/stm/registers.ld b/src/stm/registers.ld index 95a86e35..8318c75a 100644 --- a/src/stm/registers.ld +++ b/src/stm/registers.ld @@ -44,6 +44,8 @@ stm_tim4 = 0x40000800; stm_tim3 = 0x40000400; stm_tim2 = 0x40000000; +stm_systick = 0xe000e010; + stm_nvic = 0xe000e100; stm_scb = 0xe000ed00; diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 1d636037..5c0748a6 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -811,6 +811,24 @@ extern struct stm_lcd stm_lcd; #define STM_LCD_CLR_UDDC (3) #define STM_LCD_CLR_SOFC (1) +/* The SYSTICK starts at 0xe000e010 */ + +struct stm_systick { + vuint32_t csr; + vuint32_t rvr; + vuint32_t cvr; + vuint32_t calib; +}; + +extern struct stm_systick stm_systick; + +#define STM_SYSTICK_CSR_ENABLE 0 +#define STM_SYSTICK_CSR_TICKINT 1 +#define STM_SYSTICK_CSR_CLKSOURCE 2 +#define STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 0 +#define STM_SYSTICK_CSR_CLKSOURCE_HCLK 1 +#define STM_SYSTICK_CSR_COUNTFLAG 16 + /* The NVIC starts at 0xe000e100, so add that to the offsets to find the absolute address */ struct stm_nvic { -- cgit v1.2.3 From dfc268e0021e1cd3045f73339a749d292a6a6300 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Apr 2013 20:35:57 -0500 Subject: altos: Use flash loader on all STM products Includes the boot chain stuff Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 15 +++++++ src/megadongle-v0.1/Makefile | 1 + src/stm-demo/Makefile | 2 +- src/stm-demo/ao_demo.c | 8 ---- src/stm-flash/ao_pins.h | 1 - src/stm/altos-application.ld | 95 ------------------------------------------- src/stm/altos.ld | 35 +++++++++++++--- src/stm/ao_arch.h | 5 +++ src/stm/ao_boot.h | 5 +++ src/telegps-v0.1/Makefile | 1 + src/telelco-v0.1/Makefile | 1 + src/telemega-v0.1/Makefile | 1 + src/telescience-v0.2/Makefile | 1 + 13 files changed, 60 insertions(+), 111 deletions(-) delete mode 100644 src/stm/altos-application.ld (limited to 'src/stm/ao_arch.h') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 7da2384f..188b8bb4 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -385,6 +385,18 @@ ao_cmd(void) } } +#if HAS_BOOT_LOADER + +#include + +static void +ao_loader(void) +{ + flush(); + ao_boot_loader(); +} +#endif + __xdata struct ao_task ao_cmd_task; __code struct ao_cmds ao_base_cmds[] = { @@ -396,6 +408,9 @@ __code struct ao_cmds ao_base_cmds[] = { { 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/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/stm-demo/Makefile b/src/stm-demo/Makefile index e84a7675..d1f825db 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -56,7 +56,7 @@ OBJ=$(SRC:.c=.o) all: $(ELF) $(IHX) -LDFLAGS=-L../stm -Wl,-Taltos-application.ld +LDFLAGS=-L../stm -Wl,-Taltos.ld $(ELF): Makefile $(OBJ) $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJ) $(SAT_CLIB) -lgcc diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index ec572fdc..5677cdf4 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -169,13 +169,6 @@ ao_event(void) } -static void -ao_boot_loader(void) -{ - flush(); - ao_boot_reboot((uint32_t *) 0); -} - __code struct ao_cmds ao_demo_cmds[] = { { ao_dma_test, "D\0DMA test" }, { ao_spi_write, "W\0SPI write" }, @@ -183,7 +176,6 @@ __code struct ao_cmds ao_demo_cmds[] = { { ao_i2c_write, "i\0I2C write" }, { ao_temp, "t\0Show temp" }, { ao_event, "e\0Monitor event queue" }, - { ao_boot_loader, "L\0Reboot to boot loader" }, { 0, NULL } }; diff --git a/src/stm-flash/ao_pins.h b/src/stm-flash/ao_pins.h index 1c00675b..8fb56f7b 100644 --- a/src/stm-flash/ao_pins.h +++ b/src/stm-flash/ao_pins.h @@ -75,6 +75,5 @@ #define AO_BOOT_APPLICATION_PIN 0 #define AO_BOOT_APPLICATION_VALUE 1 #define AO_BOOT_APPLICATION_MODE 0 -#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x1000) #endif /* _AO_PINS_H_ */ diff --git a/src/stm/altos-application.ld b/src/stm/altos-application.ld deleted file mode 100644 index 6affc376..00000000 --- a/src/stm/altos-application.ld +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -MEMORY { - rom (rx) : ORIGIN = 0x08001000, LENGTH = 124K - ram (!w) : ORIGIN = 0x20000000, LENGTH = 16K -} - -INCLUDE registers.ld - -EXTERN (stm_interrupt_vector) - -SECTIONS { - /* - * Rom contents - */ - - .text ORIGIN(rom) : { - __text_start__ = .; - *(.interrupt) /* Interrupt vectors */ - - . = 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 */ - - } > rom - - .ARM.exidx : { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - } > 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 : { - __data_start__ = .; - *(.data) /* initialized data */ - . = ALIGN(4); - __data_end__ = .; - } >ram AT>rom - - .bss : { - __bss_start__ = .; - *(.bss) - *(COMMON) - . = ALIGN(4); - __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..cc83eac2 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -129,5 +129,10 @@ extern const uint32_t ao_radio_cal; void ao_adc_init(); +#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x1000) +#define AO_BOOT_LOADER_BASE ((uint32_t *) 0x0) +#define HAS_BOOT_LOADER 1 + #endif /* _AO_ARCH_H_ */ + diff --git a/src/stm/ao_boot.h b/src/stm/ao_boot.h index 3e8c50ba..862e8755 100644 --- a/src/stm/ao_boot.h +++ b/src/stm/ao_boot.h @@ -30,4 +30,9 @@ 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/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/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/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 \ -- cgit v1.2.3 From afad5ae893a48785f3b50ff4125dc78648343a2d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Apr 2013 20:08:35 -0600 Subject: altos/stm-flash: Check target flash address against AO_BOOT_APPLICATION_BASE Allows that value to change Signed-off-by: Keith Packard --- src/stm-flash/ao_stm_flash.c | 2 +- src/stm/ao_arch.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/stm/ao_arch.h') diff --git a/src/stm-flash/ao_stm_flash.c b/src/stm-flash/ao_stm_flash.c index f0abe7fb..df06bb09 100644 --- a/src/stm-flash/ao_stm_flash.c +++ b/src/stm-flash/ao_stm_flash.c @@ -86,7 +86,7 @@ ao_block_write(void) } u; uint16_t i; - if (addr < 0x08002000 || 0x08200000 <= addr) { + if (addr < (uint32_t) AO_BOOT_APPLICATION_BASE) { ao_put_string("Invalid address\n"); return; } diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index cc83eac2..757b5251 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -129,7 +129,7 @@ extern const uint32_t ao_radio_cal; void ao_adc_init(); -#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x1000) +#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x08001000) #define AO_BOOT_LOADER_BASE ((uint32_t *) 0x0) #define HAS_BOOT_LOADER 1 -- cgit v1.2.3 From 4a90eec4b8ee4a35711aa74c13b3f30d12c0fe08 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Apr 2013 15:33:04 -0700 Subject: altos/stm: Create per-product flash loaders Split the flash loader prototype into pieces so that each product can build a custom flash loader with very little code. Signed-off-by: Keith Packard --- src/Makefile | 7 +- src/megadongle-v0.1/flash-loader/Makefile | 7 ++ src/megadongle-v0.1/flash-loader/ao_pins.h | 34 +++++++ src/product/ao_flash_pins.h | 40 ++++++++ src/product/ao_flash_task.c | 137 ++++++++++++++++++++++++++ src/product/ao_flash_task.h | 24 +++++ src/stm-flash/ao_stm_flash.c | 152 ----------------------------- src/stm/Makefile-flash.defs | 92 +++++++++++++++++ src/stm/altos-loader.ld | 31 +++--- src/stm/ao_arch.h | 4 + src/stm/ao_flash.h | 27 +++++ src/stm/ao_flash_loader_stm.c | 32 ++++++ src/stm/ao_flash_stm.c | 2 +- src/stm/ao_flash_stm.h | 27 ----- src/stm/ao_flash_stm_pins.h | 43 ++++++++ src/telegps-v0.1/flash-loader/Makefile | 8 ++ src/telegps-v0.1/flash-loader/ao_pins.h | 34 +++++++ src/telemega-v0.1/flash-loader/Makefile | 7 ++ src/telemega-v0.1/flash-loader/ao_pins.h | 34 +++++++ src/telemega-v0.3/flash-loader/Makefile | 8 ++ src/telemega-v0.3/flash-loader/ao_pins.h | 34 +++++++ 21 files changed, 590 insertions(+), 194 deletions(-) create mode 100644 src/megadongle-v0.1/flash-loader/Makefile create mode 100644 src/megadongle-v0.1/flash-loader/ao_pins.h create mode 100644 src/product/ao_flash_pins.h create mode 100644 src/product/ao_flash_task.c create mode 100644 src/product/ao_flash_task.h delete mode 100644 src/stm-flash/ao_stm_flash.c create mode 100644 src/stm/Makefile-flash.defs create mode 100644 src/stm/ao_flash.h create mode 100644 src/stm/ao_flash_loader_stm.c delete mode 100644 src/stm/ao_flash_stm.h create mode 100644 src/stm/ao_flash_stm_pins.h create mode 100644 src/telegps-v0.1/flash-loader/Makefile create mode 100644 src/telegps-v0.1/flash-loader/ao_pins.h create mode 100644 src/telemega-v0.1/flash-loader/Makefile create mode 100644 src/telemega-v0.1/flash-loader/ao_pins.h create mode 100644 src/telemega-v0.3/flash-loader/Makefile create mode 100644 src/telemega-v0.3/flash-loader/ao_pins.h (limited to 'src/stm/ao_arch.h') 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/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 + * + * 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 + +/* 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 + * + * 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/product/ao_flash_task.c b/src/product/ao_flash_task.c new file mode 100644 index 00000000..fdc4d0aa --- /dev/null +++ b/src/product/ao_flash_task.c @@ -0,0 +1,137 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include +#include +#include +#include + +void +ao_panic(uint8_t reason) +{ +} + +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_get_hex32(void) +{ + int8_t n; + uint32_t v = 0; + + for (;;) { + n = ao_usb_getchar(); + if (n != ' ') + break; + } + for(;;) { + 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; + n = ao_usb_getchar(); + } + return v; +} + +static void +ao_block_erase(void) +{ + uint32_t addr = ao_get_hex32(); + uint32_t *p = (uint32_t *) addr; + + ao_flash_erase_page(p); +} + +static void +ao_block_write(void) +{ + uint32_t addr = ao_get_hex32(); + uint32_t *p = (uint32_t *) addr; + union { + uint8_t data8[256]; + uint32_t data32[64]; + } u; + uint16_t i; + + if (addr < (uint32_t) AO_BOOT_APPLICATION_BASE) { + ao_put_string("Invalid address\n"); + return; + } + for (i = 0; i < 256; i++) + u.data8[i] = ao_usb_getchar(); + ao_flash_page(p, u.data32); +} + +static void +ao_block_read(void) +{ + 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++; + ao_usb_putchar(c); + } +} + +static void +ao_show_version(void) +{ + 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"); +} + +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 + * + * 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-flash/ao_stm_flash.c b/src/stm-flash/ao_stm_flash.c deleted file mode 100644 index f8580735..00000000 --- a/src/stm-flash/ao_stm_flash.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include -#include -#include - -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); - } -} - -void -ao_application(void) -{ - ao_boot_reboot(AO_BOOT_APPLICATION_BASE); -} - -static uint32_t -ao_get_hex32(void) -{ - int8_t n; - uint32_t v = 0; - - for (;;) { - n = ao_usb_getchar(); - if (n != ' ') - break; - } - for(;;) { - 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; - n = ao_usb_getchar(); - } - return v; -} - -void -ao_block_erase(void) -{ - uint32_t addr = ao_get_hex32(); - uint32_t *p = (uint32_t *) addr; - - ao_flash_erase_page(p); -} - -void -ao_block_write(void) -{ - uint32_t addr = ao_get_hex32(); - uint32_t *p = (uint32_t *) addr; - union { - uint8_t data8[256]; - uint32_t data32[64]; - } u; - uint16_t i; - - if (addr < (uint32_t) AO_BOOT_APPLICATION_BASE) { - ao_put_string("Invalid address\n"); - return; - } - for (i = 0; i < 256; i++) - u.data8[i] = ao_usb_getchar(); - ao_flash_page(p, u.data32); -} - -void -ao_block_read(void) -{ - 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++; - ao_usb_putchar(c); - } -} - -static void -ao_show_version(void) -{ - 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"); -} - -static 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; - } - } -} - - -int -main(void) -{ - ao_clock_init(); - -// ao_timer_init(); -// ao_dma_init(); -// ao_exti_init(); - ao_usb_init(); - - ao_flash_task(); - return 0; -} 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/altos-loader.ld b/src/stm/altos-loader.ld index 5e10e5ba..2be964f2 100644 --- a/src/stm/altos-loader.ld +++ b/src/stm/altos-loader.ld @@ -32,19 +32,16 @@ SECTIONS { .text : { __text_start__ = .; *(.interrupt) /* Interrupt vectors */ - *(.romconfig*) - *(.text) /* Executable code */ - . = ALIGN(4); - *(.rodata*) /* Constants */ - . = ALIGN(4); - } > rom - .ARM.exidx : { - . = ALIGN(4); + . = ORIGIN(rom) + 0x100; + + ao_romconfig.o(.romconfig*) + ao_product.o(.romconfig*) + *(.text) /* Executable code */ *(.ARM.exidx* .gnu.linkonce.armexidx.*) - . = ALIGN(4); + *(.rodata*) /* Constants */ + __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. @@ -53,12 +50,20 @@ SECTIONS { .boot (NOLOAD) : { __boot_start__ = .; *(.boot) - . = ALIGN(4); __boot_end__ = .; } >ram - /* Functions placed in RAM (required for flashing) */ - .textram : { + /* 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) diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 757b5251..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 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 + * + * 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 + * + * 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 +#include +#include + +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 index b4d47024..d7a85582 100644 --- a/src/stm/ao_flash_stm.c +++ b/src/stm/ao_flash_stm.c @@ -16,7 +16,7 @@ */ #include -#include +#include static uint8_t ao_flash_pecr_is_locked(void) diff --git a/src/stm/ao_flash_stm.h b/src/stm/ao_flash_stm.h deleted file mode 100644 index 09ca5ac1..00000000 --- a/src/stm/ao_flash_stm.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_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_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 + * + * 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 + +/* 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/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 + * + * 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 + +/* 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/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 + * + * 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 + +/* 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/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 + * + * 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 + +/* 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_ */ -- cgit v1.2.3