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

cpu/cortexm_common: measure time spent with IRQ disabled

This commit is contained in:
Benjamin Valentin 2022-10-24 22:44:42 +02:00 committed by Benjamin Valentin
parent 8145c42955
commit 59a3e613fe
4 changed files with 70 additions and 4 deletions

View File

@ -35,6 +35,7 @@ extern "C" {
#define MAYBE_INLINE #define MAYBE_INLINE
#endif /* IRQ_API_INLINED */ #endif /* IRQ_API_INLINED */
#ifndef IRQ_API_INLINED
/** /**
* @brief This function sets the IRQ disable bit in the status register * @brief This function sets the IRQ disable bit in the status register
* *
@ -89,7 +90,7 @@ MAYBE_INLINE bool irq_is_enabled(void);
*/ */
MAYBE_INLINE bool irq_is_in(void); MAYBE_INLINE bool irq_is_in(void);
#ifdef IRQ_API_INLINED #else
#include "irq_arch.h" #include "irq_arch.h"
#endif /* IRQ_API_INLINED */ #endif /* IRQ_API_INLINED */

View File

@ -22,11 +22,33 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "cpu_conf.h" #include "cpu_conf.h"
#include "kernel_defines.h"
#include "debug_irq_disable.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/**
* @brief Start SysTick timer to measure time spent with IRQ disabled
*/
static inline void _irq_debug_start_count(void)
{
SysTick->VAL = 0;
SysTick->LOAD = SysTick_LOAD_RELOAD_Msk;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
}
/**
* @brief Stop SysTick timer, return time spent with IRQ disabled
*/
static inline uint32_t _irq_debug_stop_count(void)
{
uint32_t ticks = SysTick_LOAD_RELOAD_Msk - SysTick->VAL;
SysTick->CTRL = 0;
return ticks;
}
/** /**
* @brief Disable all maskable interrupts * @brief Disable all maskable interrupts
*/ */
@ -35,6 +57,10 @@ unsigned int irq_disable(void)
{ {
uint32_t mask = __get_PRIMASK(); uint32_t mask = __get_PRIMASK();
if ((mask == 0) && IS_USED(MODULE_DEBUG_IRQ_DISABLE)) {
_irq_debug_start_count();
}
__disable_irq(); __disable_irq();
return mask; return mask;
} }
@ -55,10 +81,28 @@ unsigned int irq_enable(void)
* @brief Restore the state of the IRQ flags * @brief Restore the state of the IRQ flags
*/ */
static inline __attribute__((always_inline)) static inline __attribute__((always_inline))
#if !IS_USED(MODULE_DEBUG_IRQ_DISABLE)
void irq_restore(unsigned int state) void irq_restore(unsigned int state)
{ {
__set_PRIMASK(state); __set_PRIMASK(state);
} }
#else
void _irq_restore(unsigned int state, const char *file, unsigned line)
{
uint32_t ticks = 0;
if (state == 0) {
ticks = _irq_debug_stop_count();
}
__set_PRIMASK(state);
if (ticks) {
debug_irq_disable_print(file, line, ticks);
}
}
#define irq_restore(state) _irq_restore(state, __FILE__, __LINE__);
#endif /* MODULE_DEBUG_IRQ_DISABLE */
/** /**
* @brief See if IRQs are currently enabled * @brief See if IRQs are currently enabled

View File

@ -19,17 +19,28 @@
#include <stdbool.h> #include <stdbool.h>
#include "fmt.h" #include "fmt.h"
#include "debug_irq_disable.h"
void debug_irq_disable_print(const char *file, unsigned line, uint32_t ticks) void debug_irq_disable_print(const char *file, unsigned line, uint32_t ticks)
{ {
static bool is_printing; static unsigned is_printing;
static unsigned init_skip = 10;
/* if we try to print before libc is initialized, we will hard fault */
if (init_skip && --init_skip) {
return;
}
if (is_printing) { if (is_printing) {
return; return;
} }
if (ticks < CONFIG_DEBUG_IRQ_DISABLE_THRESHOLD) {
return;
}
/* prevent infinite recursion if stdio driver uses irq_disable() */ /* prevent infinite recursion if stdio driver uses irq_disable() */
is_printing = true; ++is_printing;
print_str("irq disabled for "); print_str("irq disabled for ");
print_u32_dec(ticks); print_u32_dec(ticks);
@ -39,5 +50,5 @@ void debug_irq_disable_print(const char *file, unsigned line, uint32_t ticks)
print_u32_dec(line); print_u32_dec(line);
print_str("\n"); print_str("\n");
is_printing = false; --is_printing;
} }

View File

@ -26,6 +26,16 @@
extern "C" { extern "C" {
#endif #endif
/**
* @brief Threshold (in CPU ticks) below which periods with IRQs
* disabled are not printed.
*
* Use this to prevent *a lot* of output when debugging.
*/
#ifndef CONFIG_DEBUG_IRQ_DISABLE_THRESHOLD
#define CONFIG_DEBUG_IRQ_DISABLE_THRESHOLD (1)
#endif
/** /**
* @brief Print time spent with IRQ disabled * @brief Print time spent with IRQ disabled
* @internal * @internal