Move object creation to setup() function of arduino - c

I've created a class that handles sending data to a led matrix (max7219).
This is what I was doing to create an instance of the LedControl class.
LedControl lc=LedControl(11, 13, 12);// data, clock, latch;
void setup()
{
...
}
Now I'm trying to add timer-interrupts to my class. But I found that I can't set the appropriate registries in the initializer (LedControl::LedControl()). If I move this code to setup, it all works perfectly. My guess is that the Arduino bootloader, which uses timer1 for PWM overwrites these registries, just before calling setup() but after my object has been initialized.
So my idea was to just move the object creation to the setup function like so
// FAIL
LedControl lc;
void setup()
{
lc=LedControl(11, 13, 12);// data, clock, latch;
...
}
But then I get the error no matching function for call to 'LedControl::LedControl()'
I tried using pointers (LedControl *lc; lc=&LedControl(11, 13, 12);), but as far as I could tell, this would mean I would have to write (*lc).someFunction() everywhere instead of lc.someFunction(). Even less elegant than moving the registry setting code to setup().
So my question is. How do I create an object in the setup() function, but still have a global variable pointing to it?

Your first error "no matching.. " is because you have no default constructor. You can make that approach function.
Add a no parameter, AKA default constructor, to the class, like this:
class LedControl {
LedControl();
LedControl(uint8_t pin1, uint8_t pin2, uint8_t pin3);
private:
uint8_t pin1;
uint8_t pin2;
uint8_t pin3;
};
LedControl::LedControl() : pin1(0), pin2(0), pin3(0) {
// this constructor leaves the class unusable
}
LedControl::Ledcontrol(uint8_t p1, uint8_t p2, uint8_t p3)
: pin1(p1), pin2(p2), pin3(p3)
{
// this object is ready to use
}
With this class, your approach will work, but is not the optimal method. This line does too much work:
void setup() {
lc = LedControl(11, 13, 12);// data, clock, latch;
}
This line of code involves the compiler creating some code for you:
First another instance of the class is constructed on the stack using the parameters 11,13,12.
Then it applies the = operator copying the data from the stack object to your global object.
When setup() exits, the stack object is flushed.
Because the temporary object is on the stack, your program didn't use too much memory, but your code size is larger because it involves extra operations to construct the temporary then copy from the temporary to the permanent.
Note that the compiler is creating an = operator for you, to fill the function of the line
lc = LedControl(11, 13, 12);
This may or may not work depending on what is in your constructor. The compiler can only presume that you needed a simple = operator. All the basic assignment operator will do is copy all the data members from the instance on the right side of the = to the instance on the left side. The compiler constructed = will not contain any code.
If your constructor does anything significant (other than save the parameters) then the compiler constructed(guessed) assignment operator may not work as you expected. For your case the constructor probably sets the pin modes, something like this:
LedControl::LedControl(uint8_t p1, uint8_t p2, uint8_t p3)
: pin1(p1), pin2(p2), pin3(p3)
{
pinMode(pin1, INPUT);
pinMode(pin2, OUTPUT);
pinMode(pin3, OUTPUT);
return;
}
This happens to function, but only by chance. The pinMode() calls are made when the temporary object is constructed and called from that object, not from the global lc. Because pinMode()'s are global this case will achieve the correct goal, but maybe not in the way expected. For more complex operations such as registering interrupt handlers, you will need to create your own assignment operator:
LedControl& operator= (const LedControl & other);
In that method, you could ensure that the state of the global lc is what you need. An easier/safer approach is to not deal with that at all.
A simple and efficient approach, you may have seen in other libraries is to add a method to the class that assigns the pins:
class LedControl {
void attach(uint8_t pin1, uint8_t pin2, uint8_t pin3);
};
void LedControl::attach(uint8_t pin1, uint8_t pin2, uint8_t pin3) {
this.pin1 = pin1;
this.pin2 = pin2;
this.pin3 = pin3;
// do other setup type operations
return;
}
Now your program, constructs the blank object, and assigns pins during setup():
LedControl lc; // not ready to use until attach pins
void setup() {
lc.attach(11, 13, 12);// data, clock, latch;
...
}
This involves no temporary object construction, and no assignment operator. With respect to design, some people might fairly comment that the user might forget to call attach() and leave the global lc object unusable. For a desktop application, you might add some code to prevent that failure case. For an embedded application, that is a risk you accept which is balanced by the gains in code size or memory savings.

I just stumbled over the same problem. I wanted to create a global debug port object, but I couldn't create it as global instance, as the port won't work after setup() was called. I have the same assumptions that the arduino code does some setup stuff after my constructor (of the global object) and before setup().
I found it the easiest solution, to declare my object as a pointer and init it in setup. In your situation it would be:
LedControl* lc;
void setup()
{
lc = new LedControl(11, 13, 12);// data, clock, latch;
}
void loop()
{
lc->doSomething();
}
So there's no need for additional constructors or operators.
As the object is used until power down, theres is no delete needed in this case.

Related

How do you avoid using global variables in inherently stateful programs?

I am currently writing a small game in C and feel like I can't get away from global variables.
For example I am storing the player position as a global variable because it's needed in other files. I have set myself some rules to keep the code clean.
Only use a global variable in the file it's defined in, if possible
Never directly change the value of a global from another file (reading from another file using extern is okay)
So for example graphics settings would be stored as file scope variables in graphics.c. If code in other files wants to change the graphics settings they would have to do so through a function in graphics.c like graphics_setFOV(float fov).
Do you think those rules are sufficient for avoiding global variable hell in the long term?
How bad are file scope variables?
Is it okay to read variables from other files using extern?
Typically, this kind of problem is handled by passing around a shared context:
graphics_api.h
#ifndef GRAPHICS_API
#define GRAPHICS_API
typedef void *HANDLE;
HANDLE init_graphics(void);
void destroy_graphics(HANDLE handle);
void use_graphics(HANDLE handle);
#endif
graphics.c
#include <stdio.h>
#include <stdlib.h>
#include "graphics_api.h"
typedef struct {
int width;
int height;
} CONTEXT;
HANDLE init_graphics(void) {
CONTEXT *result = malloc(sizeof(CONTEXT));
if (result) {
result->width = 640;
result->height = 480;
}
return (HANDLE) result;
}
void destroy_graphics(HANDLE handle) {
CONTEXT *context = (CONTEXT *) handle;
if (context) {
free(context);
}
}
void use_graphics(HANDLE handle) {
CONTEXT *context = (CONTEXT *) handle;
if (context) {
printf("width = %5d\n", context->width);
printf("height = %5d\n", context->height);
}
}
main.c
#include <stdio.h>
#include "graphics_api.h"
int main(void) {
HANDLE handle = init_graphics();
if (handle) {
use_graphics(handle);
destroy_graphics(handle);
}
return 0;
}
Output
width = 640
height = 480
Hiding the details of the context by using a void pointer prevents the user from changing the data contained within the memory to which it points.
How do you avoid using global variables in inherently stateful programs?
By passing arguments...
// state.h
/// state object:
struct state {
int some_value;
};
/// Initializes state
/// #return zero on success
int state_init(struct state *s);
/// Destroys state
/// #return zero on success
int state_fini(struct state *s);
/// Does some operation with state
/// #return zero on success
int state_set_value(struct state *s, int new_value);
/// Retrieves some operation from state
/// #return zero on success
int state_get_value(struct state *s, int *value);
// state.c
#include "state.h"
int state_init(struct state *s) {
s->some_value = -1;
return 0;
}
int state_fini(struct state *s) {
// add free() etc. if needed here
// call fini of other objects here
return 0;
}
int state_set_value(struct state *s, int value) {
if (value < 0) {
return -1; // ERROR - invalid argument
// you may return EINVAL here
}
s->some_value = value;
return 0; // success
}
int state_get_value(struct state *s, int *value) {
if (s->some_value < 0) { // value not set yet
return -1;
}
*value = s->some_value;
return 0;
}
// main.c
#include "state.h"
#include <stdlib.h>
#include <stdio.h>
int main() {
struct state state; // local variable
int err = state_init(&state);
if (err) abort();
int value;
err = state_get_value(&state, &value);
if (err != 0) {
printf("Getting value errored: %d\n", err);
}
err = state_set_value(&state, 50);
if (err) abort();
err = state_get_value(&state, &value);
if (err) abort();
printf("Current value is: %d\n", value);
err = state_fini(&state);
if (err) abort();
}
The only single case where global variables (preferably only a single pointer to some stack variable anyway) have to be used are signal handlers. The standard way would be to only increment a single global variable of type sig_atomic_t inside a signal handler and do nothing else - then execute all signal handling related logic from the normal flow in the rest of the code by checking the value of that variable. (On POSIX system) all other asynchronous communication from the kernel, like timer_create, that take sigevent structure, they can pass arguments to notified function by using members in union sigval.
Do you think those rules are sufficient for avoiding global variable hell in the long term?
Subjectively: no. I believe that a potentially uneducated programmer has too much freedom in creating global variables given the first rule. In complex programs I would use a hard rule: Do not use global variables. If finally after researching all other ways and all other possibilities have been exhausted and you have to use a global variables, make sure global variables leave the smallest possible memory footprint.
In simple short programs I wouldn't care much.
How bad are file scope variables?
This is opinion based - there are good cases where projects use many global variables. I believe that topic is exhausted in are global variables bad and numerous other internet resources.
Is it okay to read variables from other files using extern?
Yes, it's ok.
There are no "hard rules" and each project has it's own rules. I also recommend to read c2 wiki global variables are bad.
The first thing you have to ask yourself is: Just why did the programming world come to loath global variables? Obviously, as you noted, the way to model a global state is essentially a global (set of) variable(s). So what's the problem with that?
The Problem
All parts of the program have access to that state. The whole program becomes tightly coupled. Global variables violate the prime directive in programming, divide and conquer. Once all functions operate on the same data you can as well do away with the functions: They are no longer logical separations of concern but degrade to a notational convenience to avoid large files.
Write access is worse than read access: You'll have a hard time finding out just why on earth the state is unexpected at a certain point; the change can have happened anywhere. It is tempting to take shortcuts: "Ah, we can make the state change right here instead of passing a computation result back up three layers to the caller; that makes the code much smaller."
Even read access can be used to cheat and e.g. change behavior of some deep-down code depending on some global information: "Ah, we can skip rendering, there is no display yet!" A decision which should not be made in the rendering code but at top level. What if top level renders to a file!?
This creates both a debugging and a development/maintenance nightmare. If every piece of the code potentially relies on the presence and semantics of certain variables — and can change them! — it becomes exponentially harder to debug or change the program. The code agglomerating around the global data is like a cast, or perhaps a Boa Constrictor, which starts to immobilize and strangle your program.
Such programming can be avoided with (self-)discipline, but imagine a large project with many teams! It's much better to "physically" prevent access. Not coincidentally all programming languages after C, even if they are otherwise fundamentally different, come with improved modularization.
So what can we do?
The solution is indeed to pass parameters to functions, as KamilCuk said; but each function should only get the information they legitimately need. Of course it is best if the access is read-only and the result is a return value: Pure functions cannot change state at all and thus perfectly separate concerns.
But simply passing a pointer to the global state around does not cut the mustard: That's only a thinly veiled global variable.
Instead, the state should be separated into sub-states. Only top-level functions (which typically do not do much themselves but mostly delegate) have access to the overall state and hand sub-states to the functions they call. Third-tier functions get sub-sub states, etc. The corresponding implementation in C is a nested struct; pointers to the members — const whenever possible — are passed to functions which therefore cannot see, let alone alter, the rest of the global state. Separation of concerns is thus guaranteed.

Accessing structure in structure through pointer

Brief description:
I write something to structure through pointer but something else gets written. I work in atollic true studio 8.1, programming an STM32F415RG MCU.
The strangest thing is that even if I look in variables and expression window, I can see the same structure with different values.
Same variable in two windows with different values
Now to elaborate a bit (I am going to simplify a lot of stuff to make it more readable).
I have my protocol handle type defined:
typedef struct
{
RS485DriverHandle master_rs485;
} EscomProtocolHandle;
My RS485 driver handle is defined as follows:
typedef struct
{
UART_HandleTypeDef* uart_handle;
TransceiverState transceiver_state;
GPIO_TypeDef* dir_gpio;
uint16_t dir_pin;
} RS485DriverHandle;
I have created my protocol handle as a global variable:
static EscomProtocolHandle hprot1;
I pass it to my protocol init function which takes a pointer to handle as an argument:
Escom_Protocol_Init(&hprot1);
Init function passes it to RS485 driver init function which takes pointer to RS485 handle as an argument (this call is simplified a lot):
void Escom_Protocol_Init(EscomProtocolHandle* protocol_handle)
{
RS485_Init(&protocol_handle->master_rs485)
}
RS485 init function sets default values:
void RS485_Init(RS485DriverHandle* rs485_handle, UART_HandleTypeDef* uart_handle,
GPIO_TypeDef* dir_gpio, uint16_t dir_pin)
{
/* default = listening */
rs485_handle->uart_handle = uart_handle;
rs485_handle->dir_gpio = dir_gpio;
rs485_handle->dir_pin = dir_pin;
ReceiverOutputEnable(rs485_handle);
rs485_handle->transceiver_state = kReceiving;
}
Now if I look at the local variable rs485_handle, the values are set correctly. But If I look at my handle hprot1, the values don't match. Even though rs485_handle's address matches the address of master_rs485 member of the hprot1 handle.
P.S.: I have not messed with the packing (#pragma pack) of any of the above mentioned structures, so that should not be an issue.
Got it!
There was a seemingly unrelated header file that had a structure prototype in it which was packed(1) and there was no #pragma pack() after the structre prototype to restore the packing to default state. Thus RS485DriverHandle was packed differently in different places. In both Escom_Protocol_Init and RS485_Init the address of the handle structure was the same, but the packing was different so for example the address of GPIO_TypeDef* dir_gpio member was 0x200000D6 in Escom_Protocol_Init but was 0x200000D9 in RS485_Init.

Shared pointers and queues in FreeRTOS

A C++ wapper around a FreeRTOS queue can be simplified into something like this:
template<typename T>
class Queue<T>
{
public:
bool push(const T& item)
{
return xQueueSendToBack(handle, &item, 0) == pdTRUE;
}
bool pop(T& target)
{
return xQueueReceive(handle, &target, 0) == pdTRUE;
}
private:
QueueHandle_t handle;
}
The documentation of xQueueSendToBack states:
The item is queued by copy, not by reference.
Unfortunately, it is literally by copy, because it all ends in a memcpy, which makes sense since it is a C API. While this works well for plain old data, more complex items such as the following event message give serious problems.
class ConnectionStatusEvent
{
public:
ConnectionStatusEvent() = default;
ConnectionStatusEvent(std::shared_ptr<ISocket> sock)
: sock(sock)
{
}
const std::shared_ptr<ISocket>& get_socket() const
{
return sock;
}
private:
const std::shared_ptr<ISocket> sock;
bool connected;
};
The problem is obviously the std::shared_ptr which doesn't work at all with a memcpy since its copy constructor/assignment operator isn't called when copied onto the queue, resulting in premature deletion of the held object when the event message, and thus the shared_ptr, goes out of scope.
I could solve this by using dynamically allocated T-instances and change the queues to only contain pointers to the instance, but I'd rather not do that since this shall run on an embedded system and I very much want to keep the memory static at run-time.
My current plan is to change the queue to contain pointers to a locally held memory area in the wrapper class in which I can implement full C++ object-copy, but as I'd also need to protect that memory area against multiple thread access, it essentially defeats the already thread-safe implementation of the FreeRTOS queues (which surely are more efficient than any implementation I can write myself) I might as well skip them entirely.
Finally, the question:
Before I implement my own queue, are there any tricks I can use to make the FreeRTOS queues function with C++ object instances, in particular std::shared_ptr?
The issue is what happens to the original once you put the pointer into the queue.
Copying seems trivial but not optimal.
To get around this issue i use a mailbox instead of a queue:
T* data = (T*) osMailAlloc(m_mail, osWaitForever);
...
osMailPut (m_mail, data);
Where you allocate the pointer explicitly to begin with. And just add the pointer to the mailbox.
And to retrieve:
osEvent ev = osMailGet(m_mail, osWaitForever);
...
osStatus freeStatus = osMailFree(m_mail, p);
All can be neatly warpend into c++ template methods.

How to implement separate static variables for a given function called with different parameters

I am currently working on a microcontroller project in C that requires several timed functions to take place. I am a using a hardware timer to produce an interrupt every millisecond, and variables as counters to produce the appropriate time intervals. The hardware details are not important.
As an example, for a particular function, the following code would be executed on every tick of the 1ms counter, resulting in Function() being called every 10ms.
if (count < 10)
{
count++;
}
else
{
Function();
count = 0;
}
I would like to implement a wrapper function to avoid rewriting the counter code for every different interval, i.e:
TimerWrapper(required interval 1, Function 1 pointer)
TimerWrapper(required interval 2, Function 2 pointer)
and call it on every tick of the timer. For this to work, each different function called by the wrapper needs to have a separate count variable that needs to persist between calls of TimerWrapper(). I would like to keep all of the implementation details separate from my main program and introduce as few variables into my main program as possible.
Is it possible to do what I am asking, or is there a simpler/better way to achieve the same effect? I know how I would do this with an object oriented language but my skills are lacking in plain C.
I would think in terms of a structure along the lines of:
struct interrupt_responder
{
int count;
int rep_count;
void (*handler)(void);
};
You then create as many such structures as you have different counters, appropriately initialized:
static struct interrupt_responder c1 = { 0, 10, Function };
You arrange to call a function with the responder:
void time_wrapper(struct interrupt_responder *r)
{
if (++r->count >= r->max_count)
{
r->count = 0;
(*r->handler)();
}
}
The function called in response to an interrupt then simply needs to know how to dispatch calls to time_wrapper with the appropriate argument each time.
void millisecond_interrupt_handler(void)
{
time_wrapper(&c1);
…
}
Or you can have an array of the interrupt responders, and the millisecond interrupt handler can loop over the array, calling the time wrapper function.
You would have a set of file scope variables for the interrupt responders, but they'd not need to be visible outside the file. If you need different argument lists for the handler functions, life is trickier — avoid that if you possibly can. However, it seems from a comment that it won't be a problem — the embedded functions pointers will always be void (*handler)(void).

Store extra data in a c function pointer

Suppose there is a library function (can not modify) that accept a callback (function pointer) as its argument which will be called at some point in the future. My question: is there a way to store extra data along with the function pointer, so that when the callback is called, the extra data can be retrieved. The program is in c.
For example:
// callback's type, no argument
typedef void (*callback_t)();
// the library function
void regist_callback(callback_t cb);
// store data with the function pointer
callback_t store_data(callback_t cb, int data);
// retrieve data within the callback
int retrieve_data();
void my_callback() {
int a;
a = retrieve_data();
// do something with a ...
}
int my_func(...) {
// some variables that i want to pass to my_callback
int a;
// ... regist_callback may be called multiple times
regist_callback(store_data(my_callback, a));
// ...
}
The problem is because callback_t accept no argument. My idea is to generate a small piece of asm code each time to fill into regist_callback, when it is called, it can find the real callback and its data and store it on the stack (or some unused register), then jump to the real callback, and inside the callback, the data can be found.
pseudocode:
typedef struct {
// some asm code knows the following is the real callback
char trampoline_code[X];
callback_t real_callback;
int data;
} func_ptr_t;
callback_t store_data(callback_t cb, int data) {
// ... malloc a func_ptr_t
func_ptr_t * fpt = malloc(...);
// fill the trampoline_code, different machine and
// different calling conversion are different
// ...
fpt->real_callback = cb;
fpt->data = data;
return (callback_t)fpt;
}
int retrieve_data() {
// ... some asm code to retrive data on stack (or some register)
// and return
}
Is it reasonable? Is there any previous work done for such problem?
Unfortunately you're likely to be prohibited from executing your trampoline in more and more systems as time goes on, as executing data is a pretty common way of exploiting security vulnerabilities.
I'd start by reporting the bug to the author of the library. Everybody should know better than to offer a callback interface with no private data parameter.
Having such a limitation would make me think twice about how whether or not the library is reentrant. I would suggest ensuring you can only have one call outstanding at a time, and store the callback parameter in a global variable.
If you believe that the library is fit for use, then you could extend this by writing n different callback trampolines, each referring to their own global data, and wrap that up in some management API.

Resources