Trying to access first member(itself a volatile pointer) of struct pointer does not return the stored member pointer but the struct address

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



Trying to access first member(itself a volatile pointer) of struct pointer does not return the stored member pointer but the struct address



I am trying to implement some pointer substitution for some communication interface by passing on a pointer to a struct of pointers to some implementation.
This is meant to run on an Atmega328p and is being compiled with avr-gcc.exe (AVR_8_bit_GNU_Toolchain_3.5.4_1709) 4.9.2, installed in/via msys2 64bit on Windows 10



Now, given the following struct


typedef struct
volatile uint8_t* baudrateRegister;
volatile uint8_t* statusRegister;
volatile uint8_t* controlRegister;
volatile uint8_t* dataRegister;
CommRegisters;



I create this as a file scope variable in my main file and fill it with the corresponding addresses (in this case 0xB9, 0xB8, 0xBC, 0xBB) according to my datasheet.


0xB9, 0xB8, 0xBC, 0xBB


CommRegisters myInterface = &BAUDRATEREGISTER, &STATUSREGISTER, &CONTROLREGISTER, &DATAREGISTER;



myInterface itself gets stored in 0x100, for reference sake, consistently.
When i try to access any of them from inside the main function it returns the corresponding and expected addresses.



I then pass that to my init function in a different .c file


CommRegisters* storedRegisters
void init(CommRegisters* registers, uint32_t clockspeed)
storedRegisters = registers;



and when i try to access any of the members i.e. by printing it with printf still in that same init function with


printf("storedRegisters %pn", storedRegisters);
printf("storedRegisters->baudrateRegister %pn", storedRegisters->baudrateRegister);
printf("storedRegisters->statusRegister %pn", storedRegisters->statusRegister);
printf("storedRegisters->controlRegister %pn", storedRegisters->controlRegister);
printf("storedRegisters->dataRegister %pn", storedRegisters->dataRegister);



I should be getting the following addresses printed 0x100, 0xB9, 0xB8, 0xBC, 0xBB, the first one being the struct itself and then the content of each member, being addresses to my registers. Instead accessing storedRegisters->baudrateRegister does return 0x100, the address to the struct itself, not the content of the member.
The output on my console is then


0x100, 0xB9, 0xB8, 0xBC, 0xBB


storedRegisters->baudrateRegister


0x100


storedRegisters 0x100
storedRegisters->baudrateRegister 0x100
storedRegisters->statusRegister 0xb8
storedRegisters->controlRegister 0xbc
storedRegisters->dataRegister 0xbb



With this I cannot access the first member pointer of my struct pointer, but all others seem fine. If I were to swap the order of e.g. control and baudrate register in my struct then the controlregister is the one that returns 0x100.
Am I missing something essential?



I am compiling this with the following options:


avr-gcc -O2 -g2 -gstabs -std=c99 -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MMD -MP -ffunction-sections -fdata-sections <some files>



and link it with


avr-gcc -Wl,-Map,.map -Wl,-u,vfprintf -lprintf_flt -lm -mmcu=atmega328p <some files>



Edit: Typo fixed



Edit2: i call the init function with


init(&myInterface, 100000L);



Edit3: fixed mixed around console output



Edit4: Added the 3 relevant source files.



The main.c file


#include "CommInterface.h"
#include <avr/io.h>
#include <util/delay.h>

//uart
#include "Debug_uart.h"
static FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
void startUart(void)
stdout = stdin = &uart_str;
uart_init();
printf("nnnn############################################n");


#define BAUDRATEREGISTER TWBR
#define STATUSREGISTER TWSR
#define CONTROLREGISTER TWCR
#define DATAREGISTER TWDR
CommRegisters myInterface = &BAUDRATEREGISTER, &STATUSREGISTER, &CONTROLREGISTER, &DATAREGISTER;

void integration_runBMETester(void)
startUart();
init(&myInterface, 100000L);
DDRB = (1 << PB5);
while(1)= (1 << PB5);
_delay_ms(500);
PORTB &= ~(1 << PB5);
_delay_ms(500)



int main(int argc, char const *argv)
#ifdef INTEGRATION_BME680
integration_runBMETester();
#endif



The CommInterface.h file


#ifndef _COMM_INTERFACE_H
#define _COMM_INTERFACE_H

#include <stdint.h>

typedef struct
volatile uint8_t* baudrateRegister;
volatile uint8_t* statusRegister;
volatile uint8_t* controlRegister;
volatile uint8_t* dataRegister;
CommRegisters;

void init(CommRegisters* registers, uint32_t clockspeed);

#endif // _COMM_INTERFACE_H



The CommInterface.c file


#include "CommInterface.h"
#include "registerAbstraction.h"

CommRegisters* storedRegisters;
void init(CommRegisters* registers, uint32_t clockspeed)
printf("initn");
storedRegisters = registers;

printf("storedRegisters %pn", storedRegisters);
printf("storedRegisters->baudrateRegister %pn", storedRegisters->baudrateRegister);
printf("storedRegisters->statusRegister %pn", storedRegisters->statusRegister);
printf("storedRegisters->controlRegister %pn", storedRegisters->controlRegister);
printf("storedRegisters->dataRegister %pn", storedRegisters->dataRegister);

abstraction_setRegisterToValue(storedRegisters->statusRegister, 0);
abstraction_setRegisterToValue(storedRegisters->baudrateRegister, ((F_CPU / clockspeed) - 16) / 2);





edited it accordingly
– Saphieron
Aug 12 at 13:39





Your console output is not in the order of your printf statements. Please make triple sure the code you are running is the code you are posting. Otherwise it gets very diffucult to reason about it very fast.
– n.m.
Aug 12 at 13:44






Please show the entire program.
– n.m.
Aug 12 at 13:51





Added the source code.
– Saphieron
Aug 12 at 14:17





This doesn't look like valid C source. For example the .h file won't compile because of a missing semicolon.
– n.m.
Aug 12 at 17:00




1 Answer
1



Please excuse this, reputation too low to comment, so I'll just put my 2 cents here.
If it's useless, feel free to downvote and so on.



I compiled and ran the code (adapted for the PC), and assuming the definitions of TWBR and the other 3 to be something like (*(uint8_t *)(0xB9)) , the correct and expected values were printed when the init() function was called in main.
It's hard to figure out without a debugger what's going on at your side, and as I can not see any obvious C errors, at best I can make wild guesses.


TWBR


(*(uint8_t *)(0xB9))


init()



if I were to make an assumption, based on what you said (" If I were to swap the order of e.g. control and baudrate register in my struct then the controlregister is the one that returns 0x100. Am I missing something essential?") I would attempt try to put the blame somewhere in the printf() statements in init().
Would you please try to swap the order of just the printf() calls (e.g. print the data register member first)? And see if the first 2 calls print 0x100 again.


printf()


init()


0x100


printf("storedRegisters %pn", storedRegisters);
printf("storedRegisters->dataRegister %pn", storedRegisters->dataRegister);
printf("storedRegisters->baudrateRegister %pn", storedRegisters->baudrateRegister);
printf("storedRegisters->statusRegister %pn", storedRegisters->statusRegister);
printf("storedRegisters->controlRegister %pn", storedRegisters->controlRegister);



I know it's rudimentary and a bit of caveman debugging, but:
1. I do not have your system to look closer myself
2. You do not have a debugger
3. I see no obvious C errors in the code you posted





I did originally have the print statements in a different order. I noticed the problem because the status register was being set correctly with 0 but the baud rate register wasn't (made the communication fail). I read the content of the registers directly by dereferencing the addresses to see if the initialisation works but it always failed for the baud rate. If i swapped the baudrate register position inside the struct definition in the h file with the status register, the status register didn't initalise with 0. So it is not just a problem with printf afaik.
– Saphieron
Aug 12 at 20:48





More guesswork: have you tried to print directly the registers parameter passed to the init() function? Nothing seems to be wrong with the code...
– LiviuH
Aug 13 at 8:12



registers


init()






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

Creating a leaderboard in HTML/JS