The hal_nsing is a set of standard firmware libraries and ARM CMSIS configurations for NSING N32 MCUs. The HAL is organized following the directory structure detailed below.
The directory is composed of three parts:
- SoC specific libraries.
- ZephyrRTOS module directory (
zephyr). - This README file.
On top of those sit the files that describe the repository itself: LICENSE, LICENSES/,
REUSE.toml, .gitattributes and scripts/sync_series.py.
.
├── n32g45x/ one directory per series, named after the lowercase SoC series
│ ├── README.md upstream origin, SDK version, what was and was not mirrored
│ ├── CMSIS/device/ <series>.h, <series>_conf.h, system_<series>.{c,h}
│ └── <series>_std_periph_driver/{inc,src}/
├── LICENSES/BSD-3-Clause.txt license text, in the REUSE layout
├── REUSE.toml per-path licensing; vendored sources are declared, never edited
├── scripts/sync_series.py mirror or verify one series against its upstream SDK
├── zephyr/module.yml Zephyr module definition
├── .gitattributes pins LF endings for every tracked file
├── .gitignore
└── LICENSE
Each N32 firmware library is organized in the following structure:
<series>/
├── README.md
├── CMSIS/device/ <series>.h, <series>_conf.h, system_<series>.{c,h}
└── <series>_std_periph_driver/
├── inc/ headers
└── src/ sources
Upstream's own directory names are kept, so a refresh is a directory copy rather than a
remapping. The only thing missing from upstream's CMSIS/device/ is startup/ and
<series>_flash.ld: CMSIS core headers come from Zephyr's own cmsis module, the vector
table is built from devicetree, and linker scripts live in the Zephyr tree under soc/.
zephyr/module.yml declares cmake-ext and kconfig-ext, so the CMake and Kconfig glue
that wires this module into the build lives in the Zephyr tree at modules/hal_nsing/, the
same arrangement as hal_gigadevice and hal_wch.
That glue derives every path from CONFIG_SOC_SERIES:
set(nsing_soc_dir ${ZEPHYR_HAL_NSING_MODULE_DIR}/${CONFIG_SOC_SERIES})which is why a series directory must be named exactly after the lowercase SoC series.
| Directory | Core | Upstream SDK |
|---|---|---|
n32g45x/ |
Cortex-M4 | NSING-Community/N32G45x-SDK |
n32h78x/ |
Cortex-M7/M4 | NSING-Community/N32H7xx-SDK |
Further series are added as sibling directories, named after the lowercase CONFIG_SOC_SERIES —
see Adding a series.
- Land the newest firmware library version. The vendor's SDK package is the source of truth here, not the git copy it is fetched from: Nations publishes no git repository, so the SDK copies on GitHub are community mirrors. The package a series was taken from is recorded in the series' README — check a mirror against it before trusting it.
- The vendored sources are never edited. They are a byte-for-byte mirror of the upstream
SDK, and editing them would break the invariant
scripts/sync_series.py --checkrelies on. Their licensing is declared inREUSE.tomlinstead of written into the files. See License. - Changes are submitted with Linux LF endings.
.gitattributespins* text=auto eol=lfso the working tree is byte-identical to the committed blobs on every platform, andsync_series.pynormalises on write whatever the SDK ships. There is no need to rundos2unixby hand. - Directory names keep upstream's spelling. That includes the capital
CMSIS. This deliberately departs from the lowercase conventionhal_gigadevicefollows: keeping upstream's own names is what makes refreshing a series a directory copy rather than a remapping. Exceptions should be discussed at review phase. - A series directory is named after the lowercase
CONFIG_SOC_SERIES. This one is a hard rule — the build glue derives every path from${ZEPHYR_HAL_NSING_MODULE_DIR}/${CONFIG_SOC_SERIES}. python scripts/sync_series.py --checkreports no drift for every series.reuse lintreports no missing licenses. A new series needs its own entry inREUSE.toml; the globs there are written per series and are not covered automatically.
Clone its SDK and mirror it:
git clone https://github.com/NSING-Community/N32G43x-SDK python scripts/sync_series.py n32g43x N32G43x-SDK/firmware
The script copies only the files a HAL needs, writes them with LF endings, and reports everything it deliberately left behind. Re-run it with
--checkat any time to see whether the tree has drifted from upstream. Pass--device-prefixwhen the SDK's device prefix differs from the series name.Add
n32g43x/README.md, usingn32g45x/README.mdas the template, recording the upstream repository, the SDK package version and any exclusions specific to that series.Add the series to Supported series above.
Add the series to
REUSE.toml, under the vendored-sources annotation.Extend
modules/hal_nsing/CMakeLists.txtandKconfigin the Zephyr tree with the new series' peripheral sources, then commit withgit commit -s.Run
reuse lintand make sure it still reports 0 missing licenses.
- A precompiled blob sits inside a header directory. Upstream ships
n32xx_tsc_alg_api.libnext to the other headers in.../std_periph_driver/inc/for N32G45x, N32G4FR and N32WB452. Any glob or whole-directory copy of that directory would quietly commit 3.2 MB of precompiled code.sync_series.pydrops every*.libalong with the header of the same stem, which is what removes both files. - Extra libraries are optional.
<series>_algo_lib,<series>_usbfs_driver/_usbfsd_driver/_usbhs_driver,<series>_periph_liband<series>_ble_driverexist for some series only. Add them as separate directories when they are actually wired into a build, not speculatively. Note that<series>_algo_lib/lib/holds five prebuilt libraries of its own (aes,algo_common,des,hash,rngfor N32G45x), which are out of scope until ablobs:entry exists for them.
No precompiled libraries are committed to this repository. Zephyr's
binary blobs policy requires
blobs to be declared in the blobs: section of zephyr/module.yml and fetched with
west blobs fetch into zephyr/blobs/, which is git-ignored; hal_stm32 is a working
example of that layout. Nothing in the module currently references a blob, so no blob is
declared. A series that needs the TSC touch-sensing algorithm will have to add a blobs: entry
with its URL, SHA256 and license path.
BSD 3-Clause; see the LICENSE file. The repository is compliant with
REUSE 3.3 — REUSE.toml and LICENSES/ carry the
machine-readable form, and reuse lint is expected to stay clean.
The driver sources under each series directory are vendored verbatim from the upstream SDK and
keep their own headers, Copyright (c) 2019, 2025 Nations Technologies Inc. They are declared
as BSD-3-Clause in REUSE.toml rather than edited, because editing them would break the
byte-for-byte mirror that scripts/sync_series.py maintains.
Note that upstream describes its own terms as "BSD-style" rather than naming a SPDX identifier, and the header text differs in drafting from the standard BSD-3-Clause — the binary-redistribution clause is not enumerated, and the disclaimer carries an extra "AND NON-INFRINGEMENT". The exact text is the header of each file. Worth putting to Nations if this module is ever challenged on it.