This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/TMS320C6424: Cannot apply copy table operator on compiler/linker >=CGT7.3.x

Part Number: TMS320C6424

Tool/software: TI C/C++ Compiler

Hi All,

we’re using a C6424-600 in one of our DSP-products, which has originally been developed with CCS3.3 and CGT6.1.23.

I’m currently migrating our CCS3.3 project to CCSV8 and tried to compile the code using the 7.x compilers. The project is legacy coff.

Unfortunately the newest compiler, that is capable of compiling and linking the code against our custom linker command file is CGT7.2.12.

Later versions like CGT7.3.23 or CGT7.4.24 are reporting a linker error as below or similar:

"C:/Path/BootloaderFlash.cmd", line 98: error #10320-D:

   cannot apply table(_ApplicationCopyTable) operator to C auto initialization

   section ".cinit"; this section contains linker-generated copy table

   sections

The corresponding part of the linker command files is:

GROUP {

.text:_c_int00

            .text:vecs

            .text

            .pinit

            .cinit

            .switch

            .const

            .cio

} load = FLASH, run = DDR2_CODE, table( _ApplicationCopyTable )

 

As already said, CGT6.1.23 and CGT7.2.12 will compile and link without any problems.

 

Any ideas? 

Btw, does it make sense to step up to the 7.x compilers or even use the 8.x compilers and migrate the code from legacy coff to eabi on a C6424?

 

Best regards,

Flux.

  • I need to understand more about how your system works now.  When and how do all those sections get copied from FLASH to DDR2_CODE?  I think it has to happen before the boot routine c_int00 starts.

    Thanks and regards,

    -George

  • Hello George,

    thank you for your reply. I will try to explain a bit more.

    The DSP-firmware has been programmed kernel-free. We’re using AIS-boot from an external 32MB parallel NOR-flash memory. The board has 256MB of DDR2-Ram.

    The AIS-script will setup the EMIFA, setup the PLL1, setup the PLL2, setup the DDR2 memory controller and call a bootsetup-routine, which will setup caches, do some system and memory testing, that cannot be done at runtime. If the tests have been successful the bootsetup-routine will copy the program code from the NOR-flash to the DDR2-memory by using the linker generated copy table. After the program code has successfully been copied to the DDR2 memory, the bootsetup-routine will return to the AIS script, which will then call c_int00, which resides in DDR2 memory at that time.

    The link process fails with reference to the .cinit section given inside the GROUP of sections in the linker-command-file. Somewhere between CGT7.2.12 and CGT7.3.23 something has changed that now prevents a successful link process.

    Best regards,

    Flux.

  • Flux said:
    the bootsetup-routine will copy the program code from the NOR-flash to the DDR2-memory by using the linker generated copy table.

    We did not anticipate that use case.

    Since the first release of copy table support, we made improvements to the error handling.  One error we detect is attempting to apply the table operator to the .cinit section.  This section contains, among other things, copy tables for initializing read/write sections like .data.  Therefore, it has be located in its final location when c_int00 starts.  Thus, we issue the error diagnostic you see.

    We presumed no one would somehow copy .cinit from elsewhere, and then start c_int00.  Yet that is what you do.  You can suppress the diagnostic with the option --diag_suppress=10320 .  To be honest, I'm not 100% certain this will solve the problem.  But I think it is worth a try.

    Thanks and regards,

    -George

  • Hello George,

    thank you for the explanation.

    But, what is the “correct” way to generate a loadable program-image resided in flash that can be copied by the bootsetup-routine to a certain memory location and THEN be started by calling c_int00?

    The reason for our approach is that we want to be able to fully test our hardware at boot-time. The bootsetup-routine among other tests will check all memory locations in DDR2 memory first, that will hold code and data, load the complete code, verify the code and then run the code by calling c_int00.

    The bootsetup-routine runs in context of the C6424 boot-rom. The extract of the AIS-script is as follows:

                .global _AisScriptStart              ; make ais script visible to the rest of the code

                .global _AisScriptEnd

                .ref _c_int00                             ; import c_int00

                .ref _BootSetup                        ; bootsetup function to call in C6424 boot-rom context

                 .sect ".AIS"

    _AisScriptStart:

                <skipped>

                .word 0x58535905                                ; ais JUMP command

                .word _BootSetup                                ; call boot setup function

                .word 0x58535906                                ; ais JUMP CLOSE command

                .word _c_int00                                     ; application start address

                .word 0x00000000                                ; number of sections that should have been loaded

                .word 0x00000000                                ; number of bytes that should have been loaded

    _AisScriptEnd:

    Indeed, after suppressing the error, the code compiles, but doesn’t run anymore. I tried that with CGT7.3.23.

    What is the proper way to do it with the newer CGTools?

    Best regards,

    Flux.

     

  • see above...

  • Hello George,

    to me it actually seems that copy table functionality has been broken in the newer compilers. And I would like to file that as a linker defect.

    Please look at the extract from the mapping file of the CGT7.2.12 and CGT7.3.23. You can see that .cinit has been properly processed with correct load and run addresses, which is completely logical.

    To me this is clearly a linker defect. It must be possible, to generate a single .out-file/single rom image that holds a bootsetup-routine (called by AIS), that does some system-testing before the actual application runs and then copies the whole application from flash to ram including .cinit. Which way can it be done then? As you can see, the older compilers did that correctly. The newer compilers now fail to handle that case. Or do you want to say, that the older compilers have been creating incorrect code when copy tables have been applied to .cinit?

    CGT7.2.12:
    =========

    LINKER GENERATED COPY TABLES

    _ApplicationCopyTable @ 42000300 records: 8, size/record: 12, table size: 100
    .text:_c_int00: copy 96 bytes from load addr=42000800 to run addr=80000000
    .text:vecs: copy 512 bytes from load addr=42000c00 to run addr=80000400
    .text: copy 197824 bytes from load addr=42000e00 to run addr=80000600
    .cinit: copy 2612 bytes from load addr=420312c0 to run addr=80030ac0
    .pinit: copy 24 bytes from load addr=42031cf4 to run addr=800314f4
    .switch: copy 256 bytes from load addr=42031d0c to run addr=8003150c
    .const: copy 23622 bytes from load addr=42031e10 to run addr=80031610
    .cio: copy 0 bytes from load addr=42037a56 to run addr=80037256


    CGT7.3.23:
    =========

    LINKER GENERATED COPY TABLES

    _ApplicationCopyTable @ 42000300 records: 6, size/record: 12, table size: 76
    .text:_c_int00: copy 96 bytes from load addr=42000800 to run addr=80000000
    .text:vecs: copy 512 bytes from load addr=42000c00 to run addr=80000400
    .text: copy 198144 bytes from load addr=42000e00 to run addr=80000600
    .pinit: copy 24 bytes from load addr=42031e34 to run addr=80031634
    .switch: copy 256 bytes from load addr=42031e4c to run addr=8003164c
    .const: copy 23622 bytes from load addr=42031f50 to run addr=80031750


    Best regards,
    Flux.
  • Hello George,

    is there any activity going on on your side regarding this issue?

    Best regards,
    Flux.
  • Flux,

    This doesn't really address the question about the linker/compiler, but I want to add that this use of the AIS JUMP command was never anticipated. That was intended for very simple bits of code to do very targeted operations. It sounds like you have written an entire boot loader of your own to operate inside that jumped to function. The data copy from the flash to the memory was anticipated to be done using AIS load/copy commands, executed by the device's ROM boot loader.

    Regards, Daniel

  • Making it an error to apply a copy table to the .cinit section is viewed as fixing an oversight that goes all the way back to the introduction of copy tables.  It is unfortunate that, in that time, you stumbled into a way to take advantage of this oversight.

    So, I filed the entry CODEGEN-5079 in the SDOWP system.  This entry does not report a bug, but requests a change in how the linker works.  The request is to allow the copy table operator to be applied to .cinit.  Such requests are reviewed on a regular basis.  Some are implemented, and some are not.  I have to be honest with you, and point out that you face a disadvantage.  The linker started issuing this error diagnostic about 7 years ago.  In all that time, you are the first to complain.

    When a bug is filed in SDOWP, it is typically made public so a customer can track it.  An internal change was recently implemented regarding enhancements.  Right now, there is no way for you to track it.  Though this may change in the near future.

    Thanks and regards,

    -George

  • Hello Daniel,

    thank you for your thoughts on this issue.

    The bootsetup is actually very few lines of C code with small memory footprint that uses the linker generated copy table to copy code/data to its final location. Very simple. Otherwise one had to use the TI Perl script to convert the .out file to AIS and somehow add the memory test before code/data is being finally copied by the C6424-bootrom. Not sure this is even possible. Simply writing some lines of C seemed more flexible to me. And if you take a look at the SPRAAK5B documentation of the C642x bootrom it even suggests to use the JUMP command for Bootloader 2. Whether or not there have  already been loaded some sections by AIS shouldn't make a difference.

    Regarding the compiler/linker question, I don't see any logical reason, why having linker generated copy tables inside .cinit should prevent applying the copy table operator with different run/load addresses to .cinit as the newer compilers suggest by throwing the error. The linker knows the load address, knows the run address and can resolve any references inside the copy records inside .cinit.

    The older compilers did that correctly. At least it seems so, regarding the map-files of the 6.1.23 or 7.2.12 compilers for example. And its the more regular case than handling .cinit differently from the other sections.

    So, I hope TI tells us, whether the older compilers have been generating correct code in that case or not. And secondly TI adds the more regular case to their newer compilers again.

    Best regards,

    Flux.

  • Hello George,

    thank you for taking the time to explain more about this issue and setting up the change request.

    Can you explain a bit more about the copy table support on the older compilers? Will the code be incorrect when the table operator has been applied to .cinit? Under what conditions? How can I find out if there are false copy records somewhere in .cinit? Any proposal?

    Best regards,
    Flux.
  • I think it would help if I explained, in general terms, how global variables are initialized, and how the .cinit section is related. (For those reading along, this explanation focuses on the older COFF ABI, which this customer uses. The newer EABI is much more common. There are some similarities at a high level. But the lower level details are quite different.)

    Start by reading the section titled System Initialization in the C6x compiler manual for version 7.4.x. Ignore the EABI sections. Focus on the section titled Autoinitialization of Variables at Run Time. This comes closest to your case. The figure there is a bit outdated. Loader should be called Flash Programmer. EXT_MEM should be called FLASH. D_MEM should be called RAM.  

    One key thing to understand is that the .cinit section performs a role similar to a copy table. Values start in .cinit, in FLASH. When the system turns on, the startup code processes entries in .cinit to copy those values to locations in RAM. The rest of the system has no idea this ever happened. It acts as if those values are always in the RAM location.

    Consider the case where the .cinit section is allocated one address for load, and another address for run. The rest of the system acts like .cinit is always at the run address. When and how does the .cinit section get copied from load to run? The startup code, as supplied, cannot do it. I suppose the startup code be changed. But, so far as we knew, no one needs this capability. So, instead of changing the startup code, we put a diagnostic in the linker. This diagnostic is emitted any time the table operator is applied to .cinit. This diagnostic should have been in the linker when copy tables were introduced. However, this detail was overlooked.   The diagnostic was added later.

    How does it work in your specific case? The .cinit section has different load and run addresses. All the rest of the system, including the startup code, acts as if .cinit is located at the run address. You use the AIS boot feature to copy .cinit from load to run. Because this copy completes before the startup code begins, it works.

    Thanks and regards,

    -George

  • Hello George,

    thank you for the clarification. Good and important to know that the older compilers haven’t generated incorrect program code in that case.

    But, I’m not sure that no one needs this feature being able to apply ‘table()’ to .cinit. Again, consider the following case: How can you test a memory system after power-on if you have already called c_int00? Calling c_int00 will initialize a lot: init runtime libraries, copy variables, etc. All that stuff must reside somewhere in the fast sdram you now want to test. How can it be done at runtime without complicated approaches?

    To me it seems relatively easy to do the required tests with a few lines of code and THEN copy the software from flash to ram with all sections including .cinit and then call c_int00. These kind of early system tests are a must if you’re in embedded design in industrial or medical measurement and have been done for decades. Not doing those tests at power-on seems a bit risky to me. So, I’m a bit astonished to hear TI say that no one needs 'table()' on .cinit.

    Given your current approach at TI, making it an error to apply ‘table()’ to .cinit, how can you do all that early system testing after power-on and having called c_int00 already? Maybe there’s also an oversight on my side which prevents using the tool’s current functionality effectively. What would you do, if a customer wants those early system tests in a product? Which way can your tools be used in that case?

    Best regards,
    Flux.
  • Hello George,

    another problem that arises, when ‘table()‘ is forbidden for .cinit is that you cannot hold multiple applications in flash anymore and load them on request.

    We’re currently using our flash memory to hold multiple applications and are loading them on request by using the copy tables of each application and applying a relocation offset. The applications have been stored consecutively one after the other in flash memory. Each application has been compiled and linked as if it were located at the flash base address. The copy routine takes care of the actual position of an application in flash. Each application comes with a program header that allows identifying it, its size and so on. The technique is useful for a system for example that needs a bootloader application as a fallback and that’s capable of flashing the actual application without risk in case the actual application’s code is defect.

    So, how can that be done, if .cinit has to be on a fixed location in flash on the newer CGTs now? Well, at the time disallowing ‘table()’ on .cinit on the newer CGTs just takes away functionality that was useful in the past. I currently don’t see any advantage in making this an error.

    But, as I already said, maybe there’s a better approach using the tools, I have overlooked. How would you do that?

    Best regards,
    Flux.
  • Thank you for taking the time to provide additional insight.  I view these posts as additional reasons to implement a change in the linker.  I added them to CODEGEN-5079, which is still under review.

    Thanks and regards,

    -George

  • You still build your project with the older COFF ABI.  Unfortunately, COFF ABI support has ended.  We no longer plan to implement any improvements for the COFF ABI tools.  

    If we agree to implement this change, it would only be available with the newer EABI.  Are you willing to change from COFF ABI to EABI?

    Thanks and regards,

    -George

  • Hello George,

    thank you for your support. Let me put it this way:

    Being able to load a program to a certain location in SDRAM is a must have for embedded applications. Please don’t see the .cinit copy table changes just dependent on our needs. These changes seem to have to be done anyways.

    The current 8.2.x compilers are relatively new and we don’t intend to use them for maintaining our C64x+ single core code. Also, first tests show, that our code runs about 15% slower than by using the 6.1.23 CGT. But maybe that’s a cache issue. Don’t know.

    Another problem indeed is eabi. The bootloader/application configuration described earlier requires the same calling convention. So, switching to eabi is most likely not an option for this project. Further on TI’s fast RTS library officially comes in coff only. Yes, there is an unofficial elf version somewhere on the forum…

    So, the right choice would be to use the 7.4.x compiler, which is mature, supports coff, is comparably fast in coff mode and has been maintained until 2017. Unfortunately if you say you don’t intend to make the changes to them, we will have to stay with the 6.1.23 CGT of 2013 for this project, which is a bit disappointing. On the other hand, the code works very well using the CGT 6.1.23.

    The 7.4.x compiler is of status “reactive”. Following your terminology, it means changes can done on a need basis. Using the latest, mature CGT 7.4.x should be the way to go.

     

    Best regards,

    Flux.

  • Once again, thank you for your feedback.  I have added it to the entry CODEGEN-5079, which is still under review.

    Thanks and regards,

    -George

  • Here is an update regarding CODEGEN-5079 ... You can look it up with the SDOWP link below in my signature (well, in a few hours).  A fix for COFF ABI will not be implemented.  A fix for EABI is not currently planned, but might be implemented in the future.

    Thanks and regards,

    -George

  • Hello George,

    making the newer code generation tools incompatible by taking away useful functionality, declaring it as a fix for an oversight, then refusing to change that back by apodictically stating “the coff abi is not supported any more”, although even in your own terminology the 7.4.x code generation tools have been labeled as “reactive”, which means that changes can still be made on a need basis, certainly doesn’t make your customers happy.

    The changes to copy tables prevent a) early system hardware/ram tests before the actual application code runs, prevent b) copying a whole application from location A to B and starting it ( the classical, reliable bootloader/application approach).

    If you refuse to change back copy table support for the current and future code generation tools, will you please describe how requirements a) and b) can be fulfilled using the current and future CGT without complicated approaches.

    Because we currently believe there is no easier way using the current CGT, we still kindly ask you to correct the broken copy table support for the CGT7.4.x and later compilers.

    Best regards,
    Flux.
  • I acknowledge our decision has a negative impact on you. Please accept our apologies. I do not expect this post to change your mind. But I hope to explain our decision enough to show that it was reached after careful and diligent consideration. But first I will discuss how you can continue useful work today.

    You are welcome to use C6000 compiler version 6.1.23 in combination with CCS version 8.x. The obvious advantage is your system continues to work as is. The downside is you don’t get to use any new features introduced in later versions of the compiler. I suspect that is not of much concern.

    Switching to an explanation of our decision …

    We have proof, by direct experiment in the field, that, except for you, our customers do not need to copy .cinit from one memory location to another. The linker started issuing the error diagnostic that prevents this copy about 7 years ago. In all that time, you are the only customer to complain.

    Why do we no longer support COFF ABI? Removing support for COFF ABI reduces our maintenance and test burden by half.   That is very significant. We introduced support for EABI about 8 years ago. We are confident nearly all our customers have switched to EABI. At some point, we have to tighten our focus on to the use cases most common among our customers. That is the level of support those customers require, and we intend to provide it.

    Therefore, we have no plans to fix this issue for COFF ABI. We may yet fix it for EABI, but even that is unlikely.

    You raise these points …

    Flux said:
    The changes to copy tables prevent a) early system hardware/ram tests before the actual application code runs, prevent b) copying a whole application from location A to B and starting it ( the classical, reliable bootloader/application approach).

    Flux said:
    please describe how requirements a) and b) can be fulfilled using the current and future CGT

    I lack the expertise to answer, though I am confident solutions exist. I suggest you start a new thread on this question in the C6400 device forum.

    Thanks and regards,

    -George