modern C++ job dispatcher

This forum is about you. Feel free to discuss anything is related to embedded and electronics, your awesome projects, your ideas, your announcements, not necessarily related to ChibiOS but to embedded in general. This forum is NOT for support.
User avatar
alex31
Posts: 380
Joined: Fri May 25, 2012 10:23 am
Location: toulouse, france
Has thanked: 38 times
Been thanked: 62 times
Contact:

modern C++ job dispatcher

Postby alex31 » Tue Jan 02, 2024 11:43 am

Hello, not really a project, just small module to discuss the use of modern C++ in embedded world.

What can modern C++ can do for us, embedded developers ?
I am not a C++ expert, but I want to submit for educational and criticism purpose a module small enough to be readable in minutes, and big enough to be useful.
The module is a job dispatcher, with an API close to the C language ChibiOS one.
Modern C++ stuff that are used are
• variant (remember discriminated records in Ada ?)
• template parameter pack
• concept
• lambda
Variant permits to safely choose the type of the argument to the callback, without cast, neither in the module nor in the calling side. Type errors will be trapped during compilation.
Parameters pack permits to list all the types that can be used
Concepts permit, in case of incorrect use of the API, to limit compiler output to dozens of lines instead of hundreds of pages, still not as readable as I hoped, but usable.
Lambda permit to have the code that is executed in the job dispatcher thread, at the same level than the submitXXX function, that can ease code reading.

The module is one header file : https://github.com/alex31/chibios_enac_ ... bQueue.hpp

the API is simple : 3 methods to declare the jobqueue, then submit job from thread or ISR
overhead is low, does not use heap, only overhead is a copy of the argument passed to the queue : argument has to be constructed on the heap, then the module copies it to the queue.

Example of use :

Code: Select all

#include <ch.h>
#include <hal.h>
#include "jobQueue.hpp"

struct BaroData {
  float p;
  float t;
};
auto& jq = JobQueue<4, BaroData, int>::instance();

static const GPTConfig gptcfg = {
  .frequency    = 10'000,
  .callback     = [](GPTDriver *gptd) {
    chSysLockFromISR();
    static int i = 0;
    if (gptd == &GPTD4) {
      jq.submitI([](int &_i) {
   chprintf(chp, "FROM GPTD4 i = %d\r\n", _i);
      }, i++);
    } else {
      jq.submitI([](BaroData &bd) {
   chprintf(chp, "FROM GPTD5 p,t = %.2f, %.2f\r\n", bd.p, bd.t);
      }, (BaroData){.p = 1013.5, .t = 13.5});
    }
    chSysUnlockFromISR();
  },
  .cr2 = 0,
  .dier = 0
};


void _init_chibios() __attribute__ ((constructor(101)));
void _init_chibios() {
  halInit();
  chSysInit();
}

int main(void)
{
  consoleInit();
  consoleLaunch();

  gptStart(&GPTD5, &gptcfg);
  gptStart(&GPTD4, &gptcfg);
  gptStartContinuous(&GPTD5, 500);
  gptStartContinuous(&GPTD4, 500);
  chThdSleep(TIME_INFINITE);
}

happy C++ coding.
Alexandre

Return to “User Projects”

Who is online

Users browsing this forum: Google [Bot] and 5 guests