commit 514670e897c4103d9a9208e0a02aefe984e47684 Author: kalipso Date: Sun Dec 18 15:37:26 2022 +0100 init 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();