element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Embedded and Microcontrollers
  • Technologies
  • More
Embedded and Microcontrollers
Blog Port an MBED design to non-MBED - Phase 1: compile without errors
  • Blog
  • Forum
  • Documents
  • Quiz
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Embedded and Microcontrollers to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 9 Nov 2019 7:25 PM Date Created
  • Views 1663 views
  • Likes 7 likes
  • Comments 7 comments
  • mbed
Related
Recommended

Port an MBED design to non-MBED - Phase 1: compile without errors

Jan Cumps
Jan Cumps
9 Nov 2019

There are many good MBED examples. It's a popular platform, supported by many manufacturers.

Here's my story on how to port one of those excellent MBED example program to another platform.

 

The program I want to port is the SemTech LoRa Ping-Pong example.

The goal is to get a reusable C++ library that can be used on micro controllers, Raspberry Pi, BeagleBone etc...

I need to find what part of the code is dependent on MBED and factor that out.

The factored-out part is the one that will have to be implemented for the target non-MBED platform.

If I get this working, in the end I have to provide an abstract C++ library that only depends on standard libraries, and a document that specs, for the missing parts, what extra functionality is needed.

I expect that the missing  (to be ported) parts are GIO, SPI and UART (optional image).

 

As test bed, I'm using a Texas Instruments Hercules micro controller. It could be any platform that supports SPI and GPIO.

I selected this one because I have two identical boards and my example is a radio Send + Receive scenario (two SemTech radios pinging and ponging each other).

 

There are several ways to replace one utility/service library by another.

In the case where there is documentation of dependencies, one can start from that.

In the case where the dependencies are to be detected from sources, there are also a few options.

You can walk through the code and flag all constructs that are dependent on the library you want to replace.

Another option is to hide that library from the build process and let the build log point out what's broken.

That's the approach I'm using here.

 

 

 

Task 1: Break the Dependency with MBED

 

The easiest way to find dependencies is to cut away the MBED sources and libraries. Then use the tool chain build errors to point at the gaps. Tools are more efficient than a full manual gap analysis in many cases.

You can start from an empty project for your target platform.

For a Pi, that could be a "Hello, world!" Linux project in Eclipse. For my platform, I used a minimal Hercules project.

As long as you have a project that successfully runs on your target (it does not have to do anything functional), you are good to go.

If you do that, you have broken the MBED link. You now have a non-MBED project as starting point.

Take care that you don't have any build errors or warnings left. We'll use the build error log in the next step to help replace the functions provided by MBED.

 

Task 2:  Integrate the MBED Example Code in your Project

 

This is the step where you copy the sources (h and cpp) from the MBED example to your project.

Usually, the library code can just be copied and pasted into your project.

You'll have to do some manual work to merge your project's main file with the main from the MBED example.

Take care that you take over all includes, move all declarations above your project's main() declaration, and add the example's main() functionality to that of your project.

Save everything. Then, just for kicks, build the example. You'll have many errors.

 

Task 3: Collect Unresolved MBED Dependencies

 

For all the errors that you have now during compilation, you'll have to provide a replacement.

My approach is to create a honeypot to put all the unresolved issues. I use a header file called missing.h for that.

First, I replace any occurance of mbed.h with missing.h in the project.

Then I compile again.

 

I then look at the errors in the build log and look for the ones that occur a lot.

I investigate the top one and try to find out what the dependency is.

A common miss is the digital i/o api from MBED.

What I then do, is look up the declaration of the missing dependency online (example: DigitalInOut).

I then create a minimal replacement of the declaration, without implementation, in the missing.h file.

 

Example:

 

class DigitalIn {
public:
  DigitalIn(PinName pin) {}
};

class DigitalOut {
public:
  DigitalOut(PinName pin) {}
  DigitalOut &operator= (int value) {}
  DigitalOut &operator= (DigitalOut &rhs) {}
};

class DigitalInOut {
public:
  DigitalInOut(PinName pin) {}
  DigitalInOut &operator= (int value) {}
  DigitalInOut &operator= (DigitalInOut &rhs) {}
  operator int() {}
  void input() {}
  void output() {}
};

 

You'll see that my classes are not complete. I only put those dependencies that break the build. And they have an empty implementation.

But those are the indicators of what functionality is missing.

 

I perform this exercise iterative.

  • find a build error
  • implement an empty implementation in missing.h
  • check that the build error is resolved
  • rinse and repeat

 

The number of comilation errors has to decrease whle doing that exercise. Repeat until no compilation errors (ignore link issues)

In my case, at the end of the exercise, I end with this missing.h file:

 

/*
 * missing.h
 *
 *  Created on: 9 nov. 2019
 *      Author: jancu
 */


#ifndef CPP_MISSING_H_
#define CPP_MISSING_H_


#include "HL_sys_common.h"


#include <stdio.h>
#include <string.h>


// define all MBED APIs, classes and defines used in the example


typedef enum {
    PIN_INPUT,
    PIN_OUTPUT
} PinDirection;


typedef enum {
  PA_0  = 0x00,
  PA_1  = 0x01,
  PA_2  = 0x02,
  PA_3  = 0x03,
  PA_4  = 0x04,
  PA_5  = 0x05,
  PA_6  = 0x06,
  PA_7  = 0x07,
  PA_8  = 0x08,
  PA_9  = 0x09,
  PA_10 = 0x0A,
  PA_11 = 0x0B,
  PA_12 = 0x0C,
  PA_13 = 0x0D,
  PA_14 = 0x0E,
  PA_15 = 0x0F,
  PB_0  = 0x10,
  PB_1  = 0x11,
  PB_2  = 0x12,
  PB_3  = 0x13,
  PB_4  = 0x14,
  PB_5  = 0x15,
  PB_6  = 0x16,
  PB_7  = 0x17,
  PB_8  = 0x18,
  PB_9  = 0x19,
  PB_10 = 0x1A,
  PB_12 = 0x1C,
  PB_13 = 0x1D,
  PB_14 = 0x1E,
  PB_15 = 0x1F,


  PC_0  = 0x20,
  PC_1  = 0x21,
  PC_2  = 0x22,
  PC_3  = 0x23,
  PC_4  = 0x24,
  PC_5  = 0x25,
  PC_6  = 0x26,
  PC_7  = 0x27,
  PC_8  = 0x28,
  PC_9  = 0x29,
  PC_10 = 0x2A,
  PC_11 = 0x2B,
  PC_12 = 0x2C,
  PC_13 = 0x2D,
  PC_14 = 0x2E,
  PC_15 = 0x2F,


  PD_2  = 0x32,


  PH_0  = 0x70,
  PH_1  = 0x71,
  A0          = PA_0,
  A3          = PB_0,
  A4          = PC_1,


  D1          = PA_2,
  D2          = PA_10,
  D3          = PB_3,
  D4          = PB_5,
  D5          = PB_4,
  D6          = PB_10,
  D7          = PA_8,
  D8          = PA_9,
  D9          = PC_7,
  D10         = PB_6,
  D11         = PA_7,
  D12         = PA_6,
  D13         = PA_5,
  D14         = PB_9,
  D15         = PB_8,


    // Generic signals namings
    LED1        = 0x05,
    LED2        = 0x05,






    // Not connected
    NC = (int)0xFFFFFFFF
} PinName;


class SPI {
public:
 SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel = NC) {}
 virtual int write(int value){return 0;}
 void format(int bits, int mode = 0) {}
};


class DigitalIn {
public:
  DigitalIn(PinName pin) {}
};


class DigitalOut {
public:
  DigitalOut(PinName pin) {}
  DigitalOut &operator= (int value) {}
  DigitalOut &operator= (DigitalOut &rhs) {}
};


class DigitalInOut {
public:
  DigitalInOut(PinName pin) {}
  DigitalInOut &operator= (int value) {}
  DigitalInOut &operator= (DigitalInOut &rhs) {}
  operator int() {}
  void input() {}
  void output() {}
};


template <typename F>
 class Callback;


class InterruptIn {
public:
  InterruptIn(PinName pin) {}
  void rise(void) {}
};


class Timeout{
protected:
  virtual void handler() {}
public:
  void detach() {}
};


// placeholder for all calls used in the MBED example that don't have an implementation
static inline void debug(const char *format, ...) {}
static inline void debug_if(int condition, const char *format, ...) {}




void wait_ms( int ) {}


void wait( int ) {}


double ceil(double) {return 0.0;}


double floor(double) {return 0.0;}


double rint(double) {return 0.0;}


#endif /* CPP_MISSING_H_ */

 

Some constructs are cumbersome to resolve, e.g.: the MBED Callback template construct.

In those cases, where it takes longer to do this exercise than it would be to build a final solution, I comment out the failing code and put a // todo: comment in the source.

Eclipse and other editors have a Task view that shows the things that have to be resolved in source code.

 

image

 

Work Items at This Stage

 

At this point, where there are 0 compilation errors left, we have a list of manageable work items.

    • All code in missing.h. Each of those will need a MBED-independent implementation.
      There's no need to implement it identical to MBED. But it's a good starting point. I think that the MBED object oriented abstractions are neat. Better than what I usually come up with.
    • The tasks in the Todo window. hose are all pieces of code you commented out but are needed for a working design.
      This is a good time to try and dig into those constructs, get a better understanding and create a solution that works on your non-MBED target platform.

Next steps for this blog: Resolve these gaps for my project and document them.

 

Because the Hercules projects are typically C, and the MBED libs are C++, I also had to provide a bridge between the two. A non-intrusive one.

Here's the write-down of that Hercules Safety Microcontroller: Use C++ with HALCoGen C Projects..

 

Related blog
Use C++ with HALCoGen C Projects

Port an MBED design to non-MBED - Phase 1: compile without errors

Port an MBED design to non-MBED - Phase 2a: DigitalOut Class Constructor
Port an MBED design to non-MBED - Phase 2b: DigitalOut Class and Blinky example
Port an MBED design to non-MBED - Phase 3: InterruptIn Class and example
Port an MBED design to non-MBED - Phase 4: Timeout Class and Blinky example
Port an MBED design to non-MBED - Phase 5: OO Callbacks Simplified
  • Sign in to reply

Top Comments

  • Jan Cumps
    Jan Cumps over 5 years ago +1
    The main functionality I'm missing at this point is difital GPIO and SPI and interrupt callbacks. It should not be too hard to come up with a design for the first two that's close to the MBED design. The…
  • Jan Cumps
    Jan Cumps over 5 years ago +1
    ... next steps are to solve those parts that are not strictly MBED dependencies, but C++ dependencies that are resolved somewhere in th MBED includes. I have these instances: memory copy and I/O (not gpio…
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to shabaz +1
    I often do the same The MBED example for the SemTech chip doesn't use the MBED OS's job scheduler - it's a straightforward main loop approach. They use some library functions though. The deeper I drill…
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to Jan Cumps

    I got rid of the .init_array linker error.

     

    .init_array section is where the C++ libraries put C++ CONSTRUCTOR TABLES

    I checked in other microcontrollers where they put that, and they typically use the same location as the .pinit section

    So I ammended my linker file

     

        .pinit  align(32) : {} > FLASH0 | FLASH1
    
    /* USER CODE BEGIN (6) */
        .init_array align(32) : {} > FLASH0 | FLASH1              /* C++ CONSTRUCTOR TABLES            */
    /* USER CODE END */
    }

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 5 years ago

    Some further progress

     

    The non-working project now compiles with 3 warnings left:

    image

    The first one I have to look into. I'm using the correct linker file for my controller but one source somewhere seems to have a sections pragma.

     

    The 2 others are to be ignored, because they are a result of me commenting out code dependencies for things I have to write.

     

    Here are the to-dos to get the cycle closed:

     

    TODO DigitalIn.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 11 C/C++ Task
    TODO DigitalInOut.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 11 C/C++ Task
    TODO DigitalInOut.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 15 C/C++ Task
    TODO DigitalInOut.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 22 C/C++ Task
    TODO DigitalInOut.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 27 C/C++ Task
    TODO DigitalInOut.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 33 C/C++ Task
    TODO DigitalInOut.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 38 C/C++ Task
    TODO DigitalOut.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 11 C/C++ Task
    TODO DigitalOut.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 18 C/C++ Task
    TODO DigitalOut.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 25 C/C++ Task
    TODO InterruptIn.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 11 C/C++ Task
    TODO SPI.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 11 C/C++ Task
    TODO SPI.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 15 C/C++ Task
    TODO SPI.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 20 C/C++ Task
    TODO SPI.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 24 C/C++ Task
    TODO = fix this->dioIrq[5] = NULL; sx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 68 C/C++ Task
    TODO Auto-generated constructor stub SemTechSx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp line 126 C/C++ Task
    TODO Auto-generated constructor stub Timeout.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 11 C/C++ Task
    TODO Auto-generated destructor stub SemTechSx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp line 131 C/C++ Task
    TODO Auto-generated destructor stub Timeout.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/implementation_dependent/client_platform line 16 C/C++ Task
    TODO fix tmath dependencies sx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 528 C/C++ Task
    TODO fix tmath dependencies sx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 578 C/C++ Task
    TODO fix tmath dependencies sx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 829 C/C++ Task
    TODO fix/port             if( this->dioIrq[4] == NULL ) sx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 1469 C/C++ Task
    TODO implement wait_ms( 1 ); sx1276-hal.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 95 C/C++ Task
    TODO implement wait_ms( 1 ); sx1276-hal.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 105 C/C++ Task
    TODO implement wait_ms( 1 ); sx1276-hal.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 304 C/C++ Task
    TODO implement wait_ms( 1 ); sx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 108 C/C++ Task
    TODO implement wait_ms( 1 ); sx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 147 C/C++ Task
    TODO implement wait_ms( 1 ); sx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 665 C/C++ Task
    TODO implement wait_ms( 10 ); SemTechSx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp line 228 C/C++ Task
    TODO implement wait_ms( 10 ); SemTechSx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp line 243 C/C++ Task
    TODO implement wait_ms( 10 ); SemTechSx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp line 268 C/C++ Task
    TODO implement wait_ms( 10 ); SemTechSx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp line 302 C/C++ Task
    TODO implement wait_ms( 10 ); SemTechSx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp line 321 C/C++ Task
    TODO implement wait_ms( 10 ); SemTechSx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp line 332 C/C++ Task
    TODO implement wait_ms( 10 ); sx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 56 C/C++ Task
    TODO implement wait_ms( 6 ); sx1276-hal.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 306 C/C++ Task
    TODO implement wait( 1 ); SemTechSx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp line 158 C/C++ Task
    TODO implement wait(0.1); sx1276-hal.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 140 C/C++ Task
    TODO port SX1276MB1xAS Radio( NULL ); SemTechSx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp line 104 C/C++ Task
    TODO port this. It was too complex to just move to missing.h sx1276-hal.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 153 C/C++ Task
    TODO port this. It was too complex to just move to missing.h sx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 925 C/C++ Task
    TODO port this. It was too complex to just move to missing.h sx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 980 C/C++ Task
    TODO port this. It was too complex to just move to missing.h sx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 1121 C/C++ Task
    TODO port this. It was too complex to just move to missing.h sx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 1209 C/C++ Task
    TODO port this. It was too complex to just move to missing.h sx1276.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 1259 C/C++ Task
    TODO set for client board sx1276-hal.cpp /TMS570LC43_semtech_sx1276_cpp/cpp/sx1276/sx1276 line 137 C/C++ Task

     

    A lot of work but many are repeats.

    • 1 to 15 and 48 are code I need to write.
    • 17 to 20 are empty constructors and destructors. Some need work, some can stay empty
    • 21 to 23 are a little harder to resolve because I may have stumbled on a know error of my compiler. I may have to provide an own implementation for 3 tmath functions.
    • 25 to 40 can be fixed in a single throw. Just need to write 2 functions that implement wait() and wait_ms() for the target controller
    • 42 to 47 are the callback mechanism for interrupts. Todo.
    • 16 and 41: random activities
    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 5 years ago in reply to Jan Cumps

    Jan Cumps  wrote:

     

    I I think that there are some good object oriented designers involved with the MBED development.

     

    Agree. It all feels production-grade. Also, there's a vast amount of functionality. mbed is a awesome system.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to shabaz

    I often do the same image

     

    The MBED example for the SemTech chip doesn't use the MBED OS's job scheduler - it's a straightforward main loop approach. They use some library functions though.

    The deeper I drill into those, the more I like them. I think that there are some good object oriented designers involved with the MBED development.

    So if I can port this while keeping their mechanisms (and blogging about them in awe image ) during the next Project14 RF month, I'll do that.

    If I fail to complete it by then, I'll take all shortcuts and approaches that I deem fit for purpose image.

     

    It's also a refresher for me. I've been a C++ developer at the beginning of my IT career - claimed being an expert at that time. I lost some of that and this is a chance to get back on level ....

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 5 years ago

    Hi Jan,

     

    This is really great progress. This will be extremely useful to anyone who wishes to work with LoRa!

    Regarding interrupt handling, if you're trying to make it cross-platform to work without an OS too, I'm sure you have your favourite methods to do it, for what it's worth for hobby stuff I sometimes I just have a timer tick always running (say every millisecond or ten millisec), and execute my state machine in there (since that doesn't take much overhead and executes quickly). Then, any messages to the state machine just become the setting of variables, and similarly any code that needs to be executed by the state machine is another variable change.. and a main while forever loop handles each message at a time. This is super-basic and full of holes if not done carefully, but at least is supported everywhere that a timer tick or periodic function works, and doesn't need threads either, nor C++. On larger systems there's the luxury of using actual real-time middleware of course, but that turns it all into a more major project.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube