From cc0fdffee6eb5251331dc58ebc03057521e45b15 Mon Sep 17 00:00:00 2001 From: Robbe Derks Date: Mon, 11 Apr 2022 11:59:47 +0200 Subject: [PATCH] Calculate interrupt load and add to health packet (#913) * calculate interrupt load * forgot to change this * being cautious about overflows * utils * fix bootstub * cleanup * also exclude pedal * fix misra Co-authored-by: Comma Device --- board/drivers/interrupts.h | 36 +++++++++++++++++++++++++++++++++- board/health.h | 3 ++- board/safety.h | 6 ------ board/stm32fx/stm32fx_config.h | 1 + board/stm32h7/stm32h7_config.h | 1 + board/usb_comms.h | 2 ++ board/utils.h | 5 +++++ python/__init__.py | 5 +++-- tests/safety/test.c | 1 + 9 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 board/utils.h diff --git a/board/drivers/interrupts.h b/board/drivers/interrupts.h index a9137f76..a3949856 100644 --- a/board/drivers/interrupts.h +++ b/board/drivers/interrupts.h @@ -7,6 +7,7 @@ typedef struct interrupt { } interrupt; void interrupt_timer_init(void); +uint32_t microsecond_timer_get(void); void unused_interrupt_handler(void) { // Something is wrong if this handler is called! @@ -25,7 +26,22 @@ interrupt interrupts[NUM_INTERRUPTS]; bool check_interrupt_rate = false; +uint8_t interrupt_depth = 0U; +uint32_t last_time = 0U; +uint32_t idle_time = 0U; +uint32_t busy_time = 0U; +float interrupt_load = 0.0f; + void handle_interrupt(IRQn_Type irq_type){ + ENTER_CRITICAL(); + if (interrupt_depth == 0U) { + uint32_t time = microsecond_timer_get(); + idle_time += get_ts_elapsed(time, last_time); + last_time = time; + } + interrupt_depth += 1U; + EXIT_CRITICAL(); + interrupts[irq_type].call_counter++; interrupts[irq_type].handler(); @@ -34,14 +50,32 @@ void handle_interrupt(IRQn_Type irq_type){ puts("Interrupt 0x"); puth(irq_type); puts(" fired too often (0x"); puth(interrupts[irq_type].call_counter); puts("/s)!\n"); fault_occurred(interrupts[irq_type].call_rate_fault); } + + ENTER_CRITICAL(); + interrupt_depth -= 1U; + if (interrupt_depth == 0U) { + uint32_t time = microsecond_timer_get(); + busy_time += get_ts_elapsed(time, last_time); + last_time = time; + } + EXIT_CRITICAL(); } -// Reset interrupt counter every second +// Every second void interrupt_timer_handler(void) { if (INTERRUPT_TIMER->SR != 0) { + // Reset interrupt counters for(uint16_t i=0U; i 0U) ? ((float) busy_time) / (busy_time + idle_time) : 0.0f; +#endif + idle_time = 0U; + busy_time = 0U; } INTERRUPT_TIMER->SR = 0; } diff --git a/board/health.h b/board/health.h index 66c686b7..12b47d89 100644 --- a/board/health.h +++ b/board/health.h @@ -1,5 +1,5 @@ // When changing this struct, python/__init__.py needs to be kept up to date! -#define HEALTH_PACKET_VERSION 4 +#define HEALTH_PACKET_VERSION 5 struct __attribute__((packed)) health_t { uint32_t uptime_pkt; uint32_t voltage_pkt; @@ -22,4 +22,5 @@ struct __attribute__((packed)) health_t { uint8_t heartbeat_lost_pkt; uint16_t alternative_experience_pkt; uint32_t blocked_msg_cnt_pkt; + float interrupt_load; }; diff --git a/board/safety.h b/board/safety.h index 24e7dc10..b8cb7935 100644 --- a/board/safety.h +++ b/board/safety.h @@ -99,12 +99,6 @@ bool msg_allowed(CANPacket_t *to_send, const CanMsg msg_list[], int len) { return allowed; } -// compute the time elapsed (in microseconds) from 2 counter samples -// case where ts < ts_last is ok: overflow is properly re-casted into uint32_t -uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last) { - return ts - ts_last; -} - int get_addr_check_index(CANPacket_t *to_push, AddrCheckStruct addr_list[], const int len) { int bus = GET_BUS(to_push); int addr = GET_ADDR(to_push); diff --git a/board/stm32fx/stm32fx_config.h b/board/stm32fx/stm32fx_config.h index cbccadab..a0e6940c 100644 --- a/board/stm32fx/stm32fx_config.h +++ b/board/stm32fx/stm32fx_config.h @@ -53,6 +53,7 @@ #include "libc.h" #include "critical.h" #include "faults.h" +#include "utils.h" #include "drivers/registers.h" #include "drivers/interrupts.h" diff --git a/board/stm32h7/stm32h7_config.h b/board/stm32h7/stm32h7_config.h index 02be1100..9755f920 100644 --- a/board/stm32h7/stm32h7_config.h +++ b/board/stm32h7/stm32h7_config.h @@ -45,6 +45,7 @@ #include "libc.h" #include "critical.h" #include "faults.h" +#include "utils.h" #include "drivers/registers.h" #include "drivers/interrupts.h" diff --git a/board/usb_comms.h b/board/usb_comms.h index 5d2ed817..64b12306 100644 --- a/board/usb_comms.h +++ b/board/usb_comms.h @@ -37,6 +37,8 @@ int get_health_pkt(void *dat) { health->fault_status_pkt = fault_status; health->faults_pkt = faults; + health->interrupt_load = interrupt_load; + return sizeof(*health); } diff --git a/board/utils.h b/board/utils.h new file mode 100644 index 00000000..d767738b --- /dev/null +++ b/board/utils.h @@ -0,0 +1,5 @@ +// compute the time elapsed (in microseconds) from 2 counter samples +// case where ts < ts_last is ok: overflow is properly re-casted into uint32_t +uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last) { + return ts - ts_last; +} diff --git a/python/__init__.py b/python/__init__.py index cc8207d1..42a20b34 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -170,8 +170,8 @@ class Panda(object): HW_TYPE_RED_PANDA = b'\x07' CAN_PACKET_VERSION = 2 - HEALTH_PACKET_VERSION = 4 - HEALTH_STRUCT = struct.Struct("