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)
|
||||
ISR(BAT_LOW_vect, ISR_BLOCK)
|
||||
{
|
||||
__enter_isr();
|
||||
atmega_enter_isr();
|
||||
DEBUG("BAT_LOW\n");
|
||||
__exit_isr();
|
||||
atmega_exit_isr();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -61,35 +61,20 @@ extern "C"
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
static inline void __exit_isr(void)
|
||||
{
|
||||
if (sched_context_switch_request) {
|
||||
thread_yield();
|
||||
__in_isr = 0;
|
||||
thread_yield_isr();
|
||||
}
|
||||
__in_isr = 0;
|
||||
}
|
||||
void atmega_exit_isr(void);
|
||||
|
||||
/**
|
||||
* @brief Initialization of the CPU
|
||||
|
||||
@ -29,12 +29,12 @@
|
||||
/**
|
||||
* @brief Macro returns state of the global interrupt register
|
||||
*/
|
||||
static uint8_t __get_interrupt_state(void);
|
||||
static void __set_interrupt_state(uint8_t state);
|
||||
static uint8_t atmega_get_interrupt_state(void);
|
||||
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;
|
||||
__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);
|
||||
}
|
||||
|
||||
__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"
|
||||
"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)
|
||||
{
|
||||
uint8_t mask = __get_interrupt_state();
|
||||
uint8_t mask = atmega_get_interrupt_state();
|
||||
cli(); /* <-- acts as memory barrier, see doc of avr-libc */
|
||||
return (unsigned int) mask;
|
||||
}
|
||||
@ -70,7 +70,7 @@ unsigned int irq_disable(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 */
|
||||
return mask;
|
||||
}
|
||||
@ -80,7 +80,7 @@ unsigned int irq_enable(void)
|
||||
*/
|
||||
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 result = __in_isr;
|
||||
int result = atmega_in_isr;
|
||||
__asm__ volatile("" ::: "memory");
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -374,16 +374,16 @@ void gpio_irq_disable(gpio_t pin)
|
||||
|
||||
static inline void irq_handler(uint8_t int_num)
|
||||
{
|
||||
__enter_isr();
|
||||
atmega_enter_isr();
|
||||
config[int_num].cb(config[int_num].arg);
|
||||
__exit_isr();
|
||||
atmega_exit_isr();
|
||||
}
|
||||
|
||||
#ifdef PCINT_NUM_BANKS
|
||||
/* inline function that is used by the PCINT ISR */
|
||||
static inline void pcint_handler(uint8_t bank, uint8_t enabled_pcints)
|
||||
{
|
||||
__enter_isr();
|
||||
atmega_enter_isr();
|
||||
/* Find right item */
|
||||
uint8_t idx = 0;
|
||||
|
||||
@ -413,7 +413,7 @@ static inline void pcint_handler(uint8_t bank, uint8_t enabled_pcints)
|
||||
idx++;
|
||||
}
|
||||
|
||||
__exit_isr();
|
||||
atmega_exit_isr();
|
||||
}
|
||||
#if defined(PCINT0_IDX)
|
||||
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);
|
||||
#endif
|
||||
|
||||
__enter_isr();
|
||||
atmega_enter_isr();
|
||||
|
||||
*ctx[tim].mask &= ~(1 << (chan + OCIE1A));
|
||||
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);
|
||||
#endif
|
||||
|
||||
__exit_isr();
|
||||
atmega_exit_isr();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -186,11 +186,11 @@ void uart_poweroff(uart_t uart)
|
||||
|
||||
static inline void isr_handler(int num)
|
||||
{
|
||||
__enter_isr();
|
||||
atmega_enter_isr();
|
||||
|
||||
isr_ctx[num].rx_cb(isr_ctx[num].arg, dev[num]->DR);
|
||||
|
||||
__exit_isr();
|
||||
atmega_exit_isr();
|
||||
}
|
||||
|
||||
#ifdef UART_0_ISR
|
||||
|
||||
@ -30,16 +30,13 @@
|
||||
#include "cpu.h"
|
||||
#include "board.h"
|
||||
|
||||
/*
|
||||
* local function declarations (prefixed with __)
|
||||
*/
|
||||
static void __context_save(void);
|
||||
static void __context_restore(void);
|
||||
static void __enter_thread_mode(void);
|
||||
static void atmega_context_save(void);
|
||||
static void atmega_context_restore(void);
|
||||
static void atmega_enter_thread_mode(void);
|
||||
|
||||
/**
|
||||
* @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:
|
||||
* ---------------thread_t (not created by thread_stack_init) ----------
|
||||
* 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
|
||||
* 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
|
||||
* (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
|
||||
* -----------------------------------------------------------------------
|
||||
*
|
||||
* 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
|
||||
* it inside of the program counter of the MCU.
|
||||
* 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)
|
||||
{
|
||||
sched_run();
|
||||
__enter_thread_mode();
|
||||
atmega_enter_thread_mode();
|
||||
}
|
||||
|
||||
#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
|
||||
*/
|
||||
void NORETURN __enter_thread_mode(void)
|
||||
void NORETURN atmega_enter_thread_mode(void)
|
||||
{
|
||||
irq_enable();
|
||||
|
||||
@ -229,7 +226,7 @@ void NORETURN __enter_thread_mode(void)
|
||||
__brkval = __malloc_heap_start;
|
||||
}
|
||||
|
||||
__context_restore();
|
||||
atmega_context_restore();
|
||||
__asm__ volatile ("ret");
|
||||
|
||||
UNREACHABLE();
|
||||
@ -238,9 +235,9 @@ void NORETURN __enter_thread_mode(void)
|
||||
void thread_yield_higher(void)
|
||||
{
|
||||
if (irq_is_in() == 0) {
|
||||
__context_save();
|
||||
atmega_context_save();
|
||||
sched_run();
|
||||
__context_restore();
|
||||
atmega_context_restore();
|
||||
__asm__ volatile ("ret");
|
||||
}
|
||||
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();
|
||||
__context_restore();
|
||||
atmega_context_restore();
|
||||
|
||||
__asm__ volatile ("reti");
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void __context_save(void)
|
||||
__attribute__((always_inline)) static inline void atmega_context_save(void)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"push __tmp_reg__ \n\t"
|
||||
@ -312,7 +310,7 @@ __attribute__((always_inline)) static inline void __context_save(void)
|
||||
"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 (
|
||||
"lds r26, sched_active_thread \n\t"
|
||||
|
||||
@ -732,7 +732,7 @@ static void _isr(netdev_t *netdev)
|
||||
*/
|
||||
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;
|
||||
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 */
|
||||
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)
|
||||
{
|
||||
__enter_isr();
|
||||
atmega_enter_isr();
|
||||
|
||||
DEBUG("TRX24_XAH_AMI\n");
|
||||
((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)
|
||||
{
|
||||
__enter_isr();
|
||||
atmega_enter_isr();
|
||||
|
||||
at86rf2xx_t *dev = (at86rf2xx_t *) at86rfmega_dev;
|
||||
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);
|
||||
}
|
||||
|
||||
__exit_isr();
|
||||
atmega_exit_isr();
|
||||
}
|
||||
|
||||
#endif /* MODULE_AT86RFA1 || MODULE_AT86RFR2 */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user