The Framework

By building frameworks for deeply embedded systems, Arselon defines how to develop for a embedded system. It defines broad range of conventions such as the coding conventions, I/O driver conventions, how IRQ’s are handled, how the data is carried from lower layers to upper layers, how the code interacts with UART, SPI, I2C ports and the devices connected to those ports..

That way, we believe that developers can concentrate on their own purpose: To ship products with minimum bugs and maximum features as fast as possible: help customers to make the world a better place..

Arselon frees the developer from dealing with low level stuff. Being able to code in C++ is enough to use a supported microcontroller. With the framework, using different microcontroller requires very minimal work, because framework behaves the same and has the same components that has the same interface across the platforms..

It would be much easier to understand with a sample. First thing developers do on a platform is to blink a led. Let say we are working on LPC1768, and a led is connected to p2_1 (Pin 1 of GPIO port 2)

#include <Acore/Pin.h>
#include <Acore/Thread.h>

using namespace Acore;

int main()
{
  Pin* led = p2_1();
  led->configure(PinFunctionOutput0);
  while (1)
  {
    led->toggle();
    sleep(500);
    led->toggle();
    sleep(500);
  }
}

This sample is using our Acore library, which the core of all Arselon libraries as the name implies. As you can see, there is no configuration, no magic macros to deal with. sleep(500) sleeps the MCU for 500ms, all the timings are handled by the framework automatically..

In the sample above sleep blocks the main thread (the thread that main function is called). Most of the the time CPU is doing nothing. Acore sleeps the CPU to conserve the power at those times. But we usually want to do more than just blinking a led in certain intervals. We have to be able to use the time sleep consumes.. Arselon suggest using event driven method instead of blocking method. What is event driven method? Instead of waiting for something to happen, system monitors that thing and informs us when it happens. Here the timeout is what we are looking for. Acore::Timer class has that ability. We may rewrite the code:

#include <Acore/Pin.h>
#include <Acore/Timer.h>
#include <Acore/Thread.h>

using namespace Acore;

Pin* led;
Timer ledTimer;

void doLedTimeOut(Object* sender)
{
  led->toggle();
  ledTimer.start();
}

int main()
{
  led = p2_1();
  led->configure(PinFunctionOutput0);
  ledTimer.onTimeOut().connect(doLedTimeOut); 
  ledTimer.setInterval(500);
  ledTimer.start();
  Thread::run();
}

When the code reaches Thread::run(), it enters the Thread’s event loop. Let’s say it stays there and if an event occurs it calls the given handler.. After the routine (here doLedTimeOut) has finished its handling the system waits for another event. If an event happens while handling another event, it is queued to be handled after the current one..

Now we may add new missions to our thread. We love blinking leds, and want to toggle another one when we pressed a button. Let say button is connected to p0_1 (pin 1 of port 0), and led is connected to p2_2 (pin 2 of port 2).

#include <Acore/Pin.h>
#include <Acore/Timer.h>
#include <Acore/Thread.h>
#include <Acore/FilteredEdgeDetector.h>

using namespace Acore;

Pin* led;
Timer ledTimer;

Pin* edgeLed;
FilteredEdgeDetector edgeDetector;

void doLedTimeOut(Object* sender)
{
  led->toggle();
  ledTimer.start();
}

void doEdgeOccured(Object* sender)
{
  edgeLed->toggle();
}

int main()
{
  led = p2_1();
  led->configure(PinFunctionOutput0);
  ledTimer.onTimeOut().connect(doLedTimeOut); 
  ledTimer.setInterval(500);
  ledTimer.start();

  edgeLed = p2_2();
  edgeLed->configure(PinFunctionOutput1);
  edgeDetector.onEvent(doEdgeOccurred); 
  edgeDetector.setPin(p0_1());
  edgeDetector.setEdge(EdgeRising);
  edgeDetector.start();

  Thread::run();
}

Now one led blinks at interval of 500ms, the other one toggles when we press the button..

FilteredEdgeDetector is a class that monitors a given pin, and it detects the rising, falling or both edges of that pin. When an edge occurs it start monitoring the pin to become stable for a configurable period. This yields “debounce filtering”. Debounce problems occurs when a mechanical contact is closed. The contact resonates which generates many unwanted pulses in signal line. FilteredEdgeDetector filters out that and only reports when the pin it stable at certain level for a certain time.

Even we added new function to our implementation, CPU spends majority of its time waiting for an event to occur. Acore powers down the CPU to conserve significant amount of power.. If the system is working from mains line, power saving would not be important however for battery powered designs it is a major concern.

If you look at the code again, you would find that there is only pin names depend on microcontroller platform. There is no specific flag, macro, register name vice versa related to a platform. You can test the project on LPC1768, than move the code to STM32F102 or even into CC430F series microcontroller. Only the pin names need to be changes (for instance pa2 for CC430F5137).. You don’t have to know the registers, how the edge detection is accomplished, how the timers work, how the CPU is made enter into low power mode etc. All you need to know about is the Acore framework..