structure initialization for xh711 issue - c

I am building a program for Xh711 on esp32. I have defined a a struct and i am trying to initialize it. I am getting the next error.
could not convert '{GPIO_NUM_18, GPIO_NUM_19, 0, 1, 1, GAIN64, 0, -1,
storm->ad_str_t::smoothed, storm->ad_str_t::sampling,
storm->ad_str_t::timerHandle}' from '' to 'ad_xh711_handle_t'
void str_init_Xh711(ad_str_t *storm){
printf("Starting xh711...\n");
ad_xh711_handle_t xh711={
.dout= GPIO_NUM_18,
.scl= GPIO_NUM_19,
.offset = 0,
.calibrationFactor = 1,//NULL,
.conversionFactor=1,
.gainValue= Gain::GAIN64,
.rawData =0,//NULL,
.value = -1,
.smoothed =storm->smoothed,
.sampling =storm->sampling,
.timerHandle = storm->timerHandle
};
xh711_init(&xh711,Gain::GAIN64);
}
typedef struct {
gpio_num_t dout;
gpio_num_t scl;
int32_t offset = 0;
double calibrationFactor;
double conversionFactor=1;
Gain gainValue;
int32_t rawData;
double value = -1;
bool smoothed;
uint8_t sampling;
esp_timer_handle_t timerHandle;
}ad_xh711_handle_t;

default values in typedef can not work and have to be removed

Related

Initialize a flexible array of arrays in a struct

The title corresponds to my last attempt, I try to store color values ​​corresponding to walls, a bit like this:
#include <stdint.h>
typedef uint8_t RGB[3];
typedef RGB ColorArray[];
typedef struct {
int wall_num;
ColorArray wall_colors;
} Map;
int main(void)
{
int wall_num = 3;
ColorArray wall_colors = {
*(RGB){ 255, 0, 0 },
*(RGB){ 0, 255, 0 },
*(RGB){ 0, 0, 255 }
};
Map my_map = {wall_num, wall_colors}; // error: non-static initialization of a flexible array member
return 0;
}
But I get this:
error: non-static initialization of a flexible array member
I tried other ways with pointers but I quickly realized that it was pointing to anything and so I got any colors until a segfault...
Is there a way to do it like this ? Or is it just the wrong way to go and I have to start all over again ?
UPDATE - (SELF ANSWER):
So I decided to call malloc() because no alternative was satisfactory for my case, I share what I did if it can help someone:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef uint8_t RGB[3];
typedef RGB RGB_Array[];
typedef struct {
int wall_num;
RGB_Array wall_colors;
} Map;
void print_map (Map *m) {
printf("wall_num: %d\n", m->wall_num);
for (int i = 0; i < m->wall_num; ++i) {
printf("wall_colors[%d]: (R:%d, G:%d, B:%d)\n", i,
m->wall_colors[i][0],
m->wall_colors[i][1],
m->wall_colors[i][2]);
}
}
int main(void)
{
int wall_num = 3;
RGB_Array color_arr = {
{255,0,0},
{0,255,0},
{0,0,255}
};
Map* map = malloc(sizeof(Map) + sizeof(color_arr));
map->wall_num = wall_num;
memcpy(map->wall_colors, color_arr, sizeof(color_arr));
print_map(map);
free(map); // free is for example
return 0;
}
Otherwise, jxh's answer is still interesting and perfectly does what was asked for, even if it doesn't suit me personally, I validate it anyway.
You cannot use an array name to initialize an array variable anyway.
There is no memory associated with the flexible array member. It is a convenience to allow you to have a name for the end of the struct to refer to the array that you intend to allocate behind the struct.
Typically, you would use malloc() and add the size of the array to the size of the struct to get a single object to represent your structure with the flexible array.
However, you can do it off the "stack" by defining a new structure where the flexible array member is replaced with an array of the appropriate size, and then casting a pointer to this structure to your desired type.
Alternatively, you could use a union and avoid the casting.
Both techniques are illustrated below. First some helpers:
...
#define MAP_TEMPLATE(N) struct { \
int wall_num; \
RGB wall_colors[N]; \
}
...
void print_map (Map *m) {
printf("wall_num: %d\n", m->wall_num);
for (int i = 0; i < m->wall_num; ++i) {
printf("wall_colors[%d]: (R:%d, G:%d, B:%d)\n", i,
m->wall_colors[i][0],
m->wall_colors[i][1],
m->wall_colors[i][2]);
}
}
Then using a new structure:
MAP_TEMPLATE(3) my_map1 = {
wall_num,
{ { 155, 0, 0 },
{ 0, 155, 0 },
{ 0, 0, 155 },
},
};
print_map((Map *)&my_map1);
And using a union:
union {
MAP_TEMPLATE(3) _;
MAP_TEMPLATE();
} my_map2 = {
{ wall_num,
{ { 255, 0, 0 },
{ 0, 255, 0 },
{ 0, 0, 255 },
},
},
};
print_map((Map *)&my_map2);

Sending pointer to a struct through a queue in FreeRTOS

I can't seem to figure out how to send a pointer to a struct using a queue in FreeRTOS. I've tried all I could think of, yet I always get a pointer to some random region of memory.
I'm trying to send a pointer to a button struct to another task, where it will then be drawn on the screen. I tried sending the whole object and it worked, but since there's a lot of data in the struct (data of two icons) I don't really want to do that.
The code is being run in Atmel SAME70 Xplained.
Here is a simpler version of the code I'm working on:
typedef struct {
uint32_t width;
uint32_t height;
uint32_t x;
uint32_t y;
uint8_t status;
void (*callback)(t_but);
tImage iconOn;
tImage iconOff;
} t_but;
void task_lcd(void) {
xQueueButtons = xQueueCreate(6, sizeof(struct t_but *));
t_but *button;
configure_lcd();
draw_screen();
while (1) {
if (xQueueReceive(xQueueButtons, &(button), (TickType_t)500 / portTICK_PERIOD_MS)) {
// This always prints some random numbers.
printf("Button X: %" PRIu32 "\r\n", button->x);
}
}
}
void task_buttons(void) {
t_but butPlay = {.width = 64,
.height = 64,
.x = 60,
.y = 445,
.status = 0,
.callback = &ButPlayCallback,
.iconOn = play_red,
.iconOff = play_black};
xQueueSend(xQueueButtons, &butPlay, 0);
while (1) {
// Some other code.
}
}
Any help is very much appreciated.
It appears from the API that the xQueueSend does a copy via the pointer passed so if you want to pass a pointer on the queue you need to pass the address of a pointer that is pointing at your structure.
void task_buttons(void) {
t_but butPlay = {.width = 64,
.height = 64,
.x = 60,
.y = 445,
.status = 0,
.callback = &ButPlayCallback,
.iconOn = play_red,
.iconOff = play_black};
t_but * const p_but = &butPlay;
xQueueSend(xQueueButtons, &p_but, 0);
while (1) {
// Some other code.
}
}

How to create an enum dynamically in compiling time for my struct

I have this struct below
struct foo {
char *name;
int (*validate)(u8_t *data, size_t size);
u8_t value;
u8_t changed;
foo_id id;
};
typedef struct foo foo_t;
I wish I to create an array of foo_t in compiling time through defines, like this:
int my_validate(u8_t *data, size_t size) {...}
FOO_CREATE(my_name, my_validate, 0, 0);
FOO_CREATE(my_name2, NULL, 0, 0);
and in compiling time the result be:
enum {
MY_NAME_FOO = 0,
MY_NAME2_FOO,
FOO_COUNT
} foo_id;
static foo_t foo[FOO_COUNT] = {
{
.name = "my_name",
.validate = my_validate,
.value = 0,
.changed = 0,
.id = MY_NAME_FOO
},
{
.name = "my_name2",
.validate = NULL,
.value = 0,
.changed = 0,
.id = MY_NAME2_FOO
},
}
If this was not possible with just C and cmake in compiling time, what do you suggest for me to make this work?
What I'm going to suggest you is something I actually have seen in a real big production project. I have to say it because I admit it is not a nice looking solution.
A file with all the macros invoked
First of all you need to put all your macro invocations in a single file. You can give it the name and the extension you want: for example the classical .h extension or something with a descriptive extension such as .def.
So, PreprocessorTypePopulation.h can be defined as follow:
FOO_CREATE(my_name, my_validate, 0, 0)
FOO_CREATE(my_name2, NULL, 0, 0)
It contains all the FOO_CREATE macro invoked.
Note: no commas or semicolons after each macro invocation. Also an implementation with commas (removing them from macros) would have worked in this case (because only enum items and array elements were involved).
The file containing the generated struct/enums:
This can be a .h file. In my example it is the C file containing a dummy demonstrative main(). I just converted OP's int types to those contained in stdint.h.
#include <stddef.h>
#include <stdint.h>
#ifdef FOO_CREATE
#undef FOO_CREATE
#endif
/* Enum creation macro */
#define FOO_CREATE(nm,func,val,chgd) nm##_FOO,
typedef enum {
#include "PreprocessorTypePopulation.h"
FOO_COUNT
} foo_id;
struct foo {
char *name;
int (*validate)(uint8_t *data, size_t size);
uint8_t value;
uint8_t changed;
foo_id id;
};
typedef struct foo foo_t;
int my_validate(uint8_t *data, size_t size)
{
return 0;
}
#undef FOO_CREATE
/* Array creation macro */
#define FOO_CREATE(nm,func,val,chgd) \
{ \
.name = (char *) #nm, \
.validate = func, \
.value = val, \
.changed = chgd, \
.id = nm##_FOO \
},
static foo_t foo[FOO_COUNT] = {
#include "PreprocessorTypePopulation.h"
};
int main(void)
{
return 0;
}
As you can see, the following strategy is implemented:
Undef any previous FOO_CREATE() definition
Define the FOO_CREATE() macro for the first task (the enumerative generation)
Include the .def file INSIDE the enum. The sequence of FOO_CREATE()s will be used to generate the enum items according to the just defined macro
Undef the macro again, and redefine it for the second task (the array of structs definition)
Include the .def file INSIDE the array definition. The sequence of FOO_CREATE()s will be used to generate the array elements according to the just defined macro
--
The output
I compiled with preprocessor-only option, in my case with
gcc PreprocessorTypePopulation.c -E -P
(-P option removes linemarkers from the output) and then I obtained the following output (I just removed all the stuff related to the included standard headers):
typedef enum {
my_name_FOO,
my_name2_FOO,
FOO_COUNT
} foo_id;
struct foo {
char *name;
int (*validate)(short *data, int size);
short value;
short changed;
foo_id id;
};
typedef struct foo foo_t;
int my_validate(short *data, int size)
{
return 0;
}
static foo_t foo[FOO_COUNT] = {
{ .name = "my_name", .validate = my_validate, .value = 0, .changed = 0, .id = my_name_FOO },
{ .name = "my_name2", .validate = NULL, .value = 0, .changed = 0, .id = my_name2_FOO },
}
int main(void)
{
return 0;
}
--
In conclusion, it's not for sure a nice looking solution. But it works, and it prevents a lot of human mistakes concentrating several definitions in a single file. In a long term big project this can save weeks of work.

Struct initialization problem in C

I seem to be having a problem setting the values of an array inside a structure with a meaningless error spat out of the compiler:
expected primary-expression before '{' token
I understand that a structure must "exist" to accept values, and it exists as a pointer to one. I would like you to explain to me what i am doing wrong and how to achieve my objective.
struct EventCheckData {
unsigned long refresh_time;
unsigned long last_execution_ms; //Can also serve to delay at startup
byte signal_type;
};
struct ClockData {
struct EventCheckData event_array[4];
byte event_count;
unsigned long last_absolute_time;
UISignal *warning_signals;
};
void ResetClock(UISignal *warning_signal, struct ClockData *clock_data, unsigned long absolute_time) {
if(SignalCheckValue(warning_signal, RESET_CLOCK, 1)) {
extern volatile unsigned long timer0_overflow_count;
timer0_overflow_count = 0;
clock_data->last_absolute_time = absolute_time;
clock_data->event_count = 3;
(clock_data->event_array)[0] = { .refresh_time = 3000UL, .last_execution_ms = 0UL, .signal_type = WATER_PUMP_ON};
// clock_data->event_array[1] = {10000UL, 0UL, EXPORT_LOG};
// clock_data->event_array[2] = {100000UL, 0UL, EXTERNAL_CONNECTION};
SignalSet(warning_signal, RESET_CLOCK, 0);
}
}
Thank you
Paulo Neves
(clock_data->event_array)[0] = { .refresh_time = 3000UL, .last_execution_ms = 0UL, .signal_type = WATER_PUMP_ON}; is not initialization. It is assignment.
And you cannot use initializer syntax in assignment.
With C99, you should be able to use a compound literal, like
(clock_data->event_array)[0] = (struct EventCheckData){ .refresh_time = 3000UL, .last_execution_ms = 0UL, .signal_type = WATER_PUMP_ON};
The way you are assigning it looks like an initializer. You need assignment, try a compound literal:
clock_data->event_array[0] = (struct EventCheckData){ .refresh_time = 3000UL, ...};
Without any C99 stuff you can simply use:
void ResetClock(UISignal *warning_signal, struct ClockData *clock_data, unsigned long absolute_time) {
if(SignalCheckValue(warning_signal, RESET_CLOCK, 1)) {
extern volatile unsigned long timer0_overflow_count;
timer0_overflow_count = 0;
clock_data->last_absolute_time = absolute_time;
clock_data->event_count = 3;
{
struct EventCheckData a[]={ {3000UL, 0UL, WATER_PUMP_ON},
{10000UL, 0UL, EXPORT_LOG},
{100000UL, 0UL, EXTERNAL_CONNECTION}};
memcpy(clock_data->event_array,a,sizeof a);
}
SignalSet(warning_signal, RESET_CLOCK, 0);
}

Using MPI_Reduce in c

I am trying to write a program in c using the MPI library.
In my program I am solving TSP (but not with any special algorithm...).
My input parameters are int nCites, int xCoord[] and int yCoord[].
I am bundling them into Coordinates and using MPI_Bcast to make them available to all the threads.
My problem is this: after I've finished calculating the weight of all the paths in each thread, I want to reduce them into one single result, the best one. I've tried using MPI_Reduce, but something, and this is where I get confused, causes a segmentation fault (only in one of the threads, usually root).
This is the main code and structs:
typedef struct Coordinates_t {
int* x;
int* y;
int n;
} Coordinates;
typedef struct PathAndLength_t {
int* path;
int pathSize;
int length;
} PathAndLength;
void comparePaths(void* a, void* b, int* len, MPI_Datatype* dataType) {
...
}
int tsp_main(int nCites, int xCoord[], int yCoord[], int P[]){
int numOfProcs, rank;
if (MPI_Comm_size(MPI_COMM_WORLD, &numOfProcs))
throw "Error: MPI_Comm_size failed";
if (MPI_Comm_rank(MPI_COMM_WORLD, &rank))
throw "Error: MPI_Comm_rank failed";
Coordinates crds;
crds.x = xCoord;
crds.y = yCoord;
crds.n = nCites;
MPI_Datatype data;
createInDataType(&crds, &data);
if (MPI_Bcast(&crds, 1, data, 0, MPI_COMM_WORLD))
throw "Error: MPI_Comm_size failed";
...
PathAndLength* pal = (PathAndLength*)malloc(sizeof(PathAndLength));
pal->path = (int*)malloc(sizeof(int)*crds.n);
pal->length = min_length;
for (int i = 0; i < crds.n; ++i) {
(pal->path)[i] = min_path[i];
}
pal->pathSize = crds.n;
MPI_Datatype outDatatype;
MPI_Op op;
createOutDataType(pal, &outDatatype);
MPI_Op_create(&comparePaths, 1, &op);
PathAndLength* result = (PathAndLength*)malloc(sizeof(PathAndLength));
result->path = (int*)malloc(sizeof(int)*crds.n);
MPI_Reduce(pal, result, crds.n, outDatatype, op, 0, MPI_COMM_WORLD);
...
return result->length;
}
And these are the createOutDataType and createInDataType I use in my code:
void createInDataType(Coordinates* indata, MPI_Datatype* message_type_ptr) {
// Build a derived datatype
int block_lengths[3];
MPI_Aint displacements[3];
MPI_Aint addresses[4];
MPI_Datatype typelist[3];
// First specify the types
typelist[0] = typelist[1] = typelist[2] = MPI_INT;
// Specify the number of elements of each type
block_lengths[0] = block_lengths[1] = indata->n;
block_lengths[2] = 1;
// Calculate the displacements of the members relative to indata
MPI_Address(indata, &addresses[0]);
MPI_Address(indata->x, &addresses[1]);
MPI_Address(indata->y, &addresses[2]);
MPI_Address(&indata->n, &addresses[3]);
displacements[0] = addresses[1] - addresses[0];
displacements[1] = addresses[2] - addresses[0];
displacements[2] = addresses[3] - addresses[0];
// Create the derived type
MPI_Type_struct(3, block_lengths, displacements, typelist, message_type_ptr);
// Commit it so that it can be used
MPI_Type_commit(message_type_ptr);
}
void createOutDataType(PathAndLength* outdata, MPI_Datatype* message_type_ptr) {
// Build a derived datatype
int block_lengths[2];
MPI_Aint displacements[2];
MPI_Aint addresses[3];
MPI_Datatype typelist[2];
// First specify the types
typelist[0] = MPI_INT;
typelist[1] = MPI_INT;
// Specify the number of elements of each type
block_lengths[0] = outdata->pathSize;
block_lengths[1] = 1;
// Calculate the displacements of the members relative to outdata
MPI_Address(outdata, &addresses[0]);
MPI_Address(outdata->path, &addresses[1]);
MPI_Address(&outdata->length, &addresses[2]);
displacements[0] = addresses[1] - addresses[0];
displacements[1] = addresses[2] - addresses[0];
// Create the derived type
MPI_Type_struct(2, block_lengths, displacements, typelist, message_type_ptr);
// Commit it so that it can be used
MPI_Type_commit(message_type_ptr);
}
Sorry for including so much code, but I couldn't decide what, if any, was irrelevant...
Thank you.
PathAndLength* result = (PathAndLength*)malloc(sizeof(PathAndLength));
result->path = (int*)malloc(sizeof(int)*crds.n);
MPI_Reduce(pal, result, crds.n, outDatatype, op, 0, MPI_COMM_WORLD);
you are receiving crds.n*outDatatypes into result buffer of size sizeof(PathAndLength). You seem to have design flaw.

Resources