Merge pull request #8988 from Josar/atmega_isr
cpu/atmega_common: __exit_isr thread_yield
This commit is contained in:
commit
f0dce1b920
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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 */
|
||||||
|
|||||||
@ -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");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user