merge base_project

This commit is contained in:
2023-02-28 11:18:50 +01:00
45 changed files with 6966 additions and 39 deletions

4
.gitignore vendored
View File

@@ -1,2 +1,6 @@
research/*
research
*.user
build/
*bak
test/

67
CMakeLists.txt Normal file
View File

@@ -0,0 +1,67 @@
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 DMA)
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}
logging.cpp
uart_handler.cpp
spi.cpp
rfm95.cpp
commons.cpp
stm32f1xx_it.c
stm32f1xx_hal_conf.h
)
set_property(TARGET stm32-blinky-f1 PROPERTY CXX_STANDARD 20)
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
HAL::STM32::F1::DMA
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)

404
cmake/FindBSP.cmake Normal file
View File

@@ -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
)

326
cmake/FindCMSIS.cmake Normal file
View File

@@ -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_<n> 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 "<release version=\"([0-9]*\\.[0-9]*\\.[0-9]*)\" date=\"[0-9]+\\-[0-9]+\\-[0-9]+\">")
list(GET VERSION_STRINGS 0 STR)
string(REGEX MATCH "<release version=\"([0-9]*)\\.([0-9]*)\\.([0-9]*)\" date=\"[0-9]+\\-[0-9]+\\-[0-9]+\">" 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 <family>.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
)

259
cmake/FindFreeRTOS.cmake Normal file
View File

@@ -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
)

315
cmake/FindHAL.cmake Normal file
View File

@@ -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<FAMILY>[..] 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<FAMILY>[..] 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<FAMILY>[..] 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
)

372
cmake/stm32/common.cmake Normal file
View File

@@ -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 $<$<C_COMPILER_ID:GNU>:--specs=nosys.specs>)
target_link_options(STM32::NoSys INTERFACE $<$<C_COMPILER_ID:GNU>:--specs=nosys.specs>)
endif()
if(NOT (TARGET STM32::Nano))
add_library(STM32::Nano INTERFACE IMPORTED)
target_compile_options(STM32::Nano INTERFACE $<$<C_COMPILER_ID:GNU>:--specs=nano.specs>)
target_link_options(STM32::Nano INTERFACE $<$<C_COMPILER_ID:GNU>:--specs=nano.specs>)
endif()
if(NOT (TARGET STM32::Nano::FloatPrint))
add_library(STM32::Nano::FloatPrint INTERFACE IMPORTED)
target_link_options(STM32::Nano::FloatPrint INTERFACE
$<$<C_COMPILER_ID:GNU>:-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
$<$<C_COMPILER_ID:GNU>:-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)

1258
cmake/stm32/devices.cmake Normal file

File diff suppressed because it is too large Load Diff

25
cmake/stm32/f0.cmake Normal file
View File

@@ -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
)

78
cmake/stm32/f1.cmake Normal file
View File

@@ -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()

39
cmake/stm32/f2.cmake Normal file
View File

@@ -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()

59
cmake/stm32/f3.cmake Normal file
View File

@@ -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()

29
cmake/stm32/f4.cmake Normal file
View File

@@ -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
)

25
cmake/stm32/f7.cmake Normal file
View File

@@ -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
)

25
cmake/stm32/g0.cmake Normal file
View File

@@ -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
)

25
cmake/stm32/g4.cmake Normal file
View File

@@ -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
)

87
cmake/stm32/h7.cmake Normal file
View File

@@ -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()

29
cmake/stm32/l0.cmake Normal file
View File

@@ -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
)

73
cmake/stm32/l1.cmake Normal file
View File

@@ -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()

40
cmake/stm32/l4.cmake Normal file
View File

@@ -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
)

22
cmake/stm32/l5.cmake Normal file
View File

@@ -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
)

158
cmake/stm32/linker_ld.cmake Normal file
View File

@@ -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}")

31
cmake/stm32/mp1.cmake Normal file
View File

@@ -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()

19
cmake/stm32/u5.cmake Normal file
View File

@@ -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
)

161
cmake/stm32/utilities.cmake Normal file
View File

@@ -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()

38
cmake/stm32/wb.cmake Normal file
View File

@@ -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()

77
cmake/stm32/wl.cmake Normal file
View File

@@ -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()

23
cmake/stm32_gcc.cmake Normal file
View File

@@ -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)

1
commons.cpp Normal file
View File

@@ -0,0 +1 @@
#include "commons.hpp"

193
commons.hpp Normal file
View File

@@ -0,0 +1,193 @@
#pragma once
#include <array>
#include <span>
#include <optional>
#include "logging.hpp"
namespace commons {
template<typename LockType>
class lock
{
public:
~lock() { locker.unlock(); }
static std::optional<lock> get(LockType& l)
{
if(!l.lock())
{
log::debug("Could not acquire lock.");
return std::nullopt;
}
return lock<LockType>{l};
}
private:
explicit lock(LockType& l) : locker{l} {}
LockType& locker;
};
class mutex
{
public:
bool lock()
{
if(locked)
{
return false;
}
locked = true;
return true;
}
void unlock()
{
locked = false;
}
bool is_locked() const {
return locked;
}
protected:
bool locked = false;
};
}
template <typename T, size_t S>
struct buffer {
constexpr buffer() {}
constexpr auto size() { return S; }
bool copy_from(const std::span<T>& input, uint16_t amount)
{
const auto lk = commons::lock<commons::mutex>::get(m);
if(!lk)
{
return false;
}
if(amount > max_size)
{
return false;
}
old_pos = new_pos;
if (old_pos + amount > max_size) {
const auto size_to_copy = max_size - old_pos;
std::copy(input.begin(),
std::next(input.begin(), size_to_copy),
std::next(buf.begin(), old_pos));
old_pos = 0;
//TODO: this only works if amount is not double the size of main_buf
std::copy(std::next(input.begin(), size_to_copy),
input.begin() + amount, buf.begin());
new_pos = amount - size_to_copy;
} else {
std::copy(input.begin(),
input.begin() + amount,
std::next(buf.begin(), old_pos));
new_pos = old_pos + amount;
}
return true;
}
template<typename Func_t>
bool execute(const Func_t& executor)
{
const auto lk = commons::lock<commons::mutex>::get(m);
if(!lk)
{
return false;
}
executor(buf);
}
bool print() const
{
const auto lk = commons::lock<commons::mutex>::get(m);
if(!lk)
{
return false;
}
uart_interface::write(
{reinterpret_cast<const char *>(buf.data()), new_pos});
return true;
}
private:
static constexpr auto max_size = S;
std::array<T, S> buf{};
size_t old_pos = 0;
size_t new_pos = 0;
mutable commons::mutex m;
};
class gps_data
{
public:
void extract_gps_data(auto& buf)
{
buf.execute([this](auto& value) { this->copy_to_own_buf(value); });
}
void copy_to_own_buf(std::span<uint8_t> other)
{
auto view = std::string_view{reinterpret_cast<const char*>(other.data()), other.size()};
const auto it_begin = view.find("$GPGGA");
if(it_begin == view.npos)
{
return;
}
view.remove_prefix(it_begin);
const auto it_end = view.find("\r\n", it_begin);
if(it_end == view.npos)
{
return;
}
view.remove_suffix(view.size() - it_end);
if(view.size() > max_size)
{
return;
}
std::copy(view.begin(), view.end(), current_line.begin());
current_size = std::distance(view.begin(), view.end());
valid = true;
}
bool is_valid() const
{
return valid;
}
void print() const
{
log::info("Current GPS Data:");
uart_interface::write(
{reinterpret_cast<const char *>(current_line.data()), current_size});
log::linebreak();
}
private:
static constexpr uint8_t max_size = 82; //defined by GPS NMEA 0183 protocol
size_t current_size = 0;
std::array<uint8_t, max_size> current_line;
bool valid = false;
};

6
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1669791787,
"narHash": "sha256-KBfoA2fOI5+wCrm7PR+j7jHqXeTkVRPQ0m5fcKchyuU=",
"lastModified": 1670929434,
"narHash": "sha256-n5UBO6XBV4h3TB7FYu2yAuNQMEYOrQyKeODUwKe06ow=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e76c78d20685a043d23f5f9e0ccd2203997f1fb1",
"rev": "1710ed1f6f8ceb75cf7d1cf55ee0cc21760e1c7a",
"type": "github"
},
"original": {

View File

@@ -1,50 +1,54 @@
{
description = "pentatrack flake";
description = "PentaTrack DevEnv";
inputs = {
utils.url = "github:numtide/flake-utils";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
inputs.utils.url = "github:numtide/flake-utils";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
outputs = { self, utils, nixpkgs }:
outputs = { self, nixpkgs, utils, ... }:
utils.lib.eachSystem [ "i686-linux" "x86_64-linux" ]
(system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
devShell = pkgs.mkShell {
ARDUINO_PATH="${pkgs.arduino-core}";
let
libstm32cubef1 = with pkgs; stdenv.mkDerivation {
name = "stm32CubeF1";
shellHok = ''
echo "entering pentatrack devenv"
export PATH="$PATH:${pkgs.arduino-core}/share/arduino/"
src = fetchFromGitHub {
owner = "STMicroelectronics";
repo = "STM32CubeF1";
rev = "c750eab6990cac35ab05020793b0221ecc1a8ce5";
sha256 = "sha256-ICGgQCkY5E5Lcd7+U+hX5+MJcTF7J51NFDx6iy/SfgA=";
};
installPhase = ''
mkdir $out
cp -r ./* $out
'';
};
nativeBuildInputs = with pkgs; [
python310Packages.grip
arduino
arduino-cli
];
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
'';
};
# here some compiler commands would be necessary i guess lul
#packages.PentaTrack = pkgs.mkDerivation rec {
# name = "PentaTrack_v${version}";
# src = ./.;
# version = "0.1.0";
# ARDUINO_PATH="${pkgs.arduino-core}";
# buildInputs = with pkgs; [
# arduino
# ];
# shellHook = ''
# export PATH="$PATH:${pkgs.arduino-core}/share/arduino/"
# '';
#};
pkgs = nixpkgs.legacyPackages.${system};
in
{
devShell = import ./shell.nix {
inherit pkgs;
libstm32cube = libstm32cubef1;
libstm32stdperiph = libstm32stdperiph;
};
}
);
}

4
logging.cpp Normal file
View File

@@ -0,0 +1,4 @@
#include "logging.hpp"
logging_adapter* log::logger = nullptr;
LogLevel log::log_level = LogLevel::INFO;

124
logging.hpp Normal file
View File

@@ -0,0 +1,124 @@
#pragma once
#include <string_view>
#include "uart_handler.hpp"
enum class LogLevel {
ERROR = 0,
INFO,
DEBUG,
TRACE,
};
inline constexpr std::string_view get_loglevel_string(LogLevel level) {
switch (level) {
case (LogLevel::ERROR): {
return "[Error]";
}
case (LogLevel::INFO): {
return "[Info] ";
}
case (LogLevel::DEBUG): {
return "[Debug]";
}
case (LogLevel::TRACE): {
return "[Trace]";
}
}
return "[Unknown]";
}
class logging_adapter {
public:
virtual bool init() { return true; }
virtual void log(std::string_view message) const = 0;
};
class uart_logger : public logging_adapter {
public:
bool init() { return uart_interface::init(); }
virtual void log(std::string_view message) const override {
uart_interface::write(message, 2048);
}
};
class log {
public:
template <typename LoggerType>
static bool init() {
if (logger) {
return true;
}
static LoggerType logger_impl;
logger = &logger_impl;
return logger_impl.init();
}
static void linebreak() {
const auto val = std::string_view{"\r\n"};
return logger->log(val);
}
template <typename... Args>
static void error(Args&&... args) {
if (!log_impl_begin(LogLevel::ERROR)) {
return;
}
log_impl(std::forward<Args&&>(args)...);
}
template <typename... Args>
static void debug(Args&&... args) {
if (!log_impl_begin(LogLevel::DEBUG)) {
return;
}
log_impl(std::forward<Args&&>(args)...);
}
template <typename... Args>
static void info(Args&&... args) {
if (!log_impl_begin(LogLevel::INFO)) {
return;
}
log_impl(std::forward<Args&&>(args)...);
}
static void set_loglevel(LogLevel level) {
info("New LogLevel: ", get_loglevel_string(level));
log_level = level;
}
private:
static bool log_impl_begin(LogLevel level) {
if (log_level < level) {
return false;
}
logger->log(get_loglevel_string(level));
logger->log(": ");
return true;
}
template <typename... Args>
static void log_impl(std::string_view message, Args&&... args) {
logger->log(message);
log_impl(std::forward<Args&&>(args)...);
}
static void log_impl(std::string_view message) {
logger->log(message);
constexpr std::string_view carriage_return{"\r\n"};
logger->log(carriage_return);
}
static logging_adapter* logger;
static LogLevel log_level;
};

354
main.cpp Normal file
View File

@@ -0,0 +1,354 @@
#include <stm32f1xx_hal.h>
#include <stm32f1xx_hal_uart.h>
#include <tuple>
#include "commons.hpp"
#include "logging.hpp"
#include "spi.hpp"
/*
* reserve PB11-PB15 for SPI2
*/
// 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
#define LoRa_RESET_Pin GPIO_PIN_4
#define LoRa_RESET_GPIO_Port GPIOC
#define LoRa_CS_Pin GPIO_PIN_5
#define LoRa_CS_GPIO_Port GPIOC
#include "rfm95.hpp"
extern uint8_t LoRa_buff[RH_RF95_FIFO_SIZE];
extern SPI_HandleTypeDef hspi1;
void print_version(void) { log::info("running PentaTrack v0.1.3"); }
void print_help(void);
void loglevel_error(void) { log::set_loglevel(LogLevel::ERROR); }
void loglevel_info(void) { log::set_loglevel(LogLevel::INFO); }
void loglevel_debug(void) { log::set_loglevel(LogLevel::DEBUG); }
template <size_t Size>
class cmd_holder {
public:
typedef void (*functionPointerType)(void);
using command_t =
std::tuple<std::string_view, std::string_view, functionPointerType>;
template <size_t S>
using command_array_t = std::array<command_t, Size>;
template <typename... Args>
constexpr cmd_holder(Args... command_list)
: commands{std::forward<Args>(command_list)...} {}
constexpr functionPointerType get_func(std::string_view message) const {
for (const auto &[cmd_name, cmd_help, func] : commands) {
if (message == cmd_name) {
return func;
}
}
return nullptr;
}
void print_help() const {
log::info("Listing available commands:");
for (const auto &[cmd_name, cmd_help, func] : commands) {
log::info("\t", cmd_name, " - ", cmd_help);
}
}
private:
std::array<command_t, Size> commands;
};
static bool updated_main_buf = false;
static bool print_main_buf = false;
static buffer<uint8_t, 512> main_buffer{};
static gps_data gps;
void print_buf(void) { main_buffer.print(); }
void print_gps(void) { gps.print(); }
void print_buf_toggle(void) { print_main_buf = !print_main_buf; }
class cmd_handler {
public:
static constexpr auto MaxCmdLength = 24;
using array_t = std::array<uint8_t, MaxCmdLength>;
using iterator_t = array_t::iterator;
using const_iterator_t = array_t::const_iterator;
constexpr cmd_handler() : symbols{}, iterator{symbols.begin()} {}
static cmd_handler &get() {
static auto c = cmd_handler{};
return c;
};
void add_symbol(uint8_t symbol) {
*iterator = symbol;
iterator++;
if (iterator == symbols.end()) {
iterator = symbols.begin();
}
}
std::string_view get_current_cmd() const {
return {reinterpret_cast<const char *>(symbols.data()),
static_cast<size_t>(
std::distance(symbols.begin(), const_iterator_t{iterator}))};
}
bool exists() const {
return commands.get_func(get_current_cmd()) != nullptr;
}
void execute() {
const auto current_cmd = get_current_cmd();
log::debug("Try executing command: ", current_cmd);
const auto func = commands.get_func(current_cmd);
iterator = symbols.begin();
if (func == nullptr) {
log::info("Unknown Command: ", current_cmd);
log::info("Type 'help' to show available commands.");
return;
}
func();
}
void queue_execution() { ShouldExecute = true; }
void run() {
if (ShouldExecute) {
execute();
ShouldExecute = false;
}
}
void print_help_() const { commands.print_help(); }
private:
static constexpr cmd_holder<8> commands{
std::make_tuple("ver", "Prints current version.", &print_version),
std::make_tuple("error", "Set LogLevel to Error.", &loglevel_error),
std::make_tuple("info", "Set LogLevel to Info.", &loglevel_info),
std::make_tuple("debug", "Set LogLevel to Debug.", &loglevel_debug),
std::make_tuple("gps", "Prints captured gps data", &print_gps),
std::make_tuple("buf", "Prints uart2 buffer", &print_buf),
std::make_tuple("buft", "toggles continous printing of uart2 buffer",
&print_buf_toggle),
std::make_tuple("help", "Prints available commands", &print_help)};
array_t symbols;
iterator_t iterator;
bool ShouldExecute = false;
};
void print_help(void) { cmd_handler::get().print_help_(); }
// This prevent name mangling for functions used in C/assembly files.
extern "C" {
void SysTick_Handler(void) {
HAL_IncTick();
HAL_SYSTICK_IRQHandler();
}
void USART2_IRQHandler(void) {
HAL_UART_IRQHandler(&gps_interface::s_UARTHandle);
HAL_UART_Receive_IT(&gps_interface::s_UARTHandle, uart_interface::get_buf(),
1);
}
void USART1_IRQHandler(void) {
HAL_UART_IRQHandler(&uart_interface::s_UARTHandle);
HAL_UART_Receive_IT(&uart_interface::s_UARTHandle, uart_interface::get_buf(),
1);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart == &gps_interface::s_UARTHandle) {
return;
}
const uint8_t value = *uart_interface::get_buf();
if (value == '\r') {
cmd_handler::get().queue_execution();
return;
}
cmd_handler::get().add_symbol(value);
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
// const uint8_t value = *gps_interface::get_buf();
// gps_interface::write({reinterpret_cast<const char *>(&value), 1});
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
// log::debug("DMA Callback");
HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET);
if (main_buffer.copy_from(gps_interface::new_rx_buf, Size)) {
updated_main_buf = true;
}
HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET);
HAL_UARTEx_ReceiveToIdle_DMA(&gps_interface::s_UARTHandle,
gps_interface::new_rx_buf.data(),
gps_interface::new_rx_buf.size());
__HAL_DMA_DISABLE_IT(&gps_interface::s_DMAHandle, DMA_IT_HT);
}
/**
* @brief This function handles DMA1 channel6 global interrupt.
*/
void DMA1_Channel6_IRQHandler(void) {
/* USER CODE BEGIN DMA1_Channel6_IRQn 0 */
/* USER CODE END DMA1_Channel6_IRQn 0 */
HAL_DMA_IRQHandler(&gps_interface::s_DMAHandle);
/* USER CODE BEGIN DMA1_Channel6_IRQn 1 */
/* USER CODE END DMA1_Channel6_IRQn 1 */
}
}
void initGPIO() {
__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<uint32_t*>(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 <stdio.h>
void start_interrupt() {
HAL_UARTEx_ReceiveToIdle_DMA(&gps_interface::s_UARTHandle,
gps_interface::new_rx_buf.data(),
gps_interface::new_rx_buf.size());
__HAL_DMA_DISABLE_IT(&gps_interface::s_DMAHandle, DMA_IT_HT);
}
}
int main(void) {
HAL_Init();
HAL_SYSTICK_Config(1);
initGPIO();
if (!log::init<uart_logger>()) {
// toggle status led or something
}
log::set_loglevel(LogLevel::DEBUG);
log::info("logging 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);
log::debug("SPI1 Initialized.");
if (!gps_interface::init()) {
log::error("UART2 Initialization failed, needed for GPS");
} else {
log::debug("Uart2 Initialized");
}
log::debug("Initialization done.");
char OP_Mode = 0x01;
char buff = 0x7F & OP_Mode;
char res = 0;
HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_RESET);
[[maybe_unused]] auto result =
HAL_SPI_Transmit(&hspi1, (uint8_t *)&buff, 1, 100);
HAL_SPI_Receive(&hspi1, (uint8_t *)&res, 1, 100);
HAL_GPIO_WritePin(LoRa_CS_GPIO_Port, LoRa_CS_Pin, GPIO_PIN_SET);
// RF95_Init();
HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_RESET);
while (1) {
cmd_handler::get().run();
// gps_interface::write("TEST");
// RF95_setModeRx_Continuous();
// HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_RESET);
// RF95_receive(LoRa_buff);
// HAL_Delay(100);
// HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET);
// HAL_Delay(100);
if (gps.is_valid()) {
HAL_GPIO_WritePin(LED_PORT, LED2_PIN, GPIO_PIN_SET);
}
if (updated_main_buf) {
updated_main_buf = false;
gps.extract_gps_data(main_buffer);
if (print_main_buf) {
updated_main_buf = !main_buffer.print();
}
}
// std::string_view msg{reinterpret_cast<char *>(LoRa_buff)};
// log::info("Received Message");
// log::debug("Received Message");
// log::debug(msg);
// std::string_view foo{"Das ist ein test"};
// strcpy((char *)LoRa_buff, foo.data());
// RF95_send(LoRa_buff);
}
return 0;
}

773
rfm95.cpp Normal file
View File

@@ -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;
// }

347
rfm95.hpp Normal file
View File

@@ -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 <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
//#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

17
shell.nix Normal file
View File

@@ -0,0 +1,17 @@
{ pkgs ? import <nixpkgs> {}, libstm32cube, libstm32stdperiph }:
with pkgs;
mkShell {
TARGET_TRIPLET="arm-none-eabi";
STM32_CUBE_F1_PATH="${libstm32cube}";
STM32STDLIB = "${libstm32stdperiph}";
nativeBuildInputs = [
gnumake
stlink
screen
gcc-arm-embedded-10
libstm32cube
libstm32stdperiph
];
}

57
spi.cpp Normal file
View File

@@ -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);
}
}
}

7
spi.hpp Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#include <stm32f1xx_hal.h>
#include "stm32f1xx_hal_spi.h"
bool MX_SPI1_Init(void);

449
stm32f1xx_hal_conf.h Executable file
View File

@@ -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
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
* All rights reserved.</center></h2>
*
* 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****/

206
stm32f1xx_it.c Normal file
View File

@@ -0,0 +1,206 @@
#include <stm32f1xx_hal.h>
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f1xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/******************************************************************************/
/* Cortex-M3 Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1)
{
}
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
}
/**
* @brief This function handles Prefetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
/* USER CODE END W1_BusFault_IRQn 0 */
}
}
/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
/* USER CODE END W1_UsageFault_IRQn 0 */
}
}
/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
/* USER CODE BEGIN SVCall_IRQn 0 */
/* USER CODE END SVCall_IRQn 0 */
/* USER CODE BEGIN SVCall_IRQn 1 */
/* USER CODE END SVCall_IRQn 1 */
}
/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
/* USER CODE END DebugMonitor_IRQn 0 */
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
/* USER CODE END DebugMonitor_IRQn 1 */
}
/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
/* USER CODE BEGIN PendSV_IRQn 0 */
/* USER CODE END PendSV_IRQn 0 */
/* USER CODE BEGIN PendSV_IRQn 1 */
/* USER CODE END PendSV_IRQn 1 */
}
/**
* @brief This function handles System tick timer.
*/
//void SysTick_Handler(void)
//{
// /* USER CODE BEGIN SysTick_IRQn 0 */
//
// /* USER CODE END SysTick_IRQn 0 */
// HAL_IncTick();
// /* USER CODE BEGIN SysTick_IRQn 1 */
// HAL_SYSTICK_IRQHandler();
//
// /* USER CODE END SysTick_IRQn 1 */
//}
/******************************************************************************/
/* STM32F1xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32f1xx.s). */
/******************************************************************************/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

69
stm32f1xx_it.h Normal file
View File

@@ -0,0 +1,69 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f1xx_it.h
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F1xx_IT_H
#define __STM32F1xx_IT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
void DMA1_Channel6_IRQHandler(void);
void USART1_IRQHandler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
#ifdef __cplusplus
}
#endif
#endif /* __STM32F1xx_IT_H */

12
uart_handler.cpp Normal file
View File

@@ -0,0 +1,12 @@
#include "uart_handler.hpp"
template <>
// uint8_t* uart_interface::rx_buff = new uint8_t[10];
uint8_t uart_interface::rx_buff = 0;
template <>
std::array<uint8_t, 1> uart_interface::new_rx_buf{};
template <>
uint8_t gps_interface::rx_buff = 0;
template <>
std::array<uint8_t, 256> gps_interface::new_rx_buf{};

242
uart_handler.hpp Normal file
View File

@@ -0,0 +1,242 @@
#pragma once
#include <stm32f1xx_hal.h>
#include <array>
#include <string_view>
#include "stm32f1xx_it.h"
// USART 1
constexpr auto UART_PORT = GPIOA_BASE;
#define UARTPORT GPIOA
#define UARTTX_PIN GPIO_PIN_9
#define UARTRX_PIN GPIO_PIN_10
// USART 2
constexpr auto UART2_PORT = GPIOA_BASE;
#define UART2PORT GPIOA
#define UART2TX_PIN GPIO_PIN_2
#define UART2RX_PIN GPIO_PIN_3
/*
* small uart wrapper
* assumes USART1 with default pins/port
*/
enum class UartMode : uint8_t {
Blocking = 0,
Interrupt,
DMA,
};
template <uint16_t PinTX, uint16_t PinRX, uint32_t Port, uint32_t UsartBase,
UartMode M = UartMode::Interrupt, uint16_t Size = 1>
struct uart_handler {
static void enable_clocks() {
if constexpr (UsartBase == USART1_BASE) {
__HAL_RCC_USART1_CLK_ENABLE();
} else if constexpr (UsartBase == USART2_BASE) {
__HAL_RCC_USART2_CLK_ENABLE();
}
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_AFIO_CLK_ENABLE();
}
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<GPIO_TypeDef*>(port), &ua_tx);
HAL_GPIO_Init(reinterpret_cast<GPIO_TypeDef*>(port), &ua_rx);
// if constexpr (UsartBase == USART1_BASE) {
// /* USART1 interrupt Init */
// HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
// HAL_NVIC_EnableIRQ(USART1_IRQn);
// }
///* USART2 interrupt Init */
// HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
// HAL_NVIC_EnableIRQ(USART2_IRQn);
}
static void init_mode() {
if (M == UartMode::Blocking) {
return; // nothing to od
}
if constexpr (M == UartMode::Interrupt) {
constexpr auto GlobalInterrupt = [](auto Base) {
if (Base == USART1_BASE) {
return USART1_IRQn;
}
if (Base == USART2_BASE) {
return USART2_IRQn;
}
}(UsartBase);
HAL_NVIC_SetPriority(GlobalInterrupt, 0, 0);
HAL_NVIC_EnableIRQ(GlobalInterrupt);
HAL_UART_Receive_IT(&s_UARTHandle, &rx_buff, rx_buff_size);
return;
}
if constexpr (M == UartMode::DMA) {
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_RCC_PWR_CLK_ENABLE();
/* System interrupt init*/
/** NOJTAG: JTAG-DP Disabled and SW-DP Enabled
*/
__HAL_AFIO_REMAP_SWJ_NOJTAG();
/* DMA interrupt init */
/* DMA1_Channel6_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
s_DMAHandle.Instance = DMA1_Channel6;
s_DMAHandle.Init.Direction = DMA_PERIPH_TO_MEMORY;
s_DMAHandle.Init.PeriphInc = DMA_PINC_DISABLE;
s_DMAHandle.Init.MemInc = DMA_MINC_ENABLE;
s_DMAHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
s_DMAHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
s_DMAHandle.Init.Mode = DMA_NORMAL;
s_DMAHandle.Init.Priority = DMA_PRIORITY_LOW;
write("TRY DMA INIT");
if (HAL_DMA_Init(&s_DMAHandle) != HAL_OK) {
write("FAILED");
// Error_Handler();
}
__HAL_LINKDMA(&s_UARTHandle, hdmarx, s_DMAHandle);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
HAL_DMA_Start_IT(
&s_DMAHandle, reinterpret_cast<uint32_t>(&s_UARTHandle.Instance->DR),
reinterpret_cast<uint32_t>(new_rx_buf.data()), new_rx_buf.size());
HAL_UARTEx_ReceiveToIdle_DMA(&s_UARTHandle, new_rx_buf.data(),
new_rx_buf.size());
__HAL_DMA_DISABLE_IT(&s_DMAHandle, DMA_IT_HT);
}
}
static bool enable_oscillators() {
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_TypeDef*>(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);
if (result != HAL_OK) {
return false;
}
return result == HAL_OK;
}
static bool init() {
enable_clocks();
init_gpio();
if (!enable_oscillators()) {
return false;
}
auto result = init_uart_handle();
init_mode();
return result;
}
static HAL_StatusTypeDef write(const std::string_view& message,
uint32_t timeout = HAL_MAX_DELAY) {
return write(reinterpret_cast<uint8_t*>(const_cast<char*>(message.data())),
message.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;
static DMA_HandleTypeDef s_DMAHandle;
static uint8_t* get_buf() { return &rx_buff; }
static const uint8_t* get_buf_c() { return &rx_buff; }
static std::array<uint8_t, Size> new_rx_buf;
private:
static constexpr auto pin_tx = PinTX;
static constexpr auto pin_rx = PinRX;
static constexpr auto port = Port;
static constexpr auto usart_base = UsartBase;
static constexpr size_t rx_buff_size = 1;
static uint8_t rx_buff;
};
template <uint16_t PinTX, uint16_t PinRX, uint32_t Port, uint32_t UsartBase,
UartMode M, uint16_t Size>
DMA_HandleTypeDef uart_handler<PinTX, PinRX, Port, UsartBase, M,
Size>::s_DMAHandle = DMA_HandleTypeDef();
template <uint16_t PinTX, uint16_t PinRX, uint32_t Port, uint32_t UsartBase,
UartMode M, uint16_t Size>
UART_HandleTypeDef uart_handler<PinTX, PinRX, Port, UsartBase, M,
Size>::s_UARTHandle = UART_HandleTypeDef();
using uart_interface = uart_handler<UARTTX_PIN, UARTRX_PIN, UART_PORT,
USART1_BASE, UartMode::Interrupt>;
using gps_interface = uart_handler<UART2TX_PIN, UART2RX_PIN, UART2_PORT,
USART2_BASE, UartMode::DMA, 256>;