The "Holy Bible" for embedded engineers
<arch>-<vendor>-<os>-<libc>
(e.g., arm-none-eabi-gcc
)Cross-compilation is the process of building software on one platform (host) to run on a different platform (target). This guide covers setting up cross-compilation toolchains for embedded systems, including toolchain selection, configuration, build system integration, and best practices for reliable cross-platform development.
Cross-compilation enables developers to:
Cross-compilation Architecture
┌─────────────────────────────────────────────────────────────┐
│ Host System (Development Machine) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ OS: Linux/macOS/Windows │ │
│ │ Arch: x86_64 │ │
│ │ Tools: Editor, IDE, Version Control │ │
│ └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Cross-compilation Toolchain │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Compiler: arm-none-eabi-gcc │ │
│ │ Assembler: arm-none-eabi-as │ │
│ │ Linker: arm-none-eabi-ld │ │
│ │ Debugger: arm-none-eabi-gdb │ │
│ │ Libraries: Target-specific (.a, .so files) │ │
│ └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Target System (Embedded Device) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ OS: Bare metal/RTOS/Linux │ │
│ │ Arch: ARM/RISC-V/MIPS │ │
│ │ Hardware: MCU/SoC/FPGA │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Toolchain Naming Convention
┌─────────────────────────────────────────────────────────────┐
│ Format: <arch>-<vendor>-<os>-<libc> │
│ │
│ Examples: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ arm-none-eabi-gcc │ │
│ │ ├── arch: arm (ARM architecture) │ │
│ │ ├── vendor: none (no specific vendor) │ │
│ │ ├── os: eabi (embedded application binary interface) │ │
│ │ └── libc: (no C library) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ riscv64-unknown-elf-gcc │ │
│ │ ├── arch: riscv64 (64-bit RISC-V) │ │
│ │ ├── vendor: unknown (unknown vendor) │ │
│ │ ├── os: elf (ELF format, bare metal) │ │
│ │ └── libc: (no C library) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ aarch64-linux-gnu-gcc │ │
│ │ ├── arch: aarch64 (64-bit ARM) │ │
│ │ ├── vendor: (no vendor specified) │ │
│ │ ├── os: linux (Linux operating system) │ │
│ │ └── libc: gnu (GNU C library) │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Cross-compilation Build Process
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Source Code │───▶│ Compiler │───▶│ Object │
│ (C/C++) │ │ (gcc/g++) │ │ Files │
└─────────────┘ └─────────────┘ └─────────────┘
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Assembly │ │ Assembler │ │ Object │
│ Files (.s) │───▶│ (as) │───▶│ Files │
└─────────────┘ └─────────────┘ └─────────────┘
│
▼
┌─────────────┐
│ Linker │
│ (ld) │
└─────────────┘
│
▼
┌─────────────┐
│ Executable │
│ (.elf) │
└─────────────┘
│
▼
┌─────────────┐
│ Binary │
│ (.bin) │
└─────────────┘
Toolchain Directory Layout
┌─────────────────────────────────────────────────────────────┐
│ /opt/arm-none-eabi/ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ bin/ (Executable tools) │ │
│ │ ├── arm-none-eabi-gcc │ │
│ │ ├── arm-none-eabi-g++ │ │
│ │ ├── arm-none-eabi-as │ │
│ │ ├── arm-none-eabi-ld │ │
│ │ ├── arm-none-eabi-objcopy │ │
│ │ ├── arm-none-eabi-objdump │ │
│ │ ├── arm-none-eabi-size │ │
│ │ ├── arm-none-eabi-strip │ │
│ │ ├── arm-none-eabi-nm │ │
│ │ ├── arm-none-eabi-readelf │ │
│ │ └── arm-none-eabi-gdb │ │
│ └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ lib/ (Libraries) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ gcc/arm-none-eabi/10.3-2021.10/ │ │
│ │ ├── libgcc.a │ │
│ │ ├── libgcc_s.so │ │
│ │ ├── crtbegin.o │ │
│ │ └── crtend.o │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ arm-none-eabi/ │ │
│ │ ├── libc.a │ │
│ │ ├── libm.a │ │
│ │ ├── libg.a │ │
│ │ └── libnosys.a │ │
│ └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ include/ (Header files) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ c++/10.3.1/ │ │
│ ├── arm-none-eabi/ │ │
│ └── ... │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
# Core compilation tools
arm-none-eabi-gcc # C/C++ compiler
arm-none-eabi-g++ # C++ compiler
arm-none-eabi-as # Assembler
arm-none-eabi-ld # Linker
arm-none-eabi-objcopy # Object file manipulation
arm-none-eabi-objdump # Object file inspection
arm-none-eabi-size # Memory usage analysis
arm-none-eabi-strip # Symbol stripping
arm-none-eabi-nm # Symbol listing
arm-none-eabi-readelf # ELF file analysis
# Additional tools
arm-none-eabi-gdb # Debugger
arm-none-eabi-ranlib # Archive index creation
arm-none-eabi-ar # Archive creation
arm-none-eabi-strings # String extraction
Toolchain Directory Layout:
/opt/arm-none-eabi/
├── bin/ # Executable tools
│ ├── arm-none-eabi-gcc
│ ├── arm-none-eabi-ld
│ └── ...
├── lib/ # Libraries
│ ├── gcc/arm-none-eabi/10.3-2021.10/
│ │ ├── libgcc.a
│ │ ├── libgcc_s.so
│ │ └── crtbegin.o
│ └── arm-none-eabi/
│ ├── libc.a
│ ├── libm.a
│ └── ...
├── include/ # Header files
│ ├── c++/10.3.1/
│ ├── arm-none-eabi/
│ └── ...
├── arm-none-eabi/ # Target-specific files
│ ├── include/
│ ├── lib/
│ └── ...
└── share/ # Documentation and examples
├── doc/
└── examples/
// Standard C library (newlib for bare metal)
#include <stdio.h> // Standard I/O
#include <stdlib.h> // Standard library
#include <string.h> // String functions
#include <math.h> // Math functions
#include <time.h> // Time functions
// Hardware-specific headers
#include <stm32f4xx.h> // STM32F4 specific
#include <stm32f4xx_hal.h> // STM32F4 HAL
#include <cmsis_os.h> // CMSIS-RTOS
// Custom hardware abstraction
#include "hw_gpio.h" // GPIO abstraction
#include "hw_uart.h" // UART abstraction
#include "hw_timer.h" // Timer abstraction
# ARM GNU Toolchain (GCC-based)
# Official ARM toolchain with excellent ARM support
wget https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.10/binrel/gcc-arm-10.3-2021.10-x86_64-arm-none-eabi.tar.xz
# Linaro Toolchain (Community maintained)
# Optimized for ARM with good performance
wget https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-eabi/gcc-linaro-7.5.0-2019.12-x86_64_arm-eabi.tar.xz
# Sourcery CodeBench (Commercial)
# Professional toolchain with advanced features
# Available from Mentor Graphics/Siemens
# RISC-V GNU Toolchain (Official)
# Complete RISC-V toolchain with GCC, binutils, and newlib
git clone https://github.com/riscv/riscv-gnu-toolchain.git
cd riscv-gnu-toolchain
./configure --prefix=/opt/riscv --enable-multilib
make
# SiFive Freedom Tools
# Optimized for SiFive RISC-V processors
wget https://static.dev.sifive.com/dev-tools/freedom-tools/v2020.12/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz
# Toolchain feature comparison
Toolchain Comparison Matrix:
┌─────────────────┬─────────────┬─────────────┬─────────────┬─────────────┐
│ Feature │ ARM GNU │ Linaro │ Sourcery │ RISC-V GNU │
├─────────────────┼─────────────┼─────────────┼─────────────┼─────────────┤
│ License │ GPL │ GPL │ Commercial │ GPL │
│ ARM Support │ Excellent │ Very Good │ Excellent │ N/A │
│ RISC-V Support│ N/A │ N/A │ N/A │ Excellent │
│ Performance │ Good │ Very Good │ Excellent │ Good │
│ Updates │ Regular │ Regular │ Regular │ Regular │
│ Support │ Community │ Community │ Commercial │ Community │
└─────────────────┴─────────────┴─────────────┴─────────────┴─────────────┘
# 1. Download toolchain
cd /tmp
wget https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.10/binrel/gcc-arm-10.3-2021.10-x86_64-arm-none-eabi.tar.xz
# 2. Extract to system directory
sudo tar -xf gcc-arm-10.3-2021.10-x86_64-arm-none-eabi.tar.xz -C /opt/
# 3. Set permissions
sudo chown -R root:root /opt/gcc-arm-10.3-2021.10-x86_64-arm-none-eabi/
# 4. Create symbolic link
sudo ln -sf /opt/gcc-arm-10.3-2021.10-x86_64-arm-none-eabi /opt/arm-none-eabi
# 5. Add to PATH
echo 'export PATH="/opt/arm-none-eabi/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# Ubuntu/Debian
sudo apt update
sudo apt install gcc-arm-none-eabi gdb-arm-none-eabi
# CentOS/RHEL/Fedora
sudo yum install arm-none-eabi-gcc arm-none-eabi-gdb
# or
sudo dnf install arm-none-eabi-gcc arm-none-eabi-gdb
# macOS (using Homebrew)
brew install arm-none-eabi-gcc
# Windows (using Chocolatey)
choco install gcc-arm-embedded
# Dockerfile for cross-compilation environment
FROM ubuntu:20.04
# Install dependencies
RUN apt-get update && apt-get install -y \
build-essential \
cmake \
git \
wget \
python3 \
python3-pip \
&& rm -rf /var/lib/apt/lists/*
# Install ARM toolchain
RUN wget -q https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.10/binrel/gcc-arm-10.3-2021.10-x86_64-arm-none-eabi.tar.xz \
&& tar -xf gcc-arm-10.3-2021.10-x86_64-arm-none-eabi.tar.xz -C /opt/ \
&& rm gcc-arm-10.3-2021.10-x86_64-arm-none-eabi.tar.xz \
&& ln -sf /opt/gcc-arm-10.3-2021.10-x86_64-arm-none-eabi /opt/arm-none-eabi
# Add toolchain to PATH
ENV PATH="/opt/arm-none-eabi/bin:${PATH}"
# Set working directory
WORKDIR /workspace
# Default command
CMD ["/bin/bash"]
# Verify toolchain installation
arm-none-eabi-gcc --version
arm-none-eabi-gdb --version
# Test basic compilation
cat > test.c << 'EOF'
#include <stdio.h>
int main() {
printf("Hello, ARM World!\n");
return 0;
}
EOF
# Compile test program
arm-none-eabi-gcc -o test.elf test.c
# Check file type
file test.elf
# Should show: test.elf: ELF 32-bit LSB executable, ARM, version 1
# Check target architecture
arm-none-eabi-objdump -f test.elf
# Should show ARM architecture information
# Cross-compilation Makefile
# Toolchain configuration
CROSS_COMPILE = arm-none-eabi-
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
SIZE = $(CROSS_COMPILE)size
# Target configuration
TARGET = stm32f4
CPU = cortex-m4
FPU = fpv4-sp-d16
FLOAT_ABI = hard
# Compiler flags
CFLAGS = -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FLOAT_ABI) \
-mthumb -mthumb-interwork \
-ffunction-sections -fdata-sections \
-fno-strict-aliasing -fno-builtin \
-Wall -Wextra -Werror \
-std=c99 -O2 -g
# Linker flags
LDFLAGS = -mcpu=$(CPU) -mfpu=$(FPU) -mfloat-abi=$(FLOAT_ABI) \
-mthumb -mthumb-interwork \
-T$(LINKER_SCRIPT) \
-Wl,--gc-sections \
-Wl,--print-memory-usage
# Source files
SRCS = main.c system.c gpio.c uart.c timer.c
OBJS = $(SRCS:.c=.o)
# Build targets
all: $(TARGET).elf $(TARGET).bin $(TARGET).hex
$(TARGET).elf: $(OBJS)
$(CC) $(OBJS) $(LDFLAGS) -o $@
$(TARGET).bin: $(TARGET).elf
$(OBJCOPY) -O binary $< $@
$(TARGET).hex: $(TARGET).elf
$(OBJCOPY) -O ihex $< $@
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJS) $(TARGET).elf $(TARGET).bin $(TARGET).hex
size: $(TARGET).elf
$(SIZE) $<
.PHONY: all clean size
# CMakeLists.txt for cross-compilation
cmake_minimum_required(VERSION 3.16)
project(STM32F4_Project C ASM)
# Set cross-compilation variables
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR ARM)
# Toolchain paths
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
set(CMAKE_OBJCOPY arm-none-eabi-objcopy)
set(CMAKE_SIZE arm-none-eabi-size)
# Compiler flags
set(CMAKE_C_FLAGS "-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -mthumb-interwork")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -fno-strict-aliasing")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -std=c99 -O2 -g")
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}")
# Linker flags
set(CMAKE_EXE_LINKER_FLAGS "-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -mthumb-interwork")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T${CMAKE_SOURCE_DIR}/stm32f4xx.ld")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -Wl,--print-memory-usage")
# Find source files
file(GLOB_RECURSE SOURCES "src/*.c" "src/*.s")
# Create executable
add_executable(${PROJECT_NAME}.elf ${SOURCES})
# Custom commands for binary generation
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
COMMAND ${CMAKE_OBJCOPY} -O ihex ${PROJECT_NAME}.elf ${PROJECT_NAME}.hex
COMMENT "Generating binary and hex files"
)
# Print size information
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
COMMAND ${CMAKE_SIZE} ${PROJECT_NAME}.elf
COMMENT "Memory usage:"
)
#!/bin/bash
# build.sh - Cross-compilation build script
set -e # Exit on any error
# Configuration
PROJECT_NAME="stm32f4_project"
BUILD_DIR="build"
TOOLCHAIN_PATH="/opt/arm-none-eabi/bin"
LINKER_SCRIPT="stm32f4xx.ld"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Function to print colored output
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Check toolchain availability
check_toolchain() {
print_status "Checking toolchain availability..."
if [ ! -d "$TOOLCHAIN_PATH" ]; then
print_error "Toolchain not found at $TOOLCHAIN_PATH"
exit 1
fi
# Add toolchain to PATH
export PATH="$TOOLCHAIN_PATH:$PATH"
# Verify tools
arm-none-eabi-gcc --version > /dev/null 2>&1 || {
print_error "arm-none-eabi-gcc not found or not working"
exit 1
}
print_status "Toolchain verified successfully"
}
# Clean build directory
clean_build() {
print_status "Cleaning build directory..."
rm -rf "$BUILD_DIR"
mkdir -p "$BUILD_DIR"
}
# Compile project
compile_project() {
print_status "Compiling project..."
cd "$BUILD_DIR"
# Compile C files
for src_file in ../src/*.c; do
if [ -f "$src_file" ]; then
obj_file=$(basename "$src_file" .c).o
print_status "Compiling $src_file -> $obj_file"
arm-none-eabi-gcc \
-mcpu=cortex-m4 \
-mfpu=fpv4-sp-d16 \
-mfloat-abi=hard \
-mthumb \
-ffunction-sections \
-fdata-sections \
-Wall \
-O2 \
-g \
-c "$src_file" \
-o "$obj_file"
fi
done
# Compile assembly files
for src_file in ../src/*.s; do
if [ -f "$src_file" ]; then
obj_file=$(basename "$src_file" .s).o
print_status "Compiling $src_file -> $obj_file"
arm-none-eabi-gcc \
-mcpu=cortex-m4 \
-mfpu=fpv4-sp-d16 \
-mfloat-abi=hard \
-mthumb \
-c "$src_file" \
-o "$obj_file"
fi
done
}
# Link project
link_project() {
print_status "Linking project..."
# Collect object files
obj_files=""
for obj_file in *.o; do
if [ -f "$obj_file" ]; then
obj_files="$obj_files $obj_file"
fi
done
if [ -z "$obj_files" ]; then
print_error "No object files found for linking"
exit 1
fi
# Link
arm-none-eabi-gcc \
-mcpu=cortex-m4 \
-mfpu=fpv4-sp-d16 \
-mfloat-abi=hard \
-mthumb \
-T"../$LINKER_SCRIPT" \
-Wl,--gc-sections \
-Wl,--print-memory-usage \
$obj_files \
-o "$PROJECT_NAME.elf"
print_status "Linking completed successfully"
}
# Generate binary files
generate_binaries() {
print_status "Generating binary files..."
# Generate binary file
arm-none-eabi-objcopy -O binary "$PROJECT_NAME.elf" "$PROJECT_NAME.bin"
# Generate hex file
arm-none-eabi-objcopy -O ihex "$PROJECT_NAME.elf" "$PROJECT_NAME.hex"
print_status "Binary files generated successfully"
}
# Show memory usage
show_memory_usage() {
print_status "Memory usage:"
arm-none-eabi-size "$PROJECT_NAME.elf"
}
# Main build process
main() {
print_status "Starting build process for $PROJECT_NAME"
check_toolchain
clean_build
compile_project
link_project
generate_binaries
show_memory_usage
print_status "Build completed successfully!"
print_status "Output files:"
ls -la *.elf *.bin *.hex
}
# Run main function
main "$@"
# Optimization levels
-O0 # No optimization (debug builds)
-O1 # Basic optimization
-O2 # More aggressive optimization
-O3 # Maximum optimization
-Os # Optimize for size
-Og # Optimize for debugging
# Architecture-specific flags
-mcpu=cortex-m4 # Target CPU
-mfpu=fpv4-sp-d16 # FPU type
-mfloat-abi=hard # Float ABI (hard/soft/softfp)
-mthumb # Use Thumb instruction set
-mthumb-interwork # Enable ARM/Thumb interworking
# Code generation flags
-ffunction-sections # Place functions in separate sections
-fdata-sections # Place data in separate sections
-fno-strict-aliasing # Disable strict aliasing
-fno-builtin # Disable built-in functions
-fomit-frame-pointer # Omit frame pointer
# Warning flags
-Wall # Enable all warnings
-Wextra # Enable extra warnings
-Werror # Treat warnings as errors
-Wpedantic # Strict ISO C compliance
/* STM32F4 Linker Script */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
CCMRAM (rwx): ORIGIN = 0x10000000, LENGTH = 64K
}
/* Entry point */
ENTRY(Reset_Handler)
/* Sections */
SECTIONS
{
/* Vector table and startup code */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
. = ALIGN(4);
} >FLASH
/* Text section (code) */
.text :
{
. = ALIGN(4);
*(.text)
*(.text*)
*(.rodata)
*(.rodata*)
. = ALIGN(4);
_etext = .;
} >FLASH
/* Data section (initialized variables) */
.data :
{
. = ALIGN(4);
_sdata = .;
*(.data)
*(.data*)
. = ALIGN(4);
_edata = .;
} >RAM AT> FLASH
/* BSS section (uninitialized variables) */
.bss :
{
. = ALIGN(4);
_sbss = .;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
} >RAM
/* Stack and heap */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + 0x1000; /* 4KB heap */
. = ALIGN(8);
PROVIDE ( _estack = . );
} >RAM
/* Remove debug information */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
}
// build_config.json - Build configuration
{
"project": {
"name": "STM32F4_Project",
"version": "1.0.0",
"description": "STM32F4 embedded project"
},
"toolchain": {
"name": "arm-none-eabi",
"version": "10.3-2021.10",
"path": "/opt/arm-none-eabi/bin"
},
"target": {
"architecture": "ARM",
"cpu": "cortex-m4",
"fpu": "fpv4-sp-d16",
"float_abi": "hard",
"instruction_set": "thumb"
},
"compiler": {
"optimization": "O2",
"debug_info": true,
"warnings": ["-Wall", "-Wextra"],
"flags": [
"-ffunction-sections",
"-fdata-sections",
"-fno-strict-aliasing"
]
},
"linker": {
"script": "stm32f4xx.ld",
"flags": [
"-Wl,--gc-sections",
"-Wl,--print-memory-usage"
]
},
"build": {
"output_dir": "build",
"clean_build": true,
"parallel_jobs": 4
}
}
# .gdbinit file for ARM debugging
set target-charset ASCII
set target-wide-charset UTF-32
# Set target
target remote localhost:3333
# Load symbols
symbol-file build/project.elf
# Set breakpoint at main
break main
# Configure GDB for embedded debugging
set confirm off
set pagination off
set output-radix 16
# Useful commands
define reset
monitor reset
continue
end
define flash
monitor program build/project.elf
monitor reset
continue
end
# openocd.cfg - OpenOCD configuration for STM32F4
source [find interface/stlink.cfg]
source [find target/stm32f4x.cfg]
# ST-Link configuration
adapter_khz 2000
# Target configuration
reset_config srst_only
# Flash configuration
program build/project.elf verify reset exit
# Debug configuration
gdb_port 3333
telnet_port 4444
tcl_port 6666
// test_framework.h - Testing framework for embedded systems
#ifndef TEST_FRAMEWORK_H
#define TEST_FRAMEWORK_H
#include <stdint.h>
#include <stdbool.h>
// Test result structure
typedef struct {
const char *test_name;
bool passed;
const char *message;
uint32_t execution_time_ms;
} test_result_t;
// Test function type
typedef bool (*test_function_t)(void);
// Test case structure
typedef struct {
const char *name;
test_function_t function;
bool enabled;
} test_case_t;
// Test suite structure
typedef struct {
const char *name;
test_case_t *tests;
uint32_t test_count;
uint32_t passed_count;
uint32_t failed_count;
} test_suite_t;
// Test framework functions
void test_framework_init(void);
void test_framework_run_suite(test_suite_t *suite);
void test_framework_run_all_suites(test_suite_t *suites[], uint32_t suite_count);
void test_framework_print_results(void);
// Assertion macros
#define TEST_ASSERT(condition) \
do { \
if (!(condition)) { \
return false; \
} \
} while(0)
#define TEST_ASSERT_EQUAL(expected, actual) \
TEST_ASSERT((expected) == (actual))
#define TEST_ASSERT_NOT_NULL(ptr) \
TEST_ASSERT((ptr) != NULL)
#endif // TEST_FRAMEWORK_H
# Problem: Toolchain not found
# Solution: Check PATH and create symlinks
# Check current PATH
echo $PATH
# Add toolchain to PATH permanently
echo 'export PATH="/opt/arm-none-eabi/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# Create symlinks in /usr/local/bin
sudo ln -sf /opt/arm-none-eabi/bin/arm-none-eabi-gcc /usr/local/bin/
sudo ln -sf /opt/arm-none-eabi/bin/arm-none-eabi-gdb /usr/local/bin/
# Problem: Missing libraries
# Solution: Check library paths and linking
# Check available libraries
find /opt/arm-none-eabi -name "*.a" | grep -E "(libc|libm|libgcc)"
# Add library search paths
arm-none-eabi-gcc -L/opt/arm-none-eabi/lib/gcc/arm-none-eabi/10.3.1/ \
-L/opt/arm-none-eabi/arm-none-eabi/lib/ \
source.c -o output.elf
# Check library dependencies
arm-none-eabi-objdump -p output.elf | grep NEEDED
# Problem: Architecture mismatch
# Solution: Check compiler flags
# Verify target architecture
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -E -dM - < /dev/null | grep -i arm
# Check FPU support
arm-none-eabi-gcc -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard \
-E -dM - < /dev/null | grep -i fpu
# Problem: Missing startup code
# Solution: Include startup files
# Compile with startup file
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb \
startup_stm32f4xx.s system_stm32f4xx.c main.c \
-Tstm32f4xx.ld -o project.elf
Cross-compilation setup is essential for efficient embedded system development. A well-configured cross-compilation environment provides:
The key to successful cross-compilation setup lies in:
By following these principles and implementing the techniques discussed in this guide, developers can create robust, efficient, and maintainable cross-compilation environments for their embedded projects.