WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content
Draft
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
27 changes: 27 additions & 0 deletions board/drivers/interrupts.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ static uint32_t idle_time = 0U;
static uint32_t busy_time = 0U;
float interrupt_load = 0.0f;

// Track NVIC priority grouping used for encoding priorities
static uint32_t nvic_priority_grouping = IRQ_PRIORITY_GROUPING_DEFAULT;

void handle_interrupt(IRQn_Type irq_type){
static uint8_t interrupt_depth = 0U;
static uint32_t last_time = 0U;
Expand Down Expand Up @@ -69,13 +72,37 @@ void interrupt_timer_handler(void) {
INTERRUPT_TIMER->SR = 0;
}

void interrupts_set_priority_grouping(uint32_t grouping) {
// Set NVIC priority grouping (0..7), 0 -> all preempt priority bits
nvic_priority_grouping = grouping;
NVIC_SetPriorityGrouping(nvic_priority_grouping);
}

void interrupts_set_priority(IRQn_Type irq_type, uint8_t preempt_prio, uint8_t sub_prio) {
if ((uint32_t)irq_type < NUM_INTERRUPTS) {
interrupts[irq_type].preempt_prio = preempt_prio;
interrupts[irq_type].sub_prio = sub_prio;
uint32_t encoded = NVIC_EncodePriority(NVIC_GetPriorityGrouping(), preempt_prio, sub_prio);
NVIC_SetPriority(irq_type, encoded);
}
}

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;
// Initialize default priorities in the descriptor table
interrupts[i].preempt_prio = IRQ_DEFAULT_PREEMPT_PRIORITY;
interrupts[i].sub_prio = IRQ_DEFAULT_SUBPRIORITY;
}

// Init interrupt timer for a 1s interval
interrupt_timer_init();

// Configure grouping and apply default priorities to all external IRQs
interrupts_set_priority_grouping(IRQ_PRIORITY_GROUPING_DEFAULT);
for (uint16_t i = 0U; i < NUM_INTERRUPTS; i++) {
interrupts_set_priority((IRQn_Type)i, IRQ_DEFAULT_PREEMPT_PRIORITY, IRQ_DEFAULT_SUBPRIORITY);
}
}
23 changes: 22 additions & 1 deletion board/drivers/interrupts_declarations.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
#pragma once

// Interrupt descriptor and (now) priority metadata
typedef struct interrupt {
IRQn_Type irq_type;
void (*handler)(void);
uint32_t call_counter;
uint32_t call_rate;
uint32_t max_call_rate; // Call rate is defined as the amount of calls each second
uint32_t call_rate_fault;
// Priority configuration (preempt priority and subpriority encoded per grouping)
// Lower numbers are higher priority on ARM NVIC.
uint8_t preempt_prio; // 0..(1<<__NVIC_PRIO_BITS)-1
uint8_t sub_prio; // typically 0 when using full preempt priority
} interrupt;

void interrupt_timer_init(void);
Expand All @@ -15,17 +20,33 @@ void unused_interrupt_handler(void);

extern interrupt interrupts[NUM_INTERRUPTS];

// Default priority configuration (fixed, not overridable)
// - Grouping 0: all available bits used for preempt priority
// - Baseline preempt priority: 2 (SPI/DMA use 0 to preempt)
// - Subpriority: 0 (unused with grouping 0)
#define IRQ_PRIORITY_GROUPING_DEFAULT (0U)
#define IRQ_DEFAULT_PREEMPT_PRIORITY (2U)
#define IRQ_DEFAULT_SUBPRIORITY (0U)

// Apply defaults on registration and set NVIC priority accordingly.
#define REGISTER_INTERRUPT(irq_num, func_ptr, call_rate_max, rate_fault) \
interrupts[irq_num].irq_type = (irq_num); \
interrupts[irq_num].handler = (func_ptr); \
interrupts[irq_num].call_counter = 0U; \
interrupts[irq_num].call_rate = 0U; \
interrupts[irq_num].max_call_rate = (call_rate_max); \
interrupts[irq_num].call_rate_fault = (rate_fault);
interrupts[irq_num].call_rate_fault = (rate_fault); \
interrupts[irq_num].preempt_prio = IRQ_DEFAULT_PREEMPT_PRIORITY; \
interrupts[irq_num].sub_prio = IRQ_DEFAULT_SUBPRIORITY; \
interrupts_set_priority((irq_num), IRQ_DEFAULT_PREEMPT_PRIORITY, IRQ_DEFAULT_SUBPRIORITY);

extern float interrupt_load;

void handle_interrupt(IRQn_Type irq_type);
// Every second
void interrupt_timer_handler(void);
void init_interrupts(bool check_rate_limit);

// Priority configuration helpers
void interrupts_set_priority(IRQn_Type irq_type, uint8_t preempt_prio, uint8_t sub_prio);
void interrupts_set_priority_grouping(uint32_t grouping);
6 changes: 6 additions & 0 deletions board/stm32h7/llspi.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ void llspi_init(void) {
REGISTER_INTERRUPT(DMA2_Stream2_IRQn, DMA2_Stream2_IRQ_Handler, SPI_IRQ_RATE, FAULT_INTERRUPT_RATE_SPI_DMA)
REGISTER_INTERRUPT(DMA2_Stream3_IRQn, DMA2_Stream3_IRQ_Handler, SPI_IRQ_RATE, FAULT_INTERRUPT_RATE_SPI_DMA)

// Elevate SPI and its DMA above the baseline so they can preempt others
// Preempt priority 0 (highest), subpriority 0
interrupts_set_priority(SPI4_IRQn, 0U, 0U);
interrupts_set_priority(DMA2_Stream2_IRQn, 0U, 0U);
interrupts_set_priority(DMA2_Stream3_IRQn, 0U, 0U);

// Setup MOSI DMA
register_set(&(DMAMUX1_Channel10->CCR), 83U, 0xFFFFFFFFU);
register_set(&(DMA2_Stream2->CR), (DMA_SxCR_MINC | DMA_SxCR_TCIE), 0x1E077EFEU);
Expand Down
Loading