I'm finally trying to get my occasional MCU projects out of the 8 bit world and into ARM, and as I'm porting over some communications stuff I'm trying to do so with an eye toward better code reuse, which is something I've never really been good about. I generally know enough C to get myself into trouble--and usually out of it, eventually--so I hope some more experienced folks can offer some advice here.
Say I'm working on a protocol driver that uses a UART at 250K and does some basic start/end checking in the ISR, but otherwise just chucks incoming data into a buffer. That's all fine and good. Now say I want to be able to use that same UART for a second protocol that requires a different ISR, and freely switch between the two during run time--and perhaps use the same protocol(s) on more than one UART simultaneously. It seems like the most efficient way to do this would be to reassign the interrupt vector to the appropriate handler function, but as far as I can see there's no way to do this during runtime, at least in the M0-M4 range. (I'm using Atmel's SAMD21 (M0+) and SAM4S (M4), for what it's worth).
Performance wise, the next best thing I expect would be to create a combined ISR that takes the appropriate actions depending on which protocol is active. However that means spreading code from what would ideally be two separate libraries across their respective files and the main application, which isn't terribly elegant.
The ideal option from a reusability standpoint would be to have protocol-specific handling functions that are selectively called from the peripheral's ISR. I know the prevailing wisdom at least in the 8-bit world is that ISRs should never call functions if at all possible, since that will increase stack usage and execution time. But I don't know to what extent that's a real concern with the increased speed and RAM of something in the ARM family, or to what extent I can rely on the compiler to optimize away that overhead. I'm already using ASF API functions for most hardware accesses anyway. I don't intend to push the limits of execution time and stack size, but I also don't want to waste resources unnecessarily. I could declare the handler functions as inline, but as far as I know that requires them to be defined locally, which again would require mixing library code into application code (maybe that's just my lack of C knowledge).
The other complication is the ability to handle different hardware. Atmel's ARMs have both UARTs and USARTs on some parts, and multiple SERCOMs on others, all of which require different configurations to do the same thing. Ideally I think what I'd like to do is have a single handler function for each protocol, and selectively call the correct handler from each interface's ISR. The call to the handler would need to pass a struct to tell the handler which hardware interface to interact with and which RX/TX buffers to use, etc. That seems like the most elegant solution, but I don't know if it's asking for performance trouble. I also don't know at the moment how tricky it will be to deal with reentrancy with multiple ISRs potentially calling the same function--presumably one UART/USART/SERCOM interrupt would never preempt another, but I haven't looked into that very deeply yet.
Or is there anything else I'm not thinking of, or am I just overthinking this whole thing?