Showing posts with label cross-platform. Show all posts
Showing posts with label cross-platform. Show all posts

Saturday, October 19, 2013

Announcing libperipha and cortex-uni-startup projects

More and more ARM Cortex based boards appear for use by OpenSource/OpenHardware/Maker communities, and
frequently asked question in response to a new announcement is often "Is this supported by open-source toolchain?". Many people know that gcc supports ARM, including Cortex-M, very well, and many projects now lean towards using https://launchpad.net/gcc-arm-embedded as the package of their choice.

But compiler is only part of the toolchain - there should be also at
least basic hardware definition headers which would allow to access peripherals of particular chip. There was big step in that direction done by ARM Ltd, itself, by releasing CMSIS library for the Cortex-M CPU cores under open-source license, though that didn't go without controversy, see comments to that post and followup.

That's great step, but again, it's only part of the story - while it allows to access Cortex-M core registers which are common across all MCUs, there're more to MCU than just CPU - it's all the peripheral blocks. Even basic things as GPIO and timers are vendor- and model-specific, and periphery is what differentiates one vendor's  offering from another's.

And other vendors don't rush to follow ARM's example, so few vendor-specific CMSIS packages are under OpenSource license (one great example of the contrary is Energy Micro EFM32 CMSIS - it's great because they open-sourced it even before ARM). One  good approach to use OpenSource-friendly MCUs for your projects, and everyone is encouraged to do so. Unfortunately, that may not be practical or even possible (I wish I could by EFM32 chips in my part of the world).

So, the idea is to provide open-source MCU headers for use in OpenSource projects - until all vendors get smart to provide them. That's how libperipha project was born. Note that it's not limited to ARM Cortex-M MCUs, though support for them was a primary motivation.

There's final, small, but just as important piece which construes MCU toolchain - startup code. Without it, your application simply won't run. Another project, cortex-uni-startup (unified Cortex startup) was created to cover that. As excellent article by Ivan Sergeev explains, Cortex-M was specifically re-engineered to allow startup code to be written without any single line of assembly! cortex-uni-startup explands on this to provide easily reusable Cortex-M core startup code (usable on any Cortex-M device, but without support for peripheral-specific interrupts), then extends it to cover interrupts of particular MCU model.

These two projects are separate to cover differences in scope (cortex-uni-startup is Cortex-M specific, libperipha is unbound), licensing (cortex-uni-startup core is public domain, libperipha is BSD and others), and usage (libperipha is gross database which you probably will just want to use, then hack, cortex-uni-startup is nice learning tool of beauty of Cortex-M architecture, which you welcome to glance over before using - you won't be overwhelmed, as it's small).

Last final note - while these projects are conceived to be comprehensive, I don't have an aim to sit and add each and every possible bit of every MCU there. Instead, it is intended to be easy do add missing pieces to it on demand - right while you're working on some applied project and find such missing pieces. Then, if people find this to be indeed so, and project overall useful and contribute, then they indeed will acquire comprehensive coverage of MCUs. So, have a look, give it a try, shared feedback, spread the word, contribute patches, and overall, enjoy ;-).

Friday, May 24, 2013

Peripheral Template Library - attempt to efficiently capture common microcontroller algorithms in C++

There were not many posts in this year, partly because I decided to concentrate on writing code and hacking things instead. One of the project I find myself hacking regularly during last half-year is a library modestly called Peripheral Template Library.

Ever since initial amazement with Arduino warn off, it became clear that while it provides concise and easy to use (to learn, to understand) API, it is to schematic, implemented too inefficiently, libraries have reuse, compatibility and configurability problems, and all those things are not portable across really wide MCU range and otherwise not production ready (because of all those efficiency, reuse, etc. issue), but rather a toybox.

Trying to implement things without Arduino overhead, there was growing dissatisfaction with the need to slash code when moving from one MCU to another (due to economical and availability issues, or plain for creative reasons). It became clear the need to abstract things away, but without losing efficiency. The only way to achieve that is metaprogramming. As nowadays nobody writes MCU software in LISP, I turned to C++ - after almost 10 years break I guess.

Many embedded programmers shrug at C++, and well, I did that for any C++ at all for quite some time. But modern C++ is not that "object-oriented syntactic sugar" which your old Turbo C++ 1.0 was (yeah, last one which could run on your old XT, because 2.0 required 286 and protected mode memory extender). Modern C++ is multi-paradigm language, of which "runtime" "object orientation" is just small part. The core part is however compile-time type-based metaprogramming template engine, that's something which allows to achieve aforementioned abstraction/efficiency ratio (and we don't talk here about "C" efficiency here, but something closer to Assembler level).

That's how PTL was born. The idea was to wrap the most core part of any MCU - GPIO (General Purpose Input/Output), and on top of it implement support for standard communication protocols - UART, SPI, I2C, 1-Wire, etc. Everything implemented as templated classes, so can be easy specialized to use hardware blocks of particular MCU. Generalized cross-MCU was one of top goals from the start, i.e. more attention was given to design and implementation of classes which capture basic MCU functionality which is available in any MCU, rather than adhoc peculiarities of particular MCU. The latter can be wrapped too of course - on demand.

Past GPIO and communication protocols, handling timers and delays was second goal. Support for CPU-based delay - both (perfect-cycle) static and dynamic was implemented, then basic timer interface was added, with delay on top of it, with all 3 kinds of delays providing the same interface and thus fully replaceable and combinable.

What comes out of it is available at https://github.com/pfalcon/PeripheralTemplateLibrary . MSP430, AVR, STM32 and EFM32 are supported (all to the different level though, but the basic functionality as described above is available for all by now). The grand aim is to design framework to support all possible (and impossible) MCUs ;-).

There're still log of refactors to do and functional block of individual MCUs to wrap. Some aspects, like clock tree management needs more though and design. Then, there's a need to add bindings/drivers for specific devices, I did that for few already, but of course that's area where I won't be able to compete with existing code, so I'm looking into finding good codebases to port.

License-wise, Peripheral Template Library is released under LGPL3 license, but I'm already thinking about adding linking exception and/or switch to BSD-like license altogether.

Here's a usual LED blinker example:

#include <gpio.hpp>
#include <cpu.hpp>
#include <board.hpp>
#include <delay_static.hpp>
#include <delay_time.hpp>

using namespace PTL;

typedef TimeDelay<board::freq, StaticDelay> delayer;

int main()
{
    cpu::init(cpu::DEFAULT);
    board::LED::port::enable();
    board::LED::output();
    while (true) {
        board::LED::high();
        delayer::delay_ms(500);
        board::LED::low();
        delayer::delay_ms(500);
    }
}

This will compile and work out of the box on any of supported boards - specific LED to use (board::LED) is configured in board config header.

Let me know what you think about PTL. For me, it's definitely exciting, innovative area - not many libs provide such efficient support with such wide heterogeneous coverage, and you really do architecturing and design here, not just dumb boring code. (I admit that partly PTL effort is driven by dissatisfaction of technical inefficiencies, imperfection and warts in "one level bigger" Linux world.)