From da4f00f652be4b80237e83b368af36ac58646e6f Mon Sep 17 00:00:00 2001 From: wangbeihong Date: Sat, 21 Mar 2026 01:49:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=AF=E7=94=A8=E7=9A=84=E6=96=87=E4=BB=B6?= =?UTF-8?q?=EF=BC=8C=E5=85=A8=E9=83=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .clangd | 11 + .gitignore | 3 + .mxproject | 36 + .settings/bundles-lock.store.json | 158 +++ .settings/bundles.store.json | 20 + .settings/ide.store.json | 9 + .vscode/c_cpp_properties.json | 8 + .vscode/settings.json | 15 + 3D.ioc | 210 ++++ CMakeLists.txt | 83 ++ CMakePresets.json | 38 + Core/Bsp/README.md | 148 +++ Core/Bsp/bsp_bmp280.c | 96 ++ Core/Bsp/bsp_bmp280.h | 32 + Core/Bsp/bsp_cmd.c | 255 ++++ Core/Bsp/bsp_cmd.h | 21 + Core/Bsp/bsp_flash.c | 114 ++ Core/Bsp/bsp_flash.h | 42 + Core/Bsp/bsp_relay.c | 177 +++ Core/Bsp/bsp_relay.h | 60 + Core/Bsp/bsp_uart.c | 131 ++ Core/Bsp/bsp_uart.h | 59 + Core/Bsp/cJSON.c | 540 ++++++++ Core/Bsp/cJSON.h | 203 +++ Core/Bsp/driver_bmp280.c | 1635 +++++++++++++++++++++++++ Core/Bsp/driver_bmp280.h | 669 ++++++++++ Core/Bsp/driver_bmp280_interface.c | 180 +++ Core/Bsp/driver_bmp280_interface.h | 161 +++ Core/Inc/FreeRTOSConfig.h | 139 +++ Core/Inc/dma.h | 52 + Core/Inc/gpio.h | 49 + Core/Inc/i2c.h | 55 + Core/Inc/main.h | 75 ++ Core/Inc/stm32f1xx_hal_conf.h | 391 ++++++ Core/Inc/stm32f1xx_it.h | 67 + Core/Inc/usart.h | 55 + Core/Src/dma.c | 58 + Core/Src/freertos.c | 168 +++ Core/Src/gpio.c | 77 ++ Core/Src/i2c.c | 186 +++ Core/Src/main.c | 218 ++++ Core/Src/stm32f1xx_hal_msp.c | 88 ++ Core/Src/stm32f1xx_hal_timebase_tim.c | 138 +++ Core/Src/stm32f1xx_it.c | 235 ++++ Core/Src/syscalls.c | 244 ++++ Core/Src/sysmem.c | 87 ++ Core/Src/system_stm32f1xx.c | 406 ++++++ Core/Src/usart.c | 241 ++++ STM32F103XX_FLASH.ld | 249 ++++ cmake/gcc-arm-none-eabi.cmake | 43 + cmake/starm-clang.cmake | 65 + cmake/stm32cubemx/CMakeLists.txt | 116 ++ mqtt_web/app.py | 159 +++ mqtt_web/requirements.txt | 2 + mqtt_web/templates/index.html | 158 +++ startup_stm32f103xb.s | 364 ++++++ 56 files changed, 9299 insertions(+) create mode 100644 .clangd create mode 100644 .gitignore create mode 100644 .mxproject create mode 100644 .settings/bundles-lock.store.json create mode 100644 .settings/bundles.store.json create mode 100644 .settings/ide.store.json create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/settings.json create mode 100644 3D.ioc create mode 100644 CMakeLists.txt create mode 100644 CMakePresets.json create mode 100644 Core/Bsp/README.md create mode 100644 Core/Bsp/bsp_bmp280.c create mode 100644 Core/Bsp/bsp_bmp280.h create mode 100644 Core/Bsp/bsp_cmd.c create mode 100644 Core/Bsp/bsp_cmd.h create mode 100644 Core/Bsp/bsp_flash.c create mode 100644 Core/Bsp/bsp_flash.h create mode 100644 Core/Bsp/bsp_relay.c create mode 100644 Core/Bsp/bsp_relay.h create mode 100644 Core/Bsp/bsp_uart.c create mode 100644 Core/Bsp/bsp_uart.h create mode 100644 Core/Bsp/cJSON.c create mode 100644 Core/Bsp/cJSON.h create mode 100644 Core/Bsp/driver_bmp280.c create mode 100644 Core/Bsp/driver_bmp280.h create mode 100644 Core/Bsp/driver_bmp280_interface.c create mode 100644 Core/Bsp/driver_bmp280_interface.h create mode 100644 Core/Inc/FreeRTOSConfig.h create mode 100644 Core/Inc/dma.h create mode 100644 Core/Inc/gpio.h create mode 100644 Core/Inc/i2c.h create mode 100644 Core/Inc/main.h create mode 100644 Core/Inc/stm32f1xx_hal_conf.h create mode 100644 Core/Inc/stm32f1xx_it.h create mode 100644 Core/Inc/usart.h create mode 100644 Core/Src/dma.c create mode 100644 Core/Src/freertos.c create mode 100644 Core/Src/gpio.c create mode 100644 Core/Src/i2c.c create mode 100644 Core/Src/main.c create mode 100644 Core/Src/stm32f1xx_hal_msp.c create mode 100644 Core/Src/stm32f1xx_hal_timebase_tim.c create mode 100644 Core/Src/stm32f1xx_it.c create mode 100644 Core/Src/syscalls.c create mode 100644 Core/Src/sysmem.c create mode 100644 Core/Src/system_stm32f1xx.c create mode 100644 Core/Src/usart.c create mode 100644 STM32F103XX_FLASH.ld create mode 100644 cmake/gcc-arm-none-eabi.cmake create mode 100644 cmake/starm-clang.cmake create mode 100644 cmake/stm32cubemx/CMakeLists.txt create mode 100644 mqtt_web/app.py create mode 100644 mqtt_web/requirements.txt create mode 100644 mqtt_web/templates/index.html create mode 100644 startup_stm32f103xb.s diff --git a/.clangd b/.clangd new file mode 100644 index 0000000..50c62c4 --- /dev/null +++ b/.clangd @@ -0,0 +1,11 @@ +CompileFlags: + Add: + - '-ferror-limit=0' + - '-Wno-implicit-int' + CompilationDatabase: build/Debug +Diagnostics: + Suppress: + - unused-includes + - unknown_typename + - unknown_typename_suggest + - typename_requires_specqual diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..185b49a --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +build +mx.scratch +!.settings \ No newline at end of file diff --git a/.mxproject b/.mxproject new file mode 100644 index 0000000..f8b376f --- /dev/null +++ b/.mxproject @@ -0,0 +1,36 @@ +[PreviousLibFiles] +LibFiles=Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_tim.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_tim_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\Legacy\stm32_hal_legacy.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_def.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_bus.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_system.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_utils.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio_ex.h;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_i2c.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_i2c.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_uart.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_usart.h;Middlewares\Third_Party\FreeRTOS\Source\include\croutine.h;Middlewares\Third_Party\FreeRTOS\Source\include\deprecated_definitions.h;Middlewares\Third_Party\FreeRTOS\Source\include\event_groups.h;Middlewares\Third_Party\FreeRTOS\Source\include\FreeRTOS.h;Middlewares\Third_Party\FreeRTOS\Source\include\list.h;Middlewares\Third_Party\FreeRTOS\Source\include\message_buffer.h;Middlewares\Third_Party\FreeRTOS\Source\include\mpu_prototypes.h;Middlewares\Third_Party\FreeRTOS\Source\include\mpu_wrappers.h;Middlewares\Third_Party\FreeRTOS\Source\include\portable.h;Middlewares\Third_Party\FreeRTOS\Source\include\projdefs.h;Middlewares\Third_Party\FreeRTOS\Source\include\queue.h;Middlewares\Third_Party\FreeRTOS\Source\include\semphr.h;Middlewares\Third_Party\FreeRTOS\Source\include\stack_macros.h;Middlewares\Third_Party\FreeRTOS\Source\include\StackMacros.h;Middlewares\Third_Party\FreeRTOS\Source\include\stream_buffer.h;Middlewares\Third_Party\FreeRTOS\Source\include\task.h;Middlewares\Third_Party\FreeRTOS\Source\include\timers.h;Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS\cmsis_os.h;Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM3\portmacro.h;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim_ex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_i2c.c;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_uart.c;Middlewares\Third_Party\FreeRTOS\Source\croutine.c;Middlewares\Third_Party\FreeRTOS\Source\event_groups.c;Middlewares\Third_Party\FreeRTOS\Source\list.c;Middlewares\Third_Party\FreeRTOS\Source\queue.c;Middlewares\Third_Party\FreeRTOS\Source\stream_buffer.c;Middlewares\Third_Party\FreeRTOS\Source\tasks.c;Middlewares\Third_Party\FreeRTOS\Source\timers.c;Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS\cmsis_os.c;Middlewares\Third_Party\FreeRTOS\Source\portable\MemMang\heap_4.c;Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM3\port.c;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_tim.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_tim_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\Legacy\stm32_hal_legacy.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_def.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_rcc_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_bus.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_rcc.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_system.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_utils.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_gpio_ex.h;Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_gpio.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_dma.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_cortex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_pwr.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_flash_ex.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_exti.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_i2c.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_i2c.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_hal_uart.h;Drivers\STM32F1xx_HAL_Driver\Inc\stm32f1xx_ll_usart.h;Middlewares\Third_Party\FreeRTOS\Source\include\croutine.h;Middlewares\Third_Party\FreeRTOS\Source\include\deprecated_definitions.h;Middlewares\Third_Party\FreeRTOS\Source\include\event_groups.h;Middlewares\Third_Party\FreeRTOS\Source\include\FreeRTOS.h;Middlewares\Third_Party\FreeRTOS\Source\include\list.h;Middlewares\Third_Party\FreeRTOS\Source\include\message_buffer.h;Middlewares\Third_Party\FreeRTOS\Source\include\mpu_prototypes.h;Middlewares\Third_Party\FreeRTOS\Source\include\mpu_wrappers.h;Middlewares\Third_Party\FreeRTOS\Source\include\portable.h;Middlewares\Third_Party\FreeRTOS\Source\include\projdefs.h;Middlewares\Third_Party\FreeRTOS\Source\include\queue.h;Middlewares\Third_Party\FreeRTOS\Source\include\semphr.h;Middlewares\Third_Party\FreeRTOS\Source\include\stack_macros.h;Middlewares\Third_Party\FreeRTOS\Source\include\StackMacros.h;Middlewares\Third_Party\FreeRTOS\Source\include\stream_buffer.h;Middlewares\Third_Party\FreeRTOS\Source\include\task.h;Middlewares\Third_Party\FreeRTOS\Source\include\timers.h;Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS\cmsis_os.h;Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM3\portmacro.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\stm32f103xb.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\stm32f1xx.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\system_stm32f1xx.h;Drivers\CMSIS\Device\ST\STM32F1xx\Include\system_stm32f1xx.h;Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c;Drivers\CMSIS\Include\cmsis_armcc.h;Drivers\CMSIS\Include\cmsis_armclang.h;Drivers\CMSIS\Include\cmsis_compiler.h;Drivers\CMSIS\Include\cmsis_gcc.h;Drivers\CMSIS\Include\cmsis_iccarm.h;Drivers\CMSIS\Include\cmsis_version.h;Drivers\CMSIS\Include\core_armv8mbl.h;Drivers\CMSIS\Include\core_armv8mml.h;Drivers\CMSIS\Include\core_cm0.h;Drivers\CMSIS\Include\core_cm0plus.h;Drivers\CMSIS\Include\core_cm1.h;Drivers\CMSIS\Include\core_cm23.h;Drivers\CMSIS\Include\core_cm3.h;Drivers\CMSIS\Include\core_cm33.h;Drivers\CMSIS\Include\core_cm4.h;Drivers\CMSIS\Include\core_cm7.h;Drivers\CMSIS\Include\core_sc000.h;Drivers\CMSIS\Include\core_sc300.h;Drivers\CMSIS\Include\mpu_armv7.h;Drivers\CMSIS\Include\mpu_armv8.h;Drivers\CMSIS\Include\tz_context.h; + +[PreviousUsedCMakes] +SourceFiles=Core\Src\main.c;Core\Src\gpio.c;Core\Src\freertos.c;Core\Src\dma.c;Core\Src\i2c.c;Core\Src\usart.c;Core\Src\stm32f1xx_it.c;Core\Src\stm32f1xx_hal_msp.c;Core\Src\stm32f1xx_hal_timebase_tim.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim_ex.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_i2c.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_uart.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\croutine.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\event_groups.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\list.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\queue.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\stream_buffer.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\tasks.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\timers.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS\cmsis_os.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\portable\MemMang\heap_4.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM3\port.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c;Core\Src\system_stm32f1xx.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio_ex.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim_ex.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_i2c.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_uart.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\croutine.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\event_groups.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\list.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\queue.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\stream_buffer.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\tasks.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\timers.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS\cmsis_os.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\portable\MemMang\heap_4.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM3\port.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\system_stm32f1xx.c;Core\Src\system_stm32f1xx.c;;;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\croutine.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\event_groups.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\list.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\queue.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\stream_buffer.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\tasks.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\timers.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS\cmsis_os.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\portable\MemMang\heap_4.c;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM3\port.c; +HeaderPath=C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Inc;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\STM32F1xx_HAL_Driver\Inc\Legacy;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\include;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM3;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\CMSIS\Device\ST\STM32F1xx\Include;C:\Users\BeihongWang\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.7\Drivers\CMSIS\Include;Core\Inc; +CDefines=USE_HAL_DRIVER;STM32F103xB;USE_HAL_DRIVER;USE_HAL_DRIVER; + +[PreviousGenFiles] +AdvancedFolderStructure=true +HeaderFileListSize=8 +HeaderFiles#0=..\Core\Inc\gpio.h +HeaderFiles#1=..\Core\Inc\FreeRTOSConfig.h +HeaderFiles#2=..\Core\Inc\dma.h +HeaderFiles#3=..\Core\Inc\i2c.h +HeaderFiles#4=..\Core\Inc\usart.h +HeaderFiles#5=..\Core\Inc\stm32f1xx_it.h +HeaderFiles#6=..\Core\Inc\stm32f1xx_hal_conf.h +HeaderFiles#7=..\Core\Inc\main.h +HeaderFolderListSize=1 +HeaderPath#0=..\Core\Inc +HeaderFiles=; +SourceFileListSize=9 +SourceFiles#0=..\Core\Src\gpio.c +SourceFiles#1=..\Core\Src\freertos.c +SourceFiles#2=..\Core\Src\dma.c +SourceFiles#3=..\Core\Src\i2c.c +SourceFiles#4=..\Core\Src\usart.c +SourceFiles#5=..\Core\Src\stm32f1xx_it.c +SourceFiles#6=..\Core\Src\stm32f1xx_hal_msp.c +SourceFiles#7=..\Core\Src\stm32f1xx_hal_timebase_tim.c +SourceFiles#8=..\Core\Src\main.c +SourceFolderListSize=1 +SourcePath#0=..\Core\Src +SourceFiles=; + diff --git a/.settings/bundles-lock.store.json b/.settings/bundles-lock.store.json new file mode 100644 index 0000000..1568284 --- /dev/null +++ b/.settings/bundles-lock.store.json @@ -0,0 +1,158 @@ +{ + "resolved": [ + { + "name": "cmake", + "version": "4.0.1+st.3", + "platform": "darwin", + "selected_by": [ + { + "name": "cmake", + "version": "4.0.1+st.3" + } + ] + }, + { + "name": "cmake", + "version": "4.0.1+st.3", + "platform": "x86_64-linux", + "selected_by": [ + { + "name": "cmake", + "version": "4.0.1+st.3" + } + ] + }, + { + "name": "cmake", + "version": "4.0.1+st.3", + "platform": "x86_64-windows", + "selected_by": [ + { + "name": "cmake", + "version": "4.0.1+st.3" + } + ] + }, + { + "name": "gnu-tools-for-stm32", + "version": "14.3.1+st.2", + "platform": "aarch64-darwin", + "selected_by": [ + { + "name": "gnu-tools-for-stm32", + "version": "14.3.1+st.2" + } + ] + }, + { + "name": "gnu-tools-for-stm32", + "version": "14.3.1+st.2", + "platform": "x86_64-darwin", + "selected_by": [ + { + "name": "gnu-tools-for-stm32", + "version": "14.3.1+st.2" + } + ] + }, + { + "name": "gnu-tools-for-stm32", + "version": "14.3.1+st.2", + "platform": "x86_64-linux", + "selected_by": [ + { + "name": "gnu-tools-for-stm32", + "version": "14.3.1+st.2" + } + ] + }, + { + "name": "gnu-tools-for-stm32", + "version": "14.3.1+st.2", + "platform": "x86_64-windows", + "selected_by": [ + { + "name": "gnu-tools-for-stm32", + "version": "14.3.1+st.2" + } + ] + }, + { + "name": "gnu-tools-for-stm32-14_3_1-description", + "version": "1.0.1+st.2", + "platform": "all", + "selected_by": [ + { + "name": "gnu-tools-for-stm32-14_3_1-description", + "version": ">=0.0.1" + } + ] + }, + { + "name": "ninja", + "version": "1.13.1+st.1", + "platform": "darwin", + "selected_by": [ + { + "name": "ninja", + "version": "1.13.1+st.1" + } + ] + }, + { + "name": "ninja", + "version": "1.13.1+st.1", + "platform": "x86_64-linux", + "selected_by": [ + { + "name": "ninja", + "version": "1.13.1+st.1" + } + ] + }, + { + "name": "ninja", + "version": "1.13.1+st.1", + "platform": "x86_64-windows", + "selected_by": [ + { + "name": "ninja", + "version": "1.13.1+st.1" + } + ] + }, + { + "name": "st-arm-clangd", + "version": "19.1.2+st.3", + "platform": "darwin", + "selected_by": [ + { + "name": "st-arm-clangd", + "version": "19.1.2+st.3" + } + ] + }, + { + "name": "st-arm-clangd", + "version": "19.1.2+st.3", + "platform": "x86_64-linux", + "selected_by": [ + { + "name": "st-arm-clangd", + "version": "19.1.2+st.3" + } + ] + }, + { + "name": "st-arm-clangd", + "version": "19.1.2+st.3", + "platform": "x86_64-windows", + "selected_by": [ + { + "name": "st-arm-clangd", + "version": "19.1.2+st.3" + } + ] + } + ] +} diff --git a/.settings/bundles.store.json b/.settings/bundles.store.json new file mode 100644 index 0000000..dd143ba --- /dev/null +++ b/.settings/bundles.store.json @@ -0,0 +1,20 @@ +{ + "bundles": [ + { + "name": "cmake", + "version": "4.0.1+st.3" + }, + { + "name": "ninja", + "version": "1.13.1+st.1" + }, + { + "name": "gnu-tools-for-stm32", + "version": "14.3.1+st.2" + }, + { + "name": "st-arm-clangd", + "version": "19.1.2+st.3" + } + ] +} diff --git a/.settings/ide.store.json b/.settings/ide.store.json new file mode 100644 index 0000000..29970d3 --- /dev/null +++ b/.settings/ide.store.json @@ -0,0 +1,9 @@ +{ + "source": { + "sourceType": "STM32CubeMX" + }, + "device": "STM32F103C8T6", + "core": "Cortex-M3", + "order": 0, + "toolchain": "GCC" +} \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..233ee1f --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,8 @@ +{ + "configurations": [ + { + "name": "STM32", + "compileCommands": "${workspaceFolder}/build/Debug/compile_commands.json" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..8627b90 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,15 @@ +{ + "cmake.cmakePath": "cube-cmake", + "cmake.configureArgs": [ + "-DCMAKE_COMMAND=cube-cmake" + ], + "cmake.preferredGenerators": [ + "Ninja" + ], + "stm32cube-ide-clangd.path": "cube", + "stm32cube-ide-clangd.arguments": [ + "starm-clangd", + "--query-driver=${env:CUBE_BUNDLE_PATH}/gnu-tools-for-stm32/14.3.1+st.2/bin/arm-none-eabi-gcc*", + "--query-driver=${env:CUBE_BUNDLE_PATH}/gnu-tools-for-stm32/14.3.1+st.2/bin/arm-none-eabi-g++*" + ] +} \ No newline at end of file diff --git a/3D.ioc b/3D.ioc new file mode 100644 index 0000000..860e578 --- /dev/null +++ b/3D.ioc @@ -0,0 +1,210 @@ +#MicroXplorer Configuration settings - do not modify +CAD.formats= +CAD.pinconfig= +CAD.provider= +Dma.Request0=USART1_RX +Dma.Request1=USART1_TX +Dma.RequestsNb=2 +Dma.USART1_RX.0.Direction=DMA_PERIPH_TO_MEMORY +Dma.USART1_RX.0.Instance=DMA1_Channel5 +Dma.USART1_RX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.USART1_RX.0.MemInc=DMA_MINC_ENABLE +Dma.USART1_RX.0.Mode=DMA_NORMAL +Dma.USART1_RX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.USART1_RX.0.PeriphInc=DMA_PINC_DISABLE +Dma.USART1_RX.0.Priority=DMA_PRIORITY_LOW +Dma.USART1_RX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +Dma.USART1_TX.1.Direction=DMA_MEMORY_TO_PERIPH +Dma.USART1_TX.1.Instance=DMA1_Channel4 +Dma.USART1_TX.1.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.USART1_TX.1.MemInc=DMA_MINC_ENABLE +Dma.USART1_TX.1.Mode=DMA_NORMAL +Dma.USART1_TX.1.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.USART1_TX.1.PeriphInc=DMA_PINC_DISABLE +Dma.USART1_TX.1.Priority=DMA_PRIORITY_LOW +Dma.USART1_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +FREERTOS.FootprintOK=true +FREERTOS.IPParameters=Tasks01,FootprintOK +FREERTOS.Tasks01=defaultTask,0,512,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL +File.Version=6 +GPIO.groupedBy=Group By Peripherals +KeepUserPlacement=false +Mcu.CPN=STM32F103C8T6 +Mcu.Family=STM32F1 +Mcu.IP0=DMA +Mcu.IP1=FREERTOS +Mcu.IP2=I2C1 +Mcu.IP3=I2C2 +Mcu.IP4=NVIC +Mcu.IP5=RCC +Mcu.IP6=SYS +Mcu.IP7=USART1 +Mcu.IP8=USART2 +Mcu.IPNb=9 +Mcu.Name=STM32F103C(8-B)Tx +Mcu.Package=LQFP48 +Mcu.Pin0=PC13-TAMPER-RTC +Mcu.Pin1=PC14-OSC32_IN +Mcu.Pin10=PB15 +Mcu.Pin11=PA9 +Mcu.Pin12=PA10 +Mcu.Pin13=PA13 +Mcu.Pin14=PA14 +Mcu.Pin15=PB6 +Mcu.Pin16=PB7 +Mcu.Pin17=VP_FREERTOS_VS_CMSIS_V1 +Mcu.Pin18=VP_SYS_VS_tim4 +Mcu.Pin2=PC15-OSC32_OUT +Mcu.Pin3=PD0-OSC_IN +Mcu.Pin4=PD1-OSC_OUT +Mcu.Pin5=PA2 +Mcu.Pin6=PA3 +Mcu.Pin7=PB10 +Mcu.Pin8=PB11 +Mcu.Pin9=PB14 +Mcu.PinsNb=19 +Mcu.ThirdParty0=RealThread.X-CUBE-RT-Thread_Nano.4.1.1 +Mcu.ThirdPartyNb=1 +Mcu.UserConstants= +Mcu.UserName=STM32F103C8Tx +MxCube.Version=6.16.1 +MxDb.Version=DB.6.0.161 +NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false +NVIC.DMA1_Channel4_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true +NVIC.DMA1_Channel5_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true +NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false +NVIC.ForceEnableDMAVector=true +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false +NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false +NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:false\:false +NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 +NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false\:false +NVIC.SavedPendsvIrqHandlerGenerated=true +NVIC.SavedSvcallIrqHandlerGenerated=true +NVIC.SavedSystickIrqHandlerGenerated=true +NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:true\:false +NVIC.TIM4_IRQn=true\:15\:0\:false\:false\:true\:false\:false\:true\:true +NVIC.TimeBase=TIM4_IRQn +NVIC.TimeBaseIP=TIM4 +NVIC.USART1_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true +NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false +PA10.Mode=Asynchronous +PA10.Signal=USART1_RX +PA13.Mode=Serial_Wire +PA13.Signal=SYS_JTMS-SWDIO +PA14.Mode=Serial_Wire +PA14.Signal=SYS_JTCK-SWCLK +PA2.Mode=Asynchronous +PA2.Signal=USART2_TX +PA3.Mode=Asynchronous +PA3.Signal=USART2_RX +PA9.Mode=Asynchronous +PA9.Signal=USART1_TX +PB10.Mode=I2C +PB10.Signal=I2C2_SCL +PB11.Mode=I2C +PB11.Signal=I2C2_SDA +PB14.GPIOParameters=PinState,GPIO_PuPd,GPIO_Label +PB14.GPIO_Label=FAN +PB14.GPIO_PuPd=GPIO_PULLUP +PB14.Locked=true +PB14.PinState=GPIO_PIN_SET +PB14.Signal=GPIO_Output +PB15.GPIOParameters=PinState,GPIO_PuPd,GPIO_Label +PB15.GPIO_Label=LIGHT +PB15.GPIO_PuPd=GPIO_PULLUP +PB15.Locked=true +PB15.PinState=GPIO_PIN_SET +PB15.Signal=GPIO_Output +PB6.Mode=I2C +PB6.Signal=I2C1_SCL +PB7.Mode=I2C +PB7.Signal=I2C1_SDA +PC13-TAMPER-RTC.GPIOParameters=GPIO_Label +PC13-TAMPER-RTC.GPIO_Label=LED +PC13-TAMPER-RTC.Locked=true +PC13-TAMPER-RTC.Signal=GPIO_Output +PC14-OSC32_IN.Mode=LSE-External-Oscillator +PC14-OSC32_IN.Signal=RCC_OSC32_IN +PC15-OSC32_OUT.Mode=LSE-External-Oscillator +PC15-OSC32_OUT.Signal=RCC_OSC32_OUT +PCC.Checker=false +PCC.Line=STM32F103 +PCC.MCU=STM32F103C(8-B)Tx +PCC.PartNumber=STM32F103C8Tx +PCC.Series=STM32F1 +PCC.Temperature=25 +PCC.Vdd=3.3 +PD0-OSC_IN.Mode=HSE-External-Oscillator +PD0-OSC_IN.Signal=RCC_OSC_IN +PD1-OSC_OUT.Mode=HSE-External-Oscillator +PD1-OSC_OUT.Signal=RCC_OSC_OUT +PinOutPanel.RotationAngle=0 +ProjectManager.AskForMigrate=true +ProjectManager.BackupPrevious=false +ProjectManager.CompilerLinker=GCC +ProjectManager.CompilerOptimize=6 +ProjectManager.ComputerToolchain=false +ProjectManager.CoupleFile=true +ProjectManager.CustomerFirmwarePackage= +ProjectManager.DefaultFWLocation=true +ProjectManager.DeletePrevious=true +ProjectManager.DeviceId=STM32F103C8Tx +ProjectManager.FirmwarePackage=STM32Cube FW_F1 V1.8.7 +ProjectManager.FreePins=false +ProjectManager.FreePinsContext= +ProjectManager.HalAssertFull=false +ProjectManager.HeapSize=0x200 +ProjectManager.KeepUserCode=true +ProjectManager.LastFirmware=true +ProjectManager.LibraryCopy=2 +ProjectManager.MainLocation=Core/Src +ProjectManager.NoMain=false +ProjectManager.PreviousToolchain= +ProjectManager.ProjectBuild=false +ProjectManager.ProjectFileName=3D.ioc +ProjectManager.ProjectName=3D +ProjectManager.ProjectStructure= +ProjectManager.RegisterCallBack= +ProjectManager.StackSize=0x400 +ProjectManager.TargetToolchain=CMake +ProjectManager.ToolChainLocation= +ProjectManager.UAScriptAfterPath= +ProjectManager.UAScriptBeforePath= +ProjectManager.UnderRoot=false +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_I2C1_Init-I2C1-false-HAL-true,5-MX_USART1_UART_Init-USART1-false-HAL-true,6-MX_USART2_UART_Init-USART2-false-HAL-true,7-MX_I2C2_Init-I2C2-false-HAL-true +RCC.ADCFreqValue=36000000 +RCC.AHBFreq_Value=72000000 +RCC.APB1CLKDivider=RCC_HCLK_DIV2 +RCC.APB1Freq_Value=36000000 +RCC.APB1TimFreq_Value=72000000 +RCC.APB2Freq_Value=72000000 +RCC.APB2TimFreq_Value=72000000 +RCC.FCLKCortexFreq_Value=72000000 +RCC.FamilyName=M +RCC.HCLKFreq_Value=72000000 +RCC.IPParameters=ADCFreqValue,AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,MCOFreq_Value,PLLCLKFreq_Value,PLLMCOFreq_Value,PLLMUL,PLLSourceVirtual,SYSCLKFreq_VALUE,SYSCLKSource,TimSysFreq_Value,USBFreq_Value,USBPrescaler,VCOOutput2Freq_Value +RCC.MCOFreq_Value=72000000 +RCC.PLLCLKFreq_Value=72000000 +RCC.PLLMCOFreq_Value=36000000 +RCC.PLLMUL=RCC_PLL_MUL9 +RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE +RCC.SYSCLKFreq_VALUE=72000000 +RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK +RCC.TimSysFreq_Value=72000000 +RCC.USBFreq_Value=48000000 +RCC.USBPrescaler=RCC_USBCLKSOURCE_PLL_DIV1_5 +RCC.VCOOutput2Freq_Value=8000000 +RealThread.X-CUBE-RT-Thread_Nano.4.1.1.RTOSJjRTAaThread_Checked=false +RealThread.X-CUBE-RT-Thread_Nano.4.1.1_SwParameter=RTAaThreadCcRTOSJjshell\:true;RTAaThreadCcRTOSJjlibcpu\:true;RTAaThreadCcRTOSJjdevice\:true;RTAaThreadCcRTOSJjkernel\:true; +USART1.IPParameters=VirtualMode +USART1.VirtualMode=VM_ASYNC +USART2.IPParameters=VirtualMode +USART2.VirtualMode=VM_ASYNC +VP_FREERTOS_VS_CMSIS_V1.Mode=CMSIS_V1 +VP_FREERTOS_VS_CMSIS_V1.Signal=FREERTOS_VS_CMSIS_V1 +VP_SYS_VS_tim4.Mode=TIM4 +VP_SYS_VS_tim4.Signal=SYS_VS_tim4 +board=custom +rtos.0.ip=FREERTOS diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3c0dc38 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,83 @@ +cmake_minimum_required(VERSION 3.22) + +# +# This file is generated only once, +# and is not re-generated if converter is called multiple times. +# +# User is free to modify the file as much as necessary +# + +# Setup compiler settings +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS ON) + + +# Define the build type +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Debug") +endif() + +# Set the project name +set(CMAKE_PROJECT_NAME 3D) + +# Enable compile command to ease indexing with e.g. clangd +set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) + +# Core project settings +project(${CMAKE_PROJECT_NAME}) +message("Build type: " ${CMAKE_BUILD_TYPE}) + +# Enable CMake support for ASM and C languages +enable_language(C ASM) + +# Create an executable object type +add_executable(${CMAKE_PROJECT_NAME}) + +# Add STM32CubeMX generated sources +add_subdirectory(cmake/stm32cubemx) + +# Link directories setup +target_link_directories(${CMAKE_PROJECT_NAME} PRIVATE + # Add user defined library search paths +) + +# Add sources to executable +target_sources(${CMAKE_PROJECT_NAME} PRIVATE + # Add user sources here + Core/Bsp/bsp_relay.c + Core/Bsp/bsp_uart.c + Core/Bsp/bsp_flash.c + Core/Bsp/bsp_cmd.c + Core/Bsp/bsp_bmp280.c + Core/Bsp/driver_bmp280.c + Core/Bsp/driver_bmp280_interface.c + Core/Bsp/cJSON.c +) + +# Add include paths +target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE + # Add user defined include paths + Core/Bsp + Core/Inc +) + +# Add project symbols (macros) +target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE + +) + +# Remove wrong libob.a library dependency when using cpp files +list(REMOVE_ITEM CMAKE_C_IMPLICIT_LINK_LIBRARIES ob) + +# Add linked libraries +target_link_libraries(${CMAKE_PROJECT_NAME} + stm32cubemx + +) + + +# Enable float support for printf +target_link_options(${CMAKE_PROJECT_NAME} PRIVATE + -u _printf_float +) \ No newline at end of file diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..9a0c120 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,38 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "default", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "toolchainFile": "${sourceDir}/cmake/gcc-arm-none-eabi.cmake", + "cacheVariables": { + } + }, + { + "name": "Debug", + "inherits": "default", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "Release", + "inherits": "default", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + } + ], + "buildPresets": [ + { + "name": "Debug", + "configurePreset": "Debug" + }, + { + "name": "Release", + "configurePreset": "Release" + } + ] +} \ No newline at end of file diff --git a/Core/Bsp/README.md b/Core/Bsp/README.md new file mode 100644 index 0000000..bda3e92 --- /dev/null +++ b/Core/Bsp/README.md @@ -0,0 +1,148 @@ +# BSP Drivers + +本目录包含外设驱动模块,包括继电器驱动、传感器驱动和UART通信。 + +--- + +## 1. 继电器驱动 (Relay) + +控制 LIGHT 和 FAN 两个继电器。 + +### 硬件连接 + +| 继电器 | GPIO端口 | 引脚 | +|--------|----------|------| +| LIGHT | GPIOB | PB15 | +| FAN | GPIOB | PB14 | + +> 注意:两个继电器均为**低电平有效**(低电平触发开启) + +### API 接口 + +| 函数 | 描述 | +|------|------| +| `BSP_Relay_Init()` | 初始化所有继电器,默认为关闭状态 | +| `BSP_LIGHT_On()` | 打开 LIGHT 继电器 | +| `BSP_LIGHT_Off()` | 关闭 LIGHT 继电器 | +| `BSP_LIGHT_Toggle()` | 切换 LIGHT 继电器状态 | +| `BSP_FAN_On()` | 打开 FAN 继电器 | +| `BSP_FAN_Off()` | 关闭 FAN 继电器 | +| `BSP_FAN_Toggle()` | 切换 FAN 继电器状态 | +| `BSP_FAN_SetMode()` | 设置风扇模式(自动/手动) | +| `BSP_FAN_SetThreshold()` | 设置自动模式温度阈值 | +| `BSP_FAN_AutoControl()` | 根据温度自动控制风扇 | + +--- + +## 2. BMP280 气压/温度传感器 + +使用 I2C1 接口 (PB6-SCL, PB7-SDA),I2C地址: 0x76 (SDO接地) + +### 配置说明 + +- I2C接口: I2C1 +- I2C地址: 0x76 +- 引脚: PB6 (SCL), PB7 (SDA) + +--- + +## 3. UART1 通信驱动 (MQTT透传) + +使用 DMA + IDLE空闲中断 实现高效接收,用于MQTT模块透明传输。 + +### 硬件连接 + +| 功能 | GPIO端口 | 引脚 | +|------|----------|------| +| TX | GPIOA | PA9 | +| RX | GPIOA | PA10 | + +### DMA配置 + +| DMA通道 | 方向 | 说明 | +|---------|------|------| +| DMA1_Channel4 | TX | USART1发送 | +| DMA1_Channel5 | RX | USART1接收 | + +### 工作原理 + +1. DMA持续接收数据到缓冲区 +2. 检测到IDLE空闲线(一帧结束)时触发中断 +3. 中断只保存数据长度并重启DMA +4. 主循环中调用 `BSP_UART1_Process()` 解析JSON命令并执行 +5. 执行结果以JSON格式通过UART1返回 + +### 文件结构 + +``` +Core/Bsp/ +├── bsp_uart.h / .c # UART1 DMA驱动 +├── bsp_cmd.h / .c # JSON命令解析与执行 +├── cJSON.h / .c # cJSON库(精简版) +├── bsp_relay.h / .c # 继电器驱动 +├── bsp_flash.h / .c # Flash存储驱动 +├── bsp_bmp280.h / .c # BMP280 BSP +├── driver_bmp280.h / .c # LibDriver BMP280 +└── driver_bmp280_interface.c / .h # HAL接口 +``` + +--- + +## 4. JSON 命令协议 + +通信采用 JSON 格式,所有命令通过 UART1 接收,响应也通过 UART1 返回。 + +### 请求格式 + +```json +{"cmd":"xxx","value":"xxx"} +``` + +### 支持的命令 + +| 命令 | 请求示例 | 说明 | +|------|---------|------| +| 查询状态 | `{"cmd":"status"}` | 返回所有状态信息 | +| 风扇模式 | `{"cmd":"fan_mode","value":"auto"}` | 设置风扇为自动/手动 | +| 风扇阈值 | `{"cmd":"fan_threshold","value":30.0}` | 设置温度阈值 | +| 风扇开关 | `{"cmd":"fan","value":"on"}` | 手动开/关风扇 | +| 灯光开关 | `{"cmd":"light","value":"on"}` | 开/关灯 | +| 恢复默认 | `{"cmd":"reset"}` | 恢复出厂设置 | + +### 响应格式 + +**简单响应:** +```json +{"status":"ok","msg":"fan mode set to auto"} +{"status":"error","msg":"unknown command"} +``` + +**状态查询响应:** +```json +{"status":"ok","data":{"fan_mode":"auto","fan_threshold":30.0,"fan":"off","light":"off"}} +``` + +--- + +## 5. Flash存储 (bsp_flash) + +将设置参数存储到内部Flash,实现断电保存。 + +- 存储地址: `0x0801F800` (最后一页) + +--- + +## 初始化 + +驱动在 `MX_FREERTOS_Init()` 和任务启动时初始化: + +```c +// MX_FREERTOS_Init() 中 +BSP_Relay_Init(); // 继电器初始化 +BSP_BMP280_Init(); // BMP280初始化 + +// StartDefaultTask() 中 +BSP_UART1_Init(); // UART1 DMA初始化 +``` + +任务循环中调用 `BSP_UART1_Process()` 处理命令。 diff --git a/Core/Bsp/bsp_bmp280.c b/Core/Bsp/bsp_bmp280.c new file mode 100644 index 0000000..be39770 --- /dev/null +++ b/Core/Bsp/bsp_bmp280.c @@ -0,0 +1,96 @@ +/** + * @file bsp_bmp280.c + * @brief BMP280 sensor driver implementation (BSP layer) + */ + +#include "bsp_bmp280.h" +#include "driver_bmp280_interface.h" + +/* Private variables ----------------------------------------------------------*/ +static bmp280_handle_t gs_bmp280_handle; +static uint8_t gs_bmp280_inited = 0; + +/** + * @brief Initialize BMP280 sensor + * @retval 0: success + * other: error code + */ +uint8_t BSP_BMP280_Init(void) +{ + uint8_t res; + + /* Initialize handle */ + DRIVER_BMP280_LINK_INIT(&gs_bmp280_handle, bmp280_handle_t); + + /* Link interface functions */ + DRIVER_BMP280_LINK_IIC_INIT(&gs_bmp280_handle, bmp280_interface_iic_init); + DRIVER_BMP280_LINK_IIC_DEINIT(&gs_bmp280_handle, bmp280_interface_iic_deinit); + DRIVER_BMP280_LINK_IIC_READ(&gs_bmp280_handle, bmp280_interface_iic_read); + DRIVER_BMP280_LINK_IIC_WRITE(&gs_bmp280_handle, bmp280_interface_iic_write); + DRIVER_BMP280_LINK_SPI_INIT(&gs_bmp280_handle, bmp280_interface_spi_init); + DRIVER_BMP280_LINK_SPI_DEINIT(&gs_bmp280_handle, bmp280_interface_spi_deinit); + DRIVER_BMP280_LINK_SPI_READ(&gs_bmp280_handle, bmp280_interface_spi_read); + DRIVER_BMP280_LINK_SPI_WRITE(&gs_bmp280_handle, bmp280_interface_spi_write); + DRIVER_BMP280_LINK_DELAY_MS(&gs_bmp280_handle, bmp280_interface_delay_ms); + DRIVER_BMP280_LINK_DEBUG_PRINT(&gs_bmp280_handle, bmp280_interface_debug_print); + + /* Set I2C interface */ + bmp280_set_interface(&gs_bmp280_handle, BMP280_INTERFACE_IIC); + + /* Set I2C address (SDO pin grounded: 0x76) */ + bmp280_set_addr_pin(&gs_bmp280_handle, BMP280_ADDRESS_ADO_LOW); + + /* Initialize BMP280 */ + res = bmp280_init(&gs_bmp280_handle); + if (res != 0) + { + gs_bmp280_inited = 0; + return res; + } + + /* Configure sensor */ + bmp280_set_temperatue_oversampling(&gs_bmp280_handle, BMP280_OVERSAMPLING_x2); + bmp280_set_pressure_oversampling(&gs_bmp280_handle, BMP280_OVERSAMPLING_x2); + bmp280_set_filter(&gs_bmp280_handle, BMP280_FILTER_COEFF_16); + bmp280_set_standby_time(&gs_bmp280_handle, BMP280_STANDBY_TIME_500_MS); + bmp280_set_mode(&gs_bmp280_handle, BMP280_MODE_NORMAL); + + gs_bmp280_inited = 1; + + return 0; +} + +/** + * @brief Read temperature and pressure data + * @param data: pointer to store sensor data + * @retval 0: success + * other: error code + */ +uint8_t BSP_BMP280_Read(bsp_bmp280_data_t *data) +{ + uint8_t res; + uint32_t temp_raw; + uint32_t press_raw; + + if (gs_bmp280_inited == 0) + { + return 1; + } + + if (data == NULL) + { + return 2; + } + + res = bmp280_read_temperature_pressure(&gs_bmp280_handle, + &temp_raw, &data->temperature, + &press_raw, &data->pressure); + if (res != 0) + { + data->is_ready = 0; + return res; + } + + data->is_ready = 1; + return 0; +} diff --git a/Core/Bsp/bsp_bmp280.h b/Core/Bsp/bsp_bmp280.h new file mode 100644 index 0000000..bd7f096 --- /dev/null +++ b/Core/Bsp/bsp_bmp280.h @@ -0,0 +1,32 @@ +/** + * @file bsp_bmp280.h + * @brief BMP280 sensor driver (BSP layer) + * @details I2C1 interface, wrapper for LibDriver BMP280 + */ + +#ifndef __BSP_BMP280_H +#define __BSP_BMP280_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "driver_bmp280.h" + +/* Exported types ------------------------------------------------------------*/ +typedef struct { + float temperature; /* Temperature in Celsius */ + float pressure; /* Pressure in Pa */ + uint8_t is_ready; /* Sensor ready flag */ +} bsp_bmp280_data_t; + +/* Exported functions prototypes --------------------------------------------*/ +uint8_t BSP_BMP280_Init(void); +uint8_t BSP_BMP280_Read(bsp_bmp280_data_t *data); + +#ifdef __cplusplus +} +#endif + +#endif /* __BSP_BMP280_H */ diff --git a/Core/Bsp/bsp_cmd.c b/Core/Bsp/bsp_cmd.c new file mode 100644 index 0000000..03841b8 --- /dev/null +++ b/Core/Bsp/bsp_cmd.c @@ -0,0 +1,255 @@ +/** + * @file bsp_cmd.c + * @brief JSON command parser - receives JSON, executes command, returns JSON via UART1 + */ + +#include "bsp_cmd.h" +#include "bsp_relay.h" +#include "bsp_uart.h" +#include "bsp_flash.h" +#include "cJSON.h" +#include +#include + +/** + * @brief Send JSON response via UART1 + */ +static void send_response(cJSON *root) +{ + char *json_str = cJSON_PrintUnformatted(root); + if (json_str != NULL) + { + BSP_UART1_SendString(json_str); + BSP_UART1_SendString("\r\n"); + cJSON_free(json_str); + } + cJSON_Delete(root); +} + +/** + * @brief Make a simple {"status":"ok","msg":"xxx"} response + */ +static void respond_ok(const char *msg) +{ + cJSON *root = cJSON_CreateObject(); + cJSON_AddStringToObject(root, "status", "ok"); + cJSON_AddStringToObject(root, "msg", msg); + send_response(root); +} + +/** + * @brief Make a {"status":"error","msg":"xxx"} response + */ +static void respond_error(const char *msg) +{ + cJSON *root = cJSON_CreateObject(); + cJSON_AddStringToObject(root, "status", "error"); + cJSON_AddStringToObject(root, "msg", msg); + send_response(root); +} + +/** + * @brief Process JSON command + * + * Supported commands: + * {"cmd":"status"} + * {"cmd":"fan_mode","value":"auto"} or "manual" + * {"cmd":"fan_threshold","value":30.0} + * {"cmd":"fan","value":"on"} or "off" + * {"cmd":"light","value":"on"} or "off" + * {"cmd":"reset"} + */ +void BSP_Cmd_ProcessJSON(const uint8_t *buf, uint16_t len) +{ + cJSON *root = NULL; + cJSON *cmd_item = NULL; + cJSON *val_item = NULL; + + if (buf == NULL || len == 0) + { + respond_error("empty input"); + return; + } + + /* Ensure null termination and strip non-JSON prefix/suffix */ + char tmp[256]; + if (len >= sizeof(tmp)) + len = sizeof(tmp) - 1; + memcpy(tmp, buf, len); + tmp[len] = '\0'; + + /* Find the first '{' to skip any MQTT topic prefix */ + char *json_start = strchr(tmp, '{'); + if (json_start == NULL) + { + respond_error("no json found"); + return; + } + + /* Find matching '}' to trim trailing garbage */ + char *json_end = json_start; + int depth = 0; + while (*json_end != '\0') + { + if (*json_end == '{') depth++; + else if (*json_end == '}') depth--; + if (depth == 0) { json_end++; break; } + json_end++; + } + *json_end = '\0'; + + /* Parse JSON */ + root = cJSON_Parse(json_start); + if (root == NULL) + { + respond_error("invalid json"); + return; + } + + /* Get "cmd" field */ + cmd_item = cJSON_GetObjectItemCaseSensitive(root, "cmd"); + if (cmd_item == NULL || !cJSON_IsString(cmd_item)) + { + respond_error("missing cmd field"); + cJSON_Delete(root); + return; + } + + const char *cmd = cmd_item->valuestring; + + /* Get "value" field (optional) */ + val_item = cJSON_GetObjectItemCaseSensitive(root, "value"); + + /* --- STATUS --- */ + if (strcasecmp(cmd, "status") == 0) + { + system_state_t state; + BSP_System_GetState(&state); + + cJSON *resp = cJSON_CreateObject(); + cJSON_AddStringToObject(resp, "status", "ok"); + + cJSON *data = cJSON_CreateObject(); + cJSON_AddStringToObject(data, "fan_mode", state.fan_mode == FAN_MODE_AUTO ? "auto" : "manual"); + cJSON_AddNumberToObject(data, "fan_threshold", state.fan_threshold); + cJSON_AddStringToObject(data, "fan", state.fan_state ? "on" : "off"); + cJSON_AddStringToObject(data, "light", state.light_state ? "on" : "off"); + cJSON_AddItemToObject(resp, "data", data); + + send_response(resp); + } + /* --- FAN MODE --- */ + else if (strcasecmp(cmd, "fan_mode") == 0) + { + if (val_item == NULL || !cJSON_IsString(val_item)) + { + respond_error("missing value"); + } + else + { + const char *val = val_item->valuestring; + if (strcasecmp(val, "auto") == 0) + { + BSP_FAN_SetMode(FAN_MODE_AUTO); + respond_ok("fan mode set to auto"); + } + else if (strcasecmp(val, "manual") == 0) + { + BSP_FAN_SetMode(FAN_MODE_MANUAL); + respond_ok("fan mode set to manual"); + } + else + { + respond_error("invalid fan_mode value"); + } + } + } + /* --- FAN THRESHOLD --- */ + else if (strcasecmp(cmd, "fan_threshold") == 0) + { + if (val_item == NULL || !cJSON_IsNumber(val_item)) + { + respond_error("missing or invalid value"); + } + else + { + float thresh = (float)val_item->valuedouble; + if (thresh > 0 && thresh < 100) + { + BSP_FAN_SetThreshold(thresh); + respond_ok("fan threshold updated"); + } + else + { + respond_error("threshold out of range"); + } + } + } + /* --- FAN ON/OFF --- */ + else if (strcasecmp(cmd, "fan") == 0) + { + if (val_item == NULL || !cJSON_IsString(val_item)) + { + respond_error("missing value"); + } + else + { + const char *val = val_item->valuestring; + if (strcasecmp(val, "on") == 0) + { + BSP_FAN_SetMode(FAN_MODE_MANUAL); + BSP_FAN_On(); + respond_ok("fan on"); + } + else if (strcasecmp(val, "off") == 0) + { + BSP_FAN_SetMode(FAN_MODE_MANUAL); + BSP_FAN_Off(); + respond_ok("fan off"); + } + else + { + respond_error("invalid fan value"); + } + } + } + /* --- LIGHT ON/OFF --- */ + else if (strcasecmp(cmd, "light") == 0) + { + if (val_item == NULL || !cJSON_IsString(val_item)) + { + respond_error("missing value"); + } + else + { + const char *val = val_item->valuestring; + if (strcasecmp(val, "on") == 0) + { + BSP_LIGHT_On(); + respond_ok("light on"); + } + else if (strcasecmp(val, "off") == 0) + { + BSP_LIGHT_Off(); + respond_ok("light off"); + } + else + { + respond_error("invalid light value"); + } + } + } + /* --- RESET --- */ + else if (strcasecmp(cmd, "reset") == 0) + { + BSP_Flash_ResetSettings(); + respond_ok("settings reset to default"); + } + /* --- UNKNOWN --- */ + else + { + respond_error("unknown command"); + } + + cJSON_Delete(root); +} diff --git a/Core/Bsp/bsp_cmd.h b/Core/Bsp/bsp_cmd.h new file mode 100644 index 0000000..299d74d --- /dev/null +++ b/Core/Bsp/bsp_cmd.h @@ -0,0 +1,21 @@ +/** + * @file bsp_cmd.h + * @brief JSON command parser for UART1 (MQTT) + */ + +#ifndef __BSP_CMD_H +#define __BSP_CMD_H + +#include + +/** + * @brief Parse and execute a JSON command from UART1 + * Request format: {"cmd":"xxx","value":"xxx"} + * Response format: {"status":"ok/error","msg":"xxx","data":{...}} + * + * @param buf: received JSON string (null-terminated) + * @param len: string length + */ +void BSP_Cmd_ProcessJSON(const uint8_t *buf, uint16_t len); + +#endif diff --git a/Core/Bsp/bsp_flash.c b/Core/Bsp/bsp_flash.c new file mode 100644 index 0000000..6f9cb9f --- /dev/null +++ b/Core/Bsp/bsp_flash.c @@ -0,0 +1,114 @@ +/** + * @file bsp_flash.c + * @brief Flash storage driver implementation + */ + +#include "bsp_flash.h" +#include "main.h" + +/* Default settings */ +static const system_settings_t default_settings = { + .fan_threshold = 30.0f, + .fan_mode = 1, // AUTO + .light_state = 0, // OFF + .valid = SETTINGS_VALID_FLAG +}; + +/** + * @brief Get Flash page address + */ +static uint32_t get_page_address(uint32_t addr) +{ + return addr & 0xFFFFF800; // 2KB page alignment +} + +/** + * @brief Erase Flash page + */ +static HAL_StatusTypeDef erase_page(uint32_t page_address) +{ + FLASH_EraseInitTypeDef erase_init; + uint32_t page_error = 0; + + HAL_FLASH_Unlock(); + + erase_init.TypeErase = FLASH_TYPEERASE_PAGES; + erase_init.PageAddress = page_address; + erase_init.NbPages = 1; + + HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&erase_init, &page_error); + + HAL_FLASH_Lock(); + + return status; +} + +/** + * @brief Load settings from Flash + */ +bool BSP_Flash_LoadSettings(system_settings_t *settings) +{ + if (settings == NULL) return false; + + /* Read from Flash */ + system_settings_t *flash_data = (system_settings_t *)SETTINGS_ADDR; + + /* Check valid flag */ + if (flash_data->valid == SETTINGS_VALID_FLAG) + { + settings->fan_threshold = flash_data->fan_threshold; + settings->fan_mode = flash_data->fan_mode; + settings->light_state = flash_data->light_state; + settings->valid = flash_data->valid; + return true; + } + + /* No valid settings, use defaults */ + *settings = default_settings; + return false; +} + +/** + * @brief Save settings to Flash + */ +bool BSP_Flash_SaveSettings(const system_settings_t *settings) +{ + if (settings == NULL) return false; + + uint32_t page_addr = get_page_address(SETTINGS_ADDR); + + /* Erase page first */ + if (erase_page(page_addr) != HAL_OK) + { + return false; + } + + HAL_FLASH_Unlock(); + + /* Write data halfword by halfword */ + uint16_t *src = (uint16_t *)settings; + uint32_t dst = SETTINGS_ADDR; + + for (uint32_t i = 0; i < sizeof(system_settings_t) / 2; i++) + { + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, dst, *src) != HAL_OK) + { + HAL_FLASH_Lock(); + return false; + } + dst += 2; + src++; + } + + HAL_FLASH_Lock(); + + return true; +} + +/** + * @brief Reset settings to default + */ +void BSP_Flash_ResetSettings(void) +{ + BSP_Flash_SaveSettings(&default_settings); +} diff --git a/Core/Bsp/bsp_flash.h b/Core/Bsp/bsp_flash.h new file mode 100644 index 0000000..6dc80a2 --- /dev/null +++ b/Core/Bsp/bsp_flash.h @@ -0,0 +1,42 @@ +/** + * @file bsp_flash.h + * @brief Flash storage driver for saving settings + */ + +#ifndef __BSP_FLASH_H +#define __BSP_FLASH_H + +#include +#include + +/* Settings structure - stored in Flash */ +typedef struct { + float fan_threshold; // Temperature threshold + uint8_t fan_mode; // Fan mode: 0=manual, 1=auto + uint8_t light_state; // Light state: 0=off, 1=on + uint8_t valid; // Valid flag (0xAA = valid) +} system_settings_t; + +#define SETTINGS_VALID_FLAG 0xAA +#define SETTINGS_ADDR 0x0801F800 // Last page of 64KB Flash + +/* Exported functions ---------------------------------------------------------*/ + +/** + * @brief Load settings from Flash + * @return true if valid settings found + */ +bool BSP_Flash_LoadSettings(system_settings_t *settings); + +/** + * @brief Save settings to Flash + * @return true if success + */ +bool BSP_Flash_SaveSettings(const system_settings_t *settings); + +/** + * @brief Reset settings to default + */ +void BSP_Flash_ResetSettings(void); + +#endif diff --git a/Core/Bsp/bsp_relay.c b/Core/Bsp/bsp_relay.c new file mode 100644 index 0000000..9703253 --- /dev/null +++ b/Core/Bsp/bsp_relay.c @@ -0,0 +1,177 @@ +/** + * @file bsp_relay.c + * @brief Relay control driver implementation + */ + +#include "bsp_relay.h" +#include "bsp_flash.h" +#include + +/* Private variables ----------------------------------------------------------*/ +static fan_mode_t s_fan_mode = FAN_MODE_MANUAL; +static float s_fan_threshold = 30.0f; // Default threshold: 30°C + +/** + * @brief Initialize all relay pins + * @retval None + */ +void BSP_Relay_Init(void) +{ + /* Set all relays to OFF state (high level) by default */ + HAL_GPIO_WritePin(LIGHT_GPIO_Port, LIGHT_Pin, RELAY_OFF); + HAL_GPIO_WritePin(FAN_GPIO_Port, FAN_Pin, RELAY_OFF); + + /* Load settings from Flash */ + system_settings_t settings; + if (BSP_Flash_LoadSettings(&settings)) + { + s_fan_mode = (fan_mode_t)settings.fan_mode; + s_fan_threshold = settings.fan_threshold; + } + else + { + /* Use default values if no valid settings */ + s_fan_mode = FAN_MODE_AUTO; + s_fan_threshold = 30.0f; + } +} + +/** + * @brief Turn LIGHT relay ON (low level output) + * @retval None + */ +void BSP_LIGHT_On(void) +{ + HAL_GPIO_WritePin(LIGHT_GPIO_Port, LIGHT_Pin, RELAY_ON); +} + +/** + * @brief Turn LIGHT relay OFF (high level output) + * @retval None + */ +void BSP_LIGHT_Off(void) +{ + HAL_GPIO_WritePin(LIGHT_GPIO_Port, LIGHT_Pin, RELAY_OFF); +} + +/** + * @brief Toggle LIGHT relay state + * @retval None + */ +void BSP_LIGHT_Toggle(void) +{ + HAL_GPIO_TogglePin(LIGHT_GPIO_Port, LIGHT_Pin); +} + +uint8_t BSP_LIGHT_GetState(void) +{ + return (HAL_GPIO_ReadPin(LIGHT_GPIO_Port, LIGHT_Pin) == RELAY_ON) ? 1 : 0; +} + +/** + * @brief Turn FAN relay ON (low level output) + * @retval None + */ +void BSP_FAN_On(void) +{ + HAL_GPIO_WritePin(FAN_GPIO_Port, FAN_Pin, RELAY_ON); +} + +/** + * @brief Turn FAN relay OFF (high level output) + * @retval None + */ +void BSP_FAN_Off(void) +{ + HAL_GPIO_WritePin(FAN_GPIO_Port, FAN_Pin, RELAY_OFF); +} + +/** + * @brief Toggle FAN relay state + * @retval None + */ +void BSP_FAN_Toggle(void) +{ + HAL_GPIO_TogglePin(FAN_GPIO_Port, FAN_Pin); +} + +uint8_t BSP_FAN_GetState(void) +{ + return (HAL_GPIO_ReadPin(FAN_GPIO_Port, FAN_Pin) == RELAY_ON) ? 1 : 0; +} + +/** + * @brief Set FAN mode and save to Flash + */ +void BSP_FAN_SetMode(fan_mode_t mode) +{ + s_fan_mode = mode; + + /* Save to Flash */ + system_settings_t settings = { + .fan_threshold = s_fan_threshold, + .fan_mode = mode, + .light_state = BSP_LIGHT_GetState(), + .valid = SETTINGS_VALID_FLAG + }; + BSP_Flash_SaveSettings(&settings); +} + +fan_mode_t BSP_FAN_GetMode(void) +{ + return s_fan_mode; +} + +/** + * @brief Set temperature threshold for auto mode and save to Flash + */ +void BSP_FAN_SetThreshold(float threshold) +{ + s_fan_threshold = threshold; + + /* Save to Flash */ + system_settings_t settings = { + .fan_threshold = threshold, + .fan_mode = s_fan_mode, + .light_state = BSP_LIGHT_GetState(), + .valid = SETTINGS_VALID_FLAG + }; + BSP_Flash_SaveSettings(&settings); +} + +float BSP_FAN_GetThreshold(void) +{ + return s_fan_threshold; +} + +/** + * @brief Auto control FAN based on temperature + * @param current_temp: current temperature in Celsius + */ +void BSP_FAN_AutoControl(float current_temp) +{ + if (s_fan_mode != FAN_MODE_AUTO) + return; + + if (current_temp >= s_fan_threshold) + { + BSP_FAN_On(); + } + else + { + BSP_FAN_Off(); + } +} + +/** + * @brief Get system state + */ +void BSP_System_GetState(system_state_t *state) +{ + if (state == NULL) return; + + state->fan_mode = s_fan_mode; + state->fan_threshold = s_fan_threshold; + state->light_state = BSP_LIGHT_GetState(); + state->fan_state = BSP_FAN_GetState(); +} diff --git a/Core/Bsp/bsp_relay.h b/Core/Bsp/bsp_relay.h new file mode 100644 index 0000000..8988003 --- /dev/null +++ b/Core/Bsp/bsp_relay.h @@ -0,0 +1,60 @@ +/** + * @file bsp_relay.h + * @brief Relay control driver (LIGHT & FAN) + * @details Low level effective (low level = ON) + */ + +#ifndef __BSP_RELAY_H +#define __BSP_RELAY_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* Exported defines ----------------------------------------------------------*/ +#define RELAY_ON GPIO_PIN_RESET // Low level activates relay +#define RELAY_OFF GPIO_PIN_SET // High level deactivates relay + +/* Exported types ------------------------------------------------------------*/ +typedef enum { + FAN_MODE_MANUAL = 0, // Manual control + FAN_MODE_AUTO = 1 // Auto control by temperature +} fan_mode_t; + +typedef struct { + fan_mode_t fan_mode; // FAN mode: manual or auto + float fan_threshold; // Temperature threshold for auto mode (Celsius) + uint8_t light_state; // LIGHT state: 0=off, 1=on + uint8_t fan_state; // FAN state: 0=off, 1=on +} system_state_t; + +/* Exported functions prototypes --------------------------------------------*/ +void BSP_Relay_Init(void); +void BSP_LIGHT_On(void); +void BSP_LIGHT_Off(void); +void BSP_LIGHT_Toggle(void); +uint8_t BSP_LIGHT_GetState(void); + +void BSP_FAN_On(void); +void BSP_FAN_Off(void); +void BSP_FAN_Toggle(void); +uint8_t BSP_FAN_GetState(void); + +/* Auto control functions (for temperature-based fan control) -------------*/ +void BSP_FAN_SetMode(fan_mode_t mode); +fan_mode_t BSP_FAN_GetMode(void); +void BSP_FAN_SetThreshold(float threshold); +float BSP_FAN_GetThreshold(void); +void BSP_FAN_AutoControl(float current_temp); + +/* System state --------------------------------------------------------------*/ +void BSP_System_GetState(system_state_t *state); + +#ifdef __cplusplus +} +#endif + +#endif /* __BSP_RELAY_H */ diff --git a/Core/Bsp/bsp_uart.c b/Core/Bsp/bsp_uart.c new file mode 100644 index 0000000..37caf88 --- /dev/null +++ b/Core/Bsp/bsp_uart.c @@ -0,0 +1,131 @@ +/** + * @file bsp_uart.c + * @brief UART1 DMA + IDLE interrupt driver + */ + +#include "bsp_uart.h" +#include "bsp_cmd.h" +#include "usart.h" +#include + +/* External DMA handle */ +extern DMA_HandleTypeDef hdma_usart1_rx; + +/* DMA receive buffer */ +uint8_t uart1_rx_buf[UART1_RX_BUF_SIZE]; + +/* IDLE interrupt sets this flag, main loop checks and processes */ +static volatile uint16_t idle_rx_len = 0; + +/** + * @brief Init UART1 for MQTT module with DMA + */ +void BSP_UART1_Init(void) +{ + /* Start DMA reception */ + HAL_UART_Receive_DMA(&huart1, uart1_rx_buf, UART1_RX_BUF_SIZE); + + /* Enable IDLE line detection interrupt */ + __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); +} + +/** + * @brief Send data via UART1 (blocking) + */ +uint16_t BSP_UART1_Send(uint8_t *data, uint16_t len) +{ + return HAL_UART_Transmit(&huart1, data, len, 1000); +} + +/** + * @brief Send string via UART1 + */ +uint16_t BSP_UART1_SendString(const char *str) +{ + return BSP_UART1_Send((uint8_t*)str, strlen(str)); +} + +/** + * @brief Get received data length in DMA buffer + */ +uint16_t BSP_UART1_GetRxLen(void) +{ + return UART1_RX_BUF_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); +} + +/** + * @brief Read data from DMA rx buffer (non-destructive copy) + */ +uint16_t BSP_UART1_Read(uint8_t *buf, uint16_t len) +{ + uint16_t head = UART1_RX_BUF_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); + + uint16_t cnt = 0; + while (cnt < len && cnt < head) + { + buf[cnt] = uart1_rx_buf[cnt]; + cnt++; + } + + return cnt; +} + +/** + * @brief Clear rx buffer (restart DMA) + */ +void BSP_UART1_ClearRxBuf(void) +{ + HAL_UART_AbortReceive(&huart1); + HAL_UART_Receive_DMA(&huart1, uart1_rx_buf, UART1_RX_BUF_SIZE); +} + +/** + * @brief Check if data received + */ +bool BSP_UART1_IsDataReceived(void) +{ + return (idle_rx_len > 0); +} + +/** + * @brief Process received data (call in main loop) + * Copies data, parses JSON command, sends JSON response via UART1 + */ +void BSP_UART1_Process(void) +{ + if (idle_rx_len == 0) + return; + + /* Copy length and clear flag */ + uint16_t rx_len = idle_rx_len; + idle_rx_len = 0; + + /* Copy data to local buffer so DMA restart won't overwrite */ + uint8_t local_buf[UART1_RX_BUF_SIZE]; + if (rx_len > sizeof(local_buf)) + rx_len = sizeof(local_buf); + memcpy(local_buf, uart1_rx_buf, rx_len); + + /* Process JSON command */ + BSP_Cmd_ProcessJSON(local_buf, rx_len); + + /* Restart DMA for next frame */ + BSP_UART1_ClearRxBuf(); +} + +/** + * @brief Called from USART1 IDLE interrupt - saves length and restarts DMA + */ +void BSP_UART1_IDLE_IRQHandler(void) +{ + uint16_t rx_len = UART1_RX_BUF_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); + + if (rx_len > 0) + { + idle_rx_len = rx_len; + } + + /* Restart DMA immediately */ + HAL_UART_AbortReceive(&huart1); + HAL_UART_Receive_DMA(&huart1, uart1_rx_buf, UART1_RX_BUF_SIZE); +} diff --git a/Core/Bsp/bsp_uart.h b/Core/Bsp/bsp_uart.h new file mode 100644 index 0000000..8f8a620 --- /dev/null +++ b/Core/Bsp/bsp_uart.h @@ -0,0 +1,59 @@ +/** + * @file bsp_uart.h + * @brief UART1 communication driver (DMA + IDLE interrupt for MQTT) + */ + +#ifndef __BSP_UART_H +#define __BSP_UART_H + +#include "main.h" +#include +#include + +#define UART1_RX_BUF_SIZE 256 + +/* Exported functions prototypes */ + +void BSP_UART1_Init(void); + +/** + * @brief Send data via UART1 (blocking) + */ +uint16_t BSP_UART1_Send(uint8_t *data, uint16_t len); + +/** + * @brief Send string via UART1 (blocking) + */ +uint16_t BSP_UART1_SendString(const char *str); + +/** + * @brief Get received data length + */ +uint16_t BSP_UART1_GetRxLen(void); + +/** + * @brief Read data from rx buffer + */ +uint16_t BSP_UART1_Read(uint8_t *buf, uint16_t len); + +/** + * @brief Clear rx buffer (restart DMA) + */ +void BSP_UART1_ClearRxBuf(void); + +/** + * @brief Check if data received + */ +bool BSP_UART1_IsDataReceived(void); + +/** + * @brief Process received data (call in main loop) + */ +void BSP_UART1_Process(void); + +/** + * @brief IDLE interrupt handler (call from ISR) + */ +void BSP_UART1_IDLE_IRQHandler(void); + +#endif diff --git a/Core/Bsp/cJSON.c b/Core/Bsp/cJSON.c new file mode 100644 index 0000000..7158511 --- /dev/null +++ b/Core/Bsp/cJSON.c @@ -0,0 +1,540 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + */ + +#include +#include +#include +#include +#include +#include +#include +#include "cJSON.h" + +/* define our own boolean type */ +#ifdef true +#undef true +#endif +#define true ((cJSON_bool)1) + +#ifdef false +#undef false +#endif +#define false ((cJSON_bool)0) + +typedef struct { + const unsigned char *content; + size_t length; + size_t offset; + size_t depth; +} parse_buffer; + +/* case insensitive strcmp */ +CJSON_PUBLIC(int) cJSON_Strcasecmp(const char *a, const char *b) +{ + if (!a && !b) return 0; + if (!a || !b) return 1; + for (; tolower(*a) == tolower(*b); a++, b++) + { + if (*a == '\0') return 0; + } + return tolower(*a) - tolower(*b); +} + +static cJSON_bool parse_number(cJSON *item, parse_buffer *input) +{ + double number = 0; + unsigned char *after_end = NULL; + unsigned char number_c_string[64]; + size_t i = 0; + + if (input->length == 0) return false; + if (input->length > (sizeof(number_c_string) - 1)) return false; + + for (i = 0; (i < input->length) && (input->content[input->offset + i] != '\0'); i++) + { + number_c_string[i] = input->content[input->offset + i]; + } + number_c_string[i] = '\0'; + + number = strtod((char *)number_c_string, (char **)&after_end); + if (number_c_string == after_end) return false; + + item->valuedouble = number; + item->valueint = (int)number; + item->type = cJSON_Number; + + input->offset += (size_t)(after_end - number_c_string); + return true; +} + +static cJSON_bool parse_string(cJSON *item, parse_buffer *input) +{ + const unsigned char *input_pointer = input->content + input->offset; + size_t i = 0; + + if (input->length < 2) return false; + if (input_pointer[0] != '\"') return false; + + input_pointer++; + while ((i < input->length) && (input_pointer[0] != '\0')) + { + if (input_pointer[0] == '\"') + { + char *output = (char *)malloc(i + 1); + if (!output) return false; + memcpy(output, input_pointer - i, i); + output[i] = '\0'; + + item->valuestring = output; + item->type = cJSON_String; + input->offset += i + 2; + return true; + } + i++; + input_pointer++; + } + return false; +} + +static parse_buffer *skip_whitespace(parse_buffer *buffer) +{ + if (buffer == NULL || buffer->content == NULL) return NULL; + while ((buffer->offset < buffer->length) && isspace(buffer->content[buffer->offset])) + { + buffer->offset++; + } + return buffer; +} + +static cJSON_bool parse_value(cJSON *item, parse_buffer *input); + +static cJSON_bool parse_array(cJSON *item, parse_buffer *input) +{ + cJSON *child = NULL; + if (input->content[input->offset] != '[') return false; + input->offset++; + skip_whitespace(input); + if (input->content[input->offset] == ']') + { + item->type = cJSON_Array; + input->offset++; + return true; + } + input->offset--; + child = cJSON_CreateNull(); + if (child == NULL) return false; + input->offset++; + if (!parse_value(child, skip_whitespace(input))) { cJSON_Delete(child); return false; } + item->child = child; + skip_whitespace(input); + while (input->content[input->offset] == ',') + { + cJSON *new_item = cJSON_CreateNull(); + if (new_item == NULL) { cJSON_Delete(child); return false; } + input->offset++; + if (!parse_value(new_item, skip_whitespace(input))) { cJSON_Delete(new_item); cJSON_Delete(child); return false; } + child->next = new_item; + new_item->prev = child; + child = new_item; + skip_whitespace(input); + } + if (input->content[input->offset] != ']') { cJSON_Delete(child); return false; } + input->offset++; + item->type = cJSON_Array; + return true; +} + +static cJSON_bool parse_object(cJSON *item, parse_buffer *input) +{ + cJSON *child = NULL; + if (input->content[input->offset] != '{') return false; + input->offset++; + skip_whitespace(input); + if (input->content[input->offset] == '}') + { + item->type = cJSON_Object; + input->offset++; + return true; + } + child = cJSON_CreateNull(); + if (child == NULL) return false; + + /* Parse key */ + if (!parse_string(child, input)) { cJSON_Delete(child); return false; } + char *key = child->valuestring; + child->valuestring = NULL; /* clear before parse_value overwrites it */ + + /* Parse value */ + skip_whitespace(input); + if (input->content[input->offset] != ':') { cJSON_Delete(child); return false; } + input->offset++; + if (!parse_value(child, skip_whitespace(input))) { cJSON_Delete(child); return false; } + + item->child = child; + child->string = key; + skip_whitespace(input); + while (input->content[input->offset] == ',') + { + cJSON *new_item = cJSON_CreateNull(); + if (new_item == NULL) { cJSON_Delete(child); return false; } + input->offset++; + + /* Parse key */ + if (!parse_string(new_item, input)) { cJSON_Delete(new_item); cJSON_Delete(child); return false; } + char *new_key = new_item->valuestring; + new_item->valuestring = NULL; + + /* Parse value */ + skip_whitespace(input); + if (input->content[input->offset] != ':') { cJSON_Delete(new_item); cJSON_Delete(child); return false; } + input->offset++; + if (!parse_value(new_item, skip_whitespace(input))) { cJSON_Delete(new_item); cJSON_Delete(child); return false; } + + new_item->string = new_key; + child->next = new_item; + new_item->prev = child; + child = new_item; + skip_whitespace(input); + } + if (input->content[input->offset] != '}') { cJSON_Delete(child); return false; } + input->offset++; + item->type = cJSON_Object; + return true; +} + +static cJSON_bool parse_value(cJSON *item, parse_buffer *input) +{ + if (input == NULL || item == NULL) return false; + skip_whitespace(input); + if (input->length == 0) return false; + + switch (input->content[input->offset]) + { + case '-': case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return parse_number(item, input); + case 't': case 'f': + if (strncmp((const char *)input->content + input->offset, "true", 4) == 0) + { + item->type = cJSON_True; + input->offset += 4; + return true; + } + if (strncmp((const char *)input->content + input->offset, "false", 5) == 0) + { + item->type = cJSON_False; + input->offset += 5; + return true; + } + return false; + case 'n': + if (strncmp((const char *)input->content + input->offset, "null", 4) == 0) + { + item->type = cJSON_NULL; + input->offset += 4; + return true; + } + return false; + case '\"': + return parse_string(item, input); + case '[': + return parse_array(item, input); + case '{': + return parse_object(item, input); + default: + return false; + } +} + +/* Custom hooks */ +static cJSON_Hooks hooks = { malloc, free }; + +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks *h) +{ + if (h != NULL) + { + hooks.malloc_fn = h->malloc_fn; + hooks.free_fn = h->free_fn; + } +} + +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) +{ + parse_buffer buffer = {0}; + cJSON *item = NULL; + + if (value == NULL) return NULL; + + buffer.length = strlen(value); + buffer.content = (const unsigned char *)value; + buffer.offset = 0; + + item = (cJSON *)hooks.malloc_fn(sizeof(cJSON)); + if (item == NULL) return NULL; + memset(item, 0, sizeof(cJSON)); + + if (!parse_value(item, skip_whitespace(&buffer))) + { + cJSON_Delete(item); + return NULL; + } + return item; +} + +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) +{ + cJSON *next = NULL; + while (item != NULL) + { + next = item->next; + if (item->child != NULL) cJSON_Delete(item->child); + if (item->valuestring != NULL) hooks.free_fn(item->valuestring); + if (item->string != NULL) hooks.free_fn(item->string); + hooks.free_fn(item); + item = next; + } +} + +/* --- Print functions (unformatted) --- */ + +static size_t print_value_ptr(const cJSON *item, char *buffer); + +static size_t print_string_to(const char *str, char *buf) +{ + size_t len = strlen(str) + 2; + if (buf) + { + buf[0] = '\"'; + memcpy(buf + 1, str, len - 2); + buf[len - 1] = '\"'; + } + return len; +} + +static size_t print_number_to(const cJSON *item, char *buf) +{ + char tmp[32]; + size_t len; + if (fabs(floor(item->valuedouble) - item->valuedouble) <= DBL_EPSILON && fabs(item->valuedouble) < 1.0e15) + len = (size_t)sprintf(tmp, "%d", item->valueint); + else + len = (size_t)sprintf(tmp, "%g", item->valuedouble); + if (buf) memcpy(buf, tmp, len); + return len; +} + +static size_t print_array_to(const cJSON *item, char *buf) +{ + size_t pos = 0; + if (buf) buf[pos++] = '['; else pos++; + cJSON *child = item->child; + while (child != NULL) + { + pos += print_value_ptr(child, buf ? buf + pos : NULL); + if (child->next != NULL) { if (buf) buf[pos++] = ','; else pos++; } + child = child->next; + } + if (buf) buf[pos++] = ']'; else pos++; + return pos; +} + +static size_t print_object_to(const cJSON *item, char *buf) +{ + size_t pos = 0; + if (buf) buf[pos++] = '{'; else pos++; + cJSON *child = item->child; + while (child != NULL) + { + pos += print_string_to(child->string, buf ? buf + pos : NULL); + if (buf) buf[pos++] = ':'; else pos++; + pos += print_value_ptr(child, buf ? buf + pos : NULL); + if (child->next != NULL) { if (buf) buf[pos++] = ','; else pos++; } + child = child->next; + } + if (buf) buf[pos++] = '}'; else pos++; + return pos; +} + +static size_t print_value_ptr(const cJSON *item, char *buffer) +{ + switch (item->type & 0xFF) + { + case cJSON_NULL: if (buffer) { memcpy(buffer, "null", 4); } return 4; + case cJSON_False: if (buffer) { memcpy(buffer, "false", 5); } return 5; + case cJSON_True: if (buffer) { memcpy(buffer, "true", 4); } return 4; + case cJSON_Number: return print_number_to(item, buffer); + case cJSON_String: return print_string_to(item->valuestring, buffer); + case cJSON_Array: return print_array_to(item, buffer); + case cJSON_Object: return print_object_to(item, buffer); + default: return 0; + } +} + +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) +{ + return cJSON_PrintUnformatted(item); +} + +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) +{ + size_t length = 0; + char *output = NULL; + + length = print_value_ptr(item, NULL); + output = (char *)hooks.malloc_fn(length + 1); + if (output == NULL) return NULL; + print_value_ptr(item, output); + output[length] = '\0'; + return output; +} + +/* --- Item access --- */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) +{ + cJSON *child = NULL; + size_t size = 0; + if (array == NULL || !cJSON_IsArray(array)) return 0; + child = array->child; + while (child != NULL) { size++; child = child->next; } + return (int)size; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) +{ + cJSON *child = NULL; + int i = 0; + if (array == NULL || !cJSON_IsArray(array)) return NULL; + child = array->child; + while (child != NULL && i < index) { i++; child = child->next; } + return child; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON *object, const char *string) +{ + cJSON *current = NULL; + if (object == NULL || string == NULL) return NULL; + current = object->child; + while (current != NULL) + { + if (current->string != NULL && strcmp(current->string, string) == 0) return current; + current = current->next; + } + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *object, const char *string) +{ + cJSON *current = NULL; + if (object == NULL || string == NULL) return NULL; + current = object->child; + while (current != NULL) + { + if (current->string != NULL && cJSON_Strcasecmp(current->string, string) == 0) return current; + current = current->next; + } + return NULL; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) +{ + return cJSON_GetObjectItem(object, string) != NULL; +} + +static const char *global_error_ptr = NULL; +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) { return global_error_ptr; } + +/* --- Create items --- */ +static cJSON *cJSON_New_Item(void) +{ + cJSON *item = (cJSON *)hooks.malloc_fn(sizeof(cJSON)); + if (item != NULL) memset(item, 0, sizeof(cJSON)); + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) { cJSON *item = cJSON_New_Item(); if(item) item->type = cJSON_NULL; return item; } +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) { cJSON *item = cJSON_New_Item(); if(item) item->type = cJSON_True; return item; } +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) { cJSON *item = cJSON_New_Item(); if(item) item->type = cJSON_False; return item; } +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) { cJSON *item = cJSON_New_Item(); if(item) item->type = b ? cJSON_True : cJSON_False; return item; } +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) { cJSON *item = cJSON_New_Item(); if(item) { item->type = cJSON_Number; item->valuedouble = num; item->valueint = (int)num; } return item; } +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *str) +{ + cJSON *item = cJSON_New_Item(); + if (item && str) + { + item->type = cJSON_String; + item->valuestring = (char *)hooks.malloc_fn(strlen(str) + 1); + if (item->valuestring) strcpy(item->valuestring, str); + } + return item; +} +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) { return cJSON_CreateString(raw); } +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) { cJSON *item = cJSON_New_Item(); if(item) item->type = cJSON_Array; return item; } +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) { cJSON *item = cJSON_New_Item(); if(item) item->type = cJSON_Object; return item; } + +/* --- Add items --- */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) +{ + cJSON *child = NULL; + if (array == NULL || item == NULL) return false; + child = array->child; + if (child == NULL) { array->child = item; } + else + { + while (child->next) child = child->next; + child->next = item; + item->prev = child; + } + return true; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *name, cJSON *item) +{ + if (object == NULL || name == NULL || item == NULL) return false; + if (item->string != NULL) hooks.free_fn(item->string); + item->string = (char *)hooks.malloc_fn(strlen(name) + 1); + if (item->string) strcpy(item->string, name); + return cJSON_AddItemToArray(object, item); +} + +/* --- Type checks --- */ +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *item) { return (item != NULL) && (item->type == cJSON_Invalid); } +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON *item) { return (item != NULL) && (item->type == cJSON_False); } +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON *item) { return (item != NULL) && (item->type == cJSON_True); } +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON *item) { return (item != NULL) && (item->type & cJSON_Bool); } +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON *item) { return (item != NULL) && (item->type == cJSON_Number); } +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON *item) { return (item != NULL) && (item->type == cJSON_String); } +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON *item) { return (item != NULL) && (item->type == cJSON_Array); } +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *item) { return (item != NULL) && (item->type == cJSON_Object); } +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON *item) { return (item != NULL) && (item->type == cJSON_Raw); } + +/* --- Add helpers --- */ +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON *object, const char *name) { cJSON *item = cJSON_CreateNull(); if(item) cJSON_AddItemToObject(object, name, item); return item; } +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON *object, const char *name) { cJSON *item = cJSON_CreateTrue(); if(item) cJSON_AddItemToObject(object, name, item); return item; } +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON *object, const char *name) { cJSON *item = cJSON_CreateFalse(); if(item) cJSON_AddItemToObject(object, name, item); return item; } +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON *object, const char *name, cJSON_bool b) { cJSON *item = cJSON_CreateBool(b); if(item) cJSON_AddItemToObject(object, name, item); return item; } +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON *object, const char *name, double n) { cJSON *item = cJSON_CreateNumber(n); if(item) cJSON_AddItemToObject(object, name, item); return item; } +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON *object, const char *name, const char *s) { cJSON *item = cJSON_CreateString(s); if(item) cJSON_AddItemToObject(object, name, item); return item; } +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON *object, const char *name, const char *raw) { cJSON *item = cJSON_CreateRaw(raw); if(item) cJSON_AddItemToObject(object, name, item); return item; } + +CJSON_PUBLIC(void) cJSON_SetValuestring(cJSON *object, const char *valuestring) +{ + if (object == NULL || !cJSON_IsString(object) || valuestring == NULL) return; + if (object->valuestring != NULL) hooks.free_fn(object->valuestring); + object->valuestring = (char *)hooks.malloc_fn(strlen(valuestring) + 1); + if (object->valuestring) strcpy(object->valuestring, valuestring); +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) { (void)numbers; (void)count; return NULL; } +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) { (void)numbers; (void)count; return NULL; } +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) { (void)numbers; (void)count; return NULL; } +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) { (void)strings; (void)count; return NULL; } + +CJSON_PUBLIC(void) cJSON_free(void *ptr) { if(ptr) hooks.free_fn(ptr); } diff --git a/Core/Bsp/cJSON.h b/Core/Bsp/cJSON.h new file mode 100644 index 0000000..268f427 --- /dev/null +++ b/Core/Bsp/cJSON.h @@ -0,0 +1,203 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +/* cJSON */ +/* JSON parser in C. */ + +#ifndef CJSON_H +#define CJSON_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) +#define __WINDOWS__ +#endif + +#ifdef __WINDOWS__ + +/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols +CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) +CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbols +*/ +#ifndef CJSON_HIDE_SYMBOLS +#define CJSON_EXPORT_SYMBOLS +#endif +#endif /* __WINDOWS__ */ + +#ifdef CJSON_EXPORT_SYMBOLS +#define CJSON_PUBLIC(type) __declspec(dllexport) type +#elif defined(CJSON_IMPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllimport) type +#else +#define CJSON_PUBLIC(type) type +#endif + +#include + +/* project version */ +#define CJSON_VERSION_MAJOR 1 +#define CJSON_VERSION_MINOR 7 +#define CJSON_VERSION_PATCH 18 + +/* cJSON Types: */ +#define cJSON_Invalid (0) +#define cJSON_False (1 << 0) +#define cJSON_True (1 << 1) +#define cJSON_Bool (cJSON_True | cJSON_False) +#define cJSON_Number (1 << 2) +#define cJSON_String (1 << 3) +#define cJSON_Array (1 << 4) +#define cJSON_Object (1 << 5) +#define cJSON_Raw (1 << 6) +#define cJSON_NULL (1 << 7) + +#define cJSON_IsReference 256 +#define cJSON_StringIsConst 512 + +/* The cJSON structure: */ +typedef struct cJSON +{ + /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *next; + struct cJSON *prev; + /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + struct cJSON *child; + + /* The type of the item, as above. */ + int type; + + /* The item's string, if type==cJSON_String and type == cJSON_Raw */ + char *valuestring; + /* The item's name string, if this item is the child of an object */ + char *string; + /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ + int valueint; + /* The item's number, if type==cJSON_Number */ + double valuedouble; +} cJSON; + +typedef struct cJSON_Hooks +{ + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +typedef int cJSON_bool; + +/* Limits how deeply nested a structure can be */ +#define CJSON_NESTING_LIMIT 1000 + +/* String comparison, case insensitive */ +CJSON_PUBLIC(int) cJSON_Strcasecmp(const char *a, const char *b); + +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); +/* Render a cJSON entity to text for transfer/storage. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. */ +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); +/* Delete a cJSON entity and all subentities. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); + +/* Returns the number of items in an array (or object). */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); +/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); +/* Get item "string" from object. Case insensitive. */ +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); + +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); + +/* These calls create a cJSON item of the appropriate type. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); +/* raw json */ +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); + +/* These utilities create an Array of count items. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count); + +/* Append item to the specified array/object. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); +/* Append item to the specified object. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); + +/* These functions check the type of an item */ +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); + +/* These calls create a cJSON item of the appropriate type and add it to the specified object. */ +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); + +/* Assign a raw string value to an object. */ +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); + +/* Memory management */ +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks *hooks); +CJSON_PUBLIC(void) cJSON_free(void *ptr); + +/* Macros for creating things quickly. */ +#define cJSON_AddNullToObject(object,name) cJSON_AddNullToObject(object, name) +#define cJSON_AddTrueToObject(object,name) cJSON_AddTrueToObject(object, name) +#define cJSON_AddFalseToObject(object,name) cJSON_AddFalseToObject(object, name) +#define cJSON_AddBoolToObject(object,name,b) cJSON_AddBoolToObject(object, name, b) +#define cJSON_AddNumberToObject(object,name,n) cJSON_AddNumberToObject(object, name, n) +#define cJSON_AddStringToObject(object,name,s) cJSON_AddStringToObject(object, name, s) + +/* When assigning a string value, cJSON will copy the string, so you don't need to worry about it being freed. + * When assigning a raw value, cJSON will NOT copy the string, so it MUST be persistent. */ +CJSON_PUBLIC(void) cJSON_SetValuestring(cJSON *object, const char *valuestring); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Core/Bsp/driver_bmp280.c b/Core/Bsp/driver_bmp280.c new file mode 100644 index 0000000..1b92ad1 --- /dev/null +++ b/Core/Bsp/driver_bmp280.c @@ -0,0 +1,1635 @@ +/** + * Copyright (c) 2015 - present LibDriver All rights reserved + * + * The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * @file driver_bmp280.c + * @brief driver bmp280 source file + * @version 1.0.0 + * @author Shifeng Li + * @date 2024-01-15 + * + *

history

+ * + *
Date Version Author Description + *
2024/01/15 1.0 Shifeng Li first upload + *
+ */ + +#include "driver_bmp280.h" + +/** + * @brief chip information definition + */ +#define CHIP_NAME "Bosch BMP280" /**< chip name */ +#define MANUFACTURER_NAME "Bosch" /**< manufacturer name */ +#define SUPPLY_VOLTAGE_MIN 1.71f /**< chip min supply voltage */ +#define SUPPLY_VOLTAGE_MAX 3.6f /**< chip max supply voltage */ +#define MAX_CURRENT 1.12f /**< chip max current */ +#define TEMPERATURE_MIN -40.0f /**< chip min operating temperature */ +#define TEMPERATURE_MAX 85.0f /**< chip max operating temperature */ +#define DRIVER_VERSION 1000 /**< driver version */ + +/** + * @brief chip register definition + */ +#define BMP280_REG_NVM_PAR_T1_L 0x88 /**< NVM PAR T1 low register */ +#define BMP280_REG_NVM_PAR_T1_H 0x89 /**< NVM PAR T1 high register */ +#define BMP280_REG_NVM_PAR_T2_L 0x8A /**< NVM PAR T2 low register */ +#define BMP280_REG_NVM_PAR_T2_H 0x8B /**< NVM PAR T2 high register */ +#define BMP280_REG_NVM_PAR_T3_L 0x8C /**< NVM PAR T3 low register */ +#define BMP280_REG_NVM_PAR_T3_H 0x8D /**< NVM PAR T3 high register */ +#define BMP280_REG_NVM_PAR_P1_L 0x8E /**< NVM PAR P1 low register */ +#define BMP280_REG_NVM_PAR_P1_H 0x8F /**< NVM PAR P1 high register */ +#define BMP280_REG_NVM_PAR_P2_L 0x90 /**< NVM PAR P2 low register */ +#define BMP280_REG_NVM_PAR_P2_H 0x91 /**< NVM PAR P2 high register */ +#define BMP280_REG_NVM_PAR_P3_L 0x92 /**< NVM PAR P3 low register */ +#define BMP280_REG_NVM_PAR_P3_H 0x93 /**< NVM PAR P3 high register */ +#define BMP280_REG_NVM_PAR_P4_L 0x94 /**< NVM PAR P4 low register */ +#define BMP280_REG_NVM_PAR_P4_H 0x95 /**< NVM PAR P4 high register */ +#define BMP280_REG_NVM_PAR_P5_L 0x96 /**< NVM PAR P5 low register */ +#define BMP280_REG_NVM_PAR_P5_H 0x97 /**< NVM PAR P5 high register */ +#define BMP280_REG_NVM_PAR_P6_L 0x98 /**< NVM PAR P6 low register */ +#define BMP280_REG_NVM_PAR_P6_H 0x99 /**< NVM PAR P6 high register */ +#define BMP280_REG_NVM_PAR_P7_L 0x9A /**< NVM PAR P7 low register */ +#define BMP280_REG_NVM_PAR_P7_H 0x9B /**< NVM PAR P7 high register */ +#define BMP280_REG_NVM_PAR_P8_L 0x9C /**< NVM PAR P8 low register */ +#define BMP280_REG_NVM_PAR_P8_H 0x9D /**< NVM PAR P8 high register */ +#define BMP280_REG_NVM_PAR_P9_L 0x9E /**< NVM PAR P9 low register */ +#define BMP280_REG_NVM_PAR_P9_H 0x9F /**< NVM PAR P9 high register */ +#define BMP280_REG_TEMP_XLSB 0xFC /**< temp xlsb register */ +#define BMP280_REG_TEMP_LSB 0xFB /**< temp lsb register */ +#define BMP280_REG_TEMP_MSB 0xFA /**< temp msb register */ +#define BMP280_REG_PRESS_XLSB 0xF9 /**< press xlsb register */ +#define BMP280_REG_PRESS_LSB 0xF8 /**< press lsb register */ +#define BMP280_REG_PRESS_MSB 0xF7 /**< press msb register */ +#define BMP280_REG_CONFIG 0xF5 /**< config register */ +#define BMP280_REG_CTRL_MEAS 0xF4 /**< ctrl meas register */ +#define BMP280_REG_STATUS 0xF3 /**< status register */ +#define BMP280_REG_RESET 0xE0 /**< soft reset register */ +#define BMP280_REG_ID 0xD0 /**< chip id register */ + +/** + * @brief read multiple bytes + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] reg register address + * @param[out] *buf pointer to a data buffer + * @param[in] len data length + * @return status code + * - 0 success + * - 1 iic spi read failed + * @note none + */ +static uint8_t a_bmp280_iic_spi_read(bmp280_handle_t *handle, uint8_t reg, uint8_t *buf, uint16_t len) +{ + if (handle->iic_spi == BMP280_INTERFACE_IIC) /* iic interface */ + { + if (handle->iic_read(handle->iic_addr, reg, buf, len) != 0) /* iic read */ + { + return 1; /* return error */ + } + + return 0; /* success return 0 */ + } + else /* spi interface */ + { + reg |= 1 << 7; /* set read mode */ + if (handle->spi_read(reg, buf, len) != 0) /* spi read */ + { + return 1; /* return error */ + } + + return 0; /* success return 0 */ + } +} + +/** + * @brief write multiple bytes + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] reg register address + * @param[in] *buf pointer to a data buffer + * @param[in] len data length + * @return status code + * - 0 success + * - 1 iic spi write failed + * @note none + */ +static uint8_t a_bmp280_iic_spi_write(bmp280_handle_t *handle, uint8_t reg, uint8_t *buf, uint16_t len) +{ + if (handle->iic_spi == BMP280_INTERFACE_IIC) /* iic interface */ + { + if (handle->iic_write(handle->iic_addr, reg, buf, len) != 0) /* iic write */ + { + return 1; /* return error */ + } + + return 0; /* success return 0 */ + } + else /* spi interface */ + { + reg &= ~(1 << 7); /* write mode */ + if (handle->spi_write(reg, buf, len) != 0) /* spi write */ + { + return 1; /* return error */ + } + + return 0; /* success return 0 */ + } +} + +/** + * @brief get nvm calibration + * @param[in] *handle pointer to a bmp280 handle structure + * @return status code + * - 0 success + * - 1 get calibration data failed + * @note none + */ +static uint8_t a_bmp280_get_nvm_calibration(bmp280_handle_t *handle) +{ + uint8_t buf[2]; + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_NVM_PAR_T1_L, (uint8_t *)buf, 2) != 0) /* read t1 */ + { + handle->debug_print("bmp280: get calibration data failed.\n"); /* get calibration data failed */ + + return 1; /* return error */ + } + handle->t1 = (uint16_t)buf[1] << 8 | buf[0]; /* set t1 */ + if (a_bmp280_iic_spi_read(handle, BMP280_REG_NVM_PAR_T2_L, (uint8_t *)buf, 2) != 0) /* read t2 */ + { + handle->debug_print("bmp280: get calibration data failed.\n"); /* get calibration data failed */ + + return 1; /* return error */ + } + handle->t2 = (int16_t)((uint16_t)buf[1] << 8 | buf[0]); /* set t2 */ + if (a_bmp280_iic_spi_read(handle, BMP280_REG_NVM_PAR_T3_L, (uint8_t *)buf, 2) != 0) /* read t3 */ + { + handle->debug_print("bmp280: get calibration data failed.\n"); /* get calibration data failed */ + + return 1; /* return error */ + } + handle->t3 = (int16_t)((uint16_t)buf[1] << 8 | buf[0]); /* set t3 */ + if (a_bmp280_iic_spi_read(handle, BMP280_REG_NVM_PAR_P1_L, (uint8_t *)buf, 2) != 0) /* read p1 */ + { + handle->debug_print("bmp280: get calibration data failed.\n"); /* get calibration data failed */ + + return 1; /* return error */ + } + handle->p1 = (uint16_t)buf[1] << 8 | buf[0]; /* set p1 */ + if (a_bmp280_iic_spi_read(handle, BMP280_REG_NVM_PAR_P2_L, (uint8_t *)buf, 2) != 0) /* read p2 */ + { + handle->debug_print("bmp280: get calibration data failed.\n"); /* get calibration data failed */ + + return 1; /* return error */ + } + handle->p2 = (int16_t)((uint16_t)buf[1] << 8 | buf[0]); /* set p2 */ + if (a_bmp280_iic_spi_read(handle, BMP280_REG_NVM_PAR_P3_L, (uint8_t *)buf, 2) != 0) /* read p3 */ + { + handle->debug_print("bmp280: get calibration data failed.\n"); /* get calibration data failed */ + + return 1; /* return error */ + } + handle->p3 = (int16_t)((uint16_t)buf[1] << 8 | buf[0]); /* set p3 */ + if (a_bmp280_iic_spi_read(handle, BMP280_REG_NVM_PAR_P4_L, (uint8_t *)buf, 2) != 0) /* read p4 */ + { + handle->debug_print("bmp280: get calibration data failed.\n"); /* get calibration data failed */ + + return 1; /* return error */ + } + handle->p4 = (int16_t)((uint16_t)buf[1] << 8 | buf[0]); /* set p4 */ + if (a_bmp280_iic_spi_read(handle, BMP280_REG_NVM_PAR_P5_L, (uint8_t *)buf, 2) != 0) /* read p5 */ + { + handle->debug_print("bmp280: get calibration data failed.\n"); /* get calibration data failed */ + + return 1; /* return error */ + } + handle->p5 = (int16_t)((uint16_t)buf[1] << 8 | buf[0]); /* set p5 */ + if (a_bmp280_iic_spi_read(handle, BMP280_REG_NVM_PAR_P6_L, (uint8_t *)buf, 2) != 0) /* read p6 */ + { + handle->debug_print("bmp280: get calibration data failed.\n"); /* get calibration data failed */ + + return 1; /* return error */ + } + handle->p6 = (int16_t)((uint16_t)buf[1] << 8 | buf[0]); /* set p6 */ + if (a_bmp280_iic_spi_read(handle, BMP280_REG_NVM_PAR_P7_L, (uint8_t *)buf, 2) != 0) /* read p7 */ + { + handle->debug_print("bmp280: get calibration data failed.\n"); /* get calibration data failed */ + + return 1; /* return error */ + } + handle->p7 = (int16_t)((uint16_t)buf[1] << 8 | buf[0]); /* set p7 */ + if (a_bmp280_iic_spi_read(handle, BMP280_REG_NVM_PAR_P8_L, (uint8_t *)buf, 2) != 0) /* read p8 */ + { + handle->debug_print("bmp280: get calibration data failed.\n"); /* get calibration data failed */ + + return 1; /* return error */ + } + handle->p8 = (int16_t)((uint16_t)buf[1] << 8 | buf[0]); /* set p8 */ + if (a_bmp280_iic_spi_read(handle, BMP280_REG_NVM_PAR_P9_L, (uint8_t *)buf, 2) != 0) /* read p9 */ + { + handle->debug_print("bmp280: get calibration data failed.\n"); /* get calibration data failed */ + + return 1; /* return error */ + } + handle->p9 = (int16_t)((uint16_t)buf[1] << 8 | buf[0]); /* set p9 */ + handle->t_fine = 0; /* init 0 */ + + return 0; /* success return 0 */ +} + +/** + * @brief compensate temperature + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] raw raw data + * @param[out] *output pointer to an output buffer + * @return status code + * - 0 success + * - 1 compensate temperature failed + * @note none + */ +static uint8_t a_bmp280_compensate_temperature(bmp280_handle_t *handle, uint32_t raw, float *output) +{ + uint8_t res; + float var1; + float var2; + float temperature; + + var1 = (((float)raw) / 16384.0f - ((float)handle->t1) / 1024.0f) * ((float)handle->t2); /* set var1 */ + var2 = ((((float)raw) / 131072.0f - ((float)handle->t1) / 8192.0f) * + (((float)raw) / 131072.0f - ((float)handle->t1) / 8192.0f)) * + ((float)handle->t3); /* set var2 */ + handle->t_fine = (int32_t)(var1 + var2); /* set t_fine */ + temperature = (var1 + var2) / 5120.0f; /* set temperature */ + res = 0; /* init 0 */ + if (temperature < -40.0f) /* check temperature min */ + { + temperature = -40.0f; /* set min */ + res = 1; /* set failed */ + } + if (temperature > 85.0f) /* check temperature max */ + { + temperature = 85.0f; /* set max */ + res = 1; /* set failed */ + } + (*output) = temperature; /* set output temperature */ + + return res; /* return result */ +} + +/** + * @brief compensate pressure + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] raw raw data + * @param[out] *output pointer to an output buffer + * @return status code + * - 0 success + * - 1 compensate pressure failed + * @note none + */ +static uint8_t a_bmp280_compensate_pressure(bmp280_handle_t *handle, uint32_t raw, float *output) +{ + uint8_t res; + float var1; + float var2; + float pressure; + + var1 = ((float)handle->t_fine / 2.0f) - 64000.0f; /* set var1 */ + var2 = var1 * var1 * ((float)handle->p6) / 32768.0f; /* set var2 */ + var2 = var2 + var1 * ((float)handle->p5) * 2.0f; /* set var2 */ + var2 = (var2 / 4.0f) + (((float)handle->p4) * 65536.0f); /* set var2 */ + var1 = (((float)handle->p3) * var1 * var1 / 524288.0f + + ((float)handle->p2) * var1) / 524288.0f; /* set var1 */ + var1 = (1.0f + var1 / 32768.0f) * ((float)handle->p1); /* set var1 */ + pressure = 0.0f; /* init 0 */ + if (var1 < 0.0f || var1 > 0.0f) /* check not zero */ + { + pressure = 1048576.0f - (float)raw; /* set pressure */ + pressure = (pressure - (var2 / 4096.0f)) * 6250.0f / var1; /* set pressure */ + var1 = ((float)handle->p9) * pressure * pressure / 2147483648.0f; /* set var1 */ + var2 = pressure * ((float)handle->p8) / 32768.0f; /* set var2 */ + pressure = pressure + (var1 + var2 + ((float)handle->p7)) / 16.0f; /* set pressure */ + res = 0; /* init 0 */ + if (pressure < 30000.0f) /* check pressure min */ + { + pressure = 30000.0f; /* set pressure min */ + res = 1; /* set failed */ + } + if (pressure > 110000.0f) /* check pressure max */ + { + pressure = 110000.0f; /* set pressure max */ + res = 1; /* set failed */ + } + + (*output) = pressure; /* set pressure output */ + + return res; /* return result */ + } + else + { + res = 1; /* set failed */ + (*output) = pressure; /* set pressure output */ + + return res; /* return result */ + } +} + +/** + * @brief set the iic address pin + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] addr_pin iic address pin + * @return status code + * - 0 success + * - 2 handle is NULL + * @note none + */ +uint8_t bmp280_set_addr_pin(bmp280_handle_t *handle, bmp280_address_t addr_pin) +{ + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + + handle->iic_addr = (uint8_t)addr_pin; /* set iic address */ + + return 0; /* success return 0 */ +} + +/** + * @brief get the iic address pin + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *addr_pin pointer to an iic address pin buffer + * @return status code + * - 0 success + * - 2 handle is NULL + * @note none + */ +uint8_t bmp280_get_addr_pin(bmp280_handle_t *handle, bmp280_address_t *addr_pin) +{ + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + + *addr_pin = (bmp280_address_t)handle->iic_addr; /* get iic address */ + + return 0; /* success return 0 */ +} + +/** + * @brief set the interface + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] interface chip interface + * @return status code + * - 0 success + * - 2 handle is NULL + * @note none + */ +uint8_t bmp280_set_interface(bmp280_handle_t *handle, bmp280_interface_t interface) +{ + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + + handle->iic_spi = (uint8_t)interface; /* set interface */ + + return 0; /* success return 0 */ +} + +/** + * @brief get the interface + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *interface pointer to a chip interface buffer + * @return status code + * - 0 success + * - 2 handle is NULL + * @note none + */ +uint8_t bmp280_get_interface(bmp280_handle_t *handle, bmp280_interface_t *interface) +{ + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + + *interface = (bmp280_interface_t)(handle->iic_spi); /* get interface */ + + return 0; /* success return 0 */ +} + +/** + * @brief initialize the chip + * @param[in] *handle pointer to a bmp280 handle structure + * @return status code + * - 0 success + * - 1 iic or spi initialization failed + * - 2 handle is NULL + * - 3 linked functions is NULL + * - 4 id is error + * - 5 get nvm calibration failed + * - 6 read calibration failed + * @note none + */ +uint8_t bmp280_init(bmp280_handle_t *handle) +{ + uint8_t id; + uint8_t reg; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->debug_print == NULL) /* check debug_print */ + { + return 3; /* return error */ + } + if (handle->iic_init == NULL) /* check iic_init */ + { + handle->debug_print("bmp280: iic_init is null.\n"); /* iic_init is nul */ + + return 3; /* return error */ + } + if (handle->iic_deinit == NULL) /* check iic_deinit */ + { + handle->debug_print("bmp280: iic_deinit is null.\n"); /* iic_deinit is null */ + + return 3; /* return error */ + } + if (handle->iic_read == NULL) /* check iic_read */ + { + handle->debug_print("bmp280: iic_read is null.\n"); /* iic_read is null */ + + return 3; /* return error */ + } + if (handle->iic_write == NULL) /* check iic_write */ + { + handle->debug_print("bmp280: iic_write is null.\n"); /* iic_write is null */ + + return 3; /* return error */ + } + if (handle->spi_init == NULL) /* check spi_init */ + { + handle->debug_print("bmp280: spi_init is null.\n"); /* spi_init is nul */ + + return 3; /* return error */ + } + if (handle->spi_deinit == NULL) /* check spi_deinit */ + { + handle->debug_print("bmp280: spi_deinit is null.\n"); /* spi_deinit is nul */ + + return 3; /* return error */ + } + if (handle->spi_read == NULL) /* check spi_read */ + { + handle->debug_print("bmp280: spi_read is null.\n"); /* spi_read is nul */ + + return 3; /* return error */ + } + if (handle->spi_write == NULL) /* check spi_write */ + { + handle->debug_print("bmp280: spi_write is null.\n"); /* spi_write is nul */ + + return 3; /* return error */ + } + if (handle->delay_ms == NULL) /* check delay_ms */ + { + handle->debug_print("bmp280: delay_ms is null.\n"); /* delay_ms is null */ + + return 3; /* return error */ + } + + if (handle->iic_spi == BMP280_INTERFACE_IIC) /* iic interface */ + { + if (handle->iic_init() != 0) /* iic init */ + { + handle->debug_print("bmp280: iic init failed.\n"); /* iic init failed */ + + return 1; /* return error */ + } + } + else /* spi interface */ + { + if (handle->spi_init() != 0) /* spi init */ + { + handle->debug_print("bmp280: spi init failed.\n"); /* spi init failed */ + + return 1; /* return error */ + } + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_ID, (uint8_t *)&id, 1) != 0) /* read chip id */ + { + handle->debug_print("bmp280: read id failed.\n"); /* read id failed */ + (void)handle->iic_deinit(); /* iic deinit */ + + return 4; /* return error */ + } + if (id != 0x58) /* check id */ + { + handle->debug_print("bmp280: id is error.\n"); /* id is error */ + (void)handle->iic_deinit(); /* iic deinit */ + + return 4; /* return error */ + } + reg = 0xB6; /* set the reset value */ + if (a_bmp280_iic_spi_write(handle, BMP280_REG_RESET, ®, 1) != 0) /* reset the chip */ + { + handle->debug_print("bmp280: reset failed.\n"); /* reset failed */ + (void)handle->iic_deinit(); /* iic deinit */ + + return 5; /* return error */ + } + handle->delay_ms(5); /* delay 5ms */ + if (a_bmp280_get_nvm_calibration(handle) != 0) /* get nvm calibration */ + { + (void)handle->iic_deinit(); /* iic deinit */ + + return 6; /* return error */ + } + handle->inited = 1; /* flag finish initialization */ + + return 0; /* success return 0 */ +} + +/** + * @brief close the chip + * @param[in] *handle pointer to a bmp280 handle structure + * @return status code + * - 0 success + * - 1 iic deinit failed + * - 2 handle is NULL + * - 3 handle is not initialized + * - 4 power down failed + * @note none + */ +uint8_t bmp280_deinit(bmp280_handle_t *handle) +{ + uint8_t prev; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 4; /* return error */ + } + prev &= ~(3 << 0); /* clear settings */ + prev |= 0 << 0; /* set sleep mode */ + if (a_bmp280_iic_spi_write(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* write ctrl meas */ + { + handle->debug_print("bmp280: write ctrl meas failed.\n"); /* write ctrl meas failed */ + + return 4; /* return error */ + } + if (handle->iic_spi == BMP280_INTERFACE_IIC) /* iic interface */ + { + if (handle->iic_deinit() != 0) /* iic deinit */ + { + handle->debug_print("bmp280: iic deinit failed.\n"); /* iic deinit failed */ + + return 1; /* return error */ + } + } + else /* spi interface */ + { + if (handle->spi_deinit() != 0) /* spi deinit */ + { + handle->debug_print("bmp280: spi deinit failed.\n"); /* spi deinit failed */ + + return 1; /* return error */ + } + } + handle->inited = 0; /* flag close */ + + return 0; /* success return 0 */ +} + +/** + * @brief soft reset + * @param[in] *handle pointer to a bmp280 handle structure + * @return status code + * - 0 success + * - 1 soft reset failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_soft_reset(bmp280_handle_t *handle) +{ + uint8_t reg; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + reg = 0xB6; /* set the reset value */ + if (a_bmp280_iic_spi_write(handle, BMP280_REG_RESET, ®, 1) != 0) /* reset the chip */ + { + handle->debug_print("bmp280: reset failed.\n"); /* reset failed */ + + return 1; /* return error */ + } + handle->delay_ms(5); /* delay 5ms */ + + return 0; /* success return 0 */ +} + +/** + * @brief get status + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *status pointer to a status buffer + * @return status code + * - 0 success + * - 1 get status failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_status(bmp280_handle_t *handle, uint8_t *status) +{ + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_STATUS, status, 1) != 0) /* read status */ + { + handle->debug_print("bmp280: read status failed.\n"); /* read status failed */ + + return 1; /* return error */ + } + + return 0; /* success return 0 */ +} + +/** + * @brief set temperatue oversampling + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] oversampling temperatue oversampling + * @return status code + * - 0 success + * - 1 set temperatue oversampling failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_set_temperatue_oversampling(bmp280_handle_t *handle, bmp280_oversampling_t oversampling) +{ + uint8_t prev; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 1; /* return error */ + } + prev &= ~(7 << 5); /* clear settings */ + prev |= oversampling << 5; /* set oversampling */ + if (a_bmp280_iic_spi_write(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* write ctrl meas */ + { + handle->debug_print("bmp280: write ctrl meas failed.\n"); /* write ctrl meas failed */ + + return 1; /* return error */ + } + + return 0; /* success return 0 */ +} + +/** + * @brief get temperatue oversampling + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *oversampling pointer to a oversampling buffer + * @return status code + * - 0 success + * - 1 get temperatue oversampling failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_temperatue_oversampling(bmp280_handle_t *handle, bmp280_oversampling_t *oversampling) +{ + uint8_t prev; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 1; /* return error */ + } + *oversampling = (bmp280_oversampling_t)((prev >> 5) & 0x7); /* set oversampling */ + + return 0; /* success return 0 */ +} + +/** + * @brief set pressure oversampling + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] oversampling pressure oversampling + * @return status code + * - 0 success + * - 1 set pressure oversampling failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_set_pressure_oversampling(bmp280_handle_t *handle, bmp280_oversampling_t oversampling) +{ + uint8_t prev; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 1; /* return error */ + } + prev &= ~(7 << 2); /* clear settings */ + prev |= oversampling << 2; /* set oversampling */ + if (a_bmp280_iic_spi_write(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* write ctrl meas */ + { + handle->debug_print("bmp280: write ctrl meas failed.\n"); /* write ctrl meas failed */ + + return 1; /* return error */ + } + + return 0; /* success return 0 */ +} + +/** + * @brief get pressure oversampling + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *oversampling pointer to a oversampling buffer + * @return status code + * - 0 success + * - 1 get pressure oversampling failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_pressure_oversampling(bmp280_handle_t *handle, bmp280_oversampling_t *oversampling) +{ + uint8_t prev; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 1; /* return error */ + } + *oversampling = (bmp280_oversampling_t)((prev >> 2) & 0x7); /* set oversampling */ + + return 0; /* success return 0 */ +} + +/** + * @brief set mode + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] mode chip mode + * @return status code + * - 0 success + * - 1 set mode failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_set_mode(bmp280_handle_t *handle, bmp280_mode_t mode) +{ + uint8_t prev; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 1; /* return error */ + } + prev &= ~(3 << 0); /* clear settings */ + prev |= mode << 0; /* set mode */ + if (a_bmp280_iic_spi_write(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* write ctrl meas */ + { + handle->debug_print("bmp280: write ctrl meas failed.\n"); /* write ctrl meas failed */ + + return 1; /* return error */ + } + + return 0; /* success return 0 */ +} + +/** + * @brief get mode + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *mode pointer to a mode buffer + * @return status code + * - 0 success + * - 1 get mode failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_mode(bmp280_handle_t *handle, bmp280_mode_t *mode) +{ + uint8_t prev; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 1; /* return error */ + } + *mode = (bmp280_mode_t)((prev >> 0) & 0x3); /* set mode */ + + return 0; /* success return 0 */ +} + +/** + * @brief set standby time + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] standby_time standby time + * @return status code + * - 0 success + * - 1 set standby time failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_set_standby_time(bmp280_handle_t *handle, bmp280_standby_time_t standby_time) +{ + uint8_t prev; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CONFIG, &prev, 1) != 0) /* read config */ + { + handle->debug_print("bmp280: read config failed.\n"); /* read config failed */ + + return 1; /* return error */ + } + prev &= ~(7 << 5); /* clear settings */ + prev |= standby_time << 5; /* set standby time */ + if (a_bmp280_iic_spi_write(handle, BMP280_REG_CONFIG, &prev, 1) != 0) /* write config */ + { + handle->debug_print("bmp280: write config failed.\n"); /* write config failed */ + + return 1; /* return error */ + } + + return 0; /* success return 0 */ +} + +/** + * @brief get standby time + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *standby_time pointer to a standby time buffer + * @return status code + * - 0 success + * - 1 get standby time failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_standby_time(bmp280_handle_t *handle, bmp280_standby_time_t *standby_time) +{ + uint8_t prev; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CONFIG, &prev, 1) != 0) /* read config */ + { + handle->debug_print("bmp280: read config failed.\n"); /* read config failed */ + + return 1; /* return error */ + } + *standby_time = (bmp280_standby_time_t)((prev >> 5) & 0x7); /* get standby time */ + + return 0; /* success return 0 */ +} + +/** + * @brief set filter + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] filter input filter + * @return status code + * - 0 success + * - 1 set filter failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_set_filter(bmp280_handle_t *handle, bmp280_filter_t filter) +{ + uint8_t prev; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CONFIG, &prev, 1) != 0) /* read config */ + { + handle->debug_print("bmp280: read config failed.\n"); /* read config failed */ + + return 1; /* return error */ + } + prev &= ~(7 << 2); /* clear settings */ + prev |= (filter & 0x07) << 2; /* set filter */ + if (a_bmp280_iic_spi_write(handle, BMP280_REG_CONFIG, &prev, 1) != 0) /* write config */ + { + handle->debug_print("bmp280: write config failed.\n"); /* write config failed */ + + return 1; /* return error */ + } + + return 0; /* success return 0 */ +} + +/** + * @brief get filter + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *filter pointer to a filter buffer + * @return status code + * - 0 success + * - 1 get filter failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_filter(bmp280_handle_t *handle, bmp280_filter_t *filter) +{ + uint8_t prev; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CONFIG, &prev, 1) != 0) /* read config */ + { + handle->debug_print("bmp280: read config failed.\n"); /* read config failed */ + + return 1; /* return error */ + } + *filter = (bmp280_filter_t)((prev >> 2) & 0x07); /* set filter */ + + return 0; /* success return 0 */ +} + +/** + * @brief set spi wire + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] spi spi wire + * @return status code + * - 0 success + * - 1 set spi wire failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_set_spi_wire(bmp280_handle_t *handle, bmp280_spi_wire_t spi) +{ + uint8_t prev; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CONFIG, &prev, 1) != 0) /* read config */ + { + handle->debug_print("bmp280: read config failed.\n"); /* read config failed */ + + return 1; /* return error */ + } + prev &= ~(1 << 0); /* clear settings */ + prev |= spi << 0; /* set spi wire */ + if (a_bmp280_iic_spi_write(handle, BMP280_REG_CONFIG, &prev, 1) != 0) /* write config */ + { + handle->debug_print("bmp280: write config failed.\n"); /* write config failed */ + + return 1; /* return error */ + } + + return 0; /* success return 0 */ +} + +/** + * @brief get spi wire + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *spi pointer to a spi wire buffer + * @return status code + * - 0 success + * - 1 get spi wire failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_spi_wire(bmp280_handle_t *handle, bmp280_spi_wire_t *spi) +{ + uint8_t prev; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CONFIG, &prev, 1) != 0) /* read config */ + { + handle->debug_print("bmp280: read config failed.\n"); /* read config failed */ + + return 1; /* return error */ + } + *spi = (bmp280_spi_wire_t)((prev >> 0) & 0x01); /* get spi */ + + return 0; /* success return 0 */ +} + +/** + * @brief read the pressure data + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *pressure_raw pointer to a raw pressure buffer + * @param[out] *pressure_pa pointer to a converted pressure buffer + * @return status code + * - 0 success + * - 1 pressure read failed + * - 2 handle is NULL + * - 3 handle is not initialized + * - 4 compensate pressure failed + * - 5 read timeout + * @note none + */ +uint8_t bmp280_read_pressure(bmp280_handle_t *handle, uint32_t *pressure_raw, float *pressure_pa) +{ + uint8_t res; + uint8_t prev; + uint32_t timeout; + uint32_t temperature_raw; + float temperature_c; + uint8_t buf[6]; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 1; /* return error */ + } + if ((prev & 0x3) == 3) /* normal mode */ + { + res = a_bmp280_iic_spi_read(handle, BMP280_REG_PRESS_MSB, buf, 6); /* read temperature and pressure */ + if (res != 0) + { + handle->debug_print("bmp280: read failed.\n"); /* read failed */ + + return 1; /* return error */ + } + temperature_raw = ((((uint32_t)(buf[3])) << 12) | + (((uint32_t)(buf[4])) << 4) | + ((uint32_t)buf[5] >> 4)); /* set temperature raw */ + res = a_bmp280_compensate_temperature(handle, temperature_raw, &temperature_c); /* compensate temperature */ + if (res != 0) + { + handle->debug_print("bmp280: compensate temperature failed.\n"); /* compensate temperature failed */ + + return 4; /* return error */ + } + *pressure_raw = ((((int32_t)(buf[0])) << 12) | + (((int32_t)(buf[1])) << 4) | + (((int32_t)(buf[2])) >> 4)); /* set pressure raw */ + res = a_bmp280_compensate_pressure(handle, *pressure_raw, pressure_pa); /* compensate pressure */ + if (res != 0) + { + handle->debug_print("bmp280: compensate pressure failed.\n"); /* compensate pressure failed */ + + return 4; /* return error */ + } + } + else /* forced mode */ + { + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 1; /* return error */ + } + prev &= ~(3 << 0); /* clear settings */ + prev |= 0x01 << 0; /* set forced mode */ + if (a_bmp280_iic_spi_write(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* write ctrl meas */ + { + handle->debug_print("bmp280: write ctrl meas failed.\n"); /* write ctrl meas failed */ + + return 1; /* return error */ + } + timeout = 10 * 1000; /* set timeout */ + while (timeout != 0) /* check timeout */ + { + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 1; /* return error */ + } + if ((prev & 0x03) == 0) /* if finished */ + { + break; /* break */ + } + handle->delay_ms(1); /* delay 1ms */ + timeout--; /* timeout-- */ + } + if (timeout == 0) /* check timeout */ + { + handle->debug_print("bmp280: read timeout.\n"); /* read timeout */ + + return 5; /* return error */ + } + res = a_bmp280_iic_spi_read(handle, BMP280_REG_PRESS_MSB, buf, 6); /* read temperature and pressure */ + if (res != 0) + { + handle->debug_print("bmp280: read failed.\n"); /* read failed */ + + return 1; /* return error */ + } + temperature_raw = ((((uint32_t)(buf[3])) << 12) | + (((uint32_t)(buf[4])) << 4) | + ((uint32_t)buf[5] >> 4)); /* set temperature raw */ + res = a_bmp280_compensate_temperature(handle, temperature_raw, &temperature_c); /* compensate temperature */ + if (res != 0) + { + handle->debug_print("bmp280: compensate temperature failed.\n"); /* compensate temperature failed */ + + return 4; /* return error */ + } + *pressure_raw = ((((int32_t)(buf[0])) << 12) | + (((int32_t)(buf[1])) << 4) | + (((int32_t)(buf[2])) >> 4)); /* set pressure raw */ + res = a_bmp280_compensate_pressure(handle, *pressure_raw, pressure_pa); /* compensate pressure */ + if (res != 0) + { + handle->debug_print("bmp280: compensate pressure failed.\n"); /* compensate pressure failed */ + + return 4; /* return error */ + } + } + + return 0; /* success return 0 */ +} + +/** + * @brief read the temperature data + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *temperature_raw pointer to a raw temperature buffer + * @param[out] *temperature_c pointer to a converted temperature buffer + * @return status code + * - 0 success + * - 1 temperature read failed + * - 2 handle is NULL + * - 3 handle is not initialized + * - 4 compensate pressure failed + * - 5 read timeout + * @note none + */ +uint8_t bmp280_read_temperature(bmp280_handle_t *handle, uint32_t *temperature_raw, float *temperature_c) +{ + uint8_t res; + uint8_t prev; + uint32_t timeout; + uint8_t buf[6]; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 1; /* return error */ + } + if ((prev & 0x3) == 3) /* normal mode */ + { + res = a_bmp280_iic_spi_read(handle, BMP280_REG_PRESS_MSB, buf, 6); /* read temperature and pressure */ + if (res != 0) + { + handle->debug_print("bmp280: read failed.\n"); /* read failed */ + + return 1; /* return error */ + } + *temperature_raw = ((((uint32_t)(buf[3])) << 12) | + (((uint32_t)(buf[4])) << 4) | + ((uint32_t)buf[5] >> 4)); /* set temperature raw */ + res = a_bmp280_compensate_temperature(handle, *temperature_raw, temperature_c); /* compensate temperature */ + if (res != 0) + { + handle->debug_print("bmp280: compensate temperature failed.\n"); /* compensate temperature failed */ + + return 4; /* return error */ + } + } + else /* forced mode */ + { + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 1; /* return error */ + } + prev &= ~(3 << 0); /* clear settings */ + prev |= 0x01 << 0; /* set forced mode */ + if (a_bmp280_iic_spi_write(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* write ctrl meas */ + { + handle->debug_print("bmp280: write ctrl meas failed.\n"); /* write ctrl meas failed */ + + return 1; /* return error */ + } + timeout = 10 * 1000; /* set timeout */ + while (timeout != 0) /* check timeout */ + { + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 1; /* return error */ + } + if ((prev & 0x03) == 0) /* if finished */ + { + break; /* break */ + } + handle->delay_ms(1); /* delay 1ms */ + timeout--; /* timeout-- */ + } + if (timeout == 0) /* check timeout */ + { + handle->debug_print("bmp280: read timeout.\n"); /* read timeout */ + + return 5; /* return error */ + } + res = a_bmp280_iic_spi_read(handle, BMP280_REG_PRESS_MSB, buf, 6); /* read temperature and pressure */ + if (res != 0) + { + handle->debug_print("bmp280: read failed.\n"); /* read failed */ + + return 1; /* return error */ + } + *temperature_raw = ((((uint32_t)(buf[3])) << 12) | + (((uint32_t)(buf[4])) << 4) | + ((uint32_t)buf[5] >> 4)); /* set temperature raw */ + res = a_bmp280_compensate_temperature(handle, *temperature_raw, temperature_c); /* compensate temperature */ + if (res != 0) + { + handle->debug_print("bmp280: compensate temperature failed.\n"); /* compensate temperature failed */ + + return 4; /* return error */ + } + } + + return 0; /* success return 0 */ +} + +/** + * @brief read the temperature and pressure data + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *temperature_raw pointer to a raw temperature buffer + * @param[out] *temperature_c pointer to a converted temperature buffer + * @param[out] *pressure_raw pointer to a raw pressure buffer + * @param[out] *pressure_pa pointer to a converted pressure buffer + * @return status code + * - 0 success + * - 1 read failed + * - 2 handle is NULL + * - 3 handle is not initialized + * - 4 compensate pressure failed + * - 5 read timeout + * @note none + */ +uint8_t bmp280_read_temperature_pressure(bmp280_handle_t *handle, uint32_t *temperature_raw, float *temperature_c, + uint32_t *pressure_raw, float *pressure_pa) +{ + uint8_t res; + uint8_t prev; + uint32_t timeout; + uint8_t buf[6]; + + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 1; /* return error */ + } + if ((prev & 0x3) == 3) /* normal mode */ + { + res = a_bmp280_iic_spi_read(handle, BMP280_REG_PRESS_MSB, buf, 6); /* read temperature and pressure */ + if (res != 0) + { + handle->debug_print("bmp280: read failed.\n"); /* read failed */ + + return 1; /* return error */ + } + *temperature_raw = ((((uint32_t)(buf[3])) << 12) | + (((uint32_t)(buf[4])) << 4) | + ((uint32_t)buf[5] >> 4)); /* set temperature raw */ + res = a_bmp280_compensate_temperature(handle, *temperature_raw, temperature_c); /* compensate temperature */ + if (res != 0) + { + handle->debug_print("bmp280: compensate temperature failed.\n"); /* compensate temperature failed */ + + return 4; /* return error */ + } + *pressure_raw = ((((int32_t)(buf[0])) << 12) | + (((int32_t)(buf[1])) << 4) | + (((int32_t)(buf[2])) >> 4)); /* set pressure raw */ + res = a_bmp280_compensate_pressure(handle, *pressure_raw, pressure_pa); /* compensate pressure */ + if (res != 0) + { + handle->debug_print("bmp280: compensate pressure failed.\n"); /* compensate pressure failed */ + + return 4; /* return error */ + } + } + else /* forced mode */ + { + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 1; /* return error */ + } + prev &= ~(3 << 0); /* clear settings */ + prev |= 0x01 << 0; /* set forced mode */ + if (a_bmp280_iic_spi_write(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* write ctrl meas */ + { + handle->debug_print("bmp280: write ctrl meas failed.\n"); /* write ctrl meas failed */ + + return 1; /* return error */ + } + timeout = 10 * 1000; /* set timeout */ + while (timeout != 0) /* check timeout */ + { + if (a_bmp280_iic_spi_read(handle, BMP280_REG_CTRL_MEAS, &prev, 1) != 0) /* read ctrl meas */ + { + handle->debug_print("bmp280: read ctrl meas failed.\n"); /* read ctrl meas failed */ + + return 1; /* return error */ + } + if ((prev & 0x03) == 0) /* if finished */ + { + break; /* break */ + } + handle->delay_ms(1); /* delay 1ms */ + timeout--; /* timeout-- */ + } + if (timeout == 0) /* check timeout */ + { + handle->debug_print("bmp280: read timeout.\n"); /* read timeout */ + + return 5; /* return error */ + } + res = a_bmp280_iic_spi_read(handle, BMP280_REG_PRESS_MSB, buf, 6); /* read temperature and pressure */ + if (res != 0) + { + handle->debug_print("bmp280: read failed.\n"); /* read failed */ + + return 1; /* return error */ + } + *temperature_raw = ((((uint32_t)(buf[3])) << 12) | + (((uint32_t)(buf[4])) << 4) | + ((uint32_t)buf[5] >> 4)); /* set temperature raw */ + res = a_bmp280_compensate_temperature(handle, *temperature_raw, temperature_c); /* compensate temperature */ + if (res != 0) + { + handle->debug_print("bmp280: compensate temperature failed.\n"); /* compensate temperature failed */ + + return 4; /* return error */ + } + *pressure_raw = ((((int32_t)(buf[0])) << 12) | + (((int32_t)(buf[1])) << 4) | + (((int32_t)(buf[2])) >> 4)); /* set pressure raw */ + res = a_bmp280_compensate_pressure(handle, *pressure_raw, pressure_pa); /* compensate pressure */ + if (res != 0) + { + handle->debug_print("bmp280: compensate pressure failed.\n"); /* compensate pressure failed */ + + return 4; /* return error */ + } + } + + return 0; /* success return 0 */ +} + +/** + * @brief set the chip register + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] reg iic register address + * @param[in] value data written to the register + * @return status code + * - 0 success + * - 1 write failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_set_reg(bmp280_handle_t *handle, uint8_t reg, uint8_t value) +{ + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + return a_bmp280_iic_spi_write(handle, reg, &value, 1); /* write register */ +} + +/** + * @brief get the chip register + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] reg iic register address + * @param[out] *value pointer to a read data buffer + * @return status code + * - 0 success + * - 1 read failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_reg(bmp280_handle_t *handle, uint8_t reg, uint8_t *value) +{ + if (handle == NULL) /* check handle */ + { + return 2; /* return error */ + } + if (handle->inited != 1) /* check handle initialization */ + { + return 3; /* return error */ + } + + return a_bmp280_iic_spi_read(handle, reg, value, 1); /* read register */ +} + +/** + * @brief get chip's information + * @param[out] *info pointer to a bmp280 info structure + * @return status code + * - 0 success + * - 2 handle is NULL + * @note none + */ +uint8_t bmp280_info(bmp280_info_t *info) +{ + if (info == NULL) /* check handle */ + { + return 2; /* return error */ + } + + memset(info, 0, sizeof(bmp280_info_t)); /* initialize bmp280 info structure */ + strncpy(info->chip_name, CHIP_NAME, 32); /* copy chip name */ + strncpy(info->manufacturer_name, MANUFACTURER_NAME, 32); /* copy manufacturer name */ + strncpy(info->interface, "IIC SPI", 8); /* copy interface name */ + info->supply_voltage_min_v = SUPPLY_VOLTAGE_MIN; /* set minimal supply voltage */ + info->supply_voltage_max_v = SUPPLY_VOLTAGE_MAX; /* set maximum supply voltage */ + info->max_current_ma = MAX_CURRENT; /* set maximum current */ + info->temperature_max = TEMPERATURE_MAX; /* set minimal temperature */ + info->temperature_min = TEMPERATURE_MIN; /* set maximum temperature */ + info->driver_version = DRIVER_VERSION; /* set driver version */ + + return 0; /* success return 0 */ +} diff --git a/Core/Bsp/driver_bmp280.h b/Core/Bsp/driver_bmp280.h new file mode 100644 index 0000000..f7d2709 --- /dev/null +++ b/Core/Bsp/driver_bmp280.h @@ -0,0 +1,669 @@ +/** + * Copyright (c) 2015 - present LibDriver All rights reserved + * + * The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * @file driver_bmp280.h + * @brief driver bmp280 header file + * @version 1.0.0 + * @author Shifeng Li + * @date 2024-01-15 + * + *

history

+ * + *
Date Version Author Description + *
2024/01/15 1.0 Shifeng Li first upload + *
+ */ + +#ifndef DRIVER_BMP280_H +#define DRIVER_BMP280_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C"{ +#endif + +/** + * @defgroup bmp280_driver bmp280 driver function + * @brief bmp280 driver modules + * @{ + */ + +/** + * @addtogroup bmp280_base_driver + * @{ + */ + +/** + * @brief bmp280 interface enumeration definition + */ +typedef enum +{ + BMP280_INTERFACE_IIC = 0x00, /**< iic interface */ + BMP280_INTERFACE_SPI = 0x01, /**< spi interface */ +} bmp280_interface_t; + +/** + * @brief bmp280 address enumeration definition + */ +typedef enum +{ + BMP280_ADDRESS_ADO_LOW = (0x76 << 1), /**< ADO is low */ + BMP280_ADDRESS_ADO_HIGH = (0x77 << 1), /**< ADO is HIGH */ +} bmp280_address_t; + +/** + * @brief bmp280 status enumeration definition + */ +typedef enum +{ + BMP280_STATUS_MEASURING = (1 << 3), /**< measuring */ + BMP280_STATUS_IM_UPDATE = (1 << 0), /**< im update */ +} bmp280_status_t; + +/** + * @brief bmp280 oversampling enumeration definition + */ +typedef enum +{ + BMP280_OVERSAMPLING_SKIP = 0x00, /**< oversampling x1 */ + BMP280_OVERSAMPLING_x1 = 0x01, /**< oversampling x1 */ + BMP280_OVERSAMPLING_x2 = 0x02, /**< oversampling x2 */ + BMP280_OVERSAMPLING_x4 = 0x03, /**< oversampling x4 */ + BMP280_OVERSAMPLING_x8 = 0x04, /**< oversampling x8 */ + BMP280_OVERSAMPLING_x16 = 0x05, /**< oversampling x16 */ +} bmp280_oversampling_t; + +/** + * @brief bmp280 mode enumeration definition + */ +typedef enum +{ + BMP280_MODE_SLEEP = 0x00, /**< sleep mode */ + BMP280_MODE_FORCED = 0x01, /**< forced mode */ + BMP280_MODE_NORMAL = 0x03, /**< normal mode */ +} bmp280_mode_t; + +/** + * @brief bmp280 standby time enumeration definition + */ +typedef enum +{ + BMP280_STANDBY_TIME_0P5_MS = 0x00, /**< 0.5ms */ + BMP280_STANDBY_TIME_62P5_MS = 0x01, /**< 62.5ms */ + BMP280_STANDBY_TIME_125_MS = 0x02, /**< 125ms */ + BMP280_STANDBY_TIME_250_MS = 0x03, /**< 250ms */ + BMP280_STANDBY_TIME_500_MS = 0x04, /**< 500ms */ + BMP280_STANDBY_TIME_1000_MS = 0x05, /**< 1000ms */ + BMP280_STANDBY_TIME_2000_MS = 0x06, /**< 2000ms */ + BMP280_STANDBY_TIME_4000_MS = 0x07, /**< 4000ms */ +} bmp280_standby_time_t; + +/** + * @brief bmp280 filter enumeration definition + */ +typedef enum +{ + BMP280_FILTER_OFF = 0x00, /**< off */ + BMP280_FILTER_COEFF_2 = 0x01, /**< coeff 2 */ + BMP280_FILTER_COEFF_4 = 0x02, /**< coeff 4 */ + BMP280_FILTER_COEFF_8 = 0x03, /**< coeff 8 */ + BMP280_FILTER_COEFF_16 = 0x04, /**< coeff 16 */ +} bmp280_filter_t; + +/** + * @brief bmp280 spi wire enumeration definition + */ +typedef enum +{ + BMP280_SPI_WIRE_4 = 0x00, /**< 4 wire */ + BMP280_SPI_WIRE_3 = 0x01, /**< 3 wire */ +} bmp280_spi_wire_t; + +/** + * @brief bmp280 handle structure definition + */ +typedef struct bmp280_handle_s +{ + uint8_t iic_addr; /**< iic device address */ + uint8_t (*iic_init)(void); /**< point to an iic_init function address */ + uint8_t (*iic_deinit)(void); /**< point to an iic_deinit function address */ + uint8_t (*iic_read)(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len); /**< point to an iic_read function address */ + uint8_t (*iic_write)(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len); /**< point to an iic_write function address */ + uint8_t (*spi_init)(void); /**< point to a spi_init function address */ + uint8_t (*spi_deinit)(void); /**< point to a spi_deinit function address */ + uint8_t (*spi_read)(uint8_t reg, uint8_t *buf, uint16_t len); /**< point to a spi_read function address */ + uint8_t (*spi_write)(uint8_t reg, uint8_t *buf, uint16_t len); /**< point to a spi_write function address */ + void (*delay_ms)(uint32_t ms); /**< point to a delay_ms function address */ + void (*debug_print)(const char *const fmt, ...); /**< point to a debug_print function address */ + uint8_t inited; /**< inited flag */ + uint8_t iic_spi; /**< iic spi interface */ + uint16_t t1; /**< t1 register */ + int16_t t2; /**< t2 register */ + int16_t t3; /**< t3 register */ + uint16_t p1; /**< p1 register */ + int16_t p2; /**< p2 register */ + int16_t p3; /**< p3 register */ + int16_t p4; /**< p4 register */ + int16_t p5; /**< p5 register */ + int16_t p6; /**< p6 register */ + int16_t p7; /**< p7 register */ + int16_t p8; /**< p8 register */ + int16_t p9; /**< p9 register */ + int32_t t_fine; /**< inner register */ +} bmp280_handle_t; + +/** + * @brief bmp280 information structure definition + */ +typedef struct bmp280_info_s +{ + char chip_name[32]; /**< chip name */ + char manufacturer_name[32]; /**< manufacturer name */ + char interface[8]; /**< chip interface name */ + float supply_voltage_min_v; /**< chip min supply voltage */ + float supply_voltage_max_v; /**< chip max supply voltage */ + float max_current_ma; /**< chip max current */ + float temperature_min; /**< chip min operating temperature */ + float temperature_max; /**< chip max operating temperature */ + uint32_t driver_version; /**< driver version */ +} bmp280_info_t; + +/** + * @} + */ + +/** + * @defgroup bmp280_link_driver bmp280 link driver function + * @brief bmp280 link driver modules + * @ingroup bmp280_driver + * @{ + */ + +/** + * @brief initialize bmp280_handle_t structure + * @param[in] HANDLE pointer to a bmp280 handle structure + * @param[in] STRUCTURE bmp280_handle_t + * @note none + */ +#define DRIVER_BMP280_LINK_INIT(HANDLE, STRUCTURE) memset(HANDLE, 0, sizeof(STRUCTURE)) + +/** + * @brief link iic_init function + * @param[in] HANDLE pointer to a bmp280 handle structure + * @param[in] FUC pointer to an iic_init function address + * @note none + */ +#define DRIVER_BMP280_LINK_IIC_INIT(HANDLE, FUC) (HANDLE)->iic_init = FUC + +/** + * @brief link iic_deinit function + * @param[in] HANDLE pointer to a bmp280 handle structure + * @param[in] FUC pointer to an iic_deinit function address + * @note none + */ +#define DRIVER_BMP280_LINK_IIC_DEINIT(HANDLE, FUC) (HANDLE)->iic_deinit = FUC + +/** + * @brief link iic_read function + * @param[in] HANDLE pointer to a bmp280 handle structure + * @param[in] FUC pointer to an iic_read function address + * @note none + */ +#define DRIVER_BMP280_LINK_IIC_READ(HANDLE, FUC) (HANDLE)->iic_read = FUC + +/** + * @brief link iic_write function + * @param[in] HANDLE pointer to a bmp280 handle structure + * @param[in] FUC pointer to an iic_write function address + * @note none + */ +#define DRIVER_BMP280_LINK_IIC_WRITE(HANDLE, FUC) (HANDLE)->iic_write = FUC + +/** + * @brief link spi_init function + * @param[in] HANDLE pointer to a bmp280 handle structure + * @param[in] FUC pointer to a spi_init function address + * @note none + */ +#define DRIVER_BMP280_LINK_SPI_INIT(HANDLE, FUC) (HANDLE)->spi_init = FUC + +/** + * @brief link spi_deinit function + * @param[in] HANDLE pointer to a bmp280 handle structure + * @param[in] FUC pointer to a spi_deinit function address + * @note none + */ +#define DRIVER_BMP280_LINK_SPI_DEINIT(HANDLE, FUC) (HANDLE)->spi_deinit = FUC + +/** + * @brief link spi_read function + * @param[in] HANDLE pointer to a bmp280 handle structure + * @param[in] FUC pointer to a spi_read function address + * @note none + */ +#define DRIVER_BMP280_LINK_SPI_READ(HANDLE, FUC) (HANDLE)->spi_read = FUC + +/** + * @brief link spi_write function + * @param[in] HANDLE pointer to a bmp280 handle structure + * @param[in] FUC pointer to a spi_write function address + * @note none + */ +#define DRIVER_BMP280_LINK_SPI_WRITE(HANDLE, FUC) (HANDLE)->spi_write = FUC + +/** + * @brief link delay_ms function + * @param[in] HANDLE pointer to a bmp280 handle structure + * @param[in] FUC pointer to a delay_ms function address + * @note none + */ +#define DRIVER_BMP280_LINK_DELAY_MS(HANDLE, FUC) (HANDLE)->delay_ms = FUC + +/** + * @brief link debug_print function + * @param[in] HANDLE pointer to a bmp280 handle structure + * @param[in] FUC pointer to a debug_print function address + * @note none + */ +#define DRIVER_BMP280_LINK_DEBUG_PRINT(HANDLE, FUC) (HANDLE)->debug_print = FUC + +/** + * @} + */ + +/** + * @defgroup bmp280_base_driver bmp280 base driver function + * @brief bmp280 base driver modules + * @ingroup bmp280_driver + * @{ + */ + +/** + * @brief get chip's information + * @param[out] *info pointer to a bmp280 info structure + * @return status code + * - 0 success + * - 2 handle is NULL + * @note none + */ +uint8_t bmp280_info(bmp280_info_t *info); + +/** + * @brief set the interface + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] interface chip interface + * @return status code + * - 0 success + * - 2 handle is NULL + * @note none + */ +uint8_t bmp280_set_interface(bmp280_handle_t *handle, bmp280_interface_t interface); + +/** + * @brief get the interface + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *interface pointer to a chip interface buffer + * @return status code + * - 0 success + * - 2 handle is NULL + * @note none + */ +uint8_t bmp280_get_interface(bmp280_handle_t *handle, bmp280_interface_t *interface); + +/** + * @brief set the iic address pin + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] addr_pin iic address pin + * @return status code + * - 0 success + * - 2 handle is NULL + * @note none + */ +uint8_t bmp280_set_addr_pin(bmp280_handle_t *handle, bmp280_address_t addr_pin); + +/** + * @brief get the iic address pin + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *addr_pin pointer to an iic address pin buffer + * @return status code + * - 0 success + * - 2 handle is NULL + * @note none + */ +uint8_t bmp280_get_addr_pin(bmp280_handle_t *handle, bmp280_address_t *addr_pin); + +/** + * @brief initialize the chip + * @param[in] *handle pointer to a bmp280 handle structure + * @return status code + * - 0 success + * - 1 iic or spi initialization failed + * - 2 handle is NULL + * - 3 linked functions is NULL + * - 4 id is error + * - 5 get nvm calibration failed + * - 6 read calibration failed + * @note none + */ +uint8_t bmp280_init(bmp280_handle_t *handle); + +/** + * @brief close the chip + * @param[in] *handle pointer to a bmp280 handle structure + * @return status code + * - 0 success + * - 1 iic deinit failed + * - 2 handle is NULL + * - 3 handle is not initialized + * - 4 power down failed + * @note none + */ +uint8_t bmp280_deinit(bmp280_handle_t *handle); + +/** + * @brief read the temperature and pressure data + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *temperature_raw pointer to a raw temperature buffer + * @param[out] *temperature_c pointer to a converted temperature buffer + * @param[out] *pressure_raw pointer to a raw pressure buffer + * @param[out] *pressure_pa pointer to a converted pressure buffer + * @return status code + * - 0 success + * - 1 read failed + * - 2 handle is NULL + * - 3 handle is not initialized + * - 4 compensate pressure failed + * - 5 read timeout + * @note none + */ +uint8_t bmp280_read_temperature_pressure(bmp280_handle_t *handle, uint32_t *temperature_raw, float *temperature_c, + uint32_t *pressure_raw, float *pressure_pa); + +/** + * @brief read the pressure data + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *pressure_raw pointer to a raw pressure buffer + * @param[out] *pressure_pa pointer to a converted pressure buffer + * @return status code + * - 0 success + * - 1 pressure read failed + * - 2 handle is NULL + * - 3 handle is not initialized + * - 4 compensate pressure failed + * - 5 read timeout + * @note none + */ +uint8_t bmp280_read_pressure(bmp280_handle_t *handle, uint32_t *pressure_raw, float *pressure_pa); + +/** + * @brief read the temperature data + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *temperature_raw pointer to a raw temperature buffer + * @param[out] *temperature_c pointer to a converted temperature buffer + * @return status code + * - 0 success + * - 1 temperature read failed + * - 2 handle is NULL + * - 3 handle is not initialized + * - 4 compensate pressure failed + * - 5 read timeout + * @note none + */ +uint8_t bmp280_read_temperature(bmp280_handle_t *handle, uint32_t *temperature_raw, float *temperature_c); + +/** + * @brief soft reset + * @param[in] *handle pointer to a bmp280 handle structure + * @return status code + * - 0 success + * - 1 soft reset failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_soft_reset(bmp280_handle_t *handle); + +/** + * @brief get status + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *status pointer to a status buffer + * @return status code + * - 0 success + * - 1 get status failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_status(bmp280_handle_t *handle, uint8_t *status); + +/** + * @brief set temperatue oversampling + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] oversampling temperatue oversampling + * @return status code + * - 0 success + * - 1 set temperatue oversampling failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_set_temperatue_oversampling(bmp280_handle_t *handle, bmp280_oversampling_t oversampling); + +/** + * @brief get temperatue oversampling + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *oversampling pointer to a oversampling buffer + * @return status code + * - 0 success + * - 1 get temperatue oversampling failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_temperatue_oversampling(bmp280_handle_t *handle, bmp280_oversampling_t *oversampling); + +/** + * @brief set pressure oversampling + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] oversampling pressure oversampling + * @return status code + * - 0 success + * - 1 set pressure oversampling failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_set_pressure_oversampling(bmp280_handle_t *handle, bmp280_oversampling_t oversampling); + +/** + * @brief get pressure oversampling + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *oversampling pointer to a oversampling buffer + * @return status code + * - 0 success + * - 1 get pressure oversampling failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_pressure_oversampling(bmp280_handle_t *handle, bmp280_oversampling_t *oversampling); + +/** + * @brief set mode + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] mode chip mode + * @return status code + * - 0 success + * - 1 set mode failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_set_mode(bmp280_handle_t *handle, bmp280_mode_t mode); + +/** + * @brief get mode + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *mode pointer to a mode buffer + * @return status code + * - 0 success + * - 1 get mode failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_mode(bmp280_handle_t *handle, bmp280_mode_t *mode); + +/** + * @brief set standby time + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] standby_time standby time + * @return status code + * - 0 success + * - 1 set standby time failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_set_standby_time(bmp280_handle_t *handle, bmp280_standby_time_t standby_time); + +/** + * @brief get standby time + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *standby_time pointer to a standby time buffer + * @return status code + * - 0 success + * - 1 get standby time failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_standby_time(bmp280_handle_t *handle, bmp280_standby_time_t *standby_time); + +/** + * @brief set filter + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] filter input filter + * @return status code + * - 0 success + * - 1 set filter failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_set_filter(bmp280_handle_t *handle, bmp280_filter_t filter); + +/** + * @brief get filter + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *filter pointer to a filter buffer + * @return status code + * - 0 success + * - 1 get filter failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_filter(bmp280_handle_t *handle, bmp280_filter_t *filter); + +/** + * @brief set spi wire + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] spi spi wire + * @return status code + * - 0 success + * - 1 set spi wire failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_set_spi_wire(bmp280_handle_t *handle, bmp280_spi_wire_t spi); + +/** + * @brief get spi wire + * @param[in] *handle pointer to a bmp280 handle structure + * @param[out] *spi pointer to a spi wire buffer + * @return status code + * - 0 success + * - 1 get spi wire failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_spi_wire(bmp280_handle_t *handle, bmp280_spi_wire_t *spi); + +/** + * @} + */ + +/** + * @defgroup bmp280_extern_driver bmp280 extern driver function + * @brief bmp280 extern driver modules + * @ingroup bmp280_driver + * @{ + */ + +/** + * @brief set the chip register + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] reg iic register address + * @param[in] value data written to the register + * @return status code + * - 0 success + * - 1 write failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_set_reg(bmp280_handle_t *handle, uint8_t reg, uint8_t value); + +/** + * @brief get the chip register + * @param[in] *handle pointer to a bmp280 handle structure + * @param[in] reg iic register address + * @param[out] *value pointer to a read data buffer + * @return status code + * - 0 success + * - 1 read failed + * - 2 handle is NULL + * - 3 handle is not initialized + * @note none + */ +uint8_t bmp280_get_reg(bmp280_handle_t *handle, uint8_t reg, uint8_t *value); + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Core/Bsp/driver_bmp280_interface.c b/Core/Bsp/driver_bmp280_interface.c new file mode 100644 index 0000000..927ce9d --- /dev/null +++ b/Core/Bsp/driver_bmp280_interface.c @@ -0,0 +1,180 @@ +/** + * @file driver_bmp280_interface.c + * @brief BMP280 driver interface for STM32 HAL (I2C1) + */ + +#include "driver_bmp280_interface.h" +#include "i2c.h" +#include "usart.h" +#include +#include +#include + +/** + * @brief interface iic bus init + * @return status code + * - 0 success + * - 1 iic init failed + * @note none + */ +uint8_t bmp280_interface_iic_init(void) +{ + /* I2C is initialized in MX_I2C1_Init() */ + return 0; +} + +/** + * @brief interface iic bus deinit + * @return status code + * - 0 success + * - 1 iic deinit failed + * @note none + */ +uint8_t bmp280_interface_iic_deinit(void) +{ + /* I2C deinit if needed */ + return 0; +} + +/** + * @brief interface iic bus read + * @param[in] addr iic device write address + * @param[in] reg iic register address + * @param[out] *buf pointer to a data buffer + * @param[in] len length of the data buffer + * @return status code + * - 0 success + * - 1 read failed + * @note none + */ +uint8_t bmp280_interface_iic_read(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len) +{ + HAL_StatusTypeDef status; + + /* Send register address */ + status = HAL_I2C_Master_Transmit(&hi2c1, addr, ®, 1, 1000); + if (status != HAL_OK) + { + return 1; + } + + /* Read data */ + status = HAL_I2C_Master_Receive(&hi2c1, addr | 0x01, buf, len, 1000); + if (status != HAL_OK) + { + return 1; + } + + return 0; +} + +/** + * @brief interface iic bus write + * @param[in] addr iic device write address + * @param[in] reg iic register address + * @param[in] *buf pointer to a data buffer + * @param[in] len length of the data buffer + * @return status code + * - 0 success + * - 1 write failed + * @note none + */ +uint8_t bmp280_interface_iic_write(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len) +{ + HAL_StatusTypeDef status; + uint8_t tx_buf[256]; + + tx_buf[0] = reg; + for (uint16_t i = 0; i < len; i++) + { + tx_buf[i + 1] = buf[i]; + } + + status = HAL_I2C_Master_Transmit(&hi2c1, addr, tx_buf, len + 1, 1000); + if (status != HAL_OK) + { + return 1; + } + + return 0; +} + +/** + * @brief interface spi bus init + * @return status code + * - 0 success + * - 1 spi init failed + * @note none + */ +uint8_t bmp280_interface_spi_init(void) +{ + return 0; +} + +/** + * @brief interface spi bus deinit + * @return status code + * - 0 success + * - 1 spi deinit failed + * @note none + */ +uint8_t bmp280_interface_spi_deinit(void) +{ + return 0; +} + +/** + * @brief interface spi bus read + * @param[in] reg register address + * @param[out] *buf pointer to a data buffer + * @param[in] len length of data buffer + * @return status code + * - 0 success + * - 1 read failed + * @note none + */ +uint8_t bmp280_interface_spi_read(uint8_t reg, uint8_t *buf, uint16_t len) +{ + return 0; +} + +/** + * @brief interface spi bus write + * @param[in] reg register address + * @param[in] *buf pointer to a data buffer + * @param[in] len length of data buffer + * @return status code + * - 0 success + * - 1 write failed + * @note none + */ +uint8_t bmp280_interface_spi_write(uint8_t reg, uint8_t *buf, uint16_t len) +{ + return 0; +} + +/** + * @brief interface delay ms + * @param[in] ms time + * @note none + */ +void bmp280_interface_delay_ms(uint32_t ms) +{ + HAL_Delay(ms); +} + +/** + * @brief interface print format data + * @param[in] fmt format data + * @note none + */ +void bmp280_interface_debug_print(const char *const fmt, ...) +{ + char buf[256]; + va_list args; + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + HAL_UART_Transmit(&huart2, (uint8_t*)buf, strlen(buf), 1000); +} diff --git a/Core/Bsp/driver_bmp280_interface.h b/Core/Bsp/driver_bmp280_interface.h new file mode 100644 index 0000000..e7134c3 --- /dev/null +++ b/Core/Bsp/driver_bmp280_interface.h @@ -0,0 +1,161 @@ +/** + * Copyright (c) 2015 - present LibDriver All rights reserved + * + * The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * @file driver_bmp280_interface.h + * @brief driver bmp280 interface header file + * @version 1.0.0 + * @author Shifeng Li + * @date 2024-01-15 + * + *

history

+ * + *
Date Version Author Description + *
2024/01/15 1.0 Shifeng Li first upload + *
+ */ + +#ifndef DRIVER_BMP280_INTERFACE_H +#define DRIVER_BMP280_INTERFACE_H + +#include "driver_bmp280.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +/** + * @defgroup bmp280_interface_driver bmp280 interface driver function + * @brief bmp280 interface driver modules + * @ingroup bmp280_driver + * @{ + */ + +/** + * @brief interface iic bus init + * @return status code + * - 0 success + * - 1 iic init failed + * @note none + */ +uint8_t bmp280_interface_iic_init(void); + +/** + * @brief interface iic bus deinit + * @return status code + * - 0 success + * - 1 iic deinit failed + * @note none + */ +uint8_t bmp280_interface_iic_deinit(void); + +/** + * @brief interface iic bus read + * @param[in] addr iic device write address + * @param[in] reg iic register address + * @param[out] *buf pointer to a data buffer + * @param[in] len length of the data buffer + * @return status code + * - 0 success + * - 1 read failed + * @note none + */ +uint8_t bmp280_interface_iic_read(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len); + +/** + * @brief interface iic bus write + * @param[in] addr iic device write address + * @param[in] reg iic register address + * @param[in] *buf pointer to a data buffer + * @param[in] len length of the data buffer + * @return status code + * - 0 success + * - 1 write failed + * @note none + */ +uint8_t bmp280_interface_iic_write(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len); + +/** + * @brief interface spi bus init + * @return status code + * - 0 success + * - 1 spi init failed + * @note none + */ +uint8_t bmp280_interface_spi_init(void); + +/** + * @brief interface spi bus deinit + * @return status code + * - 0 success + * - 1 spi deinit failed + * @note none + */ +uint8_t bmp280_interface_spi_deinit(void); + +/** + * @brief interface spi bus read + * @param[in] reg register address + * @param[out] *buf pointer to a data buffer + * @param[in] len length of data buffer + * @return status code + * - 0 success + * - 1 read failed + * @note none + */ +uint8_t bmp280_interface_spi_read(uint8_t reg, uint8_t *buf, uint16_t len); + +/** + * @brief interface spi bus write + * @param[in] reg register address + * @param[in] *buf pointer to a data buffer + * @param[in] len length of data buffer + * @return status code + * - 0 success + * - 1 write failed + * @note none + */ +uint8_t bmp280_interface_spi_write(uint8_t reg, uint8_t *buf, uint16_t len); + +/** + * @brief interface delay ms + * @param[in] ms time + * @note none + */ +void bmp280_interface_delay_ms(uint32_t ms); + +/** + * @brief interface print format data + * @param[in] fmt format data + * @note none + */ +void bmp280_interface_debug_print(const char *const fmt, ...); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Core/Inc/FreeRTOSConfig.h b/Core/Inc/FreeRTOSConfig.h new file mode 100644 index 0000000..0266984 --- /dev/null +++ b/Core/Inc/FreeRTOSConfig.h @@ -0,0 +1,139 @@ +/* USER CODE BEGIN Header */ +/* + * FreeRTOS Kernel V10.3.1 + * Portion Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Portion Copyright (C) 2019 StMicroelectronics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ +/* USER CODE END Header */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * These parameters and more are described within the 'configuration' section of the + * FreeRTOS API documentation available on the FreeRTOS.org web site. + * + * See http://www.freertos.org/a00110.html + *----------------------------------------------------------*/ + +/* USER CODE BEGIN Includes */ +/* Section where include file can be added */ +/* USER CODE END Includes */ + +/* Ensure definitions are only used by the compiler, and not by the assembler. */ +#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) + #include + extern uint32_t SystemCoreClock; +#endif +#define configENABLE_FPU 0 +#define configENABLE_MPU 0 + +#define configUSE_PREEMPTION 1 +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configCPU_CLOCK_HZ ( SystemCoreClock ) +#define configTICK_RATE_HZ ((TickType_t)1000) +#define configMAX_PRIORITIES ( 7 ) +#define configMINIMAL_STACK_SIZE ((uint16_t)128) +#define configTOTAL_HEAP_SIZE ((size_t)3072) +#define configMAX_TASK_NAME_LEN ( 16 ) +#define configUSE_16_BIT_TICKS 0 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +/* USER CODE BEGIN MESSAGE_BUFFER_LENGTH_TYPE */ +/* Defaults to size_t for backward compatibility, but can be changed + if lengths will always be less than the number of bytes in a size_t. */ +#define configMESSAGE_BUFFER_LENGTH_TYPE size_t +/* USER CODE END MESSAGE_BUFFER_LENGTH_TYPE */ + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 0 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 + +/* Cortex-M specific definitions. */ +#ifdef __NVIC_PRIO_BITS + /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ + #define configPRIO_BITS __NVIC_PRIO_BITS +#else + #define configPRIO_BITS 4 +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" +function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +/* Normal assert() semantics without relying on the provision of an assert.h +header file. */ +/* USER CODE BEGIN 1 */ +#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );} +/* USER CODE END 1 */ + +/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS +standard names. */ +#define vPortSVCHandler SVC_Handler +#define xPortPendSVHandler PendSV_Handler + +/* IMPORTANT: This define is commented when used with STM32Cube firmware, when the timebase source is SysTick, + to prevent overwriting SysTick_Handler defined within STM32Cube HAL */ + +#define xPortSysTickHandler SysTick_Handler + +/* USER CODE BEGIN Defines */ +/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */ +/* USER CODE END Defines */ + +#endif /* FREERTOS_CONFIG_H */ diff --git a/Core/Inc/dma.h b/Core/Inc/dma.h new file mode 100644 index 0000000..afad30d --- /dev/null +++ b/Core/Inc/dma.h @@ -0,0 +1,52 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file dma.h + * @brief This file contains all the function prototypes for + * the dma.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 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 __DMA_H__ +#define __DMA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* DMA memory to memory transfer handles -------------------------------------*/ + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_DMA_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __DMA_H__ */ + diff --git a/Core/Inc/gpio.h b/Core/Inc/gpio.h new file mode 100644 index 0000000..3c91c4d --- /dev/null +++ b/Core/Inc/gpio.h @@ -0,0 +1,49 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file gpio.h + * @brief This file contains all the function prototypes for + * the gpio.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 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 __GPIO_H__ +#define __GPIO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_GPIO_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif +#endif /*__ GPIO_H__ */ + diff --git a/Core/Inc/i2c.h b/Core/Inc/i2c.h new file mode 100644 index 0000000..29bebff --- /dev/null +++ b/Core/Inc/i2c.h @@ -0,0 +1,55 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file i2c.h + * @brief This file contains all the function prototypes for + * the i2c.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 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 __I2C_H__ +#define __I2C_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +extern I2C_HandleTypeDef hi2c1; + +extern I2C_HandleTypeDef hi2c2; + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_I2C1_Init(void); +void MX_I2C2_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __I2C_H__ */ + diff --git a/Core/Inc/main.h b/Core/Inc/main.h new file mode 100644 index 0000000..a45ed1e --- /dev/null +++ b/Core/Inc/main.h @@ -0,0 +1,75 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.h + * @brief : Header for main.c file. + * This file contains the common defines of the application. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 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 __MAIN_H +#define __MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f1xx_hal.h" + +/* 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 Error_Handler(void); + +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +/* Private defines -----------------------------------------------------------*/ +#define LED_Pin GPIO_PIN_13 +#define LED_GPIO_Port GPIOC +#define FAN_Pin GPIO_PIN_14 +#define FAN_GPIO_Port GPIOB +#define LIGHT_Pin GPIO_PIN_15 +#define LIGHT_GPIO_Port GPIOB + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MAIN_H */ diff --git a/Core/Inc/stm32f1xx_hal_conf.h b/Core/Inc/stm32f1xx_hal_conf.h new file mode 100644 index 0000000..c37ea46 --- /dev/null +++ b/Core/Inc/stm32f1xx_hal_conf.h @@ -0,0 +1,391 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f1xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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_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_CRYP_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_FLASH_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +/*#define HAL_I2S_MODULE_ENABLED */ +/*#define HAL_IRDA_MODULE_ENABLED */ +/*#define HAL_IWDG_MODULE_ENABLED */ +/*#define HAL_NOR_MODULE_ENABLED */ +/*#define HAL_NAND_MODULE_ENABLED */ +/*#define HAL_PCCARD_MODULE_ENABLED */ +/*#define HAL_PCD_MODULE_ENABLED */ +/*#define HAL_HCD_MODULE_ENABLED */ +/*#define HAL_PWR_MODULE_ENABLED */ +/*#define HAL_RCC_MODULE_ENABLED */ +/*#define HAL_RTC_MODULE_ENABLED */ +/*#define HAL_SD_MODULE_ENABLED */ +/*#define HAL_MMC_MODULE_ENABLED */ +/*#define HAL_SDRAM_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_CORTEX_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_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) + #define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ +#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 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 15U /*!< tick interrupt priority (lowest by default) */ +#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 /* 4 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 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)0x00) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x01) /*!< 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)0x10U) /*!< PHY status register Offset */ + +#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex 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 0U + +/* 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 */ + diff --git a/Core/Inc/stm32f1xx_it.h b/Core/Inc/stm32f1xx_it.h new file mode 100644 index 0000000..85a56ee --- /dev/null +++ b/Core/Inc/stm32f1xx_it.h @@ -0,0 +1,67 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f1xx_it.h + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 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 DebugMon_Handler(void); +void DMA1_Channel4_IRQHandler(void); +void DMA1_Channel5_IRQHandler(void); +void TIM4_IRQHandler(void); +void USART1_IRQHandler(void); +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F1xx_IT_H */ diff --git a/Core/Inc/usart.h b/Core/Inc/usart.h new file mode 100644 index 0000000..3ccb49d --- /dev/null +++ b/Core/Inc/usart.h @@ -0,0 +1,55 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file usart.h + * @brief This file contains all the function prototypes for + * the usart.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 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 __USART_H__ +#define __USART_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +extern UART_HandleTypeDef huart1; + +extern UART_HandleTypeDef huart2; + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_USART1_UART_Init(void); +void MX_USART2_UART_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USART_H__ */ + diff --git a/Core/Src/dma.c b/Core/Src/dma.c new file mode 100644 index 0000000..c6ba294 --- /dev/null +++ b/Core/Src/dma.c @@ -0,0 +1,58 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file dma.c + * @brief This file provides code for the configuration + * of all the requested memory to memory DMA transfers. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 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 "dma.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/*----------------------------------------------------------------------------*/ +/* Configure DMA */ +/*----------------------------------------------------------------------------*/ + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/** + * Enable DMA controller clock + */ +void MX_DMA_Init(void) +{ + + /* DMA controller clock enable */ + __HAL_RCC_DMA1_CLK_ENABLE(); + + /* DMA interrupt init */ + /* DMA1_Channel4_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn); + /* DMA1_Channel5_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn); + +} + +/* USER CODE BEGIN 2 */ + +/* USER CODE END 2 */ + diff --git a/Core/Src/freertos.c b/Core/Src/freertos.c new file mode 100644 index 0000000..0ee1be1 --- /dev/null +++ b/Core/Src/freertos.c @@ -0,0 +1,168 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * File Name : freertos.c + * Description : Code for freertos applications + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 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 "FreeRTOS.h" +#include "task.h" +#include "main.h" +#include "cmsis_os.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "usart.h" +#include "string.h" +#include "bsp_relay.h" +#include "bsp_bmp280.h" +#include "bsp_uart.h" +#include "bsp_cmd.h" + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* 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 Variables */ + +/* USER CODE END Variables */ +osThreadId defaultTaskHandle; + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN FunctionPrototypes */ + +/* USER CODE END FunctionPrototypes */ + +void StartDefaultTask(void const * argument); + +void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */ + +/* GetIdleTaskMemory prototype (linked to static allocation support) */ +void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ); + +/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */ +static StaticTask_t xIdleTaskTCBBuffer; +static StackType_t xIdleStack[configMINIMAL_STACK_SIZE]; + +void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) +{ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer; + *ppxIdleTaskStackBuffer = &xIdleStack[0]; + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; + /* place for user code */ +} +/* USER CODE END GET_IDLE_TASK_MEMORY */ + +/** + * @brief FreeRTOS initialization + * @param None + * @retval None + */ +void MX_FREERTOS_Init(void) { + /* USER CODE BEGIN Init */ + BSP_Relay_Init(); + BSP_BMP280_Init(); + /* USER CODE END Init */ + + /* USER CODE BEGIN RTOS_MUTEX */ + /* add mutexes, ... */ + /* USER CODE END RTOS_MUTEX */ + + /* USER CODE BEGIN RTOS_SEMAPHORES */ + /* add semaphores, ... */ + /* USER CODE END RTOS_SEMAPHORES */ + + /* USER CODE BEGIN RTOS_TIMERS */ + /* start timers, add new ones, ... */ + /* USER CODE END RTOS_TIMERS */ + + /* USER CODE BEGIN RTOS_QUEUES */ + /* add queues, ... */ + /* USER CODE END RTOS_QUEUES */ + + /* Create the thread(s) */ + /* definition and creation of defaultTask */ + osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 512); + defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL); + + /* USER CODE BEGIN RTOS_THREADS */ + /* add threads, ... */ + /* USER CODE END RTOS_THREADS */ + +} + +/* USER CODE BEGIN Header_StartDefaultTask */ +/** + * @brief Function implementing the defaultTask thread. + * @param argument: Not used + * @retval None + */ +/* USER CODE END Header_StartDefaultTask */ +void StartDefaultTask(void const * argument) +{ + /* USER CODE BEGIN StartDefaultTask */ + bsp_bmp280_data_t sensor_data; + char tx_buf[128]; + + /* Init UART1 for MQTT */ + BSP_UART1_Init(); + + /* Infinite loop */ + for(;;) + { + /* Read BMP280 sensor data */ + if (BSP_BMP280_Read(&sensor_data) == 0) + { + snprintf(tx_buf, sizeof(tx_buf), "Temp: %.2f C, Press: %.2f hPa\r\n", + sensor_data.temperature, sensor_data.pressure / 100.0f); + + /* Auto control FAN based on temperature */ + BSP_FAN_AutoControl(sensor_data.temperature); + } + else + { + snprintf(tx_buf, sizeof(tx_buf), "BMP280 Read Error\r\n"); + } + HAL_UART_Transmit(&huart2, (uint8_t*)tx_buf, strlen(tx_buf), 1000); + + /* Process UART1 commands (blocking poll) */ + BSP_UART1_Process(); + + HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); + osDelay(1000); + } + /* USER CODE END StartDefaultTask */ +} + +/* Private application code --------------------------------------------------*/ +/* USER CODE BEGIN Application */ + +/* USER CODE END Application */ + diff --git a/Core/Src/gpio.c b/Core/Src/gpio.c new file mode 100644 index 0000000..a59ce37 --- /dev/null +++ b/Core/Src/gpio.c @@ -0,0 +1,77 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file gpio.c + * @brief This file provides code for the configuration + * of all used GPIO pins. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 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 "gpio.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/*----------------------------------------------------------------------------*/ +/* Configure GPIO */ +/*----------------------------------------------------------------------------*/ +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/** Configure pins as + * Analog + * Input + * Output + * EVENT_OUT + * EXTI +*/ +void MX_GPIO_Init(void) +{ + + GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOB, FAN_Pin|LIGHT_Pin, GPIO_PIN_SET); + + /*Configure GPIO pin : LED_Pin */ + GPIO_InitStruct.Pin = LED_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct); + + /*Configure GPIO pins : FAN_Pin LIGHT_Pin */ + GPIO_InitStruct.Pin = FAN_Pin|LIGHT_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + +} + +/* USER CODE BEGIN 2 */ + +/* USER CODE END 2 */ diff --git a/Core/Src/i2c.c b/Core/Src/i2c.c new file mode 100644 index 0000000..dd48db3 --- /dev/null +++ b/Core/Src/i2c.c @@ -0,0 +1,186 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file i2c.c + * @brief This file provides code for the configuration + * of the I2C instances. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 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 "i2c.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +I2C_HandleTypeDef hi2c1; +I2C_HandleTypeDef hi2c2; + +/* I2C1 init function */ +void MX_I2C1_Init(void) +{ + + /* USER CODE BEGIN I2C1_Init 0 */ + + /* USER CODE END I2C1_Init 0 */ + + /* USER CODE BEGIN I2C1_Init 1 */ + + /* USER CODE END I2C1_Init 1 */ + hi2c1.Instance = I2C1; + hi2c1.Init.ClockSpeed = 100000; + hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; + hi2c1.Init.OwnAddress1 = 0; + hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c1.Init.OwnAddress2 = 0; + hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + if (HAL_I2C_Init(&hi2c1) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN I2C1_Init 2 */ + + /* USER CODE END I2C1_Init 2 */ + +} +/* I2C2 init function */ +void MX_I2C2_Init(void) +{ + + /* USER CODE BEGIN I2C2_Init 0 */ + + /* USER CODE END I2C2_Init 0 */ + + /* USER CODE BEGIN I2C2_Init 1 */ + + /* USER CODE END I2C2_Init 1 */ + hi2c2.Instance = I2C2; + hi2c2.Init.ClockSpeed = 100000; + hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2; + hi2c2.Init.OwnAddress1 = 0; + hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c2.Init.OwnAddress2 = 0; + hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + if (HAL_I2C_Init(&hi2c2) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN I2C2_Init 2 */ + + /* USER CODE END I2C2_Init 2 */ + +} + +void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle) +{ + + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(i2cHandle->Instance==I2C1) + { + /* USER CODE BEGIN I2C1_MspInit 0 */ + + /* USER CODE END I2C1_MspInit 0 */ + + __HAL_RCC_GPIOB_CLK_ENABLE(); + /**I2C1 GPIO Configuration + PB6 ------> I2C1_SCL + PB7 ------> I2C1_SDA + */ + GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* I2C1 clock enable */ + __HAL_RCC_I2C1_CLK_ENABLE(); + /* USER CODE BEGIN I2C1_MspInit 1 */ + + /* USER CODE END I2C1_MspInit 1 */ + } + else if(i2cHandle->Instance==I2C2) + { + /* USER CODE BEGIN I2C2_MspInit 0 */ + + /* USER CODE END I2C2_MspInit 0 */ + + __HAL_RCC_GPIOB_CLK_ENABLE(); + /**I2C2 GPIO Configuration + PB10 ------> I2C2_SCL + PB11 ------> I2C2_SDA + */ + GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* I2C2 clock enable */ + __HAL_RCC_I2C2_CLK_ENABLE(); + /* USER CODE BEGIN I2C2_MspInit 1 */ + + /* USER CODE END I2C2_MspInit 1 */ + } +} + +void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle) +{ + + if(i2cHandle->Instance==I2C1) + { + /* USER CODE BEGIN I2C1_MspDeInit 0 */ + + /* USER CODE END I2C1_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_I2C1_CLK_DISABLE(); + + /**I2C1 GPIO Configuration + PB6 ------> I2C1_SCL + PB7 ------> I2C1_SDA + */ + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6); + + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7); + + /* USER CODE BEGIN I2C1_MspDeInit 1 */ + + /* USER CODE END I2C1_MspDeInit 1 */ + } + else if(i2cHandle->Instance==I2C2) + { + /* USER CODE BEGIN I2C2_MspDeInit 0 */ + + /* USER CODE END I2C2_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_I2C2_CLK_DISABLE(); + + /**I2C2 GPIO Configuration + PB10 ------> I2C2_SCL + PB11 ------> I2C2_SDA + */ + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10); + + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_11); + + /* USER CODE BEGIN I2C2_MspDeInit 1 */ + + /* USER CODE END I2C2_MspDeInit 1 */ + } +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/Core/Src/main.c b/Core/Src/main.c new file mode 100644 index 0000000..e4abc7d --- /dev/null +++ b/Core/Src/main.c @@ -0,0 +1,218 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 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 "main.h" +#include "cmsis_os.h" +#include "dma.h" +#include "i2c.h" +#include "usart.h" +#include "gpio.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* 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 -----------------------------------------------*/ +void SystemClock_Config(void); +void MX_FREERTOS_Init(void); +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + + +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + HAL_Init(); + + /* USER CODE BEGIN Init */ + + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_DMA_Init(); + MX_I2C1_Init(); + MX_USART1_UART_Init(); + MX_USART2_UART_Init(); + MX_I2C2_Init(); + /* USER CODE BEGIN 2 */ + + /* USER CODE END 2 */ + + /* Call init function for freertos objects (in cmsis_os2.c) */ + MX_FREERTOS_Init(); + + /* Start scheduler */ + osKernelStart(); + + /* We should never get here as control is now taken by the scheduler */ + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) + { + /* USER CODE END WHILE */ + + /* USER CODE BEGIN 3 */ + + } + /* USER CODE END 3 */ +} + +/** + * @brief System Clock Configuration + * @retval None + */ +void SystemClock_Config(void) +{ + 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_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + Error_Handler(); + } + + /** 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_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) + { + Error_Handler(); + } +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/** + * @brief Period elapsed callback in non blocking mode + * @note This function is called when TIM4 interrupt took place, inside + * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment + * a global variable "uwTick" used as application time base. + * @param htim : TIM handle + * @retval None + */ +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ + /* USER CODE BEGIN Callback 0 */ + + /* USER CODE END Callback 0 */ + if (htim->Instance == TIM4) + { + HAL_IncTick(); + } + /* USER CODE BEGIN Callback 1 */ + + /* USER CODE END Callback 1 */ +} + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return state */ + __disable_irq(); + while (1) + { + } + /* USER CODE END Error_Handler_Debug */ +} +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line number, + ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/Core/Src/stm32f1xx_hal_msp.c b/Core/Src/stm32f1xx_hal_msp.c new file mode 100644 index 0000000..b09b3fd --- /dev/null +++ b/Core/Src/stm32f1xx_hal_msp.c @@ -0,0 +1,88 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f1xx_hal_msp.c + * @brief This file provides code for the MSP Initialization + * and de-Initialization codes. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 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 "main.h" +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN TD */ + +/* USER CODE END TD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN Define */ + +/* USER CODE END Define */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN Macro */ + +/* USER CODE END Macro */ + +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* External functions --------------------------------------------------------*/ +/* USER CODE BEGIN ExternalFunctions */ + +/* USER CODE END ExternalFunctions */ + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ +/** + * Initializes the Global MSP. + */ +void HAL_MspInit(void) +{ + + /* USER CODE BEGIN MspInit 0 */ + + /* USER CODE END MspInit 0 */ + + __HAL_RCC_AFIO_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + /* System interrupt init*/ + /* PendSV_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(PendSV_IRQn, 15, 0); + + /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled + */ + __HAL_AFIO_REMAP_SWJ_NOJTAG(); + + /* USER CODE BEGIN MspInit 1 */ + + /* USER CODE END MspInit 1 */ +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/Core/Src/stm32f1xx_hal_timebase_tim.c b/Core/Src/stm32f1xx_hal_timebase_tim.c new file mode 100644 index 0000000..badd077 --- /dev/null +++ b/Core/Src/stm32f1xx_hal_timebase_tim.c @@ -0,0 +1,138 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f1xx_hal_timebase_tim.c + * @brief HAL time base based on the hardware TIM. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 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_hal.h" +#include "stm32f1xx_hal_tim.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +TIM_HandleTypeDef htim4; +/* Private function prototypes -----------------------------------------------*/ +void TIM4_IRQHandler(void); +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief This function configures the TIM4 as a time base source. + * The time source is configured to have 1ms time base with a dedicated + * Tick interrupt priority. + * @note This function is called automatically at the beginning of program after + * reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig(). + * @param TickPriority: Tick interrupt priority. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) +{ + RCC_ClkInitTypeDef clkconfig; + uint32_t uwTimclock, uwAPB1Prescaler = 0U; + + uint32_t uwPrescalerValue = 0U; + uint32_t pFLatency; + + HAL_StatusTypeDef status = HAL_OK; + + /* Enable TIM4 clock */ + __HAL_RCC_TIM4_CLK_ENABLE(); + + /* Get clock configuration */ + HAL_RCC_GetClockConfig(&clkconfig, &pFLatency); + + /* Get APB1 prescaler */ + uwAPB1Prescaler = clkconfig.APB1CLKDivider; + /* Compute TIM4 clock */ + if (uwAPB1Prescaler == RCC_HCLK_DIV1) + { + uwTimclock = HAL_RCC_GetPCLK1Freq(); + } + else + { + uwTimclock = 2UL * HAL_RCC_GetPCLK1Freq(); + } + + /* Compute the prescaler value to have TIM4 counter clock equal to 1MHz */ + uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U); + + /* Initialize TIM4 */ + htim4.Instance = TIM4; + + /* Initialize TIMx peripheral as follow: + * Period = [(TIM4CLK/1000) - 1]. to have a (1/1000) s time base. + * Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock. + * ClockDivision = 0 + * Counter direction = Up + */ + htim4.Init.Period = (1000000U / 1000U) - 1U; + htim4.Init.Prescaler = uwPrescalerValue; + htim4.Init.ClockDivision = 0; + htim4.Init.CounterMode = TIM_COUNTERMODE_UP; + htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + + status = HAL_TIM_Base_Init(&htim4); + if (status == HAL_OK) + { + /* Start the TIM time Base generation in interrupt mode */ + status = HAL_TIM_Base_Start_IT(&htim4); + if (status == HAL_OK) + { + /* Enable the TIM4 global Interrupt */ + HAL_NVIC_EnableIRQ(TIM4_IRQn); + /* Configure the SysTick IRQ priority */ + if (TickPriority < (1UL << __NVIC_PRIO_BITS)) + { + /* Configure the TIM IRQ priority */ + HAL_NVIC_SetPriority(TIM4_IRQn, TickPriority, 0U); + uwTickPrio = TickPriority; + } + else + { + status = HAL_ERROR; + } + } + } + + /* Return function status */ + return status; +} + +/** + * @brief Suspend Tick increment. + * @note Disable the tick increment by disabling TIM4 update interrupt. + * @param None + * @retval None + */ +void HAL_SuspendTick(void) +{ + /* Disable TIM4 update Interrupt */ + __HAL_TIM_DISABLE_IT(&htim4, TIM_IT_UPDATE); +} + +/** + * @brief Resume Tick increment. + * @note Enable the tick increment by Enabling TIM4 update interrupt. + * @param None + * @retval None + */ +void HAL_ResumeTick(void) +{ + /* Enable TIM4 Update interrupt */ + __HAL_TIM_ENABLE_IT(&htim4, TIM_IT_UPDATE); +} + diff --git a/Core/Src/stm32f1xx_it.c b/Core/Src/stm32f1xx_it.c new file mode 100644 index 0000000..a9b6a08 --- /dev/null +++ b/Core/Src/stm32f1xx_it.c @@ -0,0 +1,235 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f1xx_it.c + * @brief Interrupt Service Routines. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 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 "main.h" +#include "stm32f1xx_it.h" +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "bsp_uart.h" +/* 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 --------------------------------------------------------*/ +extern DMA_HandleTypeDef hdma_usart1_rx; +extern DMA_HandleTypeDef hdma_usart1_tx; +extern UART_HandleTypeDef huart1; +extern TIM_HandleTypeDef htim4; + +/* 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 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 */ +} + +/******************************************************************************/ +/* 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). */ +/******************************************************************************/ + +/** + * @brief This function handles DMA1 channel4 global interrupt. + */ +void DMA1_Channel4_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Channel4_IRQn 0 */ + + /* USER CODE END DMA1_Channel4_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_usart1_tx); + /* USER CODE BEGIN DMA1_Channel4_IRQn 1 */ + + /* USER CODE END DMA1_Channel4_IRQn 1 */ +} + +/** + * @brief This function handles DMA1 channel5 global interrupt. + */ +void DMA1_Channel5_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Channel5_IRQn 0 */ + + /* USER CODE END DMA1_Channel5_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_usart1_rx); + /* USER CODE BEGIN DMA1_Channel5_IRQn 1 */ + + /* USER CODE END DMA1_Channel5_IRQn 1 */ +} + +/** + * @brief This function handles TIM4 global interrupt. + */ +void TIM4_IRQHandler(void) +{ + /* USER CODE BEGIN TIM4_IRQn 0 */ + + /* USER CODE END TIM4_IRQn 0 */ + HAL_TIM_IRQHandler(&htim4); + /* USER CODE BEGIN TIM4_IRQn 1 */ + + /* USER CODE END TIM4_IRQn 1 */ +} + +/** + * @brief This function handles USART1 global interrupt. + */ +void USART1_IRQHandler(void) +{ + /* USER CODE BEGIN USART1_IRQn 0 */ + extern void BSP_UART1_IDLE_IRQHandler(void); + + uint32_t isr_flags = READ_REG(huart1.Instance->SR); + uint32_t cr1its = READ_REG(huart1.Instance->CR1); + + /* IDLE line detection */ + if ((isr_flags & UART_FLAG_IDLE) && (cr1its & USART_CR1_IDLEIE)) + { + __HAL_UART_CLEAR_IDLEFLAG(&huart1); + BSP_UART1_IDLE_IRQHandler(); + } + + /* USER CODE END USART1_IRQn 0 */ + HAL_UART_IRQHandler(&huart1); + /* USER CODE BEGIN USART1_IRQn 1 */ + + /* USER CODE END USART1_IRQn 1 */ +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/Core/Src/syscalls.c b/Core/Src/syscalls.c new file mode 100644 index 0000000..e10d76f --- /dev/null +++ b/Core/Src/syscalls.c @@ -0,0 +1,244 @@ +/** + ****************************************************************************** + * @file syscalls.c + * @author Auto-generated by STM32CubeMX + * @brief Minimal System calls file + * + * For more information about which c-functions + * need which of these lowlevel functions + * please consult the Newlib or Picolibc libc-manual + ****************************************************************************** + * @attention + * + * Copyright (c) 2020-2025 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. + * + ****************************************************************************** + */ + +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Variables */ +extern int __io_putchar(int ch) __attribute__((weak)); +extern int __io_getchar(void) __attribute__((weak)); + + +char *__env[1] = { 0 }; +char **environ = __env; + + +/* Functions */ +void initialise_monitor_handles() +{ +} + +int _getpid(void) +{ + return 1; +} + +int _kill(int pid, int sig) +{ + (void)pid; + (void)sig; + errno = EINVAL; + return -1; +} + +void _exit (int status) +{ + _kill(status, -1); + while (1) {} /* Make sure we hang here */ +} + +__attribute__((weak)) int _read(int file, char *ptr, int len) +{ + (void)file; + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + *ptr++ = __io_getchar(); + } + + return len; +} + +__attribute__((weak)) int _write(int file, char *ptr, int len) +{ + (void)file; + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + __io_putchar(*ptr++); + } + return len; +} + +int _close(int file) +{ + (void)file; + return -1; +} + + +int _fstat(int file, struct stat *st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int file) +{ + (void)file; + return 1; +} + +int _lseek(int file, int ptr, int dir) +{ + (void)file; + (void)ptr; + (void)dir; + return 0; +} + +int _open(char *path, int flags, ...) +{ + (void)path; + (void)flags; + /* Pretend like we always fail */ + return -1; +} + +int _wait(int *status) +{ + (void)status; + errno = ECHILD; + return -1; +} + +int _unlink(char *name) +{ + (void)name; + errno = ENOENT; + return -1; +} + +clock_t _times(struct tms *buf) +{ + (void)buf; + return -1; +} + +int _stat(const char *file, struct stat *st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _link(char *old, char *new) +{ + (void)old; + (void)new; + errno = EMLINK; + return -1; +} + +int _fork(void) +{ + errno = EAGAIN; + return -1; +} + +int _execve(char *name, char **argv, char **env) +{ + (void)name; + (void)argv; + (void)env; + errno = ENOMEM; + return -1; +} + +// --- Picolibc Specific Section --- +#if defined(__PICOLIBC__) + +/** + * @brief Picolibc helper function to output a character to a FILE stream. + * This redirects the output to the low-level __io_putchar function. + * @param c Character to write. + * @param file FILE stream pointer (ignored). + * @retval int The character written. + */ +static int starm_putc(char c, FILE *file) +{ + (void) file; + __io_putchar(c); + return c; +} + +/** + * @brief Picolibc helper function to input a character from a FILE stream. + * This redirects the input from the low-level __io_getchar function. + * @param file FILE stream pointer (ignored). + * @retval int The character read, cast to an unsigned char then int. + */ +static int starm_getc(FILE *file) +{ + unsigned char c; + (void) file; + c = __io_getchar(); + return c; +} + +// Define and initialize the standard I/O streams for Picolibc. +// FDEV_SETUP_STREAM connects the starm_putc and starm_getc helper functions to a FILE structure. +// _FDEV_SETUP_RW indicates the stream is for reading and writing. +static FILE __stdio = FDEV_SETUP_STREAM(starm_putc, + starm_getc, + NULL, + _FDEV_SETUP_RW); + +// Assign the standard stream pointers (stdin, stdout, stderr) to the initialized stream. +// Picolibc uses these pointers for standard I/O operations (printf, scanf, etc.). +FILE *const stdin = &__stdio; +__strong_reference(stdin, stdout); +__strong_reference(stdin, stderr); + +// Create strong aliases mapping standard C library function names (without underscore) +// to the implemented system call stubs (with underscore). Picolibc uses these +// standard names internally, so this linking is required. +__strong_reference(_read, read); +__strong_reference(_write, write); +__strong_reference(_times, times); +__strong_reference(_execve, execve); +__strong_reference(_fork, fork); +__strong_reference(_link, link); +__strong_reference(_unlink, unlink); +__strong_reference(_stat, stat); +__strong_reference(_wait, wait); +__strong_reference(_open, open); +__strong_reference(_close, close); +__strong_reference(_lseek, lseek); +__strong_reference(_isatty, isatty); +__strong_reference(_fstat, fstat); +__strong_reference(_exit, exit); +__strong_reference(_kill, kill); +__strong_reference(_getpid, getpid); + +#endif //__PICOLIBC__ diff --git a/Core/Src/sysmem.c b/Core/Src/sysmem.c new file mode 100644 index 0000000..a875d42 --- /dev/null +++ b/Core/Src/sysmem.c @@ -0,0 +1,87 @@ +/** + ****************************************************************************** + * @file sysmem.c + * @author Generated by STM32CubeMX + * @brief System Memory calls file + * + * For more information about which C functions + * need which of these lowlevel functions + * please consult the Newlib or Picolibc libc manual + ****************************************************************************** + * @attention + * + * Copyright (c) 2025 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. + * + ****************************************************************************** + */ + +/* Includes */ +#include +#include +#include + +/** + * Pointer to the current high watermark of the heap usage + */ +static uint8_t *__sbrk_heap_end = NULL; + +/** + * @brief _sbrk() allocates memory to the newlib heap and is used by malloc + * and others from the C library + * + * @verbatim + * ############################################################################ + * # .data # .bss # newlib heap # MSP stack # + * # # # # Reserved by _Min_Stack_Size # + * ############################################################################ + * ^-- RAM start ^-- _end _estack, RAM end --^ + * @endverbatim + * + * This implementation starts allocating at the '_end' linker symbol + * The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack + * The implementation considers '_estack' linker symbol to be RAM end + * NOTE: If the MSP stack, at any point during execution, grows larger than the + * reserved size, please increase the '_Min_Stack_Size'. + * + * @param incr Memory size + * @return Pointer to allocated memory + */ +void *_sbrk(ptrdiff_t incr) +{ + extern uint8_t _end; /* Symbol defined in the linker script */ + extern uint8_t _estack; /* Symbol defined in the linker script */ + extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */ + const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size; + const uint8_t *max_heap = (uint8_t *)stack_limit; + uint8_t *prev_heap_end; + + /* Initialize heap end at first call */ + if (NULL == __sbrk_heap_end) + { + __sbrk_heap_end = &_end; + } + + /* Protect heap from growing into the reserved MSP stack */ + if (__sbrk_heap_end + incr > max_heap) + { + errno = ENOMEM; + return (void *)-1; + } + + prev_heap_end = __sbrk_heap_end; + __sbrk_heap_end += incr; + + return (void *)prev_heap_end; +} + +#if defined(__PICOLIBC__) + // Picolibc expects syscalls without the leading underscore. + // This creates a strong alias so that + // calls to `sbrk()` are resolved to our `_sbrk()` implementation. + __strong_reference(_sbrk, sbrk); +#endif diff --git a/Core/Src/system_stm32f1xx.c b/Core/Src/system_stm32f1xx.c new file mode 100644 index 0000000..3afa78d --- /dev/null +++ b/Core/Src/system_stm32f1xx.c @@ -0,0 +1,406 @@ +/** + ****************************************************************************** + * @file system_stm32f1xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File. + * + * 1. This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): Setups the system clock (System clock source, PLL Multiplier + * factors, AHB/APBx prescalers and Flash settings). + * This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32f1xx_xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * 2. After each device reset the HSI (8 MHz) is used as system clock source. + * Then SystemInit() function is called, in "startup_stm32f1xx_xx.s" file, to + * configure the system clock before to branch to main program. + * + * 4. The default value of HSE crystal is set to 8 MHz (or 25 MHz, depending on + * the product used), refer to "HSE_VALUE". + * When HSE is used as system clock source, directly or through PLL, and you + * are using different crystal you have to adapt the HSE value to your own + * configuration. + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017-2021 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. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f1xx_system + * @{ + */ + +/** @addtogroup STM32F1xx_System_Private_Includes + * @{ + */ + +#include "stm32f1xx.h" + +/** + * @} + */ + +/** @addtogroup STM32F1xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F1xx_System_Private_Defines + * @{ + */ + +#if !defined (HSE_VALUE) + #define HSE_VALUE 8000000U /*!< Default value of the External oscillator in Hz. + This value can be provided and adapted by the user application. */ +#endif /* HSE_VALUE */ + +#if !defined (HSI_VALUE) + #define HSI_VALUE 8000000U /*!< Default value of the Internal oscillator in Hz. + This value can be provided and adapted by the user application. */ +#endif /* HSI_VALUE */ + +/*!< Uncomment the following line if you need to use external SRAM */ +#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) +/* #define DATA_IN_ExtSRAM */ +#endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */ + +/* Note: Following vector table addresses must be defined in line with linker + configuration. */ +/*!< Uncomment the following line if you need to relocate the vector table + anywhere in Flash or Sram, else the vector table is kept at the automatic + remap of boot address selected */ +/* #define USER_VECT_TAB_ADDRESS */ + +#if defined(USER_VECT_TAB_ADDRESS) +/*!< Uncomment the following line if you need to relocate your vector Table + in Sram else user remap will be done in Flash. */ +/* #define VECT_TAB_SRAM */ +#if defined(VECT_TAB_SRAM) +#define VECT_TAB_BASE_ADDRESS SRAM_BASE /*!< Vector Table base address field. + This value must be a multiple of 0x200. */ +#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +#else +#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field. + This value must be a multiple of 0x200. */ +#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +#endif /* VECT_TAB_SRAM */ +#endif /* USER_VECT_TAB_ADDRESS */ + +/******************************************************************************/ + +/** + * @} + */ + +/** @addtogroup STM32F1xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F1xx_System_Private_Variables + * @{ + */ + + /* This variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ +uint32_t SystemCoreClock = 8000000; +const uint8_t AHBPrescTable[16U] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; +const uint8_t APBPrescTable[8U] = {0, 0, 0, 0, 1, 2, 3, 4}; + +/** + * @} + */ + +/** @addtogroup STM32F1xx_System_Private_FunctionPrototypes + * @{ + */ + +#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) +#ifdef DATA_IN_ExtSRAM + static void SystemInit_ExtMemCtl(void); +#endif /* DATA_IN_ExtSRAM */ +#endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */ + +/** + * @} + */ + +/** @addtogroup STM32F1xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system + * Initialize the Embedded Flash Interface, the PLL and update the + * SystemCoreClock variable. + * @note This function should be used only after reset. + * @param None + * @retval None + */ +void SystemInit (void) +{ +#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) + #ifdef DATA_IN_ExtSRAM + SystemInit_ExtMemCtl(); + #endif /* DATA_IN_ExtSRAM */ +#endif + + /* Configure the Vector Table location -------------------------------------*/ +#if defined(USER_VECT_TAB_ADDRESS) + SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */ +#endif /* USER_VECT_TAB_ADDRESS */ +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * or HSI_VALUE(*) multiplied by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32f1xx.h file (default value + * 8 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32f1xx.h file (default value + * 8 MHz or 25 MHz, depending on the product used), user has to ensure + * that HSE_VALUE is same as the real frequency of the crystal used. + * Otherwise, this function may have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * @param None + * @retval None + */ +void SystemCoreClockUpdate (void) +{ + uint32_t tmp = 0U, pllmull = 0U, pllsource = 0U; + +#if defined(STM32F105xC) || defined(STM32F107xC) + uint32_t prediv1source = 0U, prediv1factor = 0U, prediv2factor = 0U, pll2mull = 0U; +#endif /* STM32F105xC */ + +#if defined(STM32F100xB) || defined(STM32F100xE) + uint32_t prediv1factor = 0U; +#endif /* STM32F100xB or STM32F100xE */ + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) + { + case 0x00U: /* HSI used as system clock */ + SystemCoreClock = HSI_VALUE; + break; + case 0x04U: /* HSE used as system clock */ + SystemCoreClock = HSE_VALUE; + break; + case 0x08U: /* PLL used as system clock */ + + /* Get PLL clock source and multiplication factor ----------------------*/ + pllmull = RCC->CFGR & RCC_CFGR_PLLMULL; + pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; + +#if !defined(STM32F105xC) && !defined(STM32F107xC) + pllmull = ( pllmull >> 18U) + 2U; + + if (pllsource == 0x00U) + { + /* HSI oscillator clock divided by 2 selected as PLL clock entry */ + SystemCoreClock = (HSI_VALUE >> 1U) * pllmull; + } + else + { + #if defined(STM32F100xB) || defined(STM32F100xE) + prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1U; + /* HSE oscillator clock selected as PREDIV1 clock entry */ + SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; + #else + /* HSE selected as PLL clock entry */ + if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t)RESET) + {/* HSE oscillator clock divided by 2 */ + SystemCoreClock = (HSE_VALUE >> 1U) * pllmull; + } + else + { + SystemCoreClock = HSE_VALUE * pllmull; + } + #endif + } +#else + pllmull = pllmull >> 18U; + + if (pllmull != 0x0DU) + { + pllmull += 2U; + } + else + { /* PLL multiplication factor = PLL input clock * 6.5 */ + pllmull = 13U / 2U; + } + + if (pllsource == 0x00U) + { + /* HSI oscillator clock divided by 2 selected as PLL clock entry */ + SystemCoreClock = (HSI_VALUE >> 1U) * pllmull; + } + else + {/* PREDIV1 selected as PLL clock entry */ + + /* Get PREDIV1 clock source and division factor */ + prediv1source = RCC->CFGR2 & RCC_CFGR2_PREDIV1SRC; + prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1U; + + if (prediv1source == 0U) + { + /* HSE oscillator clock selected as PREDIV1 clock entry */ + SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; + } + else + {/* PLL2 clock selected as PREDIV1 clock entry */ + + /* Get PREDIV2 division factor and PLL2 multiplication factor */ + prediv2factor = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> 4U) + 1U; + pll2mull = ((RCC->CFGR2 & RCC_CFGR2_PLL2MUL) >> 8U) + 2U; + SystemCoreClock = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull; + } + } +#endif /* STM32F105xC */ + break; + + default: + SystemCoreClock = HSI_VALUE; + break; + } + + /* Compute HCLK clock frequency ----------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)]; + /* HCLK clock frequency */ + SystemCoreClock >>= tmp; +} + +#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) +/** + * @brief Setup the external memory controller. Called in startup_stm32f1xx.s + * before jump to __main + * @param None + * @retval None + */ +#ifdef DATA_IN_ExtSRAM +/** + * @brief Setup the external memory controller. + * Called in startup_stm32f1xx_xx.s/.c before jump to main. + * This function configures the external SRAM mounted on STM3210E-EVAL + * board (STM32 High density devices). This SRAM will be used as program + * data memory (including heap and stack). + * @param None + * @retval None + */ +void SystemInit_ExtMemCtl(void) +{ + __IO uint32_t tmpreg; + /*!< FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is + required, then adjust the Register Addresses */ + + /* Enable FSMC clock */ + RCC->AHBENR = 0x00000114U; + + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->AHBENR, RCC_AHBENR_FSMCEN); + + /* Enable GPIOD, GPIOE, GPIOF and GPIOG clocks */ + RCC->APB2ENR = 0x000001E0U; + + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPDEN); + + (void)(tmpreg); + +/* --------------- SRAM Data lines, NOE and NWE configuration ---------------*/ +/*---------------- SRAM Address lines configuration -------------------------*/ +/*---------------- NOE and NWE configuration --------------------------------*/ +/*---------------- NE3 configuration ----------------------------------------*/ +/*---------------- NBL0, NBL1 configuration ---------------------------------*/ + + GPIOD->CRL = 0x44BB44BBU; + GPIOD->CRH = 0xBBBBBBBBU; + + GPIOE->CRL = 0xB44444BBU; + GPIOE->CRH = 0xBBBBBBBBU; + + GPIOF->CRL = 0x44BBBBBBU; + GPIOF->CRH = 0xBBBB4444U; + + GPIOG->CRL = 0x44BBBBBBU; + GPIOG->CRH = 0x444B4B44U; + +/*---------------- FSMC Configuration ---------------------------------------*/ +/*---------------- Enable FSMC Bank1_SRAM Bank ------------------------------*/ + + FSMC_Bank1->BTCR[4U] = 0x00001091U; + FSMC_Bank1->BTCR[5U] = 0x00110212U; +} +#endif /* DATA_IN_ExtSRAM */ +#endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/Core/Src/usart.c b/Core/Src/usart.c new file mode 100644 index 0000000..d2f25cf --- /dev/null +++ b/Core/Src/usart.c @@ -0,0 +1,241 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file usart.c + * @brief This file provides code for the configuration + * of the USART instances. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 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 "usart.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +UART_HandleTypeDef huart1; +UART_HandleTypeDef huart2; +DMA_HandleTypeDef hdma_usart1_rx; +DMA_HandleTypeDef hdma_usart1_tx; + +/* USART1 init function */ + +void MX_USART1_UART_Init(void) +{ + + /* USER CODE BEGIN USART1_Init 0 */ + + /* USER CODE END USART1_Init 0 */ + + /* USER CODE BEGIN USART1_Init 1 */ + + /* USER CODE END USART1_Init 1 */ + huart1.Instance = USART1; + huart1.Init.BaudRate = 115200; + huart1.Init.WordLength = UART_WORDLENGTH_8B; + huart1.Init.StopBits = UART_STOPBITS_1; + huart1.Init.Parity = UART_PARITY_NONE; + huart1.Init.Mode = UART_MODE_TX_RX; + huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart1.Init.OverSampling = UART_OVERSAMPLING_16; + if (HAL_UART_Init(&huart1) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN USART1_Init 2 */ + + /* USER CODE END USART1_Init 2 */ + +} +/* USART2 init function */ + +void MX_USART2_UART_Init(void) +{ + + /* USER CODE BEGIN USART2_Init 0 */ + + /* USER CODE END USART2_Init 0 */ + + /* USER CODE BEGIN USART2_Init 1 */ + + /* USER CODE END USART2_Init 1 */ + huart2.Instance = USART2; + huart2.Init.BaudRate = 115200; + huart2.Init.WordLength = UART_WORDLENGTH_8B; + huart2.Init.StopBits = UART_STOPBITS_1; + huart2.Init.Parity = UART_PARITY_NONE; + huart2.Init.Mode = UART_MODE_TX_RX; + huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart2.Init.OverSampling = UART_OVERSAMPLING_16; + if (HAL_UART_Init(&huart2) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN USART2_Init 2 */ + + /* USER CODE END USART2_Init 2 */ + +} + +void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) +{ + + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(uartHandle->Instance==USART1) + { + /* USER CODE BEGIN USART1_MspInit 0 */ + + /* USER CODE END USART1_MspInit 0 */ + /* USART1 clock enable */ + __HAL_RCC_USART1_CLK_ENABLE(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**USART1 GPIO Configuration + PA9 ------> USART1_TX + PA10 ------> USART1_RX + */ + GPIO_InitStruct.Pin = GPIO_PIN_9; + 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_10; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* USART1 DMA Init */ + /* USART1_RX Init */ + hdma_usart1_rx.Instance = DMA1_Channel5; + hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_usart1_rx.Init.Mode = DMA_NORMAL; + hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW; + if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK) + { + Error_Handler(); + } + + __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx); + + /* USART1_TX Init */ + hdma_usart1_tx.Instance = DMA1_Channel4; + hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_usart1_tx.Init.Mode = DMA_NORMAL; + hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW; + if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK) + { + Error_Handler(); + } + + __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx); + + /* USART1 interrupt Init */ + HAL_NVIC_SetPriority(USART1_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(USART1_IRQn); + /* USER CODE BEGIN USART1_MspInit 1 */ + + /* USER CODE END USART1_MspInit 1 */ + } + else if(uartHandle->Instance==USART2) + { + /* USER CODE BEGIN USART2_MspInit 0 */ + + /* USER CODE END USART2_MspInit 0 */ + /* USART2 clock enable */ + __HAL_RCC_USART2_CLK_ENABLE(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**USART2 GPIO Configuration + PA2 ------> USART2_TX + PA3 ------> USART2_RX + */ + GPIO_InitStruct.Pin = GPIO_PIN_2; + 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_3; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* USER CODE BEGIN USART2_MspInit 1 */ + + /* USER CODE END USART2_MspInit 1 */ + } +} + +void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) +{ + + if(uartHandle->Instance==USART1) + { + /* USER CODE BEGIN USART1_MspDeInit 0 */ + + /* USER CODE END USART1_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USART1_CLK_DISABLE(); + + /**USART1 GPIO Configuration + PA9 ------> USART1_TX + PA10 ------> USART1_RX + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); + + /* USART1 DMA DeInit */ + HAL_DMA_DeInit(uartHandle->hdmarx); + HAL_DMA_DeInit(uartHandle->hdmatx); + + /* USART1 interrupt Deinit */ + HAL_NVIC_DisableIRQ(USART1_IRQn); + /* USER CODE BEGIN USART1_MspDeInit 1 */ + + /* USER CODE END USART1_MspDeInit 1 */ + } + else if(uartHandle->Instance==USART2) + { + /* USER CODE BEGIN USART2_MspDeInit 0 */ + + /* USER CODE END USART2_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USART2_CLK_DISABLE(); + + /**USART2 GPIO Configuration + PA2 ------> USART2_TX + PA3 ------> USART2_RX + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); + + /* USER CODE BEGIN USART2_MspDeInit 1 */ + + /* USER CODE END USART2_MspDeInit 1 */ + } +} + +/* USER CODE BEGIN 1 */ +#include "bsp_uart.h" + +/* UART1 DMA receive buffer - exposed for external use */ +extern uint8_t uart1_rx_buf[UART1_RX_BUF_SIZE]; +extern DMA_HandleTypeDef hdma_usart1_rx; + +/* USER CODE END 1 */ diff --git a/STM32F103XX_FLASH.ld b/STM32F103XX_FLASH.ld new file mode 100644 index 0000000..e982e80 --- /dev/null +++ b/STM32F103XX_FLASH.ld @@ -0,0 +1,249 @@ +/* +****************************************************************************** +** + +** File : LinkerScript.ld +** +** Author : STM32CubeMX +** +** Abstract : Linker script for STM32F103C8Tx series +** 64Kbytes FLASH and 20Kbytes RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed “as is,” without any warranty +** of any kind. +** +***************************************************************************** +** @attention +** +**

© COPYRIGHT(c) 2025 STMicroelectronics

+** +** Redistribution and use in source and binary forms, with or without modification, +** are permitted provided that the following conditions are met: +** 1. Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** 3. Neither the name of STMicroelectronics nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Specify the memory areas */ +MEMORY +{ +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K +FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 64K +} + +/* Highest address of the user mode stack */ +_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of RAM */ +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >FLASH + + .ARM (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >FLASH + + .preinit_array (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >FLASH + + .init_array (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >FLASH + + .fini_array (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *(.RamFunc) /* .RamFunc sections */ + *(.RamFunc*) /* .RamFunc* sections */ + + . = ALIGN(4); + } >RAM AT> FLASH + + /* Initialized TLS data section */ + .tdata : ALIGN(4) + { + *(.tdata .tdata.* .gnu.linkonce.td.*) + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + PROVIDE(__data_end = .); + PROVIDE(__tdata_end = .); + } >RAM AT> FLASH + + PROVIDE( __tdata_start = ADDR(.tdata) ); + PROVIDE( __tdata_size = __tdata_end - __tdata_start ); + + PROVIDE( __data_start = ADDR(.data) ); + PROVIDE( __data_size = __data_end - __data_start ); + + PROVIDE( __tdata_source = LOADADDR(.tdata) ); + PROVIDE( __tdata_source_end = LOADADDR(.tdata) + SIZEOF(.tdata) ); + PROVIDE( __tdata_source_size = __tdata_source_end - __tdata_source ); + + PROVIDE( __data_source = LOADADDR(.data) ); + PROVIDE( __data_source_end = __tdata_source_end ); + PROVIDE( __data_source_size = __data_source_end - __data_source ); + /* Uninitialized data section */ + .tbss (NOLOAD) : ALIGN(4) + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.tbss .tbss.*) + . = ALIGN(4); + PROVIDE( __tbss_end = . ); + } >RAM + + PROVIDE( __tbss_start = ADDR(.tbss) ); + PROVIDE( __tbss_size = __tbss_end - __tbss_start ); + PROVIDE( __tbss_offset = ADDR(.tbss) - ADDR(.tdata) ); + + PROVIDE( __tls_base = __tdata_start ); + PROVIDE( __tls_end = __tbss_end ); + PROVIDE( __tls_size = __tls_end - __tls_base ); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1) ); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + PROVIDE( __arm64_tls_tcb_offset = MAX(16, __tls_align) ); + + .bss (NOLOAD) : ALIGN(4) + { + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + PROVIDE( __bss_end = .); + } >RAM + PROVIDE( __non_tls_bss_start = ADDR(.bss) ); + + PROVIDE( __bss_start = __tbss_start ); + PROVIDE( __bss_size = __bss_end - __bss_start ); + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack (NOLOAD) : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a:* ( * ) + libm.a:* ( * ) + libgcc.a:* ( * ) + } + +} diff --git a/cmake/gcc-arm-none-eabi.cmake b/cmake/gcc-arm-none-eabi.cmake new file mode 100644 index 0000000..99ef08b --- /dev/null +++ b/cmake/gcc-arm-none-eabi.cmake @@ -0,0 +1,43 @@ +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR arm) + +set(CMAKE_C_COMPILER_ID GNU) +set(CMAKE_CXX_COMPILER_ID GNU) + +# Some default GCC settings +# arm-none-eabi- must be part of path environment +set(TOOLCHAIN_PREFIX arm-none-eabi-) + +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc) +set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++) +set(CMAKE_LINKER ${TOOLCHAIN_PREFIX}g++) +set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy) +set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size) + +set(CMAKE_EXECUTABLE_SUFFIX_ASM ".elf") +set(CMAKE_EXECUTABLE_SUFFIX_C ".elf") +set(CMAKE_EXECUTABLE_SUFFIX_CXX ".elf") + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +# MCU specific flags +set(TARGET_FLAGS "-mcpu=cortex-m3 ") + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_FLAGS}") +set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -MMD -MP") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fdata-sections -ffunction-sections") + +set(CMAKE_C_FLAGS_DEBUG "-O0 -g3") +set(CMAKE_C_FLAGS_RELEASE "-Os -g0") +set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3") +set(CMAKE_CXX_FLAGS_RELEASE "-Os -g0") + +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions -fno-threadsafe-statics") + +set(CMAKE_EXE_LINKER_FLAGS "${TARGET_FLAGS}") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T \"${CMAKE_SOURCE_DIR}/STM32F103XX_FLASH.ld\"") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=nano.specs") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--print-memory-usage") +set(TOOLCHAIN_LINK_LIBRARIES "m") diff --git a/cmake/starm-clang.cmake b/cmake/starm-clang.cmake new file mode 100644 index 0000000..9626b75 --- /dev/null +++ b/cmake/starm-clang.cmake @@ -0,0 +1,65 @@ +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR arm) + +set(CMAKE_C_COMPILER_ID Clang) +set(CMAKE_CXX_COMPILER_ID Clang) + +# Some default llvm settings +set(TOOLCHAIN_PREFIX starm-) + +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}clang) +set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}clang++) +set(CMAKE_LINKER ${TOOLCHAIN_PREFIX}clang) +set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy) +set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size) + +set(CMAKE_EXECUTABLE_SUFFIX_ASM ".elf") +set(CMAKE_EXECUTABLE_SUFFIX_C ".elf") +set(CMAKE_EXECUTABLE_SUFFIX_CXX ".elf") + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +# STARM_TOOLCHAIN_CONFIG allows you to choose the toolchain configuration. +# Possible values are: +# "STARM_HYBRID" : Hybrid configuration using starm-clang Assemler and Compiler and GNU Linker +# "STARM_NEWLIB" : starm-clang toolchain with NEWLIB C library +# "STARM_PICOLIBC" : starm-clang toolchain with PICOLIBC C library +set(STARM_TOOLCHAIN_CONFIG "STARM_PICOLIBC") + +if(STARM_TOOLCHAIN_CONFIG STREQUAL "STARM_HYBRID") + set(TOOLCHAIN_MULTILIBS "--multi-lib-config=\"$ENV{CLANG_GCC_CMSIS_COMPILER}/multilib.gnu_tools_for_stm32.yaml\" --gcc-toolchain=\"$ENV{GCC_TOOLCHAIN_ROOT}/..\"") +elseif (STARM_TOOLCHAIN_CONFIG STREQUAL "STARM_NEWLIB") + set(TOOLCHAIN_MULTILIBS "--config=newlib.cfg") +endif() + +# MCU specific flags +set(TARGET_FLAGS "-mcpu=cortex-m3 ${TOOLCHAIN_MULTILIBS}") + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_FLAGS}") +set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -MP") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fdata-sections -ffunction-sections") + +set(CMAKE_C_FLAGS_DEBUG "-Og -g3") +set(CMAKE_C_FLAGS_RELEASE "-Oz -g0") +set(CMAKE_CXX_FLAGS_DEBUG "-Og -g3") +set(CMAKE_CXX_FLAGS_RELEASE "-Oz -g0") + +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions -fno-threadsafe-statics") + +set(CMAKE_EXE_LINKER_FLAGS "${TARGET_FLAGS}") + +if (STARM_TOOLCHAIN_CONFIG STREQUAL "STARM_HYBRID") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --gcc-specs=nano.specs") + set(TOOLCHAIN_LINK_LIBRARIES "m") +elseif(STARM_TOOLCHAIN_CONFIG STREQUAL "STARM_NEWLIB") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lcrt0-nosys") +elseif(STARM_TOOLCHAIN_CONFIG STREQUAL "STARM_PICOLIBC") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lcrt0-hosted -z norelro") + +endif() + +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T \"${CMAKE_SOURCE_DIR}/STM32F103XX_FLASH.ld\"") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z noexecstack") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--print-memory-usage ") diff --git a/cmake/stm32cubemx/CMakeLists.txt b/cmake/stm32cubemx/CMakeLists.txt new file mode 100644 index 0000000..50df1fd --- /dev/null +++ b/cmake/stm32cubemx/CMakeLists.txt @@ -0,0 +1,116 @@ +cmake_minimum_required(VERSION 3.22) +# Enable CMake support for ASM and C languages +enable_language(C ASM) +# STM32CubeMX generated symbols (macros) +set(MX_Defines_Syms + USE_HAL_DRIVER + STM32F103xB + $<$:DEBUG> +) + +# STM32CubeMX generated include paths +set(MX_Include_Dirs + ${CMAKE_CURRENT_SOURCE_DIR}/../../Core/Inc + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Inc + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Inc/Legacy + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Middlewares/Third_Party/FreeRTOS/Source/include + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3 + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/CMSIS/Device/ST/STM32F1xx/Include + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/CMSIS/Include +) + +# STM32CubeMX generated application sources +set(MX_Application_Src + ${CMAKE_CURRENT_SOURCE_DIR}/../../Core/Src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../Core/Src/gpio.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../Core/Src/freertos.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../Core/Src/dma.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../Core/Src/i2c.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../Core/Src/usart.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../Core/Src/stm32f1xx_it.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../Core/Src/stm32f1xx_hal_msp.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../Core/Src/stm32f1xx_hal_timebase_tim.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../Core/Src/sysmem.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../Core/Src/syscalls.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../startup_stm32f103xb.s +) + +# STM32 HAL/LL Drivers +set(STM32_Drivers_Src + ${CMAKE_CURRENT_SOURCE_DIR}/../../Core/Src/system_stm32f1xx.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c +) + +# Drivers Midllewares + + +set(FreeRTOS_Src + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Middlewares/Third_Party/FreeRTOS/Source/croutine.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Middlewares/Third_Party/FreeRTOS/Source/event_groups.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Middlewares/Third_Party/FreeRTOS/Source/list.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Middlewares/Third_Party/FreeRTOS/Source/queue.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Middlewares/Third_Party/FreeRTOS/Source/stream_buffer.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Middlewares/Third_Party/FreeRTOS/Source/tasks.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Middlewares/Third_Party/FreeRTOS/Source/timers.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c + C:/Users/BeihongWang/STM32Cube/Repository/STM32Cube_FW_F1_V1.8.7/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c +) + +# Link directories setup +set(MX_LINK_DIRS + +) +# Project static libraries +set(MX_LINK_LIBS + STM32_Drivers + ${TOOLCHAIN_LINK_LIBRARIES} + FreeRTOS +) +# Interface library for includes and symbols +add_library(stm32cubemx INTERFACE) +target_include_directories(stm32cubemx INTERFACE ${MX_Include_Dirs}) +target_compile_definitions(stm32cubemx INTERFACE ${MX_Defines_Syms}) + +# Create STM32_Drivers static library +add_library(STM32_Drivers OBJECT) +target_sources(STM32_Drivers PRIVATE ${STM32_Drivers_Src}) +target_link_libraries(STM32_Drivers PUBLIC stm32cubemx) + + +# Create FreeRTOS static library +add_library(FreeRTOS OBJECT) +target_sources(FreeRTOS PRIVATE ${FreeRTOS_Src}) +target_link_libraries(FreeRTOS PUBLIC stm32cubemx) + +# Add STM32CubeMX generated application sources to the project +target_sources(${CMAKE_PROJECT_NAME} PRIVATE ${MX_Application_Src}) + +# Link directories setup +target_link_directories(${CMAKE_PROJECT_NAME} PRIVATE ${MX_LINK_DIRS}) + +# Add libraries to the project +target_link_libraries(${CMAKE_PROJECT_NAME} ${MX_LINK_LIBS}) + +# Add the map file to the list of files to be removed with 'clean' target +set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES ADDITIONAL_CLEAN_FILES ${CMAKE_PROJECT_NAME}.map) + +# Validate that STM32CubeMX code is compatible with C standard +if((CMAKE_C_STANDARD EQUAL 90) OR (CMAKE_C_STANDARD EQUAL 99)) + message(ERROR "Generated code requires C11 or higher") +endif() diff --git a/mqtt_web/app.py b/mqtt_web/app.py new file mode 100644 index 0000000..5cfefc7 --- /dev/null +++ b/mqtt_web/app.py @@ -0,0 +1,159 @@ +""" +3D Printer STM32 MQTT Web Control Panel +======================================== +Broker: mqtt.beihong.wang:1883 +Subscribe: /3D/message/put (STM32 responses) +Publish: /3D/message (commands to STM32) +""" + +import json +import time +import threading +import queue +from flask import Flask, render_template, jsonify, request, Response +import paho.mqtt.client as mqtt + +app = Flask(__name__) + +# --- MQTT Config --- +MQTT_BROKER = "mqtt.beihong.wang" +MQTT_PORT = 1883 +MQTT_USER = "3D_Stm32" +MQTT_PASS = "123456" +MQTT_CLIENT_ID = "3D_WebPanel" +MQTT_TOPIC_PUB = "/3D/message" +MQTT_TOPIC_SUB = "/3D/message/put" + +# --- Message queue for SSE --- +msg_queue = queue.Queue() + +# --- MQTT connection state --- +mqtt_state = {"connected": False} + + +def on_connect(client, userdata, flags, reason_code, properties=None): + if reason_code == 0: + mqtt_state["connected"] = True + client.subscribe(MQTT_TOPIC_SUB, qos=1) + print(f"[MQTT] Connected, subscribed to {MQTT_TOPIC_SUB}") + else: + mqtt_state["connected"] = False + print(f"[MQTT] Connect failed, code={reason_code}") + + +def on_disconnect(client, userdata, reason_code, properties=None): + mqtt_state["connected"] = False + print(f"[MQTT] Disconnected, code={reason_code}") + + +def on_message(client, userdata, msg): + try: + payload = msg.payload.decode("utf-8", errors="replace") + print(f"[MQTT] << {msg.topic}: {payload}") + msg_queue.put({"topic": msg.topic, "payload": payload, "time": time.strftime("%H:%M:%S")}) + except Exception as e: + print(f"[MQTT] Message decode error: {e}") + + +def mqtt_loop(): + client = mqtt.Client(callback_api_version=mqtt.CallbackAPIVersion.VERSION2, + client_id=MQTT_CLIENT_ID) + client.username_pw_set(MQTT_USER, MQTT_PASS) + client.on_connect = on_connect + client.on_disconnect = on_disconnect + client.on_message = on_message + + while True: + try: + print(f"[MQTT] Connecting to {MQTT_BROKER}:{MQTT_PORT} ...") + client.connect(MQTT_BROKER, MQTT_PORT, keepalive=60) + client.loop_forever() + except Exception as e: + print(f"[MQTT] Error: {e}, retrying in 5s ...") + mqtt_state["connected"] = False + time.sleep(5) + + +# --- Flask routes --- + +@app.route("/") +def index(): + return render_template("index.html") + + +@app.route("/api/status") +def api_status(): + return jsonify({"connected": mqtt_state["connected"]}) + + +@app.route("/api/send", methods=["POST"]) +def api_send(): + data = request.get_json(force=True, silent=True) + if not data: + return jsonify({"ok": False, "msg": "invalid json"}), 400 + + if not mqtt_state["connected"]: + return jsonify({"ok": False, "msg": "mqtt disconnected"}), 503 + + try: + payload = json.dumps(data, separators=(',', ':'), ensure_ascii=False) + # Publish to MQTT broker + mqtt_client.publish(MQTT_TOPIC_PUB, payload, qos=1) + print(f"[MQTT] >> {MQTT_TOPIC_PUB}: {payload}") + return jsonify({"ok": True}) + except Exception as e: + return jsonify({"ok": False, "msg": str(e)}), 500 + + +@app.route("/api/stream") +def api_stream(): + """Server-Sent Events endpoint for real-time messages""" + def generate(): + while True: + try: + msg = msg_queue.get(timeout=25) + yield f"data: {json.dumps(msg, ensure_ascii=False)}\n\n" + except queue.Empty: + yield ": keepalive\n\n" + + resp = Response(generate(), mimetype="text/event-stream") + resp.headers["Cache-Control"] = "no-cache" + resp.headers["X-Accel-Buffering"] = "no" + return resp + + +@app.route("/api/poll") +def api_poll(): + """轮询获取新消息""" + try: + msg = msg_queue.get_nowait() + return jsonify(msg) + except queue.Empty: + return jsonify({"msg": None}) + + +# --- Global MQTT client reference --- +mqtt_client = None + + +@app.before_request +def ensure_mqtt_client(): + global mqtt_client + if mqtt_client is None: + # Create a client just for publishing (the loop thread has its own) + mqtt_client = mqtt.Client(callback_api_version=mqtt.CallbackAPIVersion.VERSION2, + client_id=MQTT_CLIENT_ID + "_pub") + mqtt_client.username_pw_set(MQTT_USER, MQTT_PASS) + try: + mqtt_client.connect(MQTT_BROKER, MQTT_PORT, keepalive=60) + mqtt_client.loop_start() + except Exception: + pass + + +if __name__ == "__main__": + # Start MQTT background thread + t = threading.Thread(target=mqtt_loop, daemon=True) + t.start() + # Start Flask web server + app.run(host="127.0.0.1", port=3000, debug=False) diff --git a/mqtt_web/requirements.txt b/mqtt_web/requirements.txt new file mode 100644 index 0000000..ce4b016 --- /dev/null +++ b/mqtt_web/requirements.txt @@ -0,0 +1,2 @@ +flask>=3.0 +paho-mqtt>=2.0 diff --git a/mqtt_web/templates/index.html b/mqtt_web/templates/index.html new file mode 100644 index 0000000..dad5531 --- /dev/null +++ b/mqtt_web/templates/index.html @@ -0,0 +1,158 @@ + + + + + +3D打印控制面板 + + + + +
+

3D 打印控制面板

+
连接中...
+
+ +
+ +
+
查询
+
+ + +
+
+ +
+
灯光
+
+ + +
+
+ +
+
风扇开关
+
+ + +
+
+ + + +
+
+ +
+
风扇阈值
+
+ + + 30 + +
+
+ +
+
自定义指令
+ +
+ +
+
+ +
+
+ 消息日志 + +
+
+
等待消息...
+
+
+ +
+ +
mqtt.beihong.wang · /3D/message → STM32 · /3D/message/put ← STM32
+ + + + diff --git a/startup_stm32f103xb.s b/startup_stm32f103xb.s new file mode 100644 index 0000000..7614285 --- /dev/null +++ b/startup_stm32f103xb.s @@ -0,0 +1,364 @@ +/** + *************** (C) COPYRIGHT 2017 STMicroelectronics ************************ + * @file startup_stm32f103xb.s + * @author MCD Application Team + * @brief STM32F103xB Devices vector table for Atollic toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Configure the clock system + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M3 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017-2021 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. + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m3 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss + +.equ BootRAM, 0xF108F85F +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + +/* Call the clock system initialization function.*/ + bl SystemInit + +/* Copy the data segment initializers from flash to SRAM */ + ldr r0, =_sdata + ldr r1, =_edata + ldr r2, =_sidata + movs r3, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +LoopCopyDataInit: + adds r4, r0, r3 + cmp r4, r1 + bcc CopyDataInit + +/* Zero fill the bss segment. */ + ldr r2, =_sbss + ldr r4, =_ebss + movs r3, #0 + b LoopFillZerobss + +FillZerobss: + str r3, [r2] + adds r2, r2, #4 + +LoopFillZerobss: + cmp r2, r4 + bcc FillZerobss + +/* Call static constructors */ + bl __libc_init_array +/* Call the application's entry point.*/ + bl main + bx lr +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * + * @param None + * @retval : None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M3. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + .word WWDG_IRQHandler + .word PVD_IRQHandler + .word TAMPER_IRQHandler + .word RTC_IRQHandler + .word FLASH_IRQHandler + .word RCC_IRQHandler + .word EXTI0_IRQHandler + .word EXTI1_IRQHandler + .word EXTI2_IRQHandler + .word EXTI3_IRQHandler + .word EXTI4_IRQHandler + .word DMA1_Channel1_IRQHandler + .word DMA1_Channel2_IRQHandler + .word DMA1_Channel3_IRQHandler + .word DMA1_Channel4_IRQHandler + .word DMA1_Channel5_IRQHandler + .word DMA1_Channel6_IRQHandler + .word DMA1_Channel7_IRQHandler + .word ADC1_2_IRQHandler + .word USB_HP_CAN1_TX_IRQHandler + .word USB_LP_CAN1_RX0_IRQHandler + .word CAN1_RX1_IRQHandler + .word CAN1_SCE_IRQHandler + .word EXTI9_5_IRQHandler + .word TIM1_BRK_IRQHandler + .word TIM1_UP_IRQHandler + .word TIM1_TRG_COM_IRQHandler + .word TIM1_CC_IRQHandler + .word TIM2_IRQHandler + .word TIM3_IRQHandler + .word TIM4_IRQHandler + .word I2C1_EV_IRQHandler + .word I2C1_ER_IRQHandler + .word I2C2_EV_IRQHandler + .word I2C2_ER_IRQHandler + .word SPI1_IRQHandler + .word SPI2_IRQHandler + .word USART1_IRQHandler + .word USART2_IRQHandler + .word USART3_IRQHandler + .word EXTI15_10_IRQHandler + .word RTC_Alarm_IRQHandler + .word USBWakeUp_IRQHandler + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word BootRAM /* @0x108. This is for boot in RAM mode for + STM32F10x Medium Density devices. */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMPER_IRQHandler + .thumb_set TAMPER_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Channel1_IRQHandler + .thumb_set DMA1_Channel1_IRQHandler,Default_Handler + + .weak DMA1_Channel2_IRQHandler + .thumb_set DMA1_Channel2_IRQHandler,Default_Handler + + .weak DMA1_Channel3_IRQHandler + .thumb_set DMA1_Channel3_IRQHandler,Default_Handler + + .weak DMA1_Channel4_IRQHandler + .thumb_set DMA1_Channel4_IRQHandler,Default_Handler + + .weak DMA1_Channel5_IRQHandler + .thumb_set DMA1_Channel5_IRQHandler,Default_Handler + + .weak DMA1_Channel6_IRQHandler + .thumb_set DMA1_Channel6_IRQHandler,Default_Handler + + .weak DMA1_Channel7_IRQHandler + .thumb_set DMA1_Channel7_IRQHandler,Default_Handler + + .weak ADC1_2_IRQHandler + .thumb_set ADC1_2_IRQHandler,Default_Handler + + .weak USB_HP_CAN1_TX_IRQHandler + .thumb_set USB_HP_CAN1_TX_IRQHandler,Default_Handler + + .weak USB_LP_CAN1_RX0_IRQHandler + .thumb_set USB_LP_CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_IRQHandler + .thumb_set TIM1_BRK_IRQHandler,Default_Handler + + .weak TIM1_UP_IRQHandler + .thumb_set TIM1_UP_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_IRQHandler + .thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak USBWakeUp_IRQHandler + .thumb_set USBWakeUp_IRQHandler,Default_Handler + +