This repository collected the well proved routines of B2B & M2M infrastructure implementation of electronics device side.
Is aimed mainly in event-driven and/or single thread environment with variable frequency of the system ticks (power consumption management). And, of course, code reuse techniques by С++. This routines can be used in synchronous algorithms with multithreaded RTOS like scmRTOS (that can really unlock the potential of C++).
Tested in GNU Arm C++11 toolchain.
Modern development of electronic devices requires integration into the data aquisition & control infrastructure. So, the embedded developer must have wide knowledge. And be better if several developers will be involved in development process. But how to realize the collaboration along development process. There is solution: provide the system of pieces like a puzzle.
C++ is one the sane system-forming tool for bare-bone systems. Of course, with strictly approach according to restrictions of the tool chain (compiler) and hardware abilities:
Almost all needs by business logic & hardware implementation satisfied by next opportunities: timers, system-wide events and algorithms with external API.
Timer callback infrastracture.
This implementation not needs common header file to declare the timers array. Linker collect information about timers. This technique has key advantage of static linkage and automatic declaration of timers array. Count of timers exactly as needs.
Memory model has two pieces: ROM (timers callback table) and RAM (timers statuses table):
Runtime conseption includes system tick handler that calls callbacks according to ROM and RAM tables:
Example:
#include "Services/Timer.h"
TIMER_DECLARE(ExampleTimer) // declare the timer holder variable
void some_function()
{
auto timestamp = Timer::Now(); // system time, mS
Timer::Start(1000, TIMER_STATE(ExampleTimer)); // start the timer with interval; if timer is running - nothing will changed
Timer::Start(1000, TIMER_STATE(ExampleTimer), true); // set a new timer interval
auto interval = Timer::Interval(TIMER_STATE(ExampleTimer)); // get timer interval
auto isStarted = Timer::isStarted(TIMER_STATE(ExampleTimer));
}
// timer callback function
TIMER_CALLBACK(ExampleTimer)
{
Timer::Stop(TIMER_STATE(ExampleTimer));
}
The electronic device Services infrastracture.
Business logic often needs in wide opportunities for the performance of the algorithms. So, Service is event-driven system with system wide state of components that compound the system.
Usually, Service represent a block from functional scheme. And has relationships with other Services that consume and produce system-wide events according with hardware processing of concrete Service.
Example of S1 button service with button IRQ handler:
Example.h file:
namespace Services
{
namespace Example
{
enum class StateEnum { Start = 1, USB_Power = 2, S1_Pressed = 4 , S1_LongPressed = 8 };
enum class StateLocalEnum { S1 = 1, Overload = 2 };
extern const char *ServiceName;
}
}
Example.cpp file:
#include "Services/IService.h"
#include "Services/main.h" // main service. Used for the system-wide statuses & pulses
#include "Example.h"
namespace Services
{
namespace Example
{
const char *ServiceName = "Example";
//! Enable/disable the service
//! @note Called to enable/disable of events process for this service
static bool Enable(bool enable)
{
if(enable)
{
// enable the hardware
}
else
{
// disable the hardware
}
}
//! State changed by another service
static void StateChanged(const char *name, StateType stateBits, StateType changedStateMask)
{
if(name == Services::Main::ServiceName)
{
if(changedStateMask | (StateType)Services::Main::StateEnum::Start)
{
// main start/stop - the system-wide pulse
if(stateBits | (StateType)Services::Main::StateEnum::Start)
{
// start of the system // start processing of S1 button
}
else
{
// stop of the system // stop processing of S1 button
}
}
}
}
//! State changed by this service
//! @note Called at end of events process round
static void StateChangedBy(const char *name, StateType &stateBits, StateType changedStateMask)
{
// processing the pulses
if(changedStateMask & (StateType)StateEnum::S1_Pressed)
// clear a state bit
stateBits &= ~(StateType)StateEnum::S1_Pressed;
}
//! Local state changed by an IRQ of this service
void LocalStateChanged(const char *name __attribute__((unused)), StateType &stateBits)
{
if(stateBits & (StateType)StateLocalEnum::Overload)
{
// overload // previous button press by IRQ handler was not handled
}
if(stateBits & (StateType)StateLocalEnum::S1)
// S1 button pressed by IRQ handler
SERVICE_STATE(Example).SetState(StateEnum::S1_Pressed)
stateBits = 0;
}
// declare the service holder variables
SERVICE_DECLARE(Example, &Enable, &StateChanged, &StateChangedBy, &LocalStateChanged)
}
}
extern "C"
{
// S1 button handler // for STM32 hardware
void EXTI4_15_IRQHandler()
{
if(EXTI->PR & EXTI_PR_PIF13) // is pending interrupt
{
EXTI->PR |= EXTI_PR_PIF13; // clear pending interrupt
// set the local state from IRQ context
if(SERVICE_STATE(Example).LocalChangedState & StateLocalEnum::S1)
// overload // previous button press was not handled
SERVICE_STATE(Example).SetLocalState((Services::StateType)StateLocalEnum::Overload);
SERVICE_STATE(Example).SetLocalState((Services::StateType)StateLocalEnum::S1);
}
}
}
File system for M2M infrastructure.
Data cache as memory buffer for page by page access basis. This is part of filesystem with FLASH storage devices and used to achieve the provided lifetime.
Holds one page in RAM buffer while write process and flush the buffer when write to another page happends. Has PreFlushCallbackStruct to finalize page data before flush (write). This can be used in the deferred CRC calculation mechanism and for another actions for page data finalization.
Class | Description |
---|---|
UsbBase | Base class for hardware abstraction from USB specification. |
Cdc | USB Class Definitions for Communication Devices. Successor of UsbBase class. |