Merge pull request #12790 from maribu/atmega_isr_thread
cpu/atmega_common
This commit is contained in:
commit
41e29e3fda
@ -173,8 +173,8 @@ ISR(BADISR_vect)
|
|||||||
#if defined(CPU_ATMEGA128RFA1) || defined (CPU_ATMEGA256RFR2)
|
#if defined(CPU_ATMEGA128RFA1) || defined (CPU_ATMEGA256RFR2)
|
||||||
ISR(BAT_LOW_vect, ISR_BLOCK)
|
ISR(BAT_LOW_vect, ISR_BLOCK)
|
||||||
{
|
{
|
||||||
__enter_isr();
|
atmega_enter_isr();
|
||||||
DEBUG("BAT_LOW\n");
|
DEBUG("BAT_LOW\n");
|
||||||
__exit_isr();
|
atmega_exit_isr();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -61,35 +61,20 @@ extern "C"
|
|||||||
/**
|
/**
|
||||||
* @brief global in-ISR state variable
|
* @brief global in-ISR state variable
|
||||||
*/
|
*/
|
||||||
extern volatile uint8_t __in_isr;
|
extern volatile uint8_t atmega_in_isr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Run this code on entering interrupt routines
|
* @brief Run this code on entering interrupt routines
|
||||||
*/
|
*/
|
||||||
static inline void __enter_isr(void)
|
static inline void atmega_enter_isr(void)
|
||||||
{
|
{
|
||||||
__in_isr = 1;
|
atmega_in_isr = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @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
|
* @brief Run this code on exiting interrupt routines
|
||||||
*/
|
*/
|
||||||
static inline void __exit_isr(void)
|
void atmega_exit_isr(void);
|
||||||
{
|
|
||||||
if (sched_context_switch_request) {
|
|
||||||
thread_yield();
|
|
||||||
__in_isr = 0;
|
|
||||||
thread_yield_isr();
|
|
||||||
}
|
|
||||||
__in_isr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialization of the CPU
|
* @brief Initialization of the CPU
|
||||||
|
|||||||
@ -29,12 +29,12 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Macro returns state of the global interrupt register
|
* @brief Macro returns state of the global interrupt register
|
||||||
*/
|
*/
|
||||||
static uint8_t __get_interrupt_state(void);
|
static uint8_t atmega_get_interrupt_state(void);
|
||||||
static void __set_interrupt_state(uint8_t state);
|
static void atmega_set_interrupt_state(uint8_t state);
|
||||||
|
|
||||||
volatile uint8_t __in_isr = 0;
|
volatile uint8_t atmega_in_isr = 0;
|
||||||
|
|
||||||
__attribute__((always_inline)) static inline uint8_t __get_interrupt_state(void)
|
__attribute__((always_inline)) static inline uint8_t atmega_get_interrupt_state(void)
|
||||||
{
|
{
|
||||||
uint8_t sreg;
|
uint8_t sreg;
|
||||||
__asm__ volatile( "in __tmp_reg__, __SREG__ \n\t"
|
__asm__ volatile( "in __tmp_reg__, __SREG__ \n\t"
|
||||||
@ -43,7 +43,7 @@ __attribute__((always_inline)) static inline uint8_t __get_interrupt_state(void
|
|||||||
return sreg & (1 << 7);
|
return sreg & (1 << 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((always_inline)) inline void __set_interrupt_state(uint8_t state)
|
__attribute__((always_inline)) inline void atmega_set_interrupt_state(uint8_t state)
|
||||||
{
|
{
|
||||||
__asm__ volatile( "mov r15,%0 \n\t"
|
__asm__ volatile( "mov r15,%0 \n\t"
|
||||||
"in r16, __SREG__ \n\t"
|
"in r16, __SREG__ \n\t"
|
||||||
@ -60,7 +60,7 @@ __attribute__((always_inline)) inline void __set_interrupt_state(uint8_t state)
|
|||||||
*/
|
*/
|
||||||
unsigned int irq_disable(void)
|
unsigned int irq_disable(void)
|
||||||
{
|
{
|
||||||
uint8_t mask = __get_interrupt_state();
|
uint8_t mask = atmega_get_interrupt_state();
|
||||||
cli(); /* <-- acts as memory barrier, see doc of avr-libc */
|
cli(); /* <-- acts as memory barrier, see doc of avr-libc */
|
||||||
return (unsigned int) mask;
|
return (unsigned int) mask;
|
||||||
}
|
}
|
||||||
@ -70,7 +70,7 @@ unsigned int irq_disable(void)
|
|||||||
*/
|
*/
|
||||||
unsigned int irq_enable(void)
|
unsigned int irq_enable(void)
|
||||||
{
|
{
|
||||||
uint8_t mask = __get_interrupt_state();
|
uint8_t mask = atmega_get_interrupt_state();
|
||||||
sei(); /* <-- acts as memory barrier, see doc of avr-libc */
|
sei(); /* <-- acts as memory barrier, see doc of avr-libc */
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ unsigned int irq_enable(void)
|
|||||||
*/
|
*/
|
||||||
void irq_restore(unsigned int state)
|
void irq_restore(unsigned int state)
|
||||||
{
|
{
|
||||||
__set_interrupt_state(state);
|
atmega_set_interrupt_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,7 +88,7 @@ void irq_restore(unsigned int state)
|
|||||||
*/
|
*/
|
||||||
int irq_is_in(void)
|
int irq_is_in(void)
|
||||||
{
|
{
|
||||||
int result = __in_isr;
|
int result = atmega_in_isr;
|
||||||
__asm__ volatile("" ::: "memory");
|
__asm__ volatile("" ::: "memory");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -374,16 +374,16 @@ void gpio_irq_disable(gpio_t pin)
|
|||||||
|
|
||||||
static inline void irq_handler(uint8_t int_num)
|
static inline void irq_handler(uint8_t int_num)
|
||||||
{
|
{
|
||||||
__enter_isr();
|
atmega_enter_isr();
|
||||||
config[int_num].cb(config[int_num].arg);
|
config[int_num].cb(config[int_num].arg);
|
||||||
__exit_isr();
|
atmega_exit_isr();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PCINT_NUM_BANKS
|
#ifdef PCINT_NUM_BANKS
|
||||||
/* inline function that is used by the PCINT ISR */
|
/* inline function that is used by the PCINT ISR */
|
||||||
static inline void pcint_handler(uint8_t bank, uint8_t enabled_pcints)
|
static inline void pcint_handler(uint8_t bank, uint8_t enabled_pcints)
|
||||||
{
|
{
|
||||||
__enter_isr();
|
atmega_enter_isr();
|
||||||
/* Find right item */
|
/* Find right item */
|
||||||
uint8_t idx = 0;
|
uint8_t idx = 0;
|
||||||
|
|
||||||
@ -413,7 +413,7 @@ static inline void pcint_handler(uint8_t bank, uint8_t enabled_pcints)
|
|||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
__exit_isr();
|
atmega_exit_isr();
|
||||||
}
|
}
|
||||||
#if defined(PCINT0_IDX)
|
#if defined(PCINT0_IDX)
|
||||||
ISR(PCINT0_vect, ISR_BLOCK)
|
ISR(PCINT0_vect, ISR_BLOCK)
|
||||||
|
|||||||
@ -176,7 +176,7 @@ static inline void _isr(tim_t tim, int chan)
|
|||||||
DEBUG_TIMER_PORT |= (1 << DEBUG_TIMER_PIN);
|
DEBUG_TIMER_PORT |= (1 << DEBUG_TIMER_PIN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__enter_isr();
|
atmega_enter_isr();
|
||||||
|
|
||||||
*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);
|
||||||
@ -185,7 +185,7 @@ static inline void _isr(tim_t tim, int chan)
|
|||||||
DEBUG_TIMER_PORT &= ~(1 << DEBUG_TIMER_PIN);
|
DEBUG_TIMER_PORT &= ~(1 << DEBUG_TIMER_PIN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__exit_isr();
|
atmega_exit_isr();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -186,11 +186,11 @@ void uart_poweroff(uart_t uart)
|
|||||||
|
|
||||||
static inline void isr_handler(int num)
|
static inline void isr_handler(int num)
|
||||||
{
|
{
|
||||||
__enter_isr();
|
atmega_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);
|
||||||
|
|
||||||
__exit_isr();
|
atmega_exit_isr();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef UART_0_ISR
|
#ifdef UART_0_ISR
|
||||||
|
|||||||
@ -30,16 +30,13 @@
|
|||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
|
|
||||||
/*
|
static void atmega_context_save(void);
|
||||||
* local function declarations (prefixed with __)
|
static void atmega_context_restore(void);
|
||||||
*/
|
static void atmega_enter_thread_mode(void);
|
||||||
static void __context_save(void);
|
|
||||||
static void __context_restore(void);
|
|
||||||
static void __enter_thread_mode(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Since AVR doesn't support direct manipulation of the program counter we
|
* @brief Since AVR doesn't support direct manipulation of the program counter we
|
||||||
* model a stack like it would be left by __context_save().
|
* model a stack like it would be left by atmega_context_save().
|
||||||
* The resulting layout in memory is the following:
|
* The resulting layout in memory is the following:
|
||||||
* ---------------thread_t (not created by thread_stack_init) ----------
|
* ---------------thread_t (not created by thread_stack_init) ----------
|
||||||
* local variables (a temporary value and the stackpointer)
|
* local variables (a temporary value and the stackpointer)
|
||||||
@ -51,7 +48,7 @@ static void __enter_thread_mode(void);
|
|||||||
* -----------------------------------------------------------------------
|
* -----------------------------------------------------------------------
|
||||||
* a 16 Bit pointer to task_func
|
* a 16 Bit pointer to task_func
|
||||||
* this is placed exactly at the place where the program counter would be
|
* this is placed exactly at the place where the program counter would be
|
||||||
* stored normally and thus can be returned to when __context_restore()
|
* stored normally and thus can be returned to when atmega_context_restore()
|
||||||
* has been run
|
* has been run
|
||||||
* (Optional 17 bit (bit is set to zero) for devices with > 128kb FLASH)
|
* (Optional 17 bit (bit is set to zero) for devices with > 128kb FLASH)
|
||||||
* -----------------------------------------------------------------------
|
* -----------------------------------------------------------------------
|
||||||
@ -64,7 +61,7 @@ static void __enter_thread_mode(void);
|
|||||||
* r26 - r31
|
* r26 - r31
|
||||||
* -----------------------------------------------------------------------
|
* -----------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* After the invocation of __context_restore() the pointer to task_func is
|
* After the invocation of atmega_context_restore() the pointer to task_func is
|
||||||
* on top of the stack and can be returned to. This way we can actually place
|
* on top of the stack and can be returned to. This way we can actually place
|
||||||
* it inside of the program counter of the MCU.
|
* it inside of the program counter of the MCU.
|
||||||
* if task_func returns sched_task_exit gets popped into the PC
|
* if task_func returns sched_task_exit gets popped into the PC
|
||||||
@ -201,7 +198,7 @@ void thread_stack_print(void)
|
|||||||
void cpu_switch_context_exit(void)
|
void cpu_switch_context_exit(void)
|
||||||
{
|
{
|
||||||
sched_run();
|
sched_run();
|
||||||
__enter_thread_mode();
|
atmega_enter_thread_mode();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define STACK_POINTER ((char *)AVR_STACK_POINTER_REG)
|
#define STACK_POINTER ((char *)AVR_STACK_POINTER_REG)
|
||||||
@ -213,7 +210,7 @@ extern char *__brkval;
|
|||||||
/**
|
/**
|
||||||
* @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)
|
void NORETURN atmega_enter_thread_mode(void)
|
||||||
{
|
{
|
||||||
irq_enable();
|
irq_enable();
|
||||||
|
|
||||||
@ -229,7 +226,7 @@ void NORETURN __enter_thread_mode(void)
|
|||||||
__brkval = __malloc_heap_start;
|
__brkval = __malloc_heap_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
__context_restore();
|
atmega_context_restore();
|
||||||
__asm__ volatile ("ret");
|
__asm__ volatile ("ret");
|
||||||
|
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@ -238,9 +235,9 @@ void NORETURN __enter_thread_mode(void)
|
|||||||
void thread_yield_higher(void)
|
void thread_yield_higher(void)
|
||||||
{
|
{
|
||||||
if (irq_is_in() == 0) {
|
if (irq_is_in() == 0) {
|
||||||
__context_save();
|
atmega_context_save();
|
||||||
sched_run();
|
sched_run();
|
||||||
__context_restore();
|
atmega_context_restore();
|
||||||
__asm__ volatile ("ret");
|
__asm__ volatile ("ret");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -248,16 +245,17 @@ void thread_yield_higher(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread_yield_isr(void)
|
void atmega_exit_isr(void)
|
||||||
{
|
{
|
||||||
__context_save();
|
atmega_in_isr = 0;
|
||||||
|
atmega_context_save();
|
||||||
sched_run();
|
sched_run();
|
||||||
__context_restore();
|
atmega_context_restore();
|
||||||
|
|
||||||
__asm__ volatile ("reti");
|
__asm__ volatile ("reti");
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((always_inline)) static inline void __context_save(void)
|
__attribute__((always_inline)) static inline void atmega_context_save(void)
|
||||||
{
|
{
|
||||||
__asm__ volatile (
|
__asm__ volatile (
|
||||||
"push __tmp_reg__ \n\t"
|
"push __tmp_reg__ \n\t"
|
||||||
@ -312,7 +310,7 @@ __attribute__((always_inline)) static inline void __context_save(void)
|
|||||||
"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 atmega_context_restore(void)
|
||||||
{
|
{
|
||||||
__asm__ volatile (
|
__asm__ volatile (
|
||||||
"lds r26, sched_active_thread \n\t"
|
"lds r26, sched_active_thread \n\t"
|
||||||
|
|||||||
@ -732,7 +732,7 @@ static void _isr(netdev_t *netdev)
|
|||||||
*/
|
*/
|
||||||
ISR(TRX24_RX_END_vect, ISR_BLOCK)
|
ISR(TRX24_RX_END_vect, ISR_BLOCK)
|
||||||
{
|
{
|
||||||
__enter_isr();
|
atmega_enter_isr();
|
||||||
|
|
||||||
uint8_t status = *AT86RF2XX_REG__TRX_STATE & AT86RF2XX_TRX_STATUS_MASK__TRX_STATUS;
|
uint8_t status = *AT86RF2XX_REG__TRX_STATE & AT86RF2XX_TRX_STATUS_MASK__TRX_STATUS;
|
||||||
DEBUG("TRX24_RX_END 0x%x\n", status);
|
DEBUG("TRX24_RX_END 0x%x\n", status);
|
||||||
@ -741,7 +741,7 @@ ISR(TRX24_RX_END_vect, ISR_BLOCK)
|
|||||||
/* Call upper layer to process received data */
|
/* Call upper layer to process received data */
|
||||||
at86rfmega_dev->event_callback(at86rfmega_dev, NETDEV_EVENT_ISR);
|
at86rfmega_dev->event_callback(at86rfmega_dev, NETDEV_EVENT_ISR);
|
||||||
|
|
||||||
__exit_isr();
|
atmega_exit_isr();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -754,12 +754,12 @@ ISR(TRX24_RX_END_vect, ISR_BLOCK)
|
|||||||
*/
|
*/
|
||||||
ISR(TRX24_XAH_AMI_vect, ISR_BLOCK)
|
ISR(TRX24_XAH_AMI_vect, ISR_BLOCK)
|
||||||
{
|
{
|
||||||
__enter_isr();
|
atmega_enter_isr();
|
||||||
|
|
||||||
DEBUG("TRX24_XAH_AMI\n");
|
DEBUG("TRX24_XAH_AMI\n");
|
||||||
((at86rf2xx_t *)at86rfmega_dev)->irq_status |= AT86RF2XX_IRQ_STATUS_MASK__AMI;
|
((at86rf2xx_t *)at86rfmega_dev)->irq_status |= AT86RF2XX_IRQ_STATUS_MASK__AMI;
|
||||||
|
|
||||||
__exit_isr();
|
atmega_exit_isr();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -771,7 +771,7 @@ ISR(TRX24_XAH_AMI_vect, ISR_BLOCK)
|
|||||||
*/
|
*/
|
||||||
ISR(TRX24_TX_END_vect, ISR_BLOCK)
|
ISR(TRX24_TX_END_vect, ISR_BLOCK)
|
||||||
{
|
{
|
||||||
__enter_isr();
|
atmega_enter_isr();
|
||||||
|
|
||||||
at86rf2xx_t *dev = (at86rf2xx_t *) at86rfmega_dev;
|
at86rf2xx_t *dev = (at86rf2xx_t *) at86rfmega_dev;
|
||||||
uint8_t status = *AT86RF2XX_REG__TRX_STATE & AT86RF2XX_TRX_STATUS_MASK__TRX_STATUS;
|
uint8_t status = *AT86RF2XX_REG__TRX_STATE & AT86RF2XX_TRX_STATUS_MASK__TRX_STATUS;
|
||||||
@ -786,7 +786,7 @@ ISR(TRX24_TX_END_vect, ISR_BLOCK)
|
|||||||
at86rfmega_dev->event_callback(at86rfmega_dev, NETDEV_EVENT_ISR);
|
at86rfmega_dev->event_callback(at86rfmega_dev, NETDEV_EVENT_ISR);
|
||||||
}
|
}
|
||||||
|
|
||||||
__exit_isr();
|
atmega_exit_isr();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* MODULE_AT86RFA1 || MODULE_AT86RFR2 */
|
#endif /* MODULE_AT86RFA1 || MODULE_AT86RFR2 */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user