X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fstm%2Fao_arch_funcs.h;h=522059bc3d2193510e54d431d0bd9fd6e9bd45d5;hb=c6e57291d91f1f6c4de5c54a5cfd3eef66d9f830;hp=6fcfd5f85a1187e5e3018dd1827ef2e7e507acb4;hpb=7c9a111ac1c88467ce28e03b4a9d3eabc9d7015b;p=fw%2Faltos diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 6fcfd5f8..522059bc 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -3,7 +3,8 @@ * * 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. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -80,7 +81,13 @@ void ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index); void -ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index); +ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index); + +void +ao_spi_start_bytes(uint8_t spi_index); + +void +ao_spi_stop_bytes(uint8_t spi_index); static inline void ao_spi_send_byte(uint8_t byte, uint8_t spi_index) @@ -96,25 +103,41 @@ ao_spi_send_byte(uint8_t byte, uint8_t spi_index) break; } - stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | - (0 << STM_SPI_CR2_RXNEIE) | - (0 << STM_SPI_CR2_ERRIE) | - (0 << STM_SPI_CR2_SSOE) | - (0 << STM_SPI_CR2_TXDMAEN) | - (0 << STM_SPI_CR2_RXDMAEN)); - - /* Clear RXNE */ + while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE))) + ; + stm_spi->dr = byte; + while (!(stm_spi->sr & (1 << STM_SPI_SR_RXNE))) + ; (void) stm_spi->dr; +} - while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE))); - stm_spi->dr = byte; +static inline uint8_t +ao_spi_recv_byte(uint8_t spi_index) +{ + struct stm_spi *stm_spi; + + switch (AO_SPI_INDEX(spi_index)) { + case 0: + stm_spi = &stm_spi1; + break; + case 1: + stm_spi = &stm_spi2; + break; + } + + while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE))) + ; + stm_spi->dr = 0xff; + while (!(stm_spi->sr & (1 << STM_SPI_SR_RXNE))) + ; + return stm_spi->dr; } void ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void -ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index); +ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index); extern uint16_t ao_spi_speed[STM_NUM_SPI]; @@ -179,8 +202,11 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s #define ao_gpio_set_bits(port, bits) stm_gpio_set_bits(port, bits) +#define ao_gpio_set_mask(port, bits, mask) stm_gpio_set_mask(port, bits, mask) + #define ao_gpio_clr_bits(port, bits) stm_gpio_clr_bits(port, bits); +#define ao_gpio_get_all(port) stm_gpio_get_all(port) #define ao_enable_output(port,bit,pin,v) do { \ ao_enable_port(port); \ @@ -188,6 +214,18 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s stm_moder_set(port, bit, STM_MODER_OUTPUT);\ } while (0) +#define ao_enable_output_mask(port,bits,mask) do { \ + ao_enable_port(port); \ + ao_gpio_set_mask(port, bits, mask); \ + ao_set_output_mask(port, mask); \ + } while (0) + +#define AO_OUTPUT_PUSH_PULL STM_OTYPER_PUSH_PULL +#define AO_OUTPUT_OPEN_DRAIN STM_OTYPER_OPEN_DRAIN + +#define ao_gpio_set_output_mode(port,bit,pin,mode) \ + stm_otyper_set(port, pin, mode) + #define ao_gpio_set_mode(port,bit,mode) do { \ if (mode == AO_EXTI_MODE_PULL_UP) \ stm_pupdr_set(port, bit, STM_PUPDR_PULL_UP); \ @@ -196,36 +234,73 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s else \ stm_pupdr_set(port, bit, STM_PUPDR_NONE); \ } while (0) - + +#define ao_gpio_set_mode_mask(port,mask,mode) do { \ + if (mode == AO_EXTI_MODE_PULL_UP) \ + stm_pupdr_set_mask(port, mask, STM_PUPDR_PULL_UP); \ + else if (mode == AO_EXTI_MODE_PULL_DOWN) \ + stm_pupdr_set_mask(port, mask, STM_PUPDR_PULL_DOWN); \ + else \ + stm_pupdr_set_mask(port, mask, STM_PUPDR_NONE); \ + } while (0) + +#define ao_set_input(port, bit) do { \ + stm_moder_set(port, bit, STM_MODER_INPUT); \ + } while (0) + +#define ao_set_output(port, bit, pin, v) do { \ + ao_gpio_set(port, bit, pin, v); \ + stm_moder_set(port, bit, STM_MODER_OUTPUT); \ + } while (0) + +#define ao_set_output_mask(port, mask) do { \ + stm_moder_set_mask(port, mask, STM_MODER_OUTPUT); \ + } while (0) + +#define ao_set_input_mask(port, mask) do { \ + stm_moder_set_mask(port, mask, STM_MODER_INPUT); \ + } while (0) + #define ao_enable_input(port,bit,mode) do { \ ao_enable_port(port); \ - stm_moder_set(port, bit, STM_MODER_INPUT); \ + ao_set_input(port, bit); \ ao_gpio_set_mode(port, bit, mode); \ } while (0) -#define ao_enable_cs(port,bit) do { \ +#define ao_enable_input_mask(port,mask,mode) do { \ + ao_enable_port(port); \ + ao_gpio_set_mode_mask(port, mask, mode); \ + ao_set_input_mask(port, mask); \ + } while (0) + +#define _ao_enable_cs(port, bit) do { \ stm_gpio_set((port), bit, 1); \ stm_moder_set((port), bit, STM_MODER_OUTPUT); \ } while (0) +#define ao_enable_cs(port,bit) do { \ + ao_enable_port(port); \ + _ao_enable_cs(port, bit); \ + } while (0) + #define ao_spi_init_cs(port, mask) do { \ ao_enable_port(port); \ - if ((mask) & 0x0001) ao_enable_cs(port, 0); \ - if ((mask) & 0x0002) ao_enable_cs(port, 1); \ - if ((mask) & 0x0004) ao_enable_cs(port, 2); \ - if ((mask) & 0x0008) ao_enable_cs(port, 3); \ - if ((mask) & 0x0010) ao_enable_cs(port, 4); \ - if ((mask) & 0x0020) ao_enable_cs(port, 5); \ - if ((mask) & 0x0040) ao_enable_cs(port, 6); \ - if ((mask) & 0x0080) ao_enable_cs(port, 7); \ - if ((mask) & 0x0100) ao_enable_cs(port, 8); \ - if ((mask) & 0x0200) ao_enable_cs(port, 9); \ - if ((mask) & 0x0400) ao_enable_cs(port, 10);\ - if ((mask) & 0x0800) ao_enable_cs(port, 11);\ - if ((mask) & 0x1000) ao_enable_cs(port, 12);\ - if ((mask) & 0x2000) ao_enable_cs(port, 13);\ - if ((mask) & 0x4000) ao_enable_cs(port, 14);\ - if ((mask) & 0x8000) ao_enable_cs(port, 15);\ + if ((mask) & 0x0001) _ao_enable_cs(port, 0); \ + if ((mask) & 0x0002) _ao_enable_cs(port, 1); \ + if ((mask) & 0x0004) _ao_enable_cs(port, 2); \ + if ((mask) & 0x0008) _ao_enable_cs(port, 3); \ + if ((mask) & 0x0010) _ao_enable_cs(port, 4); \ + if ((mask) & 0x0020) _ao_enable_cs(port, 5); \ + if ((mask) & 0x0040) _ao_enable_cs(port, 6); \ + if ((mask) & 0x0080) _ao_enable_cs(port, 7); \ + if ((mask) & 0x0100) _ao_enable_cs(port, 8); \ + if ((mask) & 0x0200) _ao_enable_cs(port, 9); \ + if ((mask) & 0x0400) _ao_enable_cs(port, 10);\ + if ((mask) & 0x0800) _ao_enable_cs(port, 11);\ + if ((mask) & 0x1000) _ao_enable_cs(port, 12);\ + if ((mask) & 0x2000) _ao_enable_cs(port, 13);\ + if ((mask) & 0x4000) _ao_enable_cs(port, 14);\ + if ((mask) & 0x8000) _ao_enable_cs(port, 15);\ } while (0) /* ao_dma_stm.c @@ -249,9 +324,6 @@ ao_dma_start(uint8_t index); void ao_dma_done_transfer(uint8_t index); -void -ao_dma_abort(uint8_t index); - void ao_dma_alloc(uint8_t index); @@ -278,14 +350,35 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop); void ao_i2c_init(void); +#if USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_SW_FLOW +#define HAS_SERIAL_SW_FLOW 1 +#else +#define HAS_SERIAL_SW_FLOW 0 +#endif + +#if USE_SERIAL_1_FLOW && !USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_FLOW && !USE_SERIAL_3_SW_FLOW +#define HAS_SERIAL_HW_FLOW 1 +#else +#define HAS_SERIAL_HW_FLOW 0 +#endif + /* 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; uint8_t tx_running; uint8_t draining; +#if HAS_SERIAL_SW_FLOW + /* RTS - 0 if we have FIFO space, 1 if not + * CTS - 0 if we can send, 0 if not + */ + struct stm_gpio *gpio_rts; + struct stm_gpio *gpio_cts; + uint8_t pin_rts; + uint8_t pin_cts; + uint8_t rts; +#endif }; #if HAS_SERIAL_1 @@ -304,17 +397,43 @@ extern struct ao_stm_usart ao_stm_usart3; typedef uint32_t ao_arch_irq_t; +static inline void +ao_arch_block_interrupts(void) { +#ifdef AO_NONMASK_INTERRUPTS + asm("msr basepri,%0" : : "r" (AO_STM_NVIC_BASEPRI_MASK)); +#else + asm("cpsid i"); +#endif +} + +static inline void +ao_arch_release_interrupts(void) { +#ifdef AO_NONMASK_INTERRUPTS + asm("msr basepri,%0" : : "r" (0x0)); +#else + asm("cpsie i"); +#endif +} + static inline uint32_t ao_arch_irqsave(void) { - uint32_t primask; - asm("mrs %0,primask" : "=&r" (primask)); + uint32_t val; +#ifdef AO_NONMASK_INTERRUPTS + asm("mrs %0,basepri" : "=r" (val)); +#else + asm("mrs %0,primask" : "=r" (val)); +#endif ao_arch_block_interrupts(); - return primask; + return val; } static inline void -ao_arch_irqrestore(uint32_t primask) { - asm("msr primask,%0" : : "r" (primask)); +ao_arch_irqrestore(uint32_t basepri) { +#ifdef AO_NONMASK_INTERRUPTS + asm("msr basepri,%0" : : "r" (basepri)); +#else + asm("msr primask,%0" : : "r" (basepri)); +#endif } static inline void @@ -322,11 +441,26 @@ ao_arch_memory_barrier() { asm volatile("" ::: "memory"); } +static inline void +ao_arch_irq_check(void) { +#ifdef AO_NONMASK_INTERRUPTS + uint32_t basepri; + asm("mrs %0,basepri" : "=r" (basepri)); + if (basepri == 0) + ao_panic(AO_PANIC_IRQ); +#else + uint32_t primask; + asm("mrs %0,primask" : "=r" (primask)); + if ((primask & 1) == 0) + ao_panic(AO_PANIC_IRQ); +#endif +} + #if HAS_TASK 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 *sp = (uint32_t *) ((void*) task->stack + AO_STACK_SIZE); uint32_t a = (uint32_t) start; int i; @@ -341,7 +475,7 @@ ao_arch_init_stack(struct ao_task *task, void *start) /* APSR */ ARM_PUSH32(sp, 0); - /* PRIMASK with interrupts enabled */ + /* BASEPRI with interrupts enabled */ ARM_PUSH32(sp, 0); task->sp = sp; @@ -355,8 +489,13 @@ static inline void ao_arch_save_regs(void) { asm("mrs r0,apsr"); asm("push {r0}"); +#ifdef AO_NONMASK_INTERRUPTS + /* Save BASEPRI */ + asm("mrs r0,basepri"); +#else /* Save PRIMASK */ asm("mrs r0,primask"); +#endif asm("push {r0}"); } @@ -364,27 +503,21 @@ 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; - uint32_t control; - - asm("mrs %0,control" : "=&r" (control)); - control |= (1 << 1); - asm("msr control,%0" : : "r" (control)); - asm("isb"); - - sp = (uint32_t) ao_cur_task->sp; - /* Switch stacks */ - asm("mov sp, %0" : : "r" (sp) ); + asm("mov sp, %0" : : "r" (ao_cur_task->sp) ); +#ifdef AO_NONMASK_INTERRUPTS + /* Restore BASEPRI */ + asm("pop {r0}"); + asm("msr basepri,r0"); +#else /* Restore PRIMASK */ asm("pop {r0}"); asm("msr primask,r0"); +#endif /* Restore APSR */ asm("pop {r0}"); @@ -426,30 +559,35 @@ static inline void ao_arch_start_scheduler(void) { asm("mrs %0,msp" : "=&r" (sp)); asm("msr psp,%0" : : "r" (sp)); - asm("mrs %0,control" : "=&r" (control)); + asm("mrs %0,control" : "=r" (control)); control |= (1 << 1); asm("msr control,%0" : : "r" (control)); asm("isb"); } #endif -static inline void ao_arch_isr_stack(void) { - uint32_t control; - - asm("mrs %0,control" : "=&r" (control)); - control &= ~(1 << 1); - asm("msr control,%0" : : "r" (control)); - asm("isb"); -} +#define ao_arch_isr_stack() #endif -#define ao_arch_wait_interrupt() do { \ - asm("\twfi\n"); \ - ao_arch_release_interrupts(); \ - asm(".global ao_idle_loc\nao_idle_loc:"); \ - ao_arch_block_interrupts(); \ - } while (0) +static inline void +ao_arch_wait_interrupt(void) { +#ifdef AO_NONMASK_INTERRUPTS + asm( + "dsb\n" /* Serialize data */ + "isb\n" /* Serialize instructions */ + "cpsid i\n" /* Block all interrupts */ + "msr basepri,%0\n" /* Allow all interrupts through basepri */ + "wfi\n" /* Wait for an interrupt */ + "cpsie i\n" /* Allow all interrupts */ + "msr basepri,%1\n" /* Block interrupts through basepri */ + : : "r" (0), "r" (AO_STM_NVIC_BASEPRI_MASK)); +#else + asm("\twfi\n"); + ao_arch_release_interrupts(); + ao_arch_block_interrupts(); +#endif +} #define ao_arch_critical(b) do { \ uint32_t __mask = ao_arch_irqsave(); \