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.