/* * Copyright (C) 2014 Freie Universität Berlin, Hinnerk van Bruinehsen * 2018 RWTH Aachen, Josua Arndt * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level * directory for more details. */ /** * @ingroup cpu_atmega_common * @{ * * @file * @brief Implementation of the kernels irq interface * * @author Hauke Petersen * @author Hinnerk van Bruinehsen * @author Josua Arndt * * @} */ #include #include #include "irq.h" #include "cpu.h" /** * @brief Macro returns state of the global interrupt register */ static uint8_t __get_interrupt_state(void); static void __set_interrupt_state(uint8_t state); volatile uint8_t __in_isr = 0; __attribute__((always_inline)) static inline uint8_t __get_interrupt_state(void) { uint8_t sreg; __asm__ volatile( "in __tmp_reg__, __SREG__ \n\t" "mov %0, __tmp_reg__ \n\t" : "=g"(sreg) ); return sreg & (1 << 7); } __attribute__((always_inline)) inline void __set_interrupt_state(uint8_t state) { __asm__ volatile( "mov r15,%0 \n\t" "in r16, __SREG__ \n\t" "cbr r16,7 \n\t" "or r15,r16 \n\t" "out __SREG__, r15 \n\t" : : "g"(state) : "r15", "r16"); } /** * @brief Disable all maskable interrupts */ unsigned int irq_disable(void) { uint8_t mask = __get_interrupt_state(); cli(); return (unsigned int) mask; } /** * @brief Enable all maskable interrupts */ unsigned int irq_enable(void) { sei(); return __get_interrupt_state(); } /** * @brief Restore the state of the IRQ flags */ void irq_restore(unsigned int state) { __set_interrupt_state(state); } /** * @brief See if the current context is inside an ISR */ int irq_is_in(void) { return __in_isr; }