Accessing structure in structure through pointer - c

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.

Related

C embedded change values of struct from another file

Hello I am working on a small roboter project at uni and I have run into following issue.
I have a typedef called RoboterData inside of a header file because I want to make use of it across multiple files. Inside of the main file I have a RoboterData data variable which holds important data.
My goal is to have access from other files to this data having the ability to get and set it from another file. I want to avoid the use of a global variable.
Here are the relevant code fragments of my approach:
main.h
typedef struct {
DriveMode mode;
short sensor_left;
short sensor_mid;
short sensor_right;
int left_eng_speed;
int right_eng_speed;
} RoboterData;
main.c
# include "motors.h"
// The Data I want to get and set from other files.
RoboterData data;
// Call to a funcion defined in motors.c
drive_straight(RoboterData *data);
motors.h
void drive_straight(RoboterData *data);
motors.c
# include "main.h"
enum {
ENG_STILL = 0,
ENG_SLOW = 50,
ENG_MID = 155,
ENG_FAST = 200
}
void drive_straight(RoboterData *data) {
data ->left_eng_speed = ENG_FAST;
data ->right_eng_speed = ENG_FAST;
set_duty_cycle(LEFT_ENG, ENG_FAST);
set_duty_cycle(RIGHT_ENG, ENG_FAST);
}
When I later try to print out the values left_eng_speed and right_eng_speed via serial port it stays at 0. I know C is call by value but since I am passing a ptr to my struct the value I am passing is the adress of the struct and when I dereference it via '->' I should be able to access its original data from my understanding and not a copy because the only thing I copied was the address.
If someone could explain to me why this is not working and provide a viable alternative, I would be very greatfull.
// Call to a funcion defined in motors.c
drive_straight(RoboterData *data);
This is a function declaration. It doesn't do anything. You want
drive_straight(&data);
to actually call the function.

C, "extern" type of variables in hardware abstraction layer

I am working on a Hardware Abstraction Layer. The aim of this HAL is to easily switch between the drivers for linux and the drivers for an MCU.
I am working on the SPI interface. Below is the signature of the function of the HAL that "open" the interface of SPI.
hal/spi.h
spi_handle_t spi_open(spi_port_t channel, spi_config_t config);
spi_port_t :
On Linux, it is an elementary type : uint32_t
On the MCU, it is a struct.
spi_config_t :
On both Linux and the MCU it is a struct but with different fields.
So in mcu/spi.c I have at some point this :
typedef spiBASE_t spi_channel_t;
typedef spiDAT1_t spi_config_t;
spi_handle_t spi_open(spi_channel_t channel, spi_config_t config) {
.
.
.
}
And for linux/spi.c :
typedef uint32_t spi_channel_t;
typedef ChannelConfig_t spi_config_t;
spi_handle_t spi_open(spi_channel_t channel, spi_config_t config) {
.
.
.
}
Now the problem is in hal/spi.h, I need to define what is spi_channel_t and spi_config_t.
Is there a way to make something like (I know it is impossible with extern, but for explanation matters...) :
extern spi_channel_t;
extern spi_config_t;
This would say to the compiler : "Ok these two types are not defined in the header file, still you can find their storage size on one of the files I passed to the toolchain".
What you seem to be looking for is the trick called opaque type. It's a way to use forward declaration of structs in order to achieve private encapsulation and polymorphism in C. It is commonly used for professionally-written embedded systems drivers in particular and can be implemented like this:
hal/spi.h
// forward declaration of a struct, with typedef and struct tag:
typedef struct spi_handle_t spi_handle_t;
// Require the caller to declare a spi_handle_t* pointer, not an object:
spi_handle_t* spi_init (...);
mcu/spi.c
struct spi_handle_t
{
// whatever you need here - these are now 100% private members
};
spi_handle_t* spi_init (...)
{
spi_handle* result = address_of_some_static_memory_pool;
/* init struct members here */
return result;
}
linux/spi.c
struct spi_handle_t
{
uint32_t something;
// whatever you need here - these are now 100% private members
};
spi_handle_t* spi_init (...)
{
spi_handle* result = malloc(sizeof *result); // malloc is fine to use in Linux
/* init struct members here */
return result;
}
Now the caller will have to pass along the spi_handle* to other functions in the driver. This isn't just handy for OO design, but it also makes it possible to run the same code with multiple instances. For example if you have 2 different SPI hardware peripherals on the MCU and want to use them differently, but with the same driver code.
The typical way of doing this would be to use the preprocessor in hal/spi.h:
#if defined(HAL_LINUX)
typedef uint32_t spi_port_t; /* int in linux */
#elif defined(HAL_MCU)
typedef struct {
/* your struct in bare metal app */
} spi_port_t;
#else
#error "Platform not defined!"
#endif
You could also put the different types into different headers like hal/spi_linux.h and hal/spi_mcu.h and conditionally include one of them in hal/spi.h.
Alternatively, you could just take pointers and cast them to their actual type. This would be less safe because you would have to check the platform at runtime and decide the type behind the pointer, but this decision depends on many other things.

Compile-time check struct with function pointers to validate assignments

I'm wondering if the following is possible:
I have a namespace-style struct setup, filled with just function pointers. These are provided in the header file like so:
typedef struct {
int32_t(*const event_construct)(struct sync_event* evt);
int32_t(*const event_destroy)(struct sync_event* evt);
int32_t(*const event_set)(struct sync_event* evt);
int32_t(*const event_wait)(struct sync_event* evt);
} namespace_sync;
extern namespace_sync const sync;
and then in the relevant source file, after all the function implementations:
...
namespace_sync const sync = {
sync_event_construct,
sync_event_destroy,
sync_event_set,
sync_event_wait
};
Say I want to add an extra function not at the end; I add it to the struct and source file, but forget to assign it. Because the function declarations match, a warning isn't generated for it, and the compiler (at least in this example, vs2013) doesn't provide a hint that there's an issue.
I've got compile-time assertion checks available, but not sure if I can verify this particular aspect, since the struct size is accurate. If vs2013 can't work with it - I'm aware it's an abysmal C compiler(!) - the newest versions of gcc will also be used, so I could limit the functionality to one compiler.
One solution going forward would be to use designated initializers:
namespace_sync const sync = {
.event_construct = sync_event_construct,
.event_destroy = sync_event_destroy,
.event_set = sync_event_set,
.event_wait = sync_event_wait
};
Any unlisted members will default to null pointers.
I would advise to not add members into the middle of a struct, because it is difficult to be sure that you have correctly updated any code that was relying on the old struct layout. However, if you really do want to do this, then one way to have the compiler indicate to you where all the uses of the struct are is to change the struct name:
typedef struct {
// ...
} namespace_sync_2;
Then the code namespace_sync const sync will cause a compilation error. This alerts you to the fact that this piece of code requires a code review to make sure that it will work correctly with the new struct layout.

keyboard interrupt handler giving null value

I am learning Linux Kernel Module programming(Interrupt Handler) and using the tutorial (http://tldp.org/LDP/lkmpg/2.6/html/) exact module link(http://tldp.org/LDP/lkmpg/2.6/html/x1256.html).
In the tutorial I am getting error when I used
INIT_WORK(&task, got_char, &scancode);
The error was "error: macro "INIT_WORK" passed 3 arguments, but takes just 2"
So I found one solution and use the below line
INIT_WORK(&task, got_char);
It's working fine but the output I am getting is null. I am expecting the key number from the keyboard.
Any body have any idea ?
If it is not clear please let me know I will try to interpret more.
Thanks
Add a structure like follows,
struct getchar_info {
/* Other info ... */
struct work_struct work;
unsigned int scancode;
/* Other info ... */
};
static struct getchar_info gci; /* Statically declare or use kmalloc() */
Change got_char() to,
static void got_char(struct work_struct *work)
{
struct getchar_info *info = container_of(work, struct getchar_info, work);
info->scancode = my_val;
/* ... */
Initialize it like INIT_WORK(&gci.work, got_char);
This is a common Linux kernel paradigm or design pattern. The work queue code needs to manage this structure pointer so it is easy to provide to your got_char routine. Your driver must allocate it as part of a larger structure (it is inheritence in OO terms; it looks like composition as 'C' only supports that). The container_of is like a C++ dynamic_cast<> (with single inheritance in case any C++ gurus are looking). It lets you get the composed structure from the sub-structure.

Move object creation to setup() function of arduino

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.

Resources