尝试访问结构指针的第一个成员(本身是易失性指针)不会返回存储的成员指针,而是返回结构地址

时间:2018-08-12 13:27:43

标签: c pointers struct avr-gcc

我正在尝试通过将指针传递给某种实现的指针结构来实现某些通信接口的某种指针替换。 它打算在Atmega328p上运行,并使用avr-gcc.exe(AVR_8_bit_GNU_Toolchain_3.5.4_1709)4.9.2进行编译,该版本安装在Windows 10上的msys2 64位中(或通过msys2 64位安装)

现在,给出以下结构

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

我在我的主文件中将其创建为文件范围变量,并根据我的数据表用相应的地址(在这种情况下为0xB9, 0xB8, 0xBC, 0xBB)填充它。

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

myInterface本身始终存储在0x100中,以供参考。 当我尝试从主函数内部访问它们中的任何一个时,它将返回相应的预期地址。

然后我将其传递给另一个.c文件中的init函数

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

并且当我尝试访问任何成员时,即通过仍使用相同init函数的printf打印它

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);

我应该得到以下打印的地址0x100, 0xB9, 0xB8, 0xBC, 0xBB,第一个是结构本身,然后是每个成员的内容,它们是我的寄存器的地址。而是访问storedRegisters->baudrateRegister会返回0x100,即结构本身的地址,而不是成员的内容。 然后,我控制台上的输出是

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

因此,我无法访问结构指针的第一个成员指针,但其他所有指针似乎都很好。如果我要交换例如控制和波特率寄存器在我的结构,然后控制寄存器是返回0x100的。 我错过了一些必不可少的东西吗?

我正在使用以下选项进行编译:

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

并与之链接

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

编辑:错字固定

Edit2:我使用

调用init函数
init(&myInterface, 100000L);

Edit3:固定在控制台输出周围混合

Edit4:添加了3个相关的源文件。

main.c文件

#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
}

CommInterface.h文件

#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

CommInterface.c文件

#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);
}

1 个答案:

答案 0 :(得分:0)

请原谅,信誉太低,无法置评,所以我只把2美分放在这里。 如果没有用,请随意投票等等。

我编译并运行了代码(适用于PC),并假设TWBR和其他3的定义类似于(*(uint8_t *)(0xB9)),当{ {1}}函数在main中被调用。 如果没有调试器,很难弄清您身边的情况,并且由于我看不到任何明显的C错误,充其量我只能做出疯狂的猜测。

如果我要根据您所说的内容进行假设(“如果我要在结构中交换例如控制和波特率寄存器的顺序,则controlregister是返回0x100的那个。我是否缺少一些必要的内容? “),我会尝试将责任归咎于init()的{​​{1}}语句中。 您是否可以尝试只交换printf()调用的顺序(例如,先打印数据寄存器成员)?并查看前两个呼叫是否再次打印printf()

init()

我知道这很简单,而且有点穴居人调试,但是: 1.我没有让自己靠近的系统 2.您没有调试器 3.我发现您发布的代码中没有明显的C错误