You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
81 lines
2.3 KiB
81 lines
2.3 KiB
#include "interrupts_declarations.h"
|
|
|
|
void unused_interrupt_handler(void) {
|
|
// Something is wrong if this handler is called!
|
|
print("Unused interrupt handler called!\n");
|
|
fault_occurred(FAULT_UNUSED_INTERRUPT_HANDLED);
|
|
}
|
|
|
|
interrupt interrupts[NUM_INTERRUPTS];
|
|
|
|
static bool check_interrupt_rate = false;
|
|
|
|
static uint32_t idle_time = 0U;
|
|
static uint32_t busy_time = 0U;
|
|
float interrupt_load = 0.0f;
|
|
|
|
void handle_interrupt(IRQn_Type irq_type){
|
|
static uint8_t interrupt_depth = 0U;
|
|
static uint32_t last_time = 0U;
|
|
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();
|
|
|
|
// Check that the interrupts don't fire too often
|
|
if (check_interrupt_rate && (interrupts[irq_type].call_counter > interrupts[irq_type].max_call_rate)) {
|
|
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();
|
|
}
|
|
|
|
// Every second
|
|
void interrupt_timer_handler(void) {
|
|
if (INTERRUPT_TIMER->SR != 0U) {
|
|
for (uint16_t i = 0U; i < NUM_INTERRUPTS; i++) {
|
|
// Log IRQ call rate faults
|
|
if (check_interrupt_rate && (interrupts[i].call_counter > interrupts[i].max_call_rate)) {
|
|
print("Interrupt 0x"); puth(i); print(" fired too often (0x"); puth(interrupts[i].call_counter); print("/s)!\n");
|
|
}
|
|
|
|
// Reset interrupt counters
|
|
interrupts[i].call_rate = interrupts[i].call_counter;
|
|
interrupts[i].call_counter = 0U;
|
|
}
|
|
|
|
// Calculate interrupt load
|
|
// The bootstub does not have the FPU enabled, so can't do float operations.
|
|
#if !defined(BOOTSTUB)
|
|
interrupt_load = ((busy_time + idle_time) > 0U) ? ((float) (((float) busy_time) / (busy_time + idle_time))) : 0.0f;
|
|
#endif
|
|
idle_time = 0U;
|
|
busy_time = 0U;
|
|
}
|
|
INTERRUPT_TIMER->SR = 0;
|
|
}
|
|
|
|
void init_interrupts(bool check_rate_limit){
|
|
check_interrupt_rate = check_rate_limit;
|
|
|
|
for(uint16_t i=0U; i<NUM_INTERRUPTS; i++){
|
|
interrupts[i].handler = unused_interrupt_handler;
|
|
}
|
|
|
|
// Init interrupt timer for a 1s interval
|
|
interrupt_timer_init();
|
|
}
|
|
|