lladoware!

    For several years now the TI TM4C has been my go-to embedded system. It's very easy to develop for, it's fast enough and powerful enough for the type of work I do (more hardware control than IoT), and it's less expensive than an Arduino. But every time I start a new project, it's usually been a few months since I finished my previous project and I have to spend hours digging through my old code looking for the bits and pieces that do what I need this time around. Which is a bit sad. Because usually I'm doing the same small number of things over and over again. So a while back I figured I should write a robust and comprehensive library that contains all the functions I use over and over, which really just includes configuration of GPIO pins, PWM signals, and timers. Now that I have a lot of free time, I'm finally doing that. TI has a set of libraries called TivaWare which, honestly, I don't know much about. I just never got around to using that. So my libraries will be called lladoware.

    I've put together one library that allows me to initialize and then update arbitrary output pins as either GPIO or PWM. I've considered these to be two separate things in the past, but when I actually sat down and compared all of my old code, I realized there are only a few bytes difference between a GPIO configuration and a PWM configuration. In fact, after a pin is initialized in a particular way, only two registers have to be modified to flip that pin between GPIO and PWM or vice versa. This is a really nice thing to know. One problem I've had in the past was that when controlling a pin in PWM mode, you can set that pin to 0% duty but you can't set it to 100% duty. The highest you can go is (period-1)/period. Knowing that it takes two clock cycles to switch a pin from PWM to GPIO, I made a simple interface that ignores the distinction and configures an arbitrary pin in whichever state the user wants it to be at a given moment. This is really nice.

    So for example, if I want to initialize pin PB1 as GPIO and set it low, then initialize pin PB2 as PWM and set it to 50% duty, then change PB2 to HIGH, instead of this:

init_PB1_GPIO();
update_PB1_GPIO(1);
init_PB2_PWM();
update_PB2_PWM(PWM_PERIOD/2);
init_PB2_GPIO();
update_PB2_GPIO(1);

and then I have to write each of those functions, each filled with bitwise register operations, instead I can just write this:

init_pin_output(PB1, 0, HIGH);
init_pin_output(PB2, PERIOD, PERIOD/2);
update_pin(PB2, HIGH);

and that will just work and I don't have to remember which registers do what. Assuming I'll keep using these MCUs for random projects for the next few years, this should save a good amount of time and headache.

    After getting output working, I started putting together a library for input. Since C doesn't allow multiple inheritance, I combined output and input into a single library. I have pins working for GPIO input as well as for buttons with interrupts triggering function execution, but for some reason this isn't working on pin PA2. Or rather, it's only working once. I press the button connected to PA2, the associated task executes correctly, and then the system freezes. No idea what's causing it at this point in time. We'll see.

    Next up I need to generalize timers, which is another thing that I use regularly and always have to look up and re-learn.

Comments