1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

cpu/avr8_common: Rework avr8_state variable

The avr8_state variable uses bit operation to set/clear the state. This
rework avr8_state to use increment/decrement instead. It introduce the
use of General Purpose IO Register 1 (GPIOR1) when available.

This is a preparation for future scheduling and irq optimizations.

Signed-off-by: Gerson Fernando Budke <nandojve@gmail.com>
This commit is contained in:
Gerson Fernando Budke 2023-06-27 22:41:18 +02:00
parent b7873015aa
commit 93aa10cc5c
5 changed files with 48 additions and 63 deletions

View File

@ -68,7 +68,9 @@
*/
uint8_t mcusr_mirror __attribute__((section(".noinit")));
uint8_t soft_rst __attribute__((section(".noinit")));
uint8_t avr8_state = 0;
#if (AVR8_STATE_IRQ_USE_SRAM)
uint8_t avr8_state_irq_count_sram = 0;
#endif
#if (AVR8_STATE_UART_USE_SRAM)
uint8_t avr8_state_uart_sram = 0;
#endif
@ -123,6 +125,7 @@ void cpu_init(void)
/* Set global resources initial state */
avr8_state_uart = 0;
avr8_state_irq_count = 0;
irq_enable();
}

View File

@ -58,61 +58,6 @@ extern "C"
#define PERIPH_I2C_NEED_WRITE_REGS
/** @} */
/**
* @name Flags for the current state of the ATmega MCU
* @{
*/
#define AVR8_STATE_FLAG_ISR (0x80U) /**< In ISR */
/** @} */
/**
* @brief Global variable containing the current state of the MCU
*
* @note This variable is updated from IRQ context; access to it should
* be wrapped into @ref irq_disable and @ref irq_restore or
* @ref avr8_get_state should be used.
*
* Contents:
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 7 6 5 4 3 2 1 0
* +---+---+---+---+---+---+---+---+
* |IRQ| RESERVED |
* +---+---+---+---+---+---+---+---+
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* | Label | Description |
* |:-------|:--------------------------------------------------------------|
* | IRQ | This bit is set when in IRQ context |
*/
extern uint8_t avr8_state;
/**
* @brief Atomically read the state (@ref avr8_state)
*
* This function guarantees that the read is not optimized out, not reordered
* and done atomically. This does not mean that by the time return value is
* processed that it still reflects the value currently stored in
* @ref avr8_state.
*
* Using ASM rather than C11 atomics has less overhead, as not every access to
* the state has to be performed atomically: Those done from ISR will not be
* interrupted (no support for nested interrupts) and barriers at the begin and
* end of the ISRs make sure the access takes place before IRQ context is left.
*/
static inline uint8_t avr8_get_state(void)
{
uint8_t state;
__asm__ volatile(
"lds %[state], avr8_state \n\t"
: [state] "=r" (state)
:
: "memory"
);
return state;
}
/**
* @brief Run this code on entering interrupt routines
*/
@ -122,7 +67,7 @@ static inline void avr8_enter_isr(void)
* supported as of now. The flag will be unset before the IRQ context is
* left, so no need to use memory barriers or atomics here
*/
avr8_state |= AVR8_STATE_FLAG_ISR;
++avr8_state_irq_count;
}
/**

View File

@ -2,7 +2,7 @@
* Copyright (C) 2014 Freie Universität Berlin, Hinnerk van Bruinehsen
* 2018 RWTH Aachen, Josua Arndt <jarndt@ias.rwth-aachen.de>
* 2020 Otto-von-Guericke-Universität Magdeburg
* 2021 Gerson Fernando Budke
* 2021-2023 Gerson Fernando Budke
*
* 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
@ -100,8 +100,11 @@ __attribute__((always_inline)) static inline void irq_restore(unsigned int _stat
*/
__attribute__((always_inline)) static inline bool irq_is_in(void)
{
uint8_t state = avr8_get_state();
return (state & AVR8_STATE_FLAG_ISR);
bool is_in = avr8_state_irq_count > 0;
__asm__ volatile ("" : : : "memory");
return is_in;
}
/**

View File

@ -72,6 +72,39 @@ extern uint8_t avr8_state_uart_sram; /**< UART state variable. */
#endif
/** @} */
/**
* @name Internal flag which defines if IRQ state is stored on SRAM
* @{
*/
#ifdef GPIOR1
#define AVR8_STATE_IRQ_USE_SRAM 0 /**< IRQ state using GPIOR registers. */
#else
#define AVR8_STATE_IRQ_USE_SRAM 1 /**< IRQ state using GPIOR registers. */
#endif
/** @} */
/**
* @name Global variable containing the current state of the MCU
* @{
*
* @note This variable is updated from IRQ context; access to it should
* be wrapped into @ref irq_disable and @ref irq_restore should be
* used.
*
* Contents:
*
* | Label | Description |
* |:-------|:--------------------------------------------------------------|
* | IRQ | This variable is incremented when in IRQ context |
*/
#if (AVR8_STATE_IRQ_USE_SRAM)
extern uint8_t avr8_state_irq_count_sram; /**< IRQ state variable. */
#define avr8_state_irq_count avr8_state_irq_count_sram /**< Definition for SRAM. */
#else
#define avr8_state_irq_count GPIOR1 /**< Definition for GPIOR1. */
#endif
/** @} */
#ifdef __cplusplus
}
#endif

View File

@ -2,7 +2,7 @@
* Copyright (C) 2014 Freie Universität Berlin, Hinnerk van Bruinehsen
* 2017 Thomas Perrot <thomas.perrot@tupi.fr>
* 2018 RWTH Aachen, Josua Arndt <jarndt@ias.rwth-aachen.de>
* 2021 Gerson Fernando Budke <nandojve@gmail.com>
* 2021-2023 Gerson Fernando Budke <nandojve@gmail.com>
*
* 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
@ -273,12 +273,13 @@ void thread_yield_higher(void)
void avr8_exit_isr(void)
{
avr8_state &= ~AVR8_STATE_FLAG_ISR;
--avr8_state_irq_count;
/* Force access to avr8_state to take place */
__asm__ volatile ("" : : : "memory");
if (sched_context_switch_request) {
/* schedule should switch context when returning from a non nested interrupt */
if (sched_context_switch_request && avr8_state_irq_count == 0) {
avr8_context_save();
sched_run();
avr8_context_restore();