altos: Add one-byte SPI output routine for LPC and STM cores
[fw/altos] / src / stm / ao_arch_funcs.h
index 42f1a2e5d75c5aeb4680dbf12c7c9b0f039e9ebb..087e00d91da77d13075a80fa98c9234884a04a02 100644 (file)
@@ -82,6 +82,34 @@ 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);
 
+static inline void
+ao_spi_send_byte(uint8_t 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;
+       }
+
+       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 */
+       (void) stm_spi->dr;
+
+       while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
+       stm_spi->dr = byte;
+}
+
 void
 ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
 
@@ -335,6 +363,13 @@ static inline void ao_arch_save_stack(void) {
 
 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 */
@@ -359,6 +394,22 @@ static inline void ao_arch_restore_stack(void) {
 #define HAS_SAMPLE_PROFILE 0
 #endif
 
+#if DEBUG
+#define HAS_ARCH_VALIDATE_CUR_STACK    1
+
+static inline void
+ao_validate_cur_stack(void)
+{
+       uint8_t         *psp;
+
+       asm("mrs %0,psp" : "=&r" (psp));
+       if (ao_cur_task &&
+           psp <= ao_cur_task->stack &&
+           psp >= ao_cur_task->stack - 256)
+               ao_panic(AO_PANIC_STACK);
+}
+#endif
+
 #if !HAS_SAMPLE_PROFILE
 #define HAS_ARCH_START_SCHEDULER       1
 
@@ -375,7 +426,14 @@ static inline void ao_arch_start_scheduler(void) {
 }
 #endif
 
-#define ao_arch_isr_stack()
+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");
+}
 
 #endif