For beginners ability change IRQ handlers i suggest add attach/detach functionality to all IRQ handlers (as i understand weak not enough for this). So easy change handlers to custom. For shared IRQ handlers (for example USB/CAN) suggest attach function return false for originial processing or true for exit from original IRQ handler. Or tthis rules implement for all attach functions.
For example
Serial1.attach(custom_function)
struct usart_dev usart_dev_table[] = {
[USART1] = {
.base = (usart_port*)USART1_BASE,
.rcc_dev_num = RCC_USART1,
.nvic_dev_num = NVIC_USART1,
.handler = NULL
},
...
// Or uint8(*handler)(void)
void usart_attach(uint8 usart_num, void (*handler)(void))
{
usart_dev_table[usart_num].handler = handler;
}
void usart_detach(uint8 usart_num)
{
usart_dev_table[usart_num].handler = NULL;
}
static inline void usart_irq(int usart_num) {
if (usart_dev_table[usart_num].handler != NULL)
{
(usart_dev_table[usart_num].handler)();
if ((usart_dev_table[usart_num].handler)())
return;
}
#ifdef USART_SAFE_INSERT
/* Ignore old bytes if the user defines USART_SAFE_INSERT. */
rb_safe_insert(&(usart_dev_table[usart_num].rb), (uint8)((usart_dev_table[usart_num].base)->DR));
#else
/* By default, push bytes around in the ring buffer. */
rb_push_insert(&(usart_dev_table[usart_num].rb), (uint8)((usart_dev_table[usart_num].base)->DR));
#endif
}
void USART1_IRQHandler(void) {
usart_irq(USART1);
}
hope in some situation it's helpfull