Showing posts with label msp430. Show all posts
Showing posts with label msp430. Show all posts

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.)

Tuesday, September 11, 2012

Wednesday, July 4, 2012

TI Launchpad 1.4 vs 1.5 pin swappery

Everyone knows that AVR is the king of open-hardware/hobbyist hill, as well as one of the most available MCU family, with most popular MCUs easily sourceable around the world in the nearest half-decent electronic component shop/martetplace. Why would you want to swap Arduino-thingy for something else? Many factors would need to play for that to happen, like price, availability again, and some issues with AVR.

Texas Instruments with Launchpad devel board for MSP430 value line pushes edge on price and availability, shipping candy to almost any country in the world for unbelievable price. And one of the issue I had with AVR MCU is inconsistency in their implementation (pin and register maps), which complicates MCU upgrade and code portability among the models.

So, MSP430 delivered with Launchpad felt like fresh air, and overall pretty cleverly and attentively designed MCU. Well, as folks who watch that space know, TI replaces the original Launchpad 1.4 model which shipped with MSP430G2231 with 1.5, shipping with MSP430G2553, without changing the price, which felt like generous move, and their desire to become real Arduino competetor.

Well, one of the issue which came with 1.5 was that it turns out that MSP430G2553 uses swapped assignment of RXD & TXD pins in its hardware UART comparing to (completely software-based) UART implementation with MSP430G2231. That could raise some eyebrows: because 1) couldn't Launchpad designers be attentive and design it originally as being compatible with entire MSP430G family (i.e. use hardware UART pin assignment right away); 2) if it really happens that MSP430G2553 was designed after Launchpad 1.4, couldn't TI engineers be so attentive to be compatible with existing UART pin assignment in their advertisement product, based on which quite a few people may judge entire MSP430 family.

But OK, stuff happens. TI was kind enough to provide a workaround to swap pins using a jumper trick. And well, you mostly use UART to communicate with "big" computer, so that jumper there was the only thing need.

And few days ago I ported my code to communicate with an SPI device (using a shield) from G2231 to G2553. First issue is that former vs latter use completely different SPI (etc.) communication controllers - USI vs USCI (yup, could have been named clearly to emphasize their difference). So, I was hit by the same issue I blamed on AVR - well, there at least if there's SPI controller, it works the same, even if some register addresses/bits might be different.

But once I ported software, I still couldn't get my device working, and it took few hours to check thru datasheets and manuals to find out that G2231 vs G2553 have also MOSI vs MISO pins swapped! Now, that's something to really frown about. It's not some random software-emulated UART pins misplaced on G2231 and corrected on G2553. In case of SPI, both MCUs have hardware SPI, so swapping pins is just that - big unfriendly "surprise" delivered in hardware developer's face. It would be too naive to think that it again happened by accident or mistake - conspiracy theorist would say it was carefully managemented and engineered incompatibility within family, designed to make users keep buying old low-power stuff and disallow easier upgrades. It's pure wonder they didn't get an idea to swap VCC and GND - indeed why not, few hundreds/thousands MCUs/devices burnt, and happy customers come back to buy more.

Aftermath of SPI swap is actually more serious than UART swap - again, UART is mostly used to connect to host, so you can set needed jumper position on it and forget (scalable solution is to keep using software UART and original pin assignment, as hardware UART is absent on quite a few devices and Launchpad is limited to 9600 baud anyway). But SPI is peripheral interface and the whole idea of Arduino and which TI also seems to push to Launchpad is extension modules aka shields. And SPI swappery means if you "just" make a shield for SPI device, it won't compatible with either old or new device (on hardware level). Would be pretty serious issue for folks who try to support Launchpad ecosystem, but surprisingly I found only one post on the issue, which again, means that folks are not aware, and unhappy customers may follow.

So, it's hard to say if TI should be blamed or vice-versa, thanked for being fare and show with Launchpad not only boons, but also drawbacks of MSP430 family. What's important are lessons learned (not just with this case, but with few other Launchpad hiccups):

  1. Launchpad is not an Arduino.
  2. Launchpad will not be an Arduino.
  3. If you want nicely-working and user-friendly devel board, Arduino is always there.
  4. If you want something cheap, Launchpad so far there too.
  5. Expect Launchpad to bring issues and surprises, and break with new versions (ultimately, its price may break).
  6. MSP430 is unlikely to displace AVR.
  7. If you want to try MS430, check its availability. For example, in this part of the world, it's not possible to source small quantities of MSP430 value line, because well, nobody will get an idea to replace trusty ATtiny, so it makes no sense to bring them to shops. And nobody would get an idea to replace ATtiny because:
  8. "Didn't break - didn't fix it." If ATtiny can do it, why bother with something else. That's not just inertness of thought, which industry/experienced people possess, that's actually proved by experience, as we saw. To change that, new product should do it much better than existing, but MSP430 doesn't want to do that.

Thursday, March 29, 2012

Developing for TI LaunchPad MSP430 board on Ubuntu

If you google for it, you'll find quite a few blog posts, but most of them are from 2010. But starting with Ubuntu 11.10 (Oneiric), gcc-msp430 and friends are included in the main repositories, so you can just apt-get install them:

apt-get install binutils-msp430 gcc-msp430 \
    msp430-libc msp430mcu mspdebug

There's one annoying bug in Oneiric's version of binutils-msp430 which breaks build with -ffunction-sections -Wl,--gc-sections options (which is kinda common trick in embedded world to remove unused functions and reduce code size): mspgcc #3386145. It is fixed in Ubuntu 12.04 (Precise).

I'm however still running Maverick, so instead I downloaded following Oneiric packages:

binutils-msp430_2.21~msp20110421-2_i386.deb
gcc-msp430_4.5.3~mspgcc-4.5.2-20110612-1_i386.deb
libgmp10_5.0.1+dfsg-7ubuntu2_i386.deb
libmpc2_0.9-3_i386.deb
msp430-libc_20110612-1_i386.deb
mspdebug_0.16-1_i386.deb

Then few from Precise:
binutils-msp430_2.22~msp20110716p5-1_i386.deb
msp430mcu_20110613-3_all.deb

(If you try to install Precise versions of other packages on Maverick, they want to pull upgrades to system libs, which I wanted to avoid).

and installed them manually with dpkg.

Wednesday, March 28, 2012

Connetcing to preprogrammed TI Launchpad demo under Linux

TI Launchpad board comes with preprogrammed demo application for temperature sensing which is touted to output temperature values to host via USB-encapsulated UART. By connecting to it via terminal you can see that it indeed sends something, but that doesn't look anything like temperature represent in ascii digits, like someone naively could expect. It turns out that it's well kept secret on Launchpad wiki pages how to make sense out of it - at least, you get advertisements for CCS and Java-based GUIs to read out the output, but not straight docs of how to use builtin demo without all those crutches. So well, wrong approach - it's your random user-friendly arduino, approach of reading docs doesn't work here, better go straight to the source.

And, here's step by step instructions:

First thing to note is that Launchpad's UART-via-USB emulation is extremely fragile. It seems that if MCU started to produce UART output but host doesn't read it out, then buffer in USB bridge just gets overflowed and it stops responding to USB. So, if you want to get it working, follow each step below precisely and if any issue happens, restart from beginning (with unplugging LaunchPad).
  1. If you have plugged LaunchPad into USB, unplug it now to make sure you start with properly reset device.
  2. Plugin the board into USB, general-purpose green and red should blink interchangeably. The demo app doesn't yet sense temperature or sends it out yet in this mode.
  3. Execute stty 2400 -F /dev/ttyACM0 . That's right - the demo app communicates at 2400 bit/s data rate and using any other rate will produce garbage input. (One reason for such low speed is that LaunchPad's MCU actually doesn't have hardware UART, it is emulated in software).
  4. Run hexdump -v -C /dev/ttyACM0 . It shouldn't produce any output yet.
  5. Press GPIO button. The demo app goes into measurement mode and starts to send out temperature in Fahrenheit as raw bytes over UART. Try to heat/cool air around the board to see values change.
Sample output:

00000020  60 60 60 60 60 60 60 60  60 60 60 60 60 60 60 60  |````````````````|
00000030  60 60 60 60 60 60 60 60  60 60 60 60 60 60 60 60  |````````````````|
00000040  60 60 60 60 60 60 60 60  60 60 61 60 60 61 60 60  |``````````a``a``|
00000050  61 60 60 61 61 61 60 61  61 61 61 61 61 61 61 61  |a``aaa`aaaaaaaaa|
00000060  61 61 61 61 61 62 61 62  62 62 62 62 62 62 62 61  |aaaaababbbbbbbba|
00000070  62 62 62 62 62 62 62 62  62 62 62 62 62 62 62 62  |bbbbbbbbbbbbbbbb|
00000080  62 62 62 62 62 62 62 62  62 62 62 62 62 62 62 62  |bbbbbbbbbbbbbbbb|