# Different library for STM32 without interrupt, with interrupt or DMA?

I am an OO programmer, and since some time I'm spending time (as a hobby) with an STM32.

For a hobby project I'm using a shift register (74HC595), and LCD. For both I wrote a class to easily construct and use it.

Both are based without interrupts/DMA, so the methods are very simple (actually for the shift register there is only one method: ShiftOut(uint16_t data)).

But I can imagine later when I want to use the shift register in a more challenging program, that I want it to use interrupts or even DMA.

Since I don't have much experience with embedded libraries, and also cannot remember seeing it before, would it be better to split a library in 3 classes (one for without-interrupts, one using interrupts, and one using DMA) or an 'all in one' solution?

• Just one class
• No repeating code (most 'business logic' will be equal)

• Better performance (no need to check what manner (none, interrupt, DMA) is used)
• Less code (no checks which communication method is used)

Or I could make an abstract base class and create classes for non-interrupt, interrupt or DMA deriving from it (but that will be a performance hit for every function).

Since I mostly don't see the 'split' solution (but sometimes see different classes made by different people) I wonder if it would be useful.

Also as a side question, I'm intending to pass everything what is needed (so e.g. needed I2C or SPI port, GPIO pins). I'm not sure if I can pass easily callbacks for interrupts/DMA settings, as this is set by CubeIDE and doing that manually without CubeIDE seems a bit overwhelming right now. Can I expect problems passing interrupts/DMA functions?

• The way I see this done a lot is to use #define's to identify how the library works, for example the user of the api would declare #define SHIFTOUT_USEDMA and you would use those #defines in the library to conditionally compile code. This is different though if you are distributing the library as a compiled assembly. – Ron Beyer Jan 31 '20 at 16:22
• I don't think things are as clean cut as you make them out to be...in embedded some things are tied to hardware and can't just be arbitrarily abstracted into a class since they physically exist, are unique, and are defined elsewhere. The closest I got was making classes that took pointers as arguments to peripheral base addresses (from which peripheral registers could be accessed as long as it was the same type of peripheral since all address offsets were the same) or functions and that was a LOT of work. – DKNguyen Jan 31 '20 at 16:30
• Even then much peripheral configuration was defined out of the class, as well as the interrupt routines since doing so would mean going through every register and writing a function for each one so it could be modified with a class function. It was a matter of balancing being able to "plug stuff in" for re-use and how often it would actually be done more than once in code. Peripheral configuration is usually just done once on startup with minor modifications during run-time. Those minor modifications had functions, but the rest did not. Those were directly accessed. – DKNguyen Jan 31 '20 at 16:31
• Then you have random things where one peripheral needs multiple registers scattered around the processor (sometimes in other hardware like the clock controller, or GPIO) to be configured and it's messy to try and encapsulate those all in a generic re-usable format. – DKNguyen Jan 31 '20 at 16:33
• As long as you're using a compiler from this century and enable even the 1st level of optimization it's unlikely that using an abstract base class and deriving the other 3 from it will result in any performance hit at all. Write code that's easy for you (and whoever comes after you) to use, maintain & build onto. When you start the next project and you find that you can just pull your old libraries & drop them in, and they 'just work' you'll be thankful you did it that way. – brhans Jan 31 '20 at 16:57