Function pointer in struct not working?

时间:2016-10-19 13:42:01

标签: c struct function-pointers undefined-reference atmelstudio

I have a driver and code that works on IAR but does not work for Atmel Studio 7. I get an error ld returned 1 exit status and undefined reference to '_read' (or _write) when I try to assign a function to a pointer inside a struct.

In the driver that I need to use there are two pointers defined as follows:

#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

In the file they have a struct defined as follows:

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 */
};

In my application I try to do:

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

My functions are defined as:

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

EDIT: I am attaching the error code as asked:

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

1 个答案:

答案 0 :(得分:1)

我猜您的i2c_writei2c_read函数会调用printfwriteputcputs或类似函数。是?

您看到的错误是包装器_write_r_read_r尝试调用基础writeread函数,而无法找到它们。例如,参见this discussion (sec. 6.4)the newlib C library这些函数的实现add a leading underscore to exported names

当您注释掉bmm050.bus_write = i2c_writebmm050.bus_read = i2c_read行时,错误会消失,因为您的代码中没有其他内容会调用readwrite。如果您未在代码中引用i2c_read,例如当这些行被注释掉时,链接器可以从编译的目标文件中删除i2c_read。如果没有i2c_read,则不需要_read_rread,因此您不会收到链接器错误。

那该怎么办?

一些选项,按照我尝试的顺序。

  1. 如果您有支持合同,请致电您的电路板支持包(BSP)供应商。
  2. 搜索Atmel Studio源/库,查看它们是否为您的特定硬件提供_read_write实施。如果Atmel Studio包含适用于您的主板的BSP,则可能包括这些功能。 (我自己没有Atmel Studio,即使我这样做也可能没有相同的BSP,所以我不能告诉你更具体的东西,而不是去看哪里。)
    • 注意如果这些函数是用C. C编译器编写的this blog post,那么这些函数可能被称为read()write()(没有前导下划线)。
  3. 修改您的i2c_readi2c_write,以便他们直接访问设备的I2C寄存器。如果您可以从这些函数中删除C库的I / O例程,则不再需要_read_write
  4. 如果您找不到现有的实施或不需要,请在线查看实施。例如,this answer(德语)包含_write的示例实现。那个,加上线程下面的链接,可以帮助你(即使你不会说德语)。
  5. 最后,如有必要,请滚动您自己的_read_write,这将在您的特定目标上执行一些有意义的输入和输出。我收集了那个I2C,但您可能在某些时候想要UART,LCD,七段显示器,Nixie或其他东西 - 编写您希望的任何I / O例程!请注意,这基本上涉及与#3相同类型的工作,但在不同的上下文中。
  6. 另见:

    • this discussion,与不同平台上的类似情况有关
    • {{3}}实施您自己的操作系统(有效),以便_write_r能够与之交谈!