Trying to access first member(itself a volatile pointer) of struct pointer does not return the stored member pointer but the struct address
Clash 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);
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.
edited it accordingly
– Saphieron
Aug 12 at 13:39