I'm still learning C to be used in microprocessors. In the beginning I used lots of globals. Now I'm trying to avoid it as much as a can, but for me it's not always clear to see how to do this.
For example a battery monitor, in this case there are 4 functions that need to read or modify a variable.
I have these functions all using the variable LowVoltage.
void Check_Voltage(){
checks current voltage against LowVoltage
}
void Menu_Voltage(){
a menu on the LCD screen to set the value of LowVoltage
}
void Save_LowVoltage(){
runs after the settings menu is finished to save LowVoltage to EEPROM
}
void Load_LowVoltage(){
reads EEPROM and sets LowVoltage at startup
}
Check_Voltage() and Save_LowVoltage() need to read LowVoltage.
Load_LowVoltage() need to write LowVoltage.
Menu_Voltage() needs to read and write LowVoltage.
How can I make this work without making LowVoltage global??
Would I need to make another function to read or write LowVoltage?
Something like this:
unsigned int Low_Voltage(short Get, unsigned int Value){
static unsigned int LowVoltage;
if(Get) return LowVoltage;
else LowVoltage= Value;
}
Or are there better ways to do this? I guess there must be :)
I've been reading about structures lately, but to be honest I don't fully understand them and I'm not even sure it would help me in cases like this?
There are several choices to sharing a variable among functions:
Allocate your variable in static memory - this is pretty much what your code does. Your two choices there are function-static, translation unit-static, and global
Pass a pointer to variable as function parameter - This choice requires passing the pointer around in some form
Use thread-local storage with clever initialization - This choice is not usually available when you work with microcontrollers; I list it here for completeness.
In your case, I think that using a translation unit-static variable would be appropriate. Put implementations of the four functions into a single C file, and declare LowVoltage at the top as a static variable:
static unsigned int LowVoltage;
This simple but efficient encapsulation mechanism gives you all benefits of having a global variable, without the drawbacks of having a global variable:
All functions inside the C module "see" this variable, and can freely manipulate it
No other functions outside the C module can access this variable. They can declare their own LowVoltage variable, giving it an entirely different meaning.
Two solutions I can think of
Make the function signatures like this
unsigned int Load_LowVoltage(unsigned int lowVoltage);
and then pass LowVoltage and assign to it the return value, like this
LowVoltage = Load_LowVoltage(LowVoltage);
Modify LowVoltage inside the function and pass a pointer to your original LowVoltage like this
void LowVoltage(unsigned int *lowVoltage)
{
*lowVoltage = modifiedValue;
}
then you can use it like this
Load_LowVoltage(&LowVoltage);
I think the second solution is cleaner and since you are in un environment where resources are limited, it's also better in that sense. But they both are easy to implement and work as good.
You could create a struct holding all battery parameters, for example:
typedef struct {
int low_voltage;
int voltage;
int capacity;
int temperature;
...
} BatteryData
At the start of your program you allocate memory for it and initialise members to some starting values:
BatteryData *battery = malloc(sizeof(BatteryData));
battery->low_voltage = 0;
...
Then you pass pointer to the whole struct to functions that set or read individual values, for example:
void Load_LowVoltage(BatteryData *battery){
//reads EEPROM and sets LowVoltage at startup
int eeprom_val = get_low_voltage_from_eeprom();
battery->low_voltage = eeprom_val;
}
Free the structure when not needed:
free(battery);
Related
I need some explanation/clarification about using local variables in FreeRTOS when I need to pass them to another functions as pointers.
For example I have some function that modifies data under pointer 'data'.
void modify_data(int * data){
*data = 10;
}
Can I use it like this?
void some_function(void){
int d; // local variable
modify_data(&d);
}
Or maybe I should make global variable?
int d;
void some_function(void){
modify_data(&d);
}
Or static variable?
void some_function(void){
static int d;
modify_data(&d);
}
My question in general is:
How to use (or replace) local variables with functions that take pointers in FreeRTOS?
Edit:
At this moment my understanding of this is:
local variables within a function have no use if I want to pass their pointers to another function (or do anything with pointers pointing these variables) because task switching can cause change of memory location where local variable is stored
I have to declare variables as static or global if I want to do anything with their pointers
this is a bit annoying, because a lot of variables in my big program must be declared globally and passing pointers to global data makes no sense except for the readability of the code
I'm using FreeRTOS 10.2.1, CMSIS 1.02 and code runs on STM32 microcontroller.
For starters this statement
*data = (*data)++;
invokes undefined behavior.
As for your question then to change a variable within a function you need to pass it to the function by reference that is indirectly through a pointer to it. For example
void f( int *px )
{
*px = 10;
}
void g( void )
{
static int x;
f( &x );
}
Depends on what you want to do. If you want to use d outside of that function you need to define it as a global, if you are only gonna use it inside the function declare it as local.
So after some discussion in comments and some research I found the answer for my concerns.
Local variables can be used in any way, JUST EXCEPT local variables declared in main function (and in functions called by main) (before FreeRTOS scheduler is started).
Source of my concerns was that I have read in some tutorial, that local functions created in "main context" may be messed up or not exist. It was not explained clearly that it applies to "main c function" and I missunderstood everything thinking that "main context" is context related with Main Stack Pointer, not just "main function".
FAQ on FreeRTOS website says:
The context of main() does not exist after the FreeRTOS scheduler has
started as, from that point, only RTOS tasks and interrupts have a
context. To maximise the amount of RAM available to the FreeRTOS
application, and as allowed by the C standard as the context of main()
no longer exists, some FreeRTOS ports re-use the stack allocated to
main as the system or interrupt stack. Therefore never allocate
variables or buffers that are needed or in any way accessed by the
FreeRTOS application on the stack used by main() because they are
likely to get overwritten.
So this simplified example would be OK:
int x;
int main(void)
{
x = 10;
createTasks();
vTaskStartScheduler();
}
But something like this will not work in FreeRTOS:
int * px; // this pointer will be not valid after vTaskStartScheduler()
int main(void)
{
int x = 10;
px = &x;
createTasks();
vTaskStartScheduler();
}
Someone might ask why I used a local variable in main and want to access it in the rest of the application without declaring it as a global variable. I was doing this because I have developed specyfic/weird way of attaching my code to CMSIS/STM32Cube generated code (which forces the programmer to write in "user code regions") that was working until I started using FreeRTOS.
Detail of the problem:
Some variables are read from a fixed memory area in RAM into an array. From that array I need to read some variables and use it across the code but these variables need to be constant as they wont be changed in the program any where. Need suggestions to do it effectively! Thanks in advance for any help.
The thought was given for using const variables but then Const variables needs to be initialised during declaration itself. I need to extract bit by bit for each of these variables as I am not able to use memcpy for ensuring portability. Hence I find trouble in declaring the variables as constant.
Put those variables {myVar1, myVar2,...myVarN} into a C file myconsts.c (static to the compilation unit, this will make sure they are not visible outside). Add a header file myconsts.h with function declarations
int getmyVar1(void);
and so on for all the variables and implement the functions in myconsts.c.
They aren't const in the C sense, but they are unwriteable from outside the myconsts.c file. You can initialise them inside myconsts.c, just dont forget to call the init().
If you mean that you are trying to guarantee that these 'constants' end up in flash as opposed to your RAM memory...consult your manual.
You could use inline functions to access the data direct from the array, e.g
static inline myvar() { return array[myvaroffset]; }
Or, if you want the offsets hidden, don't use inline functions and just have a small module that just provides the functions.
If 'myvaroffset' is calculated rather than being a constant and you want to avoid the indexing overhead, copy the array element to a variable during initialisation and return that from the function. If you use real functions, the variables can be static within the function module.
in the function module
/* initialisation */
static int myvarlocal = array[myvaroffset];
...
/* function definitions */
...
int myvar() { return myvarlocal; }
When you want to use it:
i = myvar();
There is probably no need to make things complicated with const pointers etc. Simply use private encapsulation:
// data.h
int data_get (int index);
// data.c
#include "data.h"
static int the_array [N];
int data_get (int index)
{
if(index >= N)
{
// handle errors
}
return array[index];
}
I have some programming experience but not much with C.
I have a reasonably large C file. In it there are multiple functions that are executed sequentially - so in this particular case no function is called twice really, they are broken down for ease of reading, since each function still has a separate purpose.
This program does a lot of computations on several long arrays of double with variable length, so they are all pointers. Two questions:
1) The variables that are calculated once from the beginning and then serve as input to many subsequent functions - should I make them global variables inside this file? From my experience programming in higher level languages, global variables are not good. Is this not the case for C and why?
2) When 1 of my function wants to return multiple pointers (each points to an double array of length n for example), say double *p1, double *p2, double *p3 that are related, I can combine them into a struct:
struct pointers {
double *p1, *p2, *p3;
} ptr;
foo1 will take double *input as input, and calculate ptr->p1, ptr->p2, ptr->p3, and then ptr will later serve as input for foo2. Should I write
struct pointers *foo(double *input)
or
void foo1(double *input, struct pointers ptr)
or
void foo1(double *input, struct pointers *ptr)
Why is it that C functions are usually 'void' functions, unless it returns just an int or double variables? Having input and output both as parameters - is it confusing?
Should I initialize ptr->p1, ptr->p2, ptr->p3 inside or outside of foo1?
Note that foo() is the main function that will call foo1, foo2 sequentially.
To answer question
1 ) it really depends upon the size and scope of your data. If you have small amount of to be used as part of computation within your function it makes more sense to initialize it within the function thus limiting its scope to the function .
If the data size is few megabytes or even more than tens of kilobytes it makes sense to allocate on a heap using a malloc.
You can have Global variables in the file but then you have to worry about synchronizing the access to them -- who is modifying them and in which order --
To answer question 2) the better way to write a function signature would be
struct {
double output1;
double output2;
double output3;
} output_t;
and the Function signature as:
ReturnCode foo ( double input , struct output_t * output);
Where ReturnCode could be just and int value indicating whether the operation was successful or failed.
1- Global variables are highly discouraged in C also. These are two important reasons:
Most of the time you do not need to have variables available throughout the complete program, so you really don't need to make the variables global.
With local variables your code will be more maintainable and also you will be avoiding possible side effects.
But in your case, as you said ptr.p1, ptr.p2, ptr.p3 will become inputs to many other subsequent functions, may be it is a better decision to make it global. In that case, if you are defining global(only in that file), you should try the static modifier. Here you can read about static(it can have 2 different meanings)
2.I think that your second question "Having input and output both as parameters - is it confusing?" it actually depends on the developer, the language gives you both options but it depends on you to make clear code.
Global variables are not advised in C too.
What i can gather from your question is that foo1 will make the struct and foo2 will take it as input.
So in my opinion you should make foo1 return the struct and then pass the entire struct as a parameter to foo2
specially in C, global variables are highly discouraged, unless you are working on multiple files each having to store their data. it is much easier to group data in structs and pass them to functions and its makes the whole thing clear to understand
here is a sample of a code i wrote, it deals with working with structures. only the declarations of the functions are here but you get the sense
struct elem {
void *data;
struct elem *next;
};
struct binky {
struct elem *root;
int elem_size;
};
void Initialize(struct binky * b, int elem_size);
int add(struct binky * b, const void * data);
void *get(const struct binky * b, const void * data);
void freeMap(struct binky * b);
This question is about the appropriateness of using void pointers in a particular implementation.
I have a relatively simple program that consists of an infinite loop. On each loop, the program iterates over a fixed range of constant values and calls a function on each value. The particular function which is called can be one of three available and is specified at run time by an argument. Before the infinite loop starts, there is a condition block which sets a functional pointer to a function based on the supplied argument. This way the condition logic only has to be run once and not on every iteration in every loop.
This I have implemented and it works well, but I want to keep state between each call to the function. My proposal is to store state in a struct and pass that struct when calling the function on each of the values. The problem is that each function requires a different struct to store a different set of values of its state and the prototype of all three functions must be compatible (for the function pointer). I intend to solve this by using a void pointer in the prototypes of the three functions, thus maintaining compatible prototypes but allowing me to pass a different struct to each function.
The question is; is my proposal an appropriate use of void pointers or is it introducing too much runtime dynamism and I should therefore rethink my approach?
Note: It is not possible to use static variables in each of the three functions as the structs also need to be available in the infinite loop as there is also some processing to be done before and after the range of values is iterated.
As long as you are careful to keep your calls type-correct, this is a fairly C-idiomatic way to accomplish what you describe.
You could gain some measure of type safety by using a union:
typedef struct {
int a;
char *b;
} s1;
typedef struct {
double d;
int *e;
} s2;
typedef union {
s1 s1;
s2 s2;
} ocd;
typedef int (*daemon_function)(ocd *);
Then all your functions could be of type daemon_function but take different arguments through ocd.s1 or ocd2.s2. I'd tend to call all that a bunch of pointless busy-work though. A simple void* would work just as well.
You could also include a magic number at the front of your structures and then the functions could check type safety by looking at the magic number and seeing if it was the right one:
#define MAGIC 0x4d475600L
typedef struct {
long magic;
/* ... */
} whatever;
And then:
int f(void *p) {
whatever *w = (whatever *)p;
if(w->magic != MAGIC) {
/* complain and go boom! */
}
/* ... */
}
I did the magic number trick all the time back in my Motif programming days, you pass around a lot of void* pointers in Motif/Xt/X11 development.
Void pointers are a method to tell the c typing system that you want it to stop doing its job and trust you to not mess up. It is an appropriate use of a void *, the only issue is that you have lost access to any type checking that your compiler performs. You can potentially create some very bizarre and hard to diagnose bugs. If you are sure that you know what you are doing (you sound like you do) and if you have checked every single line of your code several times and are sure that there are no logical errors in it, then you should be fine.
void * is quite idiomatic in C. Personally I use it prevalently, but whenever I do it, I tend to used tagged structures for safety, i.e. I put a unique type ID at the beginning of each structure to identify it.
Generally it is OK.
I really prefer using the void * contexts but it looks like you want to avoid it.
Since you already have some code that parses the argument and choose the function, you can just select the function in a switch and call it explicitly for each iteration.
In embedded C is quite natural to have some fixed/generic algorithm but more than one possible implementation. This is due to several product presentations, sometimes options, other times its just part of product roadmap strategies, such as optional RAM, different IP-set MCU, uprated frequency, etc.
In most of my projects I deal with that by decoupling the core stuff, the algorithm and the logic architecture, from the actual functions that implement outside state evaluation, time keeping, memory storage, etc.
Naturally, I use the C function pointers mechanism, and I use a set of meaningful names for those pointers. E.G.
unsigned char (*ucEvalTemperature)(int *);
That one stores temperature in an int, and the return is OKness.
Now imagine that for a specific configuration of the product I have a
unsigned char ucReadI2C_TMP75(int *);
a function that reads temperature on the I2C bus from the TMP75 device and
unsigned char ucReadCh2_ADC(unsigned char *);
a function that reads a diode voltage drop, read by an ADC, which is a way to evaluate temperature in very broad strokes.
It's the same basic functionality but on different option-set products.
In some configs I'll have ucEvalTemperature setup to ucReadI2C_TMP75, while on other I'll have ucReadCh2_ADC. In this mild case, to avoid problems, I should change the argument type to int, because the pointer is always the same size, but the function signature isn't and the compiler will complaint. Ok... that's not a killer.
The issue becomes apparent on functions that may need to have different set of arguments. The signatures won't ever be right, and the compiler will not be able to resolve my Fpointers.
So, I have three ways:
use a global stack of arguments, and all functions are unsigned char Func(void);
use a helper function to each implementation that lets me switch on the right assignment to make/call;
use JMP / LCALL assembly calls (which of course is horrible), potentially causing major problems on the call stack.
Neither is elegant, or composed... what's your approach/advise?
I usually prefer to have a layered architecture. The communication with the hardware is achieved with "drivers". The algorithms layers call functions (readTemp), which are implemented by the driver. The key point is that an interface needs to defined and that must be honoured by all driver implementations.
The higher layer should know nothing about how the temperature is read (It doesn't matter if you use TMP75 or an ADC). The disadvantage of the drivers architecture is that you generally can't switch a driver at runtime. For most embedded projects this is not a problem. If you want to do it, define function pointers to the functions exposed by the driver (which follow the common interface) and not to the implementation functions.
If you can, use struct "interfaces":
struct Device {
int (*read_temp)(int*, Device*);
} *dev;
call it:
dev->read_temp(&ret, dev);
If you need additional arguments, pack them inside Device
struct COMDevice {
struct Device d;
int port_nr;
};
and when you use this, just downcast.
Then, you'll create functions for your devices:
int foo_read_temp(int* ret, struct Device*)
{
*ret = 100;
return 0;
}
int com_device_read_temp(int* ret, struct Device* dev)
{
struct COMDevice* cdev = (struct COMDevice*)dev; /* could be made as a macro */
... communicate with device on com port cdev->port_nr ...
*ret = ... what you got ...
return error;
}
and create the devices like this:
Device* foo_device= { .read_temp = foo_read_temp };
COMDevice* com_device_1= { .d = { .read_temp = com_read_temp },
.port_nr = 0x3e8
};
COMDevice* com_device_1= { .d = { .read_temp = com_read_temp },
.port_nr = 0x3f8
};
You'll pass the Device structure around to function that need to read the temperature.
This (or something similar) is used in the Linux kernel, exceptthat they don't put the function pointers inside the structs, but create a special static struct for it and stor pointer to this struct inside the Device struct. This is almost exactly how object oriented lingages like C++ implement polymorphism.
If you put the functions in a separate compilation unit, including the Device struct that refer to them, you can still save space and leave them out while linking.
If you need different types of arguments, or fewer arguments, just forget it. This means you cannot design a common interface (in any sense) for things you want to change, but without a common interface, no changeable implementation is possible. You can use compile-time polymorphism (eg. typedefs & separate compilation units for different implementations, one of which would be linked in your binary), but it still has to be at least source-compatible, that is, be called in the same way.
The correct way is to use a helper function. Sure, the unsigned char ucReadCh2_ADC(unsigned char *); may look like it stores the result as a value [0,255]. But who says the actual range is [0,255] ? And even if it did, what would those values represent?
On the other hand, if you'd typedef unsigned long milliKelvin, the typedef unsigned char (*EvalTemperature)(milliKelvin *out); is a lot clearer. And for every function, it becomes clear how it should be wrapped - quite often a trivial function.
Note that I removed the "uc" prefix from the typedef since the function didn't return an unsigned char anyway. It returns a boolean, OK-ness.
(Colbert fans may want to use a float to indicate truthiness ;-) )