Указатель функции в структуре не работает?

У меня есть драйвер и код, которые работают в IAR, но не работают в Atmel Studio 7. Я получаю сообщение об ошибке ld returned 1 exit status и undefined reference to '_read' (или _write), когда пытаюсь присвоить функцию указателю внутри структуры.

В драйвере, который мне нужно использовать, есть два указателя, определенные следующим образом:

#define BMM050_WR_FUNC_PTR \
    s8 (*bus_write)(u8, u8, \
    u8 *, u8)

#define BMM050_RD_FUNC_PTR \
    s8 (*bus_read)(u8, u8, \
    u8 *, u8)re

В файле у них есть структура, определенная следующим образом:

struct bmm050_t {
    u8 company_id;/**<mag chip id*/
    u8 dev_addr;/**<mag device address*/

    BMM050_WR_FUNC_PTR;/**< bus write function pointer*/
    BMM050_RD_FUNC_PTR;/**< bus read function pointer*/
    void (*delay_msec)(BMM050_MDELAY_DATA_TYPE);/**< delay function pointer*/

    s8 dig_x1;/**< trim x1 data */
    s8 dig_y1;/**< trim y1 data */

    s8 dig_x2;/**< trim x2 data */
    s8 dig_y2;/**< trim y2 data */

    u16 dig_z1;/**< trim z1 data */
    s16 dig_z2;/**< trim z2 data */
    s16 dig_z3;/**< trim z3 data */
    s16 dig_z4;/**< trim z4 data */

    u8 dig_xy1;/**< trim xy1 data */
    s8 dig_xy2;/**< trim xy2 data */

    u16 dig_xyz1;/**< trim xyz1 data */
};

В моем приложении я пытаюсь сделать:

bmm050.bus_write = i2c_write;
bmm050.bus_read = i2c_read;

Мои функции определены как:

int8_t i2c_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count);

int8_t i2c_read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count);

РЕДАКТИРОВАТЬ: я прикрепляю код ошибки по запросу:

c:/program files (x86)/atmel/studio/7.0/toolchain/arm/arm-gnu-toolchain/bin/../lib/gcc/arm-none-eabi/5.3.1/../../../../arm-none-eabi/lib/armv6-m\libc.a(lib_a-writer.o): In function `_write_r':
C:\Users\aba\Documents\Atmel Studio\7.0\Project1\Project1\Debug\writer.c(1,1): error: undefined reference to `_write'
c:/program files (x86)/atmel/studio/7.0/toolchain/arm/arm-gnu-toolchain/bin/../lib/gcc/arm-none-eabi/5.3.1/../../../../arm-none-eabi/lib/armv6-m\libc.a(lib_a-readr.o): In function `_read_r':
C:\Users\aba\Documents\Atmel Studio\7.0\Project1\Project1\Debug\readr.c(1,1): error: undefined reference to `_read'
collect2.exe(0,0): error: ld returned 1 exit status

person NitrogenAir    schedule 19.10.2016    source источник
comment
используйте отладчик, получите дамп, обратную трассировку и все такое, и посмотрите, что на самом деле представляет собой BMM050_MDELAY_DATA_TYPE.   -  person Elias Van Ootegem    schedule 19.10.2016
comment
Ни в одном из приведенных вами кодов не упоминаются _read и _write (только bus_read или i2c_read и т. д.). Что заставляет вас думать, что компоновщик жалуется на этот код?   -  person TripeHound    schedule 19.10.2016
comment
Я прокомментировал те две строки, где я пытаюсь назначить функции, и ошибки исчезают. BMM050_MDELAY_DATA_TYPE это uint_32t и по какой-то причине выполнение bmm050.delay_msec = delay_cycles_ms работает нормально   -  person NitrogenAir    schedule 19.10.2016
comment
Ради запутывания используйте typedef, а не неприглядные макросы!   -  person Lundin    schedule 19.10.2016
comment
У вас есть отличное замечание, но это исходит из полностью написанного драйвера, который я бы предпочел не менять. Я попытался переписать его с помощью typedef, однако, поскольку они используют эти макросы везде в коде, мне также нужно было бы изменить его везде...   -  person NitrogenAir    schedule 19.10.2016
comment
При поиске в Интернете я обнаружил, что многие люди связывают эту проблему с компоновщиком. Есть ли шанс, что это так?   -  person NitrogenAir    schedule 19.10.2016
comment
Насколько я понимаю, если жаловаться на _read (вместо, скажем, bus_read), то либо в коде, который вы показываете, есть ошибка вырезания и вставки (например, во втором определении макроса есть конечный re), либо какой-то вступают в силу другие макроэлементы (вы не определили i2c как пустую строку где-нибудь? ... случайные пробелы в ваших операторах присваивания?).   -  person TripeHound    schedule 19.10.2016
comment
Пожалуйста, вырежьте и вставьте полные сообщения об ошибках ld и undefined дословно в вопрос (как код).   -  person Jeff Y    schedule 19.10.2016
comment
Пожалуйста, найдите его добавленным.   -  person NitrogenAir    schedule 20.10.2016
comment
Ваши сообщения об ошибках и фрагменты кода, которые вы разместили здесь, кажутся совершенно не связанными.   -  person melpomene    schedule 20.10.2016


Ответы (1)


Я предполагаю, что ваши функции i2c_write и i2c_read вызывают printf, write, putc, puts или аналогичную функцию. Да?

Ошибки, которые вы видите, связаны с тем, что оболочки _write_r и _read_r пытаются вызвать базовые функции write и read и не могут их найти. См., например, это обсуждение (раздел 6.4) реализации этих функций в библиотека C newlib.

Ошибки исчезают, когда вы закомментируете строки bmm050.bus_write = i2c_write и bmm050.bus_read = i2c_read, потому что больше ничего в вашем коде не вызывает read или write. Если вы не ссылаетесь на i2c_read в своем коде, например, когда эти строки закомментированы, компоновщик может удалить i2c_read из скомпилированного объектного файла. Без i2c_read нет необходимости в _read_r или read, поэтому вы не получите ошибок компоновщика.

Итак, что делать?

Несколько вариантов, в том порядке, в котором я бы попробовал их.

  1. Позвоните поставщику пакета поддержки платы (BSP), если у вас есть контракт на поддержку.
  2. Search through the Atmel Studio source/libraries to see if they provide a _read or _write implementation for your particular hardware. If Atmel Studio includes a BSP for your board, that may include the functions. (I don't have Atmel Studio myself, and probably wouldn't have the same BSP even if I did, so I can't tell you more specifically than that where to look.)
  3. Измените свои i2c_read и i2c_write, чтобы они напрямую обращались к регистрам I2C устройства. Если вы сможете исключить из этих функций вызовы подпрограмм ввода-вывода библиотеки C, вам больше не понадобятся _read или _write.
  4. Если вы не можете найти существующую реализацию или устранить необходимость в ней, поищите реализации в Интернете. Например, эта запись в блоге (на немецком языке) включает пример реализации _write. Это, а также ссылки ниже в теме могут вам помочь (даже если вы не говорите по-немецки).
  5. Наконец, если необходимо, сверните свои собственные _read и _write, которые будут выполнять некоторые значимые ввод и вывод для вашей конкретной цели. Я понимаю, что это I2C, но в какой-то момент вы можете захотеть, чтобы это был UART, ЖК-дисплей, семисегментный дисплей, Nixie или что-то еще, напишите любые процедуры ввода-вывода, которые вы хотите! Обратите внимание, что это в основном включает в себя тот же тип работы, что и № 3, но в другом контексте.

Смотрите также:

  • этот ответ, который относится к аналогичной ситуации на другой платформе
  • это обсуждение реализации вашей собственной ОС (эффективно), чтобы _write_r было о чем поговорить к!
person cxw    schedule 20.10.2016