Placing Functions at Specific Flash Address to Conform to IEC 60730 Class B Tests - KBA230832

Version 2

    Author: AH_96           Version: **

     

    Question:
    How do I place the Program counter functions at a required address with a large application code when compiling with Arm® GCC?

     

    Answer:
    This document assumes that you have referred to the following application notes: AN89056 - PSoC® 4 - IEC 60730 Class B and IEC 61508 SIL Safety Software Library and AN89610 - PSoC® 4 and PSoC 5LP Arm® Cortex® Code Optimization.

    The IEC 60730 standard, which is described in AN89056 and AN89610, requires a few functions to have absolute address with some pattern in its bits (that is, its lower bits must be 0b0101, like 0x15555, or 0xaaaa). But sometimes the code size is larger than this and might cause an overlap. In this case, the user must write custom linker script with functions placed manually.

    The following steps shows how to create a custom linker script with the functions placed at the correct address:

    1. Steps to generate custom linker script:

      1. Build your project with generated linker script.
      2. Copy generated linker script file, for example, <project_folder>\Generated_Source\cm0plusgcc.ld to project_folder. cm0plusgcc is chosen as an example. The actual name of the linker script is dependent on the CPU of the device that is chosen.
      3. Click on Project > Build Settings > ARM GCC <version> > Linker > General > Custom Linker Script and choose the linker script that was copied into the project folder in the previous step.

     

    2. Once the custom linker script is ready, generate the symbols using the nm program. The GNU nm program lists the symbols from the object files. For GCC bundled with PSoC Creator, the default location is C:\Program Files (x86)\Cypress\PSoC Creator\<PSoC Creator Version>\PSoC Creator\import\gnu\arm\<arm version installed>\bin\arm-none-eabi-nm.exe. This is the path to the nm program

     

    3. Follow these steps to generate the list of code section symbols:

      1. Open command prompt and change the directory to the project’s output folder, the folder where the .hex and .elf files are stored. The typical path to this is \<ProjectName>.cydsn\CortexM0\ARM_GCC_541\Debug\.
      2. Run command: "<path to nm>\arm-none-eabi-nm.exe" -a -n <ProjectName>.elf >[RMB1] [AH2] [GKK3] <ProjectName>.defsym.
        Note: The “>” symbol after <ProjectName>.elf is added to create the output in a new file called <ProjectName>.defsym.
      3. Select only code section symbols from <ProjectName>.defsym with the following command:
        findstr "\<T\> \<t\>" <ProjectName>.defsym > <ProjectName>.defsym.code.


     

    4. Open the <ProjectName>.defsym.code file in any advanced text editor like notepad++ that allows multi-line editing and allows usage of extended symbols like “\r” and “\n” in the replace dialog.

     

    5. Move the text pointer to a position before the first character in file. Start multi-line editing of all lines in the file by pressing Page Down or Arrow Down buttons multiple times while holding Alt+Shift (in notepad++).

     

    6. When the text pointer goes to the last nonempty line of the file, release the Alt+Shift buttons.

     

    7. Press Delete button until you meet the first character of symbol names in the first column of the editor, as shown in the following screenshot.

     

    8. Write “KEEP(*(*” in multi-line editing mode, so all selected lines have “KEEP(*(*” at the beginning of them.

    9. Put “))” at the end of every non-empty line in the file, by following these steps:

      1. Press the Replace shortcut keys (Clrt+H in notepad++) or menu command Search > Replace.
      2. In the Find what field of the Replace dialog, write \r\n, or \n depending on your line endings (default “\r\n” in Windows).
      3. In the Replace with field write ))\r\n or ))\n.
      4. Make sure Extended (\n, \r, \0 …) is selected as Search Mode (notepad++).
      5. Click Replace all.

     

    10. Locate the line with symbol cyfitter_cfg.

     

    11. Remove lines that are above this line (lines from the beginning of the file up to this line, excluding this line).

     

    12. Find the lines with a symbol name that needs to be placed in a particular address – in case of ClassB tests, the symbol name is SelfTest_PCAAAA and SelfTest_PC5555. Move these to the last line of the file.

     

    13. Copy all the contents of this file to the custom linker script file created in step 1. This needs to be placed after the line with text . = MAX(., 0x100); in the .text region of linker script.

    14. Clean and build the project.

     

    15. Repeat step 3 to generate the new symbol list file <ProjectName>.defsym.code.

     

    16. In the generated <ProjectName>.defsym.code file, find the symbol with the highest address lower than 0xAAAA.

    In this case, func12 has an address of A1E4. Hence the SelfTest_PCAAAA function must be placed before this function.

    17. Open the custom linker script and insert . = MAX(., 0xAAAA); before line containing symbol mentioned in step 16.

     

    18. Remove the line KEEP(*(*SelfTest_PCAAAA)) text and insert it after the line mentioned in step 17.

    19. Clean and build the project.

     

    20. Repeat step 3 to generate the new symbol list file <ProjectName>.defsym.code.

     

    21. Find the symbol with highest address lower than 0x15555.

     

    22. Open the custom linker script and insert . = MAX(., 0x15555); before line containing symbol mentioned in step 21.

     

    23. Remove the line KEEP(*(*SelfTest_PC5555)) text and insert it after the line mentioned in step 22.

     

    24. Clean and build the project and make sure SelfTest_PCAAAA and SelfTest_PC5555 are located at the appropriate address.