Hello Everybody,
I am trying to build a firmware which is using two functions from the Keil SAM-ESV7_SFP 2.4.5 library. The compile process is okay, but I can not get the linking going.
*** Using Compiler 'V5.06 update 6 (build 750)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin' Build target 'Target' compiling afe_dma.c... linking... .\Objects\Target.axf: Error: L6218E: Undefined symbol Afe_SendData(AfeDma*, AfeCmd*) (referred from receiver.o). .\Objects\Target.axf: Error: L6218E: Undefined symbol Afe_ConfigureDma(AfeDma*, Afec*, unsigned char, _Xdmad*) (referred from receiver.o). Not enough information to list image symbols. Not enough information to list load addresses in the image map. Finished: 2 information, 0 warning and 2 error messages. ".\Objects\Target.axf" - 2 Error(s), 0 Warning(s). Target not created. Build Time Elapsed: 00:00:01
Now the weird part: The two functions Afe_SendData and Afe_ConfigureDma is defined in the afe_dma.c which gets compiled succesfully. The afe_dma.o gets generated in the Objects subfolder.
I have tried to remove the afe_dma.c from the sources and I got the same exact error as I should, but when I put it back, the file gets compiled, but the error stays.
I have tried to clean and rebuild the project several times. There are no weird characters in the paths of the project, Keil tools or the include paths.
Why the linker does not recognize the the compiled afe_dma.o? Is there a way to explicitly tell the linker to link a specific *.o file?
Thank you very much.
Oh, and one more thing. There are no #define staements that may cut anything out of the code.
Use FromELF to dump the object, and perhaps disassemble it, and review the output to understand the issue.
Make sure they aren't defined as static routines. Hard to gauge lacking file, or function(s), in question.
Check the file is not compiled as a C++ file, see options in project metadata.
Hello, thank you for your insight.
The functions are not static of course.
I copy in the functions: The definitions form afe_dma.c
/*---------------------------------------------------------------------------- * Exported functions *----------------------------------------------------------------------------*/ /** * \brief Initializes the AfeDma structure and the corresponding AFE & DMA . * hardware select value. * The driver will uses DMA channel 0 for RX . * The DMA channels are freed automatically when no DMA command processing. * * \param pAfed Pointer to a AfeDma instance. * \param pAfeHw Associated Afe peripheral. * \param AfeId Afe peripheral identifier. * \param pDmad Pointer to a Dmad instance. */ uint32_t Afe_ConfigureDma(AfeDma *pAfed , Afec *pAfeHw , uint8_t AfeId, sXdmad *pXdmad) { /* Initialize the Afe structure */ pAfed->pAfeHw = pAfeHw; pAfed->afeId = AfeId; pAfed->semaphore = 1; pAfed->pCurrentCommand = 0; pAfed->pXdmad = pXdmad; return 0; } /** * \brief Starts a AFE transfer. This is a non blocking function. It will * return as soon as the transfer is started. * * \param pAfed Pointer to a AfeDma instance. * \param pCommand Pointer to the Afe command to execute. * \returns 0 if the transfer has been started successfully; otherwise returns * AFE_ERROR_LOCK is the driver is in use, or AFE_ERROR if the command is not * valid. */ uint32_t Afe_SendData(AfeDma *pAfed, AfeCmd *pCommand) { Afec *pAfeHw = pAfed->pAfeHw; /* Try to get the dataflash semaphore */ if (pAfed->semaphore == 0) return AFE_ERROR_LOCK; pAfed->semaphore--; // Initialize the callback pAfed->pCurrentCommand = pCommand; /* Initialize DMA controller using channel 0 for RX. */ if (_AfeConfigureDmaChannels(pAfed)) return AFE_ERROR_LOCK; /* Configure and enable interrupt on RC compare */ NVIC_ClearPendingIRQ(XDMAC_IRQn); NVIC_SetPriority(XDMAC_IRQn , 1); NVIC_EnableIRQ(XDMAC_IRQn); if (_Afe_configureLinkList(pAfeHw, pAfed->pXdmad, pCommand)) return AFE_ERROR_LOCK; AFEC_StartConversion(pAfeHw); /* Start DMA 0(RX) */ if (XDMAD_StartTransfer(pAfed->pXdmad, afeDmaRxChannel)) return AFE_ERROR_LOCK; return AFE_OK; }
Both of them get declared in the afe_dma.h header file
/*------------------------------------------------------------------------------ * Exported functions *----------------------------------------------------------------------------*/ extern uint32_t Afe_ConfigureDma(AfeDma *pAfed , Afec *pAfeHw , uint8_t AfeId, sXdmad *pXdmad); extern uint32_t Afe_SendData(AfeDma *pAfed, AfeCmd *pCommand);
I continue in the next post...
I did the FromELF dump of the afe_dma.o, it is quite long, but i copy in the relevant parts for both functions.
** Section #4 Name : i.Afe_ConfigureDma Type : SHT_PROGBITS (0x00000001) Flags : SHF_ALLOC + SHF_EXECINSTR (0x00000006) Addr : 0x00000000 File Offset : 66 (0x42) Size : 20 bytes (0x14) Link : SHN_UNDEF Info : 0 Alignment : 2 Entry Size : 0
** Section #6 Name : i.Afe_SendData Type : SHT_PROGBITS (0x00000001) Flags : SHF_ALLOC + SHF_EXECINSTR (0x00000006) Addr : 0x00000000 File Offset : 304 (0x130) Size : 164 bytes (0xa4) Link : SHN_UNDEF Info : 0 Alignment : 4 Entry Size : 0
** Section #646 Name : .reli.Afe_SendData Type : SHT_REL (0x00000009) Flags : None (0x00000000) Addr : 0x00000000 File Offset : 562000 (0x89350) Size : 40 bytes (0x28) Link : Section 644 (.symtab) Info : Section 6 (i.Afe_SendData) Alignment : 4 Entry Size : 8
** Section #644 Name : .symtab Type : SHT_SYMTAB (0x00000002) Flags : None (0x00000000) Addr : 0x00000000 File Offset : 550872 (0x867d8) Size : 11104 bytes (0x2b60) Link : Section 831 (.strtab) Info : Last local symbol no = 88 Alignment : 4 Entry Size : 16 Symbol table .symtab (693 symbols, 88 local) # Symbol Name Value Bind Sec Type Vis Size ======================================================================== . . . 38 i.Afe_ConfigureDma 0x00000000 Lc 4 Sect De . . . 43 i.Afe_SendData 0x00000000 Lc 6 Sect De . . . 682 Afe_ConfigureDma 0x00000001 Gb 4 Code Hi 0x14 683 Afe_SendData 0x00000001 Gb 6 Code Hi 0x96
==================================== ** Section #832 Name : .ARM.attributes Type : SHT_ARM_ATTRIBUTES (0x70000003) Flags : None (0x00000000) Addr : 0x00000000 File Offset : 615198 (0x9631e) Size : 134 bytes (0x86) Link : SHN_UNDEF Info : 0 Alignment : 1 Entry Size : 0 'aeabi' file build attributes: 0x000000: 04 43 6f 72 74 65 78 2d 4d 37 2e 66 70 2e 64 70 .Cortex-M7.fp.dp 0x000010: 00 05 43 6f 72 74 65 78 2d 4d 37 00 06 0d 07 4d ..Cortex-M7....M 0x000020: 09 02 0a 08 11 01 14 02 17 01 18 01 19 01 1c 01 ................ 0x000030: 22 01 24 01 ".$. Tag_CPU_raw_name = "Cortex-M7.fp.dp" Tag_CPU_name = "Cortex-M7" Tag_CPU_arch = ARM v7E-M (=13) Tag_CPU_arch_profile = The microcontroller profile 'M' (e.g. for Cortex M3) (=77) Tag_THUMB_ISA_use = Thumb2 instructions were permitted (implies Thumb instructions permitted) (=2) Tag_FP_arch = Use of the ARM v8-A FP ISA was permitted, but only citing registers D0-D15, S0-S31 (=8) Tag_ABI_PCS_GOT_use = Data are imported directly (=1) Tag_ABI_FP_denormal = This code was permitted to require that the sign of a flushed-to-zero number be preserved in the sign of 0 (=2) Tag_ABI_FP_number_model = This code was permitted to use only IEEE 754 format FP numbers (=1) Tag_ABI_align_needed = Code was permitted to depend on the 8-byte alignment of 8-byte data items (=1) Tag_ABI_align_preserved = Code was required to preserve 8-byte alignment of 8-byte data objects (=1) Tag_ABI_VFP_args = FP parameter/result passing conforms to the VFP variant of the AAPCS (=1) Tag_CPU_unaligned_access = The producer was permitted to generate architecture v6-style unaligned data accesses (=1) Tag_FP_HP_extension = Use of the optional half-precision extension to VFPv3/Advanced SIMDv1 was permitted (=1) 'aeabi' section build attributes for sections: i.Afe_ConfigureDma (#4) i.Afe_Rx_Cb (#5) i.Afe_SendData (#6) i._AfeConfigureDmaChannels (#7) i._Afe_configureLinkList (#8) i.__NVIC_ClearPendingIRQ (#9) .data (#10) 0x000000: 43 32 2e 30 39 00 12 02 1a 01 1e 06 C2.09....... Tag_conformance = "2.09" Tag_ABI_PCS_wchar_t = Size of wchar_t is 2 (=2) Tag_ABI_enum_size = Enum values occupy the smallest container big enough to hold all values (=1) Tag_ABI_optimization_goals = Optimized for best debugging illusion, speed and small size sacrificed (=6) 'aeabi' section build attributes for sections: .rev16_text (#1) .revsh_text (#2) .rrx_text (#3) 0x000000: 18 00 1e 04 .... Tag_ABI_align_needed = Code was not permitted to depend on the alignment of 8-byte data (=0) Tag_ABI_optimization_goals = Optimized aggressively for small size, speed and debug illusion sacrificed (=4) 'ARM' file build attributes: 0x000000: 12 01 14 09 .... 'ARM' section build attributes for sections: .rev16_text (#1) .revsh_text (#2) .rrx_text (#3) 0x000000: 0e 01 .. ====================================
I have noticed there are no section named .reli.Afe_ConfigureDma. Is that a problem? How should I solve it?
The original error message rather strongly indicates that our problem is with mixing C and C++ code: receiver.o was built by the C++ compiler, whereas afe_dma.o was built by the C compiler.
Note how the error message refers not only to the name of the purportedly missing functions, but also their argument types? Well, if "receiver.o" had been a C source module, the linker would not know the argument types. Only C++ compilers mangle those into the names of functions as presented to the linker, because they need that extra information for argument type-based function/operator overloading.
You have two main possibilities at this point: make sure all modules are compiled as the same language (either all C++, or all C), or use the mechanisms provided by C++ to mark declarations as belonging to C objects.
extern "C" uint32_t Afe_ConfigureDma(AfeDma *pAfed , Afec *pAfeHw , uint8_t AfeId, sXdmad *pXdmad); extern "C" uint32_t Afe_SendData(AfeDma *pAfed, AfeCmd *pCommand);
Yes, my Receiver.c was set to C++ file type, I do not remember setting that, probably misclicked something. This is a silly mistake from my part, which I have never encountered before. The code is working now.
Thank both of you very much for your help, and I sorry that I robbed your valuable time.
No worries, C++ / .CPP induced name mangling catches a lot of people out, glad it is resolved.