YREA-SLS/SLS_C/build_system/compilers/arm_gcc.py

207 lines
5.8 KiB
Python

"""
ARM GCC compiler implementation for embedded targets.
This module implements the Compiler interface for ARM GCC toolchain,
used for cross-compiling to ARM Cortex-M processors (e.g., RP2040).
"""
from pathlib import Path
from typing import List, Optional
from .gcc import GCCCompiler
class ARMGCCCompiler(GCCCompiler):
"""
ARM GCC compiler implementation for embedded targets.
Uses the arm-none-eabi-gcc toolchain for bare-metal ARM development.
Extends GCCCompiler with ARM Cortex-M specific flags.
"""
def __init__(
self,
executable: str = "arm-none-eabi-gcc",
cpu: str = "cortex-m0plus"
):
"""
Initialize ARM GCC compiler.
Args:
executable: ARM GCC executable (default: "arm-none-eabi-gcc")
cpu: Target CPU architecture (default: "cortex-m0plus" for RP2040)
"""
super().__init__(executable=executable, is_clang=False)
self.cpu = cpu
self.fpu = None
self.float_abi = None
self.additional_arch_flags = []
def set_cpu(self, cpu: str):
"""
Set target CPU architecture.
Args:
cpu: CPU name (e.g., "cortex-m0plus", "cortex-m4", "cortex-m7")
Returns:
Self for method chaining
"""
self.cpu = cpu
return self
def set_fpu(self, fpu: str, float_abi: str = "hard"):
"""
Set FPU configuration (for Cortex-M4F, M7, etc.).
Args:
fpu: FPU type (e.g., "fpv4-sp-d16", "fpv5-d16")
float_abi: Float ABI ("soft", "softfp", or "hard")
Returns:
Self for method chaining
"""
self.fpu = fpu
self.float_abi = float_abi
return self
def add_arch_flags(self, flags: List[str]):
"""
Add additional architecture-specific flags.
Args:
flags: List of flags to add
Returns:
Self for method chaining
"""
self.additional_arch_flags.extend(flags)
return self
def compile(
self,
source: Path,
output: Path,
*,
includes: Optional[List[Path]] = None,
defines: Optional[dict] = None,
flags: Optional[List[str]] = None,
generate_deps: bool = True,
is_test: bool = False
) -> Path:
"""
Compile using ARM GCC with embedded-specific flags.
Adds ARM Cortex-M architecture flags before calling parent compile.
"""
flags = flags or []
# ARM architecture flags (must come early)
arch_flags = [
f"-mcpu={self.cpu}",
"-mthumb", # Use Thumb instruction set
]
# FPU flags if configured
if self.fpu:
arch_flags.append(f"-mfpu={self.fpu}")
arch_flags.append(f"-mfloat-abi={self.float_abi}")
# Additional architecture flags
arch_flags.extend(self.additional_arch_flags)
# Prepend architecture flags (they need to come before other flags)
flags = arch_flags + flags
return super().compile(
source,
output,
includes=includes,
defines=defines,
flags=flags,
generate_deps=generate_deps,
is_test=is_test
)
def link(
self,
objects: List[Path],
output: Path,
*,
libraries: Optional[List[str]] = None,
library_paths: Optional[List[Path]] = None,
flags: Optional[List[str]] = None,
linker_script: Optional[Path] = None,
specs: Optional[str] = None
) -> Path:
"""
Link using ARM GCC with embedded-specific flags.
Args:
objects: Object files to link
output: Output executable path
libraries: Libraries to link
library_paths: Library search paths
flags: Additional linker flags
linker_script: Path to linker script (.ld file)
specs: Specs file (e.g., "nosys.specs", "nano.specs")
Returns:
Path to linked executable
"""
flags = flags or []
# ARM architecture flags (need to be passed to linker too)
arch_flags = [
f"-mcpu={self.cpu}",
"-mthumb",
]
# FPU flags
if self.fpu:
arch_flags.append(f"-mfpu={self.fpu}")
arch_flags.append(f"-mfloat-abi={self.float_abi}")
# Additional architecture flags
arch_flags.extend(self.additional_arch_flags)
# Linker script
if linker_script:
arch_flags.append(f"-T{linker_script}")
# Specs file (for selecting C library variant)
if specs:
arch_flags.append(f"--specs={specs}")
# Prepend architecture flags
flags = arch_flags + flags
return super().link(
objects,
output,
libraries=libraries,
library_paths=library_paths,
flags=flags
)
def get_executable_extension(self) -> str:
"""
Get executable extension for ARM embedded.
Returns .elf for embedded binaries (can be converted to .bin, .hex, .uf2)
"""
return ".elf"
class RP2040Compiler(ARMGCCCompiler):
"""
Specialized ARM GCC compiler for RP2040 (Raspberry Pi Pico).
Pre-configured for Cortex-M0+ with RP2040-specific settings.
"""
def __init__(self, executable: str = "arm-none-eabi-gcc"):
"""Initialize compiler for RP2040."""
super().__init__(executable=executable, cpu="cortex-m0plus")