Попытка получить доступ к первому члену (сам по себе изменчивый указатель) указателя структуры не возвращает сохраненный указатель элемента, но возвращает адрес структуры

Я пытаюсь реализовать некоторую замену указателя для некоторого интерфейса связи, передав указатель на структуру указателей на некоторую реализацию. Он предназначен для работы на Atmega328p и компилируется с помощью avr-gcc.exe (AVR0x100bit_GNU_Toolchain_3.5.4_1709) 4.9.2, установленного в / через msys2 64bit в Windows 10.

Теперь, учитывая следующую структуру

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

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

и когда я пытаюсь получить доступ к любому из членов, то есть распечатывая его с помощью 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(&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);
}

person Saphieron    schedule 12.08.2018    source источник
comment
отредактировал это соответствующим образом   -  person Saphieron    schedule 12.08.2018
comment
Вывод вашей консоли не соответствует порядку операторов printf. Убедитесь, что код, который вы используете, совпадает с кодом, который вы публикуете. В противном случае очень сложно очень быстро об этом рассуждать.   -  person n. 1.8e9-where's-my-share m.    schedule 12.08.2018
comment
Исправив это, я поменял местами порядок его печати, а также порядок членов внутри структуры, чтобы увидеть, имеет ли это какое-либо значение. Должно быть скопирован неправильный вывод. Однако поведение осталось таким же, как описано.   -  person Saphieron    schedule 12.08.2018
comment
Вы должны взять отладчик, чтобы увидеть, что передается в printf. Это немного похоже на выравнивание, когда два разных файла C используют разные директивы выравнивания.   -  person Paul Ogilvie    schedule 12.08.2018
comment
Покажите, пожалуйста, всю программу.   -  person n. 1.8e9-where's-my-share m.    schedule 12.08.2018
comment
@PaulOgilvie У меня нет под рукой отладчика (наверное, я должен наконец его заказать). Чего я не понимаю, оба файла скомпилированы одним и тем же способом с точно такими же флагами. Как в этом случае изменится директива aligment?   -  person Saphieron    schedule 12.08.2018
comment
Добавил исходный код.   -  person Saphieron    schedule 12.08.2018
comment
Это не похоже на действительный источник C. Например, файл .h не компилируется из-за отсутствия точки с запятой.   -  person n. 1.8e9-where's-my-share m.    schedule 12.08.2018
comment
Исправлена ​​отсутствующая точка с запятой. Могу вас уверить, что он был скомпилирован и запущен. Форматирование stackoverflow при копировании и вставке может привести к отсутствию некоторых символов.   -  person Saphieron    schedule 12.08.2018
comment
Вы думаете, что выполняете код? Может быть нет   -  person 0___________    schedule 12.08.2018
comment
@P__J__ не совсем уверен, что собираешься делать? Я позволил этому запускаться на плате разработчика Atmega328p и прочитал результаты через USB-адаптер FTDI. Я пропустил код UART, потому что это просто средство для чтения кода, и до сих пор доказал свою работоспособность, когда я пытался считывать указатели в основном файле.   -  person Saphieron    schedule 12.08.2018
comment
Я очистил папку сборки и убедился, что все изменения были внесены в процесс компиляции, перекомпилировав все заново.   -  person Saphieron    schedule 12.08.2018
comment
Что отображает & BAUDRATEREGISTER при попытке его распечатать?   -  person Tony    schedule 12.08.2018
comment
Он показывает фактический адрес 0xB9. Это тот же адрес, который определен в предоставленном atmel файле io328p.h   -  person Saphieron    schedule 13.08.2018
comment
должен ли я беспокоиться о том, что регистр данных находится всего на 1 байт перед регистром управления? 0xbb и 0xbc соответственно. Это означало бы, что регистр даты имеет размер всего 1 байт?   -  person Kami Kaze    schedule 13.08.2018
comment
Покажите, пожалуйста, определение TWBR (например)   -  person Anton    schedule 14.08.2018


Ответы (1)


Пожалуйста, извините, репутация слишком низкая, чтобы давать комментарии, поэтому я просто положу сюда свои 2 цента. Если это бесполезно, не стесняйтесь голосовать против и так далее.

Я скомпилировал и запустил код (адаптированный для ПК) и, предположив, что определения TWBR и других 3 будут чем-то вроде (*(uint8_t *)(0xB9)), правильные и ожидаемые значения были напечатаны при вызове функции init() в main. Трудно понять без отладчика, что происходит на вашей стороне, и, поскольку я не вижу никаких очевидных ошибок C, в лучшем случае я могу делать дикие предположения.

если бы я сделал предположение, основываясь на том, что вы сказали («Если бы я поменял местами, например, регистр управления и скорости передачи в моей структуре, тогда регистр управления будет тем, который возвращает 0x100. Я упустил что-то важное?») Я попытается обвинить где-нибудь в printf() заявлениях в init(). Не могли бы вы поменять местами только вызовы printf () (например, сначала распечатать элемент регистра данных)? И посмотрите, снова ли первые 2 вызова print 0x100.

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

Я знаю, что это элементарная и немного отладка пещерного человека, но: 1. У меня нет вашей системы, чтобы я мог посмотреть поближе 2. У вас нет отладчика 3. Я не вижу очевидных ошибок C в опубликованном вами коде

person LIH    schedule 12.08.2018
comment
Изначально у меня были операторы печати в другом порядке. Я заметил проблему, потому что регистр состояния был установлен правильно с 0, но регистр скорости передачи не был (приводил к сбою связи). Я читаю содержимое регистров напрямую, разыменуя адреса, чтобы увидеть, работает ли инициализация, но всегда не удавалось для скорости передачи данных. Если я поменял местами регистр скорости передачи внутри определения структуры в h-файле с регистром состояния, регистр состояния не инициализировался с 0. Так что это проблема не только с printf afaik. - person Saphieron; 12.08.2018
comment
Больше догадок: пробовали ли вы напечатать напрямую параметр registers, переданный функции init()? Кажется, с кодом все в порядке ... - person LIH; 13.08.2018