简体   繁体   中英

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.

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 ie by printing it with printf still in that same init function with

printf("storedRegisters %p\n", storedRegisters);
printf("storedRegisters->baudrateRegister %p\n", storedRegisters->baudrateRegister);
printf("storedRegisters->statusRegister %p\n", storedRegisters->statusRegister);
printf("storedRegisters->controlRegister %p\n", storedRegisters->controlRegister);
printf("storedRegisters->dataRegister %p\n", 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

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 eg 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("\n\n\n\n############################################\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){
        PORTB |= (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("init\n");
    storedRegisters = registers;

    printf("storedRegisters %p\n", storedRegisters);
    printf("storedRegisters->baudrateRegister %p\n", storedRegisters->baudrateRegister);
    printf("storedRegisters->statusRegister %p\n", storedRegisters->statusRegister);
    printf("storedRegisters->controlRegister %p\n", storedRegisters->controlRegister);
    printf("storedRegisters->dataRegister %p\n", storedRegisters->dataRegister);

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

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.

if I were to make an assumption, based on what you said (" If I were to swap the order of eg 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 (eg print the data register member first)? And see if the first 2 calls print 0x100 again.

 printf("storedRegisters %p\n", storedRegisters);
    printf("storedRegisters->dataRegister %p\n", storedRegisters->dataRegister);
    printf("storedRegisters->baudrateRegister %p\n", storedRegisters->baudrateRegister);
    printf("storedRegisters->statusRegister %p\n", storedRegisters->statusRegister);
    printf("storedRegisters->controlRegister %p\n", 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM