Peripherals

It this chapter I will describe and give multiple examples of how to drive and control multiple hardware peripherals while using Device-Driver-Component model in conjunction with Event Loop.

All the generic, platform independent code provided here is implemented as part of embxx library while platform (Raspberry Pi) specific code is taken from embxx_on_rpi project.

All the platform specific peripheral control classes reside in src/device directory.

The src/app directory contains several simple applications, such as flashing the led or responding to button presses.

There are also common Component classes shared between the applications. They reside in src/component directory.

In order to compile all the applications please follow the instructions described in Contents of This Document.

Function Configuration

In ARM platform every pin needs to be configured as either gpio input, gpio output or having one of several alternative functions the microcontroller supports. The device::Function class defined in src/device/Function.h and src/device/Function.cpp implements simple interface which allows every Device class configure the pins it uses.

class Function
{
public:
    enum class FuncSel {
        Input,  // b000
        Output, // b001
        Alt5,   // b010
        Alt4,   // b011
        Alt0,   // b100
        Alt1,   // b101
        Alt2,   // b110
        Alt3    // b111
    };

    typedef unsigned PinIdxType;

    static const std::size_t NumOfLines = 54;

    void configure(PinIdxType idx, FuncSel sel);
};

Every implemented Device class will receive reference to Function object in its constructor and will have to use it to configure the pins as required.

Interrupts Management

There is one more componenet that every Device will use. It's device::InterruptMgr defined in src/device/InterruptMgr.h. The main responsibility of the object of this class is to control global level interrupts, register interrupt handlers from various Devices and invoke the appropriate handler when interrupt occurs.

The interface of the device::InterruptMgr is defined as following:

Every Driver will use registerHandler() member function to register its member function as the handler for its IrqId. The enableInterrupt() and disableInterrupt() are also used by the Device objects to control their interrupts on global level.

In order to use the Interrupt Manager described above every application has to implement proper interrupt handler that will retrieve the reference to device::InterruptMgr object (via global/static variables) and invoke its handleInterrupt() function, which in turn check the appropriate status register(s) and invoke registered handler(s). Please note, that the handler will be executed in interrupt context.

The code will look something like this:

There may also be a need to enable/disable all the interrupts by toggling i flag in CPS register. The same src/device/InterruptMgr.h file provides two function for this purpose:

Last updated

Was this helpful?