我有一个适用于 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
最佳答案
我猜你的 i2c_write
和 i2c_read
函数调用了 printf
、write
、putc
、puts
或类似的函数。是的?
您看到的错误是包装器 _write_r
和 _read_r
试图调用底层的 write
和 read
功能,并且无法找到它们。参见,例如 this discussion (sec. 6.4)在 the newlib C library 中实现这些功能.
当您注释掉 bmm050.bus_write = i2c_write
和 bmm050.bus_read = i2c_read
行时,错误就会消失,因为您的代码中没有其他内容调用 read
或编写
。如果您没有在代码中引用 i2c_read
,例如当这些行被注释掉时,链接器可以从编译的目标文件中删除 i2c_read
。没有 i2c_read
,就不需要 _read_r
或 read
,因此您不会遇到链接器错误。
那怎么办?
几个选项,按我尝试的顺序排列。
- 如果您有支持契约(Contract),请调用您的电路板支持包 (BSP) 供应商。
- 搜索 Atmel Studio 源代码/库,看看它们是否为您的特定硬件提供了
_read
或_write
实现。如果 Atmel Studio 包含用于您的电路板的 BSP,则可能包含这些功能。 (我自己没有 Atmel Studio,即使我有也可能不会有相同的 BSP,所以我不能告诉你比去哪里看更具体。)- 注意如果这些函数是用 C 语言编写的,则可以调用
read()
和write()
(不带前导下划线) . C编译器一般add a leading underscore to exported names .
- 注意如果这些函数是用 C 语言编写的,则可以调用
- 修改您的
i2c_read
和i2c_write
以便它们直接访问设备的I2C 寄存器。如果您可以从这些函数中消除对 C 库的 I/O 例程的调用,您将不再需要_read
或_write
。 - 如果您无法找到现有的实现或消除对实现的需求,请在线查找实现。例如,this blog post (德语)包含
_write
的示例实现。那加上线程中它下面的链接,可能会对您有所帮助(即使您不会说德语)。 - 最后,如有必要,滚动您自己的
_read
和_write
,这将对您的特定目标执行一些有意义的输入和输出。我知道那是 I2C,但在某些时候您可能希望它是 UART、LCD、七段显示器、Nixie 或其他东西 — 编写您想要的任何 I/O 例程!请注意,这基本上涉及与 #3 相同类型的工作,但在不同的上下文中。
另见:
- this answer ,这涉及到不同平台上的类似情况
- this discussion实现您自己的操作系统(有效地)以便
_write_r
有话可说!
关于c - 结构中的函数指针不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40133112/