You can download a functional toolchain from developer.arm.com and install it manually after removing your existing gcc-arm-none-eabi package.

Go to that website, click the "Download" button and get: gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2. Save it in your home directory.

Make sure you've uninstalled the old Ubuntu packages.

sudo apt remove binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi

Untar the new package in your home directory:

tar -xjvf gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2

Add the new toolchain to your path:

export PATH=$PATH:/home/(your user)/gcc-arm-none-eabi-7-2018-q2-update/bin/

At this point you should have a working ARM compiler and toolchain. (For the Unix newbies: if you close the terminal and open a new one, you'll have to re-run the export PATH statement so the compiler will get picked up again.)

To check if the compiler is installed:

gcc --version
Answer from user3486184 on Stack Exchange
🌐
Arm Developer
developer.arm.com › documentation › 102621 › latest
Install Arm Compiler for Linux
The Arm Developer website includes documentation, tutorials, support resources, and downloads for products and technologies.
🌐
Arm Learning
learn.arm.com › install-guides › acfl
Arm Compiler for Linux: Install Guide
Each command sequence includes accepting the license agreement to automate the installation and installing Environment Modules. sudo -E apt-get -y install environment-modules python3 libc6-dev tar -xvf arm-compiler-for-linux_24.10.1_Ubuntu-22.04_aarch64.tar cd ./arm-compiler-for-linux_24.10.1_Ubuntu-22.04 sudo ./arm-compiler-for-linux_24.10.1_Ubuntu-22.04.sh --accept
Top answer
1 of 2
22

As I told in comments, try

apt-get install gcc-arm-linux-gnueabi 

or

apt-get install gcc-4.7-arm-linux-gnueabi

I also strongly recommend being able to compile an ordinary C program for your Linux system (i.e. learn the basics of gcc, make ... commands and how to use some editor like emacs or gedit ...) and the cross compiler you want also depends upon the system running on your SA1100 hardware board. Don't forget to pass -Wall to any GCC compilation. You probably want to be able to debug your program (pass -g to GCC at compilation, and use the gdb debugger). When your program is running well, compile it with -O2 to ask GCC to optimize its machine code.

Learn to use GNU make -e.g. to write Makefile-s- by reading its documentation and use the arm-linux-gnueabi-gcc as the cross-compiler program. (You might want to use remake to debug your Makefile-s when make does not help enough)

You can get the list of files installed with a package with e.g. dpkg -L gcc-arm-linux-gnueabi

A cross compiled program executable for ARM very probably needs a Linux kernel with some libc (or link it statically) at least on the ARM motherboard, and you need some way to transmit the binary program from the Linux desktop to the ARM hardware.

2 of 2
5

Add the ppa: https://launchpad.net/gcc-arm-embedded The source codes for both are same. Currently supports Ubuntu 10.04/12.04/13.04/13.10/14.04 32 and 64 bit.

Detailed explanations to Launchpad PPA can be found at https://help.launchpad.net/Packaging/. That website explains how a PPA is set up and how to add existing PPA and install software from it.

Here are quick steps to install toolchain from this PPA on Ubuntu before 14.04. Open a terminal and type :

  1. sudo add-apt-repository ppa:terry.guo/gcc-arm-embedded
  2. sudo apt-get update
  3. sudo apt-get install gcc-arm-none-eabi

To remove installed toolchain, just do :

sudo apt-get remove gcc-arm-none-eabi

To update the toolchain, just repeat step 2 and 3.

🌐
Lindevs
lindevs.com › install-arm-gnu-toolchain-on-ubuntu
Install Arm GNU Toolchain on Ubuntu 22.04 | Lindevs
November 14, 2023 - The Arm GNU toolchain (previously ... GCC (GNU Compiler Collection), Binutils, GDB, and other. It is used for embedded systems software development. This toolchain targets the 32-bit ARM Cortex-A, ARM Cortex-M, and ARN Cortex-R processor families. This tutorial shows how to install Arm GNU toolchain on Ubuntu ...
Top answer
1 of 1
2

Building a project takes following steps:

1. Install the gcc-arm-none-eabi toolchain

It can be found on Launchpad or at ARM. Download the Linux installation tarball, extract, and add the /bin folder in the extracted folder to the PATH environment variable.

2. Install supporting packages

Install CMake, build-essential libusb-1.0.0-dev cmake, stlink, and OpenOCD from your distribution.

3. Create a CMake file for the toolchain

For the STM32F412 MPU I put mine below:

include(CMakeForceCompiler)

##############################
# gnu-none-ebai install dir
# /usr/lib/arm-none-eabi
#
# stm32f412
# Features:
#    - fpu
#    - dsp
#
# instructionset for libs:
# /usr/lib/arm-none-eabi/lib/armv7e-m/<soft/fpu>/{FPU precision}


set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
set(OBJCOPY arm-none-eabi-objcopy)

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(COMMON_FLAGS "-march=armv7e-m -mtune=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb -mthumb-interwork -Og -ffunction-sections -fdata-sections -fno-move-loop-invariants")
set(LINKER_SCRIPTS "-T ${CMAKE_SOURCE_DIR}/ldscripts/STM32F412RG.ld -T ${CMAKE_SOURCE_DIR}/ldscripts/sections.ld -T ${CMAKE_SOURCE_DIR}/ldscripts/libs.ld")

set(CMAKE_CXX_FLAGS "${COMMON_FLAGS} -std=c++11" CACHE INTERNAL "")
set(CMAKE_C_FLAGS "${COMMON_FLAGS} -std=gnu99" CACHE INTERNAL "")
set(CMAKE_ASM_FLAGS "${COMMON_FLAGS}" CACHE INTERNAL "")
set(CMAKE_EXE_LINKER_FLAGS  "-W -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -nostartfiles --specs=nosys.specs -ffunction-sections -fdata-sections -fno-move-loop-invariants ${LINKER_SCRIPTS}" CACHE INTERNAL "")


#
include_directories(BEFORE SYSTEM "/usr/lib/arm-none-eabi/include/")

list(APPEND TOOLCHAIN_EXTRA_LIBDIR
    "/usr/lib/arm-none-eabi/lib/armv7e-m/fpu"
)

link_directories(${TOOLCHAIN_EXTRA_LIBDIR})

set(CMAKE_C_COMPILER_WORKS 1)
set(CMAKE_CXX_COMPILER_WORKS 1)

4. Add/copy the linker scripts

4.1 sections.ld

/*
 * Default linker script for Cortex-M (it includes specifics for STM32F[34]xx).
 *
 * To make use of the multi-region initialisations, define
 * OS_INCLUDE_STARTUP_INIT_MULTIPLE_RAM_SECTIONS for the _startup.c file.
 */

/*
 * The '__stack' definition is required by crt0, do not remove it.
 */
__stack = ORIGIN(RAM) + LENGTH(RAM);

_estack = __stack;     /* STM specific definition */


/*
 * Default stack sizes.
 * These are used by the startup in order to allocate stacks
 * for the different modes.
 */

__Main_Stack_Size = 1024 ;

PROVIDE ( _Main_Stack_Size = __Main_Stack_Size ) ;

__Main_Stack_Limit = __stack  - __Main_Stack_Size ;

/* "PROVIDE" allows to easily override these values from an
 * object file or the command line. */
PROVIDE ( _Main_Stack_Limit = __Main_Stack_Limit ) ;

/*
 * There will be a link error if there is not this amount of
 * RAM free at the end.
 */
_Minimum_Stack_Size = 256 ;

/*
 * Default heap definitions.
 * The heap start immediately after the last statically allocated
 * .sbss/.noinit section, and extends up to the main stack limit.
 */
PROVIDE ( _Heap_Begin = _end_noinit ) ;
PROVIDE ( _Heap_Limit = __stack - __Main_Stack_Size ) ;

/*
 * The entry point is informative, for debuggers and simulators,
 * since the Cortex-M vector points to it anyway.
 */
ENTRY(_start)


/* Sections Definitions */

SECTIONS
{
    /*
     * For Cortex-M devices, the beginning of the startup code is stored in
     * the .isr_vector section, which goes to FLASH.
     */
    .isr_vector : ALIGN(4)
    {
        FILL(0xFF)

        __vectors_start = ABSOLUTE(.) ;
        __vectors_start__ = ABSOLUTE(.) ; /* STM specific definition */
        KEEP(*(.isr_vector))         /* Interrupt vectors */

        KEEP(*(.cfmconfig))            /* Freescale configuration words */

        /*
         * This section is here for convenience, to store the
         * startup code at the beginning of the flash area, hoping that
         * this will increase the readability of the listing.
         */
        *(.after_vectors .after_vectors.*)    /* Startup code and ISR */
        /* by StJ */
        __vectors_end = ABSOLUTE(.) ;
    } >FLASH

    .inits : ALIGN(4)
    {
        /*
         * Memory regions initialisation arrays.
         *
         * Thee are two kinds of arrays for each RAM region, one for
         * data and one for bss. Each is iterated at startup and the
         * region initialisation is performed.
         *
         * The data array includes:
         * - from (LOADADDR())
         * - region_begin (ADDR())
         * - region_end (ADDR()+SIZEOF())
         *
         * The bss array includes:
         * - region_begin (ADDR())
         * - region_end (ADDR()+SIZEOF())
         *
         * WARNING: It is mandatory that the regions are word aligned,
         * since the initialisation code works only on words.
         */

        __data_regions_array_start = .;

        LONG(LOADADDR(.data));
        LONG(ADDR(.data));
        LONG(ADDR(.data)+SIZEOF(.data));

        LONG(LOADADDR(.data_CCMRAM));
        LONG(ADDR(.data_CCMRAM));
        LONG(ADDR(.data_CCMRAM)+SIZEOF(.data_CCMRAM));

        __data_regions_array_end = .;

        __bss_regions_array_start = .;

        LONG(ADDR(.bss));
        LONG(ADDR(.bss)+SIZEOF(.bss));

        LONG(ADDR(.bss_CCMRAM));
        LONG(ADDR(.bss_CCMRAM)+SIZEOF(.bss_CCMRAM));

        __bss_regions_array_end = .;

        /* End of memory regions initialisation arrays. */

        /*
         * These are the old initialisation sections, intended to contain
         * naked code, with the prologue/epilogue added by crti.o/crtn.o
         * when linking with startup files. The standalone startup code
         * currently does not run these, better use the init arrays below.
         */
        KEEP(*(.init))
        KEEP(*(.fini))

        . = ALIGN(4);

        /*
         * The preinit code, i.e. an array of pointers to initialisation
         * functions to be performed before constructors.
         */
        PROVIDE_HIDDEN (__preinit_array_start = .);

        /*
         * Used to run the SystemInit() before anything else.
         */
        KEEP(*(.preinit_array_sysinit .preinit_array_sysinit.*))

        /*
         * Used for other platform inits.
         */
        KEEP(*(.preinit_array_platform .preinit_array_platform.*))

        /*
         * The application inits. If you need to enforce some order in
         * execution, create new sections, as before.
         */
        KEEP(*(.preinit_array .preinit_array.*))

        PROVIDE_HIDDEN (__preinit_array_end = .);

        . = ALIGN(4);

        /*
         * The init code, i.e. an array of pointers to static constructors.
         */
        PROVIDE_HIDDEN (__init_array_start = .);
        KEEP(*(SORT(.init_array.*)))
        KEEP(*(.init_array))
        PROVIDE_HIDDEN (__init_array_end = .);

        . = ALIGN(4);

        /*
         * The fini code, i.e. an array of pointers to static destructors.
         */
        PROVIDE_HIDDEN (__fini_array_start = .);
        KEEP(*(SORT(.fini_array.*)))
        KEEP(*(.fini_array))
        PROVIDE_HIDDEN (__fini_array_end = .);

    } >FLASH

    /*
     * For some STRx devices, the beginning of the startup code
     * is stored in the .flashtext section, which goes to FLASH.
     */
    .flashtext : ALIGN(4)
    {
        *(.flashtext .flashtext.*)    /* Startup code */
    } >FLASH


    /*
     * The program code is stored in the .text section,
     * which goes to FLASH.
     */
    .text : ALIGN(4)
    {
        *(.text .text.*)            /* All remaining code */

         /* read-only data (constants) */
        *(.rodata .rodata.* .constdata .constdata.*)

        *(vtable)                    /* C++ virtual tables */

        KEEP(*(.eh_frame*))

        /*
         * Stub sections generated by the linker, to glue together
         * ARM and Thumb code. .glue_7 is used for ARM code calling
         * Thumb code, and .glue_7t is used for Thumb code calling
         * ARM code. Apparently always generated by the linker, for some
         * architectures, so better leave them here.
         */
        *(.glue_7)
        *(.glue_7t)

    } >FLASH

    /* ARM magic sections */
    .ARM.extab : ALIGN(4)
       {
       *(.ARM.extab* .gnu.linkonce.armextab.*)
       } > FLASH

    . = ALIGN(4);
       __exidx_start = .;
       .ARM.exidx : ALIGN(4)
       {
       *(.ARM.exidx* .gnu.linkonce.armexidx.*)
       } > FLASH
       __exidx_end = .;

    . = ALIGN(4);
    _etext = .;
    __etext = .;

    /* MEMORY_ARRAY */
    /*
    .ROarraySection :
    {
         *(.ROarraySection .ROarraySection.*)
    } >MEMORY_ARRAY
    */

    /*
     * The secondary initialised data section.
     */
    .data_CCMRAM : ALIGN(4)
    {
       FILL(0xFF)
       *(.data.CCMRAM .data.CCMRAM.*)
       . = ALIGN(4) ;
    } > CCMRAM AT>FLASH

    /*
     * This address is used by the startup code to
     * initialise the .data section.
     */
    _sidata = LOADADDR(.data);

    /*
     * The initialised data section.
     *
     * The program executes knowing that the data is in the RAM
     * but the loader puts the initial values in the FLASH (inidata).
     * It is one task of the startup to copy the initial values from
     * FLASH to RAM.
     */
    .data : ALIGN(4)
    {
        FILL(0xFF)
        /* This is used by the startup code to initialise the .data section */
        _sdata = . ;            /* STM specific definition */
        __data_start__ = . ;
        *(.data_begin .data_begin.*)

        *(.data .data.*)

        *(.data_end .data_end.*)
        . = ALIGN(4);

        /* This is used by the startup code to initialise the .data section */
        _edata = . ;            /* STM specific definition */
        __data_end__ = . ;

    } >RAM AT>FLASH

    /*
     * The uninitialised data sections. NOLOAD is used to avoid
     * the "section `.bss' type changed to PROGBITS" warning
     */

    /* The secondary uninitialised data section. */
    .bss_CCMRAM (NOLOAD) : ALIGN(4)
    {
        *(.bss.CCMRAM .bss.CCMRAM.*)
    } > CCMRAM

    /* The primary uninitialised data section. */
    .bss (NOLOAD) : ALIGN(4)
    {
        __bss_start__ = .;         /* Standard newlib definition */
        _sbss = .;              /* STM specific definition */
        *(.bss_begin .bss_begin.*)

        *(.bss .bss.*)
        *(COMMON)

        *(.bss_end .bss_end.*)
        . = ALIGN(4);
        __bss_end__ = .;        /* Standard newlib definition */
        _ebss = . ;             /* STM specific definition */
    } >RAM

    .noinit_CCMRAM (NOLOAD) : ALIGN(4)
    {
        *(.noinit.CCMRAM .noinit.CCMRAM.*)
    } > CCMRAM

    .noinit (NOLOAD) : ALIGN(4)
    {
        _noinit = .;

        *(.noinit .noinit.*)

         . = ALIGN(4) ;
        _end_noinit = .;
    } > RAM

    /* Mandatory to be word aligned, _sbrk assumes this */
    PROVIDE ( end = _end_noinit ); /* was _ebss */
    PROVIDE ( _end = _end_noinit );
    PROVIDE ( __end = _end_noinit );
    PROVIDE ( __end__ = _end_noinit );

    /*
     * Used for validation only, do not allocate anything here!
     *
     * This is just to check that there is enough RAM left for the Main
     * stack. It should generate an error if it's full.
     */
    ._check_stack : ALIGN(4)
    {
        . = . + _Minimum_Stack_Size ;
    } >RAM

    /*
     * The FLASH Bank1.
     * The C or assembly source must explicitly place the code
     * or data there using the "section" attribute.
     */
    .b1text : ALIGN(4)
    {
        *(.b1text)                   /* Remaining code */
        *(.b1rodata)                 /* Read-only data (constants) */
        *(.b1rodata.*)
    } >FLASHB1

    /*
     * The EXTMEM.
     * The C or assembly source must explicitly place the code or data there
     * using the "section" attribute.
     */

    /* EXTMEM Bank0 */
    .eb0text : ALIGN(4)
    {
        *(.eb0text)                   /* Remaining code */
        *(.eb0rodata)                 /* Read-only data (constants) */
        *(.eb0rodata.*)
    } >EXTMEMB0

    /* EXTMEM Bank1 */
    .eb1text : ALIGN(4)
    {
        *(.eb1text)                   /* Remaining code */
        *(.eb1rodata)                 /* Read-only data (constants) */
        *(.eb1rodata.*)
    } >EXTMEMB1

    /* EXTMEM Bank2 */
    .eb2text : ALIGN(4)
    {
        *(.eb2text)                   /* Remaining code */
        *(.eb2rodata)                 /* Read-only data (constants) */
        *(.eb2rodata.*)
    } >EXTMEMB2

    /* EXTMEM Bank0 */
    .eb3text : ALIGN(4)
    {
        *(.eb3text)                   /* Remaining code */
        *(.eb3rodata)                 /* Read-only data (constants) */
        *(.eb3rodata.*)
    } >EXTMEMB3


    /* After that there are only debugging sections. */

    /* This can remove the debugging information from the standard libraries */
    /*
    DISCARD :
    {
     libc.a ( * )
     libm.a ( * )
     libgcc.a ( * )
     }
     */

    /* Stabs debugging sections.  */
    .stab          0 : { *(.stab) }
    .stabstr       0 : { *(.stabstr) }
    .stab.excl     0 : { *(.stab.excl) }
    .stab.exclstr  0 : { *(.stab.exclstr) }
    .stab.index    0 : { *(.stab.index) }
    .stab.indexstr 0 : { *(.stab.indexstr) }
    .comment       0 : { *(.comment) }
    /*
     * DWARF debug sections.
     * Symbols in the DWARF debugging sections are relative to the beginning
     * of the section so we begin them at 0.
     */
    /* DWARF 1 */
    .debug          0 : { *(.debug) }
    .line           0 : { *(.line) }
    /* GNU DWARF 1 extensions */
    .debug_srcinfo  0 : { *(.debug_srcinfo) }
    .debug_sfnames  0 : { *(.debug_sfnames) }
    /* DWARF 1.1 and DWARF 2 */
    .debug_aranges  0 : { *(.debug_aranges) }
    .debug_pubnames 0 : { *(.debug_pubnames) }
    /* DWARF 2 */
    .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
    .debug_abbrev   0 : { *(.debug_abbrev) }
    .debug_line     0 : { *(.debug_line) }
    .debug_frame    0 : { *(.debug_frame) }
    .debug_str      0 : { *(.debug_str) }
    .debug_loc      0 : { *(.debug_loc) }
    .debug_macinfo  0 : { *(.debug_macinfo) }
    /* SGI/MIPS DWARF 2 extensions */
    .debug_weaknames 0 : { *(.debug_weaknames) }
    .debug_funcnames 0 : { *(.debug_funcnames) }
    .debug_typenames 0 : { *(.debug_typenames) }
    .debug_varnames  0 : { *(.debug_varnames) }
}

/* Some adds */
__stack_end__ = _estack;
__RAM_segment_end__ = __stack ;
__vectors_load_start__ = __vectors_start;
__vectors_load_end__ = __vectors_end;
_start = main;

4.2 lib.ld

/*
 * Placeholder to list other libraries required by the application.

GROUP(
)

 */

4.3 STM32F412RG.ld

/*
 * Memory Spaces Definitions.
 *
 * Need modifying for a specific board.
 *   FLASH.ORIGIN: starting address of flash
 *   FLASH.LENGTH: length of flash
 *   RAM.ORIGIN: starting address of RAM bank 0
 *   RAM.LENGTH: length of RAM bank 0
 *
 * The values below can be addressed in further linker scripts
 * using functions like 'ORIGIN(RAM)' or 'LENGTH(RAM)'.
 */

MEMORY
{
  RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K
  CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 0K
  FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
  FLASHB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB0 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB2 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB3 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  MEMORY_ARRAY (xrw)  : ORIGIN = 0x20002000, LENGTH = 32
}

/*
 * For external ram use something like:

   RAM (xrw) : ORIGIN = 0x64000000, LENGTH = 2048K

 */

5. Instruction

  1. Create your CMake project - this example is taken from a bootloader

    cmake_minimum_required(VERSION 3.10)
    set(BL "BOOTLOADER")
    set(${BL}_VERSION_MAJOR 1)
    set(${BL}_VERSION_MINOR 4)
    set(${BL}_VERSION_REVISION 1)
    set(${BL}_SOVERSION 1)
    list(APPEND ${BL}_DEFINES
        USE_HAL_DRIVER
        STM32F412Rx
    )
    set(LINKER_FLAGS_BL "-Xlinker -Map=bl.map -Ttext 0x08020000")
    list(APPEND ${BL}_inc
        ${CMAKE_CURRENT_SOURCE_DIR}/inc/
        ${CMAKE_CURRENT_SOURCE_DIR}/drivers/CMSIS/Include
        ${CMAKE_CURRENT_SOURCE_DIR}/drivers/CMSIS/Device/ST/STM32F4xx/Include
        ${CMAKE_CURRENT_SOURCE_DIR}/drivers/STM32F4xx_HAL_Driver/Inc
        ${CMAKE_CURRENT_SOURCE_DIR}/drivers/STM32F4xx_HAL_Driver/Inc/Legacy
        ${CMAKE_CURRENT_SOURCE_DIR}/middlewares/ST/STM32_USB_Device_Library/Core/Inc
        ${CMAKE_CURRENT_SOURCE_DIR}/middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc
        ${CMAKE_CURRENT_SOURCE_DIR}/application/rtfw/Inc
        ${CMAKE_CURRENT_SOURCE_DIR}/../shared/inc
        ${CMAKE_CURRENT_SOURCE_DIR}/../3rdParty/include
      ${CMAKE_BINARY_DIR}/generated/
    )
    list(APPEND ${BL}_sources
        ${CMAKE_CURRENT_SOURCE_DIR}/../shared/src/stm32_startup.s
        ${CMAKE_CURRENT_SOURCE_DIR}/src/system_stm32f4xx.c
        ${CMAKE_CURRENT_SOURCE_DIR}/drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c
        ${CMAKE_CURRENT_SOURCE_DIR}/drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c
        ${CMAKE_CURRENT_SOURCE_DIR}/drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c
        ${CMAKE_CURRENT_SOURCE_DIR}/drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c
        ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
    )
    list(APPEND ${BL}_libDirs
    )
    list(APPEND ${BL}_libs
    )
    include_directories(${${BL}_inc})
    link_directories(${${BL}_libDirs})
    add_executable({${BL}_sources}
        ${TOOLCHAIN_EXTRA_OBJECTS}
    )
    target_compile_definitions(${BL} PRIVATE ${${BL}_DEFINES})
    target_link_libraries(${BL} PRIVATE ${${BL}_libs})
    set_target_properties(${BL} PROPERTIES
        LINK_FLAGS "${LINKER_FLAGS_BL}"
        OUTPUT_NAME "${BL}_${GIT_COMMIT_TAG}_${GIT_COMMIT_HASH}"
        VERSION "${${BL}_VERSION_MAJOR}.${${BL}_VERSION_MINOR}.${${BL}_VERSION_REVISION}"
        SOVERSION "${${BL}_SOVERSION}"
        SUFFIX ".elf"
    )
    
  2. Create bin/files form the ELF file via object copy

  3. Connect your programmer (p.e. ST-LINK)

  4. Open OpenOCD with a configuration like this

    echo "use the st link v2 cfg"
    source [find interface/stlink-v2.cfg]
    
    transport select hla_swd
    
    echo "set target to stm32f4x"
    
    source [find target/stm32f4x.cfg]
    
    reset_config srst_only
    
    $_TARGETNAME configure -event gdb-attach {
            echo "Debugger attaching: halting execution"
            reset halt
            gdb_breakpoint_override hard
    }
    
    $_TARGETNAME configure -event gdb-detach {
            echo "Debugger detaching: resuming execution"
            resume
    }
    
  5. Happy bug hunt

🌐
Learning About Electronics
learningaboutelectronics.com › Articles › How-to-install-an-ARM-cross-compilation-toolchain-ubuntu-linux.php
How to Install an ARM Cross-Compilation ToolChain on a Ubuntu Linux Operating System
Click the arm-linux-gnueabihf option. Clicking this option leads you to the following page shown below. This software should now be downloaded to your host computer. Now extract the contents of this file to the same directory. This is important because we're going to have to link to this extracted ...
Find elsewhere
🌐
Acmesystems
acmesystems.it › arm9_toolchain
Install the ARM cross compiler toolchain on your Linux PC
sudo apt update sudo apt install libc6-armel-cross libc6-dev-armel-cross binutils-arm-linux-gnueabi libncurses5-dev build-essential bison flex libssl-dev bc ... Now you are ready to cross-compile on your PC all the source available for the Acme ...
🌐
SoC
s-o-c.org › how-to-install-arm-gcc-compiler
How to Install ARM GCC Compiler - SoC
September 11, 2023 - For Linux distributions like Ubuntu, Debian, Fedora, etc. you can install the ARM GCC compiler package directly using the default package manager. Here are the steps: Open the terminal application on your Linux OS. Update your system’s package index by running: sudo apt update (for Debian/Ubuntu) ...
🌐
Arm Developer
developer.arm.com › documentation › 102621 › 0100 › Install
Documentation – Arm Developer
August 29, 2017 - This tutorial describes how to download, install, setup your environment, and get started with Arm Compiler for Linux.
🌐
Arm Community
community.arm.com › developer › ip-products › processors › f › cortex-m-forum › 8993 › installing-arm-gcc-toolchain-on-ubuntu
Challenge Validation
October 3, 2019 - Have a question? If you can, please take a moment to also see if there is a question that you are able to answer
🌐
Marksolters
marksolters.com › programming › 2016 › 06 › 22 › arm-toolchain-16-04.html
ARM GCC Toolchain in Ubuntu 16.04
June 22, 2016 - First, make sure to uninstall whatever version you may or may not already have: ... The PPA we want in this case is from the GCC ARM Embedded Maintainer’s team. sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa sudo apt-get update sudo apt-get install gcc-arm-embedded · For Ubuntu machines ...
Top answer
1 of 4
74

Install gcc-arm-linux-gnueabi and binutils-arm-linux-gnueabi packages, and then just use arm-linux-gnueabi-gcc instead of gcc for compilation.

You need to be careful on what flavour of linux and binutils you have on your target system. The newest stuff is hardfloat, in this case you would do:

sudo apt-get install gcc-arm-linux-gnueabihf

This brings in the complete cross-compile environment, including binutils.

For using this GCC in the build process write:

CC=arm-linux-gnueabihf-gcc make
2 of 4
23

64-bit ARM

For 64-bit ARM, the toolchain prefix is aarch64 and usage is:

sudo apt install gcc-aarch64-linux-gnu
aarch64-linux-gnu-gcc -o main.out main.c

You can try it out on this C hello world with QEMU:

main.c

#include <stdio.h>

int main(void) {
    puts("hello");
}

and then:

sudo apt install qemu-user
qemu-aarch64 main.out

will output:

hello

Then a few fun things you can do to quickly see that ARM is actually running under the hood:

  • GDB step debug it: https://stackoverflow.com/questions/20590155/how-to-single-step-arm-assembly-in-gdb-on-qemu/51310791#51310791
  • log the executed ARM instructions with: qemu-aarch64 -d in_asm,out_asm main.out https://stackoverflow.com/questions/13005303/how-does-native-android-code-written-for-arm-run-on-x86/44505097#44505097

Tested in Ubuntu 19.10.

For reliability in serious applications, the disk image provider must also provide a compatible cross compiler

Although you can install a cross compiler with apt conveniently, I must warn you that this is not necessarily reliable unless explicitly supported by the image provider.

If you pick the cross compiler wrongly, the following may happen:

  • the dynamic linker is at the wrong path: https://stackoverflow.com/questions/31929092/trying-to-run-a-cross-compiled-executable-on-target-device-fails-with-no-such-f/49993116#49993116
  • binary incompatibility with the glibc and any other libraries you link against: https://stackoverflow.com/questions/11107263/how-compatible-are-different-versions-of-glibc

Raspberry PI cross compilation

For RPI in particular, the provided cross compilers are available at: https://github.com/raspberrypi/tools and can be used as explained at: https://raspberrypi.stackexchange.com/questions/64273/installing-raspberry-pi-cross-compiler/83215#83215

git clone https://github.com/raspberrypi/tools
export PATH="$(pwd)/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin:${PATH}"
printf '#include <stdio.h>\nint main() { puts("hello world"); }\n' > hello_world.c
printf '#include <iostream>\nint main() { std::cout << "hello world" << std::endl; }\n' > hello_world.cpp
arm-linux-gnueabihf-gcc -std=c99 -o hello_world_c hello_world.c
arm-linux-gnueabihf-g++ -std=c++11 -o hello_world_cpp hello_world.cpp

Ubuntu cross compilation

If you want to cross compile for Ubuntu arm64, I have never been able to find a clear reference on which cross compilers support which distro version: What are the officially supported cross compilers for Ubuntu server alternative architectures like ARM?

Buildroot

My favorite alternative is to build your own image with Buildroot: https://stackoverflow.com/questions/47557262/how-to-download-the-torvalds-linux-kernel-master-recompile-it-and-boot-it-wi/49349237#49349237

This builds everything from source, including the toolchain and the image, and ensures that everything is compatible.

🌐
Arm Developer
developer.arm.com › Tools and Software › Arm Compiler for Linux
Arm Compiler for Linux Product Support
The document version is 26.01.1 ...rtranHPCLinuxCode ... ... Arm Compiler for L... ... sudo dnf install arm-performance-libraries SUSE Linux Enterprise (SLES) 15 SP7 or 16.0 ......
🌐
Arm Learning
learn.arm.com › install-guides › gcc › cross
Cross-compiler: Install Guide
Use the apt command to install the cross-compilers for 32-bit and 64-bit Arm Linux targets. sudo apt update sudo apt install gcc-arm-linux-gnueabihf -y sudo apt install gcc-aarch64-linux-gnu -y · The GCC version installed is tied to your Ubuntu ...
🌐
Jensd's I/O buffer
jensd.be › 800 › linux › cross-compiling-for-arm-with-ubuntu-16-04-lts
Cross compiling for ARM with Ubuntu 16.04 LTS | Jensd's I/O buffer
These include the standard tools needed for compiling: jensd@ubu:~$ sudo apt-get install gcc make gcc-arm-linux-gnueabi binutils-arm-linux-gnueabi Reading package lists... Done ... Do you want to continue?