From: Keith Packard Date: Fri, 26 Oct 2012 21:08:32 +0000 (-0700) Subject: Merge remote-tracking branch 'mjb/altosdroid' X-Git-Tag: 1.1.9.2~14 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=a46c9398a5f02ff4b52b7a4309a51498560cadb5;hp=56023cf5da9deede9fe627fe327783eceecf08f7 Merge remote-tracking branch 'mjb/altosdroid' --- diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index c82612a8..d626e830 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -112,7 +112,6 @@ extern uint8_t ao_cpu_sleep_disable; asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5"); \ asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0"); \ asm("in r0, __SREG__" "\n\t" "push r0"); \ - sei(); \ } while (0) #define ao_arch_save_stack() do { \ @@ -124,16 +123,28 @@ extern uint8_t ao_cpu_sleep_disable; #define ao_arch_isr_stack() /* nothing */ -#define ao_arch_cpu_idle() do { \ - if (!ao_cpu_sleep_disable) \ +/* Idle the CPU (if possible) waiting for an interrupt. Enabling + * interrupts and sleeping the CPU must be adjacent to eliminate race + * conditions. In all cases, we execute a single nop with interrupts + * enabled + */ +#define ao_arch_wait_interrupt() do { \ + if (!ao_cpu_sleep_disable) { \ + sleep_enable(); \ + sei(); \ sleep_cpu(); \ + sleep_disable(); \ + } else { \ + sei(); \ + } \ + ao_arch_nop(); \ + cli(); \ } while (0) #define ao_arch_restore_stack() do { \ uint8_t sp_l, sp_h; \ sp_l = (uint16_t) ao_cur_task->sp; \ sp_h = ((uint16_t) ao_cur_task->sp) >> 8; \ - cli(); \ asm("out __SP_H__,%0" : : "r" (sp_h) ); \ asm("out __SP_L__,%0" : : "r" (sp_l) ); \ asm("pop r0" "\n\t" \ diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index f2442eb6..9097557f 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -112,9 +112,7 @@ extern AO_ROMCONFIG_SYMBOL(0x00a6) uint32_t ao_radio_cal; /* Push ACC first, as when restoring the context it must be restored \ * last (it is used to set the IE register). */ \ push ACC \ - /* Store the IE register then enable interrupts. */ \ push _IEN0 \ - setb _EA \ push DPL \ push DPH \ push b \ @@ -147,16 +145,18 @@ extern AO_ROMCONFIG_SYMBOL(0x00a6) uint32_t ao_radio_cal; while (--stack_len); \ } -#define ao_arch_isr_stack() \ - /* Empty the stack; might as well let interrupts have the whole thing */ \ - (SP = AO_STACK_START - 1) +/* Empty the stack; might as well let interrupts have the whole thing */ +#define ao_arch_isr_stack() (SP = AO_STACK_START - 1) -#define ao_arch_cpu_idle() (PCON = PCON_IDLE) +#define ao_arch_block_interrupts() __asm clr _EA __endasm +#define ao_arch_release_interrupts() __asm setb _EA __endasm -#define ao_arch_block_interrupts() __asm clr ea __endasm -#define ao_arch_release_interrupts() __asm setb ea __endasm -#define cli() ao_arch_block_interrupts() -#define sei() ao_arch_release_interrupts() +/* Idle the CPU, waking when an interrupt occurs */ +#define ao_arch_wait_interrupt() do { \ + ao_arch_release_interrupts(); \ + (PCON = PCON_IDLE); \ + ao_arch_block_interrupts(); \ + } while (0) #define ao_arch_restore_stack() { \ uint8_t stack_len; \ @@ -197,7 +197,7 @@ extern AO_ROMCONFIG_SYMBOL(0x00a6) uint32_t ao_radio_cal; 0098$: \ SETB _EA \ 0099$: \ - /* Finally pop off the ACC, which was the first register saved. */ \ + /* Finally restore ACC, which was the first register saved. */ \ pop ACC \ ret \ __endasm; \ diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c index 693b7c7a..74bd0c5a 100644 --- a/src/core/ao_ignite.c +++ b/src/core/ao_ignite.c @@ -23,10 +23,10 @@ __xdata struct ao_ignition ao_ignition[2]; void ao_ignite(enum ao_igniter igniter) { - cli(); + ao_arch_block_interrupts(); ao_ignition[igniter].request = 1; ao_wakeup(&ao_ignition); - sei(); + ao_arch_release_interrupts(); } #ifndef AO_SENSE_DROGUE diff --git a/src/core/ao_list.h b/src/core/ao_list.h index 23cf1841..8a6fa4d9 100644 --- a/src/core/ao_list.h +++ b/src/core/ao_list.h @@ -137,7 +137,7 @@ ao_list_is_empty(struct ao_list *head) * @return A pointer to the data struct containing the list head. */ #define ao_container_of(ptr, type, member) \ - (type *)((char *)(ptr) - offsetof(type, member)) + ((type *)((char *)(ptr) - offsetof(type, member))) /** * Alias of ao_container_of diff --git a/src/core/ao_task.c b/src/core/ao_task.c index a11979f0..0411fbdd 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -114,6 +114,8 @@ ao_task_validate_alarm_queue(void) #define ao_task_validate_alarm_queue() #endif +uint16_t ao_task_alarm_tick; + static void ao_task_to_alarm_queue(struct ao_task *task) { @@ -126,6 +128,7 @@ ao_task_to_alarm_queue(struct ao_task *task) } } ao_list_append(&task->alarm_queue, &alarm_queue); + ao_task_alarm_tick = ao_list_first_entry(&alarm_queue, struct ao_task, alarm_queue)->alarm; ao_task_validate_alarm_queue(); } @@ -133,6 +136,10 @@ static void ao_task_from_alarm_queue(struct ao_task *task) { ao_list_del(&task->alarm_queue); + if (ao_list_is_empty(&alarm_queue)) + ao_task_alarm_tick = 0; + else + ao_task_alarm_tick = ao_list_first_entry(&alarm_queue, struct ao_task, alarm_queue)->alarm; ao_task_validate_alarm_queue(); } @@ -154,10 +161,7 @@ void ao_task_check_alarm(uint16_t tick) { struct ao_task *alarm, *next; - int i; - if (ao_num_tasks == 0) - return; ao_list_for_each_entry_safe(alarm, next, &alarm_queue, struct ao_task, alarm_queue) { if ((int16_t) (tick - alarm->alarm) < 0) break; @@ -173,6 +177,7 @@ ao_task_init(void) uint8_t i; ao_list_init(&run_queue); ao_list_init(&alarm_queue); + ao_task_alarm_tick = 0; for (i = 0; i < SLEEP_HASH_SIZE; i++) ao_list_init(&sleep_queue[i]); } @@ -264,14 +269,9 @@ ao_task_validate(void) } } } -#else -#define ao_task_validate() -#endif +#endif /* DEBUG */ -#else -#define ao_task_to_run_queue(task) -#define ao_task_to_alarm_queue(task) -#endif +#endif /* HAS_TASK_QUEUE */ void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant @@ -331,6 +331,7 @@ ao_yield(void) ao_arch_naked_define } ao_arch_isr_stack(); + ao_arch_block_interrupts(); #if AO_CHECK_STACK in_yield = 1; @@ -339,21 +340,19 @@ ao_yield(void) ao_arch_naked_define * this loop will run forever, which is just fine */ #if HAS_TASK_QUEUE - if (ao_cur_task->wchan == NULL) { - uint32_t flags; - flags = ao_arch_irqsave(); + /* If the current task is running, move it to the + * end of the queue to allow other tasks a chance + */ + if (ao_cur_task->wchan == NULL) ao_task_to_run_queue(ao_cur_task); - ao_arch_irqrestore(flags); - } ao_cur_task = NULL; - for (;;) { ao_arch_memory_barrier(); if (!ao_list_is_empty(&run_queue)) break; - ao_arch_cpu_idle(); + /* Wait for interrupts when there's nothing ready */ + ao_arch_wait_interrupt(); } - ao_cur_task = ao_list_first_entry(&run_queue, struct ao_task, queue); #else { @@ -374,20 +373,19 @@ ao_yield(void) ao_arch_naked_define (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) break; - /* Enter lower power mode when there isn't anything to do */ + /* Wait for interrupts when there's nothing ready */ if (ao_cur_task_index == ao_last_task_index) - ao_arch_cpu_idle(); + ao_arch_wait_interrupt(); } -#if HAS_SAMPLE_PROFILE - ao_cur_task->start = ao_sample_profile_timer_value(); -#endif } #endif +#if HAS_SAMPLE_PROFILE + ao_cur_task->start = ao_sample_profile_timer_value(); +#endif #if HAS_STACK_GUARD ao_mpu_stack_guard(ao_cur_task->stack); #endif #if AO_CHECK_STACK - ao_arch_block_interrupts(); in_yield = 0; #endif ao_arch_restore_stack(); @@ -519,7 +517,7 @@ ao_task_info(void) task->name, (int) task->wchan); } -#if HAS_TASK_QUEUE +#if HAS_TASK_QUEUE && DEBUG ao_task_validate(); #endif } diff --git a/src/core/ao_task.h b/src/core/ao_task.h index b3f152a0..049f69a7 100644 --- a/src/core/ao_task.h +++ b/src/core/ao_task.h @@ -82,6 +82,7 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam #if HAS_TASK_QUEUE /* Called on timer interrupt to check alarms */ +extern uint16_t ao_task_alarm_tick; void ao_task_check_alarm(uint16_t tick); #endif diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 7428bead..bad313eb 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -469,10 +469,10 @@ ao_rdf_run(void) { ao_radio_start_tx(); - cli(); + ao_arch_block_interrupts(); while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); - sei(); + ao_arch_release_interrupts(); if (!ao_radio_wake) ao_radio_idle(); ao_radio_put(); @@ -603,10 +603,10 @@ ao_radio_send(const void *d, uint8_t size) do { ao_radio_wake = 0; - cli(); + ao_arch_block_interrupts(); while (!ao_radio_wake) ao_sleep(&ao_radio_wake); - sei(); + ao_arch_release_interrupts(); if (!encode_len) break; fifo_space = ao_radio_tx_fifo_space(); @@ -660,14 +660,14 @@ ao_radio_rx_isr(void) static uint16_t ao_radio_rx_wait(void) { - cli(); + ao_arch_block_interrupts(); rx_waiting = 1; while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK && !ao_radio_abort) { ao_sleep(&ao_radio_wake); } rx_waiting = 0; - sei(); + ao_arch_release_interrupts(); if (ao_radio_abort) return 0; rx_data_consumed += AO_FEC_DECODE_BLOCK; diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index ce0bcf4b..55bea563 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -130,7 +130,6 @@ static uint32_t ao_ms5607_get_sample(uint8_t cmd) { uint8_t reply[3]; uint8_t read; - uint32_t loops; ao_ms5607_done = 0; @@ -142,15 +141,10 @@ ao_ms5607_get_sample(uint8_t cmd) { #if AO_MS5607_PRIVATE_PINS ao_spi_put(AO_MS5607_SPI_INDEX); #endif -// loops = 0; - cli(); - while (!ao_ms5607_done) { -// loops++; + ao_arch_block_interrupts(); + while (!ao_ms5607_done) ao_sleep((void *) &ao_ms5607_done); - } - sei(); -// if (loops > 1) -// printf ("ms5607 loops %d\n", loops); + ao_arch_release_interrupts(); #if AO_MS5607_PRIVATE_PINS stm_gpio_set(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, 1); #else diff --git a/src/drivers/ao_radio_master.c b/src/drivers/ao_radio_master.c index 4a37ace0..1e0050c8 100644 --- a/src/drivers/ao_radio_master.c +++ b/src/drivers/ao_radio_master.c @@ -75,7 +75,7 @@ ao_radio_master_send(void) */ PRINTD("Waiting radio ready\n"); - cli(); + ao_arch_block_interrupts(); ao_radio_ready = ao_gpio_get(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN, AO_RADIO_INT); ret = 0; @@ -84,7 +84,7 @@ ao_radio_master_send(void) if (ret) break; } - sei(); + ao_arch_release_interrupts(); if (ret) return 0; @@ -99,11 +99,11 @@ ao_radio_master_send(void) AO_RADIO_SPI_BUS); ao_radio_master_stop(); PRINTD("waiting for send done %d\n", ao_radio_done); - cli(); + ao_arch_block_interrupts(); while (!ao_radio_done) if (ao_sleep((void *) &ao_radio_done)) break; - sei(); + ao_arch_release_interrupts(); PRINTD ("sent, radio done %d isr_0 %d isr_1 %d\n", ao_radio_done, isr_0_count, isr_1_count); return ao_radio_done; } 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..d6ab1465 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -210,4 +210,105 @@ 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_wait_interrupt() do { \ + asm(".global ao_idle_loc\n\twfi\nao_idle_loc:"); \ + ao_arch_release_interrupts(); \ + ao_arch_block_interrupts(); \ + } 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/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index b6dd7056..779e2275 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -197,13 +197,13 @@ ao_i2c_start(uint8_t index, uint16_t addr) break; } ao_alarm(AO_MS_TO_TICKS(250)); - cli(); + ao_arch_block_interrupts(); stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); ao_i2c_ev_isr(index); while (ao_i2c_state[index] == I2C_IDLE) if (ao_sleep(&ao_i2c_state[index])) break; - sei(); + ao_arch_release_interrupts(); ao_clear_alarm(); return ao_i2c_state[index] == I2C_RUNNING; } @@ -263,7 +263,7 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) ao_dma_start(tx_dma_index); ao_alarm(1 + len); - cli(); + ao_arch_block_interrupts(); while (!ao_dma_done[tx_dma_index]) if (ao_sleep(&ao_dma_done[tx_dma_index])) break; @@ -274,7 +274,7 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) if (ao_sleep(&ao_i2c_state[index])) break; stm_i2c->cr2 = AO_STM_I2C_CR2; - sei(); + ao_arch_release_interrupts(); if (stop) { stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); ao_i2c_wait_stop(index); @@ -328,11 +328,11 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); ao_alarm(1); - cli(); + ao_arch_block_interrupts(); while (ao_i2c_recv_len[index]) if (ao_sleep(&ao_i2c_recv_len[index])) break; - sei(); + ao_arch_release_interrupts(); ret = ao_i2c_recv_len[index] == 0; ao_clear_alarm(); } else { @@ -358,11 +358,11 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) ao_dma_start(rx_dma_index); ao_alarm(len); - cli(); + ao_arch_block_interrupts(); while (!ao_dma_done[rx_dma_index]) if (ao_sleep(&ao_dma_done[rx_dma_index])) break; - sei(); + ao_arch_release_interrupts(); ao_clear_alarm(); ret = ao_dma_done[rx_dma_index]; ao_dma_done_transfer(rx_dma_index); diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c index 0f9a8eb5..4f2a2242 100644 --- a/src/stm/ao_lcd_stm.c +++ b/src/stm/ao_lcd_stm.c @@ -253,12 +253,12 @@ ao_lcd_stm_fcr_sync(void) void ao_lcd_flush(void) { - cli(); + ao_arch_block_interrupts(); ao_lcd_update_active = 1; stm_lcd.sr = (1 << STM_LCD_SR_UDR); while (ao_lcd_update_active) ao_sleep(&ao_lcd_update_active); - sei(); + ao_arch_release_interrupts(); } void diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 406da9fb..00409f4a 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -34,7 +34,7 @@ ao_debug_out(char c) } static void -ao_usart_tx_start(struct ao_stm_usart *usart) +_ao_usart_tx_start(struct ao_stm_usart *usart) { if (!ao_fifo_empty(usart->tx_fifo) && !usart->tx_started) { @@ -61,7 +61,7 @@ ao_usart_isr(struct ao_stm_usart *usart, int stdin) } if (sr & (1 << STM_USART_SR_TC)) { usart->tx_started = 0; - ao_usart_tx_start(usart); + _ao_usart_tx_start(usart); ao_wakeup(&usart->tx_fifo); } } @@ -70,11 +70,11 @@ char ao_usart_getchar(struct ao_stm_usart *usart) { char c; - cli(); + ao_arch_block_interrupts(); while (ao_fifo_empty(usart->rx_fifo)) ao_sleep(&usart->rx_fifo); ao_fifo_remove(usart->rx_fifo, c); - sei(); + ao_arch_release_interrupts(); return c; } @@ -82,34 +82,34 @@ char ao_usart_pollchar(struct ao_stm_usart *usart) { char c; - cli(); - if (ao_fifo_empty(usart->rx_fifo)) { - sei(); - return AO_READ_AGAIN; - } - ao_fifo_remove(usart->rx_fifo,c); - sei(); + + ao_arch_block_interrupts(); + if (ao_fifo_empty(usart->rx_fifo)) + c = AO_READ_AGAIN; + else + ao_fifo_remove(usart->rx_fifo,c); + ao_arch_release_interrupts(); return c; } void ao_usart_putchar(struct ao_stm_usart *usart, char c) { - cli(); + ao_arch_block_interrupts(); while (ao_fifo_full(usart->tx_fifo)) ao_sleep(&usart->tx_fifo); ao_fifo_insert(usart->tx_fifo, c); - ao_usart_tx_start(usart); - sei(); + _ao_usart_tx_start(usart); + ao_arch_release_interrupts(); } void ao_usart_drain(struct ao_stm_usart *usart) { - cli(); + ao_arch_block_interrupts(); while (!ao_fifo_empty(usart->tx_fifo)) ao_sleep(&usart->tx_fifo); - sei(); + ao_arch_release_interrupts(); } static const struct { diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index d69035f8..e07625d8 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -44,7 +44,8 @@ void stm_tim6_isr(void) stm_tim6.sr = 0; ++ao_tick_count; #if HAS_TASK_QUEUE - ao_task_check_alarm((uint16_t) ao_tick_count); + if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0) + ao_task_check_alarm((uint16_t) ao_tick_count); #endif #if AO_DATA_ALL if (++ao_data_count == ao_data_interval) { diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 8e7dacc5..d93a0c17 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -223,16 +223,16 @@ _ao_usb_set_stat_tx(int ep, uint32_t stat_tx) static void ao_usb_set_stat_tx(int ep, uint32_t stat_tx) { - cli(); + ao_arch_block_interrupts(); _ao_usb_set_stat_tx(ep, stat_tx); - sei(); + ao_arch_release_interrupts(); } static void ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { uint32_t epr_write, epr_old; - cli(); + ao_arch_block_interrupts(); epr_write = epr_old = stm_usb.epr[ep]; epr_write &= STM_USB_EPR_PRESERVE_MASK; epr_write |= STM_USB_EPR_INVARIANT; @@ -240,7 +240,7 @@ ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX, stat_rx << STM_USB_EPR_STAT_RX); stm_usb.epr[ep] = epr_write; - sei(); + ao_arch_release_interrupts(); } /* @@ -251,7 +251,7 @@ static void ao_usb_init_ep(uint8_t ep, uint32_t addr, uint32_t type, uint32_t stat_rx, uint32_t stat_tx) { uint32_t epr; - cli(); + ao_arch_block_interrupts(); epr = stm_usb.epr[ep]; epr = ((0 << STM_USB_EPR_CTR_RX) | (epr & (1 << STM_USB_EPR_DTOG_RX)) | @@ -267,7 +267,7 @@ ao_usb_init_ep(uint8_t ep, uint32_t addr, uint32_t type, uint32_t stat_rx, uint3 (stat_tx << STM_USB_EPR_STAT_TX)) | (addr << STM_USB_EPR_EA)); stm_usb.epr[ep] = epr; - sei(); + ao_arch_release_interrupts(); debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", ep, epr, stm_usb.epr[ep]); } 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;