This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Unable to convert R52 sample project from Arm Compiler for Embedded to GCC

Hi,

In order to introduce my issue, my goal is to get 2 similar projects, one compiled by Arm Compiler for Embedded 6 and the other by GCC,  both on a FVP Cortex R-52 target.

I chose to build the project on the example available when installing Arm Development Studio named startup_Cortex-R52.

Concerning the Arm Compiler part I have no issues, project works fine as I did not change anything. So I tried to build my second project, compiled by GCC based on the startup_Cortex-R52 example.

I added the GCC 10.3.1 toolchain to Arm Developement Studio and choosed this toolchain in the Tool Chain Editor of my project. I have also set up my project by giving these options in project properties for both GCC Compiler and Assembler : -mcpu=cortex-r52 -mfpu=neon-fp-armv8 -mfloat-abi=hard

Errors occur when I try to build the project and specially in the startup.s file are related to Assembler messages :

I am wondering why I faced this issues as the target is the same and Assembler language too.

If someone can help me to resolve this issue I would be grateful.

Regards, Enzo

  • Hi Enzo

    The startup_Cortex-R52 example can be compiled with arm-none-eabi-gcc in the same way as armclang, i.e.:
    arm-none-eabi-gcc -mcpu=cortex-r52 -mfpu=neon-fp-armv8 -mfloat-abi=hard -x assembler-with-cpp -mthumb -g -c startup.s

    Note that you'll need to

    1) Change line 523 from
    ANDS r0, r0, 0xF
    to
    ANDS r0, r0, #0xF
    (gcc seems stricter than armclang here)

    and

    2) Comment out line 550 (which anyway isn't needed):
    //    .size Reset_Handler, . - Reset_Handler

    Hope this helps

    Stephen

    • Hi Stephen,

      Thanks for your answer, I made the changes you suggested but it seems that the option "-x assembler-with-cpp" is not accepted.

      The way I defined it was :

      But I have an error although the command line seems similar to the one you proposed to me :

      I am a beginner with Arm Development Studio maybe I am missing something in the configuration of this flag.

      Thanks

      Enzo

      • Hi Enzo

        To use the "-x assembler-with-cpp" switch, you must use arm-none-eabi-gcc for the assemble step, instead of arm-none-eabi-as.

        You can do that by modifying the command used for the assemble step in the GUI project settings:


        To convert the rest of the project from AC6 to GCC, take a look at the smp_primes_A9x4_AC6 and smp_primes_A9x4_GCC examples.

        By comparing these two projects, you'll see what changes you will need to make to startup_Cortex-R52.

        Hope this helps

        Stephen

        • Hi Stephen

          Thank you again for your answer which allowed me to move forward.

          As you suggested I compare the two projects and find differences between GCC project and the AC6 one.

          Nevertheless i have some issues in the MPU Configuration in my R52 project, which didn't exist in A9x4 projects.

          Some references are undefined, related to "Image$$xx$xx" variables.

          In fact those "variables" are not included in both A9x4 projects so I can't compare them. Maybe you will know the GCC equivalents for those variables.

          Regards,

          Enzo

          • Hi again Enzo

            The "Image$$xx$xx" symbols are generated by the Arm Linker armlink, in response to code and data regions specified in the scatter file.

            You will need to modify the source code to use corresponding symbols that you must add into the GCC linkers .ld script.

            For example, to replace Image$$DATA$$Base, add into gcc.ld:

                .data 0x10000:
                {
                    __data_start = . ;  <<< added
            :
                }

            and change in startup.s:

                    // Region 1 - Data
                    LDR     r1, =__data_start  <<< modified to match
                    LDR     r2, =((Non_Shareable<<3) | (RW_Access<<1))
                    ORR     r1, r1, r2
                    MCR     p15, 0, r1, c6, c8, 4                   // write PRBAR1

            Hope this helps

            Stephen

            • Hi Stephen I made a gcc.ld file as you suggested to add corresponding symbols.

              But there is an error in the configuration of the flag "-T gcc.ld".

              I configure it in following this way :

              Thanks for your help,

              Enzo

              • Hi Enzo

                It looks like you are making good progress - well done!

                If you have placed gcc.ld at the root of the project, then use "-T../gcc.ld".  If not, then insert some other project-relative or absolute path.

                Hope this helps

                Stephen

                • Hi Stephen

                  Thanks for your answer. I am currently programming my gcc.ld file based on the scatter file for the R52 example. The scatter file is the following : 

                  I notice that there is no memory left between each symbol so it means that i am not supposed to have any Sections between .vectors and .data in my linker script (gcc.ld).

                  I am wondering where should I put all sections in the gcc.ld (A9x4) between .vectors and .data in my gcc.ld example.

                  i try to develop my gcc.ld this way (following the A9x4 example) but I am probably missing something.

                  But obviously I have overlap issues as there is no memory available for others sections between .vectors and .data

                  I am wondering if my linker script is similar to the initial scatter file and how to manage the location of others sections.

                  Thanks again for your help Stephen

                  Enzo

                  • Hi Enzo

                    In the scatter file for startup_Cortex-R52, the last parameter 0x8000 in the execution region "CODE +0 0x8000" is an optional maximum length that armlink can use to warn about region overflows, so in your .vectors region you don't need the line:
                            . = . + 0x8000;

                    Also, you'll need to move
                            __code_end = .;
                    to after all the code, i.e. to between the end of .jcr and the start of .data.

                    If GCC is generating larger code than Arm Compiler, causing overflows, you might need to push the start of the .data region to a higher address, e.g.
                    change
                        .data 0x8000:
                    to e.g.
                        .data 0x9000:

                    For the stack, the line in startup_Cortex-A9_GCC gcc.ld:
                            . = . + 4 * 0x4000;
                    was used to represent stack space for each of the 4 cores.
                    If your system has only a single core, you won't need the "4 *"

                    Hope this helps,

                    Stephen

                    • Hi Stephen,

                      You are right GCC is generating larger code than Arm Compiler. I add the command "-Xlinker -Map=output.map" which help me to see the memory allocation.

                      Finally my gcc.ld looks like this :

                      If it can help someone, you can mention that I add these lines to .bss to resolve an error and change .data and .heap starting addresses memory allocation :

                      Last errors are the following :

                      I know that those issues could be resolved by adding the flag "-specs=nosys.specs" but it will disable the semihosting whereas I want to use it to print the execution time and other stuff. Is there any other solution to resolved these errors ?

                      PS : I also tried the -specs=rdimon.specs but it led to this error which I am unable to resolve

                      Thanks again,

                      Enzo

                      • Hi Enzo

                        You should link with --specs=rdimon.specs, then add the necessary "__end__" symbol into your gcc.ld to mark the end of the .bss region.

                        Hope you will now get a successful link :)

                        Stephen

                        • Hi Stephen,

                          Thank you so much, now my linking is working well and i could build the project without errors.

                          When I try to debug my project I am facing an error, I think that i never reach the main of my program. I set the debut point to entry point to understand the process. My program correctly execute instructions in the startup.S file that I have created. The issue occurs after the _start symbol (at the end of my startup file) :

                          In the disassembly window, Its seems that my program is stuck after executing these line in the memset function :

                          Which led to the EL1_Abort_Addr which I think I should not be redirected to :

                          And then I am blocked in Evaluating step in the progress.

                          I don't know what can led to this issue, do you think it's a memory address assignment issue ?

                          Thanks again.

                          Enzo

                          • Hi Enzo

                            I suspect this is a problem with the stack.  As a quick experiment, try making the stack larger.  For a more detailed analysis, you will need to step through the startup code to see where the stack pointer is changing (watch SP in the Registers view).  

                            The original startup code for AC6 (in startup.s) sets up stack areas for all modes (ABT, IRQ, FIQ, SVC).  I believe the GCC startup code (within crt1.o) does the same again, so stack space is being unnecessarily wasted.  You can probably remove that unneeded code from startup.s.  

                            I hope this helps you makes some further progress with your debugging.

                            Stephen

                            • Hi Stephen

                              As you suggested I removes the unneeded code in startup.s which sets up stack areas for all modes (ABT, IRQ, FIQ, SVC).

                              I debugged my program step by step and I didn't mention any change concerning SP register during the execution of startup.S.

                              In fact, in the Disassembly window when program enter in the _stack_init symbol SP register address is moving to the value 0xFFFF0000 or my stack is define between 0x00013000 and 0x00023000 (see the following map file). I am wondering how can I change this assignment (how to access to _stack_init).

                              Thanks again.

                              Enzo

                              • Hi Enzo

                                I suspect you have not launched the FVP model with "-C cluster0.cpu0.semihosting-stack_base=0".


                                When the FVP model is launched, some default values for stack/heap base/limit are applied.
                                You can see the defaults by launching the FVP model on the command-line with e.g.:

                                C:\Program Files\Arm\Development Studio 2022.1\bin>FVP_BaseR_Cortex-R52x1.exe --list-params | find "semihosting-"
                                :
                                cluster0.cpu0.semihosting-heap_base=0                 # (int   , init-time) default = '0x0'    : Virtual address of heap base.
                                cluster0.cpu0.semihosting-heap_limit=4278190080       # (int   , init-time) default = '0xff000000' : Virtual address of top of heap.
                                cluster0.cpu0.semihosting-stack_base=4294901760       # (int   , init-time) default = '0xffff0000' : Virtual address of base of descending stack.
                                cluster0.cpu0.semihosting-stack_limit=4278190080      # (int   , init-time) default = '0xff000000' : Virtual address of stack limit.
                                :

                                That explains why you are seeing '0xffff0000' being obtained by the semihosting call at the beginning of _start:
                                MOVS     r0,#0x16
                                ADR      r1,{pc}+0xc2 ; 0x1F4
                                SVC      #0xab

                                The use of "0" for stack_base and heap_base have particular purposes.  For stack_base=0, it doesn't mean put the stack at 0x0.  At run-time, if the C library startup code gets a stack_base of 0 from that semihosting call, it replaces the 0 with a stack_base address derived from the gcc.ld script by the linker at link-time.

                                You can see this effect if you step through the code in _start.

                                Stephen

                                •  I am trying to create this exact project using GCC! Would you be able to provide it as a .zip file here for me?

                                  I would greatly appreciate it!

                                  Chris

                                  0