Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Furi: count ISR time. Cli: show ISR time in top. #3751

Merged
merged 4 commits into from
Jul 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion applications/services/cli/cli_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,8 +399,9 @@ static void cli_command_top(Cli* cli, FuriString* args, void* context) {

uint32_t uptime = tick / furi_kernel_get_tick_frequency();
printf(
"Threads: %zu, Uptime: %luh%lum%lus\r\n",
"Threads: %zu, ISR Time: %0.2f%%, Uptime: %luh%lum%lus\r\n",
furi_thread_list_size(thread_list),
(double)furi_thread_list_get_isr_time(thread_list),
uptime / 60 / 60,
uptime / 60 % 60,
uptime % 60);
Expand Down
4 changes: 2 additions & 2 deletions furi/core/common_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ extern "C" {
#define FURI_PACKED __attribute__((packed))
#endif

#ifndef FURI_ALWAYS_STATIC_INLINE
#define FURI_ALWAYS_STATIC_INLINE __attribute__((always_inline)) static inline
#ifndef FURI_ALWAYS_INLINE
#define FURI_ALWAYS_INLINE __attribute__((always_inline)) inline
#endif

#ifndef FURI_IS_IRQ_MASKED
Expand Down
16 changes: 15 additions & 1 deletion furi/core/thread_list.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "thread_list.h"
#include "check.h"

#include <furi_hal_interrupt.h>

#include <m-array.h>
#include <m-dict.h>

Expand All @@ -23,6 +25,8 @@ struct FuriThreadList {
FuriThreadListItemDict_t search;
uint32_t runtime_previous;
uint32_t runtime_current;
uint32_t isr_previous;
uint32_t isr_current;
};

FuriThreadList* furi_thread_list_alloc(void) {
Expand Down Expand Up @@ -85,7 +89,10 @@ void furi_thread_list_process(FuriThreadList* instance, uint32_t runtime, uint32
instance->runtime_previous = instance->runtime_current;
instance->runtime_current = runtime;

uint32_t runtime_counter = instance->runtime_current - instance->runtime_previous;
instance->isr_previous = instance->isr_current;
instance->isr_current = furi_hal_interrupt_get_time_in_isr_total();

const uint32_t runtime_counter = instance->runtime_current - instance->runtime_previous;

FuriThreadListItemArray_it_t it;
FuriThreadListItemArray_it(it, instance->items);
Expand All @@ -108,3 +115,10 @@ void furi_thread_list_process(FuriThreadList* instance, uint32_t runtime, uint32
}
}
}

float furi_thread_list_get_isr_time(FuriThreadList* instance) {
const uint32_t runtime_counter = instance->runtime_current - instance->runtime_previous;
const uint32_t isr_counter = instance->isr_current - instance->isr_previous;

return (float)isr_counter / (float)runtime_counter;
}
8 changes: 8 additions & 0 deletions furi/core/thread_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ FuriThreadListItem* furi_thread_list_get_or_insert(FuriThreadList* instance, Fur
*/
void furi_thread_list_process(FuriThreadList* instance, uint32_t runtime, uint32_t tick);

/** Get percent of time spent in ISR
*
* @param instance The instance
*
* @return percent of time spent in ISR
*/
float furi_thread_list_get_isr_time(FuriThreadList* instance);

#ifdef __cplusplus
}
#endif
4 changes: 3 additions & 1 deletion targets/f18/api_symbols.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,68.0,,
Version,+,68.1,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
Header,+,applications/services/cli/cli.h,,
Expand Down Expand Up @@ -1288,6 +1288,7 @@ Function,+,furi_hal_info_get_api_version,void,"uint16_t*, uint16_t*"
Function,-,furi_hal_init,void,
Function,-,furi_hal_init_early,void,
Function,+,furi_hal_interrupt_get_name,const char*,uint8_t
Function,+,furi_hal_interrupt_get_time_in_isr_total,uint32_t,
Function,-,furi_hal_interrupt_init,void,
Function,+,furi_hal_interrupt_set_isr,void,"FuriHalInterruptId, FuriHalInterruptISR, void*"
Function,+,furi_hal_interrupt_set_isr_ex,void,"FuriHalInterruptId, FuriHalInterruptPriority, FuriHalInterruptISR, void*"
Expand Down Expand Up @@ -1633,6 +1634,7 @@ Function,+,furi_thread_join,_Bool,FuriThread*
Function,+,furi_thread_list_alloc,FuriThreadList*,
Function,+,furi_thread_list_free,void,FuriThreadList*
Function,+,furi_thread_list_get_at,FuriThreadListItem*,"FuriThreadList*, size_t"
Function,+,furi_thread_list_get_isr_time,float,FuriThreadList*
Function,+,furi_thread_list_get_or_insert,FuriThreadListItem*,"FuriThreadList*, FuriThread*"
Function,+,furi_thread_list_process,void,"FuriThreadList*, uint32_t, uint32_t"
Function,+,furi_thread_list_size,size_t,FuriThreadList*
Expand Down
4 changes: 3 additions & 1 deletion targets/f7/api_symbols.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,68.0,,
Version,+,68.1,,
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
Expand Down Expand Up @@ -1413,6 +1413,7 @@ Function,+,furi_hal_infrared_set_tx_output,void,FuriHalInfraredTxPin
Function,-,furi_hal_init,void,
Function,-,furi_hal_init_early,void,
Function,+,furi_hal_interrupt_get_name,const char*,uint8_t
Function,+,furi_hal_interrupt_get_time_in_isr_total,uint32_t,
Function,-,furi_hal_interrupt_init,void,
Function,+,furi_hal_interrupt_set_isr,void,"FuriHalInterruptId, FuriHalInterruptISR, void*"
Function,+,furi_hal_interrupt_set_isr_ex,void,"FuriHalInterruptId, FuriHalInterruptPriority, FuriHalInterruptISR, void*"
Expand Down Expand Up @@ -1847,6 +1848,7 @@ Function,+,furi_thread_join,_Bool,FuriThread*
Function,+,furi_thread_list_alloc,FuriThreadList*,
Function,+,furi_thread_list_free,void,FuriThreadList*
Function,+,furi_thread_list_get_at,FuriThreadListItem*,"FuriThreadList*, size_t"
Function,+,furi_thread_list_get_isr_time,float,FuriThreadList*
Function,+,furi_thread_list_get_or_insert,FuriThreadListItem*,"FuriThreadList*, FuriThread*"
Function,+,furi_thread_list_process,void,"FuriThreadList*, uint32_t, uint32_t"
Function,+,furi_thread_list_size,size_t,FuriThreadList*
Expand Down
2 changes: 1 addition & 1 deletion targets/f7/furi_hal/furi_hal_gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ void furi_hal_gpio_remove_int_callback(const GpioPin* gpio) {
FURI_CRITICAL_EXIT();
}

FURI_ALWAYS_STATIC_INLINE void furi_hal_gpio_int_call(uint16_t pin_num) {
FURI_ALWAYS_INLINE static void furi_hal_gpio_int_call(uint16_t pin_num) {
if(gpio_interrupt[pin_num].callback) {
gpio_interrupt[pin_num].callback(gpio_interrupt[pin_num].context);
}
Expand Down
53 changes: 41 additions & 12 deletions targets/f7/furi_hal/furi_hal_interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,22 @@

#define FURI_HAL_INTERRUPT_DEFAULT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 5)

#define FURI_HAL_INTERRUPT_ACCOUNT_START() const uint32_t _isr_start = DWT->CYCCNT;
#define FURI_HAL_INTERRUPT_ACCOUNT_END() \
const uint32_t _time_in_isr = DWT->CYCCNT - _isr_start; \
furi_hal_interrupt.counter_time_in_isr_total += _time_in_isr;

typedef struct {
FuriHalInterruptISR isr;
void* context;
} FuriHalInterruptISRPair;

FuriHalInterruptISRPair furi_hal_interrupt_isr[FuriHalInterruptIdMax] = {0};
typedef struct {
FuriHalInterruptISRPair isr[FuriHalInterruptIdMax];
uint32_t counter_time_in_isr_total;
} FuriHalIterrupt;

static FuriHalIterrupt furi_hal_interrupt = {};

const IRQn_Type furi_hal_interrupt_irqn[FuriHalInterruptIdMax] = {
// TIM1, TIM16, TIM17
Expand Down Expand Up @@ -67,32 +77,36 @@ const IRQn_Type furi_hal_interrupt_irqn[FuriHalInterruptIdMax] = {
[FuriHalInterruptIdLpUart1] = LPUART1_IRQn,
};

FURI_ALWAYS_STATIC_INLINE void furi_hal_interrupt_call(FuriHalInterruptId index) {
furi_check(furi_hal_interrupt_isr[index].isr);
furi_hal_interrupt_isr[index].isr(furi_hal_interrupt_isr[index].context);
FURI_ALWAYS_INLINE static void furi_hal_interrupt_call(FuriHalInterruptId index) {
const FuriHalInterruptISRPair* isr_descr = &furi_hal_interrupt.isr[index];
furi_check(isr_descr->isr);

FURI_HAL_INTERRUPT_ACCOUNT_START();
isr_descr->isr(isr_descr->context);
FURI_HAL_INTERRUPT_ACCOUNT_END();
}

FURI_ALWAYS_STATIC_INLINE void
FURI_ALWAYS_INLINE static void
furi_hal_interrupt_enable(FuriHalInterruptId index, uint16_t priority) {
NVIC_SetPriority(
furi_hal_interrupt_irqn[index],
NVIC_EncodePriority(NVIC_GetPriorityGrouping(), priority, 0));
NVIC_EnableIRQ(furi_hal_interrupt_irqn[index]);
}

FURI_ALWAYS_STATIC_INLINE void furi_hal_interrupt_clear_pending(FuriHalInterruptId index) {
FURI_ALWAYS_INLINE static void furi_hal_interrupt_clear_pending(FuriHalInterruptId index) {
NVIC_ClearPendingIRQ(furi_hal_interrupt_irqn[index]);
}

FURI_ALWAYS_STATIC_INLINE void furi_hal_interrupt_get_pending(FuriHalInterruptId index) {
FURI_ALWAYS_INLINE static void furi_hal_interrupt_get_pending(FuriHalInterruptId index) {
NVIC_GetPendingIRQ(furi_hal_interrupt_irqn[index]);
}

FURI_ALWAYS_STATIC_INLINE void furi_hal_interrupt_set_pending(FuriHalInterruptId index) {
FURI_ALWAYS_INLINE static void furi_hal_interrupt_set_pending(FuriHalInterruptId index) {
NVIC_SetPendingIRQ(furi_hal_interrupt_irqn[index]);
}

FURI_ALWAYS_STATIC_INLINE void furi_hal_interrupt_disable(FuriHalInterruptId index) {
FURI_ALWAYS_INLINE static void furi_hal_interrupt_disable(FuriHalInterruptId index) {
NVIC_DisableIRQ(furi_hal_interrupt_irqn[index]);
}

Expand Down Expand Up @@ -137,17 +151,18 @@ void furi_hal_interrupt_set_isr_ex(

uint16_t real_priority = FURI_HAL_INTERRUPT_DEFAULT_PRIORITY - priority;

FuriHalInterruptISRPair* isr_descr = &furi_hal_interrupt.isr[index];
if(isr) {
// Pre ISR set
furi_check(furi_hal_interrupt_isr[index].isr == NULL);
furi_check(isr_descr->isr == NULL);
} else {
// Pre ISR clear
furi_hal_interrupt_disable(index);
furi_hal_interrupt_clear_pending(index);
}

furi_hal_interrupt_isr[index].isr = isr;
furi_hal_interrupt_isr[index].context = context;
isr_descr->isr = isr;
isr_descr->context = context;
__DMB();

if(isr) {
Expand Down Expand Up @@ -304,27 +319,37 @@ extern void HW_IPCC_Tx_Handler(void);
extern void HW_IPCC_Rx_Handler(void);

void SysTick_Handler(void) {
FURI_HAL_INTERRUPT_ACCOUNT_START();
furi_hal_os_tick();
FURI_HAL_INTERRUPT_ACCOUNT_END();
}

void USB_LP_IRQHandler(void) {
#ifndef FURI_RAM_EXEC
FURI_HAL_INTERRUPT_ACCOUNT_START();
usbd_poll(&udev);
FURI_HAL_INTERRUPT_ACCOUNT_END();
#endif
}

void USB_HP_IRQHandler(void) { //-V524
#ifndef FURI_RAM_EXEC
FURI_HAL_INTERRUPT_ACCOUNT_START();
usbd_poll(&udev);
FURI_HAL_INTERRUPT_ACCOUNT_END();
#endif
}

void IPCC_C1_TX_IRQHandler(void) {
FURI_HAL_INTERRUPT_ACCOUNT_START();
HW_IPCC_Tx_Handler();
FURI_HAL_INTERRUPT_ACCOUNT_END();
}

void IPCC_C1_RX_IRQHandler(void) {
FURI_HAL_INTERRUPT_ACCOUNT_START();
HW_IPCC_Rx_Handler();
FURI_HAL_INTERRUPT_ACCOUNT_END();
}

void FPU_IRQHandler(void) {
Expand Down Expand Up @@ -499,3 +524,7 @@ const char* furi_hal_interrupt_get_name(uint8_t exception_number) {
return NULL;
}
}

uint32_t furi_hal_interrupt_get_time_in_isr_total(void) {
return furi_hal_interrupt.counter_time_in_isr_total;
}
6 changes: 6 additions & 0 deletions targets/f7/furi_hal/furi_hal_interrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ void furi_hal_interrupt_set_isr_ex(
*/
const char* furi_hal_interrupt_get_name(uint8_t exception_number);

/** Get total time(in CPU clocks) spent in ISR
*
* @return total time in CPU clocks
*/
uint32_t furi_hal_interrupt_get_time_in_isr_total(void);

#ifdef __cplusplus
}
#endif
Loading