简体   繁体   中英

bare metal embedded c++: undefined reference to memcpy and memset while writing flash to ram

As the tittle suggest, I'm getting an error related to not defining memcpy and memset, even though I'm not directly using it (although I guess it is used for the linker and compiling process given the nature of this error)

long story short: I'm writing the.data and.bss section originally stored in FLASH to the SRAM memory, I'm using pointer for such operation in a fashion like the following:

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

}

I'm using arm embedded g++ compiler for building the.o files and then linking into.elf using -nostdlib option given the fact that embedded application is intended, so no stdlib are requiered/affordable.

The process fails since it appears that there is a implicit calling to "memcpy" and "memset" functions. I tried to include <string.h> (which, to my knowledge, is where those two functions are defined) Also, I've made the include inside extern "C" in order to avoid "not defined symbol" due to name mangling.

This is the make file calling and the terminal output for that:

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

The only way out of this as I see, would be to define my own implementation of memcpy and memset functions at the same time as removing #include <string.h> to avoid redefinition problems. Although I don't know what memcpy and memset do.

Thanks in advance.

EDIT:

By removing -nostdlib that is, allowing the linker to link the std libraries, I get this errors related also to undefined functions. It seems to me that it is related to assembler startup file even though I have a.cpp startup file.

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

I was able to reproduce your problem by copying your code into the Compiler Explorer . The solution is to add the -ffreestanding option to GCC when you are compiling that file. There is more info about -ffreestanding on this site.

Alternatively, you could try removing the -nostdlib option you are using during linking, allowing GCC to link in its standard libraries, assuming it is configured properly to allow for that. I recommend that you at least try doing that and see how much bloat it adds to your application. It might be fine to do that because GCC should only include the libary functions you actually are calling.

Add -fno-tree-loop-distribute-patterns to prevent gcc recognising memset , memcpy , etc., patterns and generating external function calls for them. That's typically what you want for a freestanding execution environment. Note that -ffreestanding does not necessarily suppress the generation of these function calls.

Alternatively, you can link with your own memcpy , memset implementations as you point out - but that's probably something to consider when you get everything working.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM