1

正如标题所暗示的那样,我遇到了一个与未定义 memcpy 和 memset 相关的错误,即使我没有直接使用它(尽管鉴于此错误的性质,我猜它用于链接器和编译过程)

长话短说:我正在将最初存储在 FLASH 中的 .data 和 .bss 部分写入 SRAM 存储器,我正在使用指针进行此类操作,如下所示:

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <string.h>


int main(void);
void Reset_Handler(void);
void Default_Handler(void);


#ifdef __cplusplus
}
#endif


extern uint32_t _etext;
extern uint32_t _sdata;
extern uint32_t _edata;
extern uint32_t _sbss;
extern uint32_t _ebss;


void Reset_Handler(void)
{    
   //copy .data section to SRAM
    uint32_t size = (uint32_t)&_edata - (uint32_t)&_sdata;
    
    uint8_t *pDst = (uint8_t*)&_sdata; //sram
    uint8_t *pSrc = (uint8_t*)&_etext; //source point comes from flash memory that is end of flash 
    
    for(uint32_t i =0 ; i < size ; i++)
    {
        *pDst++ = *pSrc++;              //"MEMCPY NOT DEFINED" ERROR TRIGGERS HERE
    }
    
    //copy .bss section to SRAM
    size = (uint32_t)&_ebss - (uint32_t)&_sbss;
    
    pDst = (uint8_t*)&_sbss; //sram
    
    for(uint32_t i =0 ; i < size ; i++)
    {
        *pDst++ = 0;                 //"MEMSET NOT DEFINED" ERROR TRIGGERS HERE
    }
    
    main();

}

我正在使用 arm 嵌入式 g++ 编译器来构建 .o 文件,然后使用 -nostdlib 选项链接到 .elf ,因为这是嵌入式应用程序,因此不需要 stdlib/负担得起。

该过程失败,因为似乎存在对“memcpy”和“memset”函数的隐式调用。我试图包含 <string.h> (据我所知,这是定义这两个函数的地方)另外,我已经在 extern "C" 中进行了包含,以避免由于名称修改而导致“未定义符号” .

这是 make 文件调用和终端输出:

arm-none-eabi-g++ -c -mcpu=cortex-m4 -mthumb -std=c++11 -O2 -g -fno-exceptions stm32_startup.cpp -o stm32_startup.o

arm-none-eabi-g++ -nostdlib -T stm32_ls.ld -Wl,-Map=final.map    main.o GPIO_PORT.o stm32_startup.o config.o -o final.elf

/usr/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: stm32_startup.o: in function `Reset_Handler':
/home/inumaki/Development/stm32/Workspace/stm32_startup.cpp:155: undefined reference to `memcpy'

/usr/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: /home/inumaki/Development/stm32/Workspace/stm32_startup.cpp:165: undefined reference to `memset'
collect2: error: ld returned 1 exit status
make: *** [Makefile:35: final.elf] Error 1


inumaki@dev-Inumaki:~/Development/stm32/Workspace$ make
arm-none-eabi-g++ -c -mcpu=cortex-m4 -mthumb -std=c++11 -O2 -g -fno-exceptions stm32_startup.cpp -o stm32_startup.o

arm-none-eabi-g++ -nostdlib -T stm32_ls.ld -Wl,-Map=final.map    main.o GPIO_PORT.o stm32_startup.o config.o -o final.elf

/usr/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: stm32_startup.o: in function `Reset_Handler':
/home/inumaki/Development/stm32/Workspace/stm32_startup.cpp:155: undefined reference to `memcpy'
/usr/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: /home/inumaki/Development/stm32/Workspace/stm32_startup.cpp:165: undefined reference to `memset'
collect2: error: ld returned 1 exit status
make: *** [Makefile:35: final.elf] Error 1

如我所见,解决此问题的唯一方法是在删除 #include <string.h> 的同时定义我自己的 memcpy 和 memset 函数实现以避免重新定义问题。虽然我不知道 memcpy 和 memset 是做什么的。

提前致谢。

编辑:

通过删除 -nostdlib ,即允许链接器链接标准库,我得到这个错误也与未定义的函数有关。在我看来,即使我有一个 .cpp 启动文件,它也与汇编程序启动文件有关。

inumaki@dev-Inumaki:~/Development/stm32/Workspace$ make
arm-none-eabi-g++ -c -mcpu=cortex-m4 -mthumb -std=c++11 -O2 -g -fno-exceptions main.cpp -o main.o

arm-none-eabi-g++ -c -mcpu=cortex-m4 -mthumb -std=c++11 -O2 -g -fno-exceptions GPIO_PORT.cpp -o GPIO_PORT.o

arm-none-eabi-g++ -c -mcpu=cortex-m4 -mthumb -std=c++11 -O2 -g -fno-exceptions stm32_startup.cpp -o stm32_startup.o

arm-none-eabi-g++ -c -mcpu=cortex-m4 -mthumb -std=c++11 -O2 -g -fno-exceptions config.cpp -o config.o

arm-none-eabi-g++ -T stm32_ls.ld -Wl,-Map=final.map main.o GPIO_PORT.o stm32_startup.o config.o -o final.elf

/usr/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: /usr/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/crt0.o: in function `_mainCRTStartup':
(.text+0x128): undefined reference to `__bss_start__'

/usr/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: (.text+0x12c): undefined reference to `__bss_end__'
/usr/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: /usr/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/libc.a(lib_a-exit.o): in function `exit':
exit.c:(.text.exit+0x2c): undefined reference to `_exit'
collect2: error: ld returned 1 exit status
make: *** [Makefile:35: final.elf] Error 1
4

2 回答 2

1

添加-fno-tree-loop-distribute-patterns以防止 gcc 识别memsetmemcpy等模式并为它们生成外部函数调用。这通常是您想要的独立执行环境。请注意,-ffreestanding不一定抑制这些函数调用的生成。

或者,您可以链接到您自己的memcpy实现memset,正如您所指出的那样 - 但这可能是您在一切正常时需要考虑的事情。

于 2021-11-23T22:17:43.100 回答
1

通过将您的代码复制到Compiler Explorer中,我能够重现您的问题。解决方案是在-ffreestanding编译该文件时将选项添加到 GCC。有关此站点的更多信息。-ffreestanding

或者,您可以尝试删除-nostdlib您在链接期间使用的选项,允许 GCC 在其标准库中链接,假设它已正确配置以允许这样做。我建议您至少尝试这样做,看看它给您的应用程序增加了多少膨胀。这样做可能没问题,因为 GCC 应该只包含您实际调用的库函数。

于 2021-11-23T21:48:27.760 回答