Merge pull request #8988 from Josar/atmega_isr

cpu/atmega_common: __exit_isr thread_yield
This commit is contained in:
Francisco Acosta 2018-06-26 16:12:39 +03:00 committed by GitHub
commit f0dce1b920
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 92 additions and 106 deletions

View File

@ -35,7 +35,8 @@
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include "cpu_conf.h" #include "cpu_conf.h"
#include "sched.h"
#include "thread.h"
/** /**
* For downwards compatibility with old RIOT code. * For downwards compatibility with old RIOT code.
* TODO: remove once core was adjusted * TODO: remove once core was adjusted
@ -43,7 +44,8 @@
#include "irq.h" #include "irq.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
/** /**
@ -52,7 +54,7 @@ extern "C" {
extern volatile uint8_t __in_isr; extern volatile uint8_t __in_isr;
/** /**
* @brief Flag entering of an ISR * @brief Run this code on entering interrupt routines
*/ */
static inline void __enter_isr(void) static inline void __enter_isr(void)
{ {
@ -60,10 +62,22 @@ static inline void __enter_isr(void)
} }
/** /**
* @brief Flag exiting of an ISR * @brief Exit ISR mode and yield with a return from interrupt. Use at the
* end of ISRs in place of thread_yield_higher. If thread_yield is needed, use
* thread_yield followed by thread_yield_isr instead of thread_yield alone.
*/
void thread_yield_isr(void);
/**
* @brief Run this code on exiting interrupt routines
*/ */
static inline void __exit_isr(void) static inline void __exit_isr(void)
{ {
if (sched_context_switch_request) {
thread_yield();
__in_isr = 0;
thread_yield_isr();
}
__in_isr = 0; __in_isr = 0;
} }
@ -75,20 +89,20 @@ void cpu_init(void);
/** /**
* @brief Print the last instruction's address * @brief Print the last instruction's address
*/ */
__attribute__((always_inline)) static inline void cpu_print_last_instruction(void) static inline void __attribute__((always_inline)) cpu_print_last_instruction(void)
{ {
uint8_t hi; uint8_t hi;
uint8_t lo; uint8_t lo;
uint16_t ptr; uint16_t ptr;
__asm__ volatile( "in __tmp_reg__, __SP_H__ \n\t" __asm__ volatile ("in __tmp_reg__, __SP_H__ \n\t"
"mov %0, __tmp_reg__ \n\t" "mov %0, __tmp_reg__ \n\t"
: "=g"(hi) ); : "=g" (hi));
__asm__ volatile( "in __tmp_reg__, __SP_L__ \n\t" __asm__ volatile ("in __tmp_reg__, __SP_L__ \n\t"
"mov %0, __tmp_reg__ \n\t" "mov %0, __tmp_reg__ \n\t"
: "=g"(lo) ); : "=g" (lo));
ptr = hi<<8 | lo; ptr = hi << 8 | lo;
printf("Stack Pointer: 0x%04x\n", ptr); printf("Stack Pointer: 0x%04x\n", ptr);
} }
@ -128,13 +142,6 @@ static inline void atmega_set_prescaler(uint8_t clk_scale)
*/ */
void atmega_stdio_init(void); void atmega_stdio_init(void);
/**
* @brief Exit ISR mode and yield with a return from interrupt. Use at the
* end of ISRs in place of thread_yield_higher. If thread_yield is needed, use
* thread_yield followed by thread_yield_isr instead of thread_yield alone.
*/
void thread_yield_isr(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -167,11 +167,6 @@ static inline void _isr(tim_t tim, int chan)
*ctx[tim].mask &= ~(1 << (chan + OCIE1A)); *ctx[tim].mask &= ~(1 << (chan + OCIE1A));
ctx[tim].cb(ctx[tim].arg, chan); ctx[tim].cb(ctx[tim].arg, chan);
if (sched_context_switch_request) {
thread_yield();
thread_yield_isr();
}
__exit_isr(); __exit_isr();
} }
#endif #endif

View File

@ -35,7 +35,6 @@
#include "periph/uart.h" #include "periph/uart.h"
/** /**
* @brief Maximum percentage error in calculated baud before switching to * @brief Maximum percentage error in calculated baud before switching to
* double speed transmission (U2X) * double speed transmission (U2X)
@ -90,6 +89,7 @@ static void _update_brr(uart_t uart, uint16_t brr, bool double_speed)
static void _set_brr(uart_t uart, uint32_t baudrate) static void _set_brr(uart_t uart, uint32_t baudrate)
{ {
uint16_t brr; uint16_t brr;
#if defined(UART_STDIO_BAUDRATE) #if defined(UART_STDIO_BAUDRATE)
/* UBRR_VALUE and USE_2X are statically computed from <util/setbaud.h> */ /* UBRR_VALUE and USE_2X are statically computed from <util/setbaud.h> */
if (baudrate == UART_STDIO_BAUDRATE) { if (baudrate == UART_STDIO_BAUDRATE) {
@ -134,14 +134,13 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
dev[uart]->CSRB = (1 << TXEN0); dev[uart]->CSRB = (1 << TXEN0);
} }
return UART_OK; return UART_OK;
} }
void uart_write(uart_t uart, const uint8_t *data, size_t len) void uart_write(uart_t uart, const uint8_t *data, size_t len)
{ {
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
while (!(dev[uart]->CSRA & (1 << UDRE0))) {}; while (!(dev[uart]->CSRA & (1 << UDRE0))) {}
dev[uart]->DR = data[i]; dev[uart]->DR = data[i];
} }
} }
@ -160,46 +159,37 @@ void uart_poweroff(uart_t uart)
static inline void isr_handler(int num) static inline void isr_handler(int num)
{ {
__enter_isr();
isr_ctx[num].rx_cb(isr_ctx[num].arg, dev[num]->DR); isr_ctx[num].rx_cb(isr_ctx[num].arg, dev[num]->DR);
if (sched_context_switch_request) { __exit_isr();
thread_yield();
thread_yield_isr();
}
} }
#ifdef UART_0_ISR #ifdef UART_0_ISR
ISR(UART_0_ISR, ISR_BLOCK) ISR(UART_0_ISR, ISR_BLOCK)
{ {
__enter_isr();
isr_handler(0); isr_handler(0);
__exit_isr();
} }
#endif /* UART_0_ISR */ #endif /* UART_0_ISR */
#ifdef UART_1_ISR #ifdef UART_1_ISR
ISR(UART_1_ISR, ISR_BLOCK) ISR(UART_1_ISR, ISR_BLOCK)
{ {
__enter_isr();
isr_handler(1); isr_handler(1);
__exit_isr();
} }
#endif /* UART_1_ISR */ #endif /* UART_1_ISR */
#ifdef UART_2_ISR #ifdef UART_2_ISR
ISR(UART_2_ISR, ISR_BLOCK) ISR(UART_2_ISR, ISR_BLOCK)
{ {
__enter_isr();
isr_handler(2); isr_handler(2);
__exit_isr();
} }
#endif /* UART_2_ISR */ #endif /* UART_2_ISR */
#ifdef UART_3_ISR #ifdef UART_3_ISR
ISR(UART_3_ISR, ISR_BLOCK) ISR(UART_3_ISR, ISR_BLOCK)
{ {
__enter_isr();
isr_handler(3); isr_handler(3);
__exit_isr();
} }
#endif /* UART_3_ISR */ #endif /* UART_3_ISR */

View File

@ -28,7 +28,6 @@
#include "cpu.h" #include "cpu.h"
#include "board.h" #include "board.h"
/* /*
* local function declarations (prefixed with __) * local function declarations (prefixed with __)
*/ */
@ -79,59 +78,58 @@ char *thread_stack_init(thread_task_func_t task_func, void *arg,
/* put marker on stack */ /* put marker on stack */
stk--; stk--;
*stk = (uint8_t) 0xAF; *stk = (uint8_t)0xAF;
stk--; stk--;
*stk = (uint8_t) 0xFE; *stk = (uint8_t)0xFE;
/* save sched_task_exit */ /* save sched_task_exit */
stk--; stk--;
tmp_adress = (uint16_t) sched_task_exit; tmp_adress = (uint16_t)sched_task_exit;
*stk = (uint8_t)(tmp_adress & (uint16_t) 0x00ff); *stk = (uint8_t)(tmp_adress & (uint16_t)0x00ff);
stk--; stk--;
tmp_adress >>= 8; tmp_adress >>= 8;
*stk = (uint8_t)(tmp_adress & (uint16_t) 0x00ff); *stk = (uint8_t)(tmp_adress & (uint16_t)0x00ff);
#if FLASHEND > 0x1ffff #if FLASHEND > 0x1ffff
/* Devices with more than 128kb FLASH use a 17 bit PC, we set whole the top byte forcibly to 0 */ /* Devices with more than 128kb FLASH use a 17 bit PC, we set whole the top byte forcibly to 0 */
stk--; stk--;
*stk = (uint8_t) 0x00; *stk = (uint8_t)0x00;
#endif #endif
/* save address to task_func in place of the program counter */ /* save address to task_func in place of the program counter */
stk--; stk--;
tmp_adress = (uint16_t) task_func; tmp_adress = (uint16_t)task_func;
*stk = (uint8_t)(tmp_adress & (uint16_t) 0x00ff); *stk = (uint8_t)(tmp_adress & (uint16_t)0x00ff);
stk--; stk--;
tmp_adress >>= 8; tmp_adress >>= 8;
*stk = (uint8_t)(tmp_adress & (uint16_t) 0x00ff); *stk = (uint8_t)(tmp_adress & (uint16_t)0x00ff);
#if FLASHEND > 0x1ffff #if FLASHEND > 0x1ffff
/* Devices with more than 128kb FLASH use a 17 bit PC, we set whole the top byte forcibly to 0 */ /* Devices with more than 128kb FLASH use a 17 bit PC, we set whole the top byte forcibly to 0 */
stk--; stk--;
*stk = (uint8_t) 0x00; *stk = (uint8_t)0x00;
#endif #endif
/* r0 */ /* r0 */
stk--; stk--;
*stk = (uint8_t) 0x00; *stk = (uint8_t)0x00;
/* status register (with interrupts enabled) */ /* status register (with interrupts enabled) */
stk--; stk--;
*stk = (uint8_t) 0x80; *stk = (uint8_t)0x80;
#if defined(EIND) #if defined(EIND)
stk--; stk--;
*stk = (uint8_t) 0x00; *stk = (uint8_t)0x00;
#endif #endif
#if defined(RAMPZ) #if defined(RAMPZ)
stk--; stk--;
*stk = (uint8_t) 0x00; *stk = (uint8_t)0x00;
#endif #endif
/* r1 - has always to be 0 */ /* r1 - has always to be 0 */
stk--; stk--;
*stk = (uint8_t) 0x00; *stk = (uint8_t)0x00;
/* /*
* Space for registers r2 -r23 * Space for registers r2 -r23
* *
@ -140,9 +138,9 @@ char *thread_stack_init(thread_task_func_t task_func, void *arg,
int i; int i;
for (i = 2; i <= 23 ; i++) { for (i = 2; i <= 23; i++) {
stk--; stk--;
*stk = (uint8_t) 0; *stk = (uint8_t)0;
} }
/* /*
@ -150,22 +148,22 @@ char *thread_stack_init(thread_task_func_t task_func, void *arg,
* r24 and r25 * r24 and r25
* */ * */
stk--; stk--;
tmp_adress = (uint16_t) arg; tmp_adress = (uint16_t)arg;
*stk = (uint8_t)(tmp_adress & (uint16_t) 0x00ff); *stk = (uint8_t)(tmp_adress & (uint16_t)0x00ff);
stk--; stk--;
tmp_adress >>= 8; tmp_adress >>= 8;
*stk = (uint8_t)(tmp_adress & (uint16_t) 0x00ff); *stk = (uint8_t)(tmp_adress & (uint16_t)0x00ff);
/* /*
* Space for registers r26-r31 * Space for registers r26-r31
*/ */
for (i = 26; i <= 31; i++) { for (i = 26; i <= 31; i++) {
stk--; stk--;
*stk = (uint8_t) i; *stk = (uint8_t)i;
} }
stk--; stk--;
return (char *) stk; return (char *)stk;
} }
/** /**
@ -193,8 +191,7 @@ void thread_stack_print(void)
if ((*sp == 0xFE) && (*(sp + 1) == 0xAF)) { if ((*sp == 0xFE) && (*(sp + 1) == 0xAF)) {
found_marker = 0; found_marker = 0;
} }
} } while (found_marker == 1);
while (found_marker == 1);
printf("stack size: %u bytes\n", size); printf("stack size: %u bytes\n", size);
} }
@ -209,41 +206,41 @@ void cpu_switch_context_exit(void)
/** /**
* @brief Set the MCU into Thread-Mode and load the initial task from the stack and run it * @brief Set the MCU into Thread-Mode and load the initial task from the stack and run it
*/ */
void NORETURN __enter_thread_mode(void) __attribute__((naked)); void NORETURN __enter_thread_mode(void) __attribute__((naked));
void NORETURN __enter_thread_mode(void) void NORETURN __enter_thread_mode(void)
{ {
irq_enable(); irq_enable();
__context_restore(); __context_restore();
__asm__ volatile("ret"); __asm__ volatile ("ret");
UNREACHABLE(); UNREACHABLE();
} }
void thread_yield_higher(void) { void thread_yield_higher(void)
{
if (irq_is_in() == 0) { if (irq_is_in() == 0) {
__context_save(); __context_save();
sched_run(); sched_run();
__context_restore(); __context_restore();
__asm__ volatile("ret"); __asm__ volatile ("ret");
} else { }
else {
sched_context_switch_request = 1; sched_context_switch_request = 1;
} }
} }
void thread_yield_isr(void) { void thread_yield_isr(void)
{
__context_save(); __context_save();
sched_run(); sched_run();
__context_restore(); __context_restore();
__exit_isr(); __asm__ volatile ("reti");
__asm__ volatile("reti");
} }
__attribute__((always_inline)) static inline void __context_save(void) __attribute__((always_inline)) static inline void __context_save(void)
{ {
__asm__ volatile( __asm__ volatile (
"push __tmp_reg__ \n\t" "push __tmp_reg__ \n\t"
"in __tmp_reg__, __SREG__ \n\t" "in __tmp_reg__, __SREG__ \n\t"
"cli \n\t" "cli \n\t"
@ -293,14 +290,12 @@ __attribute__((always_inline)) static inline void __context_save(void)
"in __tmp_reg__, __SP_L__ \n\t" "in __tmp_reg__, __SP_L__ \n\t"
"st x+, __tmp_reg__ \n\t" "st x+, __tmp_reg__ \n\t"
"in __tmp_reg__, __SP_H__ \n\t" "in __tmp_reg__, __SP_H__ \n\t"
"st x+, __tmp_reg__ \n\t" "st x+, __tmp_reg__ \n\t");
);
} }
__attribute__((always_inline)) static inline void __context_restore(void) __attribute__((always_inline)) static inline void __context_restore(void)
{ {
__asm__ volatile( __asm__ volatile (
"lds r26, sched_active_thread \n\t" "lds r26, sched_active_thread \n\t"
"lds r27, sched_active_thread + 1 \n\t" "lds r27, sched_active_thread + 1 \n\t"
"ld r28, x+ \n\t" "ld r28, x+ \n\t"
@ -348,6 +343,5 @@ __attribute__((always_inline)) static inline void __context_restore(void)
#endif #endif
"pop __tmp_reg__ \n\t" "pop __tmp_reg__ \n\t"
"out __SREG__, __tmp_reg__ \n\t" "out __SREG__, __tmp_reg__ \n\t"
"pop __tmp_reg__ \n\t" "pop __tmp_reg__ \n\t");
);
} }