Using GCC with Tiva in CCSv6

From Texas Instruments Wiki
Jump to: navigation, search

Introduction

Code Composer Studio v6 includes a Linaro distribution of the ARM GNU compiler, so programmers have the option of using this GCC Compiler instead of the TI compiler to build their projects. This page describes how to select and use the GCC compiler to build projects for TivaC devices.

Installation

The ARM GCC compiler can be installed in one of two ways:

  1. When installing CCSv6, you have the option to select the GCC ARM Compiler as shown in the screenshot below. If enabled, it will get installed as part of the CCS installation.
    Tiva installer2.png

  2. Alternately, if you do not select the above option during installation, you can always install it at a later time.
    • Go to menu View->CCS App Center
    • Next to Code Composer Studio Add-ons, click on See more
    • Select ARM GCC and click the “Install Software” button to start the installation.
      Tiva installer4.png

Once installed, the ARM GCC compiler tools will be in this directory within the CCS installation: \ccsv6\tools\compiler\gcc-arm-none-eabi-xxx (where xxx denotes the version number).

Creating a new ARM GCC project for TivaC

Below are the steps to create a new CCS project for TivaC that uses ARM GCC tools to build the executable.

  1. Start CCSv6 and create a new project by going to menu Project->New CCS Project…
  2. Fill in the Target and Project name fields
  3. For Compiler version, select GNU v4.7.4 (Linaro)
  4. Under Project templates and examples, select Empty Project or Empty Project (with main.c)
    New tiva gcc proj.png

  5. Click Finish
    • This will create a new project that will be visible in the Project Explorer view. The project should contain a .lds file and a startup C source file (appropriate for the target selected). The .lds file is the linker script that contains the memory layout and section allocation. This file is the equivalent of the TI linker command file (.cmd). The startup_ccs_gcc.c file contains the startup code for use with CCS and GNU tools.
  6. Add any additional source files to the project.
  7. Edit the linker script (.lds file) to rename the interrupt vector section from .intvecs to .isr_vector
    • Note: This is a bug in CCS 6.0.0 that it is named incorrectly. This step is only required if using 6.0.0. This is fixed in 6.0.1 and higher.
  8. Right-click on the project, go to Properties
  9. Go to Debug, select Flash Settings and check the box for "Reset target during program load to flash memory”
    • Note: This setting is required for GCC projects to load and run correctly. In CCS 6.1.0 and higher, this setting is enabled by default

      Blinky6.png

  10. Set any additional compiler and linker options similar to how it is done with TI compiler.
  11. Build project and load to target


Note: Avoid the use of C I/O (printf statements) in the code as they will not work with the default set up.


Changing an existing project created for TI compiler to ARM GCC

There are a few manual steps involved in converting a TivaWare project created for TI compiler to one that uses the GCC compiler. Shown below are the steps to convert a couple of examples from TivaWare.

Example 1 : Blinky project

This example shows the steps necessary to convert a blinky example from TivaWare to work with GCC. This example is for the EK-TM4C1294XL TivaC Connected Launchpad.
Note: The blinky example does not use any of the TivaWare libraries such as driverlib or usblib so the conversion process is quite simple. Projects that include one or more of those libraries may require additional conversion steps.

  1. Import the "blinky" example from TivaWare for the board you are working with (in this example, from \examples\boards\ek-tm4c1294xl\blinky) into CCSv6 (using either TI Resource Explorer or CCS menu Project->Import CCS Projects...)
  2. Right-click on the project in Project Explorer view and go to Properties
  3. Change Compiler version to GNU v4.7.4 (Linaro)
  4. Change Linker command file to tm4c1294ncpdt.lds. Be sure to pick the one that corresponds to the device shown in the Variant field

    Blinky3.png

  5. Click OK
  6. This will pop up the following dialog. Click OK.

    Blinky2.png

    • A new build configuration named Debug__GNU will be created. Note that the project now contains the GCC linker script (.lds) and a startup_ccs_gcc.c file appropriate for the device variant.
  7. Exclude the TI linker command file (blinky_ccs.cmd) and CCS startup file (startup_ccs.c) from build if this is not already done automatically. Right-click on the files and select "Exclude from build"
  8. Edit the linker script (.lds file) to rename the interrupt vector section from .intvecs to .isr_vector
    • Note: This is a bug in CCS 6.0.0 that it is named incorrectly. This step is only required if using 6.0.0. This is fixed in 6.0.1 and higher.
  9. Right-click on the project, go to Properties
  10. Go to Build->GNU Compiler->Directories, and add include paths to the TivaWare root folder and any others that are required for the project.
    In this example, ${SW_ROOT} and ${SW_ROOT}/examples/boards/ek-tm4c1294xl are added
    Tip: Use the original TI build configuration as reference to see which paths are required. You can switch to the TI build configuration by right-clicking on the project name and going to Build Configurations->Set Active->Debug. Then check the compiler include paths under Build->Compiler->Include Options

    Blinky4.png

  11. Go to Build->GNU Linker->Libraries. Under Libraries, add "gcc" and "nosys"

    Blinky5.png
    Note: For GCC linker, when specifying libraries, only specify the part of the library name after the lib prefix and with no extension.

  12. Go to Debug, select Flash Settings and check the box for "Reset target during program load to flash memory”
    • Note: This setting is required for GCC projects to load and run correctly. In CCS 6.1.0 and higher, this setting is enabled by default

      Blinky6.png

  13. Build, load and run the code


Example 2 : uart_echo project

This example shows the steps necessary to convert the uart_echo example from TivaWare to work with GCC. This example is for the EK-TM4C1294XL TivaC Connected Launchpad.
Note: This example uses driverlib and also requires some additional modifications compared to the blinky example.

  1. Import the "uart_echo" example from TivaWare for the board you are working with (in this example, from \examples\boards\ek-tm4c1294xl\uart_echo) into CCSv6 (using either TI Resource Explorer or CCS menu Project->Import CCS Projects...)
  2. Follow steps 2 through 12 as listed above for the blinky example
  3. Go to Build->GNU Compiler->Symbols, and add symbol definitions required for the project
    In this example, TARGET_IS_TM4C129_RA0 is added.
    Tip: Use the TI build configuration as reference to see which symbols are defined. You can switch to the TI build configuration by right-clicking on the project name and going to Build Configurations->Set Active->Debug. Then check the compiler symbol definitions under Build->Compiler->Advanced Options->Predefined Symbols

    Uart echo1.png

  4. Go to Build->GNU Linker->Libraries. Under Libraries, add "driver" and under Library search path, add the path to the library. Specify the library name without the lib prefix and the .a extension.
    Tip: Use the TI build configuration as reference to see which libraries are required. You can switch to the TI build configuration by right-clicking on the project name and going to Build Configurations->Set Active->Debug. Then check the libraries under Build->Linker->File Search Path

    Uart echo2.png

  5. Edit the GCC startup file to add UART interrupt handler to vector table

    Startupfile.png

  6. Build, load and run the code

Working with GCC libraries

If your code makes calls to runtime functions in the GCC libraries, it is important that the appropriate library is selected by the tools. There are different versions of the library available based on things like processor family, ARM/Thumb, Soft FP, Hard FP etc.

To ensure that the correct library is chosen, the linker should be passed the -march option (along with some other additional options). In the case of Tiva C devices, it is -march=armv7e-m.

To check which runtime library (multilib) is selected for which set of options, you can run the following command on a command prompt:
C:\ti\ccsv6\tools\compiler\gcc-arm-none-eabi-4_7-2013q3\bin>arm-none-eabi-gcc.exe --print-multi-lib

The otuput will look something like this:

.;
thumb;@mthumb
fpu;@mfloat-abi=hard
armv6-m;@mthumb@march=armv6s-m
armv7-m;@mthumb@march=armv7-m
armv7e-m;@mthumb@march=armv7e-m
armv7-ar/thumb;@mthumb@march=armv7
armv7e-m/softfp;@mthumb@march=armv7e-m@mfloat-abi=softfp@mfpu=fpv4-sp-d16
armv7e-m/fpu;@mthumb@march=armv7e-m@mfloat-abi=hard@mfpu=fpv4-sp-d16
armv7-ar/thumb/softfp;@mthumb@march=armv7@mfloat-abi=softfp@mfpu=vfpv3-d16
armv7-ar/thumb/fpu;@mthumb@march=armv7@mfloat-abi=hard@mfpu=vfpv3-d16

Based on this you can see, for example, that the libs from armv7e-m/softfp will be selected if the build options are:
-mthumb -march=armv7e-m -mfloat-abi=softfp -mfpu=fpv4-sp-d16

To set this in CCS, right-click on the Project, go to Properties->GNU Compiler->Runtime, and set the -march option.

Option.png

NOTE: This option needs to be added manually only for versions 6.0.x. In CCS 6.1.0 and higher, this option is already added by default for all new GCC projects created in CCS.
Note also that this option may be added by default only for Tiva devices and not the older Stellaris devices, so if you are using a Stellaris device, please double-check if this option is added by default and if it is not, you would need to add it manually.

Working with older Stellaris devices

If you select a lm3s* or lm4f* device in CCS, the ResetISR() routine in the startup_ccs_gcc.c file may have an issue, resulting in incorrect initialization of global variables.

The ResetISR() should look like this, so if you are using a lm3s or lm4f startup file, please correct the ResetISR function to copy the data section from __data_load__ rather than __etext, as shown below:

void
ResetISR(void)
{
    uint32_t *pui32Src, *pui32Dest;

    //
    // Copy the data segment initializers from flash to SRAM.
    //
    pui32Src = &__data_load__;
    for(pui32Dest = &__data_start__; pui32Dest < &__data_end__; )
    {
        *pui32Dest++ = *pui32Src++;
    }

Note, this issue does not exist for TM4C* devices.

Known issue when using CCS 6.1/Linaro GCC 4.8.4

Using CCS 6.1.0 and building with Linaro GCC v4.8.4 compiler (which comes with CCS 6.1.0), when a debug session is started, debugger comes up with the device running (not halted at main), and when the target is paused it is halted at FaultISR.

The reason for this appears to be a change in the GCC tools which is in turn affecting what the linker entry point is set to. In GCC 4.7.4, a symbol named "start" is defined (in addition to _start and _mainCRTStartup), which can be verified by looking at the link map file. The linker entry point is set to this symbol. In GCC 4.8.4, symbol "start" is not defined (although _start and _mainCRTStartup are) and the linker entry point defaults to the starting address of the .text section. This is expected behavior according to the information in the GCC Linker manual.

There are a couple of ways to resolve this:

  • Specify the entry point under -e option for the linker (under Project Properties->Build->GNU Linker->Basic). This can be set to _start or ResetISR
  • Add the command ENTRY(ResetISR) to the linker script


TI-RTOS projects for GCC

Large bin file produced by TI-RTOS example projects

The TI-RTOS package for TivaC includes example projects that build with GCC compiler. A post-build step could be added to those projects that invoke the tiobj2bin utility (included with CCSv6) to convert executables (.out) to binary (.bin) format. Note that the paths in the tiobj2bin command would need to be adjusted to invoke the tools from the TI compiler toolset.

The binary file produced by the conversion is very large (>512MB), which in turn, may cause issues with the LMFlash Programmer, if that programmer is used to program the binary.

The reason for the large file size is that there is a loadable section .vtable in RAM and GCC is zero-filling the memory between flash and RAM in order to generate the bin file. A workaround is to mark the ".vtable" section as NOLOAD in the linker script, and rebuild the project. This section stores the RAM vector table and will get initialized during startup, so marking the section as NOLOAD is safe to do.

In the linker script (.ld file) change

.vtable (_vtable_base_address) : AT (_vtable_base_address) {
KEEP (*(.vtable))
} > REGION_DATA

to

.vtable (_vtable_base_address) (NOLOAD) : {
    KEEP (*(.vtable))
} > REGION_DATA

This should produce a much smaller binary file.

GCC examples do not startup when run standalone without debugger connected

The TI-RTOS GCC example projects may not run correctly on power up when run standalone without CCS connected. For example:

  • Download the examples from the CCS debugger and they function correctly
  • Terminate the CCS debug session, and they continue to function
  • Press the reset button on the EK-TM4C123GXL launchpad or power cycle the board, and the programs fail to start

This is expected behavior if the example is built with semi-hosting enabled. Semi-hosting is implemented using breakpoints in Cortex-M3/M4 targets. If the debugger is connected, it knows how to process the semi-hosting breakpoint and continue execution. However, if the debugger is disconnected and the board is reset, the application will not be able to continue execution at the breakpoint.

The solution is to replace the librdimon (semi-hosting) library with libnosys library and remove the useModule for "ti.sysbios.rts.gnu.SemiHostSupport" module from the example's *.cfg file. See this forum post for a screenshot of where to find these settings.

Once these changes are made, the program should run correctly on power up.