From 633e30f278c0d19edbffd84d94cb4f4bba94352f Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Mon, 1 Dec 2025 17:08:42 -0700 Subject: [PATCH 1/4] WIP of BLE header bindgen --- stm32-bindings-gen/inc/app_conf.h | 44 +++ stm32-bindings-gen/inc/ble-wba.h | 91 +++++ stm32-bindings-gen/inc/wpan-wba.h | 14 + stm32-bindings-gen/res/src/bindings/mod.rs | 9 +- stm32-bindings-gen/res/src/lib.rs | 3 +- stm32-bindings-gen/src/lib.rs | 400 ++++++++++++++++----- 6 files changed, 470 insertions(+), 91 deletions(-) create mode 100644 stm32-bindings-gen/inc/app_conf.h create mode 100644 stm32-bindings-gen/inc/ble-wba.h diff --git a/stm32-bindings-gen/inc/app_conf.h b/stm32-bindings-gen/inc/app_conf.h new file mode 100644 index 0000000..4f01ee3 --- /dev/null +++ b/stm32-bindings-gen/inc/app_conf.h @@ -0,0 +1,44 @@ +/* Stub configuration header used during bindings generation. */ + +#ifndef STM32_BINDINGS_GEN_APP_CONF_H +#define STM32_BINDINGS_GEN_APP_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Provide minimal definitions so that ST middleware headers compile under bindgen. */ + +#ifndef LOG_LEVEL_INFO +#define LOG_LEVEL_INFO (0) +#endif + +#ifndef LOG_INFO_APP +#define LOG_INFO_APP(...) +#endif + +#ifndef CFG_LOG_SUPPORTED +#define CFG_LOG_SUPPORTED (0U) +#endif + +#ifndef PWR_LDO_SUPPLY +#define PWR_LDO_SUPPLY (0U) +#endif + +#ifndef RADIO_INTR_NUM +#define RADIO_INTR_NUM (0U) +#endif + +#ifndef RADIO_INTR_PRIO_HIGH +#define RADIO_INTR_PRIO_HIGH (0U) +#endif + +#ifndef RADIO_INTR_PRIO_LOW +#define RADIO_INTR_PRIO_LOW (0U) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* STM32_BINDINGS_GEN_APP_CONF_H */ \ No newline at end of file diff --git a/stm32-bindings-gen/inc/ble-wba.h b/stm32-bindings-gen/inc/ble-wba.h new file mode 100644 index 0000000..2117ddf --- /dev/null +++ b/stm32-bindings-gen/inc/ble-wba.h @@ -0,0 +1,91 @@ +#ifndef BLE_WBA_BINDINGS_H_ +#define BLE_WBA_BINDINGS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include "cmsis_compiler.h" + +/* Toolchain abstraction utilities */ + + +/* Link Layer command interface */ +#include "bsp.h" +#include "common_types.h" +#include "dtm.h" +#include "event_manager.h" +#include "evnt_schdlr_gnrc_if.h" +#include "hci.h" +#include "ll_error.h" +#include "ll_intf.h" +#include "ll_intf_cmn.h" +#include "mac_host_intf.h" +#include "mem_intf.h" +#include "os_wrapper.h" +#include "platform.h" +#include "power_table.h" +#include "pta.h" +#include "ral.h" +#include "rfd_dev_config.h" + + +/* Core BLE stack */ +#include "blestack.h" +#include "ble_bufsize.h" +#include "ble_codec.h" +#include "ble_const.h" +#include "ble_core.h" +#include "ble_defs.h" +#include "ble_legacy.h" +#include "ble_std.h" +#include "bleplat.h" + +/* Auto-generated ACI command definitions */ +#include "auto/ble_events.h" +#include "auto/ble_gap_aci.h" +#include "auto/ble_gatt_aci.h" +#include "auto/ble_hal_aci.h" +#include "auto/ble_hci_le.h" +#include "auto/ble_l2cap_aci.h" +#include "auto/ble_raw_api.h" +#include "auto/ble_types.h" +#include "auto/ble_vs_codes.h" + +/* BLE Audio stack */ +#include "ble_audio_stack.h" +#include "ble_audio_plat.h" +#include "audio_types.h" +#include "bap_bufsize.h" +#include "bap_types.h" +#include "cap.h" +#include "cap_types.h" +#include "ccp.h" +#include "ccp_types.h" +#include "csip.h" +#include "csip_types.h" +#include "ltv_utils.h" +#include "mcp.h" +#include "mcp_types.h" +#include "micp.h" +#include "micp_types.h" +#include "vcp.h" +#include "vcp_types.h" + +/* Codec manager interfaces */ +#include "codec_if.h" +#include "codec_mngr.h" + +/* LC3 codec interfaces */ +#include "LC3.h" +#include "LC3_decoder.h" +#include "LC3_encoder.h" + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* BLE_WBA_BINDINGS_H_ */ \ No newline at end of file diff --git a/stm32-bindings-gen/inc/wpan-wba.h b/stm32-bindings-gen/inc/wpan-wba.h index 994fdd4..cd104db 100644 --- a/stm32-bindings-gen/inc/wpan-wba.h +++ b/stm32-bindings-gen/inc/wpan-wba.h @@ -1,4 +1,18 @@ #include "st_mac_802_15_4_sap.h" +#include "st_mac_802_15_4_types.h" +#include "st_mac_802_15_4_core.h" +#include "st_mac_802_15_4_sys.h" +#include "st_mac_802_15_4_config.h" +#include "st_mac_802_15_4_core_config.h" +#include "st_mac_802_15_4_sys_svc.h" +#include "st_mac_802_15_4_svc.h" +#include "st_mac_802_15_4_ext_svc.h" +#include "st_mac_802_15_4_raw_svc.h" +#include "st_mac_802_15_4_dbg_svc.h" +#include "st_mac_buffer_management.h" +#include "st_mac_queue.h" +#include "stm_queue.h" +#include "utilities_common.h" /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef APP_CONF_H diff --git a/stm32-bindings-gen/res/src/bindings/mod.rs b/stm32-bindings-gen/res/src/bindings/mod.rs index 6443cd1..c13d2b4 100644 --- a/stm32-bindings-gen/res/src/bindings/mod.rs +++ b/stm32-bindings-gen/res/src/bindings/mod.rs @@ -1 +1,8 @@ -mod wpan_wba; +pub mod ble_stack; +pub mod mac_802_15_4; + +pub use self::mac_802_15_4 as mac; +pub use self::mac_802_15_4 as wpan_wba; + +pub use self::ble_stack as ble; +pub use self::ble_stack as ble_wba; diff --git a/stm32-bindings-gen/res/src/lib.rs b/stm32-bindings-gen/res/src/lib.rs index 1f12fe9..7593be9 100644 --- a/stm32-bindings-gen/res/src/lib.rs +++ b/stm32-bindings-gen/res/src/lib.rs @@ -4,4 +4,5 @@ #![allow(non_camel_case_types)] #![doc(html_no_source)] -mod bindings; +pub mod bindings; +pub use bindings::*; diff --git a/stm32-bindings-gen/src/lib.rs b/stm32-bindings-gen/src/lib.rs index 5f7fe07..8b260a1 100644 --- a/stm32-bindings-gen/src/lib.rs +++ b/stm32-bindings-gen/src/lib.rs @@ -1,7 +1,109 @@ use bindgen::callbacks::{ItemInfo, ItemKind, ParseCallbacks}; -use std::io::Write; -use std::{fs, path::PathBuf}; -use tempfile::NamedTempFile; +use std::path::{Path, PathBuf}; +use std::process::Command; +use std::{fs, io}; + +const STD_TO_CORE_REPLACEMENTS: &[(&str, &str)] = &[ + ("::std::mem::", "::core::mem::"), + ("::std::os::raw::", "::core::ffi::"), + ("::std::option::", "::core::option::"), + ("::std::ptr::", "::core::ptr::"), + (":: std :: mem ::", ":: core :: mem ::"), + (":: std :: os :: raw ::", ":: core :: ffi ::"), + (":: std :: option ::", ":: core :: option ::"), + (":: std :: ptr ::", ":: core :: ptr ::"), +]; + +#[derive(Debug, Clone, Copy)] +struct BindingSpec { + module: &'static str, + header: &'static str, + include_dirs: &'static [&'static str], + clang_args: &'static [&'static str], + allowlist: &'static [&'static str], + aliases: &'static [&'static str], + library_artifacts: &'static [LibraryArtifact], +} + +#[derive(Debug, Clone, Copy)] +struct LibraryArtifact { + source: &'static str, + destination: &'static str, +} + +const BINDING_SPECS: &[BindingSpec] = &[ + BindingSpec { + module: "mac_802_15_4", + header: "stm32-bindings-gen/inc/wpan-wba.h", + include_dirs: &[ + "Middlewares/ST/STM32_WPAN/mac_802_15_4/core/inc", + "Middlewares/ST/STM32_WPAN/mac_802_15_4/mac_utilities/inc", + "Middlewares/ST/STM32_WPAN", + "Drivers/CMSIS/Core/Include", + "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/inc/_40nm_reg_files", + "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/config", + "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/config/ieee_15_4_basic", + "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/inc", + "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/inc/ot_inc", + ], + clang_args: &["-DSUPPORT_MAC=1", "-DMAC=1", "-DMAC_LAYER=1"], + allowlist: &[], + aliases: &["mac", "wpan_wba"], + library_artifacts: &[ + LibraryArtifact { + source: "Middlewares/ST/STM32_WPAN/mac_802_15_4/lib", + destination: "src/lib/mac", + }, + LibraryArtifact { + source: "Middlewares/ST/STM32_WPAN/mac_802_15_4/lib/wba_mac_lib.a", + destination: "src/lib/wba_mac_lib.a", + }, + LibraryArtifact { + source: "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/lib", + destination: "src/lib/link_layer", + }, + ], + }, + BindingSpec { + module: "ble_stack", + header: "stm32-bindings-gen/inc/ble-wba.h", + include_dirs: &[ + "Middlewares/ST/STM32_WPAN/ble/stack/include", + "Middlewares/ST/STM32_WPAN/ble/stack/include/auto", + "Middlewares/ST/STM32_WPAN", + "Drivers/CMSIS/Core/Include", + "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/inc/_40nm_reg_files", + "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/config", + "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/config/ble_basic_plus", + "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/inc", + "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/inc/ot_inc", + "Middlewares/ST/STM32_WPAN/ble/audio/Inc", + "Middlewares/ST/STM32_WPAN/ble/codec/codec_manager/Inc", + "Middlewares/ST/STM32_WPAN/ble/codec/lc3/Inc", + ], + clang_args: &["-DBLE=1", "-DSUPPORT_BLE=1", "-DEXT_ADDRESS_LENGTH=8"], + allowlist: &[], + aliases: &["ble", "ble_wba"], + library_artifacts: &[ + LibraryArtifact { + source: "Middlewares/ST/STM32_WPAN/ble/stack/lib", + destination: "src/lib/ble/stack", + }, + LibraryArtifact { + source: "Middlewares/ST/STM32_WPAN/ble/audio/lib", + destination: "src/lib/ble/audio", + }, + LibraryArtifact { + source: "Middlewares/ST/STM32_WPAN/ble/codec/codec_manager/Lib", + destination: "src/lib/ble/codec_manager", + }, + LibraryArtifact { + source: "Middlewares/ST/STM32_WPAN/ble/codec/lc3/Lib", + destination: "src/lib/ble/lc3", + }, + ], + }, +]; #[derive(Debug)] struct UppercaseCallbacks; @@ -22,6 +124,23 @@ pub struct Options { pub target_triple: String, } +fn host_isystem_args() -> Vec { + let mut args = Vec::new(); + if cfg!(target_os = "macos") { + if let Ok(output) = Command::new("xcrun").arg("--show-sdk-path").output() { + if output.status.success() { + if let Ok(path) = String::from_utf8(output.stdout) { + let trimmed = path.trim(); + if !trimmed.is_empty() { + args.push(format!("-isystem{}/usr/include", trimmed)); + } + } + } + } + } + args +} + pub struct Gen { opts: Options, } @@ -32,63 +151,201 @@ impl Gen { } pub fn run_gen(&mut self) { - let _ = fs::remove_dir_all(self.opts.out_dir.clone()); - fs::create_dir_all(self.opts.out_dir.join("src/bindings")).unwrap(); - fs::create_dir_all(self.opts.out_dir.join("src/lib")).unwrap(); - - // Create a named temporary file - let mut header = NamedTempFile::new().unwrap(); - - // Write some data to the first handle - header - .write_all(include_bytes!("../inc/wpan-wba.h")) - .unwrap(); - - header.reopen().unwrap(); - - // The bindgen::Builder is the main entry point - // to bindgen, and lets you build up options for - // the resulting bindings. - let target_flag = format!("--target={}", self.opts.target_triple); - let include_arg = format!( - "-I{}/Middlewares/ST/STM32_WPAN/mac_802_15_4/core/inc", - self.opts.sources_dir.to_str().unwrap() + println!( + "Generating bindings into {} for target {}", + self.opts.out_dir.display(), + self.opts.target_triple ); + + self.prepare_out_dir(); + self.write_static_files(); + + let mut modules = Vec::new(); + let mut aliases = Vec::new(); + for spec in BINDING_SPECS { + println!(" -> generating `{}` bindings", spec.module); + self.generate_bindings_for_spec(spec); + self.copy_artifacts_for_spec(spec); + modules.push(spec.module.to_owned()); + for alias in spec.aliases { + aliases.push((spec.module.to_owned(), alias.to_string())); + } + } + + self.write_bindings_mod(&modules, &aliases); + } + + fn prepare_out_dir(&self) { + let _ = fs::remove_dir_all(&self.opts.out_dir); + self.create_dir(self.opts.out_dir.join("src/bindings")); + self.create_dir(self.opts.out_dir.join("src/lib")); + } + + fn write_static_files(&self) { + self.write_bytes("README.md", include_bytes!("../res/README.md")); + self.write_bytes("Cargo.toml", include_bytes!("../res/Cargo.toml")); + self.write_bytes("build.rs", include_bytes!("../res/build.rs")); + self.write_bytes("src/lib.rs", include_bytes!("../res/src/lib.rs")); + } + + fn write_bindings_mod(&self, modules: &[String], aliases: &[(String, String)]) { + let mut body = String::new(); + for module in modules { + body.push_str("pub mod "); + body.push_str(module); + body.push_str(";\n"); + } + if !aliases.is_empty() { + body.push('\n'); + for (module, alias) in aliases { + body.push_str("pub use self::"); + body.push_str(module); + body.push_str(" as "); + body.push_str(alias); + body.push_str(";\n"); + } + } + self.write_string("src/bindings/mod.rs", body); + } + + fn generate_bindings_for_spec(&self, spec: &BindingSpec) { let mut builder = bindgen::Builder::default() .parse_callbacks(Box::new(UppercaseCallbacks)) - // Force Clang to use the same layout as the selected target. - .clang_arg(&target_flag) - .clang_arg(&include_arg); - if self - .opts - .target_triple - .to_ascii_lowercase() - .starts_with("thumb") - { + .header(spec.header) + .clang_arg(format!("--target={}", self.opts.target_triple)); + + for arg in host_isystem_args() { + builder = builder.clang_arg(arg); + } + + let crate_inc = Path::new(env!("CARGO_MANIFEST_DIR")).join("inc"); + builder = builder.clang_arg(format!("-iquote{}", crate_inc.display())); + + if Self::is_thumb_target(&self.opts.target_triple) { builder = builder.clang_arg("-mthumb"); } + + for dir in spec.include_dirs { + let include_path = Path::new(dir); + let resolved = if include_path.is_absolute() { + include_path.to_path_buf() + } else { + self.opts.sources_dir.join(include_path) + }; + builder = builder.clang_arg(format!("-I{}", resolved.display())); + } + + for arg in spec.clang_args { + builder = builder.clang_arg(*arg); + } + + if !spec.allowlist.is_empty() { + for pattern in spec.allowlist { + builder = builder + .allowlist_type(pattern) + .allowlist_var(pattern) + .allowlist_function(pattern); + } + } + let bindings = builder - // The input header we would like to generate - // bindings for. - .header("stm32-bindings-gen/inc/wpan-wba.h") - // Finish the builder and generate the bindings. .generate() - // Unwrap the Result and panic on failure. - .expect("Unable to generate bindings"); + .unwrap_or_else(|err| panic!("Unable to generate bindings for {}: {err}", spec.module)); - let out_path = self.opts.out_dir.join("src/bindings/wpan_wba.rs"); + let mut file_contents = bindings.to_string(); + file_contents = Self::normalize_bindings(file_contents); - bindings - .write_to_file(&out_path) - .expect("Couldn't write bindings!"); + let out_path = self + .opts + .out_dir + .join("src/bindings") + .join(format!("{}.rs", spec.module)); - let mut file_contents = fs::read_to_string(&out_path).unwrap(); - file_contents = file_contents - .replace("::std::mem::", "::core::mem::") - .replace("::std::os::raw::", "::core::ffi::") - .replace("::std::option::", "::core::option::"); + self.write_string_path(&out_path, file_contents); + } + + fn copy_artifacts_for_spec(&self, spec: &BindingSpec) { + for artifact in spec.library_artifacts { + let src = self.opts.sources_dir.join(artifact.source); + let dst = self.opts.out_dir.join(artifact.destination); - file_contents = file_contents + if src.is_file() { + self.copy_file(&src, &dst) + .unwrap_or_else(|err| panic!("Failed to copy file {}: {err}", src.display())); + } else if src.is_dir() { + self.copy_dir(&src, &dst).unwrap_or_else(|err| { + panic!("Failed to copy directory {}: {err}", src.display()) + }); + } else { + panic!( + "Artifact source {} is neither file nor directory", + src.display() + ); + } + } + } + + fn write_bytes(&self, relative: &str, bytes: &[u8]) { + let path = self.opts.out_dir.join(relative); + if let Some(parent) = path.parent() { + self.create_dir(parent); + } + fs::write(path, bytes).expect("Unable to write bytes"); + } + + fn write_string(&self, relative: &str, contents: String) { + let path = self.opts.out_dir.join(relative); + self.write_string_path(&path, contents); + } + + fn write_string_path(&self, path: &Path, mut contents: String) { + if !contents.ends_with('\n') { + contents.push('\n'); + } + if let Some(parent) = path.parent() { + self.create_dir(parent); + } + fs::write(path, contents).expect("Unable to write string"); + } + + fn create_dir>(&self, path: P) { + let path_ref = path.as_ref(); + if !path_ref.exists() { + fs::create_dir_all(path_ref).expect("Unable to create directory"); + } + } + + fn copy_file(&self, src: &Path, dst: &Path) -> io::Result<()> { + if let Some(parent) = dst.parent() { + fs::create_dir_all(parent)?; + } + fs::copy(src, dst)?; + Ok(()) + } + + fn copy_dir(&self, src: &Path, dst: &Path) -> io::Result<()> { + if !dst.exists() { + fs::create_dir_all(dst)?; + } + for entry in fs::read_dir(src)? { + let entry = entry?; + let path = entry.path(); + let target = dst.join(entry.file_name()); + if path.is_dir() { + self.copy_dir(&path, &target)?; + } else { + self.copy_file(&path, &target)?; + } + } + Ok(()) + } + + fn normalize_bindings(mut contents: String) -> String { + for (from, to) in STD_TO_CORE_REPLACEMENTS { + contents = contents.replace(from, to); + } + + let normalized = contents .lines() .map(|line| { if let Some(rest) = line.strip_prefix("pub const ") { @@ -102,45 +359,10 @@ impl Gen { .collect::>() .join("\n"); - if !file_contents.ends_with('\n') { - file_contents.push('\n'); - } - - fs::write(&out_path, file_contents).unwrap(); - - // copy misc files - fs::copy( - self.opts - .sources_dir - .join("Middlewares/ST/STM32_WPAN/mac_802_15_4/lib/wba_mac_lib.a"), - self.opts.out_dir.join("src/lib/wba_mac_lib.a"), - ) - .unwrap(); - fs::write( - self.opts.out_dir.join("README.md"), - include_bytes!("../res/README.md"), - ) - .unwrap(); - fs::write( - self.opts.out_dir.join("Cargo.toml"), - include_bytes!("../res/Cargo.toml"), - ) - .unwrap(); - fs::write( - self.opts.out_dir.join("build.rs"), - include_bytes!("../res/build.rs"), - ) - .unwrap(); - fs::write( - self.opts.out_dir.join("src/lib.rs"), - include_bytes!("../res/src/lib.rs"), - ) - .unwrap(); - - fs::write( - self.opts.out_dir.join("src/bindings/mod.rs"), - include_bytes!("../res/src/bindings/mod.rs"), - ) - .unwrap(); + normalized + } + + fn is_thumb_target(triple: &str) -> bool { + triple.trim().to_ascii_lowercase().starts_with("thumb") } } From b6055db5792efe7e8a56a192a7b7d125b0f76136 Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Mon, 1 Dec 2025 17:35:08 -0700 Subject: [PATCH 2/4] Added newlines to header files --- stm32-bindings-gen/inc/app_conf.h | 2 +- stm32-bindings-gen/inc/ble-wba.h | 2 +- stm32-bindings-gen/inc/wba_wpan_mac.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stm32-bindings-gen/inc/app_conf.h b/stm32-bindings-gen/inc/app_conf.h index 4f01ee3..c8d8e73 100644 --- a/stm32-bindings-gen/inc/app_conf.h +++ b/stm32-bindings-gen/inc/app_conf.h @@ -41,4 +41,4 @@ extern "C" { } #endif -#endif /* STM32_BINDINGS_GEN_APP_CONF_H */ \ No newline at end of file +#endif /* STM32_BINDINGS_GEN_APP_CONF_H */ diff --git a/stm32-bindings-gen/inc/ble-wba.h b/stm32-bindings-gen/inc/ble-wba.h index 2117ddf..d393691 100644 --- a/stm32-bindings-gen/inc/ble-wba.h +++ b/stm32-bindings-gen/inc/ble-wba.h @@ -88,4 +88,4 @@ extern "C" { } /* extern "C" */ #endif -#endif /* BLE_WBA_BINDINGS_H_ */ \ No newline at end of file +#endif /* BLE_WBA_BINDINGS_H_ */ diff --git a/stm32-bindings-gen/inc/wba_wpan_mac.h b/stm32-bindings-gen/inc/wba_wpan_mac.h index cd104db..04d6cac 100644 --- a/stm32-bindings-gen/inc/wba_wpan_mac.h +++ b/stm32-bindings-gen/inc/wba_wpan_mac.h @@ -473,4 +473,4 @@ extern "C" } /* extern "C" */ #endif -#endif /* APP_CERTIFICATION_MAC_802_15_4_PROCESS_H */ \ No newline at end of file +#endif /* APP_CERTIFICATION_MAC_802_15_4_PROCESS_H */ From c3afa85f6cfdffe0357d82da650d4f7773feb15d Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Mon, 1 Dec 2025 17:51:50 -0700 Subject: [PATCH 3/4] Fixed CI error --- stm32-bindings-gen/src/lib.rs | 11 ++++++++++- stm32-bindings-gen/src/main.rs | 12 +++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/stm32-bindings-gen/src/lib.rs b/stm32-bindings-gen/src/lib.rs index f59addf..11d996d 100644 --- a/stm32-bindings-gen/src/lib.rs +++ b/stm32-bindings-gen/src/lib.rs @@ -84,7 +84,16 @@ const BINDING_SPECS: &[BindingSpec] = &[ "Middlewares/ST/STM32_WPAN/ble/codec/lc3/Inc", "Drivers/CMSIS/Core/Include", ], - clang_args: &["-DBLE=1", "-DSUPPORT_BLE=1", "-DEXT_ADDRESS_LENGTH=8"], + clang_args: &[ + "-DBLE=1", + "-DBLE_LL=1", + "-DMAC=1", + "-DMAC_LAYER=1", + "-DSUPPORT_CONFIG_LIB=1", + "-DSUPPORT_OPENTHREAD_1_2=1", + "-DSUPPORT_ANT_DIV=1", + "-DEXT_ADDRESS_LENGTH=8", + ], allowlist: &[], aliases: &["ble", "ble_wba"], library_artifacts: &[ diff --git a/stm32-bindings-gen/src/main.rs b/stm32-bindings-gen/src/main.rs index cdf5147..7e434f7 100644 --- a/stm32-bindings-gen/src/main.rs +++ b/stm32-bindings-gen/src/main.rs @@ -4,7 +4,7 @@ use stm32_bindings_gen::{Gen, Options}; fn main() { let out_dir = PathBuf::from("build/stm32-bindings"); - let sources_dir = PathBuf::from("sources"); + let sources_dir = resolve_sources_dir(); let target_triple = resolve_target_triple(); let opts = Options { @@ -16,6 +16,16 @@ fn main() { Gen::new(opts).run_gen(); } +fn resolve_sources_dir() -> PathBuf { + let nested = PathBuf::from("sources/STM32CubeWBA"); + + if nested.exists() { + nested + } else { + PathBuf::from("sources") + } +} + #[allow(dead_code)] fn resolve_target_triple() -> String { let mut args = env::args().skip(1); From e1da737c09d00501f170066edd0368d77edc19eb Mon Sep 17 00:00:00 2001 From: Gerzain Mata Date: Mon, 1 Dec 2025 18:15:59 -0700 Subject: [PATCH 4/4] WIP changes --- .github/workflows/rust.yml | 43 +++++----- stm32-bindings-gen/inc/string.h | 28 ++++++ stm32-bindings-gen/src/lib.rs | 147 ++++++-------------------------- 3 files changed, 75 insertions(+), 143 deletions(-) create mode 100644 stm32-bindings-gen/inc/string.h diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 97fa8c5..14b9313 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -2,33 +2,36 @@ name: Rust on: push: - branches: [ "main" ] + branches: ["main"] pull_request: - branches: [ "main" ] + branches: ["main"] env: CARGO_TERM_COLOR: always jobs: build: - runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: ⚡ Cache - uses: actions/cache@v4 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - target - key: ${{ runner.os }}-cargo - - name: Set permissions - run: chmod +x d - - name: Load sources - run: ./d download-all - - name: Run build - run: cargo run --release --bin stm32-bindings-gen - - name: Run package build - run: cd build/stm32-bindings && cargo build --target=thumbv8m.main-none-eabihf + - uses: actions/checkout@v4 + - name: ⚡ Cache + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo + - name: Install ARM GCC toolchain + run: | + sudo apt-get update + sudo apt-get install -y gcc-arm-none-eabi + - name: Set permissions + run: chmod +x d + - name: Load sources + run: ./d download-all + - name: Run build + run: cargo run --release --bin stm32-bindings-gen + - name: Run package build + run: cd build/stm32-bindings && cargo build --target=thumbv8m.main-none-eabihf diff --git a/stm32-bindings-gen/inc/string.h b/stm32-bindings-gen/inc/string.h new file mode 100644 index 0000000..07ba823 --- /dev/null +++ b/stm32-bindings-gen/inc/string.h @@ -0,0 +1,28 @@ +#ifndef STM32_BINDINGS_GEN_STUB_STRING_H +#define STM32_BINDINGS_GEN_STUB_STRING_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void *memcpy(void *dest, const void *src, size_t n); +void *memmove(void *dest, const void *src, size_t n); +void *memset(void *s, int c, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); + +size_t strlen(const char *s); +size_t strnlen(const char *s, size_t maxlen); +char *strcpy(char *dest, const char *src); +char *strncpy(char *dest, const char *src, size_t n); +char *strcat(char *dest, const char *src); +char *strncat(char *dest, const char *src, size_t n); +int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); + +#ifdef __cplusplus +} +#endif + +#endif /* STM32_BINDINGS_GEN_STUB_STRING_H */ \ No newline at end of file diff --git a/stm32-bindings-gen/src/lib.rs b/stm32-bindings-gen/src/lib.rs index 11d996d..e18db9b 100644 --- a/stm32-bindings-gen/src/lib.rs +++ b/stm32-bindings-gen/src/lib.rs @@ -1,121 +1,10 @@ use bindgen::callbacks::{ItemInfo, ItemKind, ParseCallbacks}; -use std::path::{Path, PathBuf}; -use std::process::Command; -use std::{fs, io}; - -const STD_TO_CORE_REPLACEMENTS: &[(&str, &str)] = &[ - ("::std::mem::", "::core::mem::"), - ("::std::os::raw::", "::core::ffi::"), - ("::std::option::", "::core::option::"), - ("::std::ptr::", "::core::ptr::"), - (":: std :: mem ::", ":: core :: mem ::"), - (":: std :: os :: raw ::", ":: core :: ffi ::"), - (":: std :: option ::", ":: core :: option ::"), - (":: std :: ptr ::", ":: core :: ptr ::"), -]; - -#[derive(Debug, Clone, Copy)] -struct BindingSpec { - module: &'static str, - feature: Option<&'static str>, - header: &'static str, - include_dirs: &'static [&'static str], - clang_args: &'static [&'static str], - allowlist: &'static [&'static str], - aliases: &'static [&'static str], - library_artifacts: &'static [LibraryArtifact], -} - -#[derive(Debug, Clone, Copy)] -struct LibraryArtifact { - source: &'static str, - destination: &'static str, -} - -const BINDING_SPECS: &[BindingSpec] = &[ - BindingSpec { - module: "wba_wpan_mac", - feature: Some("wba_wpan_mac"), - header: "stm32-bindings-gen/inc/wba_wpan_mac.h", - include_dirs: &[ - "Middlewares/ST/STM32_WPAN", - "Middlewares/ST/STM32_WPAN/mac_802_15_4/core/inc", - "Middlewares/ST/STM32_WPAN/mac_802_15_4/mac_utilities/inc", - "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/inc", - "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/inc/_40nm_reg_files", - "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/inc/ot_inc", - "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/config", - "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/config/ieee_15_4_basic", - "Drivers/CMSIS/Core/Include", - ], - clang_args: &["-DSUPPORT_MAC=1", "-DMAC=1", "-DMAC_LAYER=1"], - allowlist: &[], - aliases: &["mac", "mac_802_15_4", "wpan_wba"], - library_artifacts: &[ - LibraryArtifact { - source: "Middlewares/ST/STM32_WPAN/mac_802_15_4/lib", - destination: "src/lib/wba_wpan_mac", - }, - LibraryArtifact { - source: "Middlewares/ST/STM32_WPAN/mac_802_15_4/lib/wba_mac_lib.a", - destination: "src/lib/wba_mac_lib.a", - }, - LibraryArtifact { - source: "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/lib", - destination: "src/lib/link_layer", - }, - ], - }, - BindingSpec { - module: "ble_stack", - feature: Some("wba_wpan_ble"), - header: "stm32-bindings-gen/inc/ble-wba.h", - include_dirs: &[ - "Middlewares/ST/STM32_WPAN", - "Middlewares/ST/STM32_WPAN/ble/stack/include", - "Middlewares/ST/STM32_WPAN/ble/stack/include/auto", - "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/inc", - "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/inc/_40nm_reg_files", - "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/inc/ot_inc", - "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/config", - "Middlewares/ST/STM32_WPAN/link_layer/ll_cmd_lib/config/ble_basic_plus", - "Middlewares/ST/STM32_WPAN/ble/audio/Inc", - "Middlewares/ST/STM32_WPAN/ble/codec/codec_manager/Inc", - "Middlewares/ST/STM32_WPAN/ble/codec/lc3/Inc", - "Drivers/CMSIS/Core/Include", - ], - clang_args: &[ - "-DBLE=1", - "-DBLE_LL=1", - "-DMAC=1", - "-DMAC_LAYER=1", - "-DSUPPORT_CONFIG_LIB=1", - "-DSUPPORT_OPENTHREAD_1_2=1", - "-DSUPPORT_ANT_DIV=1", - "-DEXT_ADDRESS_LENGTH=8", - ], - allowlist: &[], - aliases: &["ble", "ble_wba"], - library_artifacts: &[ - LibraryArtifact { - source: "Middlewares/ST/STM32_WPAN/ble/stack/lib", - destination: "src/lib/ble/stack", - }, - LibraryArtifact { - source: "Middlewares/ST/STM32_WPAN/ble/audio/lib", - destination: "src/lib/ble/audio", - }, - LibraryArtifact { - source: "Middlewares/ST/STM32_WPAN/ble/codec/codec_manager/Lib", - destination: "src/lib/ble/codec_manager", - }, - LibraryArtifact { - source: "Middlewares/ST/STM32_WPAN/ble/codec/lc3/Lib", - destination: "src/lib/ble/lc3", - }, - ], - }, -]; +use std::io::Write; +use std::{ + fs, + path::{Path, PathBuf}, +}; +use tempfile::NamedTempFile; #[derive(Debug)] struct UppercaseCallbacks; @@ -180,12 +69,24 @@ impl Gen { self.generate_bindings_for_spec(spec); self.copy_artifacts_for_spec(spec); - modules.push((spec.module.to_owned(), spec.feature.map(str::to_owned))); - for alias in spec.aliases { - aliases.push(( - spec.module.to_owned(), - alias.to_string(), - spec.feature.map(str::to_owned), + // The bindgen::Builder is the main entry point + // to bindgen, and lets you build up options for + // the resulting bindings. + let target_flag = format!("--target={}", lib.target_triple); + + let mut builder = bindgen::Builder::default() + .parse_callbacks(Box::new(UppercaseCallbacks)) + // Force Clang to use the same layout as the selected target. + .clang_arg(&target_flag); + + let crate_inc = Path::new(env!("CARGO_MANIFEST_DIR")).join("inc"); + builder = builder.clang_arg(&format!("-iquote{}", crate_inc.display())); + builder = builder.clang_arg(&format!("-I{}", crate_inc.display())); + + for include_arg in &lib.includes { + builder = builder.clang_arg(&format!( + "-I{}", + sources_dir.join(include_arg).to_str().unwrap() )); } }