From 514670e897c4103d9a9208e0a02aefe984e47684 Mon Sep 17 00:00:00 2001 From: kalipso Date: Sun, 18 Dec 2022 15:37:26 +0100 Subject: [PATCH 01/12] init --- .gitignore | 4 + CMakeLists.txt | 65 ++ cmake/FindBSP.cmake | 404 +++++++++++ cmake/FindCMSIS.cmake | 326 +++++++++ cmake/FindFreeRTOS.cmake | 259 ++++++++ cmake/FindHAL.cmake | 315 +++++++++ cmake/stm32/common.cmake | 372 +++++++++++ cmake/stm32/devices.cmake | 1258 +++++++++++++++++++++++++++++++++++ cmake/stm32/f0.cmake | 25 + cmake/stm32/f1.cmake | 78 +++ cmake/stm32/f2.cmake | 39 ++ cmake/stm32/f3.cmake | 59 ++ cmake/stm32/f4.cmake | 29 + cmake/stm32/f7.cmake | 25 + cmake/stm32/g0.cmake | 25 + cmake/stm32/g4.cmake | 25 + cmake/stm32/h7.cmake | 87 +++ cmake/stm32/l0.cmake | 29 + cmake/stm32/l1.cmake | 73 ++ cmake/stm32/l4.cmake | 40 ++ cmake/stm32/l5.cmake | 22 + cmake/stm32/linker_ld.cmake | 158 +++++ cmake/stm32/mp1.cmake | 31 + cmake/stm32/u5.cmake | 19 + cmake/stm32/utilities.cmake | 161 +++++ cmake/stm32/wb.cmake | 38 ++ cmake/stm32/wl.cmake | 77 +++ cmake/stm32_gcc.cmake | 23 + flake.lock | 43 ++ flake.nix | 54 ++ main.cpp | 128 ++++ rfm95.cpp | 773 +++++++++++++++++++++ rfm95.hpp | 347 ++++++++++ shell.nix | 15 + spi.cpp | 57 ++ spi.hpp | 7 + stm32f1xx_hal_conf.h | 449 +++++++++++++ uart_handler.cpp | 1 + uart_handler.hpp | 120 ++++ 39 files changed, 6060 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 cmake/FindBSP.cmake create mode 100644 cmake/FindCMSIS.cmake create mode 100644 cmake/FindFreeRTOS.cmake create mode 100644 cmake/FindHAL.cmake create mode 100644 cmake/stm32/common.cmake create mode 100644 cmake/stm32/devices.cmake create mode 100644 cmake/stm32/f0.cmake create mode 100644 cmake/stm32/f1.cmake create mode 100644 cmake/stm32/f2.cmake create mode 100644 cmake/stm32/f3.cmake create mode 100644 cmake/stm32/f4.cmake create mode 100644 cmake/stm32/f7.cmake create mode 100644 cmake/stm32/g0.cmake create mode 100644 cmake/stm32/g4.cmake create mode 100644 cmake/stm32/h7.cmake create mode 100644 cmake/stm32/l0.cmake create mode 100644 cmake/stm32/l1.cmake create mode 100644 cmake/stm32/l4.cmake create mode 100644 cmake/stm32/l5.cmake create mode 100644 cmake/stm32/linker_ld.cmake create mode 100644 cmake/stm32/mp1.cmake create mode 100644 cmake/stm32/u5.cmake create mode 100644 cmake/stm32/utilities.cmake create mode 100644 cmake/stm32/wb.cmake create mode 100644 cmake/stm32/wl.cmake create mode 100644 cmake/stm32_gcc.cmake create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 main.cpp create mode 100644 rfm95.cpp create mode 100644 rfm95.hpp create mode 100644 shell.nix create mode 100644 spi.cpp create mode 100644 spi.hpp create mode 100755 stm32f1xx_hal_conf.h create mode 100644 uart_handler.cpp create mode 100644 uart_handler.hpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c2c4b46 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.user +build/ +*bak +test/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d1aceb1 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,65 @@ +cmake_minimum_required(VERSION 3.16) +set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/stm32_gcc.cmake) + +project(stm32-blinky C CXX ASM) +set(MAIN_SOURCE_FILE main.cpp) + +set(CMAKE_INCLUDE_CURRENT_DIR TRUE) + +set(HAL_COMP_LIST RCC GPIO CORTEX UART SPI) +set(CMSIS_COMP_LIST "") + +list(APPEND CMSIS_COMP_LIST STM32F1) +list(APPEND HAL_COMP_LIST STM32F1) + +find_package(CMSIS COMPONENTS STM32F1 REQUIRED) +find_package(HAL COMPONENTS "${HAL_COMP_LIST}" REQUIRED) + +# Find all device specific drivers: +#find_package(HAL COMPONENTS STM32L0 STM32F1 STM32F4 REQUIRED) +# Find drivers for all families: +#find_package(HAL COMPONENTS RCC GPIO CORTEX REQUIRED) +# Find LL driver: +#find_package(HAL COMPONENTS LL_GPIO REQUIRED) +# Find everything: +#find_package(HAL REQUIRED) + +# STM32VL-Discovery +add_executable(stm32-blinky-f1 + ${MAIN_SOURCE_FILE} + uart_handler.cpp + spi.cpp + rfm95.cpp + stm32f1xx_hal_conf.h +) + +set_property(TARGET stm32-blinky-f1 PROPERTY CXX_STANDARD 17) + +target_link_libraries(stm32-blinky-f1 + HAL::STM32::F1::UART + HAL::STM32::F1::RCC + HAL::STM32::F1::GPIO + HAL::STM32::F1::CORTEX + HAL::STM32::F1::SPI + CMSIS::STM32::F100RB + STM32::NoSys +) +stm32_print_size_of_target(stm32-blinky-f1) + +#add_executable(stm32-blinky-f1 +# test/main.c +# test/gpio.c +# test/usart.c +# test/stm32f1xx_hal_conf.h +# ) +#target_link_libraries(stm32-blinky-f1 +# HAL::STM32::F1::UART +# HAL::STM32::F1::RCC +# HAL::STM32::F1::GPIO +# HAL::STM32::F1::CORTEX +# CMSIS::STM32::F100RB +# STM32::NoSys +#) +#stm32_print_size_of_target(stm32-blinky-f1) + + diff --git a/cmake/FindBSP.cmake b/cmake/FindBSP.cmake new file mode 100644 index 0000000..7fac570 --- /dev/null +++ b/cmake/FindBSP.cmake @@ -0,0 +1,404 @@ +# For information about why and how of this file: https://cmake.org/cmake/help/latest/command/find_package.html + +### F0 ### +set(BSP_F0_BOARDS + STM32F0xx_Nucleo_32 STM32F0xx-Nucleo STM32F072B-Discovery + STM32F0308-Discovery STM32072B_EVAL STM32091C_EVAL +) +set(BSP_F0_COMPONENTS + hx8347d l3gd20 spfd5408 st7735 stlm75 +) +set(BSP_F0_SOURCES_STM32F072B_Discovery eeprom gyroscope) +set(BSP_F0_SOURCES_STM32072B_EVAL eeprom lcd sd tsensor) +set(BSP_F0_SOURCES_STM32091C_EVAL eeprom lcd sd tsensor) +set(BSP_F0_DEVICE_STM32F072B_Discovery F072RB) +set(BSP_F0_DEVICE_STM32F0308_Discovery F030R8) +set(BSP_F0_DEVICE_STM32072B_EVAL F072VB) +set(BSP_F0_DEVICE_STM32091C_EVAL F091VC) + +### F1 ### +set(BSP_F1_BOARDS + STM32F1xx_Nucleo STM32VL-Discovery STM3210C_EVAL STM3210E_EVAL +) +set(BSP_F1_COMPONENTS + ak4343 cs43l22 hx8347d ili9320 ili9325 lis302dl spfd5408 st7735 stlm75 + stmpe811 +) +set(BSP_F1_SOURCES_STM3210C_EVAL accelerometer audio eeprom io lcd sd ts) +set(BSP_F1_SOURCES_STM3210E_EVAL audio lcd nand nor sd serialflash sram tsensor) +set(BSP_F1_DEVICE_STM32VL_Discovery F100RB) +set(BSP_F1_DEVICE_STM3210C_EVAL F107VC) +set(BSP_F1_DEVICE_STM3210E_EVAL F103ZE) + +### F2 ### +set(BSP_F2_BOARDS + STM32F2xx_Nucleo_144 STM322xG_EVAL +) +set(BSP_F2_COMPONENTS + cs43l22 ili9320 ili9325 ili9341 ov2640 st7735 stmpe811 +) +set(BSP_F2_SOURCES_STM322xG_EVAL audio camera eeprom io lcd sd sram ts) +set(BSP_F2_DEVICE_STM322xG_EVAL F207IG) + +### F3 ### +set(BSP_F3_BOARDS + STM32F3-Discovery STM32F3xx_Nucleo_32 STM32F3xx_Nucleo_144 STM32F3xx-Nucleo + STM32F3348-Discovery STM32303C_EVAL STM32303E_EVAL STM32373C_EVAL +) +set(BSP_F3_COMPONENTS + cs42l52 cs43l22 hx8347d hx8347g hx8347i ili9320 ili9325 ili9328 l3gd20 + lsm303dlhc spfd5408 st7735 stts751 +) +set(BSP_F3_SOURCES_STM32F3_Discovery accelerometer gyroscope) +set(BSP_F3_SOURCES_STM32303C_EVAL audio eeprom lcd sd tsensor) +set(BSP_F3_SOURCES_STM32303E_EVAL audio eeprom lcd sd tsensor) +set(BSP_F3_SOURCES_STM32373C_EVAL audio eeprom lcd sd tsensor) +set(BSP_F3_DEVICE_STM32F3_Discovery F303VC) +set(BSP_F3_DEVICE_STM32F3348_Discovery F334C8) +set(BSP_F3_DEVICE_STM32303C_EVAL F303VC) +set(BSP_F3_DEVICE_STM32303E_EVAL F303VE) +set(BSP_F3_DEVICE_STM32373C_EVAL F373VC) + +### F4 ### +set(BSP_F4_BOARDS + STM32F4-Discovery STM32F4xx_Nucleo_144 STM32F4xx-Nucleo STM32F401-Discovery + STM32F411E-Discovery STM32F413H-Discovery STM32F429I-Discovery + STM324x9I_EVAL STM324xG_EVAL STM32412G-Discovery STM32446E_EVAL + STM32469I_EVAL STM32469I-Discovery +) +set(BSP_F4_COMPONENTS + ampire480272 ampire640480 cs43l22 exc7200 ft6x06 ili9325 ili9341 l3gd20 + lis3dsh lis302dl ls016b8uy lsm303dlhc mfxstm32l152 n25q128a n25q256a + n25q512a otm8009a ov2640 s5k5cag s25fl512s st7735 st7789h2 stmpe811 + stmpe1600 ts3510 wm8994 +) +set(BSP_F4_SOURCES_STM32F4_Discovery accelerometer audio) +set(BSP_F4_SOURCES_STM32F401_Discovery accelerometer audio gyroscope) +set(BSP_F4_SOURCES_STM32F411E_Discovery accelerometer audio gyroscope) +set(BSP_F4_SOURCES_STM32F413H_Discovery audio lcd psram qspi sd ts) +set(BSP_F4_SOURCES_STM32F429I_Discovery eeprom gyroscope io lcd sdram ts) +set(BSP_F4_SOURCES_STM324x9I_EVAL audio camera eeprom io lcd nor sd sdram sram ts) +set(BSP_F4_SOURCES_STM324xG_EVAL audio camera eeprom io lcd sd sram ts) +set(BSP_F4_SOURCES_STM32412G_Discovery audio eeprom lcd qspi sd ts) +set(BSP_F4_SOURCES_STM3232446E_EVAL audio camera eeprom io lcd qspi sd sdram ts) +set(BSP_F4_SOURCES_STM32469I_EVAL audio camera eeprom io lcd nor qspi sd sdram sram ts) +set(BSP_F4_SOURCES_STM32469I_Discovery audio eeprom lcd qspi sd sdram ts) +set(BSP_F4_DEVICE_STM32F4_Discovery F407VG) +set(BSP_F4_DEVICE_STM32F401_Discovery F401VC) +set(BSP_F4_DEVICE_STM32F411E_Discovery F411VE) +set(BSP_F4_DEVICE_STM32F413H_Discovery F413ZH) +set(BSP_F4_DEVICE_STM32F429I_Discovery F429ZI) +set(BSP_F4_DEVICE_STM324x9I_EVAL F429NI) +set(BSP_F4_DEVICE_STM324xG_EVAL F407IG) +set(BSP_F4_DEVICE_STM32412G_Discovery F412ZG) +set(BSP_F4_DEVICE_STM32446E_EVAL F446ZE) +set(BSP_F4_DEVICE_STM32469I_EVAL F469NI) +set(BSP_F4_DEVICE_STM32469I_Discovery F469NI) + +### F7 ### +set(BSP_F7_BOARDS + STM32F7xx_Nucleo_144 STM32F723E-Discovery STM32F769I_EVAL + STM32F769I-Discovery STM32F7308-Discovery STM32F7508-Discovery + STM32746G-Discovery STM32756G_EVAL +) +set(BSP_F7_COMPONENTS + adv7533 ampire480272 ampire640480 exc7200 ft6x06 ft5336 mfxstm32l152 + mx25l512 n25q128a n25q512a otm8009a ov5640 ov9655 rk043fn48h s5k5cag st7735 + st7789h2 stmpe811 ts3510 wm8994 +) +set(BSP_F7_SOURCES_STM32F723E_Discovery audio lcd psram qspi ts) +set(BSP_F7_SOURCES_STM32F769I_EVAL audio camera eeprom io lcd nor qspi sd sdram sram ts) +set(BSP_F7_SOURCES_STM32F769I_Discovery audio eeprom lcd qspi sd sdram ts) +set(BSP_F7_SOURCES_STM32F7308_Discovery audio lcd psram qspi ts) +set(BSP_F7_SOURCES_STM32F7508_Discovery audio camera eeprom lcd qspi sd sdram ts) +set(BSP_F7_SOURCES_STM32746G_Discovery audio camera eeprom lcd qspi sd sdram ts) +set(BSP_F7_SOURCES_STM32756G_EVAL audio camera eeprom io lcd nor qspi sd sdram sram ts) +set(BSP_F7_DEVICE_STM32F723E_Discovery F723IE) +set(BSP_F7_DEVICE_STM32F769I_EVAL F769NI) +set(BSP_F7_DEVICE_STM32F769I_Discovery F769NI) +set(BSP_F7_DEVICE_STM32F7308_Discovery F730I8) +set(BSP_F7_DEVICE_STM32F7508_Discovery F750N8) +set(BSP_F7_DEVICE_STM32746G_Discovery F746NG) +set(BSP_F7_DEVICE_STM32756G_EVAL F756NG) + +### G0 ### +set(BSP_G0_BOARDS + STM32G0xx_Nucleo STM32G0xx_Nucleo_32 STM32G071B-Discovery STM32G081B_EVAL + STM32G0316-Discovery +) +set(BSP_G0_COMPONENTS + hx8347d ina230 sn65dp141 ssd1315 st7735 stlm75 tusb546 +) +set(BSP_G0_DIR_STM32G0316_Discovery STM32G0316-DISCO) +set(BSP_G0_SOURCES_STM32G071B_Discovery lcd pwr pwrmon) +set(BSP_G0_SOURCES_STM32G081B_EVAL lcd mux pwr sd tsensor) +set(BSP_G0_DEVICE_STM32G071B_Discovery G071RB) +set(BSP_G0_DEVICE_STM32G081B_EVAL G081RB) +set(BSP_G0_DEVICE_STM32G0316_Discovery G031J6) + +### G4 ### +set(BSP_G4_BOARDS + B-G474E-DPOW1 STM32G4xx_Nucleo STM32G474E-EVAL +) +set(BSP_G4_COMPONENTS + hx8347d mfxstm32l152 mt25ql512abb st7735 stts751 wm8994 +) +set(BSP_G4_SOURCES_B-G474E-DPOW1 usbpd_pwr) +set(BSP_G4_SOURCES_STM32G481B_EVAL audio bus env_sensor idd io lcd qspi sd smartcard sram usbpd_pwr) +set(BSP_G4_DEVICE_B_G474E_DPOW1 G474RE) +set(BSP_G4_DEVICE_STM32G474E_EVAL G474QE) + +### H7 ### +set(BSP_H7_BOARDS + STM32H7B3I-Discovery STM32H7B3I-EVAL STM32H7xx_Nucleo STM32H743I-EVAL + STM32H745I-Discovery STM32H747I-Discovery STM32H747I-EVAL + STM32H750B-Discovery +) +set(BSP_H7_COMPONENTS + adv7533 ampire480272 ampire640480 cs42l51 es_wifi exc7200 ft6x06 ft5336 + is42s16800j is42s32800g is42s32800j lan8742 m24lr64 mfxstm32l152 + mt25tl01g mt48lc4m32b2 mx25lm51245g otm8009a ov5640 ov9655 rk043fn48h + rk070er9427 s5k5cag st7735 stmpe811 ts3510 wm8994 +) +set(BSP_H7_DIR_STM32H7B3I_Discovery STM32H7B3I-DK) +set(BSP_H7_DIR_STM32H745I_Discovery STM32H745I-DISCO) +set(BSP_H7_DIR_STM32H747I_Discovery STM32H747I-DISCO) +set(BSP_H7_DIR_STM32H750B_Discovery STM32H750B-DK) +set(BSP_H7_SOURCES_STM32H7B3I_Discovery audio bus camera eeprom lcd ospi sd sdram ts) +set(BSP_H7_SOURCES_STM32H7B3I_EVAL audio bus camera eeprom io lcd nor ospi sd sdram sram ts) +set(BSP_H7_SOURCES_STM32H743I_EVAL audio bus eeprom io lcd nor qspi sd sdram sram ts) +set(BSP_H7_SOURCES_STM32H745I_Discovery audio bus lcd mmc qspi sdram ts) +set(BSP_H7_SOURCES_STM32H747I_Discovery audio bus camera lcd qspi sd sdram ts) +set(BSP_H7_SOURCES_STM32H747I_EVAL audio bus eeprom io lcd nor qspi sd sdram sram ts) +set(BSP_H7_SOURCES_STM32H750B_Discovery audio bus lcd mmc qspi sdram ts) +set(BSP_H7_DEVICE_STM32H7B3I_Discovery H7B3LI) +set(BSP_H7_DEVICE_STM32H7B3I_EVAL H7B3LI) +set(BSP_H7_DEVICE_STM32H743I_EVAL H743XI) +set(BSP_H7_DEVICE_STM32H745I_Discovery H745XI) +set(BSP_H7_DEVICE_STM32H747I_Discovery H747XI) +set(BSP_H7_DEVICE_STM32H747I_EVAL H743XI) +set(BSP_H7_DEVICE_STM32H750B_Discovery H750XB) + +### L0 ### +set(BSP_L0_BOARDS + STM32L0xx_Nucleo STM32L0xx_Nucleo_32 STM32L073Z_EVAL STM32L0538-Discovery +) +set(BSP_L0_COMPONENTS + gde021a1 hx8347d mfxstm32l152 st7735 stlm75 +) +set(BSP_L0_SOURCES_STM32L073Z_EVAL eeprom glass_lcd idd io lcd sd tsensor) +set(BSP_L0_SOURCES_STM32L0538_Discovery epd) +set(BSP_L0_DEVICE_STM32L073Z_EVAL L073VZ) +set(BSP_L0_DEVICE_STM32L0538_Discovery L053C8) + +### L1 ### +set(BSP_L1_BOARDS + STM32L1xx_Nucleo STM32L100C-Discovery STM32L152C-Discovery STM32L152D_EVAL +) +set(BSP_L1_COMPONENTS + cs43l22 hx8347d ili9320 ili9325 spfd5408 st7735 stlm75 +) +set(BSP_L1_SOURCES_STM32L152C_Discovery glass_lcd) +set(BSP_L1_SOURCES_STM32L152D_EVAL audio eeprom audio glass_lcd lcd nor sd sram tsensor) +set(BSP_L1_DEVICE_STM32L100C_Discovery L100RC) +set(BSP_L1_DEVICE_STM32L152C_Discovery L152RC) +set(BSP_L1_DEVICE_STM32L152D_EVAL L152ZD) + +### L4 ### +set(BSP_L4_BOARDS + STM32L475E-IOT01 STM32L4P5G-Discovery STM32L4R9I_EVAL STM32L4R9I-Discovery + STM32L4xx_Nucleo STM32L4xx_Nucleo_32 STM32L4xx_Nucleo_144 STM32L476G_EVAL + STM32L476G-Discovery STM32L496G-Discovery +) +set(BSP_L4_COMPONENTS + cs42l51 cs43l22 cy8c4014lqi ft3x67 ft6x06 ft5336 hts221 hx8347g hx8347i + iss66wvh8m8 l3gd20 lis3mdl lps22hb ls016b8uy lsm6dsl lsm303c lsm303dlhc + m24sr mfxstm32l152 mx25lm51245g mx25r6435f n25q128a n25q256a ov9655 + rk043fn48h st7735 st7789h2 stmpe811 stmpe1600 wm8994 +) +set(BSP_L4_SOURCES_B_L475E_IOT01 accelerometer gyro hsensor magneto psensor qspi tsensor iot01) +set(BSP_L4_SOURCES_STM32L4P5G_Discovery idd io lcd mmc ospi_nor psram ts) +set(BSP_L4_SOURCES_STM32L4R9I_EVAL audio dsi_lcd dsi_ts eeprom idd io nor ospi_nor ospi_ram rgb_ts sd sram) +set(BSP_L4_SOURCES_STM32L4R9I_Discovery audio camera idd io lcd ospi_nor psram sd ts) +set(BSP_L4_SOURCES_STM32L476G_EVAL audio eeprom glass_lcd idd io lcd nor qspi sd sram ts) +set(BSP_L4_SOURCES_STM32L476G_Discovery audio compass glass_lcd gyroscope qspi) +set(BSP_L4_SOURCES_STM32L496G_Discovery audio camera idd io lcd qspi sd sram ts) +set(BSP_L4_DIR_STM32L475E_IOT01 B-L475E-IOT01) +set(BSP_L4_DEVICE_STM32L475E_IOT01 L475VG) +set(BSP_L4_DEVICE_STM32L4P5G_Discovery L4P5AG) +set(BSP_L4_DEVICE_STM32L4R9I_EVAL L4R9AI) +set(BSP_L4_DEVICE_STM32L4R9I_Discovery L4R9AI) +set(BSP_L4_DEVICE_STM32L476G_EVAL L476ZG) +set(BSP_L4_DEVICE_STM32L476G_Discovery L476VG) +set(BSP_L4_DEVICE_STM32L496G_Discovery L496AG) + +### L5 ### +set(BSP_L5_BOARDS + STM32L552E_EVAL STM32L562E-Discovery STM32L5xx_Nucleo_144 +) +set(BSP_L5_COMPONENTS + cs42l51 ft6x06 hx8347i iss66wvh8m8 lsm6dso mfxstm32l152 mx25lm51245g + st7789h2 stmpe811 +) +set(BSP_L5_SOURCES_STM32L562E_Discovery audio bus idd lcd motion_sensor ospi sd ts usbpd_pwr) +set(BSP_L5_SOURCES_STM32L552E_EVAL audio bus idd io lcd ospi sd sram ts usbpd_pwr) +set(BSP_L5_DEVICE_STM32L562E_Discovery L562QE) +set(BSP_L5_DEVICE_STM32L552E_EVAL L552ZE) + +### MP1 ### +set(BSP_MP1_BOARDS + STM32MP15xx_DISCO STM32MP15xx_EVAL) +set(BSP_MP1_COMPONENTS ) +set(BSP_MP1_SOURCES_STM32MP15xx_DISCO bus stpmic1) +set(BSP_MP1_SOURCES_STM32MP15xx_EVAL bus stpmic1) + +### WB ### +set(BSP_WB_BOARDS + STM32WB15CC_Nucleo STM32WB55_Nucleo STM32WB55_USBDongle STM32WB5MM_Discovery +) +set(BSP_WB_COMPONENTS + ism330dhcx s25fl128s ssd1315 stts22h +) +set(BSP_WB_DIR_STM32WB5MM_Discovery STM32WB5MM-DK) +set(BSP_WB_SOURCES_STM32WB5MM_Discovery audio bus env_sensors env_sensors_ex lcd motion_sensors motion_sensors_ex qspi) +set(BSP_WB_DEVICE_STM32WB5MM_Discovery WB5MMG) + +### WL ### +set(BSP_WL_BOARDS + STM32WLxx_Nucleo +) + + + +if(NOT BSP_FIND_COMPONENTS) + set(BSP_FIND_COMPONENTS ${STM32_SUPPORTED_FAMILIES_LONG_NAME}) +endif() + +if(STM32H7 IN_LIST BSP_FIND_COMPONENTS) + list(REMOVE_ITEM BSP_FIND_COMPONENTS STM32H7) + list(APPEND BSP_FIND_COMPONENTS STM32H7_M7 STM32H7_M4) +endif() + +if(STM32WB IN_LIST BSP_FIND_COMPONENTS) + list(REMOVE_ITEM BSP_FIND_COMPONENTS STM32WB) + list(APPEND BSP_FIND_COMPONENTS STM32WB_M4) +endif() + +if(STM32WL IN_LIST BSP_FIND_COMPONENTS) + list(REMOVE_ITEM BSP_FIND_COMPONENTS STM32WL) + list(APPEND BSP_FIND_COMPONENTS STM32WL_M4 STM32WL_M0PLUS) +endif() + +if(STM32MP1 IN_LIST BSP_FIND_COMPONENTS) + list(REMOVE_ITEM BSP_FIND_COMPONENTS STM32MP1) + list(APPEND BSP_FIND_COMPONENTS STM32MP1_M4) +endif() + +list(REMOVE_DUPLICATES BSP_FIND_COMPONENTS) + +foreach(COMP ${BSP_FIND_COMPONENTS}) + string(TOLOWER ${COMP} COMP_L) + string(TOUPPER ${COMP} COMP_U) + + string(REGEX MATCH "^STM32([FGHLMUW]P?[0-9BL])([0-9A-Z][0-9M][A-Z][0-9A-Z])?_?(M0PLUS|M4|M7)?.*$" COMP_U ${COMP_U}) + if(NOT CMAKE_MATCH_1) + message(FATAL_ERROR "Unknown BSP component: ${COMP}") + endif() + + if(CMAKE_MATCH_3) + set(CORE ${CMAKE_MATCH_3}) + set(CORE_C "::${CORE}") + set(CORE_U "_${CORE}") + else() + unset(CORE) + unset(CORE_C) + unset(CORE_U) + endif() + + set(FAMILY ${CMAKE_MATCH_1}) + string(TOLOWER ${FAMILY} FAMILY_L) + + if((NOT STM32_CUBE_${FAMILY}_PATH) AND (DEFINED ENV{STM32_CUBE_${FAMILY}_PATH)) + set(STM32_CUBE_${FAMILY}_PATH $ENV{STM32_CUBE_${FAMILY}_PATH} CACHE PATH "Path to STM32Cube${FAMILY}") + message(STATUS "ENV STM32_CUBE_${FAMILY}_PATH specified, using STM32_CUBE_${FAMILY}_PATH: ${STM32_CUBE_${FAMILY}_PATH}") + endif() + + if(NOT STM32_CUBE_${FAMILY}_PATH) + set(STM32_CUBE_${FAMILY}_PATH /opt/STM32Cube${FAMILY} CACHE PATH "Path to STM32Cube${FAMILY}") + message(STATUS "No STM32_CUBE_${FAMILY}_PATH specified using default: ${STM32_CUBE_${FAMILY}_PATH}") + endif() + + set(BSP_${FAMILY}_PATH "${STM32_CUBE_${FAMILY}_PATH}/Drivers/BSP") + if(NOT EXISTS ${BSP_${FAMILY}_PATH}) + continue() + endif() + + set(BSP_${FAMILY}_INCLUDE "${BSP_${FAMILY}_PATH}/Components/Common") + + add_library(BSP::STM32::${FAMILY}${CORE_C} INTERFACE IMPORTED) + target_link_libraries(BSP::STM32::${FAMILY}${CORE_C} INTERFACE STM32::${FAMILY}${CORE_C}) + target_include_directories(BSP::STM32::${FAMILY}${CORE_C} INTERFACE "${BSP_${FAMILY}_PATH}/Components/Common") + + foreach(BOARD ${BSP_${FAMILY}_BOARDS}) + string(REPLACE "-" "_" BOARD_CANONICAL ${BOARD}) + string(TOLOWER ${BOARD_CANONICAL} BOARD_CANONICAL_L) + set(BOARD_DEVICE ${BSP_${FAMILY}_DEVICE_${BOARD_CANONICAL}}) + + stm32_get_cores(DEV_CORES FAMILY ${FAMILY} DEVICE ${BOARD_DEVICE}) + if(CORE AND (NOT ${CORE} IN_LIST DEV_CORES)) + continue() + endif() + + find_path(BSP_${BOARD_CANONICAL}_PATH + NAMES ${BOARD_CANONICAL_L}.h + PATHS "${BSP_${FAMILY}_PATH}/${BOARD}" "${BSP_${FAMILY}_PATH}/${BSP_${FAMILY}_DIR_${BOARD_CANONICAL}}" + NO_DEFAULT_PATH + ) + if (NOT EXISTS ${BSP_${BOARD_CANONICAL}_PATH}) + continue() + endif() + + add_library(BSP::STM32::${BOARD_CANONICAL}${CORE_C} INTERFACE IMPORTED) + target_link_libraries(BSP::STM32::${BOARD_CANONICAL}${CORE_C} INTERFACE BSP::STM32::${FAMILY}${CORE_C} CMSIS::STM32::${FAMILY}${CORE_C}) + target_include_directories(BSP::STM32::${BOARD_CANONICAL}${CORE_C} INTERFACE "${BSP_${BOARD_CANONICAL}_PATH}") + target_sources(BSP::STM32::${BOARD_CANONICAL}${CORE_C} INTERFACE "${BSP_${BOARD_CANONICAL}_PATH}/${BOARD_CANONICAL_L}.c") + + foreach(SRC ${BSP_${FAMILY}_SOURCES_${BOARD_CANONICAL}}) + target_sources(BSP::STM32::${BOARD_CANONICAL}${CORE_C} INTERFACE "${BSP_${BOARD_CANONICAL}_PATH}/${BOARD_CANONICAL_L}_${SRC}.c") + endforeach() + if(BSP_${FAMILY}_DEVICE_${BOARD_CANONICAL}) + target_link_libraries(BSP::STM32::${BOARD_CANONICAL}${CORE_C} INTERFACE CMSIS::STM32::${BSP_${FAMILY}_DEVICE_${BOARD_CANONICAL}}${CORE_C}) + endif() + endforeach() + + foreach(BCOMP ${BSP_${FAMILY}_COMPONENTS}) + string(TOLOWER ${BCOMP} BCOMP_L) + string(TOUPPER ${BCOMP} BCOMP_U) + + add_library(BSP::STM32::${FAMILY}${CORE_C}::${BCOMP_U} INTERFACE IMPORTED) + target_link_libraries(BSP::STM32::${FAMILY}${CORE_C}::${BCOMP_U} INTERFACE BSP::STM32::${FAMILY}${CORE_C} CMSIS::STM32::${FAMILY}${CORE_C}) + target_include_directories(BSP::STM32::${FAMILY}${CORE_C}::${BCOMP_U} INTERFACE "${BSP_${FAMILY}_PATH}/Components/${BCOMP}") + + find_file(BSP_${BOARD_CANONICAL}_${BCOMP}_SOURCE + NAMES ${BCOMP}.c + PATHS "${BSP_${FAMILY}_PATH}/Components/${BCOMP}" + NO_DEFAULT_PATH + ) + if (BSP_${BOARD_CANONICAL}_${BCOMP}_SOURCE) + target_sources(BSP::STM32::${FAMILY}${CORE_C}::${BCOMP_U} INTERFACE "${BSP_${BOARD_CANONICAL}_${BCOMP}_SOURCE}") + endif() + endforeach() + + set(BSP_${COMP}_FOUND TRUE) + + if(BSP_${COMP}_FOUND) + list(APPEND BSP_INCLUDE_DIRS "${BSP_${FAMILY}_INCLUDE}") + endif() +endforeach() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(BSP + REQUIRED_VARS BSP_INCLUDE_DIRS + FOUND_VAR BSP_FOUND + HANDLE_COMPONENTS +) diff --git a/cmake/FindCMSIS.cmake b/cmake/FindCMSIS.cmake new file mode 100644 index 0000000..fe5d5ef --- /dev/null +++ b/cmake/FindCMSIS.cmake @@ -0,0 +1,326 @@ +# For information about why and how of this file: https://cmake.org/cmake/help/latest/command/find_package.html + + + + +set(CMSIS_RTOS RTOS RTOS_V2) + +if(NOT CMSIS_FIND_COMPONENTS) + set(CMSIS_FIND_COMPONENTS ${STM32_SUPPORTED_FAMILIES_LONG_NAME}) +endif() + +if(STM32H7 IN_LIST CMSIS_FIND_COMPONENTS) + list(REMOVE_ITEM CMSIS_FIND_COMPONENTS STM32H7) + list(APPEND CMSIS_FIND_COMPONENTS STM32H7_M7 STM32H7_M4) +endif() + +if(STM32WB IN_LIST CMSIS_FIND_COMPONENTS) + list(REMOVE_ITEM CMSIS_FIND_COMPONENTS STM32WB) + list(APPEND CMSIS_FIND_COMPONENTS STM32WB_M4) +endif() + +if(STM32WL IN_LIST CMSIS_FIND_COMPONENTS) + list(REMOVE_ITEM CMSIS_FIND_COMPONENTS STM32WL) + list(APPEND CMSIS_FIND_COMPONENTS STM32WL_M4 STM32WL_M0PLUS) +endif() + +if(STM32MP1 IN_LIST CMSIS_FIND_COMPONENTS) + list(REMOVE_ITEM CMSIS_FIND_COMPONENTS STM32MP1) + list(APPEND CMSIS_FIND_COMPONENTS STM32MP1_M4) +endif() + +list(REMOVE_DUPLICATES CMSIS_FIND_COMPONENTS) + +# This section fills the RTOS or family components list +foreach(COMP ${CMSIS_FIND_COMPONENTS}) + string(TOLOWER ${COMP} COMP_L) + string(TOUPPER ${COMP} COMP) + + # Component is RTOS component + if(${COMP} IN_LIST CMSIS_RTOS) + list(APPEND CMSIS_FIND_COMPONENTS_RTOS ${COMP}) + continue() + endif() + + # Component is not RTOS component, so check whether it is a family component + string(REGEX MATCH "^STM32([FGHLMUW]P?[0-9BL])([0-9A-Z][0-9M][A-Z][0-9A-Z])?_?(M0PLUS|M4|M7)?.*$" COMP ${COMP}) + if(CMAKE_MATCH_1) + list(APPEND CMSIS_FIND_COMPONENTS_FAMILIES ${COMP}) + endif() +endforeach() + +if(NOT CMSIS_FIND_COMPONENTS_FAMILIES) + set(CMSIS_FIND_COMPONENTS_FAMILIES ${STM32_SUPPORTED_FAMILIES_LONG_NAME}) +endif() + +if(NOT CMSIS_FIND_COMPONENTS_RTOS) + set(CMSIS_FIND_COMPONENTS_RTOS ${CMSIS_RTOS}) +endif() + +message(STATUS "Search for CMSIS families: ${CMSIS_FIND_COMPONENTS_FAMILIES}") +message(STATUS "Search for CMSIS RTOS: ${CMSIS_FIND_COMPONENTS_RTOS}") + +include(stm32/devices) + +function(cmsis_generate_default_linker_script FAMILY DEVICE CORE) + if(CORE) + set(CORE_C "::${CORE}") + set(CORE_U "_${CORE}") + endif() + + set(OUTPUT_LD_FILE "${CMAKE_CURRENT_BINARY_DIR}/${DEVICE}${CORE_U}.ld") + + if(${FAMILY} STREQUAL MP1) + string(TOLOWER ${FAMILY} FAMILY_L) + find_file(CMSIS_${FAMILY}${CORE_U}_LD_SCRIPT + NAMES stm32mp15xx_m4.ld + PATHS "${CMSIS_${FAMILY}${CORE_U}_PATH}/Source/Templates/gcc/linker" + NO_DEFAULT_PATH + ) + add_custom_command(OUTPUT "${OUTPUT_LD_FILE}" + COMMAND ${CMAKE_COMMAND} + -E copy ${CMSIS_${FAMILY}${CORE_U}_LD_SCRIPT} ${OUTPUT_LD_FILE}) + else() + stm32_get_memory_info(FAMILY ${FAMILY} DEVICE ${DEVICE} CORE ${CORE} FLASH SIZE FLASH_SIZE ORIGIN FLASH_ORIGIN) + stm32_get_memory_info(FAMILY ${FAMILY} DEVICE ${DEVICE} CORE ${CORE} RAM SIZE RAM_SIZE ORIGIN RAM_ORIGIN) + stm32_get_memory_info(FAMILY ${FAMILY} DEVICE ${DEVICE} CORE ${CORE} CCRAM SIZE CCRAM_SIZE ORIGIN CCRAM_ORIGIN) + stm32_get_memory_info(FAMILY ${FAMILY} DEVICE ${DEVICE} CORE ${CORE} RAM_SHARE SIZE RAM_SHARE_SIZE ORIGIN RAM_SHARE_ORIGIN) + stm32_get_memory_info(FAMILY ${FAMILY} DEVICE ${DEVICE} CORE ${CORE} HEAP SIZE HEAP_SIZE) + stm32_get_memory_info(FAMILY ${FAMILY} DEVICE ${DEVICE} CORE ${CORE} STACK SIZE STACK_SIZE) + + add_custom_command(OUTPUT "${OUTPUT_LD_FILE}" + COMMAND ${CMAKE_COMMAND} + -DFLASH_ORIGIN="${FLASH_ORIGIN}" + -DRAM_ORIGIN="${RAM_ORIGIN}" + -DCCRAM_ORIGIN="${CCRAM_ORIGIN}" + -DRAM_SHARE_ORIGIN="${RAM_SHARE_ORIGIN}" + -DFLASH_SIZE="${FLASH_SIZE}" + -DRAM_SIZE="${RAM_SIZE}" + -DCCRAM_SIZE="${CCRAM_SIZE}" + -DRAM_SHARE_SIZE="${RAM_SHARE_SIZE}" + -DSTACK_SIZE="${STACK_SIZE}" + -DHEAP_SIZE="${HEAP_SIZE}" + -DLINKER_SCRIPT="${OUTPUT_LD_FILE}" + -P "${STM32_CMAKE_DIR}/stm32/linker_ld.cmake" + ) + endif() + add_custom_target(CMSIS_LD_${DEVICE}${CORE_U} DEPENDS "${OUTPUT_LD_FILE}") + add_dependencies(CMSIS::STM32::${DEVICE}${CORE_C} CMSIS_LD_${DEVICE}${CORE_U}) + stm32_add_linker_script(CMSIS::STM32::${DEVICE}${CORE_C} INTERFACE "${OUTPUT_LD_FILE}") +endfunction() + +foreach(COMP ${CMSIS_FIND_COMPONENTS_FAMILIES}) + string(TOLOWER ${COMP} COMP_L) + string(TOUPPER ${COMP} COMP) + + string(REGEX MATCH "^STM32([FGHLMUW]P?[0-9BL])([0-9A-Z][0-9M][A-Z][0-9A-Z])?_?(M0PLUS|M4|M7)?.*$" COMP ${COMP}) + # CMAKE_MATCH_ contains n'th subexpression + # CMAKE_MATCH_0 contains full match + + if((NOT CMAKE_MATCH_1) AND (NOT CMAKE_MATCH_2)) + message(FATAL_ERROR "Unknown CMSIS component: ${COMP}") + endif() + + if(CMAKE_MATCH_2) + set(FAMILY ${CMAKE_MATCH_1}) + set(STM_DEVICES "${CMAKE_MATCH_1}${CMAKE_MATCH_2}") + message(TRACE "FindCMSIS: full device name match for COMP ${COMP}, STM_DEVICES is ${STM_DEVICES}") + else() + set(FAMILY ${CMAKE_MATCH_1}) + stm32_get_devices_by_family(STM_DEVICES FAMILY ${FAMILY}) + message(TRACE "FindCMSIS: family only match for COMP ${COMP}, STM_DEVICES is ${STM_DEVICES}") + endif() + + if(CMAKE_MATCH_3) + set(CORE ${CMAKE_MATCH_3}) + set(CORE_C "::${CORE}") + set(CORE_U "_${CORE}") + set(CORE_Ucm "_c${CORE}") + string(TOLOWER ${CORE_Ucm} CORE_Ucm) + message(TRACE "FindCMSIS: core match in component name for COMP ${COMP}. CORE is ${CORE}") + else() + unset(CORE) + unset(CORE_C) + unset(CORE_U) + unset(CORE_Ucm) + endif() + + string(TOLOWER ${FAMILY} FAMILY_L) + + if((NOT STM32_CMSIS_${FAMILY}_PATH) AND (NOT STM32_CUBE_${FAMILY}_PATH) AND (DEFINED ENV{STM32_CUBE_${FAMILY}_PATH})) + # try to set path from environment variable. Note it could be ...-NOT-FOUND and it's fine + set(STM32_CUBE_${FAMILY}_PATH $ENV{STM32_CUBE_${FAMILY}_PATH} CACHE PATH "Path to STM32Cube${FAMILY}") + message(STATUS "ENV STM32_CUBE_${FAMILY}_PATH specified, using STM32_CUBE_${FAMILY}_PATH: ${STM32_CUBE_${FAMILY}_PATH}") + endif() + + if((NOT STM32_CMSIS_${FAMILY}_PATH) AND (NOT STM32_CUBE_${FAMILY}_PATH)) + set(STM32_CUBE_${FAMILY}_PATH /opt/STM32Cube${FAMILY} CACHE PATH "Path to STM32Cube${FAMILY}") + message(STATUS "Neither STM32_CUBE_${FAMILY}_PATH nor STM32_CMSIS_${FAMILY}_PATH specified using default STM32_CUBE_${FAMILY}_PATH: ${STM32_CUBE_${FAMILY}_PATH}") + endif() + + # search for Include/cmsis_gcc.h + find_path(CMSIS_${FAMILY}${CORE_U}_CORE_PATH + NAMES Include/cmsis_gcc.h + PATHS "${STM32_CMSIS_PATH}" "${STM32_CUBE_${FAMILY}_PATH}/Drivers/CMSIS" + NO_DEFAULT_PATH + ) + if (NOT CMSIS_${FAMILY}${CORE_U}_CORE_PATH) + message(VERBOSE "FindCMSIS: cmsis_gcc.h for ${FAMILY}${CORE_U} has not been found") + continue() + endif() + + # search for Include/stm32[XX]xx.h + find_path(CMSIS_${FAMILY}${CORE_U}_PATH + NAMES Include/stm32${FAMILY_L}xx.h + PATHS "${STM32_CMSIS_${FAMILY}_PATH}" "${STM32_CUBE_${FAMILY}_PATH}/Drivers/CMSIS/Device/ST/STM32${FAMILY}xx" + NO_DEFAULT_PATH + ) + if (NOT CMSIS_${FAMILY}${CORE_U}_PATH) + message(VERBOSE "FindCMSIS: stm32${FAMILY_L}xx.h for ${FAMILY}${CORE_U} has not been found") + continue() + endif() + list(APPEND CMSIS_INCLUDE_DIRS "${CMSIS_${FAMILY}${CORE_U}_CORE_PATH}/Include" "${CMSIS_${FAMILY}${CORE_U}_PATH}/Include") + + if(NOT CMSIS_${FAMILY}${CORE_U}_VERSION) + find_file(CMSIS_${FAMILY}${CORE_U}_PDSC + NAMES ARM.CMSIS.pdsc + PATHS "${CMSIS_${FAMILY}${CORE_U}_CORE_PATH}" + NO_DEFAULT_PATH + ) + if (NOT CMSIS_${FAMILY}${CORE_U}_PDSC) + set(CMSIS_${FAMILY}${CORE_U}_VERSION "0.0.0") + else() + file(STRINGS "${CMSIS_${FAMILY}${CORE_U}_PDSC}" VERSION_STRINGS REGEX "") + list(GET VERSION_STRINGS 0 STR) + string(REGEX MATCH "" MATCHED ${STR}) + set(CMSIS_${FAMILY}${CORE_U}_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}" CACHE INTERNAL "CMSIS STM32${FAMILY}${CORE_U} version") + endif() + endif() + + set(CMSIS_${COMP}_VERSION ${CMSIS_${FAMILY}${CORE_U}_VERSION}) + set(CMSIS_VERSION ${CMSIS_${COMP}_VERSION}) + + if(NOT (TARGET CMSIS::STM32::${FAMILY}${CORE_C})) + message(TRACE "FindCMSIS: creating library CMSIS::STM32::${FAMILY}${CORE_C}") + add_library(CMSIS::STM32::${FAMILY}${CORE_C} INTERFACE IMPORTED) + #STM32::${FAMILY}${CORE_C} contains compile options and is define in .cmake + target_link_libraries(CMSIS::STM32::${FAMILY}${CORE_C} INTERFACE STM32::${FAMILY}${CORE_C}) + target_include_directories(CMSIS::STM32::${FAMILY}${CORE_C} INTERFACE "${CMSIS_${FAMILY}${CORE_U}_CORE_PATH}/Include") + target_include_directories(CMSIS::STM32::${FAMILY}${CORE_C} INTERFACE "${CMSIS_${FAMILY}${CORE_U}_PATH}/Include") + endif() + + # search for system_stm32[XX]xx.c + find_file(CMSIS_${FAMILY}${CORE_U}_SYSTEM + NAMES system_stm32${FAMILY_L}xx.c + PATHS "${CMSIS_${FAMILY}${CORE_U}_PATH}/Source/Templates" + NO_DEFAULT_PATH + ) + list(APPEND CMSIS_SOURCES "${CMSIS_${FAMILY}${CORE_U}_SYSTEM}") + + if(NOT CMSIS_${FAMILY}${CORE_U}_SYSTEM) + message(VERBOSE "FindCMSIS: system_stm32${FAMILY_L}xx.c for ${FAMILY}${CORE_U} has not been found") + continue() + endif() + + set(STM_DEVICES_FOUND TRUE) + foreach(DEVICE ${STM_DEVICES}) + message(TRACE "FindCMSIS: Iterating DEVICE ${DEVICE}") + + stm32_get_cores(DEV_CORES FAMILY ${FAMILY} DEVICE ${DEVICE}) + if(CORE AND (NOT ${CORE} IN_LIST DEV_CORES)) + message(TRACE "FindCMSIS: skip device because CORE ${CORE} provided doesn't correspond to FAMILY ${FAMILY} DEVICE ${DEVICE}") + continue() + endif() + + stm32_get_chip_type(${FAMILY} ${DEVICE} TYPE) + string(TOLOWER ${DEVICE} DEVICE_L) + string(TOLOWER ${TYPE} TYPE_L) + + get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES) + if(NOT "ASM" IN_LIST languages) + message(STATUS "FindCMSIS: Not generating target for startup file and linker script because ASM language is not enabled") + continue() + endif() + + find_file(CMSIS_${FAMILY}${CORE_U}_${TYPE}_STARTUP + NAMES startup_stm32${TYPE_L}.s + startup_stm32${TYPE_L}${CORE_Ucm}.s + PATHS "${CMSIS_${FAMILY}${CORE_U}_PATH}/Source/Templates/gcc" + NO_DEFAULT_PATH + ) + list(APPEND CMSIS_SOURCES "${CMSIS_${FAMILY}${CORE_U}_${TYPE}_STARTUP}") + if(NOT CMSIS_${FAMILY}${CORE_U}_${TYPE}_STARTUP) + set(STM_DEVICES_FOUND FALSE) + message(VERBOSE "FindCMSIS: did not find file: startup_stm32${TYPE_L}.s or startup_stm32${TYPE_L}${CORE_Ucm}.s") + break() + endif() + + if(NOT (TARGET CMSIS::STM32::${TYPE}${CORE_C})) + message(TRACE "FindCMSIS: creating library CMSIS::STM32::${TYPE}${CORE_C}") + add_library(CMSIS::STM32::${TYPE}${CORE_C} INTERFACE IMPORTED) + target_link_libraries(CMSIS::STM32::${TYPE}${CORE_C} INTERFACE CMSIS::STM32::${FAMILY}${CORE_C} STM32::${TYPE}${CORE_C}) + target_sources(CMSIS::STM32::${TYPE}${CORE_C} INTERFACE "${CMSIS_${FAMILY}${CORE_U}_${TYPE}_STARTUP}") + target_sources(CMSIS::STM32::${TYPE}${CORE_C} INTERFACE "${CMSIS_${FAMILY}${CORE_U}_SYSTEM}") + endif() + + add_library(CMSIS::STM32::${DEVICE}${CORE_C} INTERFACE IMPORTED) + target_link_libraries(CMSIS::STM32::${DEVICE}${CORE_C} INTERFACE CMSIS::STM32::${TYPE}${CORE_C}) + cmsis_generate_default_linker_script(${FAMILY} ${DEVICE} "${CORE}") + endforeach() + + if(STM_DEVICES_FOUND) + set(CMSIS_${COMP}_FOUND TRUE) + message(DEBUG "CMSIS_${COMP}_FOUND TRUE") + else() + set(CMSIS_${COMP}_FOUND FALSE) + message(DEBUG "CMSIS_${COMP}_FOUND FALSE") + endif() + + foreach(RTOS_COMP ${CMSIS_FIND_COMPONENTS_RTOS}) + if (${RTOS_COMP} STREQUAL "RTOS_V2") + set(RTOS_COMP_VERSION "2") + else() + unset(RTOS_COMP_VERSION) + endif() + + find_path(CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_PATH + NAMES "cmsis_os${RTOS_COMP_VERSION}.h" + PATHS "${STM32_CUBE_${FAMILY}_PATH}/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_${RTOS_COMP}" + NO_DEFAULT_PATH + ) + if (NOT CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_PATH) + continue() + endif() + + find_file(CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_SOURCE + NAMES "cmsis_os${RTOS_COMP_VERSION}.c" + PATHS "${STM32_CUBE_${FAMILY}_PATH}/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_${RTOS_COMP}" + NO_DEFAULT_PATH + ) + if (NOT CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_SOURCE) + continue() + endif() + + if(NOT (TARGET CMSIS::STM32::${FAMILY}${CORE_C}::${RTOS_COMP})) + add_library(CMSIS::STM32::${FAMILY}${CORE_C}::${RTOS_COMP} INTERFACE IMPORTED) + target_link_libraries(CMSIS::STM32::${FAMILY}${CORE_C}::${RTOS_COMP} INTERFACE CMSIS::STM32::${FAMILY}${CORE_C}) + target_include_directories(CMSIS::STM32::${FAMILY}${CORE_C}::${RTOS_COMP} INTERFACE "${CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_PATH}") + target_sources(CMSIS::STM32::${FAMILY}${CORE_C}::${RTOS_COMP} INTERFACE "${CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_SOURCE}") + endif() + + list(APPEND CMSIS_SOURCES "${CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_SOURCE}") + list(APPEND CMSIS_INCLUDE_DIRS "${CMSIS_${FAMILY}${CORE_U}_${RTOS_COMP}_PATH}") + set(CMSIS_${RTOS_COMP}_FOUND TRUE) + endforeach() + + list(REMOVE_DUPLICATES CMSIS_INCLUDE_DIRS) + list(REMOVE_DUPLICATES CMSIS_SOURCES) +endforeach() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(CMSIS + REQUIRED_VARS CMSIS_INCLUDE_DIRS CMSIS_SOURCES + FOUND_VAR CMSIS_FOUND + VERSION_VAR CMSIS_VERSION + HANDLE_COMPONENTS +) diff --git a/cmake/FindFreeRTOS.cmake b/cmake/FindFreeRTOS.cmake new file mode 100644 index 0000000..a7dbe25 --- /dev/null +++ b/cmake/FindFreeRTOS.cmake @@ -0,0 +1,259 @@ +# For information about why and how of this file: https://cmake.org/cmake/help/latest/command/find_package.html +set(FreeRTOS_PORTS ARM_CM0 ARM_CM3 ARM_CM3_MPU ARM_CM4_MPU ARM_CM4F ARM_CM7 ARM_CM7_MPU ARM_CM23 ARM_CM23_NTZ ARM_CM33 ARM_CM33_NTZ) +set(FreeRTOS_armv8_PORTS ARM_CM23_NTZ ARM_CM33_NTZ ARM_CM23 ARM_CM33) +set(FreeRTOS_armv8_trustZone_PORTS ARM_CM23 ARM_CM33) + +if(NOT FreeRTOS_FIND_COMPONENTS) + set(FreeRTOS_FIND_COMPONENTS ${FreeRTOS_PORTS}) +endif() +list(REMOVE_DUPLICATES FreeRTOS_FIND_COMPONENTS) + +if((NOT FREERTOS_PATH) AND (DEFINED ENV{FREERTOS_PATH})) + set(FREERTOS_PATH $ENV{FREERTOS_PATH} CACHE PATH "Path to FreeRTOS") + message(STATUS "ENV FREERTOS_PATH specified, using FREERTOS_PATH: ${FREERTOS_PATH}") +endif() + +if(NOT FREERTOS_PATH) + set(DEFAULT_FREERTOS_PATH "/opt/FreeRTOS") + if(EXISTS ${DEFAULT_FREERTOS_PATH}) + set(FREERTOS_PATH ${DEFAULT_FREERTOS_PATH} CACHE PATH "Path to FreeRTOS") + message(STATUS "No FREERTOS_PATH specified using default: ${DEFAULT_FREERTOS_PATH}") + else() + message(STATUS + "No FreeRTOS folder found at default location ${DEFAULT_FREERTOS_PATH}. " + "Leaving empty.." + ) + endif() +endif() + +if(STM32H7 IN_LIST FreeRTOS_FIND_COMPONENTS) + list(REMOVE_ITEM FreeRTOS_FIND_COMPONENTS STM32H7) + list(APPEND FreeRTOS_FIND_COMPONENTS STM32H7_M7 STM32H7_M4) +endif() + +if(STM32WB IN_LIST BSP_FIND_COMPONENTS) + list(REMOVE_ITEM FreeRTOS_FIND_COMPONENTS STM32WB) + list(APPEND FreeRTOS_FIND_COMPONENTS STM32WB_M4) +endif() + +if(STM32WL IN_LIST BSP_FIND_COMPONENTS) + list(REMOVE_ITEM FreeRTOS_FIND_COMPONENTS STM32WL) + list(APPEND FreeRTOS_FIND_COMPONENTS STM32WL_M4 STM32WL_M0PLUS) +endif() + +# This section fills the family and ports components list +foreach(COMP ${FreeRTOS_FIND_COMPONENTS}) + string(TOUPPER ${COMP} COMP) + string(REGEX MATCH "^STM32([FGHLMUW]P?[0-9BL])([0-9A-Z][0-9M][A-Z][0-9A-Z])?_?(M0PLUS|M4|M7)?.*$" FAMILY_COMP ${COMP}) + # Valid family component, so add it (e.g. STM32H7) + if(CMAKE_MATCH_1) + list(APPEND FreeRTOS_FIND_COMPONENTS_FAMILIES ${FAMILY_COMP}) + continue() + endif() + # Was not a family component, so add it to the port list + list(APPEND FreeRTOS_FIND_COMPONENTS_PORTS ${COMP}) +endforeach() + +if(NOT FreeRTOS_FIND_COMPONENTS_PORTS) + set(FreeRTOS_FIND_COMPONENTS_PORTS ${FreeRTOS_PORTS}) +endif() + +list(REMOVE_DUPLICATES FreeRTOS_FIND_COMPONENTS) +list(REMOVE_DUPLICATES FreeRTOS_FIND_COMPONENTS_PORTS) +list(REMOVE_DUPLICATES FreeRTOS_FIND_COMPONENTS_FAMILIES) + +set(FreeRTOS_HEAPS 1 2 3 4 5) + +macro(stm32_find_freertos FreeRTOS_NAMESPACE FREERTOS_PATH) + find_path(FreeRTOS_COMMON_INCLUDE + NAMES FreeRTOS.h + PATHS "${FREERTOS_PATH}" "${FREERTOS_PATH}/FreeRTOS" + PATH_SUFFIXES "Source/include" "include" + NO_DEFAULT_PATH + ) + + if(NOT FreeRTOS_COMMON_INCLUDE) + message(WARNING "FreeRTOS common include path not found, build might fail") + endif() + + list(APPEND FreeRTOS_INCLUDE_DIRS "${FreeRTOS_COMMON_INCLUDE}") + + find_path(FreeRTOS_SOURCE_DIR + NAMES tasks.c + PATHS "${FREERTOS_PATH}" "${FREERTOS_PATH}/FreeRTOS" + PATH_SUFFIXES "Source" + NO_DEFAULT_PATH + ) + if(NOT (TARGET FreeRTOS)) + add_library(FreeRTOS INTERFACE IMPORTED) + target_sources(FreeRTOS INTERFACE + "${FreeRTOS_SOURCE_DIR}/tasks.c" + "${FreeRTOS_SOURCE_DIR}/list.c" + "${FreeRTOS_SOURCE_DIR}/queue.c" + ) + target_include_directories(FreeRTOS INTERFACE "${FreeRTOS_COMMON_INCLUDE}") + endif() + + if(NOT (TARGET ${FreeRTOS_NAMESPACE}::Coroutine)) + add_library(${FreeRTOS_NAMESPACE}::Coroutine INTERFACE IMPORTED) + target_sources(${FreeRTOS_NAMESPACE}::Coroutine INTERFACE "${FreeRTOS_SOURCE_DIR}/croutine.c") + target_link_libraries(${FreeRTOS_NAMESPACE}::Coroutine INTERFACE FreeRTOS) + endif() + + if(NOT (TARGET ${FreeRTOS_NAMESPACE}::EventGroups)) + add_library(${FreeRTOS_NAMESPACE}::EventGroups INTERFACE IMPORTED) + target_sources(${FreeRTOS_NAMESPACE}::EventGroups INTERFACE "${FreeRTOS_SOURCE_DIR}/event_groups.c") + target_link_libraries(${FreeRTOS_NAMESPACE}::EventGroups INTERFACE FreeRTOS) + endif() + + if(NOT (TARGET ${FreeRTOS_NAMESPACE}::StreamBuffer)) + add_library(${FreeRTOS_NAMESPACE}::StreamBuffer INTERFACE IMPORTED) + target_sources(${FreeRTOS_NAMESPACE}::StreamBuffer INTERFACE "${FreeRTOS_SOURCE_DIR}/stream_buffer.c") + target_link_libraries(${FreeRTOS_NAMESPACE}::StreamBuffer INTERFACE FreeRTOS) + endif() + + if(NOT (TARGET ${FreeRTOS_NAMESPACE}::Timers)) + add_library(${FreeRTOS_NAMESPACE}::Timers INTERFACE IMPORTED) + target_sources(${FreeRTOS_NAMESPACE}::Timers INTERFACE "${FreeRTOS_SOURCE_DIR}/timers.c") + target_link_libraries(${FreeRTOS_NAMESPACE}::Timers INTERFACE FreeRTOS) + endif() + + foreach(HEAP ${FreeRTOS_HEAPS}) + if(NOT (TARGET ${FreeRTOS_NAMESPACE}::Heap::${HEAP})) + add_library(${FreeRTOS_NAMESPACE}::Heap::${HEAP} INTERFACE IMPORTED) + target_sources(${FreeRTOS_NAMESPACE}::Heap::${HEAP} INTERFACE "${FreeRTOS_SOURCE_DIR}/portable/MemMang/heap_${HEAP}.c") + target_link_libraries(${FreeRTOS_NAMESPACE}::Heap::${HEAP} INTERFACE FreeRTOS) + endif() + endforeach() + + foreach(PORT ${FreeRTOS_FIND_COMPONENTS_PORTS}) + if(${PORT} IN_LIST FreeRTOS_armv8_trustZone_PORTS) + set(ARMv8_NON_SECURE "::NON_SECURE") + endif() + + find_path(FreeRTOS_${PORT}_PATH + NAMES portmacro.h + PATHS "${FREERTOS_PATH}" "${FREERTOS_PATH}/FreeRTOS" + PATH_SUFFIXES + "portable/GCC/${PORT}" + "portable/GCC/${PORT}/r0p1" + "portable/GCC/${PORT}/non_secure" + "Source/portable/GCC/${PORT}" + "Source/portable/GCC/${PORT}/r0p1" + "Source/portable/GCC/${PORT}/non_secure" + NO_DEFAULT_PATH + ) + + if(NOT FreeRTOS_${PORT}_PATH) + message(WARNING "FreeRTOS port path not found, build might fail") + endif() + + list(APPEND FreeRTOS_INCLUDE_DIRS "${FreeRTOS_${PORT}_PATH}") + + find_file(FreeRTOS_${PORT}_SOURCE + NAMES port.c + PATHS "${FreeRTOS_${PORT}_PATH}" + NO_DEFAULT_PATH + ) + if(NOT (TARGET ${FreeRTOS_NAMESPACE}::${PORT}${ARMv8_NON_SECURE})) + add_library(${FreeRTOS_NAMESPACE}::${PORT}${ARMv8_NON_SECURE} INTERFACE IMPORTED) + target_link_libraries(${FreeRTOS_NAMESPACE}::${PORT}${ARMv8_NON_SECURE} INTERFACE FreeRTOS) + target_sources(${FreeRTOS_NAMESPACE}::${PORT}${ARMv8_NON_SECURE} INTERFACE "${FreeRTOS_${PORT}_SOURCE}") + target_include_directories(${FreeRTOS_NAMESPACE}::${PORT}${ARMv8_NON_SECURE} INTERFACE "${FreeRTOS_${PORT}_PATH}") + message(trace "FindFreeRTOS: creating target ${FreeRTOS_NAMESPACE}::${PORT}${ARMv8_NON_SECURE}") + + # armv8-m needs additional file even if using "No Trust Zone" port + if(${PORT} IN_LIST FreeRTOS_armv8_PORTS) + target_sources(${FreeRTOS_NAMESPACE}::${PORT}${ARMv8_NON_SECURE} INTERFACE "${FreeRTOS_${PORT}_PATH}/portasm.c") + endif() + + if(${PORT} IN_LIST FreeRTOS_armv8_trustZone_PORTS) + # create the secure target + add_library(${FreeRTOS_NAMESPACE}::${PORT}::SECURE INTERFACE IMPORTED) + # ::SECURE doesn't link FreeRTOS like ::NON_SECURE does + target_sources(${FreeRTOS_NAMESPACE}::${PORT}::SECURE INTERFACE "${FreeRTOS_${PORT}_PATH}/../secure/secure_context.c" + "${FreeRTOS_${PORT}_PATH}/../secure/secure_context_port.c" + "${FreeRTOS_${PORT}_PATH}/../secure/secure_heap.c" + "${FreeRTOS_${PORT}_PATH}/../secure/secure_init.c") + message(trace "FindFreeRTOS: creating target ${FreeRTOS_NAMESPACE}::${PORT}::SECURE") + + # non-secure part needs declaratation from secure includes + target_include_directories(${FreeRTOS_NAMESPACE}::${PORT}${ARMv8_NON_SECURE} INTERFACE "${FreeRTOS_${PORT}_PATH}/../secure") + # secure part needs declaratation from non-secure includes and common freeRTOS includes + target_include_directories(${FreeRTOS_NAMESPACE}::${PORT}::SECURE INTERFACE "${FreeRTOS_${PORT}_PATH}" + "${FreeRTOS_COMMON_INCLUDE}") + endif() + endif() + + if(FreeRTOS_${PORT}_PATH AND + FreeRTOS_${PORT}_SOURCE AND + FreeRTOS_COMMON_INCLUDE AND + FreeRTOS_SOURCE_DIR) + set(FreeRTOS_${PORT}_FOUND TRUE) + else() + set(FreeRTOS_${PORT}_FOUND FALSE) + endif() + endforeach() +endmacro() + +message(STATUS "Search for FreeRTOS ports: ${FreeRTOS_FIND_COMPONENTS_PORTS}") + +if(NOT FreeRTOS_FIND_COMPONENTS_FAMILIES) + stm32_find_freertos(FreeRTOS ${FREERTOS_PATH}) +else() + message(STATUS "Search for FreeRTOS families: ${FreeRTOS_FIND_COMPONENTS_FAMILIES}") + + foreach(COMP ${FreeRTOS_FIND_COMPONENTS_FAMILIES}) + string(TOLOWER ${COMP} COMP_L) + string(TOUPPER ${COMP} COMP) + + string(REGEX MATCH "^STM32([FGHLMUW]P?[0-9BL])([0-9A-Z][0-9M][A-Z][0-9A-Z])?_?(M0PLUS|M4|M7)?.*$" COMP ${COMP}) + + if((NOT CMAKE_MATCH_1) AND (NOT CMAKE_MATCH_2)) + message(FATAL_ERROR "Unknown FreeRTOS component: ${COMP}") + endif() + + if(CMAKE_MATCH_2) + set(FAMILY ${CMAKE_MATCH_1}) + set(STM_DEVICES "${CMAKE_MATCH_1}${CMAKE_MATCH_2}") + else() + set(FAMILY ${CMAKE_MATCH_1}) + stm32_get_devices_by_family(STM_DEVICES FAMILY ${FAMILY}) + endif() + + if(CMAKE_MATCH_3) + set(CORE ${CMAKE_MATCH_3}) + set(CORE_C "::${CORE}") + set(CORE_U "_${CORE}") + else() + unset(CORE) + unset(CORE_C) + unset(CORE_U) + endif() + + string(TOLOWER ${FAMILY} FAMILY_L) + if(NOT STM32_CUBE_${FAMILY}_PATH) + set(STM32_CUBE_${FAMILY}_PATH /opt/STM32Cube${FAMILY} CACHE PATH "Path to STM32Cube${FAMILY}") + message(STATUS "Did not specify STM32_CMSIS_${FAMILY}_PATH, using default STM32_CUBE_${FAMILY}_PATH: ${STM32_CUBE_${FAMILY}_PATH}") + endif() + + stm32_find_freertos(FreeRTOS::STM32::${FAMILY}${CORE_C} ${STM32_CUBE_${FAMILY}_PATH}/Middlewares/Third_Party/FreeRTOS) + foreach(PORT_COMP ${FreeRTOS_FIND_COMPONENTS_PORTS}) + if(FreeRTOS_${PORT_COMP}_PATH AND + FreeRTOS_${PORT_COMP}_SOURCE AND + FreeRTOS_COMMON_INCLUDE AND + FreeRTOS_SOURCE_DIR) + set(FreeRTOS_${COMP}_FOUND TRUE) + else() + set(FreeRTOS_${COMP}_FOUND FALSE) + endif() + endforeach() + endforeach() +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(FreeRTOS + REQUIRED_VARS FreeRTOS_INCLUDE_DIRS + FOUND_VAR FreeRTOS_FOUND + HANDLE_COMPONENTS +) diff --git a/cmake/FindHAL.cmake b/cmake/FindHAL.cmake new file mode 100644 index 0000000..7edaaf4 --- /dev/null +++ b/cmake/FindHAL.cmake @@ -0,0 +1,315 @@ +# For information about why and how of this file: https://cmake.org/cmake/help/latest/command/find_package.html + +# This function gets a list of hal_driver using a given prefix and suffix +# +# out_list_hal_drivers list of hal_drivers found +# hal_drivers_path path to the hal's drivers +# hal_driver_type hal_driver type to find (hal/ll/ex) +function(get_list_hal_drivers out_list_hal_drivers hal_drivers_path hal_driver_type) + #The pattern to retrieve a driver from a file name depends on the hal_driver_type field + if(${hal_driver_type} STREQUAL "hal" OR ${hal_driver_type} STREQUAL "ll") + #This regex match and capture a driver type (stm32xx_hal_(rcc).c or stm32xx_ll_(rcc).c => catches rcc) + set(file_pattern ".+_${hal_driver_type}_([a-z0-9]+)\\.c$") + elseif(${hal_driver_type} STREQUAL "ex") + #This regex match and capture a driver type (stm32xx_hal_(rcc)_ex.c => catches rcc) + set(file_pattern ".+_hal_([a-z0-9]+)_ex\\.c$") + else() + message(FATAL_ERROR "the inputed hal_driver_type(${hal_driver_type}) is not valid.") + endif() + + #Retrieving all the .c files from hal_drivers_path + file(GLOB filtered_files + RELATIVE "${hal_drivers_path}/Src" + "${hal_drivers_path}/Src/*.c") + # For all matched .c files keep only those with a driver name pattern (e.g. stm32xx_hal_rcc.c) + list(FILTER filtered_files INCLUDE REGEX ${file_pattern}) + # From the files names keep only the driver type part using the regex (stm32xx_hal_(rcc).c or stm32xx_ll_(rcc).c => catches rcc) + list(TRANSFORM filtered_files REPLACE ${file_pattern} "\\1") + #Making a return by reference by seting the output variable to PARENT_SCOPE + set(${out_list_hal_drivers} ${filtered_files} PARENT_SCOPE) +endfunction() + +################################################################################ +# Checking the parameters provided to the find_package(HAL ...) call +# The expected parameters are families and or drivers in *any orders* +# Families are valid if on the list of known families. +# Drivers are valid if on the list of valid driver of any family. For this +# reason the requested families must be processed in two steps +# - Step 1 : Checking all the requested families +# - Step 2 : Generating all the valid drivers from requested families +# - Step 3 : Checking the other requested components (Expected to be drivers) +################################################################################ +# Step 1 : Checking all the requested families +foreach(COMP ${HAL_FIND_COMPONENTS}) + string(TOUPPER ${COMP} COMP_U) + string(REGEX MATCH "^STM32([FGHLMUW]P?[0-9BL])([0-9A-Z][0-9M][A-Z][0-9A-Z])?_?(M0PLUS|M4|M7)?.*$" COMP_U ${COMP_U}) + if(CMAKE_MATCH_1) #Matches the family part of the provided STM32[..] component + list(APPEND HAL_FIND_COMPONENTS_FAMILIES ${COMP}) + message(TRACE "FindHAL: append COMP ${COMP} to HAL_FIND_COMPONENTS_FAMILIES") + else() + list(APPEND HAL_FIND_COMPONENTS_UNHANDLED ${COMP}) + endif() +endforeach() + +# If no family requested look for all families +if(NOT HAL_FIND_COMPONENTS_FAMILIES) + set(HAL_FIND_COMPONENTS_FAMILIES ${STM32_SUPPORTED_FAMILIES_LONG_NAME}) +endif() + +# Step 2 : Generating all the valid drivers from requested families +foreach(family_comp ${HAL_FIND_COMPONENTS_FAMILIES}) + string(TOUPPER ${family_comp} family_comp) + string(REGEX MATCH "^STM32([FGHLMUW]P?[0-9BL])([0-9A-Z][0-9M][A-Z][0-9A-Z])?_?(M0PLUS|M4|M7)?.*$" family_comp ${family_comp}) + if(CMAKE_MATCH_1) #Matches the family part of the provided STM32[..] component + set(FAMILY ${CMAKE_MATCH_1}) + endif() + find_path(HAL_${FAMILY}_PATH + NAMES Inc/stm32${FAMILY_L}xx_hal.h + PATHS "${STM32_HAL_${FAMILY}_PATH}" "${STM32_CUBE_${FAMILY}_PATH}/Drivers/STM32${FAMILY}xx_HAL_Driver" + NO_DEFAULT_PATH + ) + if(NOT HAL_${FAMILY}_PATH) + message(FATAL_ERROR "could not find HAL for family ${FAMILY}") + else() + set(HAL_${family_comp}_FOUND TRUE) + endif() + if(CMAKE_MATCH_1) #Matches the family part of the provided STM32[..] component + get_list_hal_drivers(HAL_DRIVERS_${FAMILY} ${HAL_${FAMILY}_PATH} "hal") + get_list_hal_drivers(HAL_EX_DRIVERS_${FAMILY} ${HAL_${FAMILY}_PATH} "ex") + get_list_hal_drivers(HAL_LL_DRIVERS_${FAMILY} ${HAL_${FAMILY}_PATH} "ll") + list(APPEND HAL_DRIVERS ${HAL_DRIVERS_${FAMILY}}) + list(APPEND HAL_LL_DRIVERS ${HAL_LL_DRIVERS_${FAMILY}}) + else() + endif() +endforeach() +list(REMOVE_DUPLICATES HAL_DRIVERS) +list(REMOVE_DUPLICATES HAL_LL_DRIVERS) + +# Step 3 : Checking the other requested components (Expected to be drivers) +foreach(COMP ${HAL_FIND_COMPONENTS_UNHANDLED}) + string(TOLOWER ${COMP} COMP_L) + + if(${COMP_L} IN_LIST HAL_DRIVERS) + list(APPEND HAL_FIND_COMPONENTS_DRIVERS ${COMP}) + message(TRACE "FindHAL: append COMP ${COMP} to HAL_FIND_COMPONENTS_DRIVERS") + continue() + endif() + string(REGEX REPLACE "^ll_" "" COMP_L ${COMP_L}) + if(${COMP_L} IN_LIST HAL_LL_DRIVERS) + list(APPEND HAL_FIND_COMPONENTS_DRIVERS_LL ${COMP}) + message(TRACE "FindHAL: append COMP ${COMP} to HAL_FIND_COMPONENTS_DRIVERS_LL") + continue() + endif() + message(FATAL_ERROR "FindHAL: unknown HAL component: ${COMP}") +endforeach() + + +if(STM32H7 IN_LIST HAL_FIND_COMPONENTS_FAMILIES) + list(REMOVE_ITEM HAL_FIND_COMPONENTS_FAMILIES STM32H7) + list(APPEND HAL_FIND_COMPONENTS_FAMILIES STM32H7_M7 STM32H7_M4) +endif() + +if(STM32WB IN_LIST HAL_FIND_COMPONENTS_FAMILIES) + list(REMOVE_ITEM HAL_FIND_COMPONENTS_FAMILIES STM32WB) + list(APPEND HAL_FIND_COMPONENTS_FAMILIES STM32WB_M4) +endif() + +if(STM32WL IN_LIST HAL_FIND_COMPONENTS_FAMILIES) + list(REMOVE_ITEM HAL_FIND_COMPONENTS_FAMILIES STM32WL) + list(APPEND HAL_FIND_COMPONENTS_FAMILIES STM32WL_M4 STM32WL_M0PLUS) +endif() + +if(STM32MP1 IN_LIST HAL_FIND_COMPONENTS_FAMILIES) + list(REMOVE_ITEM HAL_FIND_COMPONENTS_FAMILIES STM32MP1) + list(APPEND HAL_FIND_COMPONENTS_FAMILIES STM32MP1_M4) +endif() + +list(REMOVE_DUPLICATES HAL_FIND_COMPONENTS_FAMILIES) + +# when no explicit driver and driver_ll is given to find_component(HAL ) +# then search for all supported driver and driver_ll +if((NOT HAL_FIND_COMPONENTS_DRIVERS) AND (NOT HAL_FIND_COMPONENTS_DRIVERS_LL)) + set(HAL_FIND_COMPONENTS_DRIVERS ${HAL_DRIVERS}) + set(HAL_FIND_COMPONENTS_DRIVERS_LL ${HAL_LL_DRIVERS}) +endif() +list(REMOVE_DUPLICATES HAL_FIND_COMPONENTS_DRIVERS) +list(REMOVE_DUPLICATES HAL_FIND_COMPONENTS_DRIVERS_LL) + +message(STATUS "Search for HAL families: ${HAL_FIND_COMPONENTS_FAMILIES}") +message(STATUS "Search for HAL drivers: ${HAL_FIND_COMPONENTS_DRIVERS}") +message(STATUS "Search for HAL LL drivers: ${HAL_FIND_COMPONENTS_DRIVERS_LL}") + +foreach(COMP ${HAL_FIND_COMPONENTS_FAMILIES}) + string(TOUPPER ${COMP} COMP_U) + + string(REGEX MATCH "^STM32([FGHLMUW]P?[0-9BL])([0-9A-Z][0-9M][A-Z][0-9A-Z])?_?(M0PLUS|M4|M7)?.*$" COMP_U ${COMP_U}) + if(CMAKE_MATCH_3) + set(CORE ${CMAKE_MATCH_3}) + set(CORE_C "::${CORE}") + set(CORE_U "_${CORE}") + else() + unset(CORE) + unset(CORE_C) + unset(CORE_U) + endif() + + set(FAMILY ${CMAKE_MATCH_1}) + string(TOLOWER ${FAMILY} FAMILY_L) + + if((NOT STM32_HAL_${FAMILY}_PATH) AND (NOT STM32_CUBE_${FAMILY}_PATH) AND (DEFINED ENV{STM32_CUBE_${FAMILY}_PATH})) + set(STM32_CUBE_${FAMILY}_PATH $ENV{STM32_CUBE_${FAMILY}_PATH} CACHE PATH "Path to STM32Cube${FAMILY}") + message(STATUS "ENV STM32_CUBE_${FAMILY}_PATH specified, using STM32_CUBE_${FAMILY}_PATH: ${STM32_CUBE_${FAMILY}_PATH}") + endif() + + if((NOT STM32_HAL_${FAMILY}_PATH) AND (NOT STM32_CUBE_${FAMILY}_PATH)) + set(STM32_CUBE_${FAMILY}_PATH /opt/STM32Cube${FAMILY} CACHE PATH "Path to STM32Cube${FAMILY}") + message(STATUS "Neither STM32_CUBE_${FAMILY}_PATH nor STM32_HAL_${FAMILY}_PATH specified using default STM32_CUBE_${FAMILY}_PATH: ${STM32_CUBE_${FAMILY}_PATH}") + endif() + + #Checking HAL patch or release version + unset(VERSION_INFO) + find_file(PACKAGE_FILE NAMES package.xml PATHS ${STM32_CUBE_${FAMILY}_PATH}) + if(PACKAGE_FILE) + file(READ ${PACKAGE_FILE} PACKAGE_FILE_CONTENT) + string(REGEX MATCH "PackDescription Release=\"FW.${FAMILY}.([0-9.]+)\"( Patch=\"FW.${FAMILY}.([0-9.]+)\")?" VERSION_INFO ${PACKAGE_FILE_CONTENT}) + if(CMAKE_MATCH_3) # This is the "Patch" revision + set(HAL_${COMP}_VERSION ${CMAKE_MATCH_3}) + set(HAL_VERSION ${CMAKE_MATCH_3}) + else(CMAKE_MATCH_1) #This is the "Release" version + set(HAL_${COMP}_VERSION ${CMAKE_MATCH_1}) + set(HAL_VERSION ${CMAKE_MATCH_1}) + endif() + endif() + if(NOT VERSION_INFO) + message(STATUS "Could not read the HAL version from package.xml for ${COMP}") + endif() + + find_path(HAL_${FAMILY}_PATH + NAMES Inc/stm32${FAMILY_L}xx_hal.h + PATHS "${STM32_HAL_${FAMILY}_PATH}" "${STM32_CUBE_${FAMILY}_PATH}/Drivers/STM32${FAMILY}xx_HAL_Driver" + NO_DEFAULT_PATH + ) + if (NOT HAL_${FAMILY}_PATH) + message(DEBUG "Missing HAL_${FAMILY}_PATH path") + continue() + endif() + + find_path(HAL_${FAMILY}${CORE_U}_INCLUDE + NAMES stm32${FAMILY_L}xx_hal.h + PATHS "${HAL_${FAMILY}_PATH}/Inc" + NO_DEFAULT_PATH + ) + find_file(HAL_${FAMILY}${CORE_U}_SOURCE + NAMES stm32${FAMILY_L}xx_hal.c + PATHS "${HAL_${FAMILY}_PATH}/Src" + NO_DEFAULT_PATH + ) + + if ((NOT HAL_${FAMILY}${CORE_U}_INCLUDE) OR (NOT HAL_${FAMILY}${CORE_U}_SOURCE)) + set(HAL_${COMP}_FOUND FALSE) + message(DEBUG "FindHAL: did not find path to HAL /src or /inc dir") + continue() + endif() + + if(NOT (TARGET HAL::STM32::${FAMILY}${CORE_C})) + message(TRACE "FindHAL: creating library HAL::STM32::${FAMILY}${CORE_C}") + add_library(HAL::STM32::${FAMILY}${CORE_C} INTERFACE IMPORTED) + target_link_libraries(HAL::STM32::${FAMILY}${CORE_C} INTERFACE + STM32::${FAMILY}${CORE_C} + CMSIS::STM32::${FAMILY}${CORE_C}) + target_include_directories(HAL::STM32::${FAMILY}${CORE_C} INTERFACE "${HAL_${FAMILY}${CORE_U}_INCLUDE}") + target_sources(HAL::STM32::${FAMILY}${CORE_C} INTERFACE "${HAL_${FAMILY}${CORE_U}_SOURCE}") + endif() + + foreach(DRV_COMP ${HAL_FIND_COMPONENTS_DRIVERS}) + string(TOLOWER ${DRV_COMP} DRV_L) + string(TOUPPER ${DRV_COMP} DRV) + + if(NOT (DRV_L IN_LIST HAL_DRIVERS_${FAMILY})) + continue() + endif() + + find_file(HAL_${FAMILY}${CORE_U}_${DRV}_SOURCE + NAMES stm32${FAMILY_L}xx_hal_${DRV_L}.c + PATHS "${HAL_${FAMILY}_PATH}/Src" + NO_DEFAULT_PATH + ) + list(APPEND HAL_${FAMILY}${CORE_U}_SOURCES "${HAL_${FAMILY}_${DRV}_SOURCE}") + if(NOT HAL_${FAMILY}${CORE_U}_${DRV}_SOURCE) + message(WARNING "Cannot find ${DRV} driver for ${FAMILY}${CORE_U}") + set(HAL_${DRV_COMP}_FOUND FALSE) + continue() + endif() + + set(HAL_${DRV_COMP}_FOUND TRUE) + if(HAL_${FAMILY}${CORE_U}_${DRV}_SOURCE AND (NOT (TARGET HAL::STM32::${FAMILY}::${DRV}))) + message(TRACE "FindHAL: creating library HAL::STM32::${FAMILY}${CORE_C}::${DRV}") + add_library(HAL::STM32::${FAMILY}${CORE_C}::${DRV} INTERFACE IMPORTED) + target_link_libraries(HAL::STM32::${FAMILY}${CORE_C}::${DRV} INTERFACE HAL::STM32::${FAMILY}${CORE_C}) + target_sources(HAL::STM32::${FAMILY}${CORE_C}::${DRV} INTERFACE "${HAL_${FAMILY}${CORE_U}_${DRV}_SOURCE}") + endif() + + if(HAL_${FAMILY}${CORE_U}_${DRV}_SOURCE AND (${DRV_L} IN_LIST HAL_EX_DRIVERS_${FAMILY})) + find_file(HAL_${FAMILY}${CORE_U}_${DRV}_EX_SOURCE + NAMES stm32${FAMILY_L}xx_hal_${DRV_L}_ex.c + PATHS "${HAL_${FAMILY}_PATH}/Src" + NO_DEFAULT_PATH + ) + list(APPEND HAL_${FAMILY}${CORE_U}_SOURCES "${HAL_${FAMILY}${CORE_U}_${DRV}_EX_SOURCE}") + if(NOT HAL_${FAMILY}${CORE_U}_${DRV}_EX_SOURCE) + message(WARNING "Cannot find ${DRV}Ex driver for ${FAMILY}${CORE_U}") + endif() + + if((TARGET HAL::STM32::${FAMILY}${CORE_C}::${DRV}) AND (NOT (TARGET HAL::STM32::${FAMILY}${CORE_C}::${DRV}Ex))) + message(TRACE "FindHAL: creating library HAL::STM32::${FAMILY}${CORE_C}::${DRV}Ex") + add_library(HAL::STM32::${FAMILY}${CORE_C}::${DRV}Ex INTERFACE IMPORTED) + target_link_libraries(HAL::STM32::${FAMILY}${CORE_C}::${DRV}Ex INTERFACE HAL::STM32::${FAMILY}${CORE_C}::${DRV}) + target_sources(HAL::STM32::${FAMILY}${CORE_C}::${DRV}Ex INTERFACE "${HAL_${FAMILY}${CORE_U}_${DRV}_EX_SOURCE}") + endif() + endif() + endforeach() + + foreach(DRV_COMP ${HAL_FIND_COMPONENTS_DRIVERS_LL}) + string(TOLOWER ${DRV_COMP} DRV_L) + string(REGEX REPLACE "^ll_" "" DRV_L ${DRV_L}) + string(TOUPPER ${DRV_L} DRV) + + if(NOT (DRV_L IN_LIST HAL_LL_DRIVERS_${FAMILY})) + continue() + endif() + + find_file(HAL_${FAMILY}${CORE_U}_${DRV}_LL_SOURCE + NAMES stm32${FAMILY_L}xx_ll_${DRV_L}.c + PATHS "${HAL_${FAMILY}_PATH}/Src" + NO_DEFAULT_PATH + ) + list(APPEND HAL_${FAMILY}${CORE_U}_SOURCES "${HAL_${FAMILY}_${DRV}_LL_SOURCE}") + if(NOT HAL_${FAMILY}${CORE_U}_${DRV}_LL_SOURCE) + message(WARNING "Cannot find LL_${DRV} driver for ${FAMILY}${CORE_U}") + set(HAL_${DRV_COMP}_FOUND FALSE) + continue() + endif() + + set(HAL_${DRV_COMP}_FOUND TRUE) + if(HAL_${FAMILY}${CORE_U}_${DRV}_LL_SOURCE AND (NOT (TARGET HAL::STM32::${FAMILY}${CORE_C}::LL_${DRV}))) + message(TRACE "FindHAL: creating library HAL::STM32::${FAMILY}${CORE_C}::LL_${DRV}") + add_library(HAL::STM32::${FAMILY}${CORE_C}::LL_${DRV} INTERFACE IMPORTED) + target_include_directories(HAL::STM32::${FAMILY}${CORE_C}::LL_${DRV} INTERFACE "${HAL_${FAMILY}${CORE_U}_INCLUDE}") + target_sources(HAL::STM32::${FAMILY}${CORE_C}::LL_${DRV} INTERFACE "${HAL_${FAMILY}${CORE_U}_${DRV}_LL_SOURCE}") + endif() + endforeach() + + set(HAL_${COMP}_FOUND TRUE) + list(APPEND HAL_INCLUDE_DIRS "${HAL_${FAMILY}${CORE_U}_INCLUDE}") + list(APPEND HAL_SOURCES "${HAL_${FAMILY}${CORE_U}_SOURCES}") +endforeach() + +list(REMOVE_DUPLICATES HAL_INCLUDE_DIRS) +list(REMOVE_DUPLICATES HAL_SOURCES) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(HAL + REQUIRED_VARS HAL_INCLUDE_DIRS HAL_SOURCES + FOUND_VAR HAL_FOUND + HANDLE_COMPONENTS +) diff --git a/cmake/stm32/common.cmake b/cmake/stm32/common.cmake new file mode 100644 index 0000000..87851cb --- /dev/null +++ b/cmake/stm32/common.cmake @@ -0,0 +1,372 @@ +set(STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32F0 STM32F1 STM32F2 STM32F3 STM32F4 STM32F7 + STM32G0 STM32G4 + STM32H7_M4 STM32H7_M7 + STM32L0 STM32L1 STM32L4 STM32L5 + STM32U5 + STM32WB_M4 STM32WL_M4 STM32WL_M0PLUS + STM32MP1_M4 ) + +foreach(FAMILY ${STM32_SUPPORTED_FAMILIES_LONG_NAME}) + # append short names (F0, F1, H7_M4, ...) to STM32_SUPPORTED_FAMILIES_SHORT_NAME + string(REGEX MATCH "^STM32([FGHLMUW]P?[0-9BL])_?(M0PLUS|M4|M7)?" FAMILY ${FAMILY}) + list(APPEND STM32_SUPPORTED_FAMILIES_SHORT_NAME ${CMAKE_MATCH_1}) +endforeach() +list(REMOVE_DUPLICATES STM32_SUPPORTED_FAMILIES_SHORT_NAME) + +if(NOT STM32_TOOLCHAIN_PATH) + if(DEFINED ENV{STM32_TOOLCHAIN_PATH}) + message(STATUS "Detected toolchain path STM32_TOOLCHAIN_PATH in environmental variables: ") + message(STATUS "$ENV{STM32_TOOLCHAIN_PATH}") + set(STM32_TOOLCHAIN_PATH $ENV{STM32_TOOLCHAIN_PATH}) + else() + if(NOT CMAKE_C_COMPILER) + set(STM32_TOOLCHAIN_PATH "/usr") + message(STATUS "No STM32_TOOLCHAIN_PATH specified, using default: " ${STM32_TOOLCHAIN_PATH}) + else() + # keep only directory of compiler + get_filename_component(STM32_TOOLCHAIN_PATH ${CMAKE_C_COMPILER} DIRECTORY) + # remove the last /bin directory + get_filename_component(STM32_TOOLCHAIN_PATH ${STM32_TOOLCHAIN_PATH} DIRECTORY) + endif() + endif() + file(TO_CMAKE_PATH "${STM32_TOOLCHAIN_PATH}" STM32_TOOLCHAIN_PATH) +endif() + +if(NOT STM32_TARGET_TRIPLET) + set(STM32_TARGET_TRIPLET "arm-none-eabi") + message(STATUS "No STM32_TARGET_TRIPLET specified, using default: " ${STM32_TARGET_TRIPLET}) +endif() + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR arm) + +set(TOOLCHAIN_SYSROOT "${STM32_TOOLCHAIN_PATH}/${STM32_TARGET_TRIPLET}") +set(TOOLCHAIN_BIN_PATH "${STM32_TOOLCHAIN_PATH}/bin") +set(TOOLCHAIN_INC_PATH "${STM32_TOOLCHAIN_PATH}/${STM32_TARGET_TRIPLET}/include") +set(TOOLCHAIN_LIB_PATH "${STM32_TOOLCHAIN_PATH}/${STM32_TARGET_TRIPLET}/lib") + +find_program(CMAKE_OBJCOPY NAMES ${STM32_TARGET_TRIPLET}-objcopy HINTS ${TOOLCHAIN_BIN_PATH}) +find_program(CMAKE_OBJDUMP NAMES ${STM32_TARGET_TRIPLET}-objdump HINTS ${TOOLCHAIN_BIN_PATH}) +find_program(CMAKE_SIZE NAMES ${STM32_TARGET_TRIPLET}-size HINTS ${TOOLCHAIN_BIN_PATH}) +find_program(CMAKE_DEBUGGER NAMES ${STM32_TARGET_TRIPLET}-gdb HINTS ${TOOLCHAIN_BIN_PATH}) +find_program(CMAKE_CPPFILT NAMES ${STM32_TARGET_TRIPLET}-c++filt HINTS ${TOOLCHAIN_BIN_PATH}) + +function(stm32_print_size_of_target TARGET) + add_custom_target(${TARGET}_always_display_size + ALL COMMAND ${CMAKE_SIZE} ${TARGET}${CMAKE_EXECUTABLE_SUFFIX_C} + COMMENT "Target Sizes: " + DEPENDS ${TARGET} + ) +endfunction() + +function(stm32_generate_binary_file TARGET) + add_custom_command( + TARGET ${TARGET} + POST_BUILD + COMMAND ${CMAKE_OBJCOPY} -O binary ${TARGET}${CMAKE_EXECUTABLE_SUFFIX_C} ${TARGET}.bin + BYPRODUCTS ${TARGET}.bin + COMMENT "Generating binary file ${CMAKE_PROJECT_NAME}.bin" + ) +endfunction() + +function(stm32_generate_srec_file TARGET) + add_custom_command( + TARGET ${TARGET} + POST_BUILD + COMMAND ${CMAKE_OBJCOPY} -O srec ${TARGET}${CMAKE_EXECUTABLE_SUFFIX_C} ${TARGET}.srec + BYPRODUCTS ${TARGET}.srec + + COMMENT "Generating srec file ${CMAKE_PROJECT_NAME}.srec" + ) +endfunction() + +function(stm32_generate_hex_file TARGET) + add_custom_command( + TARGET ${TARGET} + POST_BUILD + COMMAND ${CMAKE_OBJCOPY} -O ihex ${TARGET}${CMAKE_EXECUTABLE_SUFFIX_C} ${TARGET}.hex + BYPRODUCTS ${TARGET}.hex + COMMENT "Generating hex file ${CMAKE_PROJECT_NAME}.hex" + ) +endfunction() + +# This function takes FAMILY (e.g. L4) and DEVICE (e.g. L496VG) to output TYPE (e.g. L496xx) +function(stm32_get_chip_type FAMILY DEVICE TYPE) + set(INDEX 0) + foreach(C_TYPE ${STM32_${FAMILY}_TYPES}) + list(GET STM32_${FAMILY}_TYPE_MATCH ${INDEX} REGEXP) + if(${DEVICE} MATCHES ${REGEXP}) + set(RESULT_TYPE ${C_TYPE}) + endif() + math(EXPR INDEX "${INDEX}+1") + endforeach() + if(NOT RESULT_TYPE) + message(FATAL_ERROR "Invalid/unsupported device: ${DEVICE}") + endif() + set(${TYPE} ${RESULT_TYPE} PARENT_SCOPE) +endfunction() + +function(stm32_get_chip_info CHIP) + set(ARG_OPTIONS "") + set(ARG_SINGLE FAMILY DEVICE TYPE) + set(ARG_MULTIPLE "") + cmake_parse_arguments(PARSE_ARGV 1 ARG "${ARG_OPTIONS}" "${ARG_SINGLE}" "${ARG_MULTIPLE}") + + string(TOUPPER ${CHIP} CHIP) + + string(REGEX MATCH "^STM32([FGHLMUW]P?[0-9BL])([0-9A-Z][0-9M][A-Z][0-9A-Z]).*$" CHIP ${CHIP}) + + if((NOT CMAKE_MATCH_1) OR (NOT CMAKE_MATCH_2)) + message(FATAL_ERROR "Unknown chip ${CHIP}") + endif() + + set(STM32_FAMILY ${CMAKE_MATCH_1}) + set(STM32_DEVICE "${CMAKE_MATCH_1}${CMAKE_MATCH_2}") + + + if(NOT (${STM32_FAMILY} IN_LIST STM32_SUPPORTED_FAMILIES_SHORT_NAME)) + message(FATAL_ERROR "Unsupported family ${STM32_FAMILY} for device ${CHIP}") + endif() + + stm32_get_chip_type(${STM32_FAMILY} ${STM32_DEVICE} STM32_TYPE) + + if(ARG_FAMILY) + set(${ARG_FAMILY} ${STM32_FAMILY} PARENT_SCOPE) + endif() + if(ARG_DEVICE) + set(${ARG_DEVICE} ${STM32_DEVICE} PARENT_SCOPE) + endif() + if(ARG_TYPE) + set(${ARG_TYPE} ${STM32_TYPE} PARENT_SCOPE) + endif() +endfunction() + +function(stm32_get_cores CORES) + set(ARG_OPTIONS "") + set(ARG_SINGLE CHIP FAMILY DEVICE) + set(ARG_MULTIPLE "") + cmake_parse_arguments(PARSE_ARGV 1 ARG "${ARG_OPTIONS}" "${ARG_SINGLE}" "${ARG_MULTIPLE}") + + if(ARG_CHIP) + # TODO: I don't get why stm32_get_chip_info is called in stm32_get_cores + stm32_get_chip_info(${ARG_CHIP} FAMILY ARG_FAMILY TYPE ARG_TYPE DEVICE ARG_DEVICE) + elseif(ARG_FAMILY AND ARG_DEVICE) + # TODO: I don't get why stm32_get_chip_type is called in stm32_get_cores + stm32_get_chip_type(${ARG_FAMILY} ${ARG_DEVICE} ARG_TYPE) + elseif(ARG_FAMILY) + if(${ARG_FAMILY} STREQUAL "H7") + set(${CORES} M7 M4 PARENT_SCOPE) + elseif(${ARG_FAMILY} STREQUAL "WB") + set(${CORES} M4 PARENT_SCOPE) + elseif(${ARG_FAMILY} STREQUAL "WL") + set(${CORES} M4 M0PLUS PARENT_SCOPE) + elseif(${ARG_FAMILY} STREQUAL "MP1") + set(${CORES} M4 PARENT_SCOPE) + else() + set(${CORES} "" PARENT_SCOPE) + endif() + return() + else() + message(FATAL_ERROR "Either CHIP or FAMILY or FAMILY/DEVICE should be specified for stm32_get_cores()") + endif() + + # TODO following is the only part really used by FindCMSIS. Maybe a cleanup is needed + if(${ARG_FAMILY} STREQUAL "H7") + stm32h7_get_device_cores(${ARG_DEVICE} ${ARG_TYPE} CORE_LIST) + elseif(${ARG_FAMILY} STREQUAL "WB") + # note STM32WB have an M0 core but in current state of the art it runs ST stacks and is not needed/allowed to build for customer + set(CORE_LIST M4) + elseif(${ARG_FAMILY} STREQUAL "MP1") + set(CORE_LIST M4) + elseif(${ARG_FAMILY} STREQUAL "WL") + stm32wl_get_device_cores(${ARG_DEVICE} ${ARG_TYPE} CORE_LIST) + endif() + set(${CORES} "${CORE_LIST}" PARENT_SCOPE) +endfunction() + +function(stm32_get_memory_info) + set(ARG_OPTIONS FLASH RAM CCRAM STACK HEAP RAM_SHARE) + set(ARG_SINGLE CHIP FAMILY DEVICE CORE SIZE ORIGIN) + set(ARG_MULTIPLE "") + cmake_parse_arguments(INFO "${ARG_OPTIONS}" "${ARG_SINGLE}" "${ARG_MULTIPLE}" ${ARGN}) + + if((NOT INFO_CHIP) AND ((NOT INFO_FAMILY) OR (NOT INFO_DEVICE))) + message(FATAL_ERROR "Either CHIP or FAMILY/DEVICE is required for stm32_get_memory_info()") + endif() + + if(INFO_CHIP) + stm32_get_chip_info(${INFO_CHIP} FAMILY INFO_FAMILY TYPE INFO_TYPE DEVICE INFO_DEVICE) + else() + stm32_get_chip_type(${INFO_FAMILY} ${INFO_DEVICE} INFO_TYPE) + endif() + + string(REGEX REPLACE "^[FGHLMUW]P?[0-9BL][0-9A-Z][0-9M].([3468ABCDEFGHIYZ])$" "\\1" SIZE_CODE ${INFO_DEVICE}) + + if(SIZE_CODE STREQUAL "3") + set(FLASH "8K") + elseif(SIZE_CODE STREQUAL "4") + set(FLASH "16K") + elseif(SIZE_CODE STREQUAL "6") + set(FLASH "32K") + elseif(SIZE_CODE STREQUAL "8") + set(FLASH "64K") + elseif(SIZE_CODE STREQUAL "B") + set(FLASH "128K") + elseif(SIZE_CODE STREQUAL "C") + set(FLASH "256K") + elseif(SIZE_CODE STREQUAL "D") + set(FLASH "384K") + elseif(SIZE_CODE STREQUAL "E") + set(FLASH "512K") + elseif(SIZE_CODE STREQUAL "F") + set(FLASH "768K") + elseif(SIZE_CODE STREQUAL "G") + set(FLASH "1024K") + elseif(SIZE_CODE STREQUAL "H") + set(FLASH "1536K") + elseif(SIZE_CODE STREQUAL "I") + set(FLASH "2048K") + elseif(SIZE_CODE STREQUAL "Y") + set(FLASH "640K") + elseif(SIZE_CODE STREQUAL "Z") + set(FLASH "192K") + else() + set(FLASH "16K") + message(WARNING "Unknow flash size for device ${DEVICE}. Set to ${FLASH}") + endif() + + list(FIND STM32_${INFO_FAMILY}_TYPES ${INFO_TYPE} TYPE_INDEX) + list(GET STM32_${INFO_FAMILY}_RAM_SIZES ${TYPE_INDEX} RAM) + list(GET STM32_${INFO_FAMILY}_CCRAM_SIZES ${TYPE_INDEX} CCRAM) + list(GET STM32_${INFO_FAMILY}_RAM_SHARE_SIZES ${TYPE_INDEX} RAM_SHARE) + set(FLASH_ORIGIN 0x8000000) + set(RAM_ORIGIN 0x20000000) + set(CCRAM_ORIGIN 0x10000000) + set(RAM_SHARE_ORIGIN 0x20030000) + + unset(TWO_FLASH_BANKS) + if(FAMILY STREQUAL "F1") + stm32f1_get_memory_info(${INFO_DEVICE} ${INFO_TYPE} FLASH RAM) + elseif(FAMILY STREQUAL "L1") + stm32l1_get_memory_info(${INFO_DEVICE} ${INFO_TYPE} FLASH RAM) + elseif(FAMILY STREQUAL "F2") + stm32f2_get_memory_info(${INFO_DEVICE} ${INFO_TYPE} FLASH RAM) + elseif(FAMILY STREQUAL "F3") + stm32f3_get_memory_info(${INFO_DEVICE} ${INFO_TYPE} FLASH RAM) + elseif(FAMILY STREQUAL "H7") + stm32h7_get_memory_info(${INFO_DEVICE} ${INFO_TYPE} "${INFO_CORE}" RAM FLASH_ORIGIN RAM_ORIGIN TWO_FLASH_BANKS) + elseif(FAMILY STREQUAL "WL") + stm32wl_get_memory_info(${INFO_DEVICE} ${INFO_TYPE} "${INFO_CORE}" RAM FLASH_ORIGIN RAM_ORIGIN TWO_FLASH_BANKS) + elseif(FAMILY STREQUAL "WB") + stm32wb_get_memory_info(${INFO_DEVICE} ${INFO_TYPE} "${INFO_CORE}" RAM RAM_ORIGIN TWO_FLASH_BANKS) + elseif(FAMILY STREQUAL "MP1") + stm32mp1_get_memory_info(${INFO_DEVICE} ${INFO_TYPE} FLASH) + endif() + # when a device is dual core, each core uses half of total flash + if(TWO_FLASH_BANKS) + string(REGEX MATCH "([0-9]+)K" FLASH_KB ${FLASH}) + math(EXPR FLASH_KB "${CMAKE_MATCH_1} / 2") + set(FLASH "${FLASH_KB}K") + endif() + + if(INFO_FLASH) + set(SIZE ${FLASH}) + set(ORIGIN ${FLASH_ORIGIN}) + elseif(INFO_RAM) + set(SIZE ${RAM}) + set(ORIGIN ${RAM_ORIGIN}) + elseif(INFO_CCRAM) + set(SIZE ${CCRAM}) + set(ORIGIN ${CCRAM_ORIGIN}) + elseif(INFO_RAM_SHARE) + set(SIZE ${RAM_SHARE}) + set(ORIGIN ${RAM_SHARE_ORIGIN}) + elseif(INFO_STACK) + if (RAM STREQUAL "2K") + set(SIZE 0x200) + else() + set(SIZE 0x400) + endif() + set(ORIGIN ${RAM_ORIGIN}) #TODO: Real stack pointer? + elseif(INFO_HEAP) + if (RAM STREQUAL "2K") + set(SIZE 0x100) + else() + set(SIZE 0x200) + endif() + set(ORIGIN ${RAM_ORIGIN}) #TODO: Real heap pointer? + endif() + + if(INFO_SIZE) + set(${INFO_SIZE} ${SIZE} PARENT_SCOPE) + endif() + if(INFO_ORIGIN) + set(${INFO_ORIGIN} ${ORIGIN} PARENT_SCOPE) + endif() +endfunction() + +function(stm32_add_linker_script TARGET VISIBILITY SCRIPT) + get_filename_component(SCRIPT "${SCRIPT}" ABSOLUTE) + target_link_options(${TARGET} ${VISIBILITY} -T "${SCRIPT}") + + get_target_property(TARGET_TYPE ${TARGET} TYPE) + if(TARGET_TYPE STREQUAL "INTERFACE_LIBRARY") + set(INTERFACE_PREFIX "INTERFACE_") + endif() + + get_target_property(LINK_DEPENDS ${TARGET} ${INTERFACE_PREFIX}LINK_DEPENDS) + if(LINK_DEPENDS) + list(APPEND LINK_DEPENDS "${SCRIPT}") + else() + set(LINK_DEPENDS "${SCRIPT}") + endif() + + + set_target_properties(${TARGET} PROPERTIES ${INTERFACE_PREFIX}LINK_DEPENDS "${LINK_DEPENDS}") +endfunction() + +if(NOT (TARGET STM32::NoSys)) + add_library(STM32::NoSys INTERFACE IMPORTED) + target_compile_options(STM32::NoSys INTERFACE $<$:--specs=nosys.specs>) + target_link_options(STM32::NoSys INTERFACE $<$:--specs=nosys.specs>) +endif() + +if(NOT (TARGET STM32::Nano)) + add_library(STM32::Nano INTERFACE IMPORTED) + target_compile_options(STM32::Nano INTERFACE $<$:--specs=nano.specs>) + target_link_options(STM32::Nano INTERFACE $<$:--specs=nano.specs>) +endif() + +if(NOT (TARGET STM32::Nano::FloatPrint)) + add_library(STM32::Nano::FloatPrint INTERFACE IMPORTED) + target_link_options(STM32::Nano::FloatPrint INTERFACE + $<$:-Wl,--undefined,_printf_float> + ) +endif() + +if(NOT (TARGET STM32::Nano::FloatScan)) + add_library(STM32::Nano::FloatScan INTERFACE IMPORTED) + target_link_options(STM32::Nano::FloatScan INTERFACE + $<$:-Wl,--undefined,_scanf_float> + ) +endif() + +include(stm32/utilities) +include(stm32/f0) +include(stm32/f1) +include(stm32/f2) +include(stm32/f3) +include(stm32/f4) +include(stm32/f7) +include(stm32/g0) +include(stm32/g4) +include(stm32/h7) +include(stm32/l0) +include(stm32/l1) +include(stm32/l4) +include(stm32/l5) +include(stm32/u5) +include(stm32/wb) +include(stm32/wl) +include(stm32/mp1) diff --git a/cmake/stm32/devices.cmake b/cmake/stm32/devices.cmake new file mode 100644 index 0000000..c0dcad6 --- /dev/null +++ b/cmake/stm32/devices.cmake @@ -0,0 +1,1258 @@ +set(STM32_ALL_DEVICES + F030C6 + F030C8 + F030CC + F030F4 + F030K6 + F030R8 + F030RC + F031C4 + F031C6 + F031E6 + F031F4 + F031F6 + F031G4 + F031G6 + F031K4 + F031K6 + F038C6 + F038E6 + F038F6 + F038G6 + F038K6 + F042C4 + F042C6 + F042F4 + F042F6 + F042G4 + F042G6 + F042K4 + F042K6 + F042T6 + F048C6 + F048G6 + F048T6 + F051C4 + F051C6 + F051C8 + F051K4 + F051K6 + F051K8 + F051R4 + F051R6 + F051R8 + F051T8 + F058C8 + F058R8 + F058T8 + F070C6 + F070CB + F070F6 + F070RB + F071C8 + F071CB + F071RB + F071V8 + F071VB + F072C8 + F072CB + F072R8 + F072RB + F072V8 + F072VB + F078CB + F078RB + F078VB + F091CB + F091CC + F091RB + F091RC + F091VB + F091VC + F098CC + F098RC + F098VC + F100C4 + F100C6 + F100C8 + F100CB + F100R4 + F100R6 + F100R8 + F100RB + F100RC + F100RD + F100RE + F100V8 + F100VB + F100VC + F100VD + F100VE + F100ZC + F100ZD + F100ZE + F101C4 + F101C6 + F101C8 + F101CB + F101R4 + F101R6 + F101R8 + F101RB + F101RC + F101RD + F101RE + F101RF + F101RG + F101T4 + F101T6 + F101T8 + F101TB + F101V8 + F101VB + F101VC + F101VD + F101VE + F101VF + F101VG + F101ZC + F101ZD + F101ZE + F101ZF + F101ZG + F102C4 + F102C6 + F102C8 + F102CB + F102R4 + F102R6 + F102R8 + F102RB + F103C4 + F103C6 + F103C8 + F103CB + F103R4 + F103R6 + F103R8 + F103RB + F103RC + F103RD + F103RE + F103RF + F103RG + F103T4 + F103T6 + F103T8 + F103TB + F103V8 + F103VB + F103VC + F103VD + F103VE + F103VF + F103VG + F103ZC + F103ZD + F103ZE + F103ZF + F103ZG + F105R8 + F105RB + F105RC + F105V8 + F105VB + F105VC + F107RB + F107RC + F107VB + F107VC + F205RB + F205RC + F205RE + F205RF + F205RG + F205VB + F205VC + F205VE + F205VF + F205VG + F205ZC + F205ZE + F205ZF + F205ZG + F207IC + F207IE + F207IF + F207IG + F207VC + F207VE + F207VF + F207VG + F207ZC + F207ZE + F207ZF + F207ZG + F215RE + F215RG + F215VE + F215VG + F215ZE + F215ZG + F217IE + F217IG + F217VE + F217VG + F217ZE + F217ZG + F301C6 + F301C8 + F301K6 + F301K8 + F301R6 + F301R8 + F302C6 + F302C8 + F302CB + F302CC + F302K6 + F302K8 + F302R6 + F302R8 + F302RB + F302RC + F302RD + F302RE + F302VB + F302VC + F302VD + F302VE + F302ZD + F302ZE + F303C6 + F303C8 + F303CB + F303CC + F303K6 + F303K8 + F303R6 + F303R8 + F303RB + F303RC + F303RD + F303RE + F303VB + F303VC + F303VD + F303VE + F303ZD + F303ZE + F318C8 + F318K8 + F328C8 + F334C4 + F334C6 + F334C8 + F334K4 + F334K6 + F334K8 + F334R6 + F334R8 + F358CC + F358RC + F358VC + F373C8 + F373CB + F373CC + F373R8 + F373RB + F373RC + F373V8 + F373VB + F373VC + F378CC + F378RC + F378VC + F398VE + F401CB + F401CC + F401CD + F401CE + F401RB + F401RC + F401RD + F401RE + F401VB + F401VC + F401VD + F401VE + F405OE + F405OG + F405RG + F405VG + F405ZG + F407IE + F407IG + F407VE + F407VG + F407ZE + F407ZG + F410C8 + F410CB + F410R8 + F410RB + F410T8 + F410TB + F411CC + F411CE + F411RC + F411RE + F411VC + F411VE + F412CE + F412CG + F412RE + F412RG + F412VE + F412VG + F412ZE + F412ZG + F413CG + F413CH + F413MG + F413MH + F413RG + F413RH + F413VG + F413VH + F413ZG + F413ZH + F415OG + F415RG + F415VG + F415ZG + F417IE + F417IG + F417VE + F417VG + F417ZE + F417ZG + F423CH + F423MH + F423RH + F423VH + F423ZH + F427AG + F427AI + F427IG + F427II + F427VG + F427VI + F427ZG + F427ZI + F429AG + F429AI + F429BE + F429BG + F429BI + F429IE + F429IG + F429II + F429NE + F429NG + F429NI + F429VE + F429VG + F429VI + F429ZE + F429ZG + F429ZI + F437AI + F437IG + F437II + F437VG + F437VI + F437ZG + F437ZI + F439AI + F439BG + F439BI + F439IG + F439II + F439NG + F439NI + F439VG + F439VI + F439ZG + F439ZI + F446MC + F446ME + F446RC + F446RE + F446VC + F446VE + F446ZC + F446ZE + F469AE + F469AG + F469AI + F469BE + F469BG + F469BI + F469IE + F469IG + F469II + F469NE + F469NG + F469NI + F469VE + F469VG + F469VI + F469ZE + F469ZG + F469ZI + F479AG + F479AI + F479BG + F479BI + F479IG + F479II + F479NG + F479NI + F479VG + F479VI + F479ZG + F479ZI + F722IC + F722IE + F722RC + F722RE + F722VC + F722VE + F722ZC + F722ZE + F723IC + F723IE + F723VE + F723ZC + F723ZE + F730I8 + F730R8 + F730V8 + F730Z8 + F732IE + F732RE + F732VE + F732ZE + F733IE + F733VE + F733ZE + F745IE + F745IG + F745VE + F745VG + F745ZE + F745ZG + F746BE + F746BG + F746IE + F746IG + F746NE + F746NG + F746VE + F746VG + F746ZE + F746ZG + F750N8 + F750V8 + F750Z8 + F756BG + F756IG + F756NG + F756VG + F756ZG + F765BG + F765BI + F765IG + F765II + F765NG + F765NI + F765VG + F765VI + F765ZG + F765ZI + F767BG + F767BI + F767IG + F767II + F767NG + F767NI + F767VG + F767VI + F767ZG + F767ZI + F769AI + F769BG + F769BI + F769IG + F769II + F769NG + F769NI + F777BI + F777II + F777NI + F777VI + F777ZI + F778AI + F779AI + F779BI + F779II + F779NI + G030C6 + G030C8 + G030F6 + G030J6 + G030K6 + G030K8 + G031C4 + G031C6 + G031C8 + G031F4 + G031F6 + G031F8 + G031G4 + G031G6 + G031G8 + G031J4 + G031J6 + G031K4 + G031K6 + G031K8 + G031Y8 + G041C6 + G041C8 + G041F6 + G041F8 + G041G6 + G041G8 + G041J6 + G041K6 + G041K8 + G041Y8 + G070CB + G070KB + G070RB + G071C6 + G071C8 + G071CB + G071EB + G071G6 + G071G8 + G071GB + G071K6 + G071K8 + G071KB + G071R6 + G071R8 + G071RB + G081CB + G081EB + G081GB + G081KB + G081RB + G0B1CC + G0B1CE + G0B1KC + G0B1KE + G0B1RC + G0B1RE + G0B1VC + G0B1VE + G0C1CC + G0C1CE + G0C1KC + G0C1KE + G0C1RC + G0C1RE + G0C1VC + G0C1VE + G431C6 + G431C8 + G431CB + G431K6 + G431K8 + G431KB + G431M6 + G431M8 + G431MB + G431R6 + G431R8 + G431RB + G431V6 + G431V8 + G431VB + G441CB + G441KB + G441MB + G441RB + G441VB + G471CC + G471CE + G471MC + G471ME + G471QC + G471QE + G471RC + G471RE + G471VC + G471VE + G473CB + G473CC + G473CE + G473MB + G473MC + G473ME + G473PB + G473PC + G473PE + G473QB + G473QC + G473QE + G473RB + G473RC + G473RE + G473VB + G473VC + G473VE + G474CB + G474CC + G474CE + G474MB + G474MC + G474ME + G474PB + G474PC + G474PE + G474QB + G474QC + G474QE + G474RB + G474RC + G474RE + G474VB + G474VC + G474VE + G483CE + G483ME + G483PE + G483QE + G483RE + G483VE + G484CE + G484ME + G484PE + G484QE + G484RE + G484VE + G491CC + G491KC + G491MC + G491RC + G491VC + G491CE + G491KE + G491ME + G491RE + G491VE + G4A1CE + G4A1KE + G4A1ME + G4A1RE + G4A1VE + GBK1CB + H723VE + H723VG + H723ZE + H723ZG + H725AE + H725AG + H725IE + H725IG + H725RE + H725RG + H725VE + H725VG + H725ZE + H725ZG + H730AB + H730IB + H730VB + H730ZB + H733VG + H733ZG + H735AG + H735IG + H735RG + H735VG + H735ZG + H742AG + H742AI + H742BG + H742BI + H742IG + H742II + H742VG + H742VI + H742XG + H742XI + H742ZG + H742ZI + H743AG + H743AI + H743BG + H743BI + H743IG + H743II + H743VG + H743VI + H743XG + H743XI + H743ZG + H743ZI + H745BG + H745BI + H745IG + H745II + H745XG + H745XI + H745ZG + H745ZI + H747AG + H747AI + H747BG + H747BI + H747IG + H747II + H747XG + H747XI + H747ZI + H750IB + H750VB + H750XB + H750ZB + H753AI + H753BI + H753II + H753VI + H753XI + H753ZI + H755BI + H755II + H755XI + H755ZI + H757AI + H757BI + H757II + H757XI + H757ZI + H7A3AG + H7A3AI + H7A3IG + H7A3II + H7A3LG + H7A3LI + H7A3NG + H7A3NI + H7A3QI + H7A3RG + H7A3RI + H7A3VG + H7A3VI + H7A3ZG + H7A3ZI + H7B0AB + H7B0IB + H7B0RB + H7B0VB + H7B0ZB + H7B3AI + H7B3II + H7B3LI + H7B3NI + H7B3QI + H7B3RI + H7B3VI + H7B3ZI + L010C6 + L010F4 + L010K4 + L010K8 + L010R8 + L010RB + L011D3 + L011D4 + L011E3 + L011E4 + L011F3 + L011F4 + L011G3 + L011G4 + L011K3 + L011K4 + L021D4 + L021F4 + L021G4 + L021K4 + L031C4 + L031C6 + L031E4 + L031E6 + L031F4 + L031F6 + L031G4 + L031G6 + L031K4 + L031K6 + L041C6 + L041E6 + L041F6 + L041G6 + L041K6 + L051C6 + L051C8 + L051K6 + L051K8 + L051R6 + L051R8 + L051T6 + L051T8 + L052C6 + L052C8 + L052K6 + L052K8 + L052R6 + L052R8 + L052T6 + L052T8 + L053C6 + L053C8 + L053R6 + L053R8 + L062C8 + L062K8 + L063C8 + L063R8 + L071C8 + L071CB + L071CZ + L071K8 + L071KB + L071KZ + L071RB + L071RZ + L071V8 + L071VB + L071VZ + L072CB + L072CZ + L072KB + L072KZ + L072RB + L072RZ + L072V8 + L072VB + L072VZ + L073CB + L073CZ + L073RB + L073RZ + L073V8 + L073VB + L073VZ + L081CB + L081CZ + L081KZ + L082CZ + L082KZ + L083CB + L083CZ + L083RB + L083RZ + L083V8 + L083VB + L083VZ + L100C6 + L100R8 + L100RB + L100RC + L151C6 + L151C8 + L151CB + L151CC + L151QC + L151QD + L151QE + L151R6 + L151R8 + L151RB + L151RC + L151RD + L151RE + L151UC + L151V8 + L151VB + L151VC + L151VD + L151VE + L151ZC + L151ZD + L151ZE + L152C6 + L152C8 + L152CB + L152CC + L152QC + L152QD + L152QE + L152R6 + L152R8 + L152RB + L152RC + L152RD + L152RE + L152UC + L152V8 + L152VB + L152VC + L152VD + L152VE + L152ZC + L152ZD + L152ZE + L162QC + L162QD + L162RC + L162RD + L162RE + L162VC + L162VD + L162VE + L162ZC + L162ZD + L162ZE + L412C8 + L412CB + L412K8 + L412KB + L412R8 + L412RB + L412T8 + L412TB + L422CB + L422KB + L422RB + L422TB + L431CB + L431CC + L431KB + L431KC + L431RB + L431RC + L431VC + L432KB + L432KC + L433CB + L433CC + L433RB + L433RC + L433VC + L442KC + L443CC + L443RC + L443VC + L451CC + L451CE + L451RC + L451RE + L451VC + L451VE + L452CC + L452CE + L452RC + L452RE + L452VC + L452VE + L462CE + L462RE + L462VE + L471QE + L471QG + L471RE + L471RG + L471VE + L471VG + L471ZE + L471ZG + L475RC + L475RE + L475RG + L475VC + L475VE + L475VG + L476JE + L476JG + L476ME + L476MG + L476QE + L476QG + L476RC + L476RE + L476RG + L476VC + L476VE + L476VG + L476ZE + L476ZG + L486JG + L486QG + L486RG + L486VG + L486ZG + L496AE + L496AG + L496QE + L496QG + L496RE + L496RG + L496VE + L496VG + L496ZE + L496ZG + L4A6AG + L4A6QG + L4A6RG + L4A6VG + L4A6ZG + L4P5AE + L4P5AG + L4P5CE + L4P5CG + L4P5QE + L4P5QG + L4P5RE + L4P5RG + L4P5VE + L4P5VG + L4P5ZE + L4P5ZG + L4Q5AG + L4Q5CG + L4Q5QG + L4Q5RG + L4Q5VG + L4Q5ZG + L4R5AG + L4R5AI + L4R5QG + L4R5QI + L4R5VG + L4R5VI + L4R5ZG + L4R5ZI + L4R7AI + L4R7VI + L4R7ZI + L4R9AG + L4R9AI + L4R9VG + L4R9VI + L4R9ZG + L4R9ZI + L4S5AI + L4S5QI + L4S5VI + L4S5ZI + L4S7AI + L4S7VI + L4S7ZI + L4S9AI + L4S9VI + L4S9ZI + L552CC + L552CE + L552ME + L552QC + L552QE + L552RC + L552RE + L552VC + L552VE + L552ZC + L552ZE + L562CE + L562ME + L562QE + L562RE + L562VE + L562ZE + MP151A + MP151C + MP151D + MP151F + MP153A + MP153C + MP153D + MP153F + MP157A + MP157C + MP157D + MP157F + U575CG + U575CI + U585CI + U575RG + U575RI + U585RI + U5750G + U5750I + U5850I + U575VG + U575VI + U585VI + U575QG + U575QI + U585QI + U575ZG + U575ZI + U585ZI + U575AG + U575AI + U585AI + WB5MMG + WB50CG + WB30CE + WB10CC + WB55CC + WB55CE + WB55CG + WB55RC + WB55RE + WB55RG + WB55VC + WB55VE + WB55VG + WB55VY + WB15CC + WB35CC + WB35CE + WL55CC + WL54CC + WL55JC + WL54JC + WLE5J8 + WLE5JB + WLE5JC + WLE5C8 + WLE5CB + WLE5CC + WLE4J8 + WLE4JB + WLE4JC + WLE4C8 + WLE4CB + WLE4CC +) + +# Store a list of devices into a given STM_DEVICES list. +# You can also specify multiple device families. Examples: +# Get list of all devices for H7 family: stm32_get_devices_by_family(STM_DEVICES FAMILY H7) +# Get list of all devices: stm32_get_devices_by_family(STM_DEVICES) +function(stm32_get_devices_by_family STM_DEVICES) + # Specify keywords for argument parsing here + set(ARG_OPTIONS "") + set(ARG_SINGLE "") + set(ARG_MULTIPLE FAMILY) + + # Parse arguments. Multiple families can be specified and will be stored in ARG_ + cmake_parse_arguments(PARSE_ARGV 1 ARG "${ARG_OPTIONS}" "${ARG_SINGLE}" "${ARG_MULTIPLE}") + stm32_dev_parser_check() + + # Build a list of families by filtering the whole list with the specified families + if(ARG_FAMILY) + set(RESULTING_DEV_LIST "") + foreach(FAMILY ${ARG_FAMILY}) + set(STM_DEVICE_LIST ${STM32_ALL_DEVICES}) + list(FILTER STM_DEVICE_LIST INCLUDE REGEX "^${FAMILY}") + list(APPEND RESULTING_DEV_LIST ${STM_DEVICE_LIST}) + if(NOT STM_DEVICE_LIST) + message(WARNING "No devices found for given family ${FAMILY}") + endif() + endforeach() + else() + # No family argument, so get list of all devices + set(RESULTING_DEV_LIST ${STM32_ALL_DEVICES}) + endif() + + set(${STM_DEVICES} ${RESULTING_DEV_LIST} PARENT_SCOPE) +endfunction() + +# Print the devices for a given family. You can also specify multiple device families. +# Example usage: +# Print devices for H7 family: stm32_print_devices_by_family(FAMILY H7) +# Print all devices: stm32_print_devices_by_family() +function(stm32_print_devices_by_family) + # Specify keywords for argument parsing here + set(ARG_OPTIONS "") + set(ARG_SINGLE "") + set(ARG_MULTIPLE FAMILY) + + # Parse arguments. Multiple families can be specified and will be stored in ARG_ + cmake_parse_arguments(PARSE_ARGV 0 ARG "${ARG_OPTIONS}" "${ARG_SINGLE}" "${ARG_MULTIPLE}") + stm32_dev_parser_check() + + if(ARG_FAMILY) + # print devices one family per line + foreach(FAMILY ${ARG_FAMILY}) + stm32_get_devices_by_family(STM_DEVICES FAMILY ${FAMILY}) + stm32_pretty_print_dev_list(${FAMILY} "${STM_DEVICES}") + endforeach() + else() + # print all devices + stm32_get_devices_by_family(STM_DEVICES) + stm32_pretty_print_dev_list("all" "${STM_DEVICES}") + endif() + +endfunction() + +# The arguments checked in this macro are filled by cmake_parse_argument +macro(stm32_dev_parser_check) + # contains unexpected arguments (unknown keywords beofre ARG_MULTIPLE) + if(ARG_UNPARSED_ARGUMENTS) + message(WARNING "Unknown keyword(s) ${ARG_UNPARSED_ARGUMENTS} will be ignored") + endif() + # is populated if ARG_SINGLE or ARG_MULTIPLE is used without values + if(ARG_KEYWORDS_MISSING_VALUES) + message(FATAL_ERROR "Keyword ${ARG_KEYWORDS_MISSING_VALUES} expects values") + endif() +endmacro() + +# Pretty printer to limit amount of list entries printed per line +macro(stm32_pretty_print_dev_list FAMILIES STM_DEVICES) + if(${FAMILIES} STREQUAL "all") + message(STATUS "Devices for all families") + else() + message(STATUS "Devices for ${FAMILIES} family") + endif() + set(TMP_LIST "") + foreach(STM_DEVICE ${STM_DEVICES}) + list(APPEND TMP_LIST ${STM_DEVICE}) + list(LENGTH TMP_LIST CURR_LEN) + if(CURR_LEN EQUAL 10) + message(STATUS "${TMP_LIST}") + set(TMP_LIST "") + endif() + endforeach() + if(TMP_LIST) + message(STATUS "${TMP_LIST}") + endif() +endmacro() diff --git a/cmake/stm32/f0.cmake b/cmake/stm32/f0.cmake new file mode 100644 index 0000000..92d5e7a --- /dev/null +++ b/cmake/stm32/f0.cmake @@ -0,0 +1,25 @@ +set(STM32_F0_TYPES + F030x6 F030x8 F031x6 F038xx F042x6 F048xx F051x8 F058xx + F070x6 F070xB F071xB F072xB F078xx F091xC F098xx F030xC +) +set(STM32_F0_TYPE_MATCH + "F030.[46]" "F030.8" "F031.[46]" "F038.." "F042.[46]" "F048.." "F051.[468]" "F058.." + "F070.6" "F070.B" "F071.[8B]" "F072.[8B]" "F078.." "F091.[BC]" "F098.." "F030.C" +) +set(STM32_F0_RAM_SIZES + 4K 8K 4K 4K 6K 6K 8K 8K + 6K 16K 16K 16K 16K 32K 32K 32K +) +set(STM32_F0_CCRAM_SIZES + 0K 0K 0K 0K 0K 0K 0K 0K + 0K 0K 0K 0K 0K 0K 0K 0K +) + +stm32_util_create_family_targets(F0) + +target_compile_options(STM32::F0 INTERFACE + -mcpu=cortex-m0 +) +target_link_options(STM32::F0 INTERFACE + -mcpu=cortex-m0 +) diff --git a/cmake/stm32/f1.cmake b/cmake/stm32/f1.cmake new file mode 100644 index 0000000..bc97ceb --- /dev/null +++ b/cmake/stm32/f1.cmake @@ -0,0 +1,78 @@ +set(STM32_F1_TYPES + F100xB F100xE F101x6 F101xB F101xE F101xG F102x6 F102xB + F103x6 F103xB F103xE F103xG F105xC F107xC +) +set(STM32_F1_TYPE_MATCH + "F100.[468B]" "F100.[CDE]" "F101.[46]" "F101.[8B]" "F101.[CDE]" "F101.[FG]" "F102.[46]" "F102.[8B]" + "F103.[46]" "F103.[8B]" "F103.[CDE]" "F103.[FG]" "F105.[8BC]" "F107.[BC]" +) +set(STM32_F1_RAM_SIZES + 0K 0K 0K 0K 0K 0K 0K 0K + 0K 0K 0K 0K 0K 0K +) +set(STM32_F1_CCRAM_SIZES + 0K 0K 0K 0K 0K 0K 0K 0K + 0K 0K 0K 0K 0K 0K +) + +stm32_util_create_family_targets(F1) + +target_compile_options(STM32::F1 INTERFACE + -mcpu=cortex-m3 +) +target_link_options(STM32::F1 INTERFACE + -mcpu=cortex-m3 +) + +function(stm32f1_get_memory_info DEVICE TYPE FLASH_SIZE RAM_SIZE) + string(REGEX REPLACE "F1[0-9][0-9].([468BCDEFGHI])" "\\1" SIZE_CODE ${DEVICE}) + + if((TYPE STREQUAL "F100xB") OR (TYPE STREQUAL "F100xE")) + if((SIZE_CODE STREQUAL "4") OR (SIZE_CODE STREQUAL "6")) + set(RAM "4K") + elseif((SIZE_CODE STREQUAL "8") OR (SIZE_CODE STREQUAL "B")) + set(RAM "8K") + elseif(SIZE_CODE STREQUAL "C") + set(RAM "24K") + elseif((SIZE_CODE STREQUAL "D") OR (SIZE_CODE STREQUAL "E")) + set(RAM "32K") + endif() + elseif((TYPE STREQUAL "F101x6") OR (TYPE STREQUAL "F101xB") OR + (TYPE STREQUAL "F101xE") OR (TYPE STREQUAL "F101xG") OR + (TYPE STREQUAL "F102x6") OR (TYPE STREQUAL "F102xB")) + if(SIZE_CODE STREQUAL "4") + set(RAM "4K") + elseif(SIZE_CODE STREQUAL "6") + set(RAM "6K") + elseif(SIZE_CODE STREQUAL "8") + set(RAM "10K") + elseif(SIZE_CODE STREQUAL "B") + set(RAM "16K") + elseif(SIZE_CODE STREQUAL "C") + set(RAM "32K") + elseif((SIZE_CODE STREQUAL "D") OR (SIZE_CODE STREQUAL "E")) + set(RAM "48K") + elseif((SIZE_CODE STREQUAL "F") OR (SIZE_CODE STREQUAL "G")) + set(RAM "80K") + endif() + elseif((TYPE STREQUAL "F103x6") OR (TYPE STREQUAL "F103xB") OR + (TYPE STREQUAL "F103xE") OR (TYPE STREQUAL "F103xG")) + if(SIZE_CODE STREQUAL "4") + set(RAM "6K") + elseif(SIZE_CODE STREQUAL "6") + set(RAM "10K") + elseif((SIZE_CODE STREQUAL "8") OR (SIZE_CODE STREQUAL "B")) + set(RAM "20K") + elseif(SIZE_CODE STREQUAL "C") + set(RAM "48K") + elseif((SIZE_CODE STREQUAL "D") OR (SIZE_CODE STREQUAL "E")) + set(RAM "64K") + elseif((SIZE_CODE STREQUAL "F") OR (SIZE_CODE STREQUAL "G")) + set(RAM "96K") + endif() + elseif((TYPE STREQUAL "F105xC") OR (TYPE STREQUAL "F107xC")) + set(RAM "64K") + endif() + + set(${RAM_SIZE} ${RAM} PARENT_SCOPE) +endfunction() diff --git a/cmake/stm32/f2.cmake b/cmake/stm32/f2.cmake new file mode 100644 index 0000000..38c2c2a --- /dev/null +++ b/cmake/stm32/f2.cmake @@ -0,0 +1,39 @@ +set(STM32_F2_TYPES + F205xx F215xx F207xx F217xx +) +set(STM32_F2_TYPE_MATCH + "F205.." "F215.." "F207.." "F217.." +) +set(STM32_F2_RAM_SIZES + 0K 128K 128K 128K +) +set(STM32_F2_CCRAM_SIZES + 0K 0K 0K 0K +) + +stm32_util_create_family_targets(F2) + +target_compile_options(STM32::F2 INTERFACE + -mcpu=cortex-m3 +) +target_link_options(STM32::F2 INTERFACE + -mcpu=cortex-m3 +) + +function(stm32f2_get_memory_info DEVICE TYPE FLASH_SIZE RAM_SIZE) + string(REGEX REPLACE "F2[0-9][0-9].([468BCDEFGHI])" "\\1" SIZE_CODE ${DEVICE}) + + if(TYPE STREQUAL "F205xx") + if(SIZE_CODE STREQUAL "B") + set(RAM "64K") + elseif(SIZE_CODE STREQUAL "C") + set(RAM "96K") + else() + set(RAM "128K") + endif() + endif() + + if(RAM) + set(${RAM_SIZE} ${RAM} PARENT_SCOPE) + endif() +endfunction() diff --git a/cmake/stm32/f3.cmake b/cmake/stm32/f3.cmake new file mode 100644 index 0000000..7c3845b --- /dev/null +++ b/cmake/stm32/f3.cmake @@ -0,0 +1,59 @@ +set(STM32_F3_TYPES + F301x8 F302x8 F302xC F302xE F303x8 F303xC + F303xE F318xx F328xx F334x8 F358xx F373xC + F378xx F398xx +) +set(STM32_F3_TYPE_MATCH + "301.[68]" "302.[68]" "302.[BC]" "302.[DE]" "303.[68]" "303.[BC]" + "303.[DE]" "318.." "328.." "334.[468]" "358.." "373.[8BC]" + "378.." "398.." +) +set(STM32_F3_RAM_SIZES + 16K 16K 0K 64K 12K 0K + 64K 16K 12K 12K 40K 0K + 32K 64K +) +set(STM32_F3_CCRAM_SIZES + 0K 0K 0K 0K 4K 8K + 16K 0K 4K 4K 8K 0K + 0K 16K +) + +stm32_util_create_family_targets(F3) + +target_compile_options(STM32::F3 INTERFACE + -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard +) +target_link_options(STM32::F3 INTERFACE + -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard +) + +function(stm32f3_get_memory_info DEVICE TYPE FLASH_SIZE RAM_SIZE) + string(REGEX REPLACE "F3[0-9][0-9].([468BCDEFGHI])" "\\1" SIZE_CODE ${DEVICE}) + + if(TYPE STREQUAL "F302xC") + if(SIZE_CODE STREQUAL "C") + set(RAM "40K") + else() + set(RAM "32K") + endif() + elseif(TYPE STREQUAL "F303xC") + if(SIZE_CODE STREQUAL "C") + set(RAM "40K") + else() + set(RAM "32K") + endif() + elseif(TYPE STREQUAL "F373xC") + if(SIZE_CODE STREQUAL "B") + set(RAM "24K") + elseif(SIZE_CODE STREQUAL "C") + set(RAM "32K") + else() + set(RAM "16K") + endif() + endif() + + if(RAM) + set(${RAM_SIZE} ${RAM} PARENT_SCOPE) + endif() +endfunction() diff --git a/cmake/stm32/f4.cmake b/cmake/stm32/f4.cmake new file mode 100644 index 0000000..06d1d9e --- /dev/null +++ b/cmake/stm32/f4.cmake @@ -0,0 +1,29 @@ +set(STM32_F4_TYPES + F401xC F401xE F405xx F407xx F410Cx F410Rx F410Tx F411xE + F412Cx F412Rx F412Vx F412Zx F413xx F415xx F417xx F423xx + F427xx F429xx F437xx F439xx F446xx F469xx F479xx +) +set(STM32_F4_TYPE_MATCH + "F401.[CB]" "F401.[ED]" "F405.." "F407.." "F410C." "F410R." "F410T." "F411.[CE]" + "F412C." "F412R." "F412V." "F412Z." "F413.." "F415.." "F417.." "F423.." + "F427.." "F429.." "F437.." "F439.." "F446.." "F469.." "F479.." +) +set(STM32_F4_RAM_SIZES + 64K 96K 128K 128K 32K 32K 32K 128K + 256K 256K 256K 256K 320K 128K 128K 320K + 192K 192K 192K 192K 128K 320K 320K +) +set(STM32_F4_CCRAM_SIZES + 0K 0K 64K 64K 0K 0K 0K 0K + 0K 0K 0K 0K 0K 64K 64K 0K + 64K 64K 64K 64K 0K 64K 64K +) + +stm32_util_create_family_targets(F4) + +target_compile_options(STM32::F4 INTERFACE + -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard +) +target_link_options(STM32::F4 INTERFACE + -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard +) diff --git a/cmake/stm32/f7.cmake b/cmake/stm32/f7.cmake new file mode 100644 index 0000000..cd9d87e --- /dev/null +++ b/cmake/stm32/f7.cmake @@ -0,0 +1,25 @@ +set(STM32_F7_TYPES + F756xx F746xx F745xx F765xx F767xx F769xx F777xx F779xx + F722xx F723xx F732xx F733xx F730xx F750xx +) +set(STM32_F7_TYPE_MATCH + "F756.." "F746.." "F745.." "F765.." "F767.." "F769.." "F777.." "F77[89].." + "F722.." "F723.." "F732.." "F733.." "F730.." "F750.." +) +set(STM32_F7_RAM_SIZES + 320K 320K 320K 512K 512K 512K 512K 512K + 256K 256K 256K 256K 256K 320K +) +set(STM32_F7_CCRAM_SIZES + 0K 0K 0K 0K 0K 0K 0K 0K + 0K 0K 0K 0K 0K 0K +) + +stm32_util_create_family_targets(F7) + +target_compile_options(STM32::F7 INTERFACE + -mcpu=cortex-m7 -mfpu=fpv5-sp-d16 -mfloat-abi=hard +) +target_link_options(STM32::F7 INTERFACE + -mcpu=cortex-m7 -mfpu=fpv5-sp-d16 -mfloat-abi=hard +) diff --git a/cmake/stm32/g0.cmake b/cmake/stm32/g0.cmake new file mode 100644 index 0000000..3fd3c4e --- /dev/null +++ b/cmake/stm32/g0.cmake @@ -0,0 +1,25 @@ +set(STM32_G0_TYPES + G030xx G031xx G041xx G070xx G071xx G081xx + G0B1xx G0C1xx +) +set(STM32_G0_TYPE_MATCH + "G030.." "G031.." "G041.." "G070.." "G071.." "G081.." + "G0B1.." "G0C1.." +) +set(STM32_G0_RAM_SIZES + 8K 8K 8K 36K 36K 36K + 144k 144K +) +set(STM32_G0_CCRAM_SIZES + 0K 0K 0K 0K 0K 0K + 0K 0K +) + +stm32_util_create_family_targets(G0) + +target_compile_options(STM32::G0 INTERFACE + -mcpu=cortex-m0plus +) +target_link_options(STM32::G0 INTERFACE + -mcpu=cortex-m0plus +) diff --git a/cmake/stm32/g4.cmake b/cmake/stm32/g4.cmake new file mode 100644 index 0000000..f05b575 --- /dev/null +++ b/cmake/stm32/g4.cmake @@ -0,0 +1,25 @@ +set(STM32_G4_TYPES + G431xx G441xx G471xx G473xx G483xx G474xx G484xx + G491xx G4A1xx +) +set(STM32_G4_TYPE_MATCH + "G431.." "G441.." "G471.." "G473.." "G483.." "G474.." "G484.." + "G491.." "G4A1.." +) +set(STM32_G4_RAM_SIZES + 32K 32K 128K 128K 128K 128K 128K + 112K 112K +) +set(STM32_G4_CCRAM_SIZES + 0K 0K 0K 0K 0K 0K 0K + 0K 0K +) + +stm32_util_create_family_targets(G4) + +target_compile_options(STM32::G4 INTERFACE + -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard +) +target_link_options(STM32::G4 INTERFACE + -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard +) diff --git a/cmake/stm32/h7.cmake b/cmake/stm32/h7.cmake new file mode 100644 index 0000000..b941014 --- /dev/null +++ b/cmake/stm32/h7.cmake @@ -0,0 +1,87 @@ +set(STM32_H7_TYPES + H723xx H725xx H730xx H730xxQ H733xx H735xx + H743xx H753xx H750xx H742xx H745xx H755xx H747xx H757xx + H7A3xx H7A3xxQ H7B3xx H7B3xxQ H7B0xx H7B0xxQ +) +set(STM32_H7_TYPE_MATCH + "H723.." "H725.." "H730.." "H730..Q" "H733.." "H735.." + "H743.." "H753.." "H750.." "H742.." "H745.." "H755.." "H747.." "H757.." + "H7A3.." "H7A3..Q" "H7B3.." "H7B3..Q" "H7B0.." "H7B0..Q" +) +set(STM32_H7_RAM_SIZES + 128K 128K 128K 128K 128K 128K + 128K 128K 128K 128K 128K 128K 128K 128K + 128K 128K 128K 128K 128K 128K +) +set(STM32_H7_M4_RAM_SIZES + 0K 0K 0K 0K 0K 0K + 0K 0K 0K 0K 288K 288K 288K 288K + 0K 0K 0K 0K 0K 0K +) + +set(STM32_H7_CCRAM_SIZES + 0K 0K 0K 0K 0K 0K + 0K 0K 0K 0K 0K 0K 0K 0K + 0K 0K 0K 0K 0K 0K +) + +set(STM32_H7_DUAL_CORE + H745xx H755xx H747xx H757xx +) + +stm32_util_create_family_targets(H7 M7) + +target_compile_options(STM32::H7::M7 INTERFACE + -mcpu=cortex-m7 -mfpu=fpv5-sp-d16 -mfloat-abi=hard +) +target_link_options(STM32::H7::M7 INTERFACE + -mcpu=cortex-m7 -mfpu=fpv5-sp-d16 -mfloat-abi=hard +) +target_compile_definitions(STM32::H7::M7 INTERFACE + -DCORE_CM7 +) + +stm32_util_create_family_targets(H7 M4) + +target_compile_options(STM32::H7::M4 INTERFACE + -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard +) +target_link_options(STM32::H7::M4 INTERFACE + -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard +) +target_compile_definitions(STM32::H7::M4 INTERFACE + -DCORE_CM4 +) + +function(stm32h7_get_memory_info DEVICE TYPE CORE RAM FLASH_ORIGIN RAM_ORIGIN TWO_FLASH_BANKS) + if(${TYPE} IN_LIST STM32_H7_DUAL_CORE) + set(${TWO_FLASH_BANKS} TRUE PARENT_SCOPE) + else() + set(${TWO_FLASH_BANKS} FALSE PARENT_SCOPE) + endif() + if(NOT CORE) + set(CORE "M7") + endif() + list(FIND STM32_H7_TYPES ${TYPE} TYPE_INDEX) + if(CORE STREQUAL "M7") + list(GET STM32_H7_RAM_SIZES ${TYPE_INDEX} RAM_VALUE) + set(${RAM} ${RAM_VALUE} PARENT_SCOPE) + set(${FLASH_ORIGIN} 0x8000000 PARENT_SCOPE) + set(${RAM_ORIGIN} 0x20000000 PARENT_SCOPE) + elseif((${TYPE} IN_LIST STM32_H7_DUAL_CORE) AND (CORE STREQUAL "M4")) + list(GET STM32_H7_M4_RAM_SIZES ${TYPE_INDEX} RAM_VALUE) + set(${RAM} ${RAM_VALUE} PARENT_SCOPE) + set(${FLASH_ORIGIN} 0x8100000 PARENT_SCOPE) + set(${RAM_ORIGIN} 0x10000000 PARENT_SCOPE) + else() + message(FATAL_ERROR "Unknown core ${CORE}") + endif() +endfunction() + +function(stm32h7_get_device_cores DEVICE TYPE CORES) + if(${TYPE} IN_LIST STM32_H7_DUAL_CORE) + set(${CORES} M7 M4 PARENT_SCOPE) + else() + set(${CORES} M7 PARENT_SCOPE) + endif() +endfunction() diff --git a/cmake/stm32/l0.cmake b/cmake/stm32/l0.cmake new file mode 100644 index 0000000..abc5dfd --- /dev/null +++ b/cmake/stm32/l0.cmake @@ -0,0 +1,29 @@ +set(STM32_L0_TYPES + L010x4 L010x6 L010x8 L010xB L011xx L021xx L031xx L041xx + L051xx L052xx L053xx L061xx L062xx L063xx L071xx L072xx + L073xx L081xx L082xx L083xx +) +set(STM32_L0_TYPE_MATCH + "L010.4" "L010.6" "L010.8" "L010.B" "L011.." "L021.." "L031.." "L041.." + "L051.." "L052.." "L053.." "L061.." "L062.." "L063.." "L071.." "L072.." + "L073.." "L081.." "L082.." "L083.." +) +set(STM32_L0_RAM_SIZES + 2K 8K 8K 20K 2K 2K 8K 8K + 8K 8K 8K 8K 8K 8K 20K 20K + 20K 20K 20K 20K +) +set(STM32_L0_CCRAM_SIZES + 0K 0K 0K 0K 0K 0K 0K 0K + 0K 0K 0K 0K 0K 0K 0K 0K + 0K 0K 0K 0K +) + +stm32_util_create_family_targets(L0) + +target_compile_options(STM32::L0 INTERFACE + -mcpu=cortex-m0plus +) +target_link_options(STM32::L0 INTERFACE + -mcpu=cortex-m0plus +) diff --git a/cmake/stm32/l1.cmake b/cmake/stm32/l1.cmake new file mode 100644 index 0000000..84feb79 --- /dev/null +++ b/cmake/stm32/l1.cmake @@ -0,0 +1,73 @@ +set(STM32_L1_TYPES + L100xB L100xBA L100xC L151xB L151xBA L151xC L151xCA L151xD + L151xDX L151xE L152xB L152xBA L152xC L152xCA L152xD L152xDX + L152xE L162xC L162xCA L162xD L162xDX L162xE +) +set(STM32_L1_TYPE_MATCH + "L100.[68B]" "L100.[68B]A" "L100.C" "L151.[68B]" "L151.[68B]A" "L151.C" "L151.CA" "L151.D" + "L151.DX" "L151.E" "L152.[68B]" "L152.[68B]A" "L152.C" "L152.CA" "L152.D" "L152.DX" + "L152.E" "L162.C" "L162.CA" "L162.D" "L162.DX" "L162.E" +) +set(STM32_L1_RAM_SIZES + 0K 0K 16K 0K 0K 32K 32K 48K + 80K 80K 0K 0K 32K 32K 48K 80K + 80K 32K 32K 48K 80K 80K +) +set(STM32_L1_CCRAM_SIZES + 0K 0K 0K 0K 0K 0K 0K 0K + 0K 0K 0K 0K 0K 0K 0K 0K + 0K 0K 0K 0K 0K 0K +) + +stm32_util_create_family_targets(L1) + +target_compile_options(STM32::L1 INTERFACE + -mcpu=cortex-m3 +) +target_link_options(STM32::L1 INTERFACE + -mcpu=cortex-m3 +) + +function(stm32l1_get_memory_info DEVICE TYPE FLASH_SIZE RAM_SIZE) + string(REGEX REPLACE "L1[0-9][0-9].([68BCDE])" "\\1" SIZE_CODE ${DEVICE}) + + unset(RAM) + + if((TYPE STREQUAL "L100xB")) + if(SIZE_CODE STREQUAL "6") + set(RAM "4K") + elseif(SIZE_CODE STREQUAL "8") + set(RAM "8K") + elseif(SIZE_CODE STREQUAL "B") + set(RAM "10K") + endif() + elseif((TYPE STREQUAL "L100xBA")) + if(SIZE_CODE STREQUAL "6") + set(RAM "4K") + elseif(SIZE_CODE STREQUAL "8") + set(RAM "8K") + elseif(SIZE_CODE STREQUAL "B") + set(RAM "16K") + endif() + elseif((TYPE STREQUAL "L151xB") OR (TYPE STREQUAL "L152xB")) + if(SIZE_CODE STREQUAL "6") + set(RAM "10K") + elseif(SIZE_CODE STREQUAL "8") + set(RAM "10K") + elseif(SIZE_CODE STREQUAL "B") + set(RAM "16K") + endif() + elseif((TYPE STREQUAL "L151xBA") OR (TYPE STREQUAL "L152xBA")) + if(SIZE_CODE STREQUAL "6") + set(RAM "16K") + elseif(SIZE_CODE STREQUAL "8") + set(RAM "32K") + elseif(SIZE_CODE STREQUAL "B") + set(RAM "32K") + endif() + endif() + + if(RAM) + set(${RAM_SIZE} ${RAM} PARENT_SCOPE) + endif() +endfunction() diff --git a/cmake/stm32/l4.cmake b/cmake/stm32/l4.cmake new file mode 100644 index 0000000..64f70f7 --- /dev/null +++ b/cmake/stm32/l4.cmake @@ -0,0 +1,40 @@ +set(STM32_L4_TYPES + L412xx L422xx L431xx L432xx L433xx L442xx + L443xx L451xx L452xx L462xx L471xx L475xx + L476xx L485xx L486xx L496xx L4A6xx L4P5xx + L4Q5xx L4R5xx L4R7xx L4R9xx L4S5xx L4S7xx + L4S9xx +) +set(STM32_L4_TYPE_MATCH + "L412.." "L422.." "L431.." "L432.." "L433.." "L442.." + "L443.." "L451.." "L452.." "L462.." "L471.." "L475.." + "L476.." "L485.." "L486.." "L496.." "L4A6.." "L4P5.." + "L4Q5.." "L4R5.." "L4R7.." "L4R9.." "L4S5.." "L4S7.." + "L4S9.." +) + +set(STM32_L4_RAM_SIZES + 40K 40K 64K 64K 64K 64K + 64K 160K 160K 160K 96K 96K + 96K 96K 96K 320K 320K 320K + 320K 640K 640K 640K 640K 640K + 640K +) +# on devices where CCRAM is remapped to be contiguous with RAM it is included into RAM section +# If you want to have dedicated section then you will need to use custom linker script +set(STM32_L4_CCRAM_SIZES + 0K 0K 0K 0K 0K 0K + 0K 0K 0K 0K 32K 32K + 32K 32K 32K 0K 0K 0K + 0K 0K 0K 0K 0K 0K + 0K +) + +stm32_util_create_family_targets(L4) + +target_compile_options(STM32::L4 INTERFACE + -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard +) +target_link_options(STM32::L4 INTERFACE + -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard +) diff --git a/cmake/stm32/l5.cmake b/cmake/stm32/l5.cmake new file mode 100644 index 0000000..7663b8b --- /dev/null +++ b/cmake/stm32/l5.cmake @@ -0,0 +1,22 @@ +set(STM32_L5_TYPES + L552xx L562xx +) +set(STM32_L5_TYPE_MATCH + "L552.." "L562.." +) + +set(STM32_L5_RAM_SIZES + 256K 256K +) +set(STM32_L5_CCRAM_SIZES + 0K 0K +) + +stm32_util_create_family_targets(L5) + +target_compile_options(STM32::L5 INTERFACE + -mcpu=cortex-m33 -mfpu=fpv5-sp-d16 -mfloat-abi=hard +) +target_link_options(STM32::L5 INTERFACE + -mcpu=cortex-m33 -mfpu=fpv5-sp-d16 -mfloat-abi=hard +) diff --git a/cmake/stm32/linker_ld.cmake b/cmake/stm32/linker_ld.cmake new file mode 100644 index 0000000..6b15cbb --- /dev/null +++ b/cmake/stm32/linker_ld.cmake @@ -0,0 +1,158 @@ +if((NOT CCRAM_SIZE) OR (CCRAM_SIZE STREQUAL "0K")) + set(CCRAM_DEFINITION "") + set(CCRAM_SECTION "") +else() + set(CCRAM_DEFINITION " CCMRAM (rw) : ORIGIN = ${CCRAM_ORIGIN}, LENGTH = ${CCRAM_SIZE}\n") + set(CCRAM_SECTION " +_siccmram = LOADADDR(.ccmram);\n\ +.ccmram :\n\ +{\n\ +. = ALIGN(4);\n\ +_sccmram = .;\n\ +*(.ccmram)\n\ +*(.ccmram*)\n\ +. = ALIGN(4);\n\ +_eccmram = .;\n\ +} >CCMRAM AT> FLASH\n\ + ") +endif() + +if((NOT RAM_SHARE_SIZE) OR (RAM_SHARE_SIZE STREQUAL "0K")) + set(RAM_SHARE_DEFINITION "") + set(RAM_SHARE_SECTION "") +else() + set(RAM_SHARE_DEFINITION " RAM_SHARED (rw) : ORIGIN = ${RAM_SHARE_ORIGIN}, LENGTH = ${RAM_SHARE_SIZE}\n") + set(RAM_SHARE_SECTION " +MAPPING_TABLE (NOLOAD) : { *(MAPPING_TABLE) } >RAM_SHARED\n\ +MB_MEM1 (NOLOAD) : { *(MB_MEM1) } >RAM_SHARED\n\ +MB_MEM2 (NOLOAD) : { _sMB_MEM2 = . ; *(MB_MEM2) ; _eMB_MEM2 = . ; } >RAM_SHARED\n\ + ") +endif() + +set(SCRIPT_TEXT +"ENTRY(Reset_Handler)\n\ +\n\ +_estack = ${RAM_ORIGIN} + ${RAM_SIZE};\n\ +_Min_Heap_Size = ${HEAP_SIZE};\n\ +_Min_Stack_Size = ${STACK_SIZE};\n\ +\n\ +MEMORY\n\ +{\n\ + FLASH (rx) : ORIGIN = ${FLASH_ORIGIN}, LENGTH = ${FLASH_SIZE}\n\ + RAM (xrw) : ORIGIN = ${RAM_ORIGIN}, LENGTH = ${RAM_SIZE}\n\ +${CCRAM_DEFINITION}\n\ +${RAM_SHARE_DEFINITION}\n\ +}\n\ +\n\ +SECTIONS\n\ +{\n\ + .isr_vector :\n\ + {\n\ + . = ALIGN(4);\n\ + KEEP(*(.isr_vector))\n\ + . = ALIGN(4);\n\ + } >FLASH\n\ +\n\ + .text :\n\ + {\n\ + . = ALIGN(4);\n\ + *(.text)\n\ + *(.text*)\n\ + *(.glue_7)\n\ + *(.glue_7t)\n\ + *(.eh_frame)\n\ +\n\ + KEEP (*(.init))\n\ + KEEP (*(.fini))\n\ +\n\ + . = ALIGN(4);\n\ + _etext = .;\n\ + } >FLASH\n\ +\n\ + .rodata :\n\ + {\n\ + . = ALIGN(4);\n\ + *(.rodata)\n\ + *(.rodata*)\n\ + . = ALIGN(4);\n\ + } >FLASH\n\ +\n\ + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH\n\ + .ARM : {\n\ + __exidx_start = .;\n\ + *(.ARM.exidx*)\n\ + __exidx_end = .;\n\ + } >FLASH\n\ +\n\ + .preinit_array :\n\ + {\n\ + PROVIDE_HIDDEN (__preinit_array_start = .);\n\ + KEEP (*(.preinit_array*))\n\ + PROVIDE_HIDDEN (__preinit_array_end = .);\n\ + } >FLASH\n\ + .init_array :\n\ + {\n\ + PROVIDE_HIDDEN (__init_array_start = .);\n\ + KEEP (*(SORT(.init_array.*)))\n\ + KEEP (*(.init_array*))\n\ + PROVIDE_HIDDEN (__init_array_end = .);\n\ + } >FLASH\n\ + .fini_array :\n\ + {\n\ + PROVIDE_HIDDEN (__fini_array_start = .);\n\ + KEEP (*(SORT(.fini_array.*)))\n\ + KEEP (*(.fini_array*))\n\ + PROVIDE_HIDDEN (__fini_array_end = .);\n\ + } >FLASH\n\ +\n\ + _sidata = LOADADDR(.data);\n\ +\n\ + .data : \n\ + {\n\ + . = ALIGN(4);\n\ + _sdata = .; \n\ + *(.data)\n\ + *(.data*)\n\ +\n\ + . = ALIGN(4);\n\ + _edata = .;\n\ + } >RAM AT> FLASH\n\ +${CCRAM_SECTION}\n\ + . = ALIGN(4);\n\ + .bss :\n\ + {\n\ + _sbss = .;\n\ + __bss_start__ = _sbss;\n\ + *(.bss)\n\ + *(.bss*)\n\ + *(COMMON)\n\ +\n\ + . = ALIGN(4);\n\ + _ebss = .;\n\ + __bss_end__ = _ebss;\n\ + } >RAM\n\ +\n\ + ._user_heap_stack :\n\ + {\n\ + . = ALIGN(8);\n\ + PROVIDE ( end = . );\n\ + PROVIDE ( _end = . );\n\ + . = . + _Min_Heap_Size;\n\ + . = . + _Min_Stack_Size;\n\ + . = ALIGN(8);\n\ + } >RAM\n\ +\n\ + /DISCARD/ :\n\ + {\n\ + libc.a ( * )\n\ + libm.a ( * )\n\ + libgcc.a ( * )\n\ + }\n\ +\n\ + .ARM.attributes 0 : { *(.ARM.attributes) }\n\ +${RAM_SHARE_SECTION}\n\ +}" +) +file(WRITE "${LINKER_SCRIPT}" "${SCRIPT_TEXT}") + + diff --git a/cmake/stm32/mp1.cmake b/cmake/stm32/mp1.cmake new file mode 100644 index 0000000..4c8afd6 --- /dev/null +++ b/cmake/stm32/mp1.cmake @@ -0,0 +1,31 @@ +set(STM32_MP1_TYPES + MP151Axx MP151Cxx + MP153Axx MP153Cxx + MP157Axx MP157Cxx) + +set(STM32_MP1_TYPE_MATCH + "MP151[AD](A.?)?" "MP151[CF](A.?)?" + "MP153[AD](A.?)?" "MP153[CF](A.?)?" + "MP157[AD](A.?)?" "MP157[CF](A.?)?") + +set(STM32_MP1_RAM_SIZES + 384K 384K + 384K 384K + 384K 384K) + +set(STM32_MP1_CCRAM_SIZES + 0K 0K + 0K 0K + 0K 0K) + +stm32_util_create_family_targets(MP1 M4) + +target_compile_options(STM32::MP1::M4 INTERFACE -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard) +target_link_options(STM32::MP1::M4 INTERFACE -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard) +target_compile_definitions(STM32::MP1::M4 INTERFACE CORE_CM4) + +function(stm32mp1_get_memory_info DEVICE TYPE FLASH_SIZE) + if(FLASH_SIZE) + set(${FLASH_SIZE} "0KB" PARENT_SCOPE) + endif() +endfunction() diff --git a/cmake/stm32/u5.cmake b/cmake/stm32/u5.cmake new file mode 100644 index 0000000..4dcbd7b --- /dev/null +++ b/cmake/stm32/u5.cmake @@ -0,0 +1,19 @@ +set(STM32_U5_TYPES + U575xx U585xx +) +set(STM32_U5_TYPE_MATCH + "U575.." "U585.." +) + +set(STM32_U5_RAM_SIZES + 768K 768K +) + +stm32_util_create_family_targets(U5) + +target_compile_options(STM32::U5 INTERFACE + -mcpu=cortex-m33 -mfpu=fpv5-sp-d16 -mfloat-abi=hard +) +target_link_options(STM32::U5 INTERFACE + -mcpu=cortex-m33 -mfpu=fpv5-sp-d16 -mfloat-abi=hard +) diff --git a/cmake/stm32/utilities.cmake b/cmake/stm32/utilities.cmake new file mode 100644 index 0000000..ce05bdb --- /dev/null +++ b/cmake/stm32/utilities.cmake @@ -0,0 +1,161 @@ +function(stm32_util_create_family_targets FAMILY) + set(CORES ${ARGN}) + list(LENGTH CORES NUM_CORES) + if(${NUM_CORES} EQUAL 0) + set(CORE "") + set(CORE_C "") + elseif(${NUM_CORES} EQUAL 1) + set(CORE "_${CORES}") + set(CORE_C "::${CORES}") + else() + message(FATAL_ERROR "Expected at most one core for family ${FAMILY}: ${CORES}") + endif() + + if(NOT (TARGET STM32::${FAMILY}${CORE_C})) + add_library(STM32::${FAMILY}${CORE_C} INTERFACE IMPORTED) + # Set compiler flags for target + # -Wall: all warnings activated + # -ffunction-sections -fdata-sections: remove unused code + target_compile_options(STM32::${FAMILY}${CORE_C} INTERFACE + --sysroot="${TOOLCHAIN_SYSROOT}" + -mthumb -Wall -ffunction-sections -fdata-sections + ) + # Set linker flags + # -mthumb: Generate thumb code + # -Wl,--gc-sections: Remove unused code + target_link_options(STM32::${FAMILY}${CORE_C} INTERFACE + --sysroot="${TOOLCHAIN_SYSROOT}" + -mthumb -Wl,--gc-sections + ) + target_compile_definitions(STM32::${FAMILY}${CORE_C} INTERFACE + STM32${FAMILY} + ) + endif() + foreach(TYPE ${STM32_${FAMILY}_TYPES}) + if(NOT (TARGET STM32::${TYPE}${CORE_C})) + add_library(STM32::${TYPE}${CORE_C} INTERFACE IMPORTED) + target_link_libraries(STM32::${TYPE}${CORE_C} INTERFACE STM32::${FAMILY}${CORE_C}) + target_compile_definitions(STM32::${TYPE}${CORE_C} INTERFACE + STM32${TYPE} + ) + endif() + endforeach() +endfunction() + +include(FetchContent) + +# A CMSIS or HAL driver can specify 'cube' as version number to indicate that the driver is taken from the Cube repository +set(STM32_FETCH_FAMILIES F0 F1 F2 F3 F4 F7 G0 G4 H7 L0 L1 L4 L5 MP1 U5 WB WL ) +set(STM32_FETCH_CUBE_VERSIONS v1.11.2 v1.8.4 v1.9.3 v1.11.2 v1.26.1 v1.16.1 v1.4.1 v1.4.0 v1.9.0 v1.12.0 v1.10.3 v1.17.0 v1.4.0 1.5.0 v1.0.0 v1.12.0 v1.1.0) +set(STM32_FETCH_CMSIS_VERSIONS v2.3.5 v4.3.3 v2.2.5 v2.3.5 v2.6.6 v1.2.6 v1.4.0 v1.2.1 v1.10.0 v1.9.1 v2.3.2 v1.7.1 v1.0.4 cube v1.0.0 v1.9.0 v1.1.0) +set(STM32_FETCH_HAL_VERSIONS v1.7.5 v1.1.8 v1.2.7 v1.5.5 v1.7.12 v1.2.9 v1.4.1 v1.2.1 v1.10.0 v1.10.4 v1.4.4 v1.13.0 v1.0.4 cube v1.0.0 v1.9.0 v1.1.0) + +FetchContent_Declare( + STM32-CMSIS + GIT_REPOSITORY https://github.com/STMicroelectronics/cmsis_core/ + GIT_TAG v5.6.0 + GIT_PROGRESS TRUE +) + +set(IDX 0) +foreach(FAMILY ${STM32_FETCH_FAMILIES}) + string(TOLOWER ${FAMILY} FAMILY_L) + list(GET STM32_FETCH_CUBE_VERSIONS ${IDX} CUBE_VERSION) + list(GET STM32_FETCH_CMSIS_VERSIONS ${IDX} CMSIS_VERSION) + list(GET STM32_FETCH_HAL_VERSIONS ${IDX} HAL_VERSION) + + FetchContent_Declare( + STM32Cube${FAMILY} + GIT_REPOSITORY https://github.com/STMicroelectronics/STM32Cube${FAMILY}/ + GIT_TAG ${CUBE_VERSION} + GIT_PROGRESS TRUE + ) + + if(CMSIS_VERSION STREQUAL cube) + set(STM32_USE_CMSIS_FROM_CUBE_${FAMILY} ON) + else() + FetchContent_Declare( + STM32-CMSIS-${FAMILY} + GIT_REPOSITORY https://github.com/STMicroelectronics/cmsis_device_${FAMILY_L}/ + GIT_TAG ${CMSIS_VERSION} + GIT_PROGRESS TRUE + ) + endif() + + if(HAL_VERSION STREQUAL cube) + set(STM32_USE_HAL_FROM_CUBE_${FAMILY} ON) + else() + FetchContent_Declare( + STM32-HAL-${FAMILY} + GIT_REPOSITORY https://github.com/STMicroelectronics/stm32${FAMILY_L}xx_hal_driver/ + GIT_TAG ${HAL_VERSION} + GIT_PROGRESS TRUE + ) + endif() + + math(EXPR IDX "${IDX} + 1") +endforeach() + +function(stm32_fetch_cube) + foreach(FAMILY ${ARGV}) + set(CUBE_NAME STM32Cube${FAMILY}) + string(TOLOWER ${CUBE_NAME} CUBE_NAME_L) + + if(STM32_CUBE_${FAMILY}_PATH) + message(VERBOSE "STM32_CUBE_${FAMILY}_PATH specified, skipping fetch for ${CUBE_NAME}") + continue() + endif() + + FetchContent_MakeAvailable(${CUBE_NAME}) + set(STM32_CUBE_${FAMILY}_PATH ${${CUBE_NAME_L}_SOURCE_DIR} PARENT_SCOPE) + endforeach() +endfunction() + +function(stm32_fetch_cmsis) + if(NOT STM32_CMSIS_PATH) + FetchContent_MakeAvailable(STM32-CMSIS) + set(STM32_CMSIS_PATH ${stm32-cmsis_SOURCE_DIR} PARENT_SCOPE) + else() + message(INFO "STM32_CMSIS_PATH specified, skipping fetch for STM32-CMSIS") + endif() + + foreach(FAMILY ${ARGV}) + if(STM32_USE_CMSIS_FROM_CUBE_${FAMILY}) + stm32_fetch_cube(${FAMILY}) + message(STATUS "Cube fetched for ${FAMILY} at ${STM32_CUBE_${FAMILY}_PATH}") + set(STM32_CMSIS_${FAMILY}_PATH ${STM32_CUBE_${FAMILY}_PATH}/Drivers/CMSIS/Device/ST/STM32${FAMILY}xx PARENT_SCOPE) + else() + set(CMSIS_NAME STM32-CMSIS-${FAMILY}) + string(TOLOWER ${CMSIS_NAME} CMSIS_NAME_L) + + if(STM32_CMSIS_${FAMILY}_PATH) + message(INFO "STM32_CMSIS_${FAMILY}_PATH specified, skipping fetch for ${CMSIS_NAME}") + continue() + endif() + + FetchContent_MakeAvailable(${CMSIS_NAME}) + set(STM32_CMSIS_${FAMILY}_PATH ${${CMSIS_NAME_L}_SOURCE_DIR} PARENT_SCOPE) + endif() + endforeach() +endfunction() + +function(stm32_fetch_hal) + foreach(FAMILY ${ARGV}) + if(STM32_USE_HAL_FROM_CUBE_${FAMILY}) + stm32_fetch_cube(${FAMILY}) + message(STATUS "Cube fetched for ${FAMILY} at ${STM32_CUBE_${FAMILY}_PATH}") + set(STM32_HAL_${FAMILY}_PATH ${STM32_CUBE_${FAMILY}_PATH}/Drivers/STM32${FAMILY}xx_HAL_Driver PARENT_SCOPE) + else() + set(HAL_NAME STM32-HAL-${FAMILY}) + string(TOLOWER ${HAL_NAME} HAL_NAME_L) + + if(STM32_HAL_${FAMILY}_PATH) + message(INFO "STM32_HAL_${FAMILY}_PATH specified, skipping fetch for ${HAL_NAME}") + continue() + endif() + + FetchContent_MakeAvailable(${HAL_NAME}) + set(STM32_HAL_${FAMILY}_PATH ${${HAL_NAME_L}_SOURCE_DIR} PARENT_SCOPE) + endif() + endforeach() +endfunction() diff --git a/cmake/stm32/wb.cmake b/cmake/stm32/wb.cmake new file mode 100644 index 0000000..77dfbec --- /dev/null +++ b/cmake/stm32/wb.cmake @@ -0,0 +1,38 @@ +set(STM32_WB_TYPES + WB55xx WB55xx WB35xx WB15xx WB50xx WB30xx WB10xx WB5Mxx +) +set(STM32_WB_TYPE_MATCH + "WB55.C" "WB55.[EGY]" "WB35.." "WB15.." "WB50.." "WB30.." "WB10.." "WB5M.." +) + +# this is not full RAM of the chip but only the part allocated to M4 core (SRAM1 in datasheet) +set(STM32_WB_RAM_SIZES + 64K 192K 32K 12K 64K 32K 12K 192K +) + +# WB series need special area for SRAM2 shared with core M0PLUS +set(STM32_WB_RAM_SHARE_SIZES + 10K 10K 10K 10K 10K 10K 10K 10K +) + +set(STM32_WB_CCRAM_SIZES + 0K 0K 0K 0K 0K 0K 0K 0K +) + +stm32_util_create_family_targets(WB M4) + +target_compile_options(STM32::WB::M4 INTERFACE + -mcpu=cortex-m4 -mfpu=fpv5-sp-d16 -mfloat-abi=hard +) +target_link_options(STM32::WB::M4 INTERFACE + -mcpu=cortex-m4 -mfpu=fpv5-sp-d16 -mfloat-abi=hard +) + +function(stm32wb_get_memory_info DEVICE TYPE CORE RAM RAM_ORIGIN TWO_FLASH_BANKS) + set(${TWO_FLASH_BANKS} TRUE PARENT_SCOPE) + list(FIND STM32_WB_TYPES ${TYPE} TYPE_INDEX) + list(GET STM32_WB_RAM_SIZES ${TYPE_INDEX} RAM_VALUE) + set(${RAM} "${RAM_VALUE}-4" PARENT_SCOPE) + set(${RAM_ORIGIN} 0x20000004 PARENT_SCOPE) +endfunction() + diff --git a/cmake/stm32/wl.cmake b/cmake/stm32/wl.cmake new file mode 100644 index 0000000..eb54897 --- /dev/null +++ b/cmake/stm32/wl.cmake @@ -0,0 +1,77 @@ +set(STM32_WL_TYPES + WL54xx WL55xx WLE4xx WLE5xx WLE4xx WLE5xx WLE4xx WLE5xx +) +set(STM32_WL_TYPE_MATCH + "WL54.." "WL55.." "WLE4.8" "WLE5.8" "WLE4.B" "WLE5.B" "WLE4.C" "WLE5.C" +) + +# this is RAM size allocated to M4 core +# Note devices with 20 and 48K RAM can use only half of available RAM because +# there are 2 split sections of RAM and our default linker script only manages +# one section. +set(STM32_WL_RAM_SIZES + 32K 32K 10K 10K 24K 24K 64K 64K +) + +# this is RAM size allocated to M0PLUS core +set(STM32_WL_M0PLUS_RAM_SIZES + 32K 32K 0K 0K 0K 0K 0K 0K +) + +set(STM32_WL_CCRAM_SIZES + 0K 0K 0K 0K 0K 0K 0K 0K +) + +set(STM32_WL_DUAL_CORE + WL54xx WL55xx +) + +stm32_util_create_family_targets(WL M4) + +target_compile_options(STM32::WL::M4 INTERFACE + -mcpu=cortex-m4 -mfloat-abi=soft +) +target_link_options(STM32::WL::M4 INTERFACE + -mcpu=cortex-m4 -mfloat-abi=soft +) + +stm32_util_create_family_targets(WL M0PLUS) + +target_compile_options(STM32::WL::M0PLUS INTERFACE + -mcpu=cortex-m0plus -mfloat-abi=soft +) +target_link_options(STM32::WL::M0PLUS INTERFACE + -mcpu=cortex-m0plus -mfloat-abi=soft +) + +function(stm32wl_get_memory_info DEVICE TYPE CORE RAM FLASH_ORIGIN RAM_ORIGIN TWO_FLASH_BANKS) + if(${TYPE} IN_LIST STM32_WL_DUAL_CORE) + set(${TWO_FLASH_BANKS} TRUE PARENT_SCOPE) + else() + set(${TWO_FLASH_BANKS} FALSE PARENT_SCOPE) + endif() + list(FIND STM32_WL_TYPES ${TYPE} TYPE_INDEX) + if(CORE STREQUAL "M4") + list(GET STM32_WL_RAM_SIZES ${TYPE_INDEX} RAM_VALUE) + set(${RAM} ${RAM_VALUE} PARENT_SCOPE) + set(${FLASH_ORIGIN} 0x8000000 PARENT_SCOPE) + set(${RAM_ORIGIN} 0x20000000 PARENT_SCOPE) + elseif((${TYPE} IN_LIST STM32_WL_DUAL_CORE) AND (CORE STREQUAL "M0PLUS")) + list(GET STM32_WL_M0PLUS_RAM_SIZES ${TYPE_INDEX} RAM_VALUE) + set(${RAM} ${RAM_VALUE} PARENT_SCOPE) + set(${FLASH_ORIGIN} 0x8020000 PARENT_SCOPE) + set(${RAM_ORIGIN} 0x20008000 PARENT_SCOPE) + else() + message(FATAL_ERROR "Unknown core ${CORE}") + endif() +endfunction() + + + +function(stm32wl_get_device_cores DEVICE TYPE CORES) + if(${TYPE} IN_LIST STM32_WL_DUAL_CORE) + set(${CORES} M4 M0PLUS PARENT_SCOPE) + else() + set(${CORES} M4 PARENT_SCOPE) + endif() +endfunction() \ No newline at end of file diff --git a/cmake/stm32_gcc.cmake b/cmake/stm32_gcc.cmake new file mode 100644 index 0000000..6e63c4f --- /dev/null +++ b/cmake/stm32_gcc.cmake @@ -0,0 +1,23 @@ +if(${CMAKE_VERSION} VERSION_LESS "3.16.0") + message(WARNING "Current CMake version is ${CMAKE_VERSION}. stm32-cmake requires CMake 3.16 or greater") + +endif() + +get_filename_component(STM32_CMAKE_DIR ${CMAKE_CURRENT_LIST_FILE} DIRECTORY) +list(APPEND CMAKE_MODULE_PATH ${STM32_CMAKE_DIR}) + +include(stm32/common) +include(stm32/devices) + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +find_program(CMAKE_C_COMPILER NAMES ${STM32_TARGET_TRIPLET}-gcc HINTS ${TOOLCHAIN_BIN_PATH}) +find_program(CMAKE_CXX_COMPILER NAMES ${STM32_TARGET_TRIPLET}-g++ HINTS ${TOOLCHAIN_BIN_PATH}) +find_program(CMAKE_ASM_COMPILER NAMES ${STM32_TARGET_TRIPLET}-gcc HINTS ${TOOLCHAIN_BIN_PATH}) + +set(CMAKE_EXECUTABLE_SUFFIX_C .elf) +set(CMAKE_EXECUTABLE_SUFFIX_CXX .elf) +set(CMAKE_EXECUTABLE_SUFFIX_ASM .elf) + +# This should be safe to set for a bare-metal cross-compiler +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..8ff01b4 --- /dev/null +++ b/flake.lock @@ -0,0 +1,43 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1670929434, + "narHash": "sha256-n5UBO6XBV4h3TB7FYu2yAuNQMEYOrQyKeODUwKe06ow=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1710ed1f6f8ceb75cf7d1cf55ee0cc21760e1c7a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "utils": "utils" + } + }, + "utils": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..d4ef850 --- /dev/null +++ b/flake.nix @@ -0,0 +1,54 @@ +{ + description = "STM32 Dev"; + + inputs.utils.url = "github:numtide/flake-utils"; + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + outputs = { self, nixpkgs, utils, ... }: + utils.lib.eachSystem [ "i686-linux" "x86_64-linux" ] + (system: + let + libstm32cubef1 = with pkgs; stdenv.mkDerivation { + name = "stm32CubeF1"; + + src = fetchFromGitHub { + owner = "STMicroelectronics"; + repo = "STM32CubeF1"; + rev = "c750eab6990cac35ab05020793b0221ecc1a8ce5"; + sha256 = "sha256-ICGgQCkY5E5Lcd7+U+hX5+MJcTF7J51NFDx6iy/SfgA="; + }; + + installPhase = '' + mkdir $out + cp -r ./* $out + ''; + }; + + libstm32stdperiph = with pkgs; stdenv.mkDerivation { + name = "stm32f10x-stdperiph-lib"; + + src = fetchFromGitHub { + owner = "wajatimur"; + repo = "stm32f10x-stdperiph-lib"; + rev = "master"; + sha256 = "sha256-aLXLe9bT0XbQohfSCWZcRfVvDkUreqKboqUUFkNPkzg="; + }; + + installPhase = '' + mkdir $out + cp -r ./* $out + ''; + + }; + + pkgs = nixpkgs.legacyPackages.${system}; + in + { + devShell = import ./shell.nix { + inherit pkgs; + libstm32cube = libstm32cubef1; + libstm32stdperiph = libstm32stdperiph; + }; + } + ); +} diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..c634793 --- /dev/null +++ b/main.cpp @@ -0,0 +1,128 @@ +#include + +#include "spi.hpp" +#include "uart_handler.hpp" + +// STM32VL-Discovery green led - PC9 +#define BTN_PORT GPIOA +#define LED_PORT GPIOC +#define LED1_PIN GPIO_PIN_8 +#define LED2_PIN GPIO_PIN_9 +#define BTN_PIN GPIO_PIN_0 +#define LED_PORT_CLK_ENABLE __HAL_RCC_GPIOC_CLK_ENABLE + +constexpr auto UART_PORT = GPIOA_BASE; + +#define UARTPORT GPIOA +#define UARTTX_PIN GPIO_PIN_9 +#define UARTRX_PIN GPIO_PIN_10 + +#define LoRa_RESET_Pin GPIO_PIN_3 +#define LoRa_RESET_GPIO_Port GPIOA +#define LoRa_CS_Pin GPIO_PIN_4 +#define LoRa_CS_GPIO_Port GPIOA + +#include "rfm95.hpp" + +extern uint8_t LoRa_buff[RH_RF95_FIFO_SIZE]; +extern SPI_HandleTypeDef hspi1; + +// This prevent name mangling for functions used in C/assembly files. +extern "C" { +void SysTick_Handler(void) { + HAL_IncTick(); + HAL_SYSTICK_IRQHandler(); +} +} + +void initGPIO() { + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + + GPIO_InitTypeDef GPIO_Config2; + GPIO_Config2.Mode = GPIO_MODE_INPUT; + GPIO_Config2.Pull = GPIO_PULLDOWN; + GPIO_Config2.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_Config2.Pin = BTN_PIN; + + GPIO_InitTypeDef GPIO_Config; + GPIO_Config.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_Config.Pull = GPIO_NOPULL; + GPIO_Config.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_Config.Pin = LED1_PIN | LED2_PIN; + + GPIO_InitTypeDef GPIO_ConfigSPI; + GPIO_ConfigSPI.Mode = GPIO_MODE_OUTPUT_PP; + // GPIO_ConfigSPI.Pull = GPIO_NOPULL; + GPIO_ConfigSPI.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_ConfigSPI.Pin = LoRa_CS_Pin | LoRa_RESET_Pin; + + // bare metal init of led1: + // volatile uint32_t* CRH = reinterpret_cast(0x40011000 + 0x04); + //*CRH |= 0x3; + //*CRH &= (~0xC); + + HAL_GPIO_Init(LED_PORT, &GPIO_Config); + HAL_GPIO_Init(BTN_PORT, &GPIO_Config2); + HAL_GPIO_Init(LoRa_CS_GPIO_Port, &GPIO_ConfigSPI); + // HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); + // HAL_GPIO_WritePin(LoRa_RESET_GPIO_Port, LoRa_RESET_Pin, GPIO_PIN_SET); +} + +extern "C" { +#include +} + +using uart_interface = + uart_handler; + +int main(void) { + HAL_Init(); + HAL_SYSTICK_Config(1); + initGPIO(); + + if (!uart_interface::init()) { + // toggle status led or something + } + + uart_interface::write("UART Initialized."); + + if (!MX_SPI1_Init()) { + // toggle status led or something + } + + HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); + HAL_GPIO_WritePin(LoRa_RESET_GPIO_Port, LoRa_RESET_Pin, GPIO_PIN_SET); + HAL_Delay(10); + + uart_interface::write("SPI1 Initialized."); + uart_interface::write("Initialization done."); + + char OP_Mode = 0x01; + char buff = 0x7F & OP_Mode; + char res = 0; + + HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_RESET); + auto result = HAL_SPI_Transmit(&hspi1, (uint8_t *)&buff, 1, 100); + HAL_SPI_Receive(&hspi1, (uint8_t *)&res, 1, 100); + HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); + + RF95_Init(); + while (1) { + RF95_setModeRx_Continuous(); + HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET); + RF95_receive(LoRa_buff); + HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET); + + std::string_view msg{reinterpret_cast(LoRa_buff)}; + uart_interface::write("Received Message:"); + uart_interface::write(msg); + + // std::string_view foo{"Das ist ein test"}; + // strcpy((char *)LoRa_buff, foo.data()); + + // RF95_send(LoRa_buff); + } + + return 0; +} diff --git a/rfm95.cpp b/rfm95.cpp new file mode 100644 index 0000000..2e80322 --- /dev/null +++ b/rfm95.cpp @@ -0,0 +1,773 @@ +#include "rfm95.hpp" + +#define LoRa_RESET_Pin GPIO_PIN_3 +#define LoRa_RESET_GPIO_Port GPIOA +#define LoRa_CS_Pin GPIO_PIN_4 +#define LoRa_CS_GPIO_Port GPIOA + +extern SPI_HandleTypeDef hspi1; + +RHMode _mode; +uint16_t _cad_timeout = 10000; +uint8_t LoRa_buff[RH_RF95_FIFO_SIZE] = {0}; + +#if Header == Header_used +char _txHeaderTo = 0; +#endif + +char MODEM_CONFIG_TABLE[5][3] = { + // 1d, 1e, 26 + {0x72, 0x74, 0x00}, // Bw125Cr45Sf128 (the chip default) + {0x92, 0x74, 0x00}, // Bw500Cr45Sf128 + {0x48, 0x94, 0x00}, // Bw31_25Cr48Sf512 + {0x78, 0xc4, 0x00}, // Bw125Cr48Sf4096 + {0x73, 0x74, + 0x00}, // IH_Bw125Cr45Sf128 (the chip default + Implicit header) +}; + +HAL_StatusTypeDef err; +HAL_StatusTypeDef RF95_write(char reg, char wValue) { + char buff[2] = {0}; + + buff[0] = W | reg; + buff[1] = wValue; + + HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_RESET); + err = HAL_SPI_Transmit(&hspi1, (uint8_t *)&buff, 2, 100); + HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); + + return err; +} + +HAL_StatusTypeDef RF95_write_burst(char reg, uint8_t *data) { + int length = 0; + uint8_t cmd = W | reg; + HAL_StatusTypeDef err; + + length = strlen((const char *)data); + + HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_RESET); + HAL_SPI_Transmit(&hspi1, (uint8_t *)&cmd, 1, 100); + err = HAL_SPI_Transmit(&hspi1, (uint8_t *)&LoRa_buff, length, 100); + HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); + + return err; +} + +char RF95_read(char reg) { + char buff = R & reg; + + HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_RESET); + HAL_SPI_Transmit(&hspi1, (uint8_t *)&buff, 1, 100); + HAL_SPI_Receive(&hspi1, (uint8_t *)&buff, 1, 100); + HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); + + return buff; +} + +HAL_StatusTypeDef RF95_read_burst(char reg, char *buffer, int length) { + buffer[0] = R & reg; + HAL_StatusTypeDef err; + + HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_RESET); + HAL_SPI_Transmit(&hspi1, (uint8_t *)buffer, 1, 100); + err = HAL_SPI_Receive(&hspi1, (uint8_t *)buffer, length, 100); + HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); + + return err; +} + +void RF95_Reset(void) { + HAL_GPIO_WritePin(LoRa_RESET_GPIO_Port, LoRa_RESET_Pin, GPIO_PIN_RESET); + HAL_Delay(20); + HAL_GPIO_WritePin(LoRa_RESET_GPIO_Port, LoRa_RESET_Pin, GPIO_PIN_SET); +} + +uint8_t rbuff = 0; +bool RF95_Init(void) { + RF95_Reset(); + + // Set sleep mode, so we can also set LORA mode: + RF95_sleep(); + + RF95_write(RH_RF95_REG_01_OP_MODE, + RH_RF95_MODE_SLEEP | RH_RF95_LONG_RANGE_MODE); + HAL_Delay(20); // Wait for sleep mode to take over from say, CAD + + // Check we are in sleep mode, with LORA set + rbuff = RF95_read(RH_RF95_REG_01_OP_MODE); + if (rbuff != (RH_RF95_MODE_SLEEP | RH_RF95_LONG_RANGE_MODE)) { + return false; // No device present? + } + + // Set up FIFO + // We configure so that we can use the entire 256 byte FIFO for either receive + // or transmit, but not both at the same time + RF95_write(RH_RF95_REG_0E_FIFO_TX_BASE_ADDR, 0); + RF95_write(RH_RF95_REG_0F_FIFO_RX_BASE_ADDR, 0); + + // Packet format is preamble + explicit-header + payload + crc + // Explicit Header Mode + // payload is TO + FROM + ID + FLAGS + message data + // RX mode is implmented with RXCONTINUOUS + // max message data length is 255 - 4 = 251 octets + + RF95_setModeIdle(); + + // Set up default configuration + // No Sync Words in LORA mode. + RF95_setModemConfig(Bw125Cr45Sf128); // Radio default + RF95_setPreambleLength(8); // Default is 8 + // An innocuous ISM frequency, same as RF22's + RF95_setFrequency(868.0); + // Lowish power + RF95_setTxPower(13, false); + + return true; +} + +bool RF95_setModemConfig(ModemConfigChoice index) { + RF95_write(RH_RF95_REG_1D_MODEM_CONFIG1, MODEM_CONFIG_TABLE[index][0]); + RF95_write(RH_RF95_REG_1E_MODEM_CONFIG2, MODEM_CONFIG_TABLE[index][1]); + RF95_write(RH_RF95_REG_26_MODEM_CONFIG3, MODEM_CONFIG_TABLE[index][2]); + + return true; +} + +void RF95_setPreambleLength(uint16_t bytes) { + RF95_write(RH_RF95_REG_20_PREAMBLE_MSB, bytes >> 8); + RF95_write(RH_RF95_REG_21_PREAMBLE_LSB, bytes & 0xff); +} + +bool RF95_setFrequency(float centre) { + // Frf = FRF / FSTEP + uint64_t frf = + (uint32_t)((uint32_t)centre * 1000000.0) / (uint32_t)RH_RF95_FSTEP; + RF95_write(RH_RF95_REG_06_FRF_MSB, (frf >> 16) & 0xff); + RF95_write(RH_RF95_REG_07_FRF_MID, (frf >> 8) & 0xff); + RF95_write(RH_RF95_REG_08_FRF_LSB, frf & 0xff); + + return true; +} + +void RF95_setTxPower(int8_t power, bool useRFO) { + // Sigh, different behaviours depending on whther the module use PA_BOOST or + // the RFO pin for the transmitter output + if (useRFO) { + if (power > 14) power = 14; + if (power < -1) power = -1; + RF95_write(RH_RF95_REG_09_PA_CONFIG, RH_RF95_MAX_POWER | (power + 1)); + } else { + if (power > 23) power = 23; + if (power < 5) power = 5; + + // For RH_RF95_PA_DAC_ENABLE, manual says '+20dBm on PA_BOOST when + // OutputPower=0xf' RH_RF95_PA_DAC_ENABLE actually adds about 3dBm to all + // power levels. We will us it for 21 and 23dBm + if (power > 20) { + RF95_write(RH_RF95_REG_4D_PA_DAC, RH_RF95_PA_DAC_ENABLE); + power -= 3; + } else { + RF95_write(RH_RF95_REG_4D_PA_DAC, RH_RF95_PA_DAC_DISABLE); + } + + // RFM95/96/97/98 does not have RFO pins connected to anything. Only + // PA_BOOST pin is connected, so must use PA_BOOST Pout = 2 + OutputPower. + // The documentation is pretty confusing on this topic: PaSelect says the + // max power is 20dBm, but OutputPower claims it would be 17dBm. My + // measurements show 20dBm is correct + RF95_write(RH_RF95_REG_09_PA_CONFIG, RH_RF95_PA_SELECT | (power - 5)); + } +} + +bool RF95_receive(uint8_t *data) { + int len = 0; + + if (_mode == RHModeRx) { + while (!RF95_available()) { + } + + if (RF95_Check_PayloadCRCError()) return false; + + len = RF95_read(RH_RF95_REG_13_RX_NB_BYTES); + + // Reset the fifo read ptr to the beginning of the packet + RF95_write(RH_RF95_REG_0D_FIFO_ADDR_PTR, + RF95_read(RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR)); + + RF95_read_burst(RH_RF95_REG_00_FIFO, (char *)data, len); + + RF95_setModeIdle(); + + RF95_Clear_IRQ(); + + return true; + } else + return false; +} + +bool RF95_receive_Timeout(uint8_t *buf, uint16_t timeout) { + int len = 0; + + if (_mode == RHModeRx) { + if (!RF95_available_Timeout(timeout)) { + return false; + } + + if (RF95_Check_PayloadCRCError()) return false; + + len = RF95_read(RH_RF95_REG_13_RX_NB_BYTES); + + // Reset the fifo read ptr to the beginning of the packet + RF95_write(RH_RF95_REG_0D_FIFO_ADDR_PTR, + RF95_read(RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR)); + + RF95_read_burst(RH_RF95_REG_00_FIFO, (char *)buf, len); + + RF95_setModeIdle(); + + RF95_Clear_IRQ(); + + if (RF95_Check_PayloadCRCError()) { + return false; + } else { + return true; + } + } else + return false; +} + +bool RF95_send(uint8_t *data) { + int len = strlen((char *)data); + +#if Header == Header_used + uint16_t header_len = sizeof(_txHeaderTo); +#endif + + if (len > RH_RF95_MAX_MESSAGE_LEN) return false; + + RF95_waitPacketSent(); // Make sure we dont interrupt an outgoing message + RF95_setModeIdle(); + + if (!RF95_waitCAD()) return false; // Check channel activity + + RF95_setModeIdle(); + + // Position at the beginning of the FIFO + RF95_write(RH_RF95_REG_0D_FIFO_ADDR_PTR, 0); + + // The headers +#if Header == Header_used + RF95_write(RH_RF95_REG_00_FIFO, _txHeaderTo); +#endif + + // The message data + RF95_write_burst(RH_RF95_REG_00_FIFO, data); + +#if Header == No_header + RF95_write(RH_RF95_REG_22_PAYLOAD_LENGTH, len); +#else + RF95_write(RH_RF95_REG_22_PAYLOAD_LENGTH, len + header_len); +#endif + + // uint8_t rBuff[15] = {0}; + // uint16_t lenght_ = + // RF95_read(RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR); + // RF95_write(RH_RF95_REG_0D_FIFO_ADDR_PTR, lenght_); + // RF95_read_burst(RH_RF95_REG_00_FIFO,(char*)rBuff, len); + + RF95_setModeTx(); // Start the transmitter + while (!RF95_Check_TxDone()) { + } + + RF95_setModeIdle(); + + RF95_Clear_IRQ(); + return true; +} + +bool RF95_waitCAD(void) { + if (!_cad_timeout) return true; + + // Wait for any channel activity to finish or timeout + // Sophisticated DCF function... + // DCF : BackoffTime = random() x aSlotTime + // 100 - 1000 ms + // 10 sec timeout + + RF95_setModeCAD(); + + unsigned long t = HAL_GetTick(); + while (!RF95_Check_CADDone()) { + if (HAL_GetTick() - t > _cad_timeout) return false; + } + + return true; +} + +bool RF95_waitPacketSent(void) { + if (_mode == RHModeTx) { + while (!RF95_Check_TxDone()) + ; + } + + return true; +} + +bool RF95_available(void) { + while (!RF95_Check_RxDone()) { + } + + if (RF95_Check_ValidHeader()) { + RF95_Clear_IRQ(); + return true; + } else + return false; +} + +bool RF95_available_Timeout(uint16_t timeout) { + unsigned long t = HAL_GetTick(); + + while (!RF95_Check_RxDone()) { + if (HAL_GetTick() - t > timeout) return false; + } + + if (RF95_Check_ValidHeader()) { + RF95_Clear_IRQ(); + return true; + } else + return false; +} + +void RF95_setModeCAD(void) { + if (_mode != RHModeCad) { + RF95_write(RH_RF95_REG_01_OP_MODE, RH_RF95_MODE_CAD); + RF95_write(RH_RF95_REG_40_DIO_MAPPING1, 0x80); // Interrupt on CadDone + _mode = RHModeCad; + } +} + +uint8_t aux = 0; +void RF95_setModeIdle(void) { + // uint8_t aux = 0; + if (_mode != RHModeIdle) { + aux = RF95_read(RH_RF95_REG_01_OP_MODE); + aux &= 0xF8; + aux |= RH_RF95_MODE_STDBY; + RF95_write(RH_RF95_REG_01_OP_MODE, aux); + _mode = RHModeIdle; + } +} + +bool RF95_sleep(void) { + // uint8_t aux = 0; + if (_mode != RHModeSleep) { + aux = RF95_read(RH_RF95_REG_01_OP_MODE); + aux &= 0xF8; + aux |= RH_RF95_MODE_SLEEP; + RF95_write(RH_RF95_REG_01_OP_MODE, aux); + _mode = RHModeSleep; + } + return true; +} + +void RF95_setModeRx_Single(void) { + // uint8_t aux = 0; + if (_mode != RHModeRx) { + aux = RF95_read(RH_RF95_REG_01_OP_MODE); + aux &= 0xF8; + aux |= RH_RF95_MODE_RXSINGLE; + RF95_write(RH_RF95_REG_01_OP_MODE, aux); + RF95_write(RH_RF95_REG_40_DIO_MAPPING1, 0x00); // Interrupt on RxDone + _mode = RHModeRx; + } +} + +void RF95_setModeRx_Continuous(void) { + // uint8_t aux = 0; + if (_mode != RHModeRx) { + aux = RF95_read(RH_RF95_REG_01_OP_MODE); + aux &= 0xF8; + aux |= RH_RF95_MODE_RXCONTINUOUS; + RF95_write(RH_RF95_REG_01_OP_MODE, aux); + RF95_write(RH_RF95_REG_40_DIO_MAPPING1, 0x00); // Interrupt on RxDone + _mode = RHModeRx; + } +} + +void RF95_setModeTx(void) { + // uint8_t aux = 0; + if (_mode != RHModeTx) { + aux = RF95_read(RH_RF95_REG_01_OP_MODE); + aux &= 0xF8; + aux |= RH_RF95_MODE_TX; + RF95_write(RH_RF95_REG_01_OP_MODE, aux); + RF95_write(RH_RF95_REG_40_DIO_MAPPING1, 0x40); // Interrupt on TxDone + _mode = RHModeTx; + } +} + +bool RF95_Check_RxTimeout(void) { + char reg_read = 0; + reg_read = RF95_read(RH_RF95_REG_12_IRQ_FLAGS); + reg_read = (reg_read & RH_RF95_RX_TIMEOUT) >> 7; + + return reg_read; +} + +bool RF95_Check_RxDone(void) { + char reg_read = 0; + reg_read = RF95_read(RH_RF95_REG_12_IRQ_FLAGS); + reg_read = (reg_read & RH_RF95_RX_DONE) >> 6; + + return reg_read; +} + +bool RF95_Check_PayloadCRCError(void) { + char reg_read = 0; + reg_read = RF95_read(RH_RF95_REG_12_IRQ_FLAGS); + reg_read = (reg_read & RH_RF95_PAYLOAD_CRC_ERROR) >> 5; + + return reg_read; +} + +bool RF95_Check_ValidHeader(void) { + char reg_read = 0; + reg_read = RF95_read(RH_RF95_REG_12_IRQ_FLAGS); + + reg_read = (reg_read & RH_RF95_VALID_HEADER) >> 4; + + return reg_read; +} + +bool RF95_Check_TxDone(void) { + char reg_read = 0; + reg_read = RF95_read(RH_RF95_REG_12_IRQ_FLAGS); + + reg_read = (reg_read & RH_RF95_TX_DONE) >> 3; + + return reg_read; +} + +bool RF95_Check_CADDone(void) { + char reg_read = 0; + reg_read = RF95_read(RH_RF95_REG_12_IRQ_FLAGS); + reg_read = (reg_read & RH_RF95_CAD_DONE) >> 2; + + return reg_read; +} + +bool RF95_Check_FhssChannelChange(void) { + char reg_read = 0; + reg_read = RF95_read(RH_RF95_REG_12_IRQ_FLAGS); + reg_read = (reg_read & RH_RF95_FHSS_CHANGE_CHANNEL) >> 1; + + return reg_read; +} + +bool RF95_Check_CADDetect(void) { + char reg_read = 0; + reg_read = RF95_read(RH_RF95_REG_12_IRQ_FLAGS); + reg_read = (reg_read & RH_RF95_CAD_DETECTED); + + return reg_read; +} + +void RF95_Clear_IRQ(void) { + uint8_t irq_flags = 0; + + RF95_write(RH_RF95_REG_12_IRQ_FLAGS, 0xFF); + + irq_flags = RF95_read(RH_RF95_REG_12_IRQ_FLAGS); + if (irq_flags != 0) RF95_write(RH_RF95_REG_12_IRQ_FLAGS, 0xFF); +} + +bool RF95_Check_ModemClear(void) { + char reg_read = 0; + reg_read = RF95_read(RH_RF95_REG_18_MODEM_STAT); + reg_read = (reg_read & RH_RF95_MODEM_STATUS_CLEAR) >> 4; + + return reg_read; +} + +bool RF95_Check_HeaderInfoValid(void) { + char reg_read = 0; + reg_read = RF95_read(RH_RF95_REG_18_MODEM_STAT); + reg_read = (reg_read & RH_RF95_MODEM_STATUS_HEADER_INFO_VALID) >> 3; + + return reg_read; +} + +bool RF95_Check_RxOnGoing(void) { + char reg_read = 0; + reg_read = RF95_read(RH_RF95_REG_18_MODEM_STAT); + reg_read = (reg_read & RH_RF95_MODEM_STATUS_RX_ONGOING) >> 2; + + return reg_read; +} + +bool RF95_Check_SignalSyncronized(void) { + char reg_read = 0; + reg_read = RF95_read(RH_RF95_REG_18_MODEM_STAT); + reg_read = (reg_read & RH_RF95_MODEM_STATUS_SIGNAL_SYNCHRONIZED) >> 1; + + return reg_read; +} + +bool RF95_Check_SignalDetect(void) { + char reg_read = 0; + reg_read = RF95_read(RH_RF95_REG_18_MODEM_STAT); + reg_read = (reg_read & RH_RF95_MODEM_STATUS_SIGNAL_DETECTED); + + return reg_read; +} + +uint16_t ComputeCRC(uint16_t crc, uint8_t data, uint16_t polynomial) { + uint8_t i; + for (i = 0; i < 8; i++) { + if ((((crc & 0x8000) >> 8) | (data & 0x80)) != 0) { + crc <<= 1; + crc |= polynomial; + } else { + crc <<= 1; + } + data <<= 1; + } + return crc; +} + +uint16_t RF95_ComputeCRC(uint8_t *buffer, uint8_t bufferLength, + uint8_t crcType) { + uint8_t i; + uint16_t crc; + uint16_t polynomial; + + polynomial = (crcType == CRC_TYPE_IBM) ? POLYNOMIAL_IBM : POLYNOMIAL_CCITT; + crc = (crcType == CRC_TYPE_IBM) ? CRC_IBM_SEED : CRC_CCITT_SEED; + + for (i = 0; i < bufferLength; i++) { + crc = ComputeCRC(crc, buffer[i], polynomial); + } + + if (crcType == CRC_TYPE_IBM) { + return crc; + } else { + return (uint16_t)(~crc); + } +} + +//======================================================================== +//=======================Communication protocol=========================== +//======================================================================== +/* The communication protocol uses three kinds of symbols + * + '?' -> to make petitions to a certain node + * + 'O' -> to say something has been done correctly or to continue + * + 'X' -> to say something has gone wrong or to stop + * All of them are followed with the name of the node, which is only a + * number. + */ + +// void Clear_Buffer(uint8_t *buffer) { +// memset(buffer, 0, strlen((const char *)buffer)); +// } +// +// bool RF95_Master_Receive_from_Node(uint16_t node) { +// uint8_t command[3] = {0}; +// uint8_t ACK_command[3] = {0}; +// bool error = true; // No error happend +// bool end_flag = 0; +// +// // Prepare the ACK command +// sprintf((char *)ACK_command, "O%d", node); +// +// // We prepare the command to send, in this case a request for receiving +// from +// // the master -> "?X" where the X is the node ID +// sprintf((char *)command, "?%d", node); +// // Request a reception to the node X +// do { +// Clear_Buffer(LoRa_buff); +// Set_Pin(TX_LED_GPIO_Port, TX_LED_Pin); +// HAL_Delay(2000); // Wait to give time to the slave to change to receive +// // mode +// strcpy((char *)LoRa_buff, (char *)command); +// RF95_send(LoRa_buff); // Send the request "?x" +// Reset_Pin(TX_LED_GPIO_Port, TX_LED_Pin); +// +// while (strcmp((char *)LoRa_buff, (char *)ACK_command) != 0) { +// // Receive the data +// Clear_Buffer(LoRa_buff); +// if (RF95_waitCAD()) { +// Set_Pin(RX_LED_GPIO_Port, RX_LED_Pin); +// RF95_setModeRx_Continuous(); +// error = RF95_receive_Timeout( +// LoRa_buff, 7000); // Receive an answer and if we doesn't receive +// it +// // in the time we send again the petition. +// HAL_Delay(1000); +// Reset_Pin(RX_LED_GPIO_Port, RX_LED_Pin); +// } +// } +// } while (error == false); +// +// // Prepare the command Xx in order to check if the transaction has ended or +// // has to stop +// sprintf((char *)command, "X%d", node); +// // Clear the LoRa buffer used for transactions to prevent errors +// +// Clear_Buffer(LoRa_buff); +// Set_Pin(TX_LED_GPIO_Port, TX_LED_Pin); +// HAL_Delay(3000); // Wait to give time to the slave to change to receive +// mode strcpy((char *)LoRa_buff, (char *)ACK_command); +// RF95_send(LoRa_buff); +// // Send the ACK to indicate the slave to send the data +// Reset_Pin(TX_LED_GPIO_Port, TX_LED_Pin); +// Clear_Buffer(LoRa_buff); +// +// // Receive the data from the node x +// while (end_flag == 0) { +// do { +// // Receive the data +// Clear_Buffer(LoRa_buff); +// if (RF95_waitCAD()) { +// Set_Pin(RX_LED_GPIO_Port, RX_LED_Pin); +// RF95_setModeRx_Continuous(); +// error = RF95_receive_Timeout(LoRa_buff, 7000); +// HAL_Delay(1000); +// Reset_Pin(RX_LED_GPIO_Port, RX_LED_Pin); +// +// if (strcmp((char *)LoRa_buff, (char *)command) == 0) { +// end_flag = 1; +// break; +// } +// } +// /*=====Insert here the code for processing the data received=====*/ +// +// if (strcmp((char *)LoRa_buff, "This is text message!") == 0) { +// Set_Pin(TX_LED_GPIO_Port, TX_LED_Pin); +// Set_Pin(RX_LED_GPIO_Port, RX_LED_Pin); +// HAL_Delay(3000); +// Reset_Pin(TX_LED_GPIO_Port, TX_LED_Pin); +// Reset_Pin(RX_LED_GPIO_Port, RX_LED_Pin); +// } +// /*===============================================================*/ +// if (error == true) { +// // Send ACK to the node x +// Clear_Buffer(LoRa_buff); +// Set_Pin(TX_LED_GPIO_Port, TX_LED_Pin); +// HAL_Delay(2000); // Wait to give time to the slave to change to +// receive mode strcpy((char *)LoRa_buff, +// (char *)ACK_command); // Send the ACK indicating we want +// to +// // continue the transmission +// RF95_send(LoRa_buff); +// Reset_Pin(TX_LED_GPIO_Port, TX_LED_Pin); +// } +// } while (error == false); +// } +// +// Clear_Buffer(LoRa_buff); +// return true; +// } +// +// bool RF95_Master_Receive_from_All_Nodes(void) { +// for (int i = 0; i < Num_of_Nodes; i++) { +// RF95_Master_Receive_from_Node(i + 1); +// } +// return true; +// } +// +// bool RF95_Slave_Send(void) { +// uint8_t command[3] = {0}; +// uint8_t ACK_command[3] = {0}; +// bool error = true; // No error happend +// +// // Prepare the ACK command +// sprintf((char *)ACK_command, "O%d", Node_ID); +// +// // We prepare the command to send, in this case a request for receiving +// from +// // the master -> "?x" where the x is the node ID +// sprintf((char *)command, "?%d", Node_ID); +// // Wait until a receive request is received from Master +// while (strcmp((char *)LoRa_buff, (char *)command) != 0) { +// // Receive the data +// Clear_Buffer(LoRa_buff); +// if (RF95_waitCAD()) { +// Set_Pin(RX_LED_GPIO_Port, RX_LED_Pin); +// RF95_setModeRx_Continuous(); +// RF95_receive(LoRa_buff); +// } +// } +// HAL_Delay(1000); +// Reset_Pin(RX_LED_GPIO_Port, RX_LED_Pin); +// +// // If a receive request has happened from the Master, we send the ACK to +// tell +// // the master we are going to send as soon as he send us the ACK +// do { +// Clear_Buffer(LoRa_buff); +// Set_Pin(TX_LED_GPIO_Port, TX_LED_Pin); +// HAL_Delay(2000); +// strcpy((char *)LoRa_buff, (char *)ACK_command); +// RF95_send(LoRa_buff); +// Reset_Pin(TX_LED_GPIO_Port, TX_LED_Pin); +// Clear_Buffer(LoRa_buff); +// // Wait until a receive The ACK from master, which tells us to start +// sending +// // data +// while (strcmp((char *)LoRa_buff, (char *)ACK_command) != 0) { +// // Receive the data +// Clear_Buffer(LoRa_buff); +// if (RF95_waitCAD()) { +// Set_Pin(RX_LED_GPIO_Port, RX_LED_Pin); +// RF95_setModeRx_Continuous(); +// error = RF95_receive_Timeout(LoRa_buff, 7000); +// HAL_Delay(1000); +// Reset_Pin(RX_LED_GPIO_Port, RX_LED_Pin); +// } +// } +// } +// while (error == false) +// ; +// +// /*=====Insert here the code for send data / processing the data +// * received=====*/ +// +// do { +// // Send data to the master +// Clear_Buffer(LoRa_buff); +// Set_Pin(TX_LED_GPIO_Port, TX_LED_Pin); +// HAL_Delay(3000); +// strcpy((char *)LoRa_buff, "This is text message!"); +// RF95_send(LoRa_buff); +// Reset_Pin(TX_LED_GPIO_Port, TX_LED_Pin); +// +// // Check for ACK +// Clear_Buffer(LoRa_buff); +// while (strcmp((char *)LoRa_buff, (char *)ACK_command) != 0) { +// // Receive the data +// if (RF95_waitCAD()) { +// Set_Pin(RX_LED_GPIO_Port, RX_LED_Pin); +// RF95_setModeRx_Continuous(); +// error = RF95_receive_Timeout(LoRa_buff, 7000); +// HAL_Delay(2000); +// Reset_Pin(RX_LED_GPIO_Port, RX_LED_Pin); +// } +// } +// } while (error == false); +// +// /*===============================================================*/ +// // Prepare the command Xx in order to tell the transaction has ended or has +// to +// // stop +// Clear_Buffer(LoRa_buff); +// Set_Pin(TX_LED_GPIO_Port, TX_LED_Pin); +// sprintf((char *)LoRa_buff, "X%d", Node_ID); +// HAL_Delay(2000); +// RF95_send(LoRa_buff); +// Reset_Pin(TX_LED_GPIO_Port, TX_LED_Pin); +// +// Clear_Buffer(LoRa_buff); +// return true; +// } diff --git a/rfm95.hpp b/rfm95.hpp new file mode 100644 index 0000000..bdb45e0 --- /dev/null +++ b/rfm95.hpp @@ -0,0 +1,347 @@ +/*============================================================================================================== + * To use this library a buffer called LoRa_buff has been created + * and we'll have to configure the parameters for LoRa in the RF95_Init() + +1. include the declaration "extern uint8_t LoRa_buff[RH_RF95_FIFO_SIZE];" in the main.c. + +2. Follow these steps for the sending/reception of data: + + -----------Send Mode------------- + RF95_Init(); + strcpy(LoRa_buff, "Test to send"); //It is necessary to use the buffer LoRa_buff and the function strcpy to + //copy the data to the buffer, if not the program will send nothing. + + RF95_send(LoRa_buff); + ---------------------------------- + + -----------Reception Mode------------- + RF95_Init(); + RF95_setModeRx_Continuous(); + + RF95_receive(LoRa_buff); + ---------------------------------- + +==============================================================================================================*/ + + + +#ifndef _LORA_RF95_ +#define _LORA_RF95_ + +//#include "main.h" +#include "spi.hpp" +//#include "stm32l4xx_hal_def.h" +#include +#include +#include +#include +//#include "Useful_Functions.h" + +//Modifiers for read and send +#define W 0x80 +#define R 0x7F + +// Max number of bytes the LORA Rx/Tx FIFO can hold +#define RH_RF95_FIFO_SIZE 255 + +// This is the maximum number of bytes that can be carried by the LORA. +// We use some for headers, keeping fewer for RadioHead messages +#define RH_RF95_MAX_PAYLOAD_LEN RH_RF95_FIFO_SIZE + +// The length of the headers we add. +// The headers are inside the LORA's payload +#define RH_RF95_HEADER_LEN 4 + +// This is the maximum message length that can be supported by this driver. +// Can be pre-defined to a smaller size (to save SRAM) prior to including this header +// Here we allow for 1 byte message length, 4 bytes headers, user data and 2 bytes of FCS +#ifndef RH_RF95_MAX_MESSAGE_LEN + #define RH_RF95_MAX_MESSAGE_LEN (RH_RF95_MAX_PAYLOAD_LEN - RH_RF95_HEADER_LEN) +#endif + +// The crystal oscillator frequency of the module +#define RH_RF95_FXOSC 32000000.0 + +// The Frequency Synthesizer step = RH_RF95_FXOSC / 2^^19 +#define RH_RF95_FSTEP (RH_RF95_FXOSC / 524288) + + +// Register names (LoRa Mode, from table 85) +#define RH_RF95_REG_00_FIFO 0x00 +#define RH_RF95_REG_01_OP_MODE 0x01 +#define RH_RF95_REG_02_RESERVED 0x02 +#define RH_RF95_REG_03_RESERVED 0x03 +#define RH_RF95_REG_04_RESERVED 0x04 +#define RH_RF95_REG_05_RESERVED 0x05 +#define RH_RF95_REG_06_FRF_MSB 0x06 +#define RH_RF95_REG_07_FRF_MID 0x07 +#define RH_RF95_REG_08_FRF_LSB 0x08 +#define RH_RF95_REG_09_PA_CONFIG 0x09 +#define RH_RF95_REG_0A_PA_RAMP 0x0a +#define RH_RF95_REG_0B_OCP 0x0b +#define RH_RF95_REG_0C_LNA 0x0c +#define RH_RF95_REG_0D_FIFO_ADDR_PTR 0x0d +#define RH_RF95_REG_0E_FIFO_TX_BASE_ADDR 0x0e +#define RH_RF95_REG_0F_FIFO_RX_BASE_ADDR 0x0f +#define RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR 0x10 +#define RH_RF95_REG_11_IRQ_FLAGS_MASK 0x11 +#define RH_RF95_REG_12_IRQ_FLAGS 0x12 +#define RH_RF95_REG_13_RX_NB_BYTES 0x13 +#define RH_RF95_REG_14_RX_HEADER_CNT_VALUE_MSB 0x14 +#define RH_RF95_REG_15_RX_HEADER_CNT_VALUE_LSB 0x15 +#define RH_RF95_REG_16_RX_PACKET_CNT_VALUE_MSB 0x16 +#define RH_RF95_REG_17_RX_PACKET_CNT_VALUE_LSB 0x17 +#define RH_RF95_REG_18_MODEM_STAT 0x18 +#define RH_RF95_REG_19_PKT_SNR_VALUE 0x19 +#define RH_RF95_REG_1A_PKT_RSSI_VALUE 0x1a +#define RH_RF95_REG_1B_RSSI_VALUE 0x1b +#define RH_RF95_REG_1C_HOP_CHANNEL 0x1c +#define RH_RF95_REG_1D_MODEM_CONFIG1 0x1d +#define RH_RF95_REG_1E_MODEM_CONFIG2 0x1e +#define RH_RF95_REG_1F_SYMB_TIMEOUT_LSB 0x1f +#define RH_RF95_REG_20_PREAMBLE_MSB 0x20 +#define RH_RF95_REG_21_PREAMBLE_LSB 0x21 +#define RH_RF95_REG_22_PAYLOAD_LENGTH 0x22 +#define RH_RF95_REG_23_MAX_PAYLOAD_LENGTH 0x23 +#define RH_RF95_REG_24_HOP_PERIOD 0x24 +#define RH_RF95_REG_25_FIFO_RX_BYTE_ADDR 0x25 +#define RH_RF95_REG_26_MODEM_CONFIG3 0x26 + +#define RH_RF95_REG_40_DIO_MAPPING1 0x40 +#define RH_RF95_REG_41_DIO_MAPPING2 0x41 +#define RH_RF95_REG_42_VERSION 0x42 + +#define RH_RF95_REG_4B_TCXO 0x4b +#define RH_RF95_REG_4D_PA_DAC 0x4d +#define RH_RF95_REG_5B_FORMER_TEMP 0x5b +#define RH_RF95_REG_61_AGC_REF 0x61 +#define RH_RF95_REG_62_AGC_THRESH1 0x62 +#define RH_RF95_REG_63_AGC_THRESH2 0x63 +#define RH_RF95_REG_64_AGC_THRESH3 0x64 + +// RH_RF95_REG_01_OP_MODE 0x01 +#define RH_RF95_LONG_RANGE_MODE 0x80 +#define RH_RF95_ACCESS_SHARED_REG 0x40 +#define RH_RF95_MODE 0x07 +#define RH_RF95_MODE_SLEEP 0x00 +#define RH_RF95_MODE_STDBY 0x01 +#define RH_RF95_MODE_FSTX 0x02 +#define RH_RF95_MODE_TX 0x03 +#define RH_RF95_MODE_FSRX 0x04 +#define RH_RF95_MODE_RXCONTINUOUS 0x05 +#define RH_RF95_MODE_RXSINGLE 0x06 +#define RH_RF95_MODE_CAD 0x07 + +// RH_RF95_REG_09_PA_CONFIG 0x09 +#define RH_RF95_PA_SELECT 0x80 +#define RH_RF95_MAX_POWER 0x70 +#define RH_RF95_OUTPUT_POWER 0x0f + +// RH_RF95_REG_0A_PA_RAMP 0x0a +#define RH_RF95_LOW_PN_TX_PLL_OFF 0x10 +#define RH_RF95_PA_RAMP 0x0f +#define RH_RF95_PA_RAMP_3_4MS 0x00 +#define RH_RF95_PA_RAMP_2MS 0x01 +#define RH_RF95_PA_RAMP_1MS 0x02 +#define RH_RF95_PA_RAMP_500US 0x03 +#define RH_RF95_PA_RAMP_250US 0x0 +#define RH_RF95_PA_RAMP_125US 0x05 +#define RH_RF95_PA_RAMP_100US 0x06 +#define RH_RF95_PA_RAMP_62US 0x07 +#define RH_RF95_PA_RAMP_50US 0x08 +#define RH_RF95_PA_RAMP_40US 0x09 +#define RH_RF95_PA_RAMP_31US 0x0a +#define RH_RF95_PA_RAMP_25US 0x0b +#define RH_RF95_PA_RAMP_20US 0x0c +#define RH_RF95_PA_RAMP_15US 0x0d +#define RH_RF95_PA_RAMP_12US 0x0e +#define RH_RF95_PA_RAMP_10US 0x0f + +// RH_RF95_REG_0B_OCP 0x0b +#define RH_RF95_OCP_ON 0x20 +#define RH_RF95_OCP_TRIM 0x1f + +// RH_RF95_REG_0C_LNA 0x0c +#define RH_RF95_LNA_GAIN 0xe0 +#define RH_RF95_LNA_BOOST 0x03 +#define RH_RF95_LNA_BOOST_DEFAULT 0x00 +#define RH_RF95_LNA_BOOST_150PC 0x11 + +// RH_RF95_REG_11_IRQ_FLAGS_MASK 0x11 +#define RH_RF95_RX_TIMEOUT_MASK 0x80 +#define RH_RF95_RX_DONE_MASK 0x40 +#define RH_RF95_PAYLOAD_CRC_ERROR_MASK 0x20 +#define RH_RF95_VALID_HEADER_MASK 0x10 +#define RH_RF95_TX_DONE_MASK 0x08 +#define RH_RF95_CAD_DONE_MASK 0x04 +#define RH_RF95_FHSS_CHANGE_CHANNEL_MASK 0x02 +#define RH_RF95_CAD_DETECTED_MASK 0x01 + +// RH_RF95_REG_12_IRQ_FLAGS 0x12 +#define RH_RF95_RX_TIMEOUT 0x80 +#define RH_RF95_RX_DONE 0x40 +#define RH_RF95_PAYLOAD_CRC_ERROR 0x20 +#define RH_RF95_VALID_HEADER 0x10 +#define RH_RF95_TX_DONE 0x08 +#define RH_RF95_CAD_DONE 0x04 +#define RH_RF95_FHSS_CHANGE_CHANNEL 0x02 +#define RH_RF95_CAD_DETECTED 0x01 + +// RH_RF95_REG_18_MODEM_STAT 0x18 +#define RH_RF95_RX_CODING_RATE 0xe0 +#define RH_RF95_MODEM_STATUS_CLEAR 0x10 +#define RH_RF95_MODEM_STATUS_HEADER_INFO_VALID 0x08 +#define RH_RF95_MODEM_STATUS_RX_ONGOING 0x04 +#define RH_RF95_MODEM_STATUS_SIGNAL_SYNCHRONIZED 0x02 +#define RH_RF95_MODEM_STATUS_SIGNAL_DETECTED 0x01 + +// RH_RF95_REG_1C_HOP_CHANNEL 0x1c +#define RH_RF95_PLL_TIMEOUT 0x80 +#define RH_RF95_RX_PAYLOAD_CRC_IS_ON 0x40 +#define RH_RF95_FHSS_PRESENT_CHANNEL 0x3f + +// RH_RF95_REG_1D_MODEM_CONFIG1 0x1d +#define RH_RF95_BW 0xc0 +#define RH_RF95_BW_125KHZ 0x00 +#define RH_RF95_BW_250KHZ 0x40 +#define RH_RF95_BW_500KHZ 0x80 +#define RH_RF95_BW_RESERVED 0xc0 +#define RH_RF95_CODING_RATE 0x38 +#define RH_RF95_CODING_RATE_4_5 0x00 +#define RH_RF95_CODING_RATE_4_6 0x08 +#define RH_RF95_CODING_RATE_4_7 0x10 +#define RH_RF95_CODING_RATE_4_8 0x18 +#define RH_RF95_IMPLICIT_HEADER_MODE_ON 0x04 +#define RH_RF95_RX_PAYLOAD_CRC_ON 0x02 +#define RH_RF95_LOW_DATA_RATE_OPTIMIZE 0x01 + +// RH_RF95_REG_1E_MODEM_CONFIG2 0x1e +#define RH_RF95_SPREADING_FACTOR 0xf0 +#define RH_RF95_SPREADING_FACTOR_64CPS 0x60 +#define RH_RF95_SPREADING_FACTOR_128CPS 0x70 +#define RH_RF95_SPREADING_FACTOR_256CPS 0x80 +#define RH_RF95_SPREADING_FACTOR_512CPS 0x90 +#define RH_RF95_SPREADING_FACTOR_1024CPS 0xa0 +#define RH_RF95_SPREADING_FACTOR_2048CPS 0xb0 +#define RH_RF95_SPREADING_FACTOR_4096CPS 0xc0 +#define RH_RF95_TX_CONTINUOUS_MOE 0x08 +#define RH_RF95_AGC_AUTO_ON 0x04 +#define RH_RF95_SYM_TIMEOUT_MSB 0x03 + +// RH_RF95_REG_4D_PA_DAC 0x4d +#define RH_RF95_PA_DAC_DISABLE 0x04 +#define RH_RF95_PA_DAC_ENABLE 0x07 + + +#define No_header 0 +#define Header_used 1 +#define Header No_header + +//CRC Types +#define CRC_TYPE_CCITT 0 +#define CRC_TYPE_IBM 1 + +//Polynomial = X^16 + X^12 + X^5 + 1 +#define POLYNOMIAL_CCITT 0x1021 +//Polynomial = X^16 + X^15 + X^2 + 1 +#define POLYNOMIAL_IBM 0x8005 + +//Seeds +#define CRC_IBM_SEED 0xFFFF +#define CRC_CCITT_SEED 0x1D0F + + +typedef enum +{ + Bw125Cr45Sf128 = 0, ///< Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Default medium range + Bw500Cr45Sf128, ///< Bw = 500 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Fast+short range + Bw31_25Cr48Sf512, ///< Bw = 31.25 kHz, Cr = 4/8, Sf = 512chips/symbol, CRC on. Slow+long range + Bw125Cr48Sf4096, ///< Bw = 125 kHz, Cr = 4/8, Sf = 4096chips/symbol, CRC on. Slow+long range + IH_Bw125Cr45Sf128, ///< Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Default medium range + Implicit Header +} ModemConfigChoice; + +typedef enum +{ +RHModeInitialising = 0, ///< Transport is initialising. Initial default value until init() is called.. +RHModeSleep, ///< Transport hardware is in low power sleep mode (if supported) +RHModeIdle, ///< Transport is idle. +RHModeTx, ///< Transport is in the process of transmitting a message. +RHModeRx, ///< Transport is in the process of receiving a message. +RHModeCad, +} RHMode; + +HAL_StatusTypeDef RF95_write(char reg, char wValue); +HAL_StatusTypeDef RF95_write_burst(char reg, uint8_t* data); +char RF95_read(char reg); +HAL_StatusTypeDef RF95_read_burst(char reg, char* buffer, int length); + +//=====Init and configuration=====// +bool RF95_Init(void); +void RF95_Reset(void); +bool RF95_setModemConfig(ModemConfigChoice index); +void RF95_setPreambleLength(uint16_t bytes); +void RF95_setTxPower(int8_t power, bool useRFO); +bool RF95_setFrequency(float centre); + +//=====Send and receive=====// +bool RF95_receive(uint8_t* buf); +bool RF95_receive_Timeout(uint8_t* buf, uint16_t timeout); +bool RF95_send(uint8_t* data); + +//=====Control=====// +bool RF95_available(void); +bool RF95_available_Timeout(uint16_t timeout); +bool RF95_available_Timeout(uint16_t timeout); +bool RF95_waitPacketSent(void); +bool RF95_waitCAD(void); + +//=====Modes Configuration=====// +void RF95_setModeIdle(void); +bool RF95_sleep(void); +void RF95_setModeRx_Continuous(void); +void RF95_setModeRx_Single(void); +void RF95_setModeTx(void); +void RF95_setModeCAD(void); + + +//=====Check flags=====// +bool RF95_Check_RxTimeout(void); +bool RF95_Check_RxDone(void); +bool RF95_Check_PayloadCRCError(void); +bool RF95_Check_ValidHeader(void); +bool RF95_Check_TxDone(void); +bool RF95_Check_CADDone(void); +bool RF95_Check_FhssChannelChange(void); +bool RF95_Check_CADDetect(void); +void RF95_Clear_IRQ(void); + +bool RF95_Check_ModemClear(void); +bool RF95_Check_HeaderInfoValid(void); +bool RF95_Check_RxOnGoing(void); +bool RF95_Check_SignalSyncronized(void); +bool RF95_Check_SignalDetect(void); + + +//=====CRC calculation=====// +uint16_t ComputeCRC(uint16_t crc, uint8_t data, uint16_t polynomial); +uint16_t RF95_ComputeCRC(uint8_t *buffer, uint8_t bufferLength, uint8_t crcType); + +//======================================================================== +//=======================Communication protocol=========================== +//======================================================================== +/* The communication protocol uses three kinds of symbols + * + '?' -> to make petitions to a certain node + * + 'O' -> to say something has been done correctly or to continue + * + 'X' -> to say something has gone wrong or to stop + * All of them are followed with the name of the node, which is only a number. + */ +#define Num_of_Nodes 2 +#define Node_ID 1 + +void Clear_Buffer(uint8_t* buffer); +bool RF95_Master_Receive_from_Node(uint16_t node); +bool RF95_Master_Receive_from_All_Nodes(void); +bool RF95_Slave_Send(void); + +#endif + diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..cfc734e --- /dev/null +++ b/shell.nix @@ -0,0 +1,15 @@ +{ pkgs ? import {}, libstm32cube, libstm32stdperiph }: + +with pkgs; +mkShell { + TARGET_TRIPLET="arm-none-eabi"; + STM32_CUBE_F1_PATH="${libstm32cube}"; + STM32STDLIB = "${libstm32stdperiph}"; + + nativeBuildInputs = [ + stlink + gcc-arm-embedded-10 + libstm32cube + libstm32stdperiph + ]; +} diff --git a/spi.cpp b/spi.cpp new file mode 100644 index 0000000..b98441f --- /dev/null +++ b/spi.cpp @@ -0,0 +1,57 @@ +#include "spi.hpp" + +SPI_HandleTypeDef hspi1; + +bool MX_SPI1_Init(void) { + hspi1.Instance = SPI1; + hspi1.Init.Mode = SPI_MODE_MASTER; + hspi1.Init.Direction = SPI_DIRECTION_2LINES; + hspi1.Init.DataSize = SPI_DATASIZE_8BIT; + hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; + hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; + hspi1.Init.NSS = SPI_NSS_SOFT; + hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; + hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; + hspi1.Init.TIMode = SPI_TIMODE_DISABLE; + hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + hspi1.Init.CRCPolynomial = 10; + + if (HAL_SPI_Init(&hspi1) != HAL_OK) { + return false; + } + + return true; +} + +extern "C" { +void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if (spiHandle->Instance == SPI1) { + __HAL_RCC_SPI1_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + + /**SPI1 GPIO Configuration + PA4 ------> SPI1_NSS + PA5 ------> SPI1_SCK + PA6 ------> SPI1_MISO + PA7 ------> SPI1_MOSI + */ + GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_7; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_6; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + } +} + +void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle) { + if (spiHandle->Instance == SPI1) { + __HAL_RCC_SPI1_CLK_DISABLE(); + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7); + } +} +} diff --git a/spi.hpp b/spi.hpp new file mode 100644 index 0000000..27b8926 --- /dev/null +++ b/spi.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include + +#include "stm32f1xx_hal_spi.h" + +bool MX_SPI1_Init(void); diff --git a/stm32f1xx_hal_conf.h b/stm32f1xx_hal_conf.h new file mode 100755 index 0000000..3b6ef67 --- /dev/null +++ b/stm32f1xx_hal_conf.h @@ -0,0 +1,449 @@ +/** + ****************************************************************************** + * @file stm32f1xx_hal_conf.h + * @author MCD Application Team + * @brief HAL configuration template file. + * This file should be copied to the application folder and renamed + * to stm32f1xx_hal_conf.h. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F1xx_HAL_CONF_H +#define __STM32F1xx_HAL_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +// #define HAL_ADC_MODULE_ENABLED +// #define HAL_CAN_MODULE_ENABLED +// #define HAL_CAN_LEGACY_MODULE_ENABLED +// #define HAL_CEC_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +// #define HAL_CRC_MODULE_ENABLED +// #define HAL_DAC_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +// #define HAL_ETH_MODULE_ENABLED +// #define HAL_EXTI_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +// #define HAL_HCD_MODULE_ENABLED +// #define HAL_I2C_MODULE_ENABLED +// #define HAL_I2S_MODULE_ENABLED +// #define HAL_IRDA_MODULE_ENABLED +// #define HAL_IWDG_MODULE_ENABLED +// #define HAL_NAND_MODULE_ENABLED +// #define HAL_NOR_MODULE_ENABLED +// #define HAL_PCCARD_MODULE_ENABLED +// #define HAL_PCD_MODULE_ENABLED +// #define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +// #define HAL_RTC_MODULE_ENABLED +// #define HAL_SD_MODULE_ENABLED +// #define HAL_SMARTCARD_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +// #define HAL_SRAM_MODULE_ENABLED +// #define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +//#define HAL_USART_MODULE_ENABLED +// #define HAL_WWDG_MODULE_ENABLED +// #define HAL_MMC_MODULE_ENABLED + +/* ########################## Oscillator Values adaptation + * ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your + * application. This value is used by the RCC HAL module to compute the system + * frequency (when HSE is used as system clock source, directly or through the + * PLL). + */ +#if !defined(HSE_VALUE) +#if defined(USE_STM3210C_EVAL) +#define HSE_VALUE 25000000U /*!< Value of the External oscillator in Hz */ +#else +#define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ +#endif +#endif /* HSE_VALUE */ + +#if !defined(HSE_STARTUP_TIMEOUT) +#define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system + * frequency (when HSI is used as system clock source, directly or through the + * PLL). + */ +#if !defined(HSI_VALUE) +#define HSI_VALUE 8000000U /*!< Value of the Internal oscillator in Hz */ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined(LSI_VALUE) +#define LSI_VALUE 40000U /*!< LSI Typical Value in Hz */ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz \ + The real value may vary depending on the \ + variations in voltage and temperature. */ +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system + * frequency + */ +#if !defined(LSE_VALUE) +#define LSE_VALUE \ + 32768U /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +#if !defined(LSE_STARTUP_TIMEOUT) +#define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE 3300U /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY 0x0FU /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1U + +#define USE_HAL_ADC_REGISTER_CALLBACKS \ + 0U /* ADC register callback disabled */ +#define USE_HAL_CAN_REGISTER_CALLBACKS \ + 0U /* CAN register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS \ + 0U /* CEC register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS \ + 0U /* DAC register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS \ + 0U /* ETH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS \ + 0U /* HCD register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS \ + 0U /* I2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS \ + 0U /* I2S register callback disabled */ +#define USE_HAL_MMC_REGISTER_CALLBACKS \ + 0U /* MMC register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS \ + 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS \ + 0U /* NOR register callback disabled */ +#define USE_HAL_PCCARD_REGISTER_CALLBACKS \ + 0U /* PCCARD register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS \ + 0U /* PCD register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS \ + 0U /* RTC register callback disabled */ +#define USE_HAL_SD_REGISTER_CALLBACKS \ + 0U /* SD register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS \ + 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS \ + 0U /* IRDA register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS \ + 0U /* SRAM register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS \ + 0U /* SPI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS \ + 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS \ + 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS \ + 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS \ + 0U /* WWDG register callback disabled */ + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2U +#define MAC_ADDR1 0U +#define MAC_ADDR2 0U +#define MAC_ADDR3 0U +#define MAC_ADDR4 0U +#define MAC_ADDR5 0U + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE \ + ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE \ + ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB 8U /* 8 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB 4U /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848 PHY Address*/ +#define DP83848_PHY_ADDRESS 0x01U +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY 0x000000FFU +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY 0x00000FFFU + +#define PHY_READ_TO 0x0000FFFFU +#define PHY_WRITE_TO 0x0000FFFFU + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x0000) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x0001) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M \ + ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M \ + ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M \ + ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M \ + ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION \ + ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION \ + ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN \ + ((uint16_t)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE \ + ((uint16_t)0x0400) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE \ + ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS \ + ((uint16_t)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION \ + ((uint16_t)0x0002) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ + +#define PHY_SR \ + ((uint16_t)0x0010) /*!< PHY status register Offset */ +#define PHY_MICR \ + ((uint16_t)0x0011) /*!< MII Interrupt Control Register */ +#define PHY_MISR \ + ((uint16_t)0x0012) /*!< MII Interrupt Status and Misc. Control Register */ + +#define PHY_LINK_STATUS \ + ((uint16_t)0x0001) /*!< PHY Link mask */ +#define PHY_SPEED_STATUS \ + ((uint16_t)0x0002) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS \ + ((uint16_t)0x0004) /*!< PHY Duplex mask */ + +#define PHY_MICR_INT_EN \ + ((uint16_t)0x0002) /*!< PHY Enable interrupts */ +#define PHY_MICR_INT_OE \ + ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ + +#define PHY_MISR_LINK_INT_EN \ + ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ +#define PHY_LINK_INTERRUPT \ + ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ + +#define USE_SPI_CRC 1U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32f1xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32f1xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32f1xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32f1xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED +#include "stm32f1xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED +#include "stm32f1xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CAN_LEGACY_MODULE_ENABLED +#include "Legacy/stm32f1xx_hal_can_legacy.h" +#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED +#include "stm32f1xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32f1xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32f1xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32f1xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED +#include "stm32f1xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32f1xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED +#include "stm32f1xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED +#include "stm32f1xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32f1xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED +#include "stm32f1xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32f1xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32f1xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32f1xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED +#include "stm32f1xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED +#include "stm32f1xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED +#include "stm32f1xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32f1xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32f1xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32f1xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32f1xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32f1xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32f1xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32f1xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32f1xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED +#include "stm32f1xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED +#include "stm32f1xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ +#define assert_param(expr) \ + ((expr) ? (void)0U : assert_failed((uint8_t*)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ +void assert_failed(uint8_t* file, uint32_t line); +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F1xx_HAL_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/uart_handler.cpp b/uart_handler.cpp new file mode 100644 index 0000000..69e1d81 --- /dev/null +++ b/uart_handler.cpp @@ -0,0 +1 @@ +#include "uart_handler.hpp" diff --git a/uart_handler.hpp b/uart_handler.hpp new file mode 100644 index 0000000..6571a9a --- /dev/null +++ b/uart_handler.hpp @@ -0,0 +1,120 @@ +#pragma once + +#include + +#include + +/* + * small uart wrapper + * assumes USART1 with default pins/port + */ + +template +struct uart_handler { + static void enable_clocks() { + __HAL_RCC_USART1_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_AFIO_CLK_ENABLE(); + } + + static void init_gpio() { + GPIO_InitTypeDef ua_tx; + GPIO_InitTypeDef ua_rx; + + ua_tx.Pin = pin_tx; + ua_tx.Mode = GPIO_MODE_AF_PP; + ua_tx.Speed = GPIO_SPEED_HIGH; + + ua_rx.Pin = pin_rx; + ua_rx.Mode = GPIO_MODE_INPUT; + ua_rx.Speed = GPIO_SPEED_HIGH; + + HAL_GPIO_Init(reinterpret_cast(port), &ua_tx); + HAL_GPIO_Init(reinterpret_cast(port), &ua_rx); + } + + static bool enable_oscillators() { + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { + return false; + } + + /** Initializes the CPU, AHB and APB buses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | + RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { + return false; + } + + return true; + } + + static bool init_uart_handle() { + s_UARTHandle.Instance = reinterpret_cast(usart_base); + s_UARTHandle.Init.BaudRate = 9600; + s_UARTHandle.Init.WordLength = UART_WORDLENGTH_8B; + s_UARTHandle.Init.StopBits = UART_STOPBITS_1; + s_UARTHandle.Init.Parity = UART_PARITY_NONE; + s_UARTHandle.Init.Mode = UART_MODE_TX_RX; + s_UARTHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; + + auto result = HAL_UART_Init(&s_UARTHandle); + + return result == HAL_OK; + } + + static bool init() { + enable_clocks(); + init_gpio(); + + if (!enable_oscillators()) { + return false; + } + + return init_uart_handle(); + } + + static HAL_StatusTypeDef write(const std::string_view& message, + uint32_t timeout = HAL_MAX_DELAY) { + constexpr std::string_view carriage_return{"\r\n"}; + + write(reinterpret_cast(const_cast(message.data())), + message.size(), timeout); + + return write( + reinterpret_cast(const_cast(carriage_return.data())), + carriage_return.size(), timeout); + } + + static HAL_StatusTypeDef write(uint8_t* buf, uint16_t size, + uint32_t timeout = HAL_MAX_DELAY) { + return HAL_UART_Transmit(&s_UARTHandle, buf, size, timeout); + } + + static UART_HandleTypeDef s_UARTHandle; + + private: + static constexpr auto pin_tx = PinTX; + static constexpr auto pin_rx = PinRX; + static constexpr auto port = Port; + static constexpr auto usart_base = UsartBase; +}; + +template +UART_HandleTypeDef uart_handler::s_UARTHandle = + UART_HandleTypeDef(); From b78396e8e50f523f30ab1dfcce5882ce3ffb04de Mon Sep 17 00:00:00 2001 From: kalipso Date: Fri, 17 Feb 2023 15:18:10 +0100 Subject: [PATCH 02/12] add logging structure --- CMakeLists.txt | 1 + logging.cpp | 4 +++ logging.hpp | 94 ++++++++++++++++++++++++++++++++++++++++++++++++ main.cpp | 43 +++++++++++----------- uart_handler.hpp | 44 +++++++++++++++++++---- 5 files changed, 157 insertions(+), 29 deletions(-) create mode 100644 logging.cpp create mode 100644 logging.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d1aceb1..3d52b7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ find_package(HAL COMPONENTS "${HAL_COMP_LIST}" REQUIRED) # STM32VL-Discovery add_executable(stm32-blinky-f1 ${MAIN_SOURCE_FILE} + logging.cpp uart_handler.cpp spi.cpp rfm95.cpp diff --git a/logging.cpp b/logging.cpp new file mode 100644 index 0000000..9506a1d --- /dev/null +++ b/logging.cpp @@ -0,0 +1,4 @@ +#include "logging.hpp" + +logging_adapter* log::logger = nullptr; +LogLevel log::log_level = LogLevel::INFO; diff --git a/logging.hpp b/logging.hpp new file mode 100644 index 0000000..1f6e5b0 --- /dev/null +++ b/logging.hpp @@ -0,0 +1,94 @@ +#pragma once + +#include + +#include "uart_handler.hpp" + +enum class LogLevel { + ERROR = 0, + INFO, + DEBUG, + TRACE, +}; + +inline std::string_view get_loglevel_string(LogLevel level) { + switch (level) { + case (LogLevel::ERROR): { + return "[Error]"; + } + case (LogLevel::INFO): { + return "[Info] "; + } + case (LogLevel::DEBUG): { + return "[Debug]"; + } + case (LogLevel::TRACE): { + return "[Trace]"; + } + } + + return "[Unknown]"; +} + +class logging_adapter { + public: + virtual bool init(){} + virtual void log(std::string_view message) const = 0; +}; + +class uart_logger : public logging_adapter { + public: + bool init() { return uart_interface::init(); } + + virtual void log(std::string_view message) const override { + uart_interface::write(message); + } +}; + +class log { + public: + template + static bool init() { + if (logger) { + return true; + } + + static LoggerType logger_impl; + logger = &logger_impl; + + return logger_impl.init(); + } + + static void error(std::string_view message) { + log_impl(LogLevel::ERROR, message); + } + + static void debug(std::string_view message) { + log_impl(LogLevel::DEBUG, message); + } + + static void info(std::string_view message) { + log_impl(LogLevel::INFO, message); + } + + static void set_loglevel(LogLevel level) { log_level = level; } + + private: + static void log_impl(LogLevel level, std::string_view message) { + if (log_level < level) { + return; + } + + //std::stringstream msg; + //msg << get_loglevel_string(level) << ": " << message; + logger->log(get_loglevel_string(level)); + logger->log(": "); + logger->log(message); + + constexpr std::string_view carriage_return{"\r\n"}; + logger->log(carriage_return); + } + + static logging_adapter* logger; + static LogLevel log_level; +}; diff --git a/main.cpp b/main.cpp index c634793..c9b088b 100644 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,7 @@ #include +#include "logging.hpp" #include "spi.hpp" -#include "uart_handler.hpp" // STM32VL-Discovery green led - PC9 #define BTN_PORT GPIOA @@ -11,12 +11,6 @@ #define BTN_PIN GPIO_PIN_0 #define LED_PORT_CLK_ENABLE __HAL_RCC_GPIOC_CLK_ENABLE -constexpr auto UART_PORT = GPIOA_BASE; - -#define UARTPORT GPIOA -#define UARTTX_PIN GPIO_PIN_9 -#define UARTRX_PIN GPIO_PIN_10 - #define LoRa_RESET_Pin GPIO_PIN_3 #define LoRa_RESET_GPIO_Port GPIOA #define LoRa_CS_Pin GPIO_PIN_4 @@ -73,19 +67,17 @@ extern "C" { #include } -using uart_interface = - uart_handler; - int main(void) { HAL_Init(); HAL_SYSTICK_Config(1); initGPIO(); - if (!uart_interface::init()) { + if (!log::init()) { // toggle status led or something } - - uart_interface::write("UART Initialized."); + log::set_loglevel(LogLevel::DEBUG); + log::info("logging Initialized"); + log::info("running PentaTrack v0.1.3"); if (!MX_SPI1_Init()) { // toggle status led or something @@ -95,28 +87,35 @@ int main(void) { HAL_GPIO_WritePin(LoRa_RESET_GPIO_Port, LoRa_RESET_Pin, GPIO_PIN_SET); HAL_Delay(10); - uart_interface::write("SPI1 Initialized."); - uart_interface::write("Initialization done."); + log::debug("SPI1 Initialized."); + log::debug("Initialization done."); char OP_Mode = 0x01; char buff = 0x7F & OP_Mode; char res = 0; HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_RESET); - auto result = HAL_SPI_Transmit(&hspi1, (uint8_t *)&buff, 1, 100); + [[maybe_unused]] auto result = + HAL_SPI_Transmit(&hspi1, (uint8_t *)&buff, 1, 100); HAL_SPI_Receive(&hspi1, (uint8_t *)&res, 1, 100); HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); - RF95_Init(); + // RF95_Init(); + int i = 0; while (1) { - RF95_setModeRx_Continuous(); + // RF95_setModeRx_Continuous(); HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET); - RF95_receive(LoRa_buff); + HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_RESET); + // RF95_receive(LoRa_buff); + HAL_Delay(500); HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET); + HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_SET); + HAL_Delay(500); - std::string_view msg{reinterpret_cast(LoRa_buff)}; - uart_interface::write("Received Message:"); - uart_interface::write(msg); + // std::string_view msg{reinterpret_cast(LoRa_buff)}; + // log::info("Received Message"); + // log::debug("Received Message"); + // log::debug(msg); // std::string_view foo{"Das ist ein test"}; // strcpy((char *)LoRa_buff, foo.data()); diff --git a/uart_handler.hpp b/uart_handler.hpp index 6571a9a..6f616a0 100644 --- a/uart_handler.hpp +++ b/uart_handler.hpp @@ -4,11 +4,15 @@ #include +constexpr auto UART_PORT = GPIOA_BASE; +#define UARTPORT GPIOA +#define UARTTX_PIN GPIO_PIN_9 +#define UARTRX_PIN GPIO_PIN_10 + /* * small uart wrapper * assumes USART1 with default pins/port */ - template struct uart_handler { static void enable_clocks() { @@ -31,6 +35,10 @@ struct uart_handler { HAL_GPIO_Init(reinterpret_cast(port), &ua_tx); HAL_GPIO_Init(reinterpret_cast(port), &ua_rx); + + /* USART1 interrupt Init */ + // HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); + // HAL_NVIC_EnableIRQ(USART1_IRQn); } static bool enable_oscillators() { @@ -75,6 +83,12 @@ struct uart_handler { auto result = HAL_UART_Init(&s_UARTHandle); + if (result != HAL_OK) { + return false; + } + + // result = HAL_UART_Receive_IT(&s_UARTHandle, rx_buff, rx_buff_size); + return result == HAL_OK; } @@ -91,14 +105,14 @@ struct uart_handler { static HAL_StatusTypeDef write(const std::string_view& message, uint32_t timeout = HAL_MAX_DELAY) { - constexpr std::string_view carriage_return{"\r\n"}; + // constexpr std::string_view carriage_return{"\r\n"}; - write(reinterpret_cast(const_cast(message.data())), - message.size(), timeout); + return write(reinterpret_cast(const_cast(message.data())), + message.size(), timeout); - return write( - reinterpret_cast(const_cast(carriage_return.data())), - carriage_return.size(), timeout); + // return write( + // reinterpret_cast(const_cast(carriage_return.data())), + // carriage_return.size(), timeout); } static HAL_StatusTypeDef write(uint8_t* buf, uint16_t size, @@ -108,13 +122,29 @@ struct uart_handler { static UART_HandleTypeDef s_UARTHandle; + static uint8_t* get_buf() { return rx_buff; } + private: static constexpr auto pin_tx = PinTX; static constexpr auto pin_rx = PinRX; static constexpr auto port = Port; static constexpr auto usart_base = UsartBase; + static constexpr size_t rx_buff_size = 10; + static inline uint8_t* rx_buff; }; template UART_HandleTypeDef uart_handler::s_UARTHandle = UART_HandleTypeDef(); + +using uart_interface = + uart_handler; + +template <> +uint8_t* uart_interface::rx_buff = new uint8_t[10]; + +// inline void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart) { +// static int count = 0; +// count++; +// HAL_UART_Receive_IT(huart, uart_interface::get_buf(), 10); +// } From e313b8f2be042ddc01f85198cb75798223be61af Mon Sep 17 00:00:00 2001 From: kalipso Date: Fri, 17 Feb 2023 15:18:23 +0100 Subject: [PATCH 03/12] add gnumake & screen to shell --- shell.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shell.nix b/shell.nix index cfc734e..5bd4555 100644 --- a/shell.nix +++ b/shell.nix @@ -7,7 +7,9 @@ mkShell { STM32STDLIB = "${libstm32stdperiph}"; nativeBuildInputs = [ + gnumake stlink + screen gcc-arm-embedded-10 libstm32cube libstm32stdperiph From 2d3a358dfee1d5b36d70db217d4586fae03c0a61 Mon Sep 17 00:00:00 2001 From: kalipso Date: Fri, 17 Feb 2023 19:19:11 +0100 Subject: [PATCH 04/12] working receive --- CMakeLists.txt | 6 +++--- logging.hpp | 6 +++--- main.cpp | 19 +++++++++++++++++-- uart_handler.cpp | 4 ++++ uart_handler.hpp | 24 +++++++++--------------- 5 files changed, 36 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d52b7e..1a02e3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(MAIN_SOURCE_FILE main.cpp) set(CMAKE_INCLUDE_CURRENT_DIR TRUE) -set(HAL_COMP_LIST RCC GPIO CORTEX UART SPI) +set(HAL_COMP_LIST RCC GPIO CORTEX UART SPI DMA) set(CMSIS_COMP_LIST "") list(APPEND CMSIS_COMP_LIST STM32F1) @@ -31,6 +31,7 @@ add_executable(stm32-blinky-f1 uart_handler.cpp spi.cpp rfm95.cpp + stm32f1xx_it.c stm32f1xx_hal_conf.h ) @@ -42,6 +43,7 @@ target_link_libraries(stm32-blinky-f1 HAL::STM32::F1::GPIO HAL::STM32::F1::CORTEX HAL::STM32::F1::SPI + HAL::STM32::F1::DMA CMSIS::STM32::F100RB STM32::NoSys ) @@ -62,5 +64,3 @@ stm32_print_size_of_target(stm32-blinky-f1) # STM32::NoSys #) #stm32_print_size_of_target(stm32-blinky-f1) - - diff --git a/logging.hpp b/logging.hpp index 1f6e5b0..db3c711 100644 --- a/logging.hpp +++ b/logging.hpp @@ -32,7 +32,7 @@ inline std::string_view get_loglevel_string(LogLevel level) { class logging_adapter { public: - virtual bool init(){} + virtual bool init() { return true; } virtual void log(std::string_view message) const = 0; }; @@ -79,8 +79,8 @@ class log { return; } - //std::stringstream msg; - //msg << get_loglevel_string(level) << ": " << message; + // std::stringstream msg; + // msg << get_loglevel_string(level) << ": " << message; logger->log(get_loglevel_string(level)); logger->log(": "); logger->log(message); diff --git a/main.cpp b/main.cpp index c9b088b..6828099 100644 --- a/main.cpp +++ b/main.cpp @@ -1,4 +1,5 @@ #include +#include #include "logging.hpp" #include "spi.hpp" @@ -27,6 +28,22 @@ void SysTick_Handler(void) { HAL_IncTick(); HAL_SYSTICK_IRQHandler(); } + +void USART1_IRQHandler(void) { + HAL_UART_IRQHandler(&uart_interface::s_UARTHandle); + HAL_UART_Receive_IT(&uart_interface::s_UARTHandle, uart_interface::get_buf(), + 1); +} + +void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { + const char value = *reinterpret_cast(uart_interface::get_buf()); + + if (value == '\r') { + HAL_GPIO_TogglePin(LED_PORT, LED2_PIN); + } + + log::debug({&value, 1}); +} } void initGPIO() { @@ -105,11 +122,9 @@ int main(void) { while (1) { // RF95_setModeRx_Continuous(); HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET); - HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_RESET); // RF95_receive(LoRa_buff); HAL_Delay(500); HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET); - HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_SET); HAL_Delay(500); // std::string_view msg{reinterpret_cast(LoRa_buff)}; diff --git a/uart_handler.cpp b/uart_handler.cpp index 69e1d81..11d3529 100644 --- a/uart_handler.cpp +++ b/uart_handler.cpp @@ -1 +1,5 @@ #include "uart_handler.hpp" + +template <> +// uint8_t* uart_interface::rx_buff = new uint8_t[10]; +uint8_t uart_interface::rx_buff = 0; diff --git a/uart_handler.hpp b/uart_handler.hpp index 6f616a0..22311a8 100644 --- a/uart_handler.hpp +++ b/uart_handler.hpp @@ -4,6 +4,8 @@ #include +#include "stm32f1xx_it.h" + constexpr auto UART_PORT = GPIOA_BASE; #define UARTPORT GPIOA #define UARTTX_PIN GPIO_PIN_9 @@ -37,8 +39,8 @@ struct uart_handler { HAL_GPIO_Init(reinterpret_cast(port), &ua_rx); /* USART1 interrupt Init */ - // HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); - // HAL_NVIC_EnableIRQ(USART1_IRQn); + HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(USART1_IRQn); } static bool enable_oscillators() { @@ -87,7 +89,7 @@ struct uart_handler { return false; } - // result = HAL_UART_Receive_IT(&s_UARTHandle, rx_buff, rx_buff_size); + result = HAL_UART_Receive_IT(&s_UARTHandle, &rx_buff, rx_buff_size); return result == HAL_OK; } @@ -122,15 +124,16 @@ struct uart_handler { static UART_HandleTypeDef s_UARTHandle; - static uint8_t* get_buf() { return rx_buff; } + static uint8_t* get_buf() { return &rx_buff; } + static const uint8_t* get_buf_c() { return &rx_buff; } private: static constexpr auto pin_tx = PinTX; static constexpr auto pin_rx = PinRX; static constexpr auto port = Port; static constexpr auto usart_base = UsartBase; - static constexpr size_t rx_buff_size = 10; - static inline uint8_t* rx_buff; + static constexpr size_t rx_buff_size = 1; + static uint8_t rx_buff; }; template @@ -139,12 +142,3 @@ UART_HandleTypeDef uart_handler::s_UARTHandle = using uart_interface = uart_handler; - -template <> -uint8_t* uart_interface::rx_buff = new uint8_t[10]; - -// inline void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart) { -// static int count = 0; -// count++; -// HAL_UART_Receive_IT(huart, uart_interface::get_buf(), 10); -// } From 7a3859f9324c0a523afb8ba987a2edbc17716370 Mon Sep 17 00:00:00 2001 From: kalipso Date: Sat, 18 Feb 2023 11:00:01 +0100 Subject: [PATCH 05/12] add simple cmd handler --- main.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/main.cpp b/main.cpp index 6828099..78892a7 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,9 @@ #include #include +#include +#include + #include "logging.hpp" #include "spi.hpp" @@ -22,6 +25,72 @@ extern uint8_t LoRa_buff[RH_RF95_FIFO_SIZE]; extern SPI_HandleTypeDef hspi1; +void print_version(void) { log::info("running PentaTrack v0.1.3"); } + +class cmd_holder { + public: + typedef void (*functionPointerType)(void); + + void add_cmd(std::string_view msg, functionPointerType func) { + commands[amount_cmds++] = std::make_tuple(msg, func); + } + + functionPointerType get_func(std::string_view message) const { + for (const auto &[msg, func] : commands) { + if (message == msg) { + return func; + } + } + + return nullptr; + } + + private: + std::array, 12> commands; + size_t amount_cmds = 0; +}; + +class cmd_handler { + public: + using array_t = std::array; + using iterator_t = array_t::iterator; + using const_iterator_t = array_t::const_iterator; + + cmd_handler() : symbols{}, iterator{symbols.begin()} { + commands.add_cmd("ver", &print_version); + } + + static cmd_handler *get_instance() { + static cmd_handler handler{}; + + return &handler; + } + + void add_symbol(uint8_t symbol) { + *iterator++ = symbol; + if (iterator == symbols.end()) { + iterator = symbols.begin(); + } + } + + std::string_view get_current_cmd() const { + return {reinterpret_cast(symbols.data()), + static_cast( + std::distance(symbols.begin(), const_iterator_t{iterator}))}; + } + + void log_current_command() { log::debug(get_current_cmd()); } + + private: + cmd_holder commands; + + array_t symbols; + iterator_t iterator; +}; + +// cmd_handler::array_t cmd_handler::symbols = cmd_handler::array_t{}; +// cmd_handler::iterator_t cmd_handler::iterator = cmd_handler::iterator_t{}; + // This prevent name mangling for functions used in C/assembly files. extern "C" { void SysTick_Handler(void) { From 658f545f2385455160272f01c36b5e4331132258 Mon Sep 17 00:00:00 2001 From: kalipso Date: Sat, 18 Feb 2023 11:00:29 +0100 Subject: [PATCH 06/12] add interrupts --- stm32f1xx_it.c | 206 +++++++++++++++++++++++++++++++++++++++++++++++++ stm32f1xx_it.h | 66 ++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100644 stm32f1xx_it.c create mode 100644 stm32f1xx_it.h diff --git a/stm32f1xx_it.c b/stm32f1xx_it.c new file mode 100644 index 0000000..3a758e6 --- /dev/null +++ b/stm32f1xx_it.c @@ -0,0 +1,206 @@ +#include + + +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f1xx_it.c + * @brief Interrupt Service Routines. + ****************************************************************************** + * @attention + * + * Copyright (c) 2022 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f1xx_it.h" +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN TD */ + +/* USER CODE END TD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* External variables --------------------------------------------------------*/ + +/* USER CODE BEGIN EV */ + +/* USER CODE END EV */ + +/******************************************************************************/ +/* Cortex-M3 Processor Interruption and Exception Handlers */ +/******************************************************************************/ +/** + * @brief This function handles Non maskable interrupt. + */ +void NMI_Handler(void) +{ + /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ + + /* USER CODE END NonMaskableInt_IRQn 0 */ + /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ + while (1) + { + } + /* USER CODE END NonMaskableInt_IRQn 1 */ +} + +/** + * @brief This function handles Hard fault interrupt. + */ +void HardFault_Handler(void) +{ + /* USER CODE BEGIN HardFault_IRQn 0 */ + + /* USER CODE END HardFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_HardFault_IRQn 0 */ + /* USER CODE END W1_HardFault_IRQn 0 */ + } +} + +/** + * @brief This function handles Memory management fault. + */ +void MemManage_Handler(void) +{ + /* USER CODE BEGIN MemoryManagement_IRQn 0 */ + + /* USER CODE END MemoryManagement_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ + /* USER CODE END W1_MemoryManagement_IRQn 0 */ + } +} + +/** + * @brief This function handles Prefetch fault, memory access fault. + */ +void BusFault_Handler(void) +{ + /* USER CODE BEGIN BusFault_IRQn 0 */ + + /* USER CODE END BusFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_BusFault_IRQn 0 */ + /* USER CODE END W1_BusFault_IRQn 0 */ + } +} + +/** + * @brief This function handles Undefined instruction or illegal state. + */ +void UsageFault_Handler(void) +{ + /* USER CODE BEGIN UsageFault_IRQn 0 */ + + /* USER CODE END UsageFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_UsageFault_IRQn 0 */ + /* USER CODE END W1_UsageFault_IRQn 0 */ + } +} + +/** + * @brief This function handles System service call via SWI instruction. + */ +void SVC_Handler(void) +{ + /* USER CODE BEGIN SVCall_IRQn 0 */ + + /* USER CODE END SVCall_IRQn 0 */ + /* USER CODE BEGIN SVCall_IRQn 1 */ + + /* USER CODE END SVCall_IRQn 1 */ +} + +/** + * @brief This function handles Debug monitor. + */ +void DebugMon_Handler(void) +{ + /* USER CODE BEGIN DebugMonitor_IRQn 0 */ + + /* USER CODE END DebugMonitor_IRQn 0 */ + /* USER CODE BEGIN DebugMonitor_IRQn 1 */ + + /* USER CODE END DebugMonitor_IRQn 1 */ +} + +/** + * @brief This function handles Pendable request for system service. + */ +void PendSV_Handler(void) +{ + /* USER CODE BEGIN PendSV_IRQn 0 */ + + /* USER CODE END PendSV_IRQn 0 */ + /* USER CODE BEGIN PendSV_IRQn 1 */ + + /* USER CODE END PendSV_IRQn 1 */ +} + +/** + * @brief This function handles System tick timer. + */ +//void SysTick_Handler(void) +//{ +// /* USER CODE BEGIN SysTick_IRQn 0 */ +// +// /* USER CODE END SysTick_IRQn 0 */ +// HAL_IncTick(); +// /* USER CODE BEGIN SysTick_IRQn 1 */ +// HAL_SYSTICK_IRQHandler(); +// +// /* USER CODE END SysTick_IRQn 1 */ +//} + +/******************************************************************************/ +/* STM32F1xx Peripheral Interrupt Handlers */ +/* Add here the Interrupt Handlers for the used peripherals. */ +/* For the available peripheral interrupt handler names, */ +/* please refer to the startup file (startup_stm32f1xx.s). */ +/******************************************************************************/ + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/stm32f1xx_it.h b/stm32f1xx_it.h new file mode 100644 index 0000000..4ea7520 --- /dev/null +++ b/stm32f1xx_it.h @@ -0,0 +1,66 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f1xx_it.h + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * @attention + * + * Copyright (c) 2022 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F1xx_IT_H +#define __STM32F1xx_IT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +void NMI_Handler(void); +void HardFault_Handler(void); +void MemManage_Handler(void); +void BusFault_Handler(void); +void UsageFault_Handler(void); +void SVC_Handler(void); +void DebugMon_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F1xx_IT_H */ From fa857790888d18fed7b5f5b6461af92310715829 Mon Sep 17 00:00:00 2001 From: kalipso Date: Sun, 19 Feb 2023 22:31:07 +0100 Subject: [PATCH 07/12] working cmd handler --- CMakeLists.txt | 2 +- logging.hpp | 35 ++++++++++++------ main.cpp | 96 +++++++++++++++++++++++++++++++++++++------------- 3 files changed, 96 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a02e3b..c3b40be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ add_executable(stm32-blinky-f1 stm32f1xx_hal_conf.h ) -set_property(TARGET stm32-blinky-f1 PROPERTY CXX_STANDARD 17) +set_property(TARGET stm32-blinky-f1 PROPERTY CXX_STANDARD 20) target_link_libraries(stm32-blinky-f1 HAL::STM32::F1::UART diff --git a/logging.hpp b/logging.hpp index db3c711..45b6ce5 100644 --- a/logging.hpp +++ b/logging.hpp @@ -59,32 +59,45 @@ class log { return logger_impl.init(); } - static void error(std::string_view message) { - log_impl(LogLevel::ERROR, message); + template + static void error(Args&&... args) { + log_impl_begin(LogLevel::ERROR); + log_impl(std::forward(args)...); } - static void debug(std::string_view message) { - log_impl(LogLevel::DEBUG, message); + template + static void debug(Args&&... args) { + log_impl_begin(LogLevel::DEBUG); + log_impl(std::forward(args)...); } - static void info(std::string_view message) { - log_impl(LogLevel::INFO, message); + template + static void info(Args&&... args) { + log_impl_begin(LogLevel::INFO); + log_impl(std::forward(args)...); } static void set_loglevel(LogLevel level) { log_level = level; } private: - static void log_impl(LogLevel level, std::string_view message) { + static bool log_impl_begin(LogLevel level) { if (log_level < level) { - return; + return false; } - // std::stringstream msg; - // msg << get_loglevel_string(level) << ": " << message; logger->log(get_loglevel_string(level)); logger->log(": "); - logger->log(message); + return true; + } + template + static void log_impl(std::string_view message, Args&&... args) { + logger->log(message); + log_impl(std::forward(args)...); + } + + static void log_impl(std::string_view message) { + logger->log(message); constexpr std::string_view carriage_return{"\r\n"}; logger->log(carriage_return); } diff --git a/main.cpp b/main.cpp index 78892a7..3002c35 100644 --- a/main.cpp +++ b/main.cpp @@ -26,18 +26,25 @@ extern uint8_t LoRa_buff[RH_RF95_FIFO_SIZE]; extern SPI_HandleTypeDef hspi1; void print_version(void) { log::info("running PentaTrack v0.1.3"); } +void print_help(void); +template class cmd_holder { public: typedef void (*functionPointerType)(void); - void add_cmd(std::string_view msg, functionPointerType func) { - commands[amount_cmds++] = std::make_tuple(msg, func); - } + using command_t = + std::tuple; + template + using command_array_t = std::array; - functionPointerType get_func(std::string_view message) const { - for (const auto &[msg, func] : commands) { - if (message == msg) { + template + consteval cmd_holder(Args... command_list) + : commands{std::forward(command_list)...} {} + + constexpr functionPointerType get_func(std::string_view message) const { + for (const auto &[cmd_name, cmd_help, func] : commands) { + if (message == cmd_name) { return func; } } @@ -45,29 +52,35 @@ class cmd_holder { return nullptr; } + void print_help() const { + log::info("Listing available commands:"); + for (const auto &[cmd_name, cmd_help, func] : commands) { + log::info("\t", cmd_name, " - ", cmd_help); + } + } + private: - std::array, 12> commands; - size_t amount_cmds = 0; + std::array commands; }; class cmd_handler { public: - using array_t = std::array; + static constexpr auto MaxCmdLength = 24; + using array_t = std::array; using iterator_t = array_t::iterator; using const_iterator_t = array_t::const_iterator; - cmd_handler() : symbols{}, iterator{symbols.begin()} { - commands.add_cmd("ver", &print_version); - } - - static cmd_handler *get_instance() { - static cmd_handler handler{}; - - return &handler; - } + consteval cmd_handler() + : commands{std::make_tuple("ver", "Prints current version.", + &print_version), + std::make_tuple("help", "Prints available commands", + &print_help)}, + symbols{}, + iterator{symbols.begin()} {} void add_symbol(uint8_t symbol) { - *iterator++ = symbol; + *iterator = symbol; + iterator++; if (iterator == symbols.end()) { iterator = symbols.begin(); } @@ -79,15 +92,45 @@ class cmd_handler { std::distance(symbols.begin(), const_iterator_t{iterator}))}; } - void log_current_command() { log::debug(get_current_cmd()); } + bool exists() const { + return commands.get_func(get_current_cmd()) != nullptr; + } + + void execute() { + const auto current_cmd = get_current_cmd(); + log::debug("Try executing command: ", current_cmd); + const auto func = commands.get_func(current_cmd); + iterator = symbols.begin(); + + if (func == nullptr) { + return; + } + + func(); + } + + void queue_execution() { ShouldExecute = true; } + + void run() { + if (ShouldExecute) { + execute(); + ShouldExecute = false; + } + } + + void print_help_() const { commands.print_help(); } private: - cmd_holder commands; - + cmd_holder<2> commands; array_t symbols; iterator_t iterator; + bool ShouldExecute = false; }; +static cmd_handler commands{}; + +void print_help(void) { commands.print_help_(); } + // cmd_handler::array_t cmd_handler::symbols = cmd_handler::array_t{}; // cmd_handler::iterator_t cmd_handler::iterator = cmd_handler::iterator_t{}; @@ -105,13 +148,15 @@ void USART1_IRQHandler(void) { } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { - const char value = *reinterpret_cast(uart_interface::get_buf()); + const uint8_t value = *uart_interface::get_buf(); if (value == '\r') { + commands.queue_execution(); HAL_GPIO_TogglePin(LED_PORT, LED2_PIN); + return; } - log::debug({&value, 1}); + commands.add_symbol(value); } } @@ -187,8 +232,9 @@ int main(void) { HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); // RF95_Init(); - int i = 0; while (1) { + commands.run(); + // RF95_setModeRx_Continuous(); HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET); // RF95_receive(LoRa_buff); From 045302cc9653c9839fa9b1e27b2f86c97199e198 Mon Sep 17 00:00:00 2001 From: kalipso Date: Sun, 19 Feb 2023 22:47:24 +0100 Subject: [PATCH 08/12] add loglevel commands --- logging.hpp | 22 +++++++++++++++++----- main.cpp | 31 +++++++++++++++++++------------ 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/logging.hpp b/logging.hpp index 45b6ce5..0b5910a 100644 --- a/logging.hpp +++ b/logging.hpp @@ -11,7 +11,7 @@ enum class LogLevel { TRACE, }; -inline std::string_view get_loglevel_string(LogLevel level) { +inline constexpr std::string_view get_loglevel_string(LogLevel level) { switch (level) { case (LogLevel::ERROR): { return "[Error]"; @@ -61,23 +61,35 @@ class log { template static void error(Args&&... args) { - log_impl_begin(LogLevel::ERROR); + if (!log_impl_begin(LogLevel::ERROR)) { + return; + } + log_impl(std::forward(args)...); } template static void debug(Args&&... args) { - log_impl_begin(LogLevel::DEBUG); + if (!log_impl_begin(LogLevel::DEBUG)) { + return; + } + log_impl(std::forward(args)...); } template static void info(Args&&... args) { - log_impl_begin(LogLevel::INFO); + if (!log_impl_begin(LogLevel::INFO)) { + return; + } + log_impl(std::forward(args)...); } - static void set_loglevel(LogLevel level) { log_level = level; } + static void set_loglevel(LogLevel level) { + info("New LogLevel: ", get_loglevel_string(level)); + log_level = level; + } private: static bool log_impl_begin(LogLevel level) { diff --git a/main.cpp b/main.cpp index 3002c35..e3a09ca 100644 --- a/main.cpp +++ b/main.cpp @@ -28,6 +28,10 @@ extern SPI_HandleTypeDef hspi1; void print_version(void) { log::info("running PentaTrack v0.1.3"); } void print_help(void); +void loglevel_error(void) { log::set_loglevel(LogLevel::ERROR); } +void loglevel_info(void) { log::set_loglevel(LogLevel::INFO); } +void loglevel_debug(void) { log::set_loglevel(LogLevel::DEBUG); } + template class cmd_holder { public: @@ -63,6 +67,7 @@ class cmd_holder { std::array commands; }; +template class cmd_handler { public: static constexpr auto MaxCmdLength = 24; @@ -70,11 +75,9 @@ class cmd_handler { using iterator_t = array_t::iterator; using const_iterator_t = array_t::const_iterator; - consteval cmd_handler() - : commands{std::make_tuple("ver", "Prints current version.", - &print_version), - std::make_tuple("help", "Prints available commands", - &print_help)}, + template + consteval cmd_handler(Args &&...command_list) + : commands{std::forward(command_list)...}, symbols{}, iterator{symbols.begin()} {} @@ -121,19 +124,21 @@ class cmd_handler { void print_help_() const { commands.print_help(); } private: - cmd_holder<2> commands; + cmd_holder commands; array_t symbols; iterator_t iterator; bool ShouldExecute = false; }; -static cmd_handler commands{}; +static cmd_handler<5> commands{ + std::make_tuple("ver", "Prints current version.", &print_version), + std::make_tuple("error", "Set LogLevel to Error.", &loglevel_error), + std::make_tuple("info", "Set LogLevel to Info.", &loglevel_info), + std::make_tuple("debug", "Set LogLevel to Debug.", &loglevel_debug), + std::make_tuple("help", "Prints available commands", &print_help)}; void print_help(void) { commands.print_help_(); } -// cmd_handler::array_t cmd_handler::symbols = cmd_handler::array_t{}; -// cmd_handler::iterator_t cmd_handler::iterator = cmd_handler::iterator_t{}; - // This prevent name mangling for functions used in C/assembly files. extern "C" { void SysTick_Handler(void) { @@ -183,7 +188,8 @@ void initGPIO() { GPIO_ConfigSPI.Pin = LoRa_CS_Pin | LoRa_RESET_Pin; // bare metal init of led1: - // volatile uint32_t* CRH = reinterpret_cast(0x40011000 + 0x04); + // volatile uint32_t* CRH = reinterpret_cast(0x40011000 + + // 0x04); //*CRH |= 0x3; //*CRH &= (~0xC); @@ -191,7 +197,8 @@ void initGPIO() { HAL_GPIO_Init(BTN_PORT, &GPIO_Config2); HAL_GPIO_Init(LoRa_CS_GPIO_Port, &GPIO_ConfigSPI); // HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); - // HAL_GPIO_WritePin(LoRa_RESET_GPIO_Port, LoRa_RESET_Pin, GPIO_PIN_SET); + // HAL_GPIO_WritePin(LoRa_RESET_GPIO_Port, LoRa_RESET_Pin, + // GPIO_PIN_SET); } extern "C" { From 32eca023a50cc9312b9a3c6cdc12a79ae5f9a960 Mon Sep 17 00:00:00 2001 From: kalipso Date: Thu, 23 Feb 2023 11:03:57 +0100 Subject: [PATCH 09/12] WIP adding uart2 --- main.cpp | 69 +++++++++++++++++++++++++++++++----------------- uart_handler.cpp | 3 +++ uart_handler.hpp | 15 +++++++++++ 3 files changed, 63 insertions(+), 24 deletions(-) diff --git a/main.cpp b/main.cpp index e3a09ca..4601bb1 100644 --- a/main.cpp +++ b/main.cpp @@ -7,6 +7,10 @@ #include "logging.hpp" #include "spi.hpp" +/* + * reserve PB11-PB15 for SPI2 + */ + // STM32VL-Discovery green led - PC9 #define BTN_PORT GPIOA #define LED_PORT GPIOC @@ -15,10 +19,10 @@ #define BTN_PIN GPIO_PIN_0 #define LED_PORT_CLK_ENABLE __HAL_RCC_GPIOC_CLK_ENABLE -#define LoRa_RESET_Pin GPIO_PIN_3 -#define LoRa_RESET_GPIO_Port GPIOA -#define LoRa_CS_Pin GPIO_PIN_4 -#define LoRa_CS_GPIO_Port GPIOA +#define LoRa_RESET_Pin GPIO_PIN_4 +#define LoRa_RESET_GPIO_Port GPIOC +#define LoRa_CS_Pin GPIO_PIN_5 +#define LoRa_CS_GPIO_Port GPIOC #include "rfm95.hpp" @@ -43,7 +47,7 @@ class cmd_holder { using command_array_t = std::array; template - consteval cmd_holder(Args... command_list) + constexpr cmd_holder(Args... command_list) : commands{std::forward(command_list)...} {} constexpr functionPointerType get_func(std::string_view message) const { @@ -67,7 +71,6 @@ class cmd_holder { std::array commands; }; -template class cmd_handler { public: static constexpr auto MaxCmdLength = 24; @@ -75,11 +78,12 @@ class cmd_handler { using iterator_t = array_t::iterator; using const_iterator_t = array_t::const_iterator; - template - consteval cmd_handler(Args &&...command_list) - : commands{std::forward(command_list)...}, - symbols{}, - iterator{symbols.begin()} {} + constexpr cmd_handler() : symbols{}, iterator{symbols.begin()} {} + + static cmd_handler &get() { + static auto c = cmd_handler{}; + return c; + }; void add_symbol(uint8_t symbol) { *iterator = symbol; @@ -124,20 +128,19 @@ class cmd_handler { void print_help_() const { commands.print_help(); } private: - cmd_holder commands; + static constexpr cmd_holder<5> commands{ + std::make_tuple("ver", "Prints current version.", &print_version), + std::make_tuple("error", "Set LogLevel to Error.", &loglevel_error), + std::make_tuple("info", "Set LogLevel to Info.", &loglevel_info), + std::make_tuple("debug", "Set LogLevel to Debug.", &loglevel_debug), + std::make_tuple("help", "Prints available commands", &print_help)}; + array_t symbols; iterator_t iterator; bool ShouldExecute = false; }; -static cmd_handler<5> commands{ - std::make_tuple("ver", "Prints current version.", &print_version), - std::make_tuple("error", "Set LogLevel to Error.", &loglevel_error), - std::make_tuple("info", "Set LogLevel to Info.", &loglevel_info), - std::make_tuple("debug", "Set LogLevel to Debug.", &loglevel_debug), - std::make_tuple("help", "Prints available commands", &print_help)}; - -void print_help(void) { commands.print_help_(); } +void print_help(void) { cmd_handler::get().print_help_(); } // This prevent name mangling for functions used in C/assembly files. extern "C" { @@ -146,6 +149,12 @@ void SysTick_Handler(void) { HAL_SYSTICK_IRQHandler(); } +void USART2_IRQHandler(void) { + HAL_UART_IRQHandler(&gps_interface::s_UARTHandle); + HAL_UART_Receive_IT(&gps_interface::s_UARTHandle, uart_interface::get_buf(), + 1); +} + void USART1_IRQHandler(void) { HAL_UART_IRQHandler(&uart_interface::s_UARTHandle); HAL_UART_Receive_IT(&uart_interface::s_UARTHandle, uart_interface::get_buf(), @@ -153,15 +162,20 @@ void USART1_IRQHandler(void) { } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { + if (huart != &gps_interface::s_UARTHandle) { + return; + } + const uint8_t value = *uart_interface::get_buf(); if (value == '\r') { - commands.queue_execution(); + cmd_handler::get().queue_execution(); HAL_GPIO_TogglePin(LED_PORT, LED2_PIN); return; } - commands.add_symbol(value); + gps_interface::write({reinterpret_cast(&value), 1}); + cmd_handler::get().add_symbol(value); } } @@ -215,17 +229,23 @@ int main(void) { } log::set_loglevel(LogLevel::DEBUG); log::info("logging Initialized"); - log::info("running PentaTrack v0.1.3"); if (!MX_SPI1_Init()) { // toggle status led or something } + if (!gps_interface::init()) { + log::error("UART2 Initialization failed, needed for GPS"); + } else { + log::debug("Uart2 Initialized"); + } + HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(LoRa_RESET_GPIO_Port, LoRa_RESET_Pin, GPIO_PIN_SET); HAL_Delay(10); log::debug("SPI1 Initialized."); + log::debug("Initialization done."); char OP_Mode = 0x01; @@ -240,8 +260,9 @@ int main(void) { // RF95_Init(); while (1) { - commands.run(); + cmd_handler::get().run(); + gps_interface::write("TEST"); // RF95_setModeRx_Continuous(); HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET); // RF95_receive(LoRa_buff); diff --git a/uart_handler.cpp b/uart_handler.cpp index 11d3529..ef72567 100644 --- a/uart_handler.cpp +++ b/uart_handler.cpp @@ -3,3 +3,6 @@ template <> // uint8_t* uart_interface::rx_buff = new uint8_t[10]; uint8_t uart_interface::rx_buff = 0; + +template <> +uint8_t gps_interface::rx_buff = 0; diff --git a/uart_handler.hpp b/uart_handler.hpp index 22311a8..f8b1971 100644 --- a/uart_handler.hpp +++ b/uart_handler.hpp @@ -6,11 +6,18 @@ #include "stm32f1xx_it.h" +// USART 1 constexpr auto UART_PORT = GPIOA_BASE; #define UARTPORT GPIOA #define UARTTX_PIN GPIO_PIN_9 #define UARTRX_PIN GPIO_PIN_10 +// USART 2 +constexpr auto UART2_PORT = GPIOA_BASE; +#define UART2PORT GPIOA +#define UART2TX_PIN GPIO_PIN_2 +#define UART2RX_PIN GPIO_PIN_3 + /* * small uart wrapper * assumes USART1 with default pins/port @@ -19,6 +26,7 @@ template struct uart_handler { static void enable_clocks() { __HAL_RCC_USART1_CLK_ENABLE(); + __HAL_RCC_USART2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_AFIO_CLK_ENABLE(); } @@ -41,6 +49,10 @@ struct uart_handler { /* USART1 interrupt Init */ HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); + + /* USART2 interrupt Init */ + HAL_NVIC_SetPriority(USART2_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(USART2_IRQn); } static bool enable_oscillators() { @@ -142,3 +154,6 @@ UART_HandleTypeDef uart_handler::s_UARTHandle = using uart_interface = uart_handler; + +using gps_interface = + uart_handler; From c3d62bba0867b5ec0796f5ad62a827f3184d7626 Mon Sep 17 00:00:00 2001 From: kalipso Date: Mon, 27 Feb 2023 23:16:39 +0100 Subject: [PATCH 10/12] add smaller timeout to logging --- logging.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logging.hpp b/logging.hpp index 0b5910a..7d9acdb 100644 --- a/logging.hpp +++ b/logging.hpp @@ -41,7 +41,7 @@ class uart_logger : public logging_adapter { bool init() { return uart_interface::init(); } virtual void log(std::string_view message) const override { - uart_interface::write(message); + uart_interface::write(message, 2048); } }; From 9b22bc6acf6bb5ab0c929aa361821817c24579d4 Mon Sep 17 00:00:00 2001 From: kalipso Date: Mon, 27 Feb 2023 23:17:11 +0100 Subject: [PATCH 11/12] WIP working buffer copy with simple locking --- .envrc | 1 + CMakeLists.txt | 1 + commons.cpp | 1 + commons.hpp | 122 ++++++++++++++++++++++++++++++++++++++++++ main.cpp | 78 ++++++++++++++++++++++----- stm32f1xx_it.h | 33 ++++++------ uart_handler.cpp | 4 ++ uart_handler.hpp | 135 ++++++++++++++++++++++++++++++++++++++--------- 8 files changed, 322 insertions(+), 53 deletions(-) create mode 100644 .envrc create mode 100644 commons.cpp create mode 100644 commons.hpp diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/CMakeLists.txt b/CMakeLists.txt index c3b40be..57a2bdd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ add_executable(stm32-blinky-f1 uart_handler.cpp spi.cpp rfm95.cpp + commons.cpp stm32f1xx_it.c stm32f1xx_hal_conf.h ) diff --git a/commons.cpp b/commons.cpp new file mode 100644 index 0000000..aec1aac --- /dev/null +++ b/commons.cpp @@ -0,0 +1 @@ +#include "commons.hpp" diff --git a/commons.hpp b/commons.hpp new file mode 100644 index 0000000..1bfe234 --- /dev/null +++ b/commons.hpp @@ -0,0 +1,122 @@ +#pragma once + +#include +#include +#include + +#include "logging.hpp" + +namespace commons { + +template +class lock +{ +public: + ~lock() { locker.unlock(); } + + static std::optional get(LockType& l) + { + if(!l.lock()) + { + log::debug("Could not acquire lock."); + return std::nullopt; + } + return lock{l}; + } + +private: + explicit lock(LockType& l) : locker{l} {} + LockType& locker; +}; + +class mutex +{ +public: + bool lock() + { + if(locked) + { + return false; + } + + locked = true; + return true; + } + + void unlock() + { + locked = false; + } + + bool is_locked() const { + return locked; + } + +protected: + bool locked = false; +}; + +} + +template +struct buffer { + constexpr buffer() {} + constexpr auto size() { return S; } + + bool copy_from(const std::span& input, uint16_t amount) + { + const auto lk = commons::lock::get(m); + if(!lk) + { + return false; + } + + if(amount > max_size) + { + return false; + } + + old_pos = new_pos; + + if (old_pos + amount > max_size) { + const auto size_to_copy = max_size - old_pos; + std::copy(input.begin(), + std::next(input.begin(), size_to_copy), + std::next(buf.begin(), old_pos)); + old_pos = 0; + + //TODO: this only works if amount is not double the size of main_buf + std::copy(std::next(input.begin(), size_to_copy), + input.begin() + amount, buf.begin()); + new_pos = amount - size_to_copy; + } else { + std::copy(input.begin(), + input.begin() + amount, + std::next(buf.begin(), old_pos)); + new_pos = old_pos + amount; + } + + return true; + } + + bool print() const + { + const auto lk = commons::lock::get(m); + if(!lk) + { + return false; + } + + uart_interface::write( + {reinterpret_cast(buf.data()), new_pos}); + return true; + } + +private: + static constexpr auto max_size = S; + std::array buf{}; + size_t old_pos = 0; + size_t new_pos = 0; + mutable commons::mutex m; +}; + diff --git a/main.cpp b/main.cpp index 4601bb1..366c545 100644 --- a/main.cpp +++ b/main.cpp @@ -1,9 +1,9 @@ #include #include -#include #include +#include "commons.hpp" #include "logging.hpp" #include "spi.hpp" @@ -71,6 +71,11 @@ class cmd_holder { std::array commands; }; +static bool updated_main_buf = false; +static buffer main_buffer; + +void print_buf(void) { main_buffer.print(); } + class cmd_handler { public: static constexpr auto MaxCmdLength = 24; @@ -110,6 +115,8 @@ class cmd_handler { iterator = symbols.begin(); if (func == nullptr) { + log::info("Unknown Command: ", current_cmd); + log::info("Type 'help' to show available commands."); return; } @@ -128,11 +135,12 @@ class cmd_handler { void print_help_() const { commands.print_help(); } private: - static constexpr cmd_holder<5> commands{ + static constexpr cmd_holder<6> commands{ std::make_tuple("ver", "Prints current version.", &print_version), std::make_tuple("error", "Set LogLevel to Error.", &loglevel_error), std::make_tuple("info", "Set LogLevel to Info.", &loglevel_info), std::make_tuple("debug", "Set LogLevel to Debug.", &loglevel_debug), + std::make_tuple("buf", "Prints gps uart buffer", &print_buf), std::make_tuple("help", "Prints available commands", &print_help)}; array_t symbols; @@ -162,7 +170,7 @@ void USART1_IRQHandler(void) { } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { - if (huart != &gps_interface::s_UARTHandle) { + if (huart == &gps_interface::s_UARTHandle) { return; } @@ -174,9 +182,43 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { return; } - gps_interface::write({reinterpret_cast(&value), 1}); cmd_handler::get().add_symbol(value); } + +void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { + // const uint8_t value = *gps_interface::get_buf(); + // gps_interface::write({reinterpret_cast(&value), 1}); +} + +void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { + // log::debug("DMA Callback"); + + HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET); + if (main_buffer.copy_from(gps_interface::new_rx_buf, Size)) { + log::debug("Copied to main buff"); + updated_main_buf = true; + } + HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET); + + HAL_UARTEx_ReceiveToIdle_DMA(&gps_interface::s_UARTHandle, + gps_interface::new_rx_buf.data(), + gps_interface::new_rx_buf.size()); + __HAL_DMA_DISABLE_IT(&gps_interface::s_DMAHandle, DMA_IT_HT); +} + +/** + * @brief This function handles DMA1 channel6 global interrupt. + */ +void DMA1_Channel6_IRQHandler(void) { + /* USER CODE BEGIN DMA1_Channel6_IRQn 0 */ + + /* USER CODE END DMA1_Channel6_IRQn 0 */ + HAL_DMA_IRQHandler(&gps_interface::s_DMAHandle); + + /* USER CODE BEGIN DMA1_Channel6_IRQn 1 */ + + /* USER CODE END DMA1_Channel6_IRQn 1 */ +} } void initGPIO() { @@ -217,6 +259,13 @@ void initGPIO() { extern "C" { #include + +void start_interrupt() { + HAL_UARTEx_ReceiveToIdle_DMA(&gps_interface::s_UARTHandle, + gps_interface::new_rx_buf.data(), + gps_interface::new_rx_buf.size()); + __HAL_DMA_DISABLE_IT(&gps_interface::s_DMAHandle, DMA_IT_HT); +} } int main(void) { @@ -242,10 +291,9 @@ int main(void) { HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(LoRa_RESET_GPIO_Port, LoRa_RESET_Pin, GPIO_PIN_SET); - HAL_Delay(10); + HAL_Delay(1000); log::debug("SPI1 Initialized."); - log::debug("Initialization done."); char OP_Mode = 0x01; @@ -259,16 +307,22 @@ int main(void) { HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); // RF95_Init(); + while (1) { cmd_handler::get().run(); - gps_interface::write("TEST"); - // RF95_setModeRx_Continuous(); - HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET); + // gps_interface::write("TEST"); + // RF95_setModeRx_Continuous(); + // HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET); // RF95_receive(LoRa_buff); - HAL_Delay(500); - HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET); - HAL_Delay(500); + // HAL_Delay(100); + // HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET); + HAL_Delay(100); + + // if (updated_main_buf) { + // log::debug("Printing main buf"); + // updated_main_buf = !main_buffer.print(); + // } // std::string_view msg{reinterpret_cast(LoRa_buff)}; // log::info("Received Message"); diff --git a/stm32f1xx_it.h b/stm32f1xx_it.h index 4ea7520..c7815c5 100644 --- a/stm32f1xx_it.h +++ b/stm32f1xx_it.h @@ -1,20 +1,20 @@ /* USER CODE BEGIN Header */ /** - ****************************************************************************** - * @file stm32f1xx_it.h - * @brief This file contains the headers of the interrupt handlers. - ****************************************************************************** - * @attention - * - * Copyright (c) 2022 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * ****************************************************************************** - */ + * @file stm32f1xx_it.h + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * @attention + * + * Copyright (c) 2022 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ /* USER CODE END Header */ /* Define to prevent recursive inclusion -------------------------------------*/ @@ -22,7 +22,7 @@ #define __STM32F1xx_IT_H #ifdef __cplusplus - extern "C" { +extern "C" { #endif /* Private includes ----------------------------------------------------------*/ @@ -55,6 +55,9 @@ void SVC_Handler(void); void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); +void DMA1_Channel6_IRQHandler(void); +void USART1_IRQHandler(void); + /* USER CODE BEGIN EFP */ /* USER CODE END EFP */ diff --git a/uart_handler.cpp b/uart_handler.cpp index ef72567..70b30f1 100644 --- a/uart_handler.cpp +++ b/uart_handler.cpp @@ -3,6 +3,10 @@ template <> // uint8_t* uart_interface::rx_buff = new uint8_t[10]; uint8_t uart_interface::rx_buff = 0; +template <> +std::array uart_interface::new_rx_buf{}; template <> uint8_t gps_interface::rx_buff = 0; +template <> +std::array gps_interface::new_rx_buf{}; diff --git a/uart_handler.hpp b/uart_handler.hpp index f8b1971..96870c7 100644 --- a/uart_handler.hpp +++ b/uart_handler.hpp @@ -2,6 +2,7 @@ #include +#include #include #include "stm32f1xx_it.h" @@ -22,11 +23,22 @@ constexpr auto UART2_PORT = GPIOA_BASE; * small uart wrapper * assumes USART1 with default pins/port */ -template +enum class UartMode : uint8_t { + Blocking = 0, + Interrupt, + DMA, +}; + +template struct uart_handler { static void enable_clocks() { - __HAL_RCC_USART1_CLK_ENABLE(); - __HAL_RCC_USART2_CLK_ENABLE(); + if constexpr (UsartBase == USART1_BASE) { + __HAL_RCC_USART1_CLK_ENABLE(); + } else if constexpr (UsartBase == USART2_BASE) { + __HAL_RCC_USART2_CLK_ENABLE(); + } + __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_AFIO_CLK_ENABLE(); } @@ -46,13 +58,83 @@ struct uart_handler { HAL_GPIO_Init(reinterpret_cast(port), &ua_tx); HAL_GPIO_Init(reinterpret_cast(port), &ua_rx); - /* USART1 interrupt Init */ - HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(USART1_IRQn); + // if constexpr (UsartBase == USART1_BASE) { + // /* USART1 interrupt Init */ + // HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); + // HAL_NVIC_EnableIRQ(USART1_IRQn); + // } - /* USART2 interrupt Init */ - HAL_NVIC_SetPriority(USART2_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(USART2_IRQn); + ///* USART2 interrupt Init */ + // HAL_NVIC_SetPriority(USART2_IRQn, 0, 0); + // HAL_NVIC_EnableIRQ(USART2_IRQn); + } + + static void init_mode() { + if (M == UartMode::Blocking) { + return; // nothing to od + } + + if constexpr (M == UartMode::Interrupt) { + constexpr auto GlobalInterrupt = [](auto Base) { + if (Base == USART1_BASE) { + return USART1_IRQn; + } + if (Base == USART2_BASE) { + return USART2_IRQn; + } + }(UsartBase); + + HAL_NVIC_SetPriority(GlobalInterrupt, 0, 0); + HAL_NVIC_EnableIRQ(GlobalInterrupt); + + HAL_UART_Receive_IT(&s_UARTHandle, &rx_buff, rx_buff_size); + return; + } + if constexpr (M == UartMode::DMA) { + /* DMA controller clock enable */ + __HAL_RCC_DMA1_CLK_ENABLE(); + __HAL_RCC_AFIO_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + /* System interrupt init*/ + + /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled + */ + __HAL_AFIO_REMAP_SWJ_NOJTAG(); + + /* DMA interrupt init */ + /* DMA1_Channel6_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn); + + s_DMAHandle.Instance = DMA1_Channel6; + s_DMAHandle.Init.Direction = DMA_PERIPH_TO_MEMORY; + s_DMAHandle.Init.PeriphInc = DMA_PINC_DISABLE; + s_DMAHandle.Init.MemInc = DMA_MINC_ENABLE; + s_DMAHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + s_DMAHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + s_DMAHandle.Init.Mode = DMA_NORMAL; + s_DMAHandle.Init.Priority = DMA_PRIORITY_LOW; + write("TRY DMA INIT"); + if (HAL_DMA_Init(&s_DMAHandle) != HAL_OK) { + write("FAILED"); + // Error_Handler(); + } + + __HAL_LINKDMA(&s_UARTHandle, hdmarx, s_DMAHandle); + + /* USART1 interrupt Init */ + HAL_NVIC_SetPriority(USART2_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(USART2_IRQn); + + HAL_DMA_Start_IT( + &s_DMAHandle, reinterpret_cast(&s_UARTHandle.Instance->DR), + reinterpret_cast(new_rx_buf.data()), new_rx_buf.size()); + + HAL_UARTEx_ReceiveToIdle_DMA(&s_UARTHandle, new_rx_buf.data(), + new_rx_buf.size()); + __HAL_DMA_DISABLE_IT(&s_DMAHandle, DMA_IT_HT); + } } static bool enable_oscillators() { @@ -101,32 +183,25 @@ struct uart_handler { return false; } - result = HAL_UART_Receive_IT(&s_UARTHandle, &rx_buff, rx_buff_size); - return result == HAL_OK; } static bool init() { enable_clocks(); init_gpio(); - if (!enable_oscillators()) { return false; } - return init_uart_handle(); + auto result = init_uart_handle(); + init_mode(); + return result; } static HAL_StatusTypeDef write(const std::string_view& message, uint32_t timeout = HAL_MAX_DELAY) { - // constexpr std::string_view carriage_return{"\r\n"}; - return write(reinterpret_cast(const_cast(message.data())), message.size(), timeout); - - // return write( - // reinterpret_cast(const_cast(carriage_return.data())), - // carriage_return.size(), timeout); } static HAL_StatusTypeDef write(uint8_t* buf, uint16_t size, @@ -135,9 +210,11 @@ struct uart_handler { } static UART_HandleTypeDef s_UARTHandle; + static DMA_HandleTypeDef s_DMAHandle; static uint8_t* get_buf() { return &rx_buff; } static const uint8_t* get_buf_c() { return &rx_buff; } + static std::array new_rx_buf; private: static constexpr auto pin_tx = PinTX; @@ -148,12 +225,18 @@ struct uart_handler { static uint8_t rx_buff; }; -template -UART_HandleTypeDef uart_handler::s_UARTHandle = - UART_HandleTypeDef(); +template +DMA_HandleTypeDef uart_handler::s_DMAHandle = DMA_HandleTypeDef(); -using uart_interface = - uart_handler; +template +UART_HandleTypeDef uart_handler::s_UARTHandle = UART_HandleTypeDef(); -using gps_interface = - uart_handler; +using uart_interface = uart_handler; + +using gps_interface = uart_handler; From 8bd5604a3c66f39b79d2afaf8ca859a543568b32 Mon Sep 17 00:00:00 2001 From: kalipso Date: Tue, 28 Feb 2023 01:34:04 +0100 Subject: [PATCH 12/12] WIP add super basic gps handler --- commons.hpp | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ logging.hpp | 5 ++++ main.cpp | 45 ++++++++++++++++++++---------- uart_handler.cpp | 2 +- uart_handler.hpp | 2 +- 5 files changed, 108 insertions(+), 17 deletions(-) diff --git a/commons.hpp b/commons.hpp index 1bfe234..081917d 100644 --- a/commons.hpp +++ b/commons.hpp @@ -99,6 +99,18 @@ struct buffer { return true; } + template + bool execute(const Func_t& executor) + { + const auto lk = commons::lock::get(m); + if(!lk) + { + return false; + } + + executor(buf); + } + bool print() const { const auto lk = commons::lock::get(m); @@ -120,3 +132,62 @@ private: mutable commons::mutex m; }; +class gps_data +{ +public: + void extract_gps_data(auto& buf) + { + buf.execute([this](auto& value) { this->copy_to_own_buf(value); }); + } + + void copy_to_own_buf(std::span other) + { + auto view = std::string_view{reinterpret_cast(other.data()), other.size()}; + + const auto it_begin = view.find("$GPGGA"); + + if(it_begin == view.npos) + { + return; + } + + view.remove_prefix(it_begin); + const auto it_end = view.find("\r\n", it_begin); + + if(it_end == view.npos) + { + return; + } + + view.remove_suffix(view.size() - it_end); + + if(view.size() > max_size) + { + return; + } + + std::copy(view.begin(), view.end(), current_line.begin()); + current_size = std::distance(view.begin(), view.end()); + valid = true; + } + + bool is_valid() const + { + return valid; + } + + void print() const + { + log::info("Current GPS Data:"); + uart_interface::write( + {reinterpret_cast(current_line.data()), current_size}); + log::linebreak(); + } + +private: + static constexpr uint8_t max_size = 82; //defined by GPS NMEA 0183 protocol + size_t current_size = 0; + std::array current_line; + bool valid = false; +}; + diff --git a/logging.hpp b/logging.hpp index 7d9acdb..8cbcc1f 100644 --- a/logging.hpp +++ b/logging.hpp @@ -59,6 +59,11 @@ class log { return logger_impl.init(); } + static void linebreak() { + const auto val = std::string_view{"\r\n"}; + return logger->log(val); + } + template static void error(Args&&... args) { if (!log_impl_begin(LogLevel::ERROR)) { diff --git a/main.cpp b/main.cpp index 366c545..b743c88 100644 --- a/main.cpp +++ b/main.cpp @@ -72,9 +72,13 @@ class cmd_holder { }; static bool updated_main_buf = false; -static buffer main_buffer; +static bool print_main_buf = false; +static buffer main_buffer{}; +static gps_data gps; void print_buf(void) { main_buffer.print(); } +void print_gps(void) { gps.print(); } +void print_buf_toggle(void) { print_main_buf = !print_main_buf; } class cmd_handler { public: @@ -135,12 +139,15 @@ class cmd_handler { void print_help_() const { commands.print_help(); } private: - static constexpr cmd_holder<6> commands{ + static constexpr cmd_holder<8> commands{ std::make_tuple("ver", "Prints current version.", &print_version), std::make_tuple("error", "Set LogLevel to Error.", &loglevel_error), std::make_tuple("info", "Set LogLevel to Info.", &loglevel_info), std::make_tuple("debug", "Set LogLevel to Debug.", &loglevel_debug), - std::make_tuple("buf", "Prints gps uart buffer", &print_buf), + std::make_tuple("gps", "Prints captured gps data", &print_gps), + std::make_tuple("buf", "Prints uart2 buffer", &print_buf), + std::make_tuple("buft", "toggles continous printing of uart2 buffer", + &print_buf_toggle), std::make_tuple("help", "Prints available commands", &print_help)}; array_t symbols; @@ -178,7 +185,6 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (value == '\r') { cmd_handler::get().queue_execution(); - HAL_GPIO_TogglePin(LED_PORT, LED2_PIN); return; } @@ -195,7 +201,6 @@ void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET); if (main_buffer.copy_from(gps_interface::new_rx_buf, Size)) { - log::debug("Copied to main buff"); updated_main_buf = true; } HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET); @@ -282,6 +287,11 @@ int main(void) { if (!MX_SPI1_Init()) { // toggle status led or something } + HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); + HAL_GPIO_WritePin(LoRa_RESET_GPIO_Port, LoRa_RESET_Pin, GPIO_PIN_SET); + HAL_Delay(10); + + log::debug("SPI1 Initialized."); if (!gps_interface::init()) { log::error("UART2 Initialization failed, needed for GPS"); @@ -289,11 +299,6 @@ int main(void) { log::debug("Uart2 Initialized"); } - HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET); - HAL_GPIO_WritePin(LoRa_RESET_GPIO_Port, LoRa_RESET_Pin, GPIO_PIN_SET); - HAL_Delay(1000); - - log::debug("SPI1 Initialized."); log::debug("Initialization done."); char OP_Mode = 0x01; @@ -308,6 +313,8 @@ int main(void) { // RF95_Init(); + HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_RESET); + while (1) { cmd_handler::get().run(); @@ -317,12 +324,20 @@ int main(void) { // RF95_receive(LoRa_buff); // HAL_Delay(100); // HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET); - HAL_Delay(100); + // HAL_Delay(100); - // if (updated_main_buf) { - // log::debug("Printing main buf"); - // updated_main_buf = !main_buffer.print(); - // } + if (gps.is_valid()) { + HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_SET); + } + + if (updated_main_buf) { + updated_main_buf = false; + gps.extract_gps_data(main_buffer); + + if (print_main_buf) { + updated_main_buf = !main_buffer.print(); + } + } // std::string_view msg{reinterpret_cast(LoRa_buff)}; // log::info("Received Message"); diff --git a/uart_handler.cpp b/uart_handler.cpp index 70b30f1..3accf2a 100644 --- a/uart_handler.cpp +++ b/uart_handler.cpp @@ -9,4 +9,4 @@ std::array uart_interface::new_rx_buf{}; template <> uint8_t gps_interface::rx_buff = 0; template <> -std::array gps_interface::new_rx_buf{}; +std::array gps_interface::new_rx_buf{}; diff --git a/uart_handler.hpp b/uart_handler.hpp index 96870c7..0dfd863 100644 --- a/uart_handler.hpp +++ b/uart_handler.hpp @@ -239,4 +239,4 @@ using uart_interface = uart_handler; using gps_interface = uart_handler; + USART2_BASE, UartMode::DMA, 256>;