summaryrefslogtreecommitdiff
path: root/src/stm
diff options
context:
space:
mode:
Diffstat (limited to 'src/stm')
-rw-r--r--src/stm/ao_arch.h112
-rw-r--r--src/stm/ao_arch_funcs.h101
-rw-r--r--src/stm/ao_i2c_stm.c16
-rw-r--r--src/stm/ao_lcd_stm.c4
-rw-r--r--src/stm/ao_serial_stm.c32
-rw-r--r--src/stm/ao_timer.c3
-rw-r--r--src/stm/ao_usb_stm.c12
-rw-r--r--src/stm/registers.ld2
-rw-r--r--src/stm/stm32l.h30
9 files changed, 170 insertions, 142 deletions
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;