Error: L6218E: Undefined symbol ulICCIAR (referred from portASM-77f2ec.o

I’m trying to create a port for Cortex R8 using Cortex R5 as a reference and my compiler is ARMClang. While compiling the portASM.S with armclang compiler. Whille using the R5 port.c and portASM.S as reference I’m getting an issue at the assembly compilation phase. The variable is declared in port.c and port.o is getting compiled. There are 9 other symbold from portASM.S getting the same error. how to compile this portASM.S succesfully with these symbols.

This symbol is defined in that port’s port.c file as:

uint32_t ulICCIAR __attribute__( ( at( portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ) ) );

in the RVDS port and

__attribute__( ( used ) ) const uint32_t ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;

in the GCC port.

The linker can’t see where the symbol gets used because its declared in the c file but used in the asm file - hence the “used” attribute to prevent the symbol being removed. I’m not sure what the ARMClang equivalent will be, but as its LLVM based I imaging the GCC syntax would work.

the cortex R5 port had the GCC port which i used in my case also,

 __attribute__( ( used ) ) const uint32_t ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;

So the error I posted is for the GCC port only.

Are you compiling port.c and passing the corresponding port.o to the linker? You can check that by adding -v to see the linker command used by armclang. The next step is to check if port.o exports this symbol. You can use nm command to see the symbols exported from port.o.

The nm command showed the symbols are exported, adding the -v command the port.o is not passed to the linker. Sharing the armlink command here,

"/usr/local/ArmCompilerforembedded6.21/bin/armlink" -o ../../out/OBJS/portASM.o --stdlib=libc++ /tmp/portASM-c0908f.o

Your compiler command seems to have a wrong flag -I in front of …/port.c.
So it’s maybe not compiled at all ? I’d try to remove or fix the spurious -I flag right before port.c and check if there is a compiled port.o to link.

That is an issue. Why is that not happening? Which build system are you using?

I am using make for my compilation,
After seeing the -v prints, I understood that the compilation is happening in two steps. One with armclang and then with armlink.

From the manual I checked there is a command line option -Xlinker to pass arguments to the linker. I added the following flag, is this the right method to bypass the problem.

ASFLAGS += -Xlinker ../../out/OBJS/port.o

ASFLAGS are probably for assembler. Are you invoking linker manually? Can you share your Makefile?

Yes, i am currently invoking the linker manually.

At firs I didn’t add the -c flag was not part of the ASFLAGS, so to pass port.o to linker I had to use the -Xlinker. But that was not necessary once I added the -c flag. Now I’m able to compile and create the final binary with some symbol problems which I’m addressing below.

I wont be able to share my Makefile but it looks very similar to the CR5 demo Makefile.

  1. The symbols ulICCIAR, ulICCEOIR, ullCCPMR, ulMaxAPIPriorityMask used in port.c like this,
__attribute__( ( used ) ) const uint32_t ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
__attribute__( ( used ) ) const uint32_t ulICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS;
__attribute__( ( used ) ) const uint32_t ulICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS;
__attribute__( ( used ) ) const uint32_t ulMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );

I was getting undefined symbol issue until I removed the const keyword from all these 4 variables as this,

__attribute__( ( used ) )  uint32_t ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
__attribute__( ( used ) )  uint32_t ulICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS;
__attribute__( ( used ) )  uint32_t ulICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS;
__attribute__( ( used ) )  uint32_t ulMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
  1. The symbols pxCurrentTCB, vTaskSwitchContext are not present in the port folder of CR5, other port folders have these. I had to comment out these for now. Where should I find the best suitable ports for these symbols.
  2. vPortRestoreTaskContext is a symbol defined in portASM.S and used as extern in port.c currently is going undefined. What makefile changes should I make for this to be included rightly.
  3. Some symbols needed definition vMainAssertCalled, vClearTickInterupt, configureTickInterrupt from the project folder for which I have created empty stubs for now.

The __attribute__( ( used ) ) should ensure that the compiler does not drop these symbols. Can you run nm on port.o and confirm if these symbols exist?

These are defined in tasks.c.

Can you share what errors are you getting?

Are you trying to build just the port files? You need to build all the the files (FreeRTOS common files, FreeRTOS port files and application files) in one application.

I seem to remember one of the C Standard updates made primative const objects that are initialized in the translation unit to be “static” by default, so header files could use them as constants, and not forcd the creation of memory (or multiple definitions) for them.

See it making them extern const fixes the issue, as that forces them to be global, and the initialization forces them to be made in that file.

Good point. I think it is done in C++. Regardless, nm would confirm if this symbol is not exported from port.o.