 110a9efc3c
			
		
	
	
		110a9efc3c
		
			
		
	
	
	
	
		
			
			* proof of concept * fix syntax for rust and add auto fix syntax * fix syntax for C * fix bug with files owner * add information to wiki * try to add ci * format code from master * even more format fixes * change docker to docker-compose * Exclude ./target_*/build directories from format check * Run rustfmt only on project files * add ulimit setup for long clang list * merge * fix rustfmt, exclude target Inc directory * sync with master * abspath Co-authored-by: aanper <mail@s3f.ru> Co-authored-by: Vadim Kaushan <admin@disasm.info>
		
			
				
	
	
		
			289 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			289 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use std::env;
 | |
| use std::fs;
 | |
| use std::path::{Path, PathBuf};
 | |
| 
 | |
| fn main() {
 | |
|     println!("cargo:rerun-if-env-changed=FORCE_BINDGEN");
 | |
| 
 | |
|     let generator = BindingsGenerator::new();
 | |
|     generator.generate_cmsis_os_bindings();
 | |
|     generator.generate_stm32_hal_bindings();
 | |
|     generator.generate_stm32_hal_statics();
 | |
| }
 | |
| 
 | |
| struct BindingsGenerator {
 | |
|     clib_dir: PathBuf,
 | |
|     workspace_dir: PathBuf,
 | |
|     out_dir: PathBuf,
 | |
|     gcc_include_dir: PathBuf,
 | |
|     force_bindgen: bool,
 | |
| }
 | |
| 
 | |
| impl BindingsGenerator {
 | |
|     pub fn new() -> Self {
 | |
|         let out_dir = env::var("OUT_DIR").unwrap();
 | |
| 
 | |
|         let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
 | |
|         let workspace_dir = Path::new(&crate_dir).parent().unwrap();
 | |
|         let clib_dir = workspace_dir.parent().unwrap().join("target_f1");
 | |
|         assert!(clib_dir.is_dir());
 | |
| 
 | |
|         let force_bindgen: bool = std::env::var_os("FORCE_BINDGEN").is_some();
 | |
| 
 | |
|         let gcc_include_dir = detect_gcc_inclide_dir();
 | |
| 
 | |
|         Self {
 | |
|             clib_dir: clib_dir.to_path_buf(),
 | |
|             workspace_dir: workspace_dir.to_path_buf(),
 | |
|             out_dir: Path::new(&out_dir).to_path_buf(),
 | |
|             gcc_include_dir,
 | |
|             force_bindgen,
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     fn builder(&self) -> bindgen::Builder {
 | |
|         let stm32_sdk_includes = [
 | |
|             "Inc",
 | |
|             "Drivers/STM32L4xx_HAL_Driver/Inc",
 | |
|             "Drivers/STM32L4xx_HAL_Driver/Inc/Legacy",
 | |
|             "Middlewares/Third_Party/FreeRTOS/Source/include",
 | |
|             "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS",
 | |
|             "Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F",
 | |
|             "Drivers/CMSIS/Device/ST/STM32L4xx/Include",
 | |
|             "Drivers/CMSIS/Include",
 | |
|             "Middlewares/ST/STM32_USB_Device_Library/Core/Inc",
 | |
|             "Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc",
 | |
|         ];
 | |
| 
 | |
|         let stm32_sdk_includes = stm32_sdk_includes
 | |
|             .iter()
 | |
|             .map(|stm32_include| format!("{}/{}", self.clib_dir.to_string_lossy(), stm32_include));
 | |
| 
 | |
|         let flipper_core_bindings = self.workspace_dir.join("flipper-core").join("bindings");
 | |
| 
 | |
|         let includes = [
 | |
|             // This are bindings generated by cbindgen nearby
 | |
|             &flipper_core_bindings.to_string_lossy(),
 | |
|             &self.gcc_include_dir.to_string_lossy(),
 | |
|         ];
 | |
| 
 | |
|         #[rustfmt::skip]
 | |
|         return bindgen::Builder::default()
 | |
|             .use_core()
 | |
|             .ctypes_prefix("self")
 | |
|             .blacklist_type("__uint8_t")
 | |
|             .blacklist_type("__uint32_t")
 | |
|             .blacklist_type("c_int")
 | |
|             .blacklist_type("__int32_t")
 | |
|             // TODO there's no .no_debug method, to disable only for specific type
 | |
|             .derive_debug(false)
 | |
|             .clang_arg("-DUSE_HAL_DRIVER")
 | |
|             .clang_arg("-DSTM32L476xx")
 | |
|             .clang_arg("-DBUTON_INVERT=false")
 | |
|             .clang_arg("-DDEBUG_UART=huart1")
 | |
|             .clang_args(
 | |
|                 (includes.iter().map(|x| From::from(x as &str)).chain(stm32_sdk_includes))
 | |
|                     .map(|include| format!("-I{}", include))
 | |
|             )
 | |
|             .clang_arg("--target=thumbv7em-none-eabihf")
 | |
|             .clang_arg("--verbose")
 | |
|             //.clang_arg("-nostdinc")
 | |
|         ;
 | |
|     }
 | |
| 
 | |
|     pub fn generate_cmsis_os_bindings(&self) {
 | |
|         let result_path = self.out_dir.join("cmsis_os_bindings.rs");
 | |
|         let should_build = !result_path.is_file() || self.force_bindgen;
 | |
|         if !should_build {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         println!("cargo:warning=writing cmsis os bindings");
 | |
| 
 | |
|         #[rustfmt::skip]
 | |
|         let builder = self.builder()
 | |
|             .whitelist_recursively(false)
 | |
| 
 | |
|             .header(format!("{}/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.h", self.clib_dir.to_string_lossy()))
 | |
| 
 | |
|             .whitelist_type("osStatus")
 | |
|             .rustified_enum("osStatus")
 | |
| 
 | |
|             .whitelist_type("osEvent")
 | |
| 
 | |
|             .whitelist_type("os_pthread")
 | |
|             .whitelist_type("osThreadId")
 | |
|             .opaque_type("osThreadId")
 | |
|             .whitelist_type("os_thread_def")
 | |
|             .whitelist_type("osThreadDef_t")
 | |
|             .whitelist_type("osStaticThreadDef_t")
 | |
|             .opaque_type("osStaticThreadDef_t")
 | |
|             .whitelist_type("osPriority")
 | |
|             .rustified_enum("osPriority")
 | |
|             .whitelist_function("osThreadCreate")
 | |
|             .whitelist_function("osThreadGetId")
 | |
|             .whitelist_function("osThreadTerminate")
 | |
|             .whitelist_function("osThreadYield")
 | |
| 
 | |
|             .whitelist_type("osMutexId")
 | |
|             .opaque_type("osMutexId")
 | |
|             .whitelist_type("os_mutex_def")
 | |
|             .whitelist_type("osMutexDef_t")
 | |
|             .whitelist_type("osStaticMutexDef_t")
 | |
|             .opaque_type("osStaticMutexDef_t")
 | |
|             .whitelist_function("osMutexCreate")
 | |
|             .whitelist_function("osMutexWait")
 | |
|             .whitelist_function("osMutexRelease")
 | |
| 
 | |
|             .whitelist_type("osSemaphoreId")
 | |
|             .opaque_type("osSemaphoreId")
 | |
|             .whitelist_type("os_semaphore_def")
 | |
|             .whitelist_type("osSemaphoreDef_t")
 | |
|             .whitelist_type("osStaticSemaphoreDef_t")
 | |
|             .opaque_type("osStaticSemaphoreDef_t")
 | |
|             .whitelist_function("osSemaphoreCreate")
 | |
|             .whitelist_function("osSemaphoreWait")
 | |
|             .whitelist_function("osSemaphoreRelease")
 | |
| 
 | |
|             .whitelist_type("osMessageQId")
 | |
|             .opaque_type("osMessageQId")
 | |
| 
 | |
|             .whitelist_type("osMailQId")
 | |
|             .opaque_type("osMailQId")
 | |
|             .whitelist_type("os_mailQ_def")
 | |
|             .whitelist_type("osMailQDef_t")
 | |
|             .whitelist_type("os_mailQ_cb")
 | |
|             .whitelist_function("osMailCreate")
 | |
|             .whitelist_function("osMailAlloc")
 | |
|             .whitelist_function("osMailFree")
 | |
|             .whitelist_function("osMailPut")
 | |
|             .whitelist_function("osMailGet")
 | |
| 
 | |
|             .whitelist_var("osWaitForever")
 | |
|             .whitelist_function("osDelay")
 | |
| 
 | |
|             // TODO for some reason, bindgen wont generate osKernelSysTickFrequency
 | |
|             .whitelist_var("osKernelSysTickFrequency")
 | |
|             .whitelist_function("osKernelSysTick")
 | |
|         ;
 | |
| 
 | |
|         let bindings = builder.generate().expect("Unable to generate bindings");
 | |
| 
 | |
|         bindings
 | |
|             .write_to_file(result_path)
 | |
|             .expect("Couldn't write bindings!");
 | |
|     }
 | |
| 
 | |
|     pub fn generate_stm32_hal_bindings(&self) {
 | |
|         let result_path = self.out_dir.join("stm32_hal_bindings.rs");
 | |
|         let should_build = !result_path.is_file() || self.force_bindgen;
 | |
|         if !should_build {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         println!("cargo:warning=writing STM32 HAL bindings");
 | |
| 
 | |
|         #[rustfmt::skip]
 | |
|         let builder = self.builder()
 | |
|             .whitelist_recursively(false)
 | |
| 
 | |
|             .header(format!("{}/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h", self.clib_dir.to_string_lossy()))
 | |
| 
 | |
|             .whitelist_type("HAL_StatusTypeDef")
 | |
|             .rustified_enum("HAL_StatusTypeDef")
 | |
| 
 | |
|             .whitelist_type("GPIO_TypeDef")
 | |
|             .opaque_type("GPIO_TypeDef")
 | |
|             .whitelist_type("GPIO_PinState")
 | |
|             .rustified_enum("GPIO_PinState")
 | |
|             .whitelist_function("HAL_GPIO_WritePin")
 | |
|             .whitelist_function("HAL_GPIO_TogglePin")
 | |
|             .whitelist_function("HAL_GPIO_ReadPin")
 | |
| 
 | |
|             .whitelist_type("UART_HandleTypeDef")
 | |
|             .opaque_type("UART_HandleTypeDef")
 | |
|             .whitelist_function("HAL_UART_Transmit_IT")
 | |
| 
 | |
|             .whitelist_type("SPI_HandleTypeDef")
 | |
|             .opaque_type("SPI_HandleTypeDef")
 | |
|             .whitelist_function("HAL_SPI_Transmit_IT")
 | |
|             .whitelist_function("HAL_SPI_Receive_IT")
 | |
|             .whitelist_function("HAL_SPI_TransmitReceive_IT")
 | |
| 
 | |
|             .whitelist_type("ADC_HandleTypeDef")
 | |
|             .opaque_type("ADC_HandleTypeDef")
 | |
| 
 | |
|             .whitelist_type("COMP_HandleTypeDef")
 | |
|             .opaque_type("COMP_HandleTypeDef")
 | |
| 
 | |
|             .whitelist_type("DAC_HandleTypeDef")
 | |
|             .opaque_type("DAC_HandleTypeDef")
 | |
| 
 | |
|             .whitelist_type("TIM_HandleTypeDef")
 | |
|             .opaque_type("TIM_HandleTypeDef")
 | |
|         ;
 | |
| 
 | |
|         let bindings = builder.generate().expect("Unable to generate bindings");
 | |
| 
 | |
|         bindings
 | |
|             .write_to_file(result_path)
 | |
|             .expect("Couldn't write bindings!");
 | |
|     }
 | |
| 
 | |
|     pub fn generate_stm32_hal_statics(&self) {
 | |
|         let result_path = self.out_dir.join("stm32_hal_statics.rs");
 | |
|         let should_build = !result_path.is_file() || self.force_bindgen;
 | |
|         if !should_build {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         println!("cargo:warning=writing STM32 HAL bindings");
 | |
| 
 | |
|         #[rustfmt::skip]
 | |
|         let builder = self.builder()
 | |
|             .whitelist_recursively(false)
 | |
| 
 | |
|             .header(format!("{}/Src/main.c", self.clib_dir.to_string_lossy()))
 | |
| 
 | |
|             .whitelist_var(".*_Pin")
 | |
|             .whitelist_var(".*_Port")
 | |
| 
 | |
|             .whitelist_var("HAL_.*_Pin")
 | |
|             .whitelist_var("HAL_.*_Port")
 | |
|             .whitelist_var("hadc[0-9]+")
 | |
|             .whitelist_var("hcomp[0-9]+")
 | |
|             .whitelist_var("hdac[0-9]+")
 | |
|             .whitelist_var("hspi[0-9]+")
 | |
|             .whitelist_var("htim[0-9]+")
 | |
|             .whitelist_var("huart[0-9]+")
 | |
|             ;
 | |
| 
 | |
|         let bindings = builder.generate().expect("Unable to generate bindings");
 | |
| 
 | |
|         bindings
 | |
|             .write_to_file(result_path)
 | |
|             .expect("Couldn't write bindings!");
 | |
|     }
 | |
| }
 | |
| 
 | |
| fn detect_gcc_inclide_dir() -> PathBuf {
 | |
|     let base_path = Path::new("/usr/lib/gcc/arm-none-eabi");
 | |
|     if !base_path.is_dir() {
 | |
|         panic!("Can't find arm-none-eabi-gcc lib directory");
 | |
|     }
 | |
| 
 | |
|     let entries = fs::read_dir(base_path).expect("Can't read arm-none-eabi-gcc lib directory");
 | |
| 
 | |
|     for entry in entries {
 | |
|         let entry = entry.expect("Can't read dir entry");
 | |
|         let path = entry.path();
 | |
|         if path.is_dir() {
 | |
|             let include_dir = path.join("include");
 | |
|             if include_dir.is_dir() {
 | |
|                 return include_dir.to_path_buf();
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     panic!("Can't find arm-none-eabi-gcc include directory");
 | |
| }
 |