Tools & patches to build nRF5 SDK with LLVM/Clang toolchain
This repository contains some tools and patches so that the Nordic Semi nRF5 SDK can be build with Clang/LLVM toolchain.
It has been succesfully tested (real product) with nRF5 SDK v14.2, SDK v15.3, with SoftDevice S132 v5, v6 and v7 series.
It is used from LLVM 6.0 series and up to 8.0.0 for arm-none-eabi Cortex-M4 targets, i.e. with nRF52 SoCs. nRF51 has never been tested.
Thw whole toolchain, including the Clang compiler, the integrated assembler and
the LLVM linker ld.lld
is used to build nRF52 executable.
Your mileage may vary!
The software is provided "as is", without warranty of any kind. Please read the MIT license.
It is not affiliated in any way with Nordic Semiconductor, and obviously NOT supported by Nordic Semiconductor. Be sure not to report issues that might be introduced by the use of these tools to Nordic Semi.
The patches only tweak the files for the GCC toolchain, and try to be conservative, i.e. patched files should execute in the exact same way when GCC is used.
The patched SVC calls are only activated when Clang is actually used to build, while some other fixes are also enabled when GCC is used.
In any case, it is strongly advised to backup your original SDK files before applying these scripts. A source control system such as Git can help to check which and how files have been modified.
Please also note that while these scripts enable building nRF52-based applications, they may not be enough to build - all - applications. The author has used them to build a BLE 4.x peripheral application with S132 SoftDevice on a nRF52832 SoC. Patches are warmly welcomed!
- LLVM/Clang toolchain
- v7+ is recommended, v8 is the preferred version.
- Python 3.5+ to run the scripts.
patch
and EOL-converter tool such asdos2unix
- Shell and common unix tools
- nRF5 SDK v14 or greater
This tool patches some Nordic Semi header files to:
-
Declare SVCALL macro as a static inline function
-
Rewrite all SVCALLs to properly declare to the compiler which ARM registers are used with SVC calls.
python3 nrfsvc.py -h usage: nrfsvc.py [-h] [-u] -k {svc,wrap} [-d] dir nRF5 service call adapter for CLANG/LLVM toolchain positional arguments: dir top directory to seek for header files optional arguments: -h, --help show this help message and exit -u, --update update source file -k {svc,wrap}, --kind {svc,wrap} Action to perform: "svc": Patch CALLs, "wrap": Patch SVCALL macros -d, --debug enable debug mode
This script should be invoked twice:
- once to tweak the SVCALL macro definition for Clang (
wrap
) - once to actually patch all the header files that declare SVC calls (
svc
).
The script walks through the specified SDK directory to detect header files that need to be patched. It is not recommended to specify the top-level directory of the SDK distribution archive as the start directory, as the script would uselessly skim through the numerous examples files and third-party libraries.
A good start point for patching SVC calls is to use the top-level SoftDevice
directory, i.e. components/softdevice
.
To successfully use the patch command, you may need to first convert the
original source file to Unix EOL using dos2unix
file, apply the patch, then
optionally revert back to Windows format using unix2dos
utility. The patch
utility has trouble working with the Windows EOL. Better: do not use Windows.
This script wraps up the patch files to apply them w/o dealing with EOL issues.
The following patches need to be applied with the patch
command.
Note that Nordic Semi distributes its SDK as Windows file: they use CRLF line ending, and even source files may be defined as executable due to the use of barely appropriate ZIP container.
vmsr.patch
this patch is a generic patch for modern GCCs and Clang for CMSIS header file. It is not specific to this SDKisr_vector.patch
is used to declare theisr_vector
section as executable. ISR vector is an array of addresses, i.e pure data, which is used by the Cortex-M4 as a jump table to exception routines. It is stored within the.text
, i.e. executable code section. LLVMld.lld
does not accept mixed-style sections, i.e. executable and code within the same section declaration. It is right to do so, but this breaks most of the linker script designed for Cortex-M series. This patch declares the isr_vector jump table as executable as a workaround - the clean solution would be to rewrite all the LD linker scripts. Note that LLVMld.lld
may not safely detect this issue: depending on the content and order of all object files it is given to link as the final executable, various and hard-to-debug error messages may be raised, or even worse: the final executable may be invalid, LLVM LD failing to compute the LMA addressed for the.data
section. Failing to fixing the isr_vector definition may result in quite difficult issues to track and debug. YMMV.stack_ptr.h
fixes the retrieval of the current stack pointer value. Note that this patch lacks extensive testing.error_handler.patch
fixes an ASM routine used to call the application error handler call. The original code generates a pseudo assembly instruction such asldr r0,=#1234
, but the LLVM integrated assembler does not accept the=#
syntax as an immediate value. The instruction is replaced with two ARMmov
instructions.