diff --git a/demos/MSP430-MSP430x1611-GCC/board.c b/demos/MSP430-MSP430x1611-GCC/board.c index 8fcecec17..f5e5e4012 100644 --- a/demos/MSP430-MSP430x1611-GCC/board.c +++ b/demos/MSP430-MSP430x1611-GCC/board.c @@ -85,9 +85,13 @@ void hwinit(void) { InitSerial(); } -interrupt(TIMERA0_VECTOR) tmr0irq(void) { +SYS_IRQ_HANDLER(TIMERA0_VECTOR) tmr0irq(void) { - chSysIRQEnterI(); + SYS_IRQ_PROLOGUE(); + + chSysLockI(); chSysTimerHandlerI(); - chSysIRQExitI(); + chSysUnlockI(); + + SYS_IRQ_EPILOGUE(); } diff --git a/ports/MSP430/chcore.c b/ports/MSP430/chcore.c index e9a5dc574..e56f41120 100644 --- a/ports/MSP430/chcore.c +++ b/ports/MSP430/chcore.c @@ -31,12 +31,55 @@ * because performance concerns. */ +/** + * The default implementation of this function is void so no messages are + * actually printed. + * @note The function is declared as a weak symbol, it is possible to redefine + * it in your application code. + * @param msg pointer to the message string + */ +__attribute__((weak)) void sys_puts(char *msg) { } +/** + * Performs a context switch between two threads. + * @param otp the thread to be switched out + * @param ntp the thread to be switched in + * @note The function is declared as a weak symbol, it is possible to redefine + * it in your application code. + */ +__attribute__((naked, weak)) void sys_switch(Thread *otp, Thread *ntp) { + register struct intctx *sp asm("r1"); + + asm volatile ("push r11 \n\t" \ + "push r10 \n\t" \ + "push r9 \n\t" \ + "push r8 \n\t" \ + "push r7 \n\t" \ + "push r6 \n\t" \ + "push r6 \n\t" \ + "push r4"); + otp->p_ctx.sp = sp; + sp = ntp->p_ctx.sp; + asm volatile ("pop r4 \n\t" \ + "pop r5 \n\t" \ + "pop r6 \n\t" \ + "pop r7 \n\t" \ + "pop r8 \n\t" \ + "pop r9 \n\t" \ + "pop r10 \n\t" \ + "pop r11 \n\t" \ + "ret" : : "r" (sp)); } +/** + * Disables the interrupts and halts the system. + * @note The function is declared as a weak symbol, it is possible to redefine + * it in your application code. + */ +__attribute__((weak)) void sys_halt(void) { sys_disable(); @@ -44,4 +87,16 @@ void sys_halt(void) { } } +/** + * Start a thread by invoking its work function. + * If the work function returns @p chThdExit() is automatically invoked. + */ +void threadstart(void) { + + asm volatile ("eint \n\t" \ + "mov r11, r15 \n\t" \ + "call r10 \n\t" \ + "call #chThdExit"); +} + /** @} */ diff --git a/ports/MSP430/chcore.h b/ports/MSP430/chcore.h index db0d25f77..a4a866f11 100644 --- a/ports/MSP430/chcore.h +++ b/ports/MSP430/chcore.h @@ -150,6 +150,12 @@ if (chSchRescRequiredI()) \ chSchDoRescheduleI(); \ } +/** + * IRQ handler function modifier. Note it just aliases the WinMSP "interrupt" + * macro. + */ +#define SYS_IRQ_HANDLER interrupt + /** * This port function is implemented as inlined code for performance reasons. */ @@ -181,11 +187,6 @@ if (chSchRescRequiredI()) \ #define sys_wait_for_interrupt() #endif -/** - * IRQ handler function modifier. - */ -#define SYS_IRQ_HANDLER - #ifdef __cplusplus extern "C" { #endif diff --git a/ports/MSP430/msp430_serial.c b/ports/MSP430/msp430_serial.c index 384cda0fc..27094edeb 100644 --- a/ports/MSP430/msp430_serial.c +++ b/ports/MSP430/msp430_serial.c @@ -34,7 +34,9 @@ static void SetError(uint8_t urctl, FullDuplexDriver *com) { sts |= SD_FRAMING_ERROR; if (urctl & BRK) sts |= SD_BREAK_DETECTED; + chSysLockI(); chFDDAddFlagsI(com, sts); + chSysUnlockI(); } #ifdef USE_MSP430_USART0 @@ -42,30 +44,34 @@ FullDuplexDriver COM1; static uint8_t ib1[SERIAL_BUFFERS_SIZE]; static uint8_t ob1[SERIAL_BUFFERS_SIZE]; -interrupt(USART0TX_VECTOR) u0txirq(void) { +SYS_IRQ_HANDLER(USART0TX_VECTOR) u0txirq(void) { msg_t b; - chSysIRQEnterI(); + SYS_IRQ_PROLOGUE(); + chSysLockI(); b = chFDDRequestDataI(&COM1); + chSysUnlockI(); if (b < Q_OK) U0IE &= ~UTXIE0; else U0TXBUF = b; - chSysIRQExitI(); + SYS_IRQ_EPILOGUE(); } -interrupt(USART0RX_VECTOR) u0rxirq(void) { +SYS_IRQ_HANDLER(USART0RX_VECTOR) u0rxirq(void) { uint8_t urctl; - chSysIRQEnterI(); + SYS_IRQ_PROLOGUE(); if ((urctl = U0RCTL) & RXERR) SetError(urctl, &COM1); + chSysLockI(); chFDDIncomingDataI(&COM1, U0RXBUF); + chSysUnlockI(); - chSysIRQExitI(); + SYS_IRQ_EPILOGUE(); } /* @@ -75,7 +81,9 @@ interrupt(USART0RX_VECTOR) u0rxirq(void) { static void OutNotify1(void) { if (!(U0IE & UTXIE0)) { + chSysLockI(); U0TXBUF = (uint8_t)chFDDRequestDataI(&COM1); + chSysUnlockI(); U0IE |= UTXIE0; } } @@ -108,30 +116,34 @@ FullDuplexDriver COM2; static uint8_t ib2[SERIAL_BUFFERS_SIZE]; static uint8_t ob2[SERIAL_BUFFERS_SIZE]; -interrupt(USART1TX_VECTOR) u1txirq(void) { +SYS_IRQ_HANDLER(USART1TX_VECTOR) u1txirq(void) { msg_t b; - chSysIRQEnterI(); + SYS_IRQ_PROLOGUE(); + chSysLockI(); b = chFDDRequestDataI(&COM2); + chSysUnlockI(); if (b < Q_OK) U1IE &= ~UTXIE1; else U1TXBUF = b; - chSysIRQExitI(); + SYS_IRQ_EPILOGUE(); } -interrupt(USART1RX_VECTOR) u1rxirq(void) { +SYS_IRQ_HANDLER(USART1RX_VECTOR) u1rxirq(void) { uint8_t urctl; - chSysIRQEnterI(); + SYS_IRQ_PROLOGUE(); if ((urctl = U1RCTL) & RXERR) SetError(urctl, &COM2); + chSysLockI(); chFDDIncomingDataI(&COM2, U1RXBUF); + chSysUnlockI(); - chSysIRQExitI(); + SYS_IRQ_EPILOGUE(); }