Trinity Devboard PCB V1.0 Firmware. FreeRTOS is setup and the MCU reads IMU data over SPI fand Magnetometer data over I2C, each with a seperate task. Sensordata is then run though MadgwickAHRS and send over USB as serial packet data to use in trinity visualizer. Bare minimum functionality works and is replicated from the first prototype.
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/*
|
||||
* FreeRTOS Kernel V10.6.2
|
||||
* 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(__ARMCC_VERSION) || defined(__GNUC__)
|
||||
#include <stdint.h>
|
||||
extern uint32_t SystemCoreClock;
|
||||
#endif
|
||||
#ifndef CMSIS_device_header
|
||||
#define CMSIS_device_header "stm32wbxx.h"
|
||||
#endif /* CMSIS_device_header */
|
||||
|
||||
#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 ( 56 )
|
||||
#define configUSE_SB_COMPLETED_CALLBACK ( 0 )
|
||||
#define configUSE_MINI_LIST_ITEM ( 1 )
|
||||
#define configMINIMAL_STACK_SIZE ((uint16_t)512)
|
||||
#define configTOTAL_HEAP_SIZE ((size_t)64000)
|
||||
#define configMAX_TASK_NAME_LEN ( 16 )
|
||||
#define configHEAP_CLEAR_MEMORY_ON_FREE 0
|
||||
#define configUSE_TRACE_FACILITY 1
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
#define configUSE_MUTEXES 1
|
||||
#define configQUEUE_REGISTRY_SIZE 8
|
||||
#define configUSE_RECURSIVE_MUTEXES 1
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
|
||||
/* 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 )
|
||||
|
||||
/* Software timer definitions. */
|
||||
#define configUSE_TIMERS 1
|
||||
#define configTIMER_TASK_PRIORITY ( 2 )
|
||||
#define configTIMER_QUEUE_LENGTH 10
|
||||
#define configTIMER_TASK_STACK_DEPTH 1024
|
||||
|
||||
/* CMSIS-RTOS V2 flags */
|
||||
#define configUSE_OS2_THREAD_SUSPEND_RESUME 1
|
||||
#define configUSE_OS2_THREAD_ENUMERATE 1
|
||||
#define configUSE_OS2_EVENTFLAGS_FROM_ISR 1
|
||||
#define configUSE_OS2_THREAD_FLAGS 1
|
||||
#define configUSE_OS2_TIMER 1
|
||||
#define configUSE_OS2_MUTEX 1
|
||||
/* 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 1
|
||||
#define INCLUDE_vTaskDelay 1
|
||||
#define INCLUDE_xTaskGetSchedulerState 1
|
||||
#define INCLUDE_xTimerPendFunctionCall 1
|
||||
#define INCLUDE_xQueueGetMutexHolder 1
|
||||
#define INCLUDE_uxTaskGetStackHighWaterMark 1
|
||||
#define INCLUDE_xTaskGetCurrentTaskHandle 1
|
||||
#define INCLUDE_eTaskGetState 1
|
||||
|
||||
/*
|
||||
* The CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation used
|
||||
* by the application thus the correct define need to be enabled below
|
||||
*/
|
||||
#define USE_FreeRTOS_HEAP_4
|
||||
|
||||
/* 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: After 10.3.1 update, Systick_Handler comes from NVIC (if SYS timebase = systick), otherwise from cmsis_os2.c */
|
||||
|
||||
#define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 0
|
||||
|
||||
/* 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 */
|
||||
@@ -0,0 +1,113 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file app_common.h
|
||||
* @author MCD Application Team
|
||||
* @brief App Common application configuration file for STM32WPAN Middleware.
|
||||
******************************************************************************
|
||||
* @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 APP_COMMON_H
|
||||
#define APP_COMMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "app_conf.h"
|
||||
|
||||
/* -------------------------------- *
|
||||
* Basic definitions *
|
||||
* -------------------------------- */
|
||||
#undef NULL
|
||||
#define NULL 0
|
||||
|
||||
#undef FALSE
|
||||
#define FALSE 0
|
||||
|
||||
#undef TRUE
|
||||
#define TRUE (!0)
|
||||
|
||||
/* -------------------------------- *
|
||||
* Critical Section definition *
|
||||
* -------------------------------- */
|
||||
#define BACKUP_PRIMASK() uint32_t primask_bit= __get_PRIMASK()
|
||||
#define DISABLE_IRQ() __disable_irq()
|
||||
#define RESTORE_PRIMASK() __set_PRIMASK(primask_bit)
|
||||
|
||||
/* -------------------------------- *
|
||||
* Macro delimiters *
|
||||
* -------------------------------- */
|
||||
#define M_BEGIN do {
|
||||
|
||||
#define M_END } while(0)
|
||||
|
||||
/* -------------------------------- *
|
||||
* Some useful macro definitions *
|
||||
* -------------------------------- */
|
||||
#ifndef MAX
|
||||
#define MAX( x, y ) (((x)>(y))?(x):(y))
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN( x, y ) (((x)<(y))?(x):(y))
|
||||
#endif
|
||||
|
||||
#define MODINC( a, m ) M_BEGIN (a)++; if ((a)>=(m)) (a)=0; M_END
|
||||
|
||||
#define MODDEC( a, m ) M_BEGIN if ((a)==0) (a)=(m); (a)--; M_END
|
||||
|
||||
#define MODADD( a, b, m ) M_BEGIN (a)+=(b); if ((a)>=(m)) (a)-=(m); M_END
|
||||
|
||||
#define MODSUB( a, b, m ) MODADD( a, (m)-(b), m )
|
||||
|
||||
#define PAUSE( t ) M_BEGIN \
|
||||
__IO int _i; \
|
||||
for ( _i = t; _i > 0; _i -- ); \
|
||||
M_END
|
||||
|
||||
#define DIVF( x, y ) ((x)/(y))
|
||||
|
||||
#define DIVC( x, y ) (((x)+(y)-1)/(y))
|
||||
|
||||
#define DIVR( x, y ) (((x)+((y)/2))/(y))
|
||||
|
||||
#define SHRR( x, n ) ((((x)>>((n)-1))+1)>>1)
|
||||
|
||||
#define BITN( w, n ) (((w)[(n)/32] >> ((n)%32)) & 1)
|
||||
|
||||
#define BITNSET( w, n, b ) M_BEGIN (w)[(n)/32] |= ((U32)(b))<<((n)%32); M_END
|
||||
|
||||
/* -------------------------------- *
|
||||
* Compiler *
|
||||
* -------------------------------- */
|
||||
#define PLACE_IN_SECTION( __x__ ) __attribute__((section (__x__)))
|
||||
|
||||
#ifdef WIN32
|
||||
#define ALIGN(n)
|
||||
#else
|
||||
#define ALIGN(n) __attribute__((aligned(n)))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*APP_COMMON_H */
|
||||
@@ -0,0 +1,681 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file app_conf.h
|
||||
* @author MCD Application Team
|
||||
* @brief Application configuration file for STM32WPAN Middleware.
|
||||
******************************************************************************
|
||||
* @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 APP_CONF_H
|
||||
#define APP_CONF_H
|
||||
|
||||
#include "hw.h"
|
||||
#include "hw_conf.h"
|
||||
#include "hw_if.h"
|
||||
#include "ble_bufsize.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Application Config
|
||||
******************************************************************************/
|
||||
/**< generic parameters ******************************************************/
|
||||
|
||||
/**
|
||||
* Define Tx Power
|
||||
*/
|
||||
#define CFG_TX_POWER (0x18) /* -0.15dBm */
|
||||
|
||||
/**
|
||||
* Define Advertising parameters
|
||||
*/
|
||||
#define CFG_ADV_BD_ADDRESS (0x11aabbccddee)
|
||||
|
||||
#define CFG_FAST_CONN_ADV_INTERVAL_MIN (0x80) /**< 80ms */
|
||||
#define CFG_FAST_CONN_ADV_INTERVAL_MAX (0xA0) /**< 100ms */
|
||||
#define CFG_LP_CONN_ADV_INTERVAL_MIN (0x640) /**< 1s */
|
||||
#define CFG_LP_CONN_ADV_INTERVAL_MAX (0xFA0) /**< 2.5s */
|
||||
#define ADV_TYPE
|
||||
#define BLE_ADDR_TYPE GAP_PUBLIC_ADDR
|
||||
#define ADV_FILTER
|
||||
/**
|
||||
* Define IO Authentication
|
||||
*/
|
||||
#define CFG_BONDING_MODE (0)
|
||||
#define CFG_ENCRYPTION_KEY_SIZE_MAX (16)
|
||||
#define CFG_ENCRYPTION_KEY_SIZE_MIN (8)
|
||||
|
||||
/**
|
||||
* Define IO capabilities
|
||||
*/
|
||||
#define CFG_IO_CAPABILITY_DISPLAY_ONLY (0x00)
|
||||
#define CFG_IO_CAPABILITY_DISPLAY_YES_NO (0x01)
|
||||
#define CFG_IO_CAPABILITY_KEYBOARD_ONLY (0x02)
|
||||
#define CFG_IO_CAPABILITY_NO_INPUT_NO_OUTPUT (0x03)
|
||||
#define CFG_IO_CAPABILITY_KEYBOARD_DISPLAY (0x04)
|
||||
|
||||
#define CFG_IO_CAPABILITY CFG_IO_CAPABILITY_DISPLAY_YES_NO
|
||||
|
||||
/**
|
||||
* Define MITM modes
|
||||
*/
|
||||
#define CFG_MITM_PROTECTION_NOT_REQUIRED (0x00)
|
||||
#define CFG_MITM_PROTECTION_REQUIRED (0x01)
|
||||
|
||||
#define CFG_MITM_PROTECTION CFG_MITM_PROTECTION_REQUIRED
|
||||
|
||||
/**
|
||||
* Define Secure Connections Support
|
||||
*/
|
||||
#define CFG_SECURE_NOT_SUPPORTED (0x00)
|
||||
#define CFG_SECURE_OPTIONAL (0x01)
|
||||
#define CFG_SECURE_MANDATORY (0x02)
|
||||
|
||||
#define CFG_SC_SUPPORT CFG_SECURE_OPTIONAL
|
||||
|
||||
/**
|
||||
* Define Keypress Notification Support
|
||||
*/
|
||||
#define CFG_KEYPRESS_NOT_SUPPORTED (0x00)
|
||||
#define CFG_KEYPRESS_SUPPORTED (0x01)
|
||||
|
||||
#define CFG_KEYPRESS_NOTIFICATION_SUPPORT CFG_KEYPRESS_NOT_SUPPORTED
|
||||
|
||||
/**
|
||||
* Numeric Comparison Answers
|
||||
*/
|
||||
#define YES (0x01)
|
||||
#define NO (0x00)
|
||||
|
||||
/**
|
||||
* Device name configuration for Generic Access Service
|
||||
*/
|
||||
#define CFG_GAP_DEVICE_NAME "TEMPLATE"
|
||||
#define CFG_GAP_DEVICE_NAME_LENGTH (8)
|
||||
|
||||
/**
|
||||
* Define PHY
|
||||
*/
|
||||
#define ALL_PHYS_PREFERENCE 0x00
|
||||
#define RX_2M_PREFERRED 0x02
|
||||
#define TX_2M_PREFERRED 0x02
|
||||
#define TX_1M 0x01
|
||||
#define TX_2M 0x02
|
||||
#define RX_1M 0x01
|
||||
#define RX_2M 0x02
|
||||
|
||||
/**
|
||||
* Identity root key used to derive IRK and DHK(Legacy)
|
||||
*/
|
||||
#define CFG_BLE_IR {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0}
|
||||
|
||||
/**
|
||||
* Encryption root key used to derive LTK(Legacy) and CSRK
|
||||
*/
|
||||
#define CFG_BLE_ER {0xFE, 0xDC, 0xBA, 0x09, 0x87, 0x65, 0x43, 0x21, 0xFE, 0xDC, 0xBA, 0x09, 0x87, 0x65, 0x43, 0x21}
|
||||
|
||||
/**
|
||||
* SMPS supply
|
||||
* SMPS not used when Set to 0
|
||||
* SMPS used when Set to 1
|
||||
*/
|
||||
#define CFG_USE_SMPS 0
|
||||
|
||||
/* USER CODE BEGIN Generic_Parameters */
|
||||
|
||||
/* USER CODE END Generic_Parameters */
|
||||
|
||||
/**< specific parameters */
|
||||
/*****************************************************/
|
||||
|
||||
/* USER CODE BEGIN Specific_Parameters */
|
||||
|
||||
/* USER CODE END Specific_Parameters */
|
||||
|
||||
/******************************************************************************
|
||||
* BLE Stack
|
||||
******************************************************************************/
|
||||
/**
|
||||
* Maximum number of simultaneous connections that the device will support.
|
||||
* Valid values are from 1 to 8
|
||||
*/
|
||||
#define CFG_BLE_NUM_LINK 2
|
||||
|
||||
/**
|
||||
* Maximum number of Services that can be stored in the GATT database.
|
||||
* Note that the GAP and GATT services are automatically added so this parameter should be 2 plus the number of user services
|
||||
*/
|
||||
#define CFG_BLE_NUM_GATT_SERVICES 8
|
||||
|
||||
/**
|
||||
* Maximum number of Attributes
|
||||
* (i.e. the number of characteristic + the number of characteristic values + the number of descriptors, excluding the services)
|
||||
* that can be stored in the GATT database.
|
||||
* Note that certain characteristics and relative descriptors are added automatically during device initialization
|
||||
* so this parameters should be 9 plus the number of user Attributes
|
||||
*/
|
||||
#define CFG_BLE_NUM_GATT_ATTRIBUTES 68
|
||||
|
||||
/**
|
||||
* Maximum supported ATT_MTU size
|
||||
* This parameter is ignored by the CPU2 when CFG_BLE_OPTIONS has SHCI_C2_BLE_INIT_OPTIONS_LL_ONLY flag set
|
||||
*/
|
||||
#define CFG_BLE_MAX_ATT_MTU (156)
|
||||
|
||||
/**
|
||||
* Size of the storage area for Attribute values
|
||||
* This value depends on the number of attributes used by application. In particular the sum of the following quantities (in octets) should be made for each attribute:
|
||||
* - attribute value length
|
||||
* - 5, if UUID is 16 bit; 19, if UUID is 128 bit
|
||||
* - 2, if server configuration descriptor is used
|
||||
* - 2*DTM_NUM_LINK, if client configuration descriptor is used
|
||||
* - 2, if extended properties is used
|
||||
* The total amount of memory needed is the sum of the above quantities for each attribute.
|
||||
* This parameter is ignored by the CPU2 when CFG_BLE_OPTIONS has SHCI_C2_BLE_INIT_OPTIONS_LL_ONLY flag set
|
||||
*/
|
||||
#define CFG_BLE_ATT_VALUE_ARRAY_SIZE (1344)
|
||||
|
||||
/**
|
||||
* Prepare Write List size in terms of number of packet
|
||||
* This parameter is ignored by the CPU2 when CFG_BLE_OPTIONS has SHCI_C2_BLE_INIT_OPTIONS_LL_ONLY flag set
|
||||
*/
|
||||
#define CFG_BLE_PREPARE_WRITE_LIST_SIZE BLE_PREP_WRITE_X_ATT(CFG_BLE_MAX_ATT_MTU)
|
||||
|
||||
/**
|
||||
* Number of allocated memory blocks
|
||||
* This parameter is overwritten by the CPU2 with an hardcoded optimal value when the parameter CFG_BLE_OPTIONS has SHCI_C2_BLE_INIT_OPTIONS_LL_ONLY flag set
|
||||
*/
|
||||
#define CFG_BLE_MBLOCK_COUNT (BLE_MBLOCKS_CALC(CFG_BLE_PREPARE_WRITE_LIST_SIZE, CFG_BLE_MAX_ATT_MTU, CFG_BLE_NUM_LINK))
|
||||
|
||||
/**
|
||||
* Enable or disable the Extended Packet length feature. Valid values are 0 or 1.
|
||||
*/
|
||||
#define CFG_BLE_DATA_LENGTH_EXTENSION 1
|
||||
|
||||
/**
|
||||
* Sleep clock accuracy in Peripheral mode (ppm value)
|
||||
*/
|
||||
#define CFG_BLE_PERIPHERAL_SCA 500
|
||||
|
||||
/**
|
||||
* Sleep clock accuracy in Central mode
|
||||
* 0 : 251 ppm to 500 ppm
|
||||
* 1 : 151 ppm to 250 ppm
|
||||
* 2 : 101 ppm to 150 ppm
|
||||
* 3 : 76 ppm to 100 ppm
|
||||
* 4 : 51 ppm to 75 ppm
|
||||
* 5 : 31 ppm to 50 ppm
|
||||
* 6 : 21 ppm to 30 ppm
|
||||
* 7 : 0 ppm to 20 ppm
|
||||
*/
|
||||
#define CFG_BLE_CENTRAL_SCA 0
|
||||
|
||||
/**
|
||||
* LsSource
|
||||
* Some information for Low speed clock mapped in bits field
|
||||
* - bit 0: 1: Calibration for the RF system wakeup clock source 0: No calibration for the RF system wakeup clock source
|
||||
* - bit 1: 1: STM32WB5M Module device 0: Other devices as STM32WBxx SOC, STM32WB1M module
|
||||
* - bit 2: 1: HSE/1024 Clock config 0: LSE Clock config
|
||||
*/
|
||||
#if defined(STM32WB5Mxx)
|
||||
#define CFG_BLE_LS_SOURCE (SHCI_C2_BLE_INIT_CFG_BLE_LS_NOCALIB | SHCI_C2_BLE_INIT_CFG_BLE_LS_MOD5MM_DEV | SHCI_C2_BLE_INIT_CFG_BLE_LS_CLK_HSE_1024)
|
||||
#else
|
||||
#define CFG_BLE_LS_SOURCE (SHCI_C2_BLE_INIT_CFG_BLE_LS_NOCALIB | SHCI_C2_BLE_INIT_CFG_BLE_LS_OTHER_DEV | SHCI_C2_BLE_INIT_CFG_BLE_LS_CLK_HSE_1024)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Start up time of the high speed (16 or 32 MHz) crystal oscillator in units of 625/256 us (~2.44 us)
|
||||
*/
|
||||
#define CFG_BLE_HSE_STARTUP_TIME 0x148
|
||||
|
||||
/**
|
||||
* Maximum duration of the connection event when the device is in Peripheral mode in units of 625/256 us (~2.44 us)
|
||||
*/
|
||||
#define CFG_BLE_MAX_CONN_EVENT_LENGTH (0xFFFFFFFF)
|
||||
|
||||
/**
|
||||
* Viterbi Mode
|
||||
* 1 : enabled
|
||||
* 0 : disabled
|
||||
*/
|
||||
#define CFG_BLE_VITERBI_MODE 1
|
||||
|
||||
/**
|
||||
* BLE stack Options flags to be configured with:
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_LL_ONLY
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_LL_HOST
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_NO_SVC_CHANGE_DESC
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_WITH_SVC_CHANGE_DESC
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_DEVICE_NAME_RO
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_DEVICE_NAME_RW
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_NO_EXT_ADV
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_CS_ALGO2
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_NO_CS_ALGO2
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_REDUC_GATTDB_NVM
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_FULL_GATTDB_NVM
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_GATT_CACHING_USED
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_GATT_CACHING_NOTUSED
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_POWER_CLASS_1
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_POWER_CLASS_2_3
|
||||
* which are used to set following configuration bits:
|
||||
* (bit 0): 1: LL only
|
||||
* 0: LL + host
|
||||
* (bit 1): 1: no service change desc.
|
||||
* 0: with service change desc.
|
||||
* (bit 2): 1: device name Read-Only
|
||||
* 0: device name R/W
|
||||
* (bit 3): 1: extended advertizing supported
|
||||
* 0: extended advertizing not supported
|
||||
* (bit 4): 1: CS Algo #2 supported
|
||||
* 0: CS Algo #2 not supported
|
||||
* (bit 5): 1: Reduced GATT database in NVM
|
||||
* 0: Full GATT database in NVM
|
||||
* (bit 6): 1: GATT caching is used
|
||||
* 0: GATT caching is not used
|
||||
* (bit 7): 1: LE Power Class 1
|
||||
* 0: LE Power Class 2-3
|
||||
* other bits: complete with Options_extension flag
|
||||
*/
|
||||
#define CFG_BLE_OPTIONS (SHCI_C2_BLE_INIT_OPTIONS_LL_HOST | SHCI_C2_BLE_INIT_OPTIONS_WITH_SVC_CHANGE_DESC | SHCI_C2_BLE_INIT_OPTIONS_DEVICE_NAME_RW | SHCI_C2_BLE_INIT_OPTIONS_NO_EXT_ADV | SHCI_C2_BLE_INIT_OPTIONS_NO_CS_ALGO2 | SHCI_C2_BLE_INIT_OPTIONS_FULL_GATTDB_NVM | SHCI_C2_BLE_INIT_OPTIONS_GATT_CACHING_NOTUSED | SHCI_C2_BLE_INIT_OPTIONS_POWER_CLASS_2_3)
|
||||
|
||||
/**
|
||||
* BLE stack Options_extension flags to be configured with:
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_APPEARANCE_WRITABLE
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_APPEARANCE_READONLY
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_ENHANCED_ATT_SUPPORTED
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_ENHANCED_ATT_NOTSUPPORTED
|
||||
* which are used to set following configuration bits:
|
||||
* (bit 0): 1: appearance Writable
|
||||
* 0: appearance Read-Only
|
||||
* (bit 1): 1: Enhanced ATT supported
|
||||
* 0: Enhanced ATT not supported
|
||||
* other bits: reserved (shall be set to 0)
|
||||
*/
|
||||
#define CFG_BLE_OPTIONS_EXT (SHCI_C2_BLE_INIT_OPTIONS_APPEARANCE_READONLY | SHCI_C2_BLE_INIT_OPTIONS_ENHANCED_ATT_NOTSUPPORTED)
|
||||
|
||||
#define CFG_BLE_MAX_COC_INITIATOR_NBR (32)
|
||||
|
||||
#define CFG_BLE_MIN_TX_POWER (0)
|
||||
|
||||
#define CFG_BLE_MAX_TX_POWER (0)
|
||||
|
||||
/**
|
||||
* BLE stack Maximum number of created Enhanced ATT bearers to be configured
|
||||
* in addition to the number of links
|
||||
* - Range: 0 .. 4
|
||||
*/
|
||||
#define CFG_BLE_MAX_ADD_EATT_BEARERS (4)
|
||||
|
||||
/**
|
||||
* BLE Rx model configuration flags to be configured with:
|
||||
* - SHCI_C2_BLE_INIT_RX_MODEL_AGC_RSSI_LEGACY
|
||||
* - SHCI_C2_BLE_INIT_RX_MODEL_AGC_RSSI_BLOCKER
|
||||
* which are used to set following configuration bits:
|
||||
* (bit 0): 1: agc_rssi model improved vs RF blockers
|
||||
* 0: Legacy agc_rssi model
|
||||
* other bits: reserved (shall be set to 0)
|
||||
*/
|
||||
|
||||
#define CFG_BLE_RX_MODEL_CONFIG (SHCI_C2_BLE_INIT_RX_MODEL_AGC_RSSI_LEGACY)
|
||||
|
||||
/* Maximum number of advertising sets.
|
||||
* Range: 1 .. 8 with limitation:
|
||||
* This parameter is linked to CFG_BLE_MAX_ADV_DATA_LEN such as both compliant with allocated Total memory computed with BLE_EXT_ADV_BUFFER_SIZE based
|
||||
* on Max Extended advertising configuration supported.
|
||||
* This parameter is considered by the CPU2 when CFG_BLE_OPTIONS has SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV flag set
|
||||
*/
|
||||
|
||||
#define CFG_BLE_MAX_ADV_SET_NBR (3)
|
||||
|
||||
/* Maximum advertising data length (in bytes)
|
||||
* Range: 31 .. 1650 with limitation:
|
||||
* This parameter is linked to CFG_BLE_MAX_ADV_SET_NBR such as both compliant with allocated Total memory computed with BLE_EXT_ADV_BUFFER_SIZE based
|
||||
* on Max Extended advertising configuration supported.
|
||||
* This parameter is considered by the CPU2 when CFG_BLE_OPTIONS has SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV flag set
|
||||
*/
|
||||
|
||||
#define CFG_BLE_MAX_ADV_DATA_LEN (1650)
|
||||
|
||||
/* RF TX Path Compensation Value (16-bit signed integer). Units: 0.1 dB.
|
||||
* Range: -1280 .. 1280
|
||||
*/
|
||||
|
||||
#define CFG_BLE_TX_PATH_COMPENS (0)
|
||||
|
||||
/* RF RX Path Compensation Value (16-bit signed integer). Units: 0.1 dB.
|
||||
* Range: -1280 .. 1280
|
||||
*/
|
||||
|
||||
#define CFG_BLE_RX_PATH_COMPENS (0)
|
||||
|
||||
/* BLE core version (16-bit signed integer).
|
||||
* - SHCI_C2_BLE_INIT_BLE_CORE_5_2
|
||||
* - SHCI_C2_BLE_INIT_BLE_CORE_5_3
|
||||
* - SHCI_C2_BLE_INIT_BLE_CORE_5_4
|
||||
* which are used to set: 11(5.2), 12(5.3), 13(5.4).
|
||||
*/
|
||||
|
||||
#define CFG_BLE_CORE_VERSION (SHCI_C2_BLE_INIT_BLE_CORE_5_4)
|
||||
|
||||
/******************************************************************************
|
||||
* Transport Layer
|
||||
******************************************************************************/
|
||||
/**
|
||||
* Queue length of BLE Event
|
||||
* This parameter defines the number of asynchronous events that can be stored in the HCI layer before
|
||||
* being reported to the application. When a command is sent to the BLE core coprocessor, the HCI layer
|
||||
* is waiting for the event with the Num_HCI_Command_Packets set to 1. The receive queue shall be large
|
||||
* enough to store all asynchronous events received in between.
|
||||
* When CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE is set to 27, this allow to store three 255 bytes long asynchronous events
|
||||
* between the HCI command and its event.
|
||||
* This parameter depends on the value given to CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE. When the queue size is to small,
|
||||
* the system may hang if the queue is full with asynchronous events and the HCI layer is still waiting
|
||||
* for a CC/CS event, In that case, the notification TL_BLE_HCI_ToNot() is called to indicate
|
||||
* to the application a HCI command did not receive its command event within 30s (Default HCI Timeout).
|
||||
*/
|
||||
#define CFG_TLBLE_EVT_QUEUE_LENGTH 5
|
||||
/**
|
||||
* This parameter should be set to fit most events received by the HCI layer. It defines the buffer size of each element
|
||||
* allocated in the queue of received events and can be used to optimize the amount of RAM allocated by the Memory Manager.
|
||||
* It should not exceed 255 which is the maximum HCI packet payload size (a greater value is a lost of memory as it will
|
||||
* never be used)
|
||||
* It shall be at least 4 to receive the command status event in one frame.
|
||||
* The default value is set to 27 to allow receiving an event of MTU size in a single buffer. This value maybe reduced
|
||||
* further depending on the application.
|
||||
*/
|
||||
#define CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE 255 /**< Set to 255 with the memory manager and the mailbox */
|
||||
|
||||
#define TL_BLE_EVENT_FRAME_SIZE ( TL_EVT_HDR_SIZE + CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE )
|
||||
/******************************************************************************
|
||||
* UART interfaces
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Select UART interfaces
|
||||
*/
|
||||
#define CFG_DEBUG_TRACE_UART 0
|
||||
#define CFG_CONSOLE_MENU 0
|
||||
/******************************************************************************
|
||||
* USB interface
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Enable/Disable USB interface
|
||||
*/
|
||||
#define CFG_USB_INTERFACE_ENABLE 0
|
||||
|
||||
/******************************************************************************
|
||||
* IPCC interface
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* The IPCC is dedicated to the communication between the CPU2 and the CPU1
|
||||
* and shall not be modified by the application
|
||||
* The two following definitions shall not be modified
|
||||
*/
|
||||
#define HAL_IPCC_TX_IRQHandler(...) HW_IPCC_Tx_Handler( )
|
||||
#define HAL_IPCC_RX_IRQHandler(...) HW_IPCC_Rx_Handler( )
|
||||
|
||||
/******************************************************************************
|
||||
* Low Power
|
||||
******************************************************************************/
|
||||
/**
|
||||
* When set to 1, the low power mode is enable
|
||||
* When set to 0, the device stays in RUN mode
|
||||
*/
|
||||
#define CFG_LPM_SUPPORTED 0
|
||||
|
||||
/******************************************************************************
|
||||
* RTC interface
|
||||
******************************************************************************/
|
||||
#define HAL_RTCEx_WakeUpTimerIRQHandler(...) HW_TS_RTC_Wakeup_Handler( )
|
||||
|
||||
/******************************************************************************
|
||||
* Timer Server
|
||||
******************************************************************************/
|
||||
/**
|
||||
* CFG_RTC_WUCKSEL_DIVIDER: This sets the RTCCLK divider to the wakeup timer.
|
||||
* The lower is the value, the better is the power consumption and the accuracy of the timerserver
|
||||
* The higher is the value, the finest is the granularity
|
||||
*
|
||||
* CFG_RTC_ASYNCH_PRESCALER: This sets the asynchronous prescaler of the RTC. It should as high as possible ( to output
|
||||
* clock as low as possible) but the output clock should be equal or higher frequency compare to the clock feeding
|
||||
* the wakeup timer. A lower clock speed would impact the accuracy of the timer server.
|
||||
*
|
||||
* CFG_RTC_SYNCH_PRESCALER: This sets the synchronous prescaler of the RTC.
|
||||
* When the 1Hz calendar clock is required, it shall be sets according to other settings
|
||||
* When the 1Hz calendar clock is not needed, CFG_RTC_SYNCH_PRESCALER should be set to 0x7FFF (MAX VALUE)
|
||||
*
|
||||
* CFG_RTCCLK_DIVIDER_CONF:
|
||||
* Shall be set to either 0,2,4,8,16
|
||||
* When set to either 2,4,8,16, the 1Hhz calendar is supported
|
||||
* When set to 0, the user sets its own configuration
|
||||
*
|
||||
* The following settings are computed with LSI as input to the RTC
|
||||
*/
|
||||
|
||||
#define CFG_RTCCLK_DIVIDER_CONF 0
|
||||
|
||||
#if (CFG_RTCCLK_DIVIDER_CONF == 0)
|
||||
/**
|
||||
* Custom configuration
|
||||
* It does not support 1Hz calendar
|
||||
* It divides the RTC CLK by 16
|
||||
*/
|
||||
|
||||
#define CFG_RTCCLK_DIV (16)
|
||||
#define CFG_RTC_WUCKSEL_DIVIDER (0)
|
||||
#define CFG_RTC_ASYNCH_PRESCALER (0x0F)
|
||||
#define CFG_RTC_SYNCH_PRESCALER (0x7FFF)
|
||||
|
||||
#else
|
||||
|
||||
#if (CFG_RTCCLK_DIVIDER_CONF == 2)
|
||||
/**
|
||||
* It divides the RTC CLK by 2
|
||||
*/
|
||||
#define CFG_RTC_WUCKSEL_DIVIDER (3)
|
||||
#endif
|
||||
|
||||
#if (CFG_RTCCLK_DIVIDER_CONF == 4)
|
||||
/**
|
||||
* It divides the RTC CLK by 4
|
||||
*/
|
||||
#define CFG_RTC_WUCKSEL_DIVIDER (2)
|
||||
#endif
|
||||
|
||||
#if (CFG_RTCCLK_DIVIDER_CONF == 8)
|
||||
/**
|
||||
* It divides the RTC CLK by 8
|
||||
*/
|
||||
#define CFG_RTC_WUCKSEL_DIVIDER (1)
|
||||
#endif
|
||||
|
||||
#if (CFG_RTCCLK_DIVIDER_CONF == 16)
|
||||
/**
|
||||
* It divides the RTC CLK by 16
|
||||
*/
|
||||
#define CFG_RTC_WUCKSEL_DIVIDER (0)
|
||||
#endif
|
||||
|
||||
#define CFG_RTCCLK_DIV CFG_RTCCLK_DIVIDER_CONF
|
||||
#define CFG_RTC_ASYNCH_PRESCALER (CFG_RTCCLK_DIV - 1)
|
||||
#define CFG_RTC_SYNCH_PRESCALER (DIVR( LSE_VALUE, (CFG_RTC_ASYNCH_PRESCALER+1) ) - 1 )
|
||||
|
||||
#endif
|
||||
|
||||
/** tick timer values */
|
||||
#define CFG_TS_TICK_VAL DIVR( (CFG_RTCCLK_DIV * 1000000), LSE_VALUE )
|
||||
#define CFG_TS_TICK_VAL_PS DIVR( ((uint64_t)CFG_RTCCLK_DIV * 1e12), (uint64_t)LSE_VALUE )
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CFG_TIM_PROC_ID_ISR,
|
||||
/* USER CODE BEGIN CFG_TimProcID_t */
|
||||
|
||||
/* USER CODE END CFG_TimProcID_t */
|
||||
} CFG_TimProcID_t;
|
||||
|
||||
/******************************************************************************
|
||||
* Debug
|
||||
******************************************************************************/
|
||||
/**
|
||||
* When set, this resets some hw resources to put the device in the same state as at power up.
|
||||
* It resets only register that may prevent the FW to run properly.
|
||||
*
|
||||
* This shall be set to 0 in a final product
|
||||
*
|
||||
*/
|
||||
#define CFG_HW_RESET_BY_FW 0
|
||||
|
||||
/**
|
||||
* keep debugger enabled while in any low power mode when set to 1
|
||||
* should be set to 0 in production
|
||||
*/
|
||||
#define CFG_DEBUGGER_SUPPORTED 1
|
||||
|
||||
/**
|
||||
* When set to 1, the traces are enabled in the BLE services
|
||||
*/
|
||||
#define CFG_DEBUG_BLE_TRACE 0
|
||||
|
||||
/**
|
||||
* Enable or Disable traces in application
|
||||
*/
|
||||
#define CFG_DEBUG_APP_TRACE 0
|
||||
|
||||
#if (CFG_DEBUG_APP_TRACE != 0)
|
||||
#define APP_DBG_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define APP_DBG_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if ( (CFG_DEBUG_BLE_TRACE != 0) || (CFG_DEBUG_APP_TRACE != 0) )
|
||||
#define CFG_DEBUG_TRACE 1
|
||||
#endif
|
||||
|
||||
#if (CFG_DEBUG_TRACE != 0)
|
||||
#undef CFG_LPM_SUPPORTED
|
||||
#undef CFG_DEBUGGER_SUPPORTED
|
||||
#define CFG_LPM_SUPPORTED 0
|
||||
#define CFG_DEBUGGER_SUPPORTED 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* When CFG_DEBUG_TRACE_FULL is set to 1, the trace are output with the API name, the file name and the line number
|
||||
* When CFG_DEBUG_TRACE_LIGHT is set to 1, only the debug message is output
|
||||
*
|
||||
* When both are set to 0, no trace are output
|
||||
* When both are set to 1, CFG_DEBUG_TRACE_FULL is selected
|
||||
*/
|
||||
#define CFG_DEBUG_TRACE_LIGHT 0
|
||||
#define CFG_DEBUG_TRACE_FULL 0
|
||||
|
||||
#if (( CFG_DEBUG_TRACE != 0 ) && ( CFG_DEBUG_TRACE_LIGHT == 0 ) && (CFG_DEBUG_TRACE_FULL == 0))
|
||||
#undef CFG_DEBUG_TRACE_FULL
|
||||
#undef CFG_DEBUG_TRACE_LIGHT
|
||||
#define CFG_DEBUG_TRACE_FULL 0
|
||||
#define CFG_DEBUG_TRACE_LIGHT 1
|
||||
#endif
|
||||
|
||||
#if ( CFG_DEBUG_TRACE == 0 )
|
||||
#undef CFG_DEBUG_TRACE_FULL
|
||||
#undef CFG_DEBUG_TRACE_LIGHT
|
||||
#define CFG_DEBUG_TRACE_FULL 0
|
||||
#define CFG_DEBUG_TRACE_LIGHT 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* When not set, the traces is looping on sending the trace over UART
|
||||
*/
|
||||
#define DBG_TRACE_USE_CIRCULAR_QUEUE 1
|
||||
|
||||
/**
|
||||
* max buffer Size to queue data traces and max data trace allowed.
|
||||
* Only Used if DBG_TRACE_USE_CIRCULAR_QUEUE is defined
|
||||
*/
|
||||
#define DBG_TRACE_MSG_QUEUE_SIZE 4096
|
||||
#define MAX_DBG_TRACE_MSG_SIZE 1024
|
||||
|
||||
/* USER CODE BEGIN Defines */
|
||||
|
||||
/* USER CODE END Defines */
|
||||
|
||||
/******************************************************************************
|
||||
* FreeRTOS
|
||||
******************************************************************************/
|
||||
/* USER CODE BEGIN FreeRTOS */
|
||||
|
||||
/* USER CODE END FreeRTOS */
|
||||
#define CFG_SHCI_USER_EVT_PROCESS_NAME "SHCI_USER_EVT_PROCESS"
|
||||
#define CFG_SHCI_USER_EVT_PROCESS_ATTR_BITS (0)
|
||||
#define CFG_SHCI_USER_EVT_PROCESS_CB_MEM (0)
|
||||
#define CFG_SHCI_USER_EVT_PROCESS_CB_SIZE (0)
|
||||
#define CFG_SHCI_USER_EVT_PROCESS_STACK_MEM (0)
|
||||
#define CFG_SHCI_USER_EVT_PROCESS_PRIORITY osPriorityNone
|
||||
#define CFG_SHCI_USER_EVT_PROCESS_STACK_SIZE (128 * 20)
|
||||
|
||||
#define CFG_HCI_USER_EVT_PROCESS_NAME "HCI_USER_EVT_PROCESS"
|
||||
#define CFG_HCI_USER_EVT_PROCESS_ATTR_BITS (0)
|
||||
#define CFG_HCI_USER_EVT_PROCESS_CB_MEM (0)
|
||||
#define CFG_HCI_USER_EVT_PROCESS_CB_SIZE (0)
|
||||
#define CFG_HCI_USER_EVT_PROCESS_STACK_MEM (0)
|
||||
#define CFG_HCI_USER_EVT_PROCESS_PRIORITY osPriorityNone
|
||||
#define CFG_HCI_USER_EVT_PROCESS_STACK_SIZE (128 * 40)
|
||||
|
||||
#define CFG_ADV_UPDATE_PROCESS_NAME "ADV_UPDATE_PROCESS"
|
||||
#define CFG_ADV_UPDATE_PROCESS_ATTR_BITS (0)
|
||||
#define CFG_ADV_UPDATE_PROCESS_CB_MEM (0)
|
||||
#define CFG_ADV_UPDATE_PROCESS_CB_SIZE (0)
|
||||
#define CFG_ADV_UPDATE_PROCESS_STACK_MEM (0)
|
||||
#define CFG_ADV_UPDATE_PROCESS_PRIORITY osPriorityNone
|
||||
#define CFG_ADV_UPDATE_PROCESS_STACK_SIZE (128 * 20)
|
||||
|
||||
#define CFG_HRS_PROCESS_NAME "HRS_PROCESS"
|
||||
#define CFG_HRS_PROCESS_ATTR_BITS (0)
|
||||
#define CFG_HRS_PROCESS_CB_MEM (0)
|
||||
#define CFG_HRS_PROCESS_CB_SIZE (0)
|
||||
#define CFG_HRS_PROCESS_STACK_MEM (0)
|
||||
#define CFG_HRS_PROCESS_PRIORITY osPriorityNone
|
||||
#define CFG_HRS_PROCESS_STACK_SIZE (128 * 20)
|
||||
|
||||
/* USER CODE BEGIN FreeRTOS_Defines */
|
||||
|
||||
/* USER CODE END FreeRTOS_Defines */
|
||||
|
||||
/******************************************************************************
|
||||
* LOW POWER
|
||||
******************************************************************************/
|
||||
/**
|
||||
* Supported requester to the MCU Low Power Manager - can be increased up to 32
|
||||
* It list a bit mapping of all user of the Low Power Manager
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CFG_LPM_APP,
|
||||
CFG_LPM_APP_BLE,
|
||||
/* USER CODE BEGIN CFG_LPM_Id_t */
|
||||
|
||||
/* USER CODE END CFG_LPM_Id_t */
|
||||
} CFG_LPM_Id_t;
|
||||
|
||||
/******************************************************************************
|
||||
* OTP manager
|
||||
******************************************************************************/
|
||||
#define CFG_OTP_BASE_ADDRESS OTP_AREA_BASE
|
||||
|
||||
#define CFG_OTP_END_ADRESS OTP_AREA_END_ADDR
|
||||
|
||||
#endif /*APP_CONF_H */
|
||||
@@ -0,0 +1,67 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file app_debug.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for app_debug.c module
|
||||
******************************************************************************
|
||||
* @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 APP_DEBUG_H
|
||||
#define APP_DEBUG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
/* 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 variables --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EV */
|
||||
|
||||
/* USER CODE END EV */
|
||||
|
||||
/* Exported macros ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EM */
|
||||
|
||||
/* USER CODE END EM */
|
||||
|
||||
/* Exported functions ---------------------------------------------*/
|
||||
void APPD_Init( void );
|
||||
void APPD_EnableCPU2( void );
|
||||
/* USER CODE BEGIN EF */
|
||||
|
||||
/* USER CODE END EF */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*APP_DEBUG_H */
|
||||
@@ -0,0 +1,70 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file app_entry.h
|
||||
* @author MCD Application Team
|
||||
* @brief Interface to 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 APP_ENTRY_H
|
||||
#define APP_ENTRY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
/* 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 variables --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EV */
|
||||
|
||||
/* USER CODE END EV */
|
||||
|
||||
/* Exported macros ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EM */
|
||||
|
||||
/* USER CODE END EM */
|
||||
|
||||
/* Exported functions ---------------------------------------------*/
|
||||
void MX_APPE_Config(void);
|
||||
void MX_APPE_Init(void);
|
||||
void Init_Exti(void);
|
||||
void Init_Smps(void);
|
||||
|
||||
/* USER CODE BEGIN EF */
|
||||
|
||||
/* USER CODE END EF */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*APP_ENTRY_H */
|
||||
@@ -0,0 +1,170 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file hw_conf.h
|
||||
* @author MCD Application Team
|
||||
* @brief Configuration of hardware interface
|
||||
******************************************************************************
|
||||
* @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 HW_CONF_H
|
||||
#define HW_CONF_H
|
||||
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Semaphores
|
||||
* THIS SHALL NO BE CHANGED AS THESE SEMAPHORES ARE USED AS WELL ON THE CM0+
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* The CPU2 may be configured to store the Thread persistent data either in internal NVM storage on CPU2 or in
|
||||
* SRAM2 buffer provided by the user application. This can be configured with the system command SHCI_C2_Config()
|
||||
* When the CPU2 is requested to store persistent data in SRAM2, it can write data in this buffer at any time when needed.
|
||||
* In order to read consistent data with the CPU1 from the SRAM2 buffer, the flow should be:
|
||||
* + CPU1 takes CFG_HW_THREAD_NVM_SRAM_SEMID semaphore
|
||||
* + CPU1 reads all persistent data from SRAM2 (most of the time, the goal is to write these data into an NVM managed by CPU1)
|
||||
* + CPU1 releases CFG_HW_THREAD_NVM_SRAM_SEMID semaphore
|
||||
* CFG_HW_THREAD_NVM_SRAM_SEMID semaphore makes sure CPU2 does not update the persistent data in SRAM2 at the same time CPU1 is reading them.
|
||||
* There is no timing constraint on how long this semaphore can be kept.
|
||||
*/
|
||||
#define CFG_HW_THREAD_NVM_SRAM_SEMID 9
|
||||
|
||||
/**
|
||||
* The CPU2 may be configured to store the BLE persistent data either in internal NVM storage on CPU2 or in
|
||||
* SRAM2 buffer provided by the user application. This can be configured with the system command SHCI_C2_Config()
|
||||
* When the CPU2 is requested to store persistent data in SRAM2, it can write data in this buffer at any time when needed.
|
||||
* In order to read consistent data with the CPU1 from the SRAM2 buffer, the flow should be:
|
||||
* + CPU1 takes CFG_HW_BLE_NVM_SRAM_SEMID semaphore
|
||||
* + CPU1 reads all persistent data from SRAM2 (most of the time, the goal is to write these data into an NVM managed by CPU1)
|
||||
* + CPU1 releases CFG_HW_BLE_NVM_SRAM_SEMID semaphore
|
||||
* CFG_HW_BLE_NVM_SRAM_SEMID semaphore makes sure CPU2 does not update the persistent data in SRAM2 at the same time CPU1 is reading them.
|
||||
* There is no timing constraint on how long this semaphore can be kept.
|
||||
*/
|
||||
#define CFG_HW_BLE_NVM_SRAM_SEMID 8
|
||||
|
||||
/**
|
||||
* Index of the semaphore used by CPU2 to prevent the CPU1 to either write or erase data in flash
|
||||
* The CPU1 shall not either write or erase in flash when this semaphore is taken by the CPU2
|
||||
* When the CPU1 needs to either write or erase in flash, it shall first get the semaphore and release it just
|
||||
* after writing a raw (64bits data) or erasing one sector.
|
||||
* Once the Semaphore has been released, there shall be at least 1us before it can be taken again. This is required
|
||||
* to give the opportunity to CPU2 to take it.
|
||||
* On v1.4.0 and older CPU2 wireless firmware, this semaphore is unused and CPU2 is using PES bit.
|
||||
* By default, CPU2 is using the PES bit to protect its timing. The CPU1 may request the CPU2 to use the semaphore
|
||||
* instead of the PES bit by sending the system command SHCI_C2_SetFlashActivityControl()
|
||||
*/
|
||||
#define CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID 7
|
||||
|
||||
/**
|
||||
* Index of the semaphore used by CPU1 to prevent the CPU2 to either write or erase data in flash
|
||||
* In order to protect its timing, the CPU1 may get this semaphore to prevent the CPU2 to either
|
||||
* write or erase in flash (as this will stall both CPUs)
|
||||
* The PES bit shall not be used as this may stall the CPU2 in some cases.
|
||||
*/
|
||||
#define CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID 6
|
||||
|
||||
/**
|
||||
* Index of the semaphore used to manage the CLK48 clock configuration
|
||||
* When the USB is required, this semaphore shall be taken before configuring te CLK48 for USB
|
||||
* and should be released after the application switch OFF the clock when the USB is not used anymore
|
||||
* When using the RNG, it is good enough to use CFG_HW_RNG_SEMID to control CLK48.
|
||||
* More details in AN5289
|
||||
*/
|
||||
#define CFG_HW_CLK48_CONFIG_SEMID 5
|
||||
|
||||
/* Index of the semaphore used to manage the entry Stop Mode procedure */
|
||||
#define CFG_HW_ENTRY_STOP_MODE_SEMID 4
|
||||
|
||||
/* Index of the semaphore used to access the RCC */
|
||||
#define CFG_HW_RCC_SEMID 3
|
||||
|
||||
/* Index of the semaphore used to access the FLASH */
|
||||
#define CFG_HW_FLASH_SEMID 2
|
||||
|
||||
/* Index of the semaphore used to access the PKA */
|
||||
#define CFG_HW_PKA_SEMID 1
|
||||
|
||||
/* Index of the semaphore used to access the RNG */
|
||||
#define CFG_HW_RNG_SEMID 0
|
||||
|
||||
/******************************************************************************
|
||||
* HW TIMER SERVER
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* The user may define the maximum number of virtual timers supported.
|
||||
* It shall not exceed 255
|
||||
*/
|
||||
#define CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER 6
|
||||
|
||||
/**
|
||||
* The user may define the priority in the NVIC of the RTC_WKUP interrupt handler that is used to manage the
|
||||
* wakeup timer.
|
||||
* This setting is the preemptpriority part of the NVIC.
|
||||
*/
|
||||
#define CFG_HW_TS_NVIC_RTC_WAKEUP_IT_PREEMPTPRIO (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1) /* FreeRTOS requirement */
|
||||
|
||||
/**
|
||||
* The user may define the priority in the NVIC of the RTC_WKUP interrupt handler that is used to manage the
|
||||
* wakeup timer.
|
||||
* This setting is the subpriority part of the NVIC. It does not exist on all processors. When it is not supported
|
||||
* on the CPU, the setting is ignored
|
||||
*/
|
||||
#define CFG_HW_TS_NVIC_RTC_WAKEUP_IT_SUBPRIO 0
|
||||
|
||||
/**
|
||||
* Define a critical section in the Timer server
|
||||
* The Timer server does not support the API to be nested
|
||||
* The Application shall either:
|
||||
* a) Ensure this will never happen
|
||||
* b) Define the critical section
|
||||
* The default implementations is masking all interrupts using the PRIMASK bit
|
||||
* The TimerServer driver uses critical sections to avoid context corruption. This is achieved with the macro
|
||||
* TIMER_ENTER_CRITICAL_SECTION and TIMER_EXIT_CRITICAL_SECTION. When CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION is set
|
||||
* to 1, all STM32 interrupts are masked with the PRIMASK bit of the CortexM CPU. It is possible to use the BASEPRI
|
||||
* register of the CortexM CPU to keep allowed some interrupts with high priority. In that case, the user shall
|
||||
* re-implement TIMER_ENTER_CRITICAL_SECTION and TIMER_EXIT_CRITICAL_SECTION and shall make sure that no TimerServer
|
||||
* API are called when the TIMER critical section is entered
|
||||
*/
|
||||
#define CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION 1
|
||||
|
||||
/**
|
||||
* This value shall reflect the maximum delay there could be in the application between the time the RTC interrupt
|
||||
* is generated by the Hardware and the time when the RTC interrupt handler is called. This time is measured in
|
||||
* number of RTCCLK ticks.
|
||||
* A relaxed timing would be 10ms
|
||||
* When the value is too short, the timerserver will not be able to count properly and all timeout may be random.
|
||||
* When the value is too long, the device may wake up more often than the most optimal configuration. However, the
|
||||
* impact on power consumption would be marginal (unless the value selected is extremely too long). It is strongly
|
||||
* recommended to select a value large enough to make sure it is not too short to ensure reliability of the system
|
||||
* as this will have marginal impact on low power mode
|
||||
*/
|
||||
#define CFG_HW_TS_RTC_HANDLER_MAX_DELAY ( 10 * (LSI_VALUE/1000) )
|
||||
|
||||
/**
|
||||
* Interrupt ID in the NVIC of the RTC Wakeup interrupt handler
|
||||
* It shall be type of IRQn_Type
|
||||
*/
|
||||
#define CFG_HW_TS_RTC_WAKEUP_HANDLER_ID RTC_WKUP_IRQn
|
||||
|
||||
/******************************************************************************
|
||||
* HW UART
|
||||
*****************************************************************************/
|
||||
#define CFG_HW_LPUART1_ENABLED 0
|
||||
#define CFG_HW_LPUART1_DMA_TX_SUPPORTED 0
|
||||
|
||||
#define CFG_HW_USART1_ENABLED 0
|
||||
#define CFG_HW_USART1_DMA_TX_SUPPORTED 0
|
||||
|
||||
#endif /*HW_CONF_H */
|
||||
@@ -0,0 +1,247 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file hw_if.h
|
||||
* @author MCD Application Team
|
||||
* @brief Hardware Interface
|
||||
******************************************************************************
|
||||
* @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 HW_IF_H
|
||||
#define HW_IF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32wbxx.h"
|
||||
#include "stm32wbxx_ll_exti.h"
|
||||
#include "stm32wbxx_ll_system.h"
|
||||
#include "stm32wbxx_ll_rcc.h"
|
||||
#include "stm32wbxx_ll_ipcc.h"
|
||||
#include "stm32wbxx_ll_bus.h"
|
||||
#include "stm32wbxx_ll_pwr.h"
|
||||
#include "stm32wbxx_ll_cortex.h"
|
||||
#include "stm32wbxx_ll_utils.h"
|
||||
#include "stm32wbxx_ll_hsem.h"
|
||||
#include "stm32wbxx_ll_gpio.h"
|
||||
#include "stm32wbxx_ll_rtc.h"
|
||||
|
||||
#ifdef USE_STM32WBXX_USB_DONGLE
|
||||
#include "stm32wbxx_usb_dongle.h"
|
||||
#endif
|
||||
#ifdef USE_STM32WBXX_NUCLEO
|
||||
#include "stm32wbxx_nucleo.h"
|
||||
#endif
|
||||
#ifdef USE_X_NUCLEO_EPD
|
||||
#include "x_nucleo_epd.h"
|
||||
#endif
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/******************************************************************************
|
||||
* HW UART
|
||||
******************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
hw_uart1,
|
||||
hw_uart2,
|
||||
hw_lpuart1,
|
||||
} hw_uart_id_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
hw_uart_ok,
|
||||
hw_uart_error,
|
||||
hw_uart_busy,
|
||||
hw_uart_to,
|
||||
} hw_status_t;
|
||||
|
||||
void HW_UART_Init(hw_uart_id_t hw_uart_id);
|
||||
void HW_UART_Receive_IT(hw_uart_id_t hw_uart_id, uint8_t *pData, uint16_t Size, void (*Callback)(void));
|
||||
void HW_UART_Transmit_IT(hw_uart_id_t hw_uart_id, uint8_t *pData, uint16_t Size, void (*Callback)(void));
|
||||
hw_status_t HW_UART_Transmit(hw_uart_id_t hw_uart_id, uint8_t *p_data, uint16_t size, uint32_t timeout);
|
||||
hw_status_t HW_UART_Transmit_DMA(hw_uart_id_t hw_uart_id, uint8_t *p_data, uint16_t size, void (*Callback)(void));
|
||||
void HW_UART_Interrupt_Handler(hw_uart_id_t hw_uart_id);
|
||||
void HW_UART_DMA_Interrupt_Handler(hw_uart_id_t hw_uart_id);
|
||||
|
||||
/******************************************************************************
|
||||
* HW TimerServer
|
||||
******************************************************************************/
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/**
|
||||
* This setting is used when standby mode is supported.
|
||||
* hw_ts_InitMode_Limited should be used when the device restarts from Standby Mode. In that case, the Timer Server does
|
||||
* not re-initialized its context. Only the Hardware register which content has been lost is reconfigured
|
||||
* Otherwise, hw_ts_InitMode_Full should be requested (Start from Power ON) and everything is re-initialized.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
hw_ts_InitMode_Full,
|
||||
hw_ts_InitMode_Limited,
|
||||
} HW_TS_InitMode_t;
|
||||
|
||||
/**
|
||||
* When a Timer is created as a SingleShot timer, it is not automatically restarted when the timeout occurs. However,
|
||||
* the timer is kept reserved in the list and could be restarted at anytime with HW_TS_Start()
|
||||
*
|
||||
* When a Timer is created as a Repeated timer, it is automatically restarted when the timeout occurs.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
hw_ts_SingleShot,
|
||||
hw_ts_Repeated
|
||||
} HW_TS_Mode_t;
|
||||
|
||||
/**
|
||||
* hw_ts_Successful is returned when a Timer has been successfully created with HW_TS_Create(). Otherwise, hw_ts_Failed
|
||||
* is returned. When hw_ts_Failed is returned, that means there are not enough free slots in the list to create a
|
||||
* Timer. In that case, CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER should be increased
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
hw_ts_Successful,
|
||||
hw_ts_Failed,
|
||||
}HW_TS_ReturnStatus_t;
|
||||
|
||||
typedef void (*HW_TS_pTimerCb_t)(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize the timer server
|
||||
* This API shall be called by the application before any timer is requested to the timer server. It
|
||||
* configures the RTC module to be connected to the LSI input clock.
|
||||
*
|
||||
* @param TimerInitMode: When the device restarts from Standby, it should request hw_ts_InitMode_Limited so that the
|
||||
* Timer context is not re-initialized. Otherwise, hw_ts_InitMode_Full should be requested
|
||||
* @param hrtc: RTC Handle
|
||||
* @retval None
|
||||
*/
|
||||
void HW_TS_Init(HW_TS_InitMode_t TimerInitMode, RTC_HandleTypeDef *hrtc);
|
||||
|
||||
/**
|
||||
* @brief Interface to create a virtual timer
|
||||
* The user shall call this API to create a timer. Once created, the timer is reserved to the module until it
|
||||
* has been deleted. When creating a timer, the user shall specify the mode (single shot or repeated), the
|
||||
* callback to be notified when the timer expires and a module ID to identify in the timer interrupt handler
|
||||
* which module is concerned. In return, the user gets a timer ID to handle it.
|
||||
*
|
||||
* @param TimerProcessID: This is an identifier provided by the user and returned in the callback to allow
|
||||
* identification of the requester
|
||||
* @param pTimerId: Timer Id returned to the user to request operation (start, stop, delete)
|
||||
* @param TimerMode: Mode of the virtual timer (Single shot or repeated)
|
||||
* @param pTimerCallBack: Callback when the virtual timer expires
|
||||
* @retval HW_TS_ReturnStatus_t: Return whether the creation is successful or not
|
||||
*/
|
||||
HW_TS_ReturnStatus_t HW_TS_Create(uint32_t TimerProcessID, uint8_t *pTimerId, HW_TS_Mode_t TimerMode, HW_TS_pTimerCb_t pTimerCallBack);
|
||||
|
||||
/**
|
||||
* @brief Stop a virtual timer
|
||||
* This API may be used to stop a running timer. A timer which is stopped is move to the pending state.
|
||||
* A pending timer may be restarted at any time with a different timeout value but the mode cannot be changed.
|
||||
* Nothing is done when it is called to stop a timer which has been already stopped
|
||||
*
|
||||
* @param TimerID: Id of the timer to stop
|
||||
* @retval None
|
||||
*/
|
||||
void HW_TS_Stop(uint8_t TimerID);
|
||||
|
||||
/**
|
||||
* @brief Start a virtual timer
|
||||
* This API shall be used to start a timer. The timeout value is specified and may be different each time.
|
||||
* When the timer is in the single shot mode, it will move to the pending state when it expires. The user may
|
||||
* restart it at any time with a different timeout value. When the timer is in the repeated mode, it always
|
||||
* stay in the running state. When the timer expires, it will be restarted with the same timeout value.
|
||||
* This API shall not be called on a running timer.
|
||||
*
|
||||
* @param TimerID: The ID Id of the timer to start
|
||||
* @param timeout_ticks: Number of ticks of the virtual timer (Maximum value is (0xFFFFFFFF-0xFFFF = 0xFFFF0000)
|
||||
* @retval None
|
||||
*/
|
||||
void HW_TS_Start(uint8_t TimerID, uint32_t timeout_ticks);
|
||||
|
||||
/**
|
||||
* @brief Delete a virtual timer from the list
|
||||
* This API should be used when a timer is not needed anymore by the user. A deleted timer is removed from
|
||||
* the timer list managed by the timer server. It cannot be restarted again. The user has to go with the
|
||||
* creation of a new timer if required and may get a different timer id
|
||||
*
|
||||
* @param TimerID: The ID of the timer to remove from the list
|
||||
* @retval None
|
||||
*/
|
||||
void HW_TS_Delete(uint8_t TimerID);
|
||||
|
||||
/**
|
||||
* @brief Schedule the timer list on the timer interrupt handler
|
||||
* This interrupt handler shall be called by the application in the RTC interrupt handler. This handler takes
|
||||
* care of clearing all status flag required in the RTC and EXTI peripherals
|
||||
*
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void HW_TS_RTC_Wakeup_Handler(void);
|
||||
|
||||
/**
|
||||
* @brief Return the number of ticks to count before the interrupt
|
||||
* This API returns the number of ticks left to be counted before an interrupt is generated by the
|
||||
* Timer Server. This API may be used by the application for power management optimization. When the system
|
||||
* enters low power mode, the mode selection is a tradeoff between the wakeup time where the CPU is running
|
||||
* and the time while the CPU will be kept in low power mode before next wakeup. The deeper is the
|
||||
* low power mode used, the longer is the wakeup time. The low power mode management considering wakeup time
|
||||
* versus time in low power mode is implementation specific
|
||||
* When the timer is disabled (No timer in the list), it returns 0xFFFF
|
||||
*
|
||||
* @param None
|
||||
* @retval The number of ticks left to count
|
||||
*/
|
||||
uint16_t HW_TS_RTC_ReadLeftTicksToCount(void);
|
||||
|
||||
/**
|
||||
* @brief Notify the application that a registered timer has expired
|
||||
* This API shall be implemented by the user application.
|
||||
* This API notifies the application that a timer expires. This API is running in the RTC Wakeup interrupt
|
||||
* context. The application may implement an Operating System to change the context priority where the timer
|
||||
* callback may be handled. This API provides the module ID to identify which module is concerned and to allow
|
||||
* sending the information to the correct task
|
||||
*
|
||||
* @param TimerProcessID: The TimerProcessId associated with the timer when it has been created
|
||||
* @param TimerID: The TimerID of the expired timer
|
||||
* @param pTimerCallBack: The Callback associated with the timer when it has been created
|
||||
* @retval None
|
||||
*/
|
||||
void HW_TS_RTC_Int_AppNot(uint32_t TimerProcessID, uint8_t TimerID, HW_TS_pTimerCb_t pTimerCallBack);
|
||||
|
||||
/**
|
||||
* @brief Notify the application that the wakeupcounter has been updated
|
||||
* This API should be implemented by the user application
|
||||
* This API notifies the application that the counter has been updated. This is expected to be used along
|
||||
* with the HW_TS_RTC_ReadLeftTicksToCount () API. It could be that the counter has been updated since the
|
||||
* last call of HW_TS_RTC_ReadLeftTicksToCount () and before entering low power mode. This notification
|
||||
* provides a way to the application to solve that race condition to reevaluate the counter value before
|
||||
* entering low power mode
|
||||
*
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void HW_TS_RTC_CountUpdated_AppNot(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*HW_IF_H */
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/* 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 "stm32wbxx_hal.h"
|
||||
|
||||
#include "app_conf.h"
|
||||
#include "app_entry.h"
|
||||
#include "app_common.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 */
|
||||
|
||||
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void Error_Handler(void);
|
||||
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#define SPI2_SD_MOSI_Pin GPIO_PIN_1
|
||||
#define SPI2_SD_MOSI_GPIO_Port GPIOC
|
||||
#define SPI2_SD_MISO_Pin GPIO_PIN_2
|
||||
#define SPI2_SD_MISO_GPIO_Port GPIOC
|
||||
#define GPIO_CONNECT_LED_Pin GPIO_PIN_0
|
||||
#define GPIO_CONNECT_LED_GPIO_Port GPIOA
|
||||
#define GPIO_STATUS_LED_Pin GPIO_PIN_1
|
||||
#define GPIO_STATUS_LED_GPIO_Port GPIOA
|
||||
#define GPIO_DEBUG_LED_Pin GPIO_PIN_2
|
||||
#define GPIO_DEBUG_LED_GPIO_Port GPIOA
|
||||
#define GPIO_SPI1_IMU_CS_Pin GPIO_PIN_3
|
||||
#define GPIO_SPI1_IMU_CS_GPIO_Port GPIOA
|
||||
#define SPI1_IMU_SCK_Pin GPIO_PIN_5
|
||||
#define SPI1_IMU_SCK_GPIO_Port GPIOA
|
||||
#define SPI1_IMU_MISO_Pin GPIO_PIN_6
|
||||
#define SPI1_IMU_MISO_GPIO_Port GPIOA
|
||||
#define SPI1_IMU_MOSI_Pin GPIO_PIN_7
|
||||
#define SPI1_IMU_MOSI_GPIO_Port GPIOA
|
||||
#define SPI2_SD_SCK_Pin GPIO_PIN_9
|
||||
#define SPI2_SD_SCK_GPIO_Port GPIOA
|
||||
#define GPIO_SPI2_SD_CD_Pin GPIO_PIN_5
|
||||
#define GPIO_SPI2_SD_CD_GPIO_Port GPIOC
|
||||
#define GPIO_SPI2_SD_CS_Pin GPIO_PIN_6
|
||||
#define GPIO_SPI2_SD_CS_GPIO_Port GPIOC
|
||||
#define GPIO_IMU_INT_Pin GPIO_PIN_10
|
||||
#define GPIO_IMU_INT_GPIO_Port GPIOA
|
||||
#define GPIO_MAGN_INT_Pin GPIO_PIN_11
|
||||
#define GPIO_MAGN_INT_GPIO_Port GPIOC
|
||||
#define GPIO_SD_LDO_EN_Pin GPIO_PIN_12
|
||||
#define GPIO_SD_LDO_EN_GPIO_Port GPIOC
|
||||
|
||||
/* USER CODE BEGIN Private defines */
|
||||
|
||||
/* USER CODE END Private defines */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MAIN_H */
|
||||
@@ -0,0 +1,80 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32_lpm_if.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for stm32_lpm_if.c module (device specific LP management)
|
||||
******************************************************************************
|
||||
* @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 STM32_LPM_IF_H
|
||||
#define STM32_LPM_IF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Enters Low Power Off Mode
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_EnterOffMode( void );
|
||||
/**
|
||||
* @brief Exits Low Power Off Mode
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_ExitOffMode( void );
|
||||
|
||||
/**
|
||||
* @brief Enters Low Power Stop Mode
|
||||
* @note ARM exists the function when waking up
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_EnterStopMode( void );
|
||||
/**
|
||||
* @brief Exits Low Power Stop Mode
|
||||
* @note Enable the pll at 32MHz
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_ExitStopMode( void );
|
||||
|
||||
/**
|
||||
* @brief Enters Low Power Sleep Mode
|
||||
* @note ARM exits the function when waking up
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_EnterSleepMode( void );
|
||||
|
||||
/**
|
||||
* @brief Exits Low Power Sleep Mode
|
||||
* @note ARM exits the function when waking up
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_ExitSleepMode( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*STM32_LPM_IF_H */
|
||||
|
||||
@@ -0,0 +1,352 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32wbxx_hal_conf.h
|
||||
* @author MCD Application Team
|
||||
* @brief HAL configuration file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2019 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 __STM32WBxx_HAL_CONF_H
|
||||
#define __STM32WBxx_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_COMP_MODULE_ENABLED */
|
||||
/*#define HAL_CRC_MODULE_ENABLED */
|
||||
#define HAL_HSEM_MODULE_ENABLED
|
||||
#define HAL_I2C_MODULE_ENABLED
|
||||
#define HAL_IPCC_MODULE_ENABLED
|
||||
/*#define HAL_IRDA_MODULE_ENABLED */
|
||||
/*#define HAL_IWDG_MODULE_ENABLED */
|
||||
/*#define HAL_LCD_MODULE_ENABLED */
|
||||
/*#define HAL_LPTIM_MODULE_ENABLED */
|
||||
#define HAL_PCD_MODULE_ENABLED
|
||||
/*#define HAL_PKA_MODULE_ENABLED */
|
||||
/*#define HAL_QSPI_MODULE_ENABLED */
|
||||
/*#define HAL_RNG_MODULE_ENABLED */
|
||||
#define HAL_RTC_MODULE_ENABLED
|
||||
/*#define HAL_SAI_MODULE_ENABLED */
|
||||
/*#define HAL_SMBUS_MODULE_ENABLED */
|
||||
/*#define HAL_SMARTCARD_MODULE_ENABLED */
|
||||
#define HAL_SPI_MODULE_ENABLED
|
||||
#define HAL_TIM_MODULE_ENABLED
|
||||
/*#define HAL_TSC_MODULE_ENABLED */
|
||||
/*#define HAL_UART_MODULE_ENABLED */
|
||||
/*#define HAL_USART_MODULE_ENABLED */
|
||||
/*#define HAL_WWDG_MODULE_ENABLED */
|
||||
#define HAL_EXTI_MODULE_ENABLED
|
||||
#define HAL_CORTEX_MODULE_ENABLED
|
||||
#define HAL_DMA_MODULE_ENABLED
|
||||
#define HAL_FLASH_MODULE_ENABLED
|
||||
#define HAL_GPIO_MODULE_ENABLED
|
||||
#define HAL_PWR_MODULE_ENABLED
|
||||
#define HAL_RCC_MODULE_ENABLED
|
||||
|
||||
#define USE_HAL_ADC_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_COMP_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_CRYP_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_I2C_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_IRDA_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_PCD_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_PKA_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_QSPI_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_RNG_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_RTC_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_SAI_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_SPI_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_TIM_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_TSC_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_UART_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_USART_REGISTER_CALLBACKS 0u
|
||||
#define USE_HAL_WWDG_REGISTER_CALLBACKS 0u
|
||||
|
||||
/* ########################## 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 32000000U /*!< Value of the External oscillator in Hz */
|
||||
#endif /* HSE_VALUE */
|
||||
|
||||
#if !defined (HSE_STARTUP_TIMEOUT)
|
||||
#define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */
|
||||
#endif /* HSE_STARTUP_TIMEOUT */
|
||||
|
||||
/**
|
||||
* @brief Internal Multiple Speed oscillator (MSI) default value.
|
||||
* This value is the default MSI range value after Reset.
|
||||
*/
|
||||
#if !defined (MSI_VALUE)
|
||||
#define MSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/
|
||||
#endif /* MSI_VALUE */
|
||||
|
||||
/**
|
||||
* @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 16000000U /*!< Value of the Internal oscillator in Hz*/
|
||||
#endif /* HSI_VALUE */
|
||||
|
||||
/**
|
||||
* @brief Internal Low Speed oscillator (LSI1) value.
|
||||
*/
|
||||
#if !defined (LSI1_VALUE)
|
||||
#define LSI1_VALUE ((uint32_t)32000) /*!< LSI1 Typical Value in Hz*/
|
||||
#endif /* LSI1_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
|
||||
The real value may vary depending on the variations
|
||||
in voltage and temperature.*/
|
||||
/**
|
||||
* @brief Internal Low Speed oscillator (LSI2) value.
|
||||
*/
|
||||
#if !defined (LSI2_VALUE)
|
||||
#define LSI2_VALUE ((uint32_t)32000) /*!< LSI2 Typical Value in Hz*/
|
||||
#endif /* LSI2_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 */
|
||||
|
||||
/**
|
||||
* @brief Internal Multiple Speed oscillator (HSI48) default value.
|
||||
* This value is the default HSI48 range value after Reset.
|
||||
*/
|
||||
#if !defined (HSI48_VALUE)
|
||||
#define HSI48_VALUE ((uint32_t)48000000) /*!< Value of the Internal oscillator in Hz*/
|
||||
#endif /* HSI48_VALUE */
|
||||
|
||||
#if !defined (LSE_STARTUP_TIMEOUT)
|
||||
#define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */
|
||||
#endif /* LSE_STARTUP_TIMEOUT */
|
||||
|
||||
/**
|
||||
* @brief External clock source for SAI1 peripheral
|
||||
* This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source
|
||||
* frequency.
|
||||
*/
|
||||
#if !defined (EXTERNAL_SAI1_CLOCK_VALUE)
|
||||
#define EXTERNAL_SAI1_CLOCK_VALUE ((uint32_t)2097000) /*!< Value of the SAI1 External clock source in Hz*/
|
||||
#endif /* EXTERNAL_SAI1_CLOCK_VALUE */
|
||||
|
||||
/* 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 */
|
||||
#define USE_RTOS 0U
|
||||
#define PREFETCH_ENABLE 1U
|
||||
#define INSTRUCTION_CACHE_ENABLE 1U
|
||||
#define DATA_CACHE_ENABLE 1U
|
||||
|
||||
/* ########################## Assert Selection ############################## */
|
||||
/**
|
||||
* @brief Uncomment the line below to expanse the "assert_param" macro in the
|
||||
* HAL drivers code
|
||||
*/
|
||||
/* #define USE_FULL_ASSERT 1U */
|
||||
|
||||
/* ################## 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_DMA_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_dma.h"
|
||||
#endif /* HAL_DMA_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_ADC_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_adc.h"
|
||||
#endif /* HAL_ADC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_COMP_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_comp.h"
|
||||
#endif /* HAL_COMP_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CORTEX_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_cortex.h"
|
||||
#endif /* HAL_CORTEX_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CRC_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_crc.h"
|
||||
#endif /* HAL_CRC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_CRYP_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_cryp.h"
|
||||
#endif /* HAL_CRYP_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_EXTI_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_exti.h"
|
||||
#endif /* HAL_EXTI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_FLASH_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_flash.h"
|
||||
#endif /* HAL_FLASH_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_GPIO_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_gpio.h"
|
||||
#endif /* HAL_GPIO_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_HSEM_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_hsem.h"
|
||||
#endif /* HAL_HSEM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_I2C_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_i2c.h"
|
||||
#endif /* HAL_I2C_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_IPCC_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_ipcc.h"
|
||||
#endif /* HAL_IPCC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_IRDA_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_irda.h"
|
||||
#endif /* HAL_IRDA_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_IWDG_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_iwdg.h"
|
||||
#endif /* HAL_IWDG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_LCD_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_lcd.h"
|
||||
#endif /* HAL_LCD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_LPTIM_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_lptim.h"
|
||||
#endif /* HAL_LPTIM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PCD_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_pcd.h"
|
||||
#endif /* HAL_PCD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PKA_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_pka.h"
|
||||
#endif /* HAL_PKA_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_PWR_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_pwr.h"
|
||||
#endif /* HAL_PWR_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_QSPI_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_qspi.h"
|
||||
#endif /* HAL_QSPI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_RCC_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_rcc.h"
|
||||
#endif /* HAL_RCC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_RNG_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_rng.h"
|
||||
#endif /* HAL_RNG_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_RTC_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_rtc.h"
|
||||
#endif /* HAL_RTC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SAI_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_sai.h"
|
||||
#endif /* HAL_SAI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SMARTCARD_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_smartcard.h"
|
||||
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SMBUS_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_smbus.h"
|
||||
#endif /* HAL_SMBUS_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_SPI_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_spi.h"
|
||||
#endif /* HAL_SPI_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_TIM_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_tim.h"
|
||||
#endif /* HAL_TIM_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_TSC_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_tsc.h"
|
||||
#endif /* HAL_TSC_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_UART_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_uart.h"
|
||||
#endif /* HAL_UART_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_USART_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_usart.h"
|
||||
#endif /* HAL_USART_MODULE_ENABLED */
|
||||
|
||||
#ifdef HAL_WWDG_MODULE_ENABLED
|
||||
#include "stm32wbxx_hal_wwdg.h"
|
||||
#endif /* HAL_WWDG_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 /* __STM32WBxx_HAL_CONF_H */
|
||||
@@ -0,0 +1,75 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32wbxx_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 __STM32WBxx_IT_H
|
||||
#define __STM32WBxx_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 RTC_WKUP_IRQHandler(void);
|
||||
void DMA1_Channel1_IRQHandler(void);
|
||||
void DMA1_Channel2_IRQHandler(void);
|
||||
void DMA1_Channel3_IRQHandler(void);
|
||||
void DMA1_Channel4_IRQHandler(void);
|
||||
void USB_LP_IRQHandler(void);
|
||||
void TIM1_UP_TIM16_IRQHandler(void);
|
||||
void I2C1_EV_IRQHandler(void);
|
||||
void I2C1_ER_IRQHandler(void);
|
||||
void IPCC_C1_RX_IRQHandler(void);
|
||||
void IPCC_C1_TX_IRQHandler(void);
|
||||
void HSEM_IRQHandler(void);
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __STM32WBxx_IT_H */
|
||||
@@ -0,0 +1,65 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file utilities_conf.h
|
||||
* @author MCD Application Team
|
||||
* @brief Configuration file for STM32 Utilities.
|
||||
******************************************************************************
|
||||
* @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 UTILITIES_CONF_H
|
||||
#define UTILITIES_CONF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "cmsis_compiler.h"
|
||||
#include "string.h"
|
||||
#include "app_conf.h"
|
||||
/******************************************************************************
|
||||
* common
|
||||
******************************************************************************/
|
||||
#define UTILS_ENTER_CRITICAL_SECTION( ) uint32_t primask_bit = __get_PRIMASK( );\
|
||||
__disable_irq( )
|
||||
|
||||
#define UTILS_EXIT_CRITICAL_SECTION( ) __set_PRIMASK( primask_bit )
|
||||
|
||||
#define UTILS_MEMSET8( dest, value, size ) memset( dest, value, size);
|
||||
|
||||
/******************************************************************************
|
||||
* tiny low power manager
|
||||
* (any macro that does not need to be modified can be removed)
|
||||
******************************************************************************/
|
||||
#define UTIL_LPM_INIT_CRITICAL_SECTION( )
|
||||
#define UTIL_LPM_ENTER_CRITICAL_SECTION( ) UTILS_ENTER_CRITICAL_SECTION( )
|
||||
#define UTIL_LPM_EXIT_CRITICAL_SECTION( ) UTILS_EXIT_CRITICAL_SECTION( )
|
||||
|
||||
/******************************************************************************
|
||||
* sequencer
|
||||
* (any macro that does not need to be modified can be removed)
|
||||
******************************************************************************/
|
||||
#define UTIL_SEQ_INIT_CRITICAL_SECTION( )
|
||||
#define UTIL_SEQ_ENTER_CRITICAL_SECTION( ) UTILS_ENTER_CRITICAL_SECTION( )
|
||||
#define UTIL_SEQ_EXIT_CRITICAL_SECTION( ) UTILS_EXIT_CRITICAL_SECTION( )
|
||||
#define UTIL_SEQ_CONF_TASK_NBR (32)
|
||||
#define UTIL_SEQ_CONF_PRIO_NBR CFG_SCH_PRIO_NBR
|
||||
#define UTIL_SEQ_MEMSET8( dest, value, size ) UTILS_MEMSET8( dest, value, size )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*UTILITIES_CONF_H */
|
||||
@@ -0,0 +1,252 @@
|
||||
//=====================================================================================================
|
||||
// MadgwickAHRS.c
|
||||
//=====================================================================================================
|
||||
//
|
||||
// Implementation of Madgwick's IMU and AHRS algorithms.
|
||||
// See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms
|
||||
//
|
||||
// Date Author Notes
|
||||
// 29/09/2011 SOH Madgwick Initial release
|
||||
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load
|
||||
// 19/02/2012 SOH Madgwick Magnetometer measurement is normalised
|
||||
//
|
||||
//=====================================================================================================
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Header files
|
||||
|
||||
#include "MadgwickAHRS.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Definitions
|
||||
|
||||
//#define sampleFreq 512.0f // sample frequency in Hz
|
||||
//#define betaDef 0.1f // 2 * proportional gain
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Variable definitions
|
||||
|
||||
//volatile float beta = betaDef; // 2 * proportional gain (Kp)
|
||||
//volatile float q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f; // quaternion of sensor frame relative to auxiliary frame
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Function declarations
|
||||
|
||||
float invSqrt(float x);
|
||||
|
||||
//====================================================================================================
|
||||
// Functions
|
||||
|
||||
void MadgwickAHRS_init (MadgwickAHRS_Filter* filter, float beta, float sample_freq) {
|
||||
filter->q[0] = 1.0f; // qw
|
||||
filter->q[1] = 0.0f; // qx
|
||||
filter->q[2] = 0.0f; // qy
|
||||
filter->q[3] = 0.0f; // qz
|
||||
filter->beta = beta;
|
||||
filter->sample_freq = sample_freq;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// AHRS algorithm update
|
||||
|
||||
void MadgwickAHRS_update(MadgwickAHRS_Filter* filter, float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz) {
|
||||
float q[4] = {filter->q[0], filter->q[1], filter->q[2], filter->q[3]};
|
||||
float recipNorm;
|
||||
float s0, s1, s2, s3;
|
||||
float qDot[4];
|
||||
float hx, hy;
|
||||
float _2q0mx, _2q0my, _2q0mz, _2q1mx, _2bx, _2bz, _4bx, _4bz, _2q0, _2q1, _2q2, _2q3, _2q0q2, _2q2q3, q0q0, q0q1, q0q2, q0q3, q1q1, q1q2, q1q3, q2q2, q2q3, q3q3;
|
||||
|
||||
// Use IMU algorithm if magnetometer measurement invalid (avoids NaN in magnetometer normalisation)
|
||||
if((mx == 0.0f) && (my == 0.0f) && (mz == 0.0f)) {
|
||||
MadgwickAHRS_update_IMU(filter, gx, gy, gz, ax, ay, az);
|
||||
return;
|
||||
}
|
||||
|
||||
// Rate of change of quaternion from gyroscope
|
||||
qDot[0] = 0.5f * (-q[1] * gx - q[2] * gy - q[3] * gz);
|
||||
qDot[1] = 0.5f * (q[0] * gx + q[2] * gz - q[3] * gy);
|
||||
qDot[2] = 0.5f * (q[0] * gy - q[1] * gz + q[3] * gx);
|
||||
qDot[3] = 0.5f * (q[0] * gz + q[1] * gy - q[2] * gx);
|
||||
|
||||
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
|
||||
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
|
||||
|
||||
// Normalise accelerometer measurement
|
||||
recipNorm = invSqrt(ax * ax + ay * ay + az * az);
|
||||
ax *= recipNorm;
|
||||
ay *= recipNorm;
|
||||
az *= recipNorm;
|
||||
|
||||
// Normalise magnetometer measurement
|
||||
recipNorm = invSqrt(mx * mx + my * my + mz * mz);
|
||||
mx *= recipNorm;
|
||||
my *= recipNorm;
|
||||
mz *= recipNorm;
|
||||
|
||||
// Auxiliary variables to avoid repeated arithmetic
|
||||
_2q0mx = 2.0f * q[0] * mx;
|
||||
_2q0my = 2.0f * q[0] * my;
|
||||
_2q0mz = 2.0f * q[0] * mz;
|
||||
_2q1mx = 2.0f * q[1] * mx;
|
||||
_2q0 = 2.0f * q[0];
|
||||
_2q1 = 2.0f * q[1];
|
||||
_2q2 = 2.0f * q[2];
|
||||
_2q3 = 2.0f * q[3];
|
||||
_2q0q2 = 2.0f * q[0] * q[2];
|
||||
_2q2q3 = 2.0f * q[2] * q[3];
|
||||
q0q0 = q[0] * q[0];
|
||||
q0q1 = q[0] * q[1];
|
||||
q0q2 = q[0] * q[2];
|
||||
q0q3 = q[0] * q[3];
|
||||
q1q1 = q[1] * q[1];
|
||||
q1q2 = q[1] * q[2];
|
||||
q1q3 = q[1] * q[3];
|
||||
q2q2 = q[2] * q[2];
|
||||
q2q3 = q[2] * q[3];
|
||||
q3q3 = q[3] * q[3];
|
||||
|
||||
// Reference direction of Earth's magnetic field
|
||||
hx = mx * q0q0 - _2q0my * q[3] + _2q0mz * q[2] + mx * q1q1 + _2q1 * my * q[2] + _2q1 * mz * q[3] - mx * q2q2 - mx * q3q3;
|
||||
hy = _2q0mx * q[3] + my * q0q0 - _2q0mz * q[1] + _2q1mx * q[2] - my * q1q1 + my * q2q2 + _2q2 * mz * q[3] - my * q3q3;
|
||||
_2bx = sqrt(hx * hx + hy * hy);
|
||||
_2bz = -_2q0mx * q[2] + _2q0my * q[1] + mz * q0q0 + _2q1mx * q[3] - mz * q1q1 + _2q2 * my * q[3] - mz * q2q2 + mz * q3q3;
|
||||
_4bx = 2.0f * _2bx;
|
||||
_4bz = 2.0f * _2bz;
|
||||
|
||||
// Gradient decent algorithm corrective step
|
||||
s0 = -_2q2 * (2.0f * q1q3 - _2q0q2 - ax) + _2q1 * (2.0f * q0q1 + _2q2q3 - ay) - _2bz * q[2] * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (-_2bx * q[3] + _2bz * q[1]) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + _2bx * q[2] * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz);
|
||||
s1 = _2q3 * (2.0f * q1q3 - _2q0q2 - ax) + _2q0 * (2.0f * q0q1 + _2q2q3 - ay) - 4.0f * q[1] * (1 - 2.0f * q1q1 - 2.0f * q2q2 - az) + _2bz * q[3] * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (_2bx * q[2] + _2bz * q[0]) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + (_2bx * q[3] - _4bz * q[1]) * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz);
|
||||
s2 = -_2q0 * (2.0f * q1q3 - _2q0q2 - ax) + _2q3 * (2.0f * q0q1 + _2q2q3 - ay) - 4.0f * q[2] * (1 - 2.0f * q1q1 - 2.0f * q2q2 - az) + (-_4bx * q[2] - _2bz * q[0]) * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (_2bx * q[1] + _2bz * q[3]) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + (_2bx * q[0] - _4bz * q[2]) * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz);
|
||||
s3 = _2q1 * (2.0f * q1q3 - _2q0q2 - ax) + _2q2 * (2.0f * q0q1 + _2q2q3 - ay) + (-_4bx * q[3] + _2bz * q[1]) * (_2bx * (0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (-_2bx * q[0] + _2bz * q[2]) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + _2bx * q[1] * (_2bx * (q0q2 + q1q3) + _2bz * (0.5f - q1q1 - q2q2) - mz);
|
||||
recipNorm = invSqrt(s0 * s0 + s1 * s1 + s2 * s2 + s3 * s3); // normalise step magnitude
|
||||
s0 *= recipNorm;
|
||||
s1 *= recipNorm;
|
||||
s2 *= recipNorm;
|
||||
s3 *= recipNorm;
|
||||
|
||||
// Apply feedback step
|
||||
qDot[0] -= filter->beta * s0;
|
||||
qDot[1] -= filter->beta * s1;
|
||||
qDot[2] -= filter->beta * s2;
|
||||
qDot[3] -= filter->beta * s3;
|
||||
}
|
||||
|
||||
// Integrate rate of change of quaternion to yield quaternion
|
||||
q[0] += qDot[0] * (1.0f / filter->sample_freq);
|
||||
q[1] += qDot[1] * (1.0f / filter->sample_freq);
|
||||
q[2] += qDot[2] * (1.0f / filter->sample_freq);
|
||||
q[3] += qDot[3] * (1.0f / filter->sample_freq);
|
||||
|
||||
// Normalise quaternion
|
||||
recipNorm = invSqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
|
||||
q[0] *= recipNorm;
|
||||
q[1] *= recipNorm;
|
||||
q[2] *= recipNorm;
|
||||
q[3] *= recipNorm;
|
||||
|
||||
// Update filter state
|
||||
filter->q[0] = q[0];
|
||||
filter->q[1] = q[1];
|
||||
filter->q[2] = q[2];
|
||||
filter->q[3] = q[3];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// IMU algorithm update
|
||||
|
||||
void MadgwickAHRS_update_IMU(MadgwickAHRS_Filter* filter, float gx, float gy, float gz, float ax, float ay, float az) {
|
||||
float q[4] = {filter->q[0], filter->q[1], filter->q[2], filter->q[3]};
|
||||
float recipNorm;
|
||||
float s0, s1, s2, s3;
|
||||
float qDot[4];
|
||||
float _2q0, _2q1, _2q2, _2q3, _4q0, _4q1, _4q2 ,_8q1, _8q2, q0q0, q1q1, q2q2, q3q3;
|
||||
|
||||
// Rate of change of quaternion from gyroscope
|
||||
qDot[0] = 0.5f * (-q[1] * gx - q[2] * gy - q[3] * gz);
|
||||
qDot[1] = 0.5f * (q[0] * gx + q[2] * gz - q[3] * gy);
|
||||
qDot[2] = 0.5f * (q[0] * gy - q[1] * gz + q[3] * gx);
|
||||
qDot[3] = 0.5f * (q[0] * gz + q[1] * gy - q[2] * gx);
|
||||
|
||||
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
|
||||
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
|
||||
|
||||
// Normalise accelerometer measurement
|
||||
recipNorm = invSqrt(ax * ax + ay * ay + az * az);
|
||||
ax *= recipNorm;
|
||||
ay *= recipNorm;
|
||||
az *= recipNorm;
|
||||
|
||||
// Auxiliary variables to avoid repeated arithmetic
|
||||
_2q0 = 2.0f * q[0];
|
||||
_2q1 = 2.0f * q[1];
|
||||
_2q2 = 2.0f * q[2];
|
||||
_2q3 = 2.0f * q[3];
|
||||
_4q0 = 4.0f * q[0];
|
||||
_4q1 = 4.0f * q[1];
|
||||
_4q2 = 4.0f * q[2];
|
||||
_8q1 = 8.0f * q[1];
|
||||
_8q2 = 8.0f * q[2];
|
||||
q0q0 = q[0] * q[0];
|
||||
q1q1 = q[1] * q[1];
|
||||
q2q2 = q[2] * q[2];
|
||||
q3q3 = q[3] * q[3];
|
||||
|
||||
// Gradient decent algorithm corrective step
|
||||
s0 = _4q0 * q2q2 + _2q2 * ax + _4q0 * q1q1 - _2q1 * ay;
|
||||
s1 = _4q1 * q3q3 - _2q3 * ax + 4.0f * q0q0 * q[1] - _2q0 * ay - _4q1 + _8q1 * q1q1 + _8q1 * q2q2 + _4q1 * az;
|
||||
s2 = 4.0f * q0q0 * q[2] + _2q0 * ax + _4q2 * q3q3 - _2q3 * ay - _4q2 + _8q2 * q1q1 + _8q2 * q2q2 + _4q2 * az;
|
||||
s3 = 4.0f * q1q1 * q[3] - _2q1 * ax + 4.0f * q2q2 * q[3] - _2q2 * ay;
|
||||
recipNorm = invSqrt(s0 * s0 + s1 * s1 + s2 * s2 + s3 * s3); // normalise step magnitude
|
||||
s0 *= recipNorm;
|
||||
s1 *= recipNorm;
|
||||
s2 *= recipNorm;
|
||||
s3 *= recipNorm;
|
||||
|
||||
// Apply feedback step
|
||||
qDot[0] -= filter->beta * s0;
|
||||
qDot[1] -= filter->beta * s1;
|
||||
qDot[2] -= filter->beta * s2;
|
||||
qDot[3] -= filter->beta * s3;
|
||||
}
|
||||
|
||||
// Integrate rate of change of quaternion to yield quaternion
|
||||
q[0] += qDot[0] * (1.0f / filter->sample_freq);
|
||||
q[1] += qDot[1] * (1.0f / filter->sample_freq);
|
||||
q[2] += qDot[2] * (1.0f / filter->sample_freq);
|
||||
q[3] += qDot[3] * (1.0f / filter->sample_freq);
|
||||
|
||||
// Normalise quaternion
|
||||
recipNorm = invSqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
|
||||
q[0] *= recipNorm;
|
||||
q[1] *= recipNorm;
|
||||
q[2] *= recipNorm;
|
||||
q[3] *= recipNorm;
|
||||
|
||||
// Update filter state
|
||||
filter->q[0] = q[0];
|
||||
filter->q[1] = q[1];
|
||||
filter->q[2] = q[2];
|
||||
filter->q[3] = q[3];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Fast inverse square-root
|
||||
// See: http://en.wikipedia.org/wiki/Fast_inverse_square_root
|
||||
|
||||
float invSqrt(float x) {
|
||||
float halfx = 0.5f * x;
|
||||
float y = x;
|
||||
long i = *(long*)&y;
|
||||
i = 0x5f3759df - (i>>1);
|
||||
y = *(float*)&i;
|
||||
y = y * (1.5f - (halfx * y * y));
|
||||
return y;
|
||||
}
|
||||
|
||||
//====================================================================================================
|
||||
// END OF CODE
|
||||
//====================================================================================================
|
||||
@@ -0,0 +1,37 @@
|
||||
//=====================================================================================================
|
||||
// MadgwickAHRS.h
|
||||
//=====================================================================================================
|
||||
//
|
||||
// Implementation of Madgwick's IMU and AHRS algorithms.
|
||||
// See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms
|
||||
//
|
||||
// Date Author Notes
|
||||
// 29/09/2011 SOH Madgwick Initial release
|
||||
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load
|
||||
//
|
||||
//=====================================================================================================
|
||||
#ifndef MadgwickAHRS_h
|
||||
#define MadgwickAHRS_h
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// Variable declaration
|
||||
|
||||
//extern volatile float beta; // algorithm gain
|
||||
//extern volatile float q0, q1, q2, q3; // quaternion of sensor frame relative to auxiliary frame
|
||||
|
||||
typedef struct {
|
||||
float q[4]; // Quaternion: [qw, qx, qy, qz]
|
||||
float beta; // Filter gain (tunes correction strength)
|
||||
float sample_freq; // Sampling frequency in Hz
|
||||
} MadgwickAHRS_Filter;
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Function declarations
|
||||
|
||||
void MadgwickAHRS_init (MadgwickAHRS_Filter* filter, float beta, float sample_freq);
|
||||
void MadgwickAHRS_update(MadgwickAHRS_Filter* filter, float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz);
|
||||
void MadgwickAHRS_update_IMU(MadgwickAHRS_Filter* filter, float gx, float gy, float gz, float ax, float ay, float az);
|
||||
|
||||
#endif
|
||||
//=====================================================================================================
|
||||
// End of file
|
||||
//=====================================================================================================
|
||||
@@ -0,0 +1,409 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file app_debug.c
|
||||
* @author MCD Application Team
|
||||
* @brief Debug capabilities source file for STM32WPAN Middleware
|
||||
******************************************************************************
|
||||
* @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 ------------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
#include "app_common.h"
|
||||
|
||||
#include "app_debug.h"
|
||||
#include "utilities_common.h"
|
||||
#include "shci.h"
|
||||
#include "tl.h"
|
||||
#include "dbg_trace.h"
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PTD */
|
||||
typedef PACKED_STRUCT
|
||||
{
|
||||
GPIO_TypeDef* port;
|
||||
uint16_t pin;
|
||||
uint8_t enable;
|
||||
uint8_t reserved;
|
||||
} APPD_GpioConfig_t;
|
||||
/* USER CODE END PTD */
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PD */
|
||||
#define GPIO_NBR_OF_RF_SIGNALS 9
|
||||
#define GPIO_CFG_NBR_OF_FEATURES 38
|
||||
#define NBR_OF_TRACES_CONFIG_PARAMETERS 4
|
||||
#define NBR_OF_GENERAL_CONFIG_PARAMETERS 4
|
||||
/**
|
||||
* THIS SHALL BE SET TO A VALUE DIFFERENT FROM 0 ONLY ON REQUEST FROM ST SUPPORT
|
||||
*/
|
||||
#define BLE_DTB_CFG 0
|
||||
|
||||
/**
|
||||
* System Debug Options flags to be configured with:
|
||||
* - SHCI_C2_DEBUG_OPTIONS_IPCORE_LP
|
||||
* - SHCI_C2_DEBUG_OPTIONS_IPCORE_NO_LP
|
||||
* - SHCI_C2_DEBUG_OPTIONS_CPU2_STOP_EN
|
||||
* - SHCI_C2_DEBUG_OPTIONS_CPU2_STOP_DIS
|
||||
* which are used to set following configuration bits:
|
||||
* - bit 0: 0: IP BLE core in LP mode 1: IP BLE core in run mode (no LP supported)
|
||||
* - bit 1: 0: CPU2 STOP mode Enable 1: CPU2 STOP mode Disable
|
||||
* - bit [2-7]: bits reserved ( shall be set to 0)
|
||||
*/
|
||||
#define SYS_DBG_CFG1 (SHCI_C2_DEBUG_OPTIONS_IPCORE_LP | SHCI_C2_DEBUG_OPTIONS_CPU2_STOP_EN)
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PM */
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PV */
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static SHCI_C2_DEBUG_TracesConfig_t APPD_TracesConfig={0, 0, 0, 0};
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static SHCI_C2_DEBUG_GeneralConfig_t APPD_GeneralConfig={BLE_DTB_CFG, SYS_DBG_CFG1, {0, 0}};
|
||||
|
||||
#ifdef CFG_DEBUG_TRACE_UART
|
||||
#if(CFG_HW_LPUART1_ENABLED == 1)
|
||||
extern void MX_LPUART1_UART_Init(void);
|
||||
#endif
|
||||
#if(CFG_HW_USART1_ENABLED == 1)
|
||||
extern void MX_USART1_UART_Init(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* THE DEBUG ON GPIO FOR CPU2 IS INTENDED TO BE USED ONLY ON REQUEST FROM ST SUPPORT
|
||||
* It provides timing information on the CPU2 activity.
|
||||
* All configuration of (port, pin) is supported for each features and can be selected by the user
|
||||
* depending on the availability
|
||||
*/
|
||||
static const APPD_GpioConfig_t aGpioConfigList[GPIO_CFG_NBR_OF_FEATURES] =
|
||||
{
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_ISR - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_STACK_TICK - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_CMD_PROCESS - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_ACL_DATA_PROCESS - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* SYS_CMD_PROCESS - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* RNG_PROCESS - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVM_PROCESS - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_GENERAL - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_CMD_RX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_EVT_TX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_ACL_DATA_RX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_SYS_CMD_RX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_SYS_EVT_TX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_CLI_CMD_RX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_OT_CMD_RX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_OT_ACK_TX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_CLI_ACK_TX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_MEM_MANAGER_RX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_TRACES_TX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* HARD_FAULT - Set on Entry / Reset on Exit */
|
||||
/* From v1.1.1 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IP_CORE_LP_STATUS - Set on Entry / Reset on Exit */
|
||||
/* From v1.2.0 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* END_OF_CONNECTION_EVENT - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* TIMER_SERVER_CALLBACK - Toggle on Entry */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* PES_ACTIVITY - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* MB_BLE_SEND_EVT - Set on Entry / Reset on Exit */
|
||||
/* From v1.3.0 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_NO_DELAY - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_STACK_STORE_NVM_CB - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_WRITE_ONGOING - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_WRITE_COMPLETE - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_CLEANUP - Set on Entry / Reset on Exit */
|
||||
/* From v1.4.0 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_START - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* FLASH_EOP - Set on Entry / Reset on Exit */
|
||||
/* From v1.5.0 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* FLASH_WRITE - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* FLASH_ERASE - Set on Entry / Reset on Exit */
|
||||
/* From v1.6.0 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_RESCHEDULE_EVENT - Set on Entry / Reset on Exit */
|
||||
/* From v1.8.0 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_LLD_CMD_RX - Set on Entry / Reset on Exit */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_LLD_ACK_TX - Set on Entry / Reset on Exit */
|
||||
/* From v1.9.0 */
|
||||
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_ASYNCH_EVENT_NACKED - Set on Entry / Reset on Exit */
|
||||
};
|
||||
|
||||
/**
|
||||
* THE DEBUG ON GPIO FOR CPU2 IS INTENDED TO BE USED ONLY ON REQUEST FROM ST SUPPORT
|
||||
* This table is relevant only for BLE
|
||||
* It provides timing information on BLE RF activity.
|
||||
* New signals may be allocated at any location when requested by ST
|
||||
* The GPIO allocated to each signal depend on the BLE_DTB_CFG value and cannot be changed
|
||||
*/
|
||||
#if( BLE_DTB_CFG == 7)
|
||||
static const APPD_GpioConfig_t aRfConfigList[GPIO_NBR_OF_RF_SIGNALS] =
|
||||
{
|
||||
{ GPIOB, LL_GPIO_PIN_2, 0, 0}, /* DTB10 - Tx/Rx SPI */
|
||||
{ GPIOB, LL_GPIO_PIN_7, 0, 0}, /* DTB11 - Tx/Tx SPI Clk */
|
||||
{ GPIOA, LL_GPIO_PIN_8, 0, 0}, /* DTB12 - Tx/Rx Ready & SPI Select */
|
||||
{ GPIOA, LL_GPIO_PIN_9, 0, 0}, /* DTB13 - Tx/Rx Start */
|
||||
{ GPIOA, LL_GPIO_PIN_10, 0, 0}, /* DTB14 - FSM0 */
|
||||
{ GPIOA, LL_GPIO_PIN_11, 0, 0}, /* DTB15 - FSM1 */
|
||||
{ GPIOB, LL_GPIO_PIN_8, 0, 0}, /* DTB16 - FSM2 */
|
||||
{ GPIOB, LL_GPIO_PIN_11, 0, 0}, /* DTB17 - FSM3 */
|
||||
{ GPIOB, LL_GPIO_PIN_10, 0, 0}, /* DTB18 - FSM4 */
|
||||
};
|
||||
#endif
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN GV */
|
||||
/* USER CODE END GV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* USER CODE BEGIN PFP */
|
||||
static void APPD_SetCPU2GpioConfig( void );
|
||||
static void APPD_BleDtbCfg( void );
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
void APPD_Init( void )
|
||||
{
|
||||
/* USER CODE BEGIN APPD_Init */
|
||||
#if (CFG_DEBUGGER_SUPPORTED == 1)
|
||||
/**
|
||||
* Keep debugger enabled while in any low power mode
|
||||
*/
|
||||
HAL_DBGMCU_EnableDBGSleepMode();
|
||||
HAL_DBGMCU_EnableDBGStopMode();
|
||||
|
||||
/***************** ENABLE DEBUGGER *************************************/
|
||||
LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_48);
|
||||
|
||||
#else
|
||||
GPIO_InitTypeDef gpio_config = {0};
|
||||
|
||||
gpio_config.Pull = GPIO_NOPULL;
|
||||
gpio_config.Mode = GPIO_MODE_ANALOG;
|
||||
|
||||
gpio_config.Pin = GPIO_PIN_15 | GPIO_PIN_14 | GPIO_PIN_13;
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOA, &gpio_config);
|
||||
__HAL_RCC_GPIOA_CLK_DISABLE();
|
||||
|
||||
gpio_config.Pin = GPIO_PIN_4 | GPIO_PIN_3;
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOB, &gpio_config);
|
||||
__HAL_RCC_GPIOB_CLK_DISABLE();
|
||||
|
||||
HAL_DBGMCU_DisableDBGSleepMode();
|
||||
HAL_DBGMCU_DisableDBGStopMode();
|
||||
HAL_DBGMCU_DisableDBGStandbyMode();
|
||||
|
||||
#endif /* (CFG_DEBUGGER_SUPPORTED == 1) */
|
||||
|
||||
#if(CFG_DEBUG_TRACE != 0)
|
||||
DbgTraceInit();
|
||||
#endif
|
||||
|
||||
APPD_SetCPU2GpioConfig( );
|
||||
APPD_BleDtbCfg( );
|
||||
|
||||
/* USER CODE END APPD_Init */
|
||||
return;
|
||||
}
|
||||
|
||||
void APPD_EnableCPU2( void )
|
||||
{
|
||||
/* USER CODE BEGIN APPD_EnableCPU2 */
|
||||
SHCI_C2_DEBUG_Init_Cmd_Packet_t DebugCmdPacket =
|
||||
{
|
||||
{{0,0,0}}, /**< Does not need to be initialized */
|
||||
{(uint8_t *)aGpioConfigList,
|
||||
(uint8_t *)&APPD_TracesConfig,
|
||||
(uint8_t *)&APPD_GeneralConfig,
|
||||
GPIO_CFG_NBR_OF_FEATURES,
|
||||
NBR_OF_TRACES_CONFIG_PARAMETERS,
|
||||
NBR_OF_GENERAL_CONFIG_PARAMETERS}
|
||||
};
|
||||
|
||||
/**< Traces channel initialization */
|
||||
TL_TRACES_Init( );
|
||||
|
||||
/** GPIO DEBUG Initialization */
|
||||
SHCI_C2_DEBUG_Init( &DebugCmdPacket );
|
||||
|
||||
/* USER CODE END APPD_EnableCPU2 */
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* LOCAL FUNCTIONS
|
||||
*
|
||||
*************************************************************/
|
||||
static void APPD_SetCPU2GpioConfig( void )
|
||||
{
|
||||
/* USER CODE BEGIN APPD_SetCPU2GpioConfig */
|
||||
GPIO_InitTypeDef gpio_config = {0};
|
||||
uint8_t local_loop;
|
||||
uint16_t gpioa_pin_list;
|
||||
uint16_t gpiob_pin_list;
|
||||
uint16_t gpioc_pin_list;
|
||||
gpioa_pin_list = 0;
|
||||
gpiob_pin_list = 0;
|
||||
gpioc_pin_list = 0;
|
||||
|
||||
for(local_loop = 0 ; local_loop < GPIO_CFG_NBR_OF_FEATURES; local_loop++)
|
||||
{
|
||||
if( aGpioConfigList[local_loop].enable != 0)
|
||||
{
|
||||
switch((uint32_t)aGpioConfigList[local_loop].port)
|
||||
{
|
||||
case (uint32_t)GPIOA:
|
||||
gpioa_pin_list |= aGpioConfigList[local_loop].pin;
|
||||
break;
|
||||
case (uint32_t)GPIOB:
|
||||
gpiob_pin_list |= aGpioConfigList[local_loop].pin;
|
||||
break;
|
||||
case (uint32_t)GPIOC:
|
||||
gpioc_pin_list |= aGpioConfigList[local_loop].pin;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gpio_config.Pull = GPIO_NOPULL;
|
||||
gpio_config.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
gpio_config.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
|
||||
if(gpioa_pin_list != 0)
|
||||
{
|
||||
gpio_config.Pin = gpioa_pin_list;
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_C2GPIOA_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOA, &gpio_config);
|
||||
HAL_GPIO_WritePin(GPIOA, gpioa_pin_list, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
if(gpiob_pin_list != 0)
|
||||
{
|
||||
gpio_config.Pin = gpiob_pin_list;
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_C2GPIOB_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOB, &gpio_config);
|
||||
HAL_GPIO_WritePin(GPIOB, gpiob_pin_list, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
if(gpioc_pin_list != 0)
|
||||
{
|
||||
gpio_config.Pin = gpioc_pin_list;
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_C2GPIOC_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOC, &gpio_config);
|
||||
HAL_GPIO_WritePin(GPIOC, gpioc_pin_list, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
/* USER CODE END APPD_SetCPU2GpioConfig */
|
||||
return;
|
||||
}
|
||||
|
||||
static void APPD_BleDtbCfg( void )
|
||||
{
|
||||
/* USER CODE BEGIN APPD_BleDtbCfg */
|
||||
#if (BLE_DTB_CFG != 0)
|
||||
GPIO_InitTypeDef gpio_config = {0};
|
||||
uint8_t local_loop;
|
||||
uint16_t gpioa_pin_list;
|
||||
uint16_t gpiob_pin_list;
|
||||
gpioa_pin_list = 0;
|
||||
gpiob_pin_list = 0;
|
||||
|
||||
for(local_loop = 0 ; local_loop < GPIO_NBR_OF_RF_SIGNALS; local_loop++)
|
||||
{
|
||||
if( aRfConfigList[local_loop].enable != 0)
|
||||
{
|
||||
switch((uint32_t)aRfConfigList[local_loop].port)
|
||||
{
|
||||
case (uint32_t)GPIOA:
|
||||
gpioa_pin_list |= aRfConfigList[local_loop].pin;
|
||||
break;
|
||||
case (uint32_t)GPIOB:
|
||||
gpiob_pin_list |= aRfConfigList[local_loop].pin;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
gpio_config.Pull = GPIO_NOPULL;
|
||||
gpio_config.Mode = GPIO_MODE_AF_PP;
|
||||
gpio_config.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
gpio_config.Alternate = GPIO_AF6_RF_DTB7;
|
||||
|
||||
if(gpioa_pin_list != 0)
|
||||
{
|
||||
gpio_config.Pin = gpioa_pin_list;
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_C2GPIOA_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOA, &gpio_config);
|
||||
}
|
||||
|
||||
if(gpiob_pin_list != 0)
|
||||
{
|
||||
gpio_config.Pin = gpiob_pin_list;
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_C2GPIOB_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOB, &gpio_config);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* USER CODE END APPD_BleDtbCfg */
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* WRAP FUNCTIONS
|
||||
*
|
||||
*************************************************************/
|
||||
#if(CFG_DEBUG_TRACE != 0)
|
||||
void DbgOutputInit( void )
|
||||
{
|
||||
/* USER CODE BEGIN DbgOutputInit */
|
||||
#ifdef CFG_DEBUG_TRACE_UART
|
||||
if (CFG_DEBUG_TRACE_UART == hw_lpuart1)
|
||||
{
|
||||
#if(CFG_HW_LPUART1_ENABLED == 1)
|
||||
MX_LPUART1_UART_Init();
|
||||
#endif
|
||||
}
|
||||
else if (CFG_DEBUG_TRACE_UART == hw_uart1)
|
||||
{
|
||||
#if(CFG_HW_USART1_ENABLED == 1)
|
||||
MX_USART1_UART_Init();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* USER CODE END DbgOutputInit */
|
||||
return;
|
||||
}
|
||||
|
||||
void DbgOutputTraces( uint8_t *p_data, uint16_t size, void (*cb)(void) )
|
||||
{
|
||||
/* USER CODE BEGIN DbgOutputTraces */
|
||||
HW_UART_Transmit_DMA(CFG_DEBUG_TRACE_UART, p_data, size, cb);
|
||||
|
||||
/* USER CODE END DbgOutputTraces */
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,626 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file app_entry.c
|
||||
* @author MCD Application Team
|
||||
* @brief Entry point 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 */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "app_common.h"
|
||||
#include "main.h"
|
||||
#include "app_entry.h"
|
||||
#include "ble.h"
|
||||
#include "tl.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "shci_tl.h"
|
||||
#include "stm32_lpm.h"
|
||||
#include "app_debug.h"
|
||||
#include "dbg_trace.h"
|
||||
#include "shci.h"
|
||||
#include "otp.h"
|
||||
|
||||
/* Private includes -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
extern RTC_HandleTypeDef hrtc;
|
||||
|
||||
/* USER CODE BEGIN PTD */
|
||||
|
||||
/* USER CODE END PTD */
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#define POOL_SIZE (CFG_TLBLE_EVT_QUEUE_LENGTH*4U*DIVC((sizeof(TL_PacketHeader_t) + TL_BLE_EVENT_FRAME_SIZE), 4U))
|
||||
|
||||
/* USER CODE BEGIN PD */
|
||||
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PM */
|
||||
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t EvtPool[POOL_SIZE];
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t SystemCmdBuffer;
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t SystemSpareEvtBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255U];
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t BleSpareEvtBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255];
|
||||
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
osMutexId_t MtxShciId;
|
||||
osSemaphoreId_t SemShciId;
|
||||
osThreadId_t ShciUserEvtProcessId;
|
||||
|
||||
const osThreadAttr_t ShciUserEvtProcess_attr = {
|
||||
.name = CFG_SHCI_USER_EVT_PROCESS_NAME,
|
||||
.attr_bits = CFG_SHCI_USER_EVT_PROCESS_ATTR_BITS,
|
||||
.cb_mem = CFG_SHCI_USER_EVT_PROCESS_CB_MEM,
|
||||
.cb_size = CFG_SHCI_USER_EVT_PROCESS_CB_SIZE,
|
||||
.stack_mem = CFG_SHCI_USER_EVT_PROCESS_STACK_MEM,
|
||||
.priority = CFG_SHCI_USER_EVT_PROCESS_PRIORITY,
|
||||
.stack_size = CFG_SHCI_USER_EVT_PROCESS_STACK_SIZE
|
||||
};
|
||||
|
||||
/* Private functions prototypes-----------------------------------------------*/
|
||||
static void ShciUserEvtProcess(void *argument);
|
||||
static void Config_HSE(void);
|
||||
static void Reset_Device(void);
|
||||
#if (CFG_HW_RESET_BY_FW == 1)
|
||||
static void Reset_IPCC(void);
|
||||
static void Reset_BackupDomain(void);
|
||||
#endif /* CFG_HW_RESET_BY_FW == 1*/
|
||||
static void System_Init(void);
|
||||
static void SystemPower_Config(void);
|
||||
static void appe_Tl_Init(void);
|
||||
static void APPE_SysStatusNot(SHCI_TL_CmdStatus_t status);
|
||||
static void APPE_SysUserEvtRx(void * pPayload);
|
||||
static void APPE_SysEvtReadyProcessing(void * pPayload);
|
||||
static void APPE_SysEvtError(void * pPayload);
|
||||
static void Init_Rtc(void);
|
||||
__WEAK void APP_BLE_Init(void);
|
||||
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
void MX_APPE_Config(void)
|
||||
{
|
||||
/**
|
||||
* The OPTVERR flag is wrongly set at power on
|
||||
* It shall be cleared before using any HAL_FLASH_xxx() api
|
||||
*/
|
||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
|
||||
|
||||
/**
|
||||
* Reset some configurations so that the system behave in the same way
|
||||
* when either out of nReset or Power On
|
||||
*/
|
||||
Reset_Device();
|
||||
|
||||
/* Configure HSE Tuning */
|
||||
Config_HSE();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void MX_APPE_Init(void)
|
||||
{
|
||||
System_Init(); /**< System initialization */
|
||||
|
||||
SystemPower_Config(); /**< Configure the system Power Mode */
|
||||
|
||||
HW_TS_Init(hw_ts_InitMode_Full, &hrtc); /**< Initialize the TimerServer */
|
||||
|
||||
/* USER CODE BEGIN APPE_Init_1 */
|
||||
|
||||
/* USER CODE END APPE_Init_1 */
|
||||
appe_Tl_Init(); /* Initialize all transport layers */
|
||||
|
||||
/**
|
||||
* From now, the application is waiting for the ready event (VS_HCI_C2_Ready)
|
||||
* received on the system channel before starting the Stack
|
||||
* This system event is received with APPE_SysUserEvtRx()
|
||||
*/
|
||||
/* USER CODE BEGIN APPE_Init_2 */
|
||||
|
||||
/* USER CODE END APPE_Init_2 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Init_Smps(void)
|
||||
{
|
||||
#if (CFG_USE_SMPS != 0)
|
||||
/**
|
||||
* Configure and enable SMPS
|
||||
*
|
||||
* The SMPS configuration is not yet supported by CubeMx
|
||||
* when SMPS output voltage is set to 1.4V, the RF output power is limited to 3.7dBm
|
||||
* the SMPS output voltage shall be increased for higher RF output power
|
||||
*/
|
||||
LL_PWR_SMPS_SetStartupCurrent(LL_PWR_SMPS_STARTUP_CURRENT_80MA);
|
||||
LL_PWR_SMPS_SetOutputVoltageLevel(LL_PWR_SMPS_OUTPUT_VOLTAGE_1V40);
|
||||
LL_PWR_SMPS_Enable();
|
||||
#endif /* CFG_USE_SMPS != 0 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Init_Exti(void)
|
||||
{
|
||||
/* Enable IPCC(36), HSEM(38) wakeup interrupts on CPU1 */
|
||||
LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_36 | LL_EXTI_LINE_38);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN FD */
|
||||
|
||||
/* USER CODE END FD */
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* LOCAL FUNCTIONS
|
||||
*
|
||||
*************************************************************/
|
||||
static void Reset_Device(void)
|
||||
{
|
||||
#if (CFG_HW_RESET_BY_FW == 1)
|
||||
Reset_BackupDomain();
|
||||
|
||||
Reset_IPCC();
|
||||
#endif /* CFG_HW_RESET_BY_FW == 1 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if (CFG_HW_RESET_BY_FW == 1)
|
||||
static void Reset_BackupDomain(void)
|
||||
{
|
||||
if ((LL_RCC_IsActiveFlag_PINRST() != FALSE) && (LL_RCC_IsActiveFlag_SFTRST() == FALSE))
|
||||
{
|
||||
HAL_PWR_EnableBkUpAccess(); /**< Enable access to the RTC registers */
|
||||
|
||||
/**
|
||||
* Write twice the value to flush the APB-AHB bridge
|
||||
* This bit shall be written in the register before writing the next one
|
||||
*/
|
||||
HAL_PWR_EnableBkUpAccess();
|
||||
|
||||
__HAL_RCC_BACKUPRESET_FORCE();
|
||||
__HAL_RCC_BACKUPRESET_RELEASE();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void Reset_IPCC(void)
|
||||
{
|
||||
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_IPCC);
|
||||
|
||||
LL_C1_IPCC_ClearFlag_CHx(
|
||||
IPCC,
|
||||
LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
|
||||
| LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
|
||||
|
||||
LL_C2_IPCC_ClearFlag_CHx(
|
||||
IPCC,
|
||||
LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
|
||||
| LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
|
||||
|
||||
LL_C1_IPCC_DisableTransmitChannel(
|
||||
IPCC,
|
||||
LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
|
||||
| LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
|
||||
|
||||
LL_C2_IPCC_DisableTransmitChannel(
|
||||
IPCC,
|
||||
LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
|
||||
| LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
|
||||
|
||||
LL_C1_IPCC_DisableReceiveChannel(
|
||||
IPCC,
|
||||
LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
|
||||
| LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
|
||||
|
||||
LL_C2_IPCC_DisableReceiveChannel(
|
||||
IPCC,
|
||||
LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
|
||||
| LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* CFG_HW_RESET_BY_FW == 1 */
|
||||
|
||||
static void Config_HSE(void)
|
||||
{
|
||||
OTP_ID0_t * p_otp;
|
||||
|
||||
/**
|
||||
* Read HSE_Tuning from OTP
|
||||
*/
|
||||
p_otp = (OTP_ID0_t *) OTP_Read(0);
|
||||
if (p_otp)
|
||||
{
|
||||
LL_RCC_HSE_SetCapacitorTuning(p_otp->hse_tuning);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void System_Init(void)
|
||||
{
|
||||
Init_Smps();
|
||||
|
||||
Init_Exti();
|
||||
|
||||
Init_Rtc();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void Init_Rtc(void)
|
||||
{
|
||||
/* Disable RTC registers write protection */
|
||||
LL_RTC_DisableWriteProtection(RTC);
|
||||
|
||||
LL_RTC_WAKEUP_SetClock(RTC, CFG_RTC_WUCKSEL_DIVIDER);
|
||||
|
||||
/* Enable RTC registers write protection */
|
||||
LL_RTC_EnableWriteProtection(RTC);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the system for power optimization
|
||||
*
|
||||
* @note This API configures the system to be ready for low power mode
|
||||
*
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void SystemPower_Config(void)
|
||||
{
|
||||
/**
|
||||
* Select HSI as system clock source after Wake Up from Stop mode
|
||||
*/
|
||||
LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI);
|
||||
|
||||
/* Initialize low power manager */
|
||||
UTIL_LPM_Init();
|
||||
/* Initialize the CPU2 reset value before starting CPU2 with C2BOOT */
|
||||
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
|
||||
|
||||
#if (CFG_USB_INTERFACE_ENABLE != 0)
|
||||
/**
|
||||
* Enable USB power
|
||||
*/
|
||||
HAL_PWREx_EnableVddUSB();
|
||||
#endif /* CFG_USB_INTERFACE_ENABLE != 0 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void appe_Tl_Init(void)
|
||||
{
|
||||
TL_MM_Config_t tl_mm_config;
|
||||
SHCI_TL_HciInitConf_t SHci_Tl_Init_Conf;
|
||||
/**< Reference table initialization */
|
||||
TL_Init();
|
||||
|
||||
MtxShciId = osMutexNew(NULL);
|
||||
SemShciId = osSemaphoreNew(1, 0, NULL); /*< Create the semaphore and make it busy at initialization */
|
||||
|
||||
/** FreeRTOS system task creation */
|
||||
ShciUserEvtProcessId = osThreadNew(ShciUserEvtProcess, NULL, &ShciUserEvtProcess_attr);
|
||||
|
||||
/**< System channel initialization */
|
||||
SHci_Tl_Init_Conf.p_cmdbuffer = (uint8_t*)&SystemCmdBuffer;
|
||||
SHci_Tl_Init_Conf.StatusNotCallBack = APPE_SysStatusNot;
|
||||
shci_init(APPE_SysUserEvtRx, (void*) &SHci_Tl_Init_Conf);
|
||||
|
||||
/**< Memory Manager channel initialization */
|
||||
tl_mm_config.p_BleSpareEvtBuffer = BleSpareEvtBuffer;
|
||||
tl_mm_config.p_SystemSpareEvtBuffer = SystemSpareEvtBuffer;
|
||||
tl_mm_config.p_AsynchEvtPool = EvtPool;
|
||||
tl_mm_config.AsynchEvtPoolSize = POOL_SIZE;
|
||||
TL_MM_Init(&tl_mm_config);
|
||||
|
||||
TL_Enable();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
__WEAK void APP_BLE_Init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void APPE_SysStatusNot(SHCI_TL_CmdStatus_t status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case SHCI_TL_CmdBusy:
|
||||
osMutexAcquire(MtxShciId, osWaitForever);
|
||||
break;
|
||||
|
||||
case SHCI_TL_CmdAvailable:
|
||||
osMutexRelease(MtxShciId);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of the payload for a system user event is tSHCI_UserEvtRxParam
|
||||
* When the system event is both :
|
||||
* - a ready event (subevtcode = SHCI_SUB_EVT_CODE_READY)
|
||||
* - reported by the FUS (sysevt_ready_rsp == FUS_FW_RUNNING)
|
||||
* The buffer shall not be released
|
||||
* (eg ((tSHCI_UserEvtRxParam*)pPayload)->status shall be set to SHCI_TL_UserEventFlow_Disable)
|
||||
* When the status is not filled, the buffer is released by default
|
||||
*/
|
||||
static void APPE_SysUserEvtRx(void * pPayload)
|
||||
{
|
||||
TL_AsynchEvt_t *p_sys_event;
|
||||
WirelessFwInfo_t WirelessInfo;
|
||||
|
||||
p_sys_event = (TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload);
|
||||
|
||||
switch(p_sys_event->subevtcode)
|
||||
{
|
||||
case SHCI_SUB_EVT_CODE_READY:
|
||||
/* Read the firmware version of both the wireless firmware and the FUS */
|
||||
SHCI_GetWirelessFwInfo(&WirelessInfo);
|
||||
APP_DBG_MSG("Wireless Firmware version %d.%d.%d\n", WirelessInfo.VersionMajor, WirelessInfo.VersionMinor, WirelessInfo.VersionSub);
|
||||
APP_DBG_MSG("Wireless Firmware build %d\n", WirelessInfo.VersionReleaseType);
|
||||
APP_DBG_MSG("FUS version %d.%d.%d\n", WirelessInfo.FusVersionMajor, WirelessInfo.FusVersionMinor, WirelessInfo.FusVersionSub);
|
||||
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_CODE_READY\n\r");
|
||||
APPE_SysEvtReadyProcessing(pPayload);
|
||||
break;
|
||||
|
||||
case SHCI_SUB_EVT_ERROR_NOTIF:
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_ERROR_NOTIF \n\r");
|
||||
APPE_SysEvtError(pPayload);
|
||||
break;
|
||||
|
||||
case SHCI_SUB_EVT_BLE_NVM_RAM_UPDATE:
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_BLE_NVM_RAM_UPDATE -- BLE NVM RAM HAS BEEN UPDATED BY CPU2 \n");
|
||||
APP_DBG_MSG(" - StartAddress = %lx , Size = %ld\n",
|
||||
((SHCI_C2_BleNvmRamUpdate_Evt_t*)p_sys_event->payload)->StartAddress,
|
||||
((SHCI_C2_BleNvmRamUpdate_Evt_t*)p_sys_event->payload)->Size);
|
||||
break;
|
||||
|
||||
case SHCI_SUB_EVT_NVM_START_WRITE:
|
||||
APP_DBG_MSG("==>> SHCI_SUB_EVT_NVM_START_WRITE : NumberOfWords = %ld\n",
|
||||
((SHCI_C2_NvmStartWrite_Evt_t*)p_sys_event->payload)->NumberOfWords);
|
||||
break;
|
||||
|
||||
case SHCI_SUB_EVT_NVM_END_WRITE:
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_NVM_END_WRITE\n\r");
|
||||
break;
|
||||
|
||||
case SHCI_SUB_EVT_NVM_START_ERASE:
|
||||
APP_DBG_MSG("==>>SHCI_SUB_EVT_NVM_START_ERASE : NumberOfSectors = %ld\n",
|
||||
((SHCI_C2_NvmStartErase_Evt_t*)p_sys_event->payload)->NumberOfSectors);
|
||||
break;
|
||||
|
||||
case SHCI_SUB_EVT_NVM_END_ERASE:
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_NVM_END_ERASE\n\r");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notify a system error coming from the M0 firmware
|
||||
* @param ErrorCode : errorCode detected by the M0 firmware
|
||||
*
|
||||
* @retval None
|
||||
*/
|
||||
static void APPE_SysEvtError(void * pPayload)
|
||||
{
|
||||
TL_AsynchEvt_t *p_sys_event;
|
||||
SCHI_SystemErrCode_t *p_sys_error_code;
|
||||
|
||||
p_sys_event = (TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload);
|
||||
p_sys_error_code = (SCHI_SystemErrCode_t*) p_sys_event->payload;
|
||||
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_ERROR_NOTIF WITH REASON %x \n\r",(*p_sys_error_code));
|
||||
|
||||
if ((*p_sys_error_code) == ERR_BLE_INIT)
|
||||
{
|
||||
/* Error during BLE stack initialization */
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_ERROR_NOTIF WITH REASON - ERR_BLE_INIT \n");
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_ERROR_NOTIF WITH REASON - BLE ERROR \n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void APPE_SysEvtReadyProcessing(void * pPayload)
|
||||
{
|
||||
TL_AsynchEvt_t *p_sys_event;
|
||||
SHCI_C2_Ready_Evt_t *p_sys_ready_event;
|
||||
|
||||
SHCI_C2_CONFIG_Cmd_Param_t config_param = {0};
|
||||
uint32_t RevisionID=0;
|
||||
uint32_t DeviceID=0;
|
||||
|
||||
p_sys_event = (TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload);
|
||||
p_sys_ready_event = (SHCI_C2_Ready_Evt_t*) p_sys_event->payload;
|
||||
|
||||
if (p_sys_ready_event->sysevt_ready_rsp == WIRELESS_FW_RUNNING)
|
||||
{
|
||||
/**
|
||||
* The wireless firmware is running on the CPU2
|
||||
*/
|
||||
APP_DBG_MSG(">>== WIRELESS_FW_RUNNING \n");
|
||||
|
||||
/* Traces channel initialization */
|
||||
APPD_EnableCPU2();
|
||||
|
||||
/* Enable all events Notification */
|
||||
config_param.PayloadCmdSize = SHCI_C2_CONFIG_PAYLOAD_CMD_SIZE;
|
||||
config_param.EvtMask1 = SHCI_C2_CONFIG_EVTMASK1_BIT0_ERROR_NOTIF_ENABLE
|
||||
+ SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE
|
||||
+ SHCI_C2_CONFIG_EVTMASK1_BIT2_THREAD_NVM_RAM_UPDATE_ENABLE
|
||||
+ SHCI_C2_CONFIG_EVTMASK1_BIT3_NVM_START_WRITE_ENABLE
|
||||
+ SHCI_C2_CONFIG_EVTMASK1_BIT4_NVM_END_WRITE_ENABLE
|
||||
+ SHCI_C2_CONFIG_EVTMASK1_BIT5_NVM_START_ERASE_ENABLE
|
||||
+ SHCI_C2_CONFIG_EVTMASK1_BIT6_NVM_END_ERASE_ENABLE;
|
||||
|
||||
/* Read revision identifier */
|
||||
/**
|
||||
* @brief Return the device revision identifier
|
||||
* @note This field indicates the revision of the device.
|
||||
* @rmtoll DBGMCU_IDCODE REV_ID LL_DBGMCU_GetRevisionID
|
||||
* @retval Values between Min_Data=0x00 and Max_Data=0xFFFF
|
||||
*/
|
||||
RevisionID = LL_DBGMCU_GetRevisionID();
|
||||
|
||||
APP_DBG_MSG(">>== DBGMCU_GetRevisionID= %lx \n\r", RevisionID);
|
||||
|
||||
config_param.RevisionID = (uint16_t)RevisionID;
|
||||
|
||||
DeviceID = LL_DBGMCU_GetDeviceID();
|
||||
APP_DBG_MSG(">>== DBGMCU_GetDeviceID= %lx \n\r", DeviceID);
|
||||
config_param.DeviceID = (uint16_t)DeviceID;
|
||||
(void)SHCI_C2_Config(&config_param);
|
||||
|
||||
APP_BLE_Init();
|
||||
UTIL_LPM_SetOffMode(1U << CFG_LPM_APP, UTIL_LPM_ENABLE);
|
||||
}
|
||||
else if (p_sys_ready_event->sysevt_ready_rsp == FUS_FW_RUNNING)
|
||||
{
|
||||
/**
|
||||
* The FUS firmware is running on the CPU2
|
||||
* In the scope of this application, there should be no case when we get here
|
||||
*/
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_CODE_READY - FUS_FW_RUNNING \n\r");
|
||||
|
||||
/* The packet shall not be released as this is not supported by the FUS */
|
||||
((tSHCI_UserEvtRxParam*)pPayload)->status = SHCI_TL_UserEventFlow_Disable;
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_DBG_MSG(">>== SHCI_SUB_EVT_CODE_READY - UNEXPECTED CASE \n\r");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* FREERTOS WRAPPER FUNCTIONS
|
||||
*
|
||||
*************************************************************/
|
||||
static void ShciUserEvtProcess(void *argument)
|
||||
{
|
||||
UNUSED(argument);
|
||||
for(;;)
|
||||
{
|
||||
/* USER CODE BEGIN SHCI_USER_EVT_PROCESS_1 */
|
||||
|
||||
/* USER CODE END SHCI_USER_EVT_PROCESS_1 */
|
||||
osThreadFlagsWait(1, osFlagsWaitAny, osWaitForever);
|
||||
shci_user_evt_proc();
|
||||
/* USER CODE BEGIN SHCI_USER_EVT_PROCESS_2 */
|
||||
|
||||
/* USER CODE END SHCI_USER_EVT_PROCESS_2 */
|
||||
}
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN FD_LOCAL_FUNCTIONS */
|
||||
|
||||
/* USER CODE END FD_LOCAL_FUNCTIONS */
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* WRAP FUNCTIONS
|
||||
*
|
||||
*************************************************************/
|
||||
void HAL_Delay(uint32_t Delay)
|
||||
{
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t wait = Delay;
|
||||
|
||||
/* Add a freq to guarantee minimum wait */
|
||||
if (wait < HAL_MAX_DELAY)
|
||||
{
|
||||
wait += HAL_GetTickFreq();
|
||||
}
|
||||
|
||||
while ((HAL_GetTick() - tickstart) < wait)
|
||||
{
|
||||
/************************************************************************************
|
||||
* ENTER SLEEP MODE
|
||||
***********************************************************************************/
|
||||
LL_LPM_EnableSleep(); /**< Clear SLEEPDEEP bit of Cortex System Control Register */
|
||||
|
||||
/**
|
||||
* This option is used to ensure that store operations are completed
|
||||
*/
|
||||
#if defined (__CC_ARM) || defined (__ARMCC_VERSION)
|
||||
__force_stores();
|
||||
#endif /* __ARMCC_VERSION */
|
||||
|
||||
__WFI();
|
||||
}
|
||||
}
|
||||
|
||||
void shci_notify_asynch_evt(void* pdata)
|
||||
{
|
||||
UNUSED(pdata);
|
||||
osThreadFlagsSet(ShciUserEvtProcessId, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
void shci_cmd_resp_release(uint32_t flag)
|
||||
{
|
||||
UNUSED(flag);
|
||||
osSemaphoreRelease(SemShciId);
|
||||
return;
|
||||
}
|
||||
|
||||
void shci_cmd_resp_wait(uint32_t timeout)
|
||||
{
|
||||
UNUSED(timeout);
|
||||
osSemaphoreAcquire(SemShciId, osWaitForever);
|
||||
return;
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN FD_WRAP_FUNCTIONS */
|
||||
|
||||
/* USER CODE END FD_WRAP_FUNCTIONS */
|
||||
@@ -0,0 +1,58 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : app_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"
|
||||
|
||||
/* 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 Variables */
|
||||
|
||||
/* USER CODE END Variables */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* USER CODE BEGIN FunctionPrototypes */
|
||||
|
||||
/* USER CODE END FunctionPrototypes */
|
||||
|
||||
/* Private application code --------------------------------------------------*/
|
||||
/* USER CODE BEGIN Application */
|
||||
|
||||
/* USER CODE END Application */
|
||||
+2196
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,656 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Bosch Sensortec GmbH. All rights reserved.
|
||||
*
|
||||
* BSD-3-Clause
|
||||
*
|
||||
* 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 the copyright holder 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.
|
||||
*
|
||||
* @file bmm350.h
|
||||
* @date 2025-10-30
|
||||
* @version v1.10.0
|
||||
*
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @defgroup bmm350 BMM350
|
||||
* @brief Sensor driver for BMM350 sensor
|
||||
*/
|
||||
|
||||
#ifndef _BMM350_H
|
||||
#define _BMM350_H
|
||||
|
||||
/*! CPP guard */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*************************** Header files *******************************/
|
||||
|
||||
#include "bmm350_defs.h"
|
||||
|
||||
/******************* Function prototype declarations ********************/
|
||||
|
||||
/**
|
||||
* \ingroup bmm350
|
||||
* \defgroup bmm350ApiVersion Information
|
||||
* @brief Get the BMM350 SensorAPI Version
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiVersion
|
||||
* \page bmm350_api_bmm350_api_version bmm350_api_version
|
||||
* \code
|
||||
* int8_t bmm350_api_version(struct bmm350_version *api_verison);
|
||||
* \endcode
|
||||
* @details This API gives the release version details of the BMM350 SensorAPI.
|
||||
*
|
||||
* @param[out] version : Structure instance of bmm350_version
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_api_version(struct bmm350_version *api_version);
|
||||
|
||||
/**
|
||||
* \ingroup bmm350
|
||||
* \defgroup bmm350ApiInit Initialization
|
||||
* @brief Initialize the sensor and device structure
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiInit
|
||||
* \page bmm350_api_bmm350_init bmm350_init
|
||||
* \code
|
||||
* int8_t bmm350_init(struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API is the entry point. Call this API before using other APIs.
|
||||
* This API reads the chip-id of the sensor which is the first step to
|
||||
* verify the sensor and also it configures the read mechanism of I2C and
|
||||
* I3C interface.
|
||||
*
|
||||
* @param[in,out] dev : Structure instance of bmm350_dev
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_init(struct bmm350_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmm350
|
||||
* \defgroup bmm350ApiReset Reset
|
||||
* @brief Reset APIs
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiReset
|
||||
* \page bmm350_api_bmm350_soft_reset bmm350_soft_reset
|
||||
* \code
|
||||
* int8_t bmm350_soft_reset(struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API is used to perform soft-reset of the sensor
|
||||
* where all the registers are reset to their default values.
|
||||
*
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
|
||||
int8_t bmm350_soft_reset(struct bmm350_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmm350
|
||||
* \defgroup bmm350ApiSetGet Set-Get
|
||||
* @brief Set and Get APIs
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiSetGet
|
||||
* \page bmm350_api_bmm350_set_regs bmm350_set_regs
|
||||
* \code
|
||||
* int8_t bmm350_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint16_t len, struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API writes the given data to the register address
|
||||
* of the sensor.
|
||||
*
|
||||
* @param[in] reg_addr : Register address from where the data to be written.
|
||||
* @param[in] reg_data : Pointer to data buffer which is to be written
|
||||
* in the reg_addr of sensor.
|
||||
* @param[in] len : No of bytes of data to write..
|
||||
* @param[in, out] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint16_t len, struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiSetGet
|
||||
* \page bmm350_api_bmm350_get_regs bmm350_get_regs
|
||||
* \code
|
||||
* int8_t bmm350_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API reads the data from the given register address of sensor.
|
||||
*
|
||||
* @param[in] reg_addr : Register address from where the data to be read
|
||||
* @param[out] reg_data : Pointer to data buffer to store the read data.
|
||||
* @param[in] len : No of bytes of data to be read.
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct bmm350_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmm350
|
||||
* \defgroup bmm350ApiDelay Delay
|
||||
* @brief Delay function in microseconds
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiDelay
|
||||
* \page bmm350_api_bmm350_delay_us bmm350_delay_us
|
||||
* \code
|
||||
* int8_t bmm350_delay_us(uint32_t period_us, const struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This function provides the delay for required time (Microsecond) as per the input provided in some of the
|
||||
* APIs.
|
||||
*
|
||||
* @param[in] period_us : The required wait time in microsecond.
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_delay_us(uint32_t period_us, const struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiSetGet
|
||||
* \page bmm350_api_bmm350_get_interrupt_status bmm350_get_interrupt_status
|
||||
* \code
|
||||
* int8_t bmm350_get_interrupt_status(uint8_t *drdy_status, struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API obtains the status flags of all interrupt
|
||||
* which is used to check for the assertion of interrupts
|
||||
*
|
||||
* @param[in,out] drdy_status : Variable to store data ready interrupt status.
|
||||
* @param[in,out] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
*
|
||||
* @return Result of API execution status and self test result.
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_get_interrupt_status(uint8_t *drdy_status, struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiSetGet
|
||||
* \page bmm350_api_bmm350_set_powermode bmm350_set_powermode
|
||||
* \code
|
||||
* int8_t bmm350_set_powermode(enum bmm350_power_modes powermode, struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API is used to set the power mode of the sensor
|
||||
*
|
||||
* @param[in] powermode : Set power mode
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
*@verbatim
|
||||
powermode | Power mode
|
||||
-------------------------|-----------------------
|
||||
| BMM350_SUSPEND_MODE
|
||||
| BMM350_NORMAL_MODE
|
||||
| BMM350_FORCED_MODE
|
||||
| BMM350_FORCED_MODE_FAST
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_set_powermode(enum bmm350_power_modes powermode, struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiSetGet
|
||||
* \page bmm350_api_bmm350_set_odr_performance bmm350_set_odr_performance
|
||||
* \code
|
||||
* int8_t bmm350_set_odr_performance(enum bmm350_data_rates odr,
|
||||
* enum bmm350_performance_parameters avg,
|
||||
* struct bmm350_dev *dev);
|
||||
*
|
||||
* \endcode
|
||||
* @details This API sets the ODR and averaging factor.
|
||||
* If ODR and performance is a combination which is not allowed, then
|
||||
* the combination setting is corrected to the next lower possible setting
|
||||
*
|
||||
* @param[in] odr : enum bmm350_data_rates
|
||||
*
|
||||
*@verbatim
|
||||
Data rate (ODR) | odr
|
||||
-------------------------|-----------------------
|
||||
400Hz | BMM350_DATA_RATE_400HZ
|
||||
200Hz | BMM350_DATA_RATE_200HZ
|
||||
100Hz | BMM350_DATA_RATE_100HZ
|
||||
50Hz | BMM350_DATA_RATE_50HZ
|
||||
25Hz | BMM350_DATA_RATE_25HZ
|
||||
12.5Hz | BMM350_DATA_RATE_12_5HZ
|
||||
6.25Hz | BMM350_DATA_RATE_6_25HZ
|
||||
3.125Hz | BMM350_DATA_RATE_3_125HZ
|
||||
1.5625Hz | BMM350_DATA_RATE_1_5625HZ
|
||||
*@endverbatim
|
||||
*
|
||||
* @param[in] avg : enum bmm350_performance_parameters
|
||||
*
|
||||
*@verbatim
|
||||
avg | averaging factor alias
|
||||
---------------------------|------------------------------------------
|
||||
low power/highest noise | BMM350_NO_AVERAGING BMM350_LOWPOWER
|
||||
lesser noise | BMM350_AVERAGING_2 BMM350_REGULARPOWER
|
||||
even lesser noise | BMM350_AVERAGING_4 BMM350_LOWNOISE
|
||||
lowest noise/highest power | BMM350_AVERAGING_8 BMM350_ULTRALOWNOISE
|
||||
*@endverbatim
|
||||
*
|
||||
* @param[in,out] dev : Structure instance of bmm350_dev
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_set_odr_performance(enum bmm350_data_rates odr,
|
||||
enum bmm350_performance_parameters avg,
|
||||
struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiSetGet
|
||||
* \page bmm350_api_bmm350_enable_axes bmm350_enable_axes
|
||||
* \code
|
||||
* int8_t bmm350_enable_axes(enum bmm350_x_axis_en_dis en_x, enum bmm350_y_axis_en_dis en_y, enum bmm350_z_axis_en_dis en_z, struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API is used to enable or disable the magnetic
|
||||
* measurement of x,y,z axes
|
||||
*
|
||||
* @param[in] en_x : Enable or disable X axis
|
||||
* @param[in] en_y : Enable or disable Y axis
|
||||
* @param[in] en_z : Enable or disable Z axis
|
||||
* @param[in,out] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
*@verbatim
|
||||
Value | Axis (en_x, en_y, en_z)
|
||||
-------------------|-----------------------
|
||||
BMM350_ENABLE | Enabled
|
||||
BMM350_DISABLE | Disabled
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_enable_axes(enum bmm350_x_axis_en_dis en_x,
|
||||
enum bmm350_y_axis_en_dis en_y,
|
||||
enum bmm350_z_axis_en_dis en_z,
|
||||
struct bmm350_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmm350
|
||||
* \defgroup bmm350ApiRead Sensortime
|
||||
* @brief Reads sensortime
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiRead
|
||||
* \page bmm350_api_bmm350_read_sensortime bmm350_read_sensortime
|
||||
* \code
|
||||
* int8_t bmm350_read_sensortime(uint32_t *seconds, uint32_t *nanoseconds, struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API is used to read the sensor time.
|
||||
* It converts the sensor time register values to the representative time value.
|
||||
* Returns the sensor time in ticks.
|
||||
*
|
||||
* @param[out] seconds : Variable to get sensor time in seconds.
|
||||
* @param[out] nanoseconds : Variable to get sensor time in nanoseconds.
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_read_sensortime(uint32_t *seconds, uint32_t *nanoseconds, struct bmm350_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmm350
|
||||
* \defgroup bmm350ApiInterrupt Enable Interrupt
|
||||
* @brief Interrupt enable APIs
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiInterrupt
|
||||
* \page bmm350_api_bmm350_enable_interrupt bmm350_enable_interrupt
|
||||
* \code
|
||||
* int8_t bmm350_enable_interrupt(enum bmm350_interrupt_enable_disable enable_disable, struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API is used to enable or disable the data ready interrupt
|
||||
*
|
||||
* @param[in] enable_disable : Enable/ Disable data ready interrupt.
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_enable_interrupt(enum bmm350_interrupt_enable_disable enable_disable, struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiInterrupt
|
||||
* \page bmm350_api_bmm350_configure_interrupt bmm350_configure_interrupt
|
||||
* \code
|
||||
* int8_t bmm350_configure_interrupt(enum bmm350_intr_latch latching,
|
||||
* enum bmm350_intr_polarity polarity,
|
||||
* enum bmm350_intr_drive drivertype,
|
||||
* enum bmm350_intr_map map_nomap,
|
||||
* struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API is used to configure the interrupt control settings.
|
||||
*
|
||||
* @param[in] latching : Sets either latched or pulsed.
|
||||
* @param[in] polarity : Sets either polarity high or low.
|
||||
* @param[in] drivertype : Sets either open drain or push pull.
|
||||
* @param[in] map_nomap : Sets either map or unmap the pins.
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_configure_interrupt(enum bmm350_intr_latch latching,
|
||||
enum bmm350_intr_polarity polarity,
|
||||
enum bmm350_intr_drive drivertype,
|
||||
enum bmm350_intr_map map_nomap,
|
||||
struct bmm350_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmm350
|
||||
* \defgroup bmm350ApiUncompMag Uncompensated mag
|
||||
* @brief Reads uncompensated mag and temperature data
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiUncompMag
|
||||
* \page bmm350_api_bmm350_read_uncomp_mag_temp_data bmm350_read_uncomp_mag_temp_data
|
||||
* \code
|
||||
* int8_t bmm350_read_uncomp_mag_temp_data(struct bmm350_raw_mag_data *raw_data, struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API is used to read uncompensated mag and temperature data
|
||||
*
|
||||
* @param[in, out] raw_data : Structure instance of bmm350_raw_mag_data.
|
||||
* @param[in, out] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_read_uncomp_mag_temp_data(struct bmm350_raw_mag_data *raw_data, struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiSetGet
|
||||
* \page bmm350_api_bmm350_set_int_ctrl_ibi bmm350_set_int_ctrl_ibi
|
||||
* \code
|
||||
* int8_t bmm350_set_int_ctrl_ibi(enum bmm350_drdy_int_map_to_ibi en_dis,
|
||||
* enum bmm350_clear_drdy_int_status_upon_ibi clear_on_ibi, struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API sets the interrupt control IBI configurations to the sensor.
|
||||
* And enables conventional interrupt if IBI is enabled.
|
||||
*
|
||||
* @param[in] en_dis : Sets either enable or disable IBI.
|
||||
* @param[in] clear_on_ibi : sets either clear or no clear on IBI.
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_set_int_ctrl_ibi(enum bmm350_drdy_int_map_to_ibi en_dis,
|
||||
enum bmm350_clear_drdy_int_status_upon_ibi clear_on_ibi,
|
||||
struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiSetGet
|
||||
* \page bmm350_api_bmm350_set_pad_drive bmm350_set_pad_drive
|
||||
* \code
|
||||
* int8_t bmm350_set_pad_drive(uint8_t drive, struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API is used to set the pad drive strength
|
||||
*
|
||||
* @param[in] drive : Drive settings, range 0 (weak) ..7(strong)
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_set_pad_drive(uint8_t drive, struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiReset
|
||||
* \page bmm350_api_bmm350_magnetic_reset_and_wait bmm350_magnetic_reset_and_wait
|
||||
* \code
|
||||
* int8_t bmm350_magnetic_reset_and_wait(struct bmm350_dev *dev)
|
||||
* \endcode
|
||||
* @details This API is used to perform the magnetic reset of the sensor
|
||||
* which is necessary after a field shock (400mT field applied to sensor).
|
||||
* It sends flux guide or bit reset to the device in suspend mode.
|
||||
*
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_magnetic_reset_and_wait(struct bmm350_dev *dev);
|
||||
|
||||
#ifdef BMM350_USE_FIXED_POINT
|
||||
|
||||
/**
|
||||
* \ingroup bmm350ApiMagTemp
|
||||
* \page bmm350_api_bmm350_get_compensated_mag_xyz_temp_data_fixed bmm350_get_compensated_mag_xyz_temp_data_fixed
|
||||
* \code
|
||||
* int8_t bmm350_get_compensated_mag_xyz_temp_data_fixed(struct bmm350_mag_temp_data *mag_temp_data, struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API is used to read mag and temperature data in the units of uT and *C
|
||||
*
|
||||
* @param[in, out] mag_temp_data : Structure instance of bmm350_mag_temp_data.
|
||||
* @param[in, out] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_get_compensated_mag_xyz_temp_data_fixed(struct bmm350_mag_temp_data *mag_temp_data,
|
||||
struct bmm350_dev *dev);
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* \ingroup bmm350
|
||||
* \defgroup bmm350ApiMagComp Compensation
|
||||
* @brief Compensation for mag x,y,z axis and temperature API
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiMagComp
|
||||
* \page bmm350_api_bmm350_get_compensated_mag_xyz_temp_data bmm350_get_compensated_mag_xyz_temp_data
|
||||
* \code
|
||||
* int8_t bmm350_get_compensated_mag_xyz_temp_data(struct bmm350_mag_temp_data *mag_temp_data, struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API is used to perform compensation for raw magnetometer and temperature data.
|
||||
*
|
||||
* @param[out] mag_temp_data : Structure instance of bmm350_mag_temp_data.
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_get_compensated_mag_xyz_temp_data(struct bmm350_mag_temp_data *mag_temp_data, struct bmm350_dev *dev);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \ingroup bmm350
|
||||
* \defgroup bmm350ApiSelftest Self-test
|
||||
* @brief Perform self-test for x and y axis
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiSelftest
|
||||
* \page bmm350_api_bmm350_perform_self_test bmm350_perform_self_test
|
||||
* \code
|
||||
* int8_t bmm350_perform_self_test(struct bmm350_self_test *out_data, struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API executes FGR and BR sequences to initialize TMR sensor and performs self-test for x and y axis.
|
||||
*
|
||||
* @param[in, out] out_data : Structure instance of bmm350_self_test.
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_perform_self_test(struct bmm350_self_test *out_data, struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiSetGet
|
||||
* \page bmm350_api_bmm350_set_i2c_wdt bmm350_set_i2c_wdt
|
||||
* \code
|
||||
* int8_t bmm350_set_i2c_wdt(enum bmm350_i2c_wdt_en i2c_wdt_en_dis, enum bmm350_i2c_wdt_sel i2c_wdt_sel,
|
||||
* struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API sets the I2C watchdog timer configurations to the sensor.
|
||||
*
|
||||
* @param[in] i2c_wdt_en_dis : Enable/ Disable I2C watchdog timer.
|
||||
* @param[in] i2c_wdt_sel : I2C watchdog timer selection period.
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_set_i2c_wdt(enum bmm350_i2c_wdt_en i2c_wdt_en_dis,
|
||||
enum bmm350_i2c_wdt_sel i2c_wdt_sel,
|
||||
struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiSetGet
|
||||
* \page bmm350_api_bmm350_set_tmr_selftest_user bmm350_set_tmr_selftest_user
|
||||
* \code
|
||||
* int8_t bmm350_set_tmr_selftest_user(enum bmm350_st_igen_en st_igen_en_dis,
|
||||
* enum bmm350_st_n st_n_en_dis,
|
||||
* enum bmm350_st_p st_p_en_dis,
|
||||
* enum bmm350_ist_en_x ist_x_en_dis,
|
||||
* enum bmm350_ist_en_y ist_y_en_dis,
|
||||
* struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API sets the TMR user self-test register
|
||||
*
|
||||
* @param[in] st_igen_en_dis : Enable/ Disable self-test internal current gen.
|
||||
* @param[in] st_n_en_dis : Enable/ Disable dc_st_n signal.
|
||||
* @param[in] st_p_en_dis : Enable/ Disable dc_st_p signal.
|
||||
* @param[in] ist_x_en_dis : Enable/ Disable dc_ist_en_x signal.
|
||||
* @param[in] ist_y_en_dis : Enable/ Disable dc_ist_en_y signal.
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_set_tmr_selftest_user(enum bmm350_st_igen_en st_igen_en_dis,
|
||||
enum bmm350_st_n st_n_en_dis,
|
||||
enum bmm350_st_p st_p_en_dis,
|
||||
enum bmm350_ist_en_x ist_x_en_dis,
|
||||
enum bmm350_ist_en_y ist_y_en_dis,
|
||||
struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiSetGet
|
||||
* \page bmm350_api_bmm350_set_ctrl_user bmm350_set_ctrl_user
|
||||
* \code
|
||||
* int8_t bmm350_set_ctrl_user(enum bmm350_ctrl_user cfg_sens_tim_aon_en_dis, struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API sets the control user configurations to the sensor.
|
||||
*
|
||||
* @param[in] cfg_sens_tim_aon_en_dis : Enable/ Disable configuration of sensor time to run on suspend mode.
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_set_ctrl_user(enum bmm350_ctrl_user cfg_sens_tim_aon_en_dis, struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmm350ApiSetGet
|
||||
* \page bmm350_api_bmm350_get_pmu_cmd_status_0 bmm350_get_pmu_cmd_status_0
|
||||
* \code
|
||||
* int8_t bmm350_get_pmu_cmd_status_0(struct bmm350_pmu_cmd_status_0 *pmu_cmd_stat_0, struct bmm350_dev *dev);
|
||||
* \endcode
|
||||
* @details This API gets the PMU command status 0 value.
|
||||
*
|
||||
* @param[out] pmu_cmd_stat_0 : Structure instance of bmm350_pmu_cmd_status_0.
|
||||
* @param[in] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_get_pmu_cmd_status_0(struct bmm350_pmu_cmd_status_0 *pmu_cmd_stat_0, struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* @brief This internal API is used to compute the square root in fixed point.
|
||||
* @param[in] inp : input, whose square root needs to be computed
|
||||
*
|
||||
* @return square root of the input
|
||||
*/
|
||||
uint16_t bmm350_fixed_point_sqrt(uint32_t inp);
|
||||
|
||||
#ifdef BMM350_USE_FIXED_POINT
|
||||
fixed_t fixed_add(fixed_t a, fixed_t b);
|
||||
fixed_t fixed_sub(fixed_t a, fixed_t b);
|
||||
fixed_t fixed_mul_A48_16(fixed_t a, fixed_t b);
|
||||
fixed_t fixed_div(fixed_t a, fixed_t b);
|
||||
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* End of CPP guard */
|
||||
|
||||
#endif /* _BMM350_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,540 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Bosch Sensortec GmbH. All rights reserved.
|
||||
*
|
||||
* BSD-3-Clause
|
||||
*
|
||||
* 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 the copyright holder 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.
|
||||
*
|
||||
* @file bmm350_oor.c
|
||||
* @date 2025-10-30
|
||||
* @version v1.10.0
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bmm350.h"
|
||||
#include "bmm350_oor.h"
|
||||
|
||||
#ifndef BMM350_USE_FIXED_POINT
|
||||
#include "math.h"
|
||||
|
||||
#else
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#include "stdlib.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/********************** Static function declarations ************************/
|
||||
|
||||
/*!
|
||||
* @brief This internal API is used to execute delay operation for the reset functions.
|
||||
*/
|
||||
static int8_t execute_delay_in_steps(uint32_t delay, uint32_t delay_step, const struct bmm350_dev *dev);
|
||||
|
||||
#ifdef BMM350_OOR_HALF_SELF_TEST
|
||||
|
||||
/*!
|
||||
* @brief This internal API is used to trigger half self-test
|
||||
* @param[out] oor : Structure that stores the state of the out of range detector
|
||||
* @param[in,out] dev : Device structure of the BMM350
|
||||
*/
|
||||
static int8_t trigger_half_selftest(const struct bmm350_oor_reset_delay *rdelay,
|
||||
struct bmm350_oor_params *oor,
|
||||
struct bmm350_dev *dev)
|
||||
{
|
||||
int8_t rslt = BMM350_OK;
|
||||
|
||||
uint8_t pmu_cmd = BMM350_PMU_CMD_BR;
|
||||
|
||||
oor->st_cmd = BMM350_SELF_TEST_DISABLE;
|
||||
|
||||
/* Trigger a self-test on every alternate measurement if needed */
|
||||
if (oor->enable_selftest)
|
||||
{
|
||||
oor->st_counter++;
|
||||
|
||||
switch (oor->st_counter)
|
||||
{
|
||||
case 1:
|
||||
oor->st_cmd = BMM350_SELF_TEST_POS_X;
|
||||
break;
|
||||
case 2:
|
||||
oor->st_cmd = BMM350_SELF_TEST_DISABLE;
|
||||
break;
|
||||
case 3:
|
||||
oor->st_cmd = BMM350_SELF_TEST_POS_Y;
|
||||
break;
|
||||
case 4:
|
||||
oor->st_cmd = BMM350_SELF_TEST_DISABLE;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
if (dev->enable_auto_br == BMM350_DISABLE)
|
||||
{
|
||||
/* Trigger the Bit Reset */
|
||||
pmu_cmd = BMM350_PMU_CMD_BR;
|
||||
rslt = bmm350_set_regs(BMM350_REG_PMU_CMD, &pmu_cmd, 1, dev);
|
||||
if (rslt == BMM350_OK)
|
||||
{
|
||||
/* Bit Reset delay*/
|
||||
(void)execute_delay_in_steps(rdelay->br_delay, rdelay->delay_step, dev);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
oor->st_counter = 0;
|
||||
oor->st_cmd = BMM350_SELF_TEST_DISABLE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
oor->st_counter = 0;
|
||||
oor->st_cmd = BMM350_SELF_TEST_DISABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
rslt = bmm350_set_regs(BMM350_REG_TMR_SELFTEST_USER, &(oor->st_cmd), 1, dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oor->last_st_cmd != BMM350_SELF_TEST_DISABLE)
|
||||
{
|
||||
rslt = bmm350_set_regs(BMM350_REG_TMR_SELFTEST_USER, &(oor->st_cmd), 1, dev);
|
||||
oor->st_counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief This internal API is used to validate half self-test
|
||||
* @param[out] data : Sensor data
|
||||
* @param[out] oor : Structure that stores the state of the out of range detector
|
||||
*/
|
||||
static void validate_half_selftest(const struct bmm350_mag_temp_data *data, struct bmm350_oor_params *oor)
|
||||
{
|
||||
switch (oor->last_st_cmd)
|
||||
{
|
||||
case BMM350_SELF_TEST_DISABLE:
|
||||
oor->mag_x_st_dis = data->x;
|
||||
oor->mag_y_st_dis = data->y;
|
||||
break;
|
||||
|
||||
case BMM350_SELF_TEST_POS_X:
|
||||
oor->mag_x_st_en = data->x;
|
||||
oor->x_failed = (oor->mag_x_st_en - oor->mag_x_st_dis) < BMM350_HALF_ST_THRESHOLD ? true : false;
|
||||
break;
|
||||
|
||||
case BMM350_SELF_TEST_POS_Y:
|
||||
oor->mag_y_st_en = data->y;
|
||||
oor->y_failed = (oor->mag_y_st_en - oor->mag_y_st_dis) < BMM350_HALF_ST_THRESHOLD ? true : false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
/*!
|
||||
* @brief This internal API is used to trigger self-test
|
||||
* @param[in] rdelay : Structure that stores the delay settings for the various magnetic reset sequences
|
||||
* @param[out] oor : Structure that stores the state of the out of range detector
|
||||
* @param[in,out] dev : Device structure of the BMM350
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
static int8_t trigger_selftest(const struct bmm350_oor_reset_delay *rdelay,
|
||||
struct bmm350_oor_params *oor,
|
||||
struct bmm350_dev *dev)
|
||||
{
|
||||
int8_t rslt = BMM350_OK;
|
||||
uint8_t pmu_cmd = BMM350_PMU_CMD_BR;
|
||||
|
||||
oor->st_cmd = BMM350_SELF_TEST_DISABLE;
|
||||
|
||||
/* Trigger a self-test on every alternate measurement if needed */
|
||||
if (oor->enable_selftest)
|
||||
{
|
||||
oor->st_counter++;
|
||||
|
||||
switch (oor->st_counter)
|
||||
{
|
||||
case 1:
|
||||
oor->st_cmd = BMM350_SELF_TEST_POS_X;
|
||||
break;
|
||||
case 2:
|
||||
oor->st_cmd = BMM350_SELF_TEST_NEG_X;
|
||||
break;
|
||||
case 3:
|
||||
oor->st_cmd = BMM350_SELF_TEST_POS_Y;
|
||||
break;
|
||||
case 4:
|
||||
oor->st_cmd = BMM350_SELF_TEST_NEG_Y;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
if (dev->enable_auto_br == BMM350_DISABLE)
|
||||
{
|
||||
/* Trigger the Bit Reset */
|
||||
pmu_cmd = BMM350_PMU_CMD_BR;
|
||||
rslt = bmm350_set_regs(BMM350_REG_PMU_CMD, &pmu_cmd, 1, dev);
|
||||
if (rslt == BMM350_OK)
|
||||
{
|
||||
/* Bit Reset delay*/
|
||||
(void)execute_delay_in_steps(rdelay->br_delay, rdelay->delay_step, dev);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
oor->st_counter = 0;
|
||||
oor->st_cmd = BMM350_SELF_TEST_DISABLE;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
oor->st_counter = 0;
|
||||
oor->st_cmd = BMM350_SELF_TEST_DISABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
rslt = bmm350_set_regs(BMM350_REG_TMR_SELFTEST_USER, &(oor->st_cmd), 1, dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oor->last_st_cmd != BMM350_SELF_TEST_DISABLE)
|
||||
{
|
||||
rslt = bmm350_set_regs(BMM350_REG_TMR_SELFTEST_USER, &(oor->st_cmd), 1, dev);
|
||||
oor->st_counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief This internal API is used to validate self-test during the self-test window
|
||||
* @param[in] data : Sensor data
|
||||
* @param[out] oor : Structure that stores the state of the out of range detector
|
||||
*/
|
||||
static void validate_selftest_window(const struct bmm350_mag_temp_data *data, struct bmm350_oor_params *oor)
|
||||
{
|
||||
switch (oor->last_st_cmd)
|
||||
{
|
||||
case BMM350_SELF_TEST_POS_X:
|
||||
oor->mag_x_st_en = data->x;
|
||||
break;
|
||||
|
||||
case BMM350_SELF_TEST_NEG_X:
|
||||
oor->mag_x_st_dis = data->x;
|
||||
oor->x_failed = (oor->mag_x_st_en - oor->mag_x_st_dis) < BMM350_FULL_ST_THRESHOLD ? true : false;
|
||||
break;
|
||||
|
||||
case BMM350_SELF_TEST_POS_Y:
|
||||
oor->mag_y_st_en = data->y;
|
||||
break;
|
||||
|
||||
case BMM350_SELF_TEST_NEG_Y:
|
||||
oor->mag_y_st_dis = data->y;
|
||||
oor->y_failed = (oor->mag_y_st_en - oor->mag_y_st_dis) < BMM350_FULL_ST_THRESHOLD ? true : false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/********************** Global function definitions ************************/
|
||||
|
||||
/*!
|
||||
* @brief This internal API is used to validate out of range.
|
||||
* @param[in] data : Sensor data
|
||||
* @param[out] oor : Structure that stores the state of the out of range detector
|
||||
*/
|
||||
void bmm350_oor_validate_out_of_range(const struct bmm350_mag_temp_data *data, struct bmm350_oor_params *oor)
|
||||
{
|
||||
#ifdef BMM350_USE_FIXED_POINT
|
||||
|
||||
/* Threshold to start out of range detection */
|
||||
fixed_t threshold = BMM350_OUT_OF_RANGE_THRESHOLD;
|
||||
|
||||
/* Threshold to start self-tests */
|
||||
fixed_t st_threshold = BMM350_SELF_TEST_THRESHOLD;
|
||||
|
||||
/* Variable to compute the magnitude square */
|
||||
fixed_t magnitude_square = 0;
|
||||
#else
|
||||
|
||||
/* Threshold to start out of range detection */
|
||||
float threshold = BMM350_OUT_OF_RANGE_THRESHOLD;
|
||||
|
||||
/* Threshold to start self-tests */
|
||||
float st_threshold = BMM350_SELF_TEST_THRESHOLD;
|
||||
#endif
|
||||
|
||||
#ifdef BMM350_USE_FIXED_POINT
|
||||
|
||||
/* Compute the Field Strength */
|
||||
magnitude_square =
|
||||
(uint32_t)((fixed_mul_A48_16(data->x,
|
||||
data->x) +
|
||||
fixed_mul_A48_16(data->y, data->y) + fixed_mul_A48_16(data->z, data->z)) >> F16_FRAC_BITS);
|
||||
oor->field_strength = (uint32_t)bmm350_fixed_point_sqrt(magnitude_square);
|
||||
#else
|
||||
|
||||
/* Compute the Field Strength */
|
||||
oor->field_strength = sqrtf((data->x * data->x) + (data->y * data->y) + (data->z * data->z));
|
||||
#endif
|
||||
|
||||
/* If either self-test failed, alert that the sensor is out of range and continue self-tests */
|
||||
if (oor->x_failed || oor->y_failed)
|
||||
{
|
||||
oor->out_of_range = true;
|
||||
oor->enable_selftest = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Check for the self-test threshold and perform self-tests to catch if the sensor is out of range */
|
||||
#ifdef BMM350_USE_FIXED_POINT
|
||||
if ((abs(data->x) >= st_threshold) || (abs(data->y) >= st_threshold) || (abs(data->z) >= st_threshold) ||
|
||||
(oor->field_strength >= (uint32_t)(st_threshold >> F16_FRAC_BITS)))
|
||||
#else
|
||||
if ((fabsf(data->x) >= st_threshold) || (fabsf(data->y) >= st_threshold) || (fabsf(data->z) >= st_threshold) ||
|
||||
(oor->field_strength >= st_threshold))
|
||||
#endif
|
||||
{
|
||||
oor->enable_selftest = true;
|
||||
}
|
||||
else if (oor->st_counter == 0) /* If a self-test procedure has started, wait for it to complete */
|
||||
{
|
||||
oor->enable_selftest = false;
|
||||
}
|
||||
|
||||
/* If out of range was previously detected, reduce the threshold to get back in range,
|
||||
* effectively preventing hysteresis. Selecting 400uT */
|
||||
if (oor->out_of_range)
|
||||
{
|
||||
threshold = BMM350_IN_RANGE_THRESHOLD;
|
||||
}
|
||||
|
||||
/* Check if X or Y or Z > the threshold or the magnitude of all 3 is greater */
|
||||
#ifdef BMM350_USE_FIXED_POINT
|
||||
if ((abs(data->x) >= threshold) || (abs(data->y) >= threshold) || (abs(data->z) >= threshold) ||
|
||||
(oor->field_strength >= (uint32_t)(threshold >> F16_FRAC_BITS)))
|
||||
#else
|
||||
if ((fabsf(data->x) >= threshold) || (fabsf(data->y) >= threshold) || (fabsf(data->z) >= threshold) ||
|
||||
(oor->field_strength >= threshold))
|
||||
#endif
|
||||
{
|
||||
oor->out_of_range = true;
|
||||
}
|
||||
else if (oor->st_counter == 0) /* If a self-test procedure has started, wait for it to complete */
|
||||
{
|
||||
if (oor->out_of_range)
|
||||
{
|
||||
oor->trigger_reset = true;
|
||||
}
|
||||
|
||||
oor->out_of_range = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief This API is used to perform magnetic reset sequence.
|
||||
* @param[in] rdelay : Structure that stores the delay settings for the various magnetic reset sequences
|
||||
* @param[out] oor : Structure that stores the state of the out of range detector
|
||||
* @param[in,out] dev : Device structure of the BMM350
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_oor_perform_reset_sequence(const struct bmm350_oor_reset_delay *rdelay,
|
||||
struct bmm350_oor_params *oor,
|
||||
struct bmm350_dev *dev)
|
||||
{
|
||||
int8_t rslt = 0;
|
||||
uint8_t pmu_cmd = 0;
|
||||
|
||||
oor->reset_counter++;
|
||||
|
||||
switch (oor->reset_counter)
|
||||
{
|
||||
case 1: /* Trigger the Bit reset fast */
|
||||
pmu_cmd = BMM350_PMU_CMD_BR_FAST;
|
||||
rslt = bmm350_set_regs(BMM350_REG_PMU_CMD, &pmu_cmd, 1, dev);
|
||||
if (rslt == BMM350_OK)
|
||||
{
|
||||
/* Bit Reset Window synchronization delay*/
|
||||
(void)execute_delay_in_steps(rdelay->br_delay, rdelay->delay_step, dev);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 2: /* Trigger Flux Guide reset */
|
||||
pmu_cmd = BMM350_PMU_CMD_FGR;
|
||||
rslt = bmm350_set_regs(BMM350_REG_PMU_CMD, &pmu_cmd, 1, dev);
|
||||
if (rslt == BMM350_OK)
|
||||
{
|
||||
/* Flux Guide Reset Window synchronization delay*/
|
||||
(void)execute_delay_in_steps(rdelay->fgr_delay, rdelay->delay_step, dev);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 3: /* Flux Guide dummy */
|
||||
break;
|
||||
|
||||
default: /* Default acts like the Flux guide reset dummy */
|
||||
oor->reset_counter = 0;
|
||||
oor->trigger_reset = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief This API is used to read out of range in during self-test.
|
||||
* @param[in] rdelay : Structure that stores the delay settings for the various magnetic reset sequences
|
||||
* @param[out] data : Sensor data
|
||||
* @param[out] oor : Structure that stores the state of the out of range detector
|
||||
* @param[in,out] dev : Device structure of the BMM350
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_oor_read(const struct bmm350_oor_reset_delay *rdelay,
|
||||
struct bmm350_mag_temp_data *data,
|
||||
struct bmm350_oor_params *oor,
|
||||
struct bmm350_dev *dev)
|
||||
{
|
||||
int8_t rslt = 0;
|
||||
uint8_t pmu_cmd = BMM350_PMU_CMD_SUS;
|
||||
|
||||
#ifdef BMM350_OOR_HALF_SELF_TEST
|
||||
rslt = trigger_half_selftest(rdelay, oor, dev);
|
||||
#else
|
||||
rslt = trigger_selftest(rdelay, oor, dev);
|
||||
#endif
|
||||
|
||||
if (rslt == BMM350_OK)
|
||||
{
|
||||
pmu_cmd = BMM350_PMU_CMD_FM_FAST;
|
||||
rslt = bmm350_set_regs(BMM350_REG_PMU_CMD, &pmu_cmd, 1, dev);
|
||||
|
||||
if (rslt == BMM350_OK)
|
||||
{
|
||||
#ifdef BMM350_USE_FIXED_POINT
|
||||
rslt = bmm350_get_compensated_mag_xyz_temp_data_fixed(data, dev);
|
||||
#else
|
||||
rslt = bmm350_get_compensated_mag_xyz_temp_data(data, dev);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BMM350_OOR_HALF_SELF_TEST
|
||||
validate_half_selftest(data, oor);
|
||||
#else
|
||||
validate_selftest_window(data, oor);
|
||||
#endif
|
||||
|
||||
bmm350_oor_validate_out_of_range(data, oor);
|
||||
|
||||
oor->last_st_cmd = oor->st_cmd;
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief This API is used to computing the reset delay settings for Magnetic Reset Sequence.
|
||||
* @param[in] odr_config : ODR Configuration
|
||||
* @param[out] rdelay : Structure that stores the delay settings for the various magnetic reset sequences
|
||||
*/
|
||||
void bmm350_oor_compute_delay_setting(uint8_t odr_config, struct bmm350_oor_reset_delay *rdelay)
|
||||
{
|
||||
uint16_t min_dealy_unit = 2500; /* corresponds to 400Hz -> (1/400) * (10^6) us */
|
||||
|
||||
#ifdef BMM350_USE_FIXED_POINT
|
||||
uint32_t power_scale = ((uint32_t)1 << (odr_config - BMM350_ODR_400HZ));
|
||||
rdelay->delay_step = (uint32_t)(min_dealy_unit * power_scale);
|
||||
#else
|
||||
rdelay->delay_step = (uint32_t)(min_dealy_unit * (pow(2.0, (double)(odr_config - BMM350_ODR_400HZ))));
|
||||
#endif
|
||||
|
||||
rdelay->br_delay = ((rdelay->delay_step * 3) - 1000);
|
||||
rdelay->fgr_delay = ((rdelay->delay_step * 4) - 2000);
|
||||
}
|
||||
|
||||
/********************** Static function definitions ************************/
|
||||
|
||||
/*!
|
||||
* @brief This internal API is used to execute delay operation for the reset functions.
|
||||
* @param[in] delay : ODR Window Delay
|
||||
* @param[in] delay_step : Delay Time Resolution
|
||||
* @param[in,out] dev : Device structure of the BMM350
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
static int8_t execute_delay_in_steps(uint32_t delay, uint32_t delay_step, const struct bmm350_dev *dev)
|
||||
{
|
||||
int8_t rslt = BMM350_OK;
|
||||
|
||||
if ((delay > 0) && (delay_step > 0) && (delay >= delay_step))
|
||||
{
|
||||
while (delay >= delay_step)
|
||||
{
|
||||
rslt = bmm350_delay_us(delay_step, dev);
|
||||
if (rslt == BMM350_OK)
|
||||
{
|
||||
delay = delay - delay_step;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rslt = BMM350_E_INVALID_INPUT;
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Bosch Sensortec GmbH. All rights reserved.
|
||||
*
|
||||
* BSD-3-Clause
|
||||
*
|
||||
* 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 the copyright holder 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.
|
||||
*
|
||||
* @file bmm350_oor.h
|
||||
* @date 2025-10-30
|
||||
* @version v1.10.0
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _BMM350_OOR_H
|
||||
#define _BMM350_OOR_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#ifdef BMM350_USE_FIXED_POINT
|
||||
#include <math.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "bmm350.h"
|
||||
|
||||
/*! CPP guard */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/*! @name General Macro Definitions */
|
||||
/******************************************************************************/
|
||||
|
||||
/*! Macro to define half self-test for out of range
|
||||
* NOTE: Comment this to use generic self test */
|
||||
|
||||
/*#define BMM350_OOR_HALF_SELF_TEST */
|
||||
|
||||
/*! Macro to synchronize the reset window with the measurement window */
|
||||
#define BMM350_OOR_WINDOW_SYNC_DELAY UINT16_C(9000)
|
||||
|
||||
/*! Macro to define mag data minimum and maximum range in uT */
|
||||
#ifdef BMM350_USE_FIXED_POINT
|
||||
#define BMM350_HALF_ST_THRESHOLD (130 << F16_FRAC_BITS)
|
||||
#define BMM350_FULL_ST_THRESHOLD (300 << F16_FRAC_BITS)
|
||||
#else
|
||||
#define BMM350_HALF_ST_THRESHOLD (130.0f)
|
||||
#define BMM350_FULL_ST_THRESHOLD (300.0f)
|
||||
#endif
|
||||
|
||||
/*! Macro to define threshold values of in range, out of range and self-test */
|
||||
#ifdef BMM350_USE_FIXED_POINT
|
||||
#define BMM350_IN_RANGE_THRESHOLD (2000 << F16_FRAC_BITS)
|
||||
#define BMM350_OUT_OF_RANGE_THRESHOLD (2400 << F16_FRAC_BITS)
|
||||
#define BMM350_SELF_TEST_THRESHOLD (2600 << F16_FRAC_BITS)
|
||||
#else
|
||||
#define BMM350_IN_RANGE_THRESHOLD (2000.0f)
|
||||
#define BMM350_OUT_OF_RANGE_THRESHOLD (2400.0f)
|
||||
#define BMM350_SELF_TEST_THRESHOLD (2600.0f)
|
||||
#endif
|
||||
|
||||
/************************* Structure definitions *************************/
|
||||
|
||||
/*!
|
||||
* @brief Structure to define bmm350 out of range parameters
|
||||
*/
|
||||
struct bmm350_oor_params
|
||||
{
|
||||
/*! Field Strength */
|
||||
#ifdef BMM350_USE_FIXED_POINT
|
||||
uint32_t field_strength;
|
||||
#else
|
||||
float field_strength;
|
||||
#endif
|
||||
|
||||
/*! Flags to enable Out of Range */
|
||||
bool out_of_range;
|
||||
|
||||
/*! Counter to track what self test to trigger */
|
||||
uint8_t st_counter;
|
||||
|
||||
/*! Current self-test command */
|
||||
uint8_t st_cmd;
|
||||
|
||||
/*! Stores the last applied self test configuration */
|
||||
uint8_t last_st_cmd;
|
||||
|
||||
/*! Self test enabled/disabled measurements for X and Y */
|
||||
#ifdef BMM350_USE_FIXED_POINT
|
||||
fixed_t mag_x_st_en, mag_x_st_dis, mag_y_st_en, mag_y_st_dis, mag_x_st_dis_avg, mag_y_st_dis_avg;
|
||||
#else
|
||||
float mag_x_st_en, mag_x_st_dis, mag_y_st_en, mag_y_st_dis, mag_x_st_dis_avg, mag_y_st_dis_avg;
|
||||
#endif
|
||||
|
||||
/*! Flags to track if the test failed to redo it */
|
||||
bool x_failed, y_failed;
|
||||
|
||||
/*! Flags to enable self-test */
|
||||
bool enable_selftest;
|
||||
|
||||
/*! Flags to trigger reset */
|
||||
bool trigger_reset;
|
||||
|
||||
/*! Variable to store reset counter value */
|
||||
uint8_t reset_counter;
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Structure to define bmm350 out of range reset delay parameters
|
||||
*/
|
||||
struct bmm350_oor_reset_delay
|
||||
{
|
||||
uint32_t delay_step;
|
||||
uint32_t br_delay;
|
||||
uint32_t fgr_delay;
|
||||
};
|
||||
|
||||
/******************* Function prototype declarations ********************/
|
||||
|
||||
/*!
|
||||
* @brief Function to read data and validate if the sensor is out of range
|
||||
*
|
||||
* @param[in] rdelay : Structure that stores the delay settings for the various magnetic reset sequences
|
||||
* @param[out] data : Sensor data
|
||||
* @param[out] oor : Structure that stores the state of the out of range detector
|
||||
* @param[in,out] dev : Device structure of the BMM350
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_oor_read(const struct bmm350_oor_reset_delay *rdelay,
|
||||
struct bmm350_mag_temp_data *data,
|
||||
struct bmm350_oor_params *oor,
|
||||
struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* @brief Function to perform reset sequence in forced mode.
|
||||
*
|
||||
* @param[in] rdelay : Structure that stores the delay settings for the various magnetic reset sequences
|
||||
* @param[in,out] oor : Structure that stores the state of the out of range detector
|
||||
* @param[in,out] dev : Structure instance of bmm350_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval = 0 -> Success
|
||||
* @retval < 0 -> Error
|
||||
*/
|
||||
int8_t bmm350_oor_perform_reset_sequence(const struct bmm350_oor_reset_delay *rdelay,
|
||||
struct bmm350_oor_params *oor,
|
||||
struct bmm350_dev *dev);
|
||||
|
||||
/*!
|
||||
* @brief Function to compute the delay settings for the magnetic reset sequence.
|
||||
*
|
||||
* @param[in] odr_config : Configured Output Data Rate
|
||||
* @param[in] rdelay : Structure that stores the delay settings for the various magnetic reset sequences
|
||||
* @param[in,out] dev : Structure instance of bmm350_dev.
|
||||
*/
|
||||
void bmm350_oor_compute_delay_setting(uint8_t odr_config, struct bmm350_oor_reset_delay *rdelay);
|
||||
|
||||
/*!
|
||||
* @brief Function to check for the Out of Range condition.
|
||||
*
|
||||
* @param[out] data : Sensor data
|
||||
* @param[in,out] oor : Structure that stores the state of the out of range detector
|
||||
*/
|
||||
void bmm350_oor_validate_out_of_range(const struct bmm350_mag_temp_data *data, struct bmm350_oor_params *oor);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* End of CPP guard */
|
||||
|
||||
#endif /* _BMM350_OOR_H */
|
||||
@@ -0,0 +1,322 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file freertos_port.c
|
||||
* @author MCD Application Team
|
||||
* @brief Custom porting of FreeRTOS functionalities
|
||||
******************************************************************************
|
||||
* @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 "app_common.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "stm32_lpm.h"
|
||||
#include <limits.h>
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t LpTimeLeftOnEntry;
|
||||
uint8_t LpTimerFreeRTOS_Id;
|
||||
} LpTimerContext_t;
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#ifndef configSYSTICK_CLOCK_HZ
|
||||
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||
#else
|
||||
/* The way the SysTick is clocked is not modified in case it is not the same
|
||||
as the core. */
|
||||
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||
#endif
|
||||
|
||||
#define CPU_CLOCK_KHZ ( configCPU_CLOCK_HZ / 1000 )
|
||||
|
||||
/* Constants required to manipulate the core. Registers first... */
|
||||
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/*
|
||||
* The number of SysTick increments that make up one tick period.
|
||||
*/
|
||||
#if ( CFG_LPM_SUPPORTED != 0)
|
||||
static uint32_t ulTimerCountsForOneTick;
|
||||
|
||||
static LpTimerContext_t LpTimerContext;
|
||||
#endif
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
#if ( CFG_LPM_SUPPORTED != 0)
|
||||
static void LpTimerInit( void );
|
||||
static void LpTimerCb( void );
|
||||
static void LpTimerStart( uint32_t time_to_sleep );
|
||||
static void LpEnter( void );
|
||||
static uint32_t LpGetElapsedTime( void );
|
||||
void vPortSetupTimerInterrupt( void );
|
||||
#endif
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Implement the tickless feature
|
||||
*
|
||||
*
|
||||
* @param: xExpectedIdleTime is given in number of FreeRTOS Ticks
|
||||
* @retval: None
|
||||
*/
|
||||
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||
{
|
||||
/* If low power is not used, do not stop the SysTick and continue execution */
|
||||
#if ( CFG_LPM_SUPPORTED != 0)
|
||||
/**
|
||||
* Although this is not documented as such, when xExpectedIdleTime = 0xFFFFFFFF = (~0),
|
||||
* it likely means the system may enter low power for ever ( from a FreeRTOS point of view ).
|
||||
* Otherwise, for a FreeRTOS tick set to 1ms, that would mean it is requested to wakeup in 8 years from now.
|
||||
* When the system may enter low power mode for ever, FreeRTOS is not really interested to maintain a
|
||||
* systick count and when the system exits from low power mode, there is no need to update the count with
|
||||
* the time spent in low power mode
|
||||
*/
|
||||
uint32_t ulCompleteTickPeriods;
|
||||
|
||||
/* Stop the SysTick to avoid the interrupt to occur while in the critical section.
|
||||
* Otherwise, this will prevent the device to enter low power mode
|
||||
* At this time, an update of the systick will not be considered
|
||||
*
|
||||
*/
|
||||
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||
method as that will mask interrupts that should exit sleep mode. */
|
||||
__disable_irq();
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
/* If a context switch is pending or a task is waiting for the scheduler
|
||||
to be unsuspended then abandon the low power entry. */
|
||||
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||
{
|
||||
/* Restart SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Re-enable interrupts - see comments above __disable_interrupt()
|
||||
call above. */
|
||||
__enable_irq();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (xExpectedIdleTime != (~0))
|
||||
{
|
||||
/* Remove one tick to wake up before the event occurs */
|
||||
xExpectedIdleTime--;
|
||||
/* Start the low power timer */
|
||||
LpTimerStart( xExpectedIdleTime );
|
||||
}
|
||||
|
||||
/* Enter low power mode */
|
||||
LpEnter( );
|
||||
|
||||
if (xExpectedIdleTime != (~0))
|
||||
{
|
||||
/**
|
||||
* Get the number of FreeRTOS ticks that has been suppressed
|
||||
* In the current implementation, this shall be kept in critical section
|
||||
* so that the timer server return the correct elapsed time
|
||||
*/
|
||||
ulCompleteTickPeriods = LpGetElapsedTime( );
|
||||
vTaskStepTick( ulCompleteTickPeriods );
|
||||
}
|
||||
|
||||
/* Restart SysTick */
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||
|
||||
/* Exit with interrUpts enabled. */
|
||||
__enable_irq();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the systick timer to generate the tick interrupts at the required
|
||||
* frequency and initialize a low power timer
|
||||
* The current implementation is kept as close as possible to the default tickless
|
||||
* mode provided.
|
||||
* The systick is still used when there is no need to go in low power mode.
|
||||
* When the system needs to enter low power mode, the tick is suppressed and a low power timer
|
||||
* is used over that time
|
||||
* Note that in sleep mode, the system clock is still running and the default tickless implementation
|
||||
* using systick could have been kept.
|
||||
* However, as at that time, it is not yet known whereas the low power mode that will be used is stop mode or
|
||||
* sleep mode, it is easier and simpler to go with a low power timer as soon as the tick need to be
|
||||
* suppressed.
|
||||
*/
|
||||
#if ( CFG_LPM_SUPPORTED != 0)
|
||||
void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
LpTimerInit( );
|
||||
|
||||
/* Calculate the constants required to configure the tick interrupt. */
|
||||
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||
|
||||
/* Stop and clear the SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief The current implementation uses the hw_timerserver to provide a low power timer
|
||||
* This may be replaced by another low power timer.
|
||||
*
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
#if ( CFG_LPM_SUPPORTED != 0)
|
||||
static void LpTimerInit( void )
|
||||
{
|
||||
( void ) HW_TS_Create(CFG_TIM_PROC_ID_ISR, &(LpTimerContext.LpTimerFreeRTOS_Id), hw_ts_SingleShot, LpTimerCb);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Low power timer callback
|
||||
*
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
#if ( CFG_LPM_SUPPORTED != 0)
|
||||
static void LpTimerCb( void )
|
||||
{
|
||||
/**
|
||||
* Nothing to be done
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Request to start a low power timer ( running is stop mode )
|
||||
*
|
||||
* @param time_to_sleep : Number of FreeRTOS ticks
|
||||
* @retval None
|
||||
*/
|
||||
#if ( CFG_LPM_SUPPORTED != 0)
|
||||
static void LpTimerStart( uint32_t time_to_sleep )
|
||||
{
|
||||
uint64_t time;
|
||||
|
||||
/* Converts the number of FreeRTOS ticks into hw timer tick */
|
||||
if (time_to_sleep > (ULLONG_MAX / 1e12)) /* Prevent overflow in else statement */
|
||||
{
|
||||
time = 0xFFFF0000; /* Maximum value equal to 24 days */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The result always fits in uint32_t and is always less than 0xFFFF0000 */
|
||||
time = time_to_sleep * 1000000000000ULL;
|
||||
time = (uint64_t)( time / ( CFG_TS_TICK_VAL_PS * configTICK_RATE_HZ ));
|
||||
}
|
||||
|
||||
HW_TS_Start(LpTimerContext.LpTimerFreeRTOS_Id, (uint32_t)time);
|
||||
|
||||
/**
|
||||
* There might be other timers already running in the timer server that may elapse
|
||||
* before this one.
|
||||
* Store how long before the next event so that on wakeup, it will be possible to calculate
|
||||
* how long the tick has been suppressed
|
||||
*/
|
||||
LpTimerContext.LpTimeLeftOnEntry = HW_TS_RTC_ReadLeftTicksToCount( );
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enter low power mode
|
||||
*
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
#if ( CFG_LPM_SUPPORTED != 0)
|
||||
static void LpEnter( void )
|
||||
{
|
||||
#if ( CFG_LPM_SUPPORTED == 1)
|
||||
UTIL_LPM_EnterLowPower();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Read how long the tick has been suppressed
|
||||
*
|
||||
* @param None
|
||||
* @retval The number of tick rate (FreeRTOS tick)
|
||||
*/
|
||||
#if ( CFG_LPM_SUPPORTED != 0)
|
||||
static uint32_t LpGetElapsedTime( void )
|
||||
{
|
||||
uint64_t val_ticks, time_ps;
|
||||
uint32_t LpTimeLeftOnExit;
|
||||
|
||||
LpTimeLeftOnExit = HW_TS_RTC_ReadLeftTicksToCount();
|
||||
/* This cannot overflow. Max result is ~ 1.6e13 */
|
||||
time_ps = (uint64_t)((CFG_TS_TICK_VAL_PS) * (uint64_t)(LpTimerContext.LpTimeLeftOnEntry - LpTimeLeftOnExit));
|
||||
|
||||
/* time_ps can be less than 1 RTOS tick in following situations
|
||||
* a) MCU didn't go to STOP2 due to wake-up unrelated to Timer Server or woke up from STOP2 very shortly after.
|
||||
* Advancing RTOS clock by 1 FreeRTOS tick doesn't hurt in this case.
|
||||
* b) vPortSuppressTicksAndSleep(xExpectedIdleTime) was called with xExpectedIdleTime = 2 which is minimum value defined by configEXPECTED_IDLE_TIME_BEFORE_SLEEP.
|
||||
* The xExpectedIdleTime is decremented by one RTOS tick to wake-up in advance.
|
||||
* Ex: RTOS tick is 1ms, the timer Server wakes the MCU in ~977 us. RTOS clock should be advanced by 1 ms.
|
||||
* */
|
||||
if(time_ps <= (1e12 / configTICK_RATE_HZ)) /* time_ps < RTOS tick */
|
||||
{
|
||||
val_ticks = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Convert pS time into OS ticks */
|
||||
val_ticks = time_ps * configTICK_RATE_HZ; /* This cannot overflow. Max result is ~ 1.6e16 */
|
||||
val_ticks = (uint64_t)(val_ticks / (1e12)); /* The result always fits in uint32_t */
|
||||
}
|
||||
|
||||
/**
|
||||
* The system may have been out from another reason than the timer
|
||||
* Stop the timer after the elapsed time is calculated other wise, HW_TS_RTC_ReadLeftTicksToCount()
|
||||
* may return 0xFFFF ( TIMER LIST EMPTY )
|
||||
* It does not hurt stopping a timer that exists but is not running.
|
||||
*/
|
||||
HW_TS_Stop(LpTimerContext.LpTimerFreeRTOS_Id);
|
||||
|
||||
return (uint32_t)val_ticks;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,888 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file hw_timerserver.c
|
||||
* @author MCD Application Team
|
||||
* @brief Hardware timerserver source file for STM32WPAN Middleware.
|
||||
******************************************************************************
|
||||
* @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 "app_common.h"
|
||||
#include "hw_conf.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
typedef enum
|
||||
{
|
||||
TimerID_Free,
|
||||
TimerID_Created,
|
||||
TimerID_Running
|
||||
}TimerIDStatus_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SSR_Read_Requested,
|
||||
SSR_Read_Not_Requested
|
||||
}RequestReadSSR_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WakeupTimerValue_Overpassed,
|
||||
WakeupTimerValue_LargeEnough
|
||||
}WakeupTimerLimitation_Status_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HW_TS_pTimerCb_t pTimerCallBack;
|
||||
uint32_t CounterInit;
|
||||
uint32_t CountLeft;
|
||||
TimerIDStatus_t TimerIDStatus;
|
||||
HW_TS_Mode_t TimerMode;
|
||||
uint32_t TimerProcessID;
|
||||
uint8_t PreviousID;
|
||||
uint8_t NextID;
|
||||
}TimerContext_t;
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#define SSR_FORBIDDEN_VALUE 0xFFFFFFFF
|
||||
#define TIMER_LIST_EMPTY 0xFFFF
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* START of Section TIMERSERVER_CONTEXT
|
||||
*/
|
||||
|
||||
static volatile TimerContext_t aTimerContext[CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER];
|
||||
static volatile uint8_t CurrentRunningTimerID;
|
||||
static volatile uint8_t PreviousRunningTimerID;
|
||||
static volatile uint32_t SSRValueOnLastSetup;
|
||||
static volatile WakeupTimerLimitation_Status_t WakeupTimerLimitation;
|
||||
|
||||
/**
|
||||
* END of Section TIMERSERVER_CONTEXT
|
||||
*/
|
||||
|
||||
static uint8_t WakeupTimerDivider;
|
||||
static uint8_t AsynchPrescalerUserConfig;
|
||||
static uint16_t SynchPrescalerUserConfig;
|
||||
static volatile uint16_t MaxWakeupTimerSetup;
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
extern RTC_HandleTypeDef hrtc;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static void RestartWakeupCounter(uint16_t Value);
|
||||
static uint16_t ReturnTimeElapsed(void);
|
||||
static void RescheduleTimerList(void);
|
||||
static void UnlinkTimer(uint8_t TimerID, RequestReadSSR_t RequestReadSSR);
|
||||
static void LinkTimerBefore(uint8_t TimerID, uint8_t RefTimerID);
|
||||
static void LinkTimerAfter(uint8_t TimerID, uint8_t RefTimerID);
|
||||
static uint16_t linkTimer(uint8_t TimerID);
|
||||
static uint32_t ReadRtcSsrValue(void);
|
||||
|
||||
__weak void HW_TS_RTC_CountUpdated_AppNot(void);
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Read the RTC_SSR value
|
||||
* As described in the reference manual, the RTC_SSR shall be read twice to ensure
|
||||
* reliability of the value
|
||||
* @param None
|
||||
* @retval SSR value read
|
||||
*/
|
||||
static uint32_t ReadRtcSsrValue(void)
|
||||
{
|
||||
uint32_t first_read;
|
||||
uint32_t second_read;
|
||||
|
||||
first_read = (uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS));
|
||||
|
||||
second_read = (uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS));
|
||||
|
||||
while(first_read != second_read)
|
||||
{
|
||||
first_read = second_read;
|
||||
|
||||
second_read = (uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS));
|
||||
}
|
||||
|
||||
return second_read;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert a Timer in the list after the Timer ID specified
|
||||
* @param TimerID: The ID of the Timer
|
||||
* @param RefTimerID: The ID of the Timer to be linked after
|
||||
* @retval None
|
||||
*/
|
||||
static void LinkTimerAfter(uint8_t TimerID, uint8_t RefTimerID)
|
||||
{
|
||||
uint8_t next_id;
|
||||
|
||||
next_id = aTimerContext[RefTimerID].NextID;
|
||||
|
||||
if(next_id != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
|
||||
{
|
||||
aTimerContext[next_id].PreviousID = TimerID;
|
||||
}
|
||||
aTimerContext[TimerID].NextID = next_id;
|
||||
aTimerContext[TimerID].PreviousID = RefTimerID ;
|
||||
aTimerContext[RefTimerID].NextID = TimerID;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert a Timer in the list before the ID specified
|
||||
* @param TimerID: The ID of the Timer
|
||||
* @param RefTimerID: The ID of the Timer to be linked before
|
||||
* @retval None
|
||||
*/
|
||||
static void LinkTimerBefore(uint8_t TimerID, uint8_t RefTimerID)
|
||||
{
|
||||
uint8_t previous_id;
|
||||
|
||||
if(RefTimerID != CurrentRunningTimerID)
|
||||
{
|
||||
previous_id = aTimerContext[RefTimerID].PreviousID;
|
||||
|
||||
aTimerContext[previous_id].NextID = TimerID;
|
||||
aTimerContext[TimerID].NextID = RefTimerID;
|
||||
aTimerContext[TimerID].PreviousID = previous_id ;
|
||||
aTimerContext[RefTimerID].PreviousID = TimerID;
|
||||
}
|
||||
else
|
||||
{
|
||||
aTimerContext[TimerID].NextID = RefTimerID;
|
||||
aTimerContext[RefTimerID].PreviousID = TimerID;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert a Timer in the list
|
||||
* @param TimerID: The ID of the Timer
|
||||
* @retval None
|
||||
*/
|
||||
static uint16_t linkTimer(uint8_t TimerID)
|
||||
{
|
||||
uint32_t time_left;
|
||||
uint16_t time_elapsed;
|
||||
uint8_t timer_id_lookup;
|
||||
uint8_t next_id;
|
||||
|
||||
if(CurrentRunningTimerID == CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
|
||||
{
|
||||
/**
|
||||
* No timer in the list
|
||||
*/
|
||||
PreviousRunningTimerID = CurrentRunningTimerID;
|
||||
CurrentRunningTimerID = TimerID;
|
||||
aTimerContext[TimerID].NextID = CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER;
|
||||
|
||||
SSRValueOnLastSetup = SSR_FORBIDDEN_VALUE;
|
||||
time_elapsed = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
time_elapsed = ReturnTimeElapsed();
|
||||
|
||||
/**
|
||||
* update count of the timer to be linked
|
||||
*/
|
||||
aTimerContext[TimerID].CountLeft += time_elapsed;
|
||||
time_left = aTimerContext[TimerID].CountLeft;
|
||||
|
||||
/**
|
||||
* Search for index where the new timer shall be linked
|
||||
*/
|
||||
if(aTimerContext[CurrentRunningTimerID].CountLeft <= time_left)
|
||||
{
|
||||
/**
|
||||
* Search for the ID after the first one
|
||||
*/
|
||||
timer_id_lookup = CurrentRunningTimerID;
|
||||
next_id = aTimerContext[timer_id_lookup].NextID;
|
||||
while((next_id != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER) && (aTimerContext[next_id].CountLeft <= time_left))
|
||||
{
|
||||
timer_id_lookup = aTimerContext[timer_id_lookup].NextID;
|
||||
next_id = aTimerContext[timer_id_lookup].NextID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link after the ID
|
||||
*/
|
||||
LinkTimerAfter(TimerID, timer_id_lookup);
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* Link before the first ID
|
||||
*/
|
||||
LinkTimerBefore(TimerID, CurrentRunningTimerID);
|
||||
PreviousRunningTimerID = CurrentRunningTimerID;
|
||||
CurrentRunningTimerID = TimerID;
|
||||
}
|
||||
}
|
||||
|
||||
return time_elapsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove a Timer from the list
|
||||
* @param TimerID: The ID of the Timer
|
||||
* @param RequestReadSSR: Request to read the SSR register or not
|
||||
* @retval None
|
||||
*/
|
||||
static void UnlinkTimer(uint8_t TimerID, RequestReadSSR_t RequestReadSSR)
|
||||
{
|
||||
uint8_t previous_id;
|
||||
uint8_t next_id;
|
||||
|
||||
if(TimerID == CurrentRunningTimerID)
|
||||
{
|
||||
PreviousRunningTimerID = CurrentRunningTimerID;
|
||||
CurrentRunningTimerID = aTimerContext[TimerID].NextID;
|
||||
}
|
||||
else
|
||||
{
|
||||
previous_id = aTimerContext[TimerID].PreviousID;
|
||||
next_id = aTimerContext[TimerID].NextID;
|
||||
|
||||
aTimerContext[previous_id].NextID = aTimerContext[TimerID].NextID;
|
||||
if(next_id != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
|
||||
{
|
||||
aTimerContext[next_id].PreviousID = aTimerContext[TimerID].PreviousID;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Timer is out of the list
|
||||
*/
|
||||
aTimerContext[TimerID].TimerIDStatus = TimerID_Created;
|
||||
|
||||
if((CurrentRunningTimerID == CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER) && (RequestReadSSR == SSR_Read_Requested))
|
||||
{
|
||||
SSRValueOnLastSetup = SSR_FORBIDDEN_VALUE;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the number of ticks counted by the wakeuptimer since it has been started
|
||||
* @note The API is reading the SSR register to get how many ticks have been counted
|
||||
* since the time the timer has been started
|
||||
* @param None
|
||||
* @retval Time expired in Ticks
|
||||
*/
|
||||
static uint16_t ReturnTimeElapsed(void)
|
||||
{
|
||||
uint32_t return_value;
|
||||
uint32_t wrap_counter;
|
||||
|
||||
if(SSRValueOnLastSetup != SSR_FORBIDDEN_VALUE)
|
||||
{
|
||||
return_value = ReadRtcSsrValue(); /**< Read SSR register first */
|
||||
|
||||
if (SSRValueOnLastSetup >= return_value)
|
||||
{
|
||||
return_value = SSRValueOnLastSetup - return_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
wrap_counter = SynchPrescalerUserConfig - return_value;
|
||||
return_value = SSRValueOnLastSetup + wrap_counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* At this stage, ReturnValue holds the number of ticks counted by SSR
|
||||
* Need to translate in number of ticks counted by the Wakeuptimer
|
||||
*/
|
||||
return_value = return_value*AsynchPrescalerUserConfig;
|
||||
return_value = return_value >> WakeupTimerDivider;
|
||||
}
|
||||
else
|
||||
{
|
||||
return_value = 0;
|
||||
}
|
||||
|
||||
return (uint16_t)return_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the wakeup counter
|
||||
* @note The API is writing the counter value so that the value is decreased by one to cope with the fact
|
||||
* the interrupt is generated with 1 extra clock cycle (See RefManuel)
|
||||
* It assumes all condition are met to be allowed to write the wakeup counter
|
||||
* @param Value: Value to be written in the counter
|
||||
* @retval None
|
||||
*/
|
||||
static void RestartWakeupCounter(uint16_t Value)
|
||||
{
|
||||
/**
|
||||
* The wakeuptimer has been disabled in the calling function to reduce the time to poll the WUTWF
|
||||
* FLAG when the new value will have to be written
|
||||
* __HAL_RTC_WAKEUPTIMER_DISABLE(&hrtc);
|
||||
*/
|
||||
|
||||
if(Value == 0)
|
||||
{
|
||||
SSRValueOnLastSetup = ReadRtcSsrValue();
|
||||
|
||||
/**
|
||||
* Simulate that the Timer expired
|
||||
*/
|
||||
HAL_NVIC_SetPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);
|
||||
}
|
||||
else
|
||||
{
|
||||
if((Value > 1) ||(WakeupTimerDivider != 1))
|
||||
{
|
||||
Value -= 1;
|
||||
}
|
||||
|
||||
while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hrtc, RTC_FLAG_WUTWF) == RESET);
|
||||
|
||||
/**
|
||||
* make sure to clear the flags after checking the WUTWF.
|
||||
* It takes 2 RTCCLK between the time the WUTE bit is disabled and the
|
||||
* time the timer is disabled. The WUTWF bit somehow guarantee the system is stable
|
||||
* Otherwise, when the timer is periodic with 1 Tick, it may generate an extra interrupt in between
|
||||
* due to the autoreload feature
|
||||
*/
|
||||
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF); /**< Clear flag in RTC module */
|
||||
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**< Clear flag in EXTI module */
|
||||
HAL_NVIC_ClearPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Clear pending bit in NVIC */
|
||||
|
||||
MODIFY_REG(RTC->WUTR, RTC_WUTR_WUT, Value);
|
||||
|
||||
/**
|
||||
* Update the value here after the WUTWF polling that may take some time
|
||||
*/
|
||||
SSRValueOnLastSetup = ReadRtcSsrValue();
|
||||
|
||||
__HAL_RTC_WAKEUPTIMER_ENABLE(&hrtc); /**< Enable the Wakeup Timer */
|
||||
|
||||
HW_TS_RTC_CountUpdated_AppNot();
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reschedule the list of timer
|
||||
* @note 1) Update the count left for each timer in the list
|
||||
* 2) Setup the wakeuptimer
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void RescheduleTimerList(void)
|
||||
{
|
||||
uint8_t localTimerID;
|
||||
uint32_t timecountleft;
|
||||
uint16_t wakeup_timer_value;
|
||||
uint16_t time_elapsed;
|
||||
|
||||
/**
|
||||
* The wakeuptimer is disabled now to reduce the time to poll the WUTWF
|
||||
* FLAG when the new value will have to be written
|
||||
*/
|
||||
if((READ_BIT(RTC->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) == SET)
|
||||
{
|
||||
/**
|
||||
* Wait for the flag to be back to 0 when the wakeup timer is enabled
|
||||
*/
|
||||
while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hrtc, RTC_FLAG_WUTWF) == SET);
|
||||
}
|
||||
__HAL_RTC_WAKEUPTIMER_DISABLE(&hrtc); /**< Disable the Wakeup Timer */
|
||||
|
||||
localTimerID = CurrentRunningTimerID;
|
||||
|
||||
/**
|
||||
* Calculate what will be the value to write in the wakeuptimer
|
||||
*/
|
||||
timecountleft = aTimerContext[localTimerID].CountLeft;
|
||||
|
||||
/**
|
||||
* Read how much has been counted
|
||||
*/
|
||||
time_elapsed = ReturnTimeElapsed();
|
||||
|
||||
if(timecountleft < time_elapsed )
|
||||
{
|
||||
/**
|
||||
* There is no tick left to count
|
||||
*/
|
||||
wakeup_timer_value = 0;
|
||||
WakeupTimerLimitation = WakeupTimerValue_LargeEnough;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(timecountleft > (time_elapsed + MaxWakeupTimerSetup))
|
||||
{
|
||||
/**
|
||||
* The number of tick left is greater than the Wakeuptimer maximum value
|
||||
*/
|
||||
wakeup_timer_value = MaxWakeupTimerSetup;
|
||||
|
||||
WakeupTimerLimitation = WakeupTimerValue_Overpassed;
|
||||
}
|
||||
else
|
||||
{
|
||||
wakeup_timer_value = timecountleft - time_elapsed;
|
||||
WakeupTimerLimitation = WakeupTimerValue_LargeEnough;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* update ticks left to be counted for each timer
|
||||
*/
|
||||
while(localTimerID != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
|
||||
{
|
||||
if (aTimerContext[localTimerID].CountLeft < time_elapsed)
|
||||
{
|
||||
aTimerContext[localTimerID].CountLeft = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
aTimerContext[localTimerID].CountLeft -= time_elapsed;
|
||||
}
|
||||
localTimerID = aTimerContext[localTimerID].NextID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write next count
|
||||
*/
|
||||
RestartWakeupCounter(wakeup_timer_value);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
/* Public functions ----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* For all public interface except that may need write access to the RTC, the RTC
|
||||
* shall be unlock at the beginning and locked at the output
|
||||
* In order to ease maintainability, the unlock is done at the top and the lock at then end
|
||||
* in case some new implementation is coming in the future
|
||||
*/
|
||||
|
||||
void HW_TS_RTC_Wakeup_Handler(void)
|
||||
{
|
||||
HW_TS_pTimerCb_t ptimer_callback;
|
||||
uint32_t timer_process_id;
|
||||
uint8_t local_current_running_timer_id;
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
uint32_t primask_bit;
|
||||
#endif
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
#endif
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE( &hrtc );
|
||||
|
||||
/**
|
||||
* Disable the Wakeup Timer
|
||||
* This may speed up a bit the processing to wait the timer to be disabled
|
||||
* The timer is still counting 2 RTCCLK
|
||||
*/
|
||||
__HAL_RTC_WAKEUPTIMER_DISABLE(&hrtc);
|
||||
|
||||
local_current_running_timer_id = CurrentRunningTimerID;
|
||||
|
||||
if(aTimerContext[local_current_running_timer_id].TimerIDStatus == TimerID_Running)
|
||||
{
|
||||
ptimer_callback = aTimerContext[local_current_running_timer_id].pTimerCallBack;
|
||||
timer_process_id = aTimerContext[local_current_running_timer_id].TimerProcessID;
|
||||
|
||||
/**
|
||||
* It should be good to check whether the TimeElapsed is greater or not than the tick left to be counted
|
||||
* However, due to the inaccuracy of the reading of the time elapsed, it may return there is 1 tick
|
||||
* to be left whereas the count is over
|
||||
* A more secure implementation has been done with a flag to state whereas the full count has been written
|
||||
* in the wakeuptimer or not
|
||||
*/
|
||||
if(WakeupTimerLimitation != WakeupTimerValue_Overpassed)
|
||||
{
|
||||
if(aTimerContext[local_current_running_timer_id].TimerMode == hw_ts_Repeated)
|
||||
{
|
||||
UnlinkTimer(local_current_running_timer_id, SSR_Read_Not_Requested);
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
HW_TS_Start(local_current_running_timer_id, aTimerContext[local_current_running_timer_id].CounterInit);
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE( &hrtc );
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
HW_TS_Stop(local_current_running_timer_id);
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE( &hrtc );
|
||||
}
|
||||
|
||||
HW_TS_RTC_Int_AppNot(timer_process_id, local_current_running_timer_id, ptimer_callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
RescheduleTimerList();
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* We should never end up in this case
|
||||
* However, if due to any bug in the timer server this is the case, the mistake may not impact the user.
|
||||
* We could just clean the interrupt flag and get out from this unexpected interrupt
|
||||
*/
|
||||
while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hrtc, RTC_FLAG_WUTWF) == RESET);
|
||||
|
||||
/**
|
||||
* make sure to clear the flags after checking the WUTWF.
|
||||
* It takes 2 RTCCLK between the time the WUTE bit is disabled and the
|
||||
* time the timer is disabled. The WUTWF bit somehow guarantee the system is stable
|
||||
* Otherwise, when the timer is periodic with 1 Tick, it may generate an extra interrupt in between
|
||||
* due to the autoreload feature
|
||||
*/
|
||||
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF); /**< Clear flag in RTC module */
|
||||
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**< Clear flag in EXTI module */
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE( &hrtc );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_TS_Init(HW_TS_InitMode_t TimerInitMode, RTC_HandleTypeDef *phrtc)
|
||||
{
|
||||
uint8_t loop;
|
||||
uint32_t localmaxwakeuptimersetup;
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE( &hrtc );
|
||||
|
||||
SET_BIT(RTC->CR, RTC_CR_BYPSHAD);
|
||||
|
||||
/**
|
||||
* Readout the user config
|
||||
*/
|
||||
WakeupTimerDivider = (4 - ((uint32_t)(READ_BIT(RTC->CR, RTC_CR_WUCKSEL))));
|
||||
|
||||
AsynchPrescalerUserConfig = (uint8_t)(READ_BIT(RTC->PRER, RTC_PRER_PREDIV_A) >> (uint32_t)POSITION_VAL(RTC_PRER_PREDIV_A)) + 1;
|
||||
|
||||
SynchPrescalerUserConfig = (uint16_t)(READ_BIT(RTC->PRER, RTC_PRER_PREDIV_S)) + 1;
|
||||
|
||||
/**
|
||||
* Margin is taken to avoid wrong calculation when the wrap around is there and some
|
||||
* application interrupts may have delayed the reading
|
||||
*/
|
||||
localmaxwakeuptimersetup = ((((SynchPrescalerUserConfig - 1)*AsynchPrescalerUserConfig) - CFG_HW_TS_RTC_HANDLER_MAX_DELAY) >> WakeupTimerDivider);
|
||||
|
||||
if(localmaxwakeuptimersetup >= 0xFFFF)
|
||||
{
|
||||
MaxWakeupTimerSetup = 0xFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
MaxWakeupTimerSetup = (uint16_t)localmaxwakeuptimersetup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure EXTI module
|
||||
*/
|
||||
LL_EXTI_EnableRisingTrig_0_31(RTC_EXTI_LINE_WAKEUPTIMER_EVENT);
|
||||
LL_EXTI_EnableIT_0_31(RTC_EXTI_LINE_WAKEUPTIMER_EVENT);
|
||||
|
||||
if(TimerInitMode == hw_ts_InitMode_Full)
|
||||
{
|
||||
WakeupTimerLimitation = WakeupTimerValue_LargeEnough;
|
||||
SSRValueOnLastSetup = SSR_FORBIDDEN_VALUE;
|
||||
|
||||
/**
|
||||
* Initialize the timer server
|
||||
*/
|
||||
for(loop = 0; loop < CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER; loop++)
|
||||
{
|
||||
aTimerContext[loop].TimerIDStatus = TimerID_Free;
|
||||
}
|
||||
|
||||
CurrentRunningTimerID = CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER; /**< Set ID to non valid value */
|
||||
|
||||
__HAL_RTC_WAKEUPTIMER_DISABLE(&hrtc); /**< Disable the Wakeup Timer */
|
||||
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF); /**< Clear flag in RTC module */
|
||||
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**< Clear flag in EXTI module */
|
||||
HAL_NVIC_ClearPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Clear pending bit in NVIC */
|
||||
__HAL_RTC_WAKEUPTIMER_ENABLE_IT(&hrtc, RTC_IT_WUT); /**< Enable interrupt in RTC module */
|
||||
}
|
||||
else
|
||||
{
|
||||
if(__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hrtc, RTC_FLAG_WUTF) != RESET)
|
||||
{
|
||||
/**
|
||||
* Simulate that the Timer expired
|
||||
*/
|
||||
HAL_NVIC_SetPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE( &hrtc );
|
||||
|
||||
HAL_NVIC_SetPriority(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID, CFG_HW_TS_NVIC_RTC_WAKEUP_IT_PREEMPTPRIO, CFG_HW_TS_NVIC_RTC_WAKEUP_IT_SUBPRIO); /**< Set NVIC priority */
|
||||
HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Enable NVIC */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
HW_TS_ReturnStatus_t HW_TS_Create(uint32_t TimerProcessID, uint8_t *pTimerId, HW_TS_Mode_t TimerMode, HW_TS_pTimerCb_t pftimeout_handler)
|
||||
{
|
||||
HW_TS_ReturnStatus_t localreturnstatus;
|
||||
uint8_t loop = 0;
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
uint32_t primask_bit;
|
||||
#endif
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
#endif
|
||||
|
||||
while((loop < CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER) && (aTimerContext[loop].TimerIDStatus != TimerID_Free))
|
||||
{
|
||||
loop++;
|
||||
}
|
||||
|
||||
if(loop != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
|
||||
{
|
||||
aTimerContext[loop].TimerIDStatus = TimerID_Created;
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
|
||||
aTimerContext[loop].TimerProcessID = TimerProcessID;
|
||||
aTimerContext[loop].TimerMode = TimerMode;
|
||||
aTimerContext[loop].pTimerCallBack = pftimeout_handler;
|
||||
*pTimerId = loop;
|
||||
|
||||
localreturnstatus = hw_ts_Successful;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
|
||||
localreturnstatus = hw_ts_Failed;
|
||||
}
|
||||
|
||||
return(localreturnstatus);
|
||||
}
|
||||
|
||||
void HW_TS_Delete(uint8_t timer_id)
|
||||
{
|
||||
HW_TS_Stop(timer_id);
|
||||
|
||||
aTimerContext[timer_id].TimerIDStatus = TimerID_Free; /**< release ID */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_TS_Stop(uint8_t timer_id)
|
||||
{
|
||||
uint8_t localcurrentrunningtimerid;
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
uint32_t primask_bit;
|
||||
#endif
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
#endif
|
||||
|
||||
HAL_NVIC_DisableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Disable NVIC */
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE( &hrtc );
|
||||
|
||||
if(aTimerContext[timer_id].TimerIDStatus == TimerID_Running)
|
||||
{
|
||||
UnlinkTimer(timer_id, SSR_Read_Requested);
|
||||
localcurrentrunningtimerid = CurrentRunningTimerID;
|
||||
|
||||
if(localcurrentrunningtimerid == CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
|
||||
{
|
||||
/**
|
||||
* List is empty
|
||||
*/
|
||||
|
||||
/**
|
||||
* Disable the timer
|
||||
*/
|
||||
if((READ_BIT(RTC->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) == SET)
|
||||
{
|
||||
/**
|
||||
* Wait for the flag to be back to 0 when the wakeup timer is enabled
|
||||
*/
|
||||
while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hrtc, RTC_FLAG_WUTWF) == SET);
|
||||
}
|
||||
__HAL_RTC_WAKEUPTIMER_DISABLE(&hrtc); /**< Disable the Wakeup Timer */
|
||||
|
||||
while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hrtc, RTC_FLAG_WUTWF) == RESET);
|
||||
|
||||
/**
|
||||
* make sure to clear the flags after checking the WUTWF.
|
||||
* It takes 2 RTCCLK between the time the WUTE bit is disabled and the
|
||||
* time the timer is disabled. The WUTWF bit somehow guarantee the system is stable
|
||||
* Otherwise, when the timer is periodic with 1 Tick, it may generate an extra interrupt in between
|
||||
* due to the autoreload feature
|
||||
*/
|
||||
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF); /**< Clear flag in RTC module */
|
||||
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**< Clear flag in EXTI module */
|
||||
HAL_NVIC_ClearPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Clear pending bit in NVIC */
|
||||
}
|
||||
else if(PreviousRunningTimerID != localcurrentrunningtimerid)
|
||||
{
|
||||
RescheduleTimerList();
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE( &hrtc );
|
||||
|
||||
HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Enable NVIC */
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_TS_Start(uint8_t timer_id, uint32_t timeout_ticks)
|
||||
{
|
||||
uint16_t time_elapsed;
|
||||
uint8_t localcurrentrunningtimerid;
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
uint32_t primask_bit;
|
||||
#endif
|
||||
|
||||
if(aTimerContext[timer_id].TimerIDStatus == TimerID_Running)
|
||||
{
|
||||
HW_TS_Stop( timer_id );
|
||||
}
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
#endif
|
||||
|
||||
HAL_NVIC_DisableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Disable NVIC */
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE( &hrtc );
|
||||
|
||||
aTimerContext[timer_id].TimerIDStatus = TimerID_Running;
|
||||
|
||||
aTimerContext[timer_id].CountLeft = timeout_ticks;
|
||||
aTimerContext[timer_id].CounterInit = timeout_ticks;
|
||||
|
||||
time_elapsed = linkTimer(timer_id);
|
||||
|
||||
localcurrentrunningtimerid = CurrentRunningTimerID;
|
||||
|
||||
if(PreviousRunningTimerID != localcurrentrunningtimerid)
|
||||
{
|
||||
RescheduleTimerList();
|
||||
}
|
||||
else
|
||||
{
|
||||
aTimerContext[timer_id].CountLeft -= time_elapsed;
|
||||
}
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE( &hrtc );
|
||||
|
||||
HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**< Enable NVIC */
|
||||
|
||||
#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t HW_TS_RTC_ReadLeftTicksToCount(void)
|
||||
{
|
||||
uint32_t primask_bit;
|
||||
uint16_t return_value, auro_reload_value, elapsed_time_value;
|
||||
|
||||
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
|
||||
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
|
||||
|
||||
if((READ_BIT(RTC->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) == SET)
|
||||
{
|
||||
auro_reload_value = (uint32_t)(READ_BIT(RTC->WUTR, RTC_WUTR_WUT));
|
||||
|
||||
elapsed_time_value = ReturnTimeElapsed();
|
||||
|
||||
if(auro_reload_value > elapsed_time_value)
|
||||
{
|
||||
return_value = auro_reload_value - elapsed_time_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return_value = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return_value = TIMER_LIST_EMPTY;
|
||||
}
|
||||
|
||||
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
|
||||
|
||||
return (return_value);
|
||||
}
|
||||
|
||||
__weak void HW_TS_RTC_Int_AppNot(uint32_t TimerProcessID, uint8_t TimerID, HW_TS_pTimerCb_t pTimerCallBack)
|
||||
{
|
||||
pTimerCallBack();
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
#include "madgwick.h"
|
||||
#include <math.h>
|
||||
|
||||
// Initialize the filter
|
||||
void MadgwickFilter_Init(MadgwickFilter* filter, float sampleFreq, float beta) {
|
||||
filter->q[0] = 1.0f; // qw (scalar component)
|
||||
filter->q[1] = 0.0f; // qx
|
||||
filter->q[2] = 0.0f; // qy
|
||||
filter->q[3] = 0.0f; // qz
|
||||
filter->beta = beta; // Filter gain (e.g., 0.1)
|
||||
filter->sampleFreq = sampleFreq; // Sampling frequency in Hz
|
||||
}
|
||||
|
||||
// Update the quaternion using accelerometer and gyroscope data
|
||||
void MadgwickFilter_Update(MadgwickFilter* filter, float gx, float gy, float gz,
|
||||
float ax, float ay, float az) {
|
||||
float q[4] = {filter->q[0], filter->q[1], filter->q[2], filter->q[3]};
|
||||
float recipNorm;
|
||||
float s[4];
|
||||
float qDot[4];
|
||||
float _2q0, _2q1, _2q2, _2q3, _4q0, _4q1, _4q2, _8q1, _8q2, q0q0, q1q1, q2q2, q3q3;
|
||||
|
||||
// Convert gyroscope data from degrees/s to radians/s
|
||||
gx *= 0.0174533f; // deg/s to rad/s
|
||||
gy *= 0.0174533f;
|
||||
gz *= 0.0174533f;
|
||||
|
||||
// Rate of change of quaternion from gyroscope
|
||||
qDot[0] = 0.5f * (-q[1] * gx - q[2] * gy - q[3] * gz);
|
||||
qDot[1] = 0.5f * (q[0] * gx + q[2] * gz - q[3] * gy);
|
||||
qDot[2] = 0.5f * (q[0] * gy - q[1] * gz + q[3] * gx);
|
||||
qDot[3] = 0.5f * (q[0] * gz + q[1] * gy - q[2] * gx);
|
||||
|
||||
// Compute accelerometer objective function and Jacobian
|
||||
if ((ax != 0.0f) || (ay != 0.0f) || (az != 0.0f)) {
|
||||
// Normalize accelerometer measurement
|
||||
recipNorm = 1.0f / sqrtf(ax * ax + ay * ay + az * az);
|
||||
ax *= recipNorm;
|
||||
ay *= recipNorm;
|
||||
az *= recipNorm;
|
||||
|
||||
// Auxiliary variables to avoid repeated calculations
|
||||
_2q0 = 2.0f * q[0];
|
||||
_2q1 = 2.0f * q[1];
|
||||
_2q2 = 2.0f * q[2];
|
||||
_2q3 = 2.0f * q[3];
|
||||
_4q0 = 4.0f * q[0];
|
||||
_4q1 = 4.0f * q[1];
|
||||
_4q2 = 4.0f * q[2];
|
||||
_8q1 = 8.0f * q[1];
|
||||
_8q2 = 8.0f * q[2];
|
||||
q0q0 = q[0] * q[0];
|
||||
q1q1 = q[1] * q[1];
|
||||
q2q2 = q[2] * q[2];
|
||||
q3q3 = q[3] * q[3];
|
||||
|
||||
// Gradient descent algorithm corrective step
|
||||
s[0] = _4q0 * q2q2 + _2q2 * ax + _4q0 * q1q1 - _2q1 * ay;
|
||||
s[1] = _4q1 * q3q3 - _2q3 * ax + 4.0f * q0q0 * q[1] - _2q0 * ay - _4q1 + _8q1 * q1q1 + _8q1 * q2q2 + _4q1 * az;
|
||||
s[2] = 4.0f * q0q0 * q[2] + _2q0 * ax + _4q2 * q3q3 - _2q3 * ay - _4q2 + _8q2 * q1q1 + _8q2 * q2q2 + _4q2 * az;
|
||||
s[3] = 4.0f * q1q1 * q[3] - _2q1 * ax + 4.0f * q2q2 * q[3] - _2q2 * ay;
|
||||
|
||||
// Normalize step magnitude
|
||||
recipNorm = 1.0f / sqrtf(s[0] * s[0] + s[1] * s[1] + s[2] * s[2] + s[3] * s[3]);
|
||||
s[0] *= recipNorm;
|
||||
s[1] *= recipNorm;
|
||||
s[2] *= recipNorm;
|
||||
s[3] *= recipNorm;
|
||||
|
||||
// Apply feedback step
|
||||
qDot[0] -= filter->beta * s[0];
|
||||
qDot[1] -= filter->beta * s[1];
|
||||
qDot[2] -= filter->beta * s[2];
|
||||
qDot[3] -= filter->beta * s[3];
|
||||
}
|
||||
|
||||
// Integrate rate of change of quaternion
|
||||
float dt = 1.0f / filter->sampleFreq;
|
||||
q[0] += qDot[0] * dt;
|
||||
q[1] += qDot[1] * dt;
|
||||
q[2] += qDot[2] * dt;
|
||||
q[3] += qDot[3] * dt;
|
||||
|
||||
// Normalize quaternion
|
||||
recipNorm = 1.0f / sqrtf(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
|
||||
q[0] *= recipNorm;
|
||||
q[1] *= recipNorm;
|
||||
q[2] *= recipNorm;
|
||||
q[3] *= recipNorm;
|
||||
|
||||
// Update filter state
|
||||
filter->q[0] = q[0];
|
||||
filter->q[1] = q[1];
|
||||
filter->q[2] = q[2];
|
||||
filter->q[3] = q[3];
|
||||
}
|
||||
|
||||
// Convert quaternion to Euler angles (roll, pitch, yaw) in degrees
|
||||
void MadgwickFilter_GetEulerAngles(MadgwickFilter* filter, float* roll, float* pitch, float* yaw) {
|
||||
float q0 = filter->q[0];
|
||||
float q1 = filter->q[1];
|
||||
float q2 = filter->q[2];
|
||||
float q3 = filter->q[3];
|
||||
|
||||
// Roll (x-axis rotation)
|
||||
*roll = atan2f(2.0f * (q0 * q1 + q2 * q3), 1.0f - 2.0f * (q1 * q1 + q2 * q2)) * 57.2958f;
|
||||
|
||||
// Pitch (y-axis rotation)
|
||||
float sinp = 2.0f * (q0 * q2 - q3 * q1);
|
||||
if (fabsf(sinp) >= 1)
|
||||
*pitch = copysignf(M_PI / 2, sinp) * 57.2958f; // Use 90 degrees if out of range
|
||||
else
|
||||
*pitch = asinf(sinp) * 57.2958f;
|
||||
|
||||
// Yaw (z-axis rotation) - Note: Without magnetometer, yaw will drift
|
||||
*yaw = atan2f(2.0f * (q0 * q3 + q1 * q2), 1.0f - 2.0f * (q2 * q2 + q3 * q3)) * 57.2958f;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef MADGWICK_FILTER_H
|
||||
#define MADGWICK_FILTER_H
|
||||
|
||||
typedef struct {
|
||||
float q[4]; // Quaternion: [qw, qx, qy, qz]
|
||||
float beta; // Filter gain (tunes correction strength)
|
||||
float sampleFreq; // Sampling frequency in Hz
|
||||
} MadgwickFilter;
|
||||
|
||||
void MadgwickFilter_Init(MadgwickFilter* filter, float sampleFreq, float beta);
|
||||
void MadgwickFilter_Update(MadgwickFilter* filter, float gx, float gy, float gz,
|
||||
float ax, float ay, float az);
|
||||
void MadgwickFilter_GetEulerAngles(MadgwickFilter* filter, float* roll, float* pitch, float* yaw);
|
||||
|
||||
#endif /* MADGWICK_FILTER_H */
|
||||
@@ -0,0 +1,135 @@
|
||||
#ifndef MADGWICK_H
|
||||
#define MADGWICK_H
|
||||
|
||||
typedef struct {
|
||||
float q[4]; // Quaternion: [qw, qx, qy, qz]
|
||||
float beta; // Filter gain (tunes correction strength)
|
||||
float sampleFreq; // Sampling frequency in Hz
|
||||
} MadgwickFilter;
|
||||
|
||||
void MadgwickFilter_Init(MadgwickFilter* filter, float sampleFreq, float beta);
|
||||
void MadgwickFilter_Update(MadgwickFilter* filter, float gx, float gy, float gz,
|
||||
float ax, float ay, float az);
|
||||
void MadgwickFilter_GetEulerAngles(MadgwickFilter* filter, float* roll, float* pitch, float* yaw);
|
||||
|
||||
#ifdef MADGWICK_IMPLEMENTATION
|
||||
#include <math.h>
|
||||
|
||||
// Initialize the filter
|
||||
void MadgwickFilter_Init(MadgwickFilter* filter, float sampleFreq, float beta) {
|
||||
filter->q[0] = 1.0f; // qw (scalar component)
|
||||
filter->q[1] = 0.0f; // qx
|
||||
filter->q[2] = 0.0f; // qy
|
||||
filter->q[3] = 0.0f; // qz
|
||||
filter->beta = beta; // Filter gain (e.g., 0.1)
|
||||
filter->sampleFreq = sampleFreq; // Sampling frequency in Hz
|
||||
}
|
||||
|
||||
// Update the quaternion using accelerometer and gyroscope data
|
||||
void MadgwickFilter_Update(MadgwickFilter* filter, float gx, float gy, float gz,
|
||||
float ax, float ay, float az) {
|
||||
float q[4] = {filter->q[0], filter->q[1], filter->q[2], filter->q[3]};
|
||||
float recipNorm;
|
||||
float s[4];
|
||||
float qDot[4];
|
||||
float _2q0, _2q1, _2q2, _2q3, _4q0, _4q1, _4q2, _8q1, _8q2, q0q0, q1q1, q2q2, q3q3;
|
||||
|
||||
// Convert gyroscope data from degrees/s to radians/s
|
||||
gx *= 0.0174533f; // deg/s to rad/s
|
||||
gy *= 0.0174533f;
|
||||
gz *= 0.0174533f;
|
||||
|
||||
// Rate of change of quaternion from gyroscope
|
||||
qDot[0] = 0.5f * (-q[1] * gx - q[2] * gy - q[3] * gz);
|
||||
qDot[1] = 0.5f * (q[0] * gx + q[2] * gz - q[3] * gy);
|
||||
qDot[2] = 0.5f * (q[0] * gy - q[1] * gz + q[3] * gx);
|
||||
qDot[3] = 0.5f * (q[0] * gz + q[1] * gy - q[2] * gx);
|
||||
|
||||
// Compute accelerometer objective function and Jacobian
|
||||
if ((ax != 0.0f) || (ay != 0.0f) || (az != 0.0f)) {
|
||||
// Normalize accelerometer measurement
|
||||
recipNorm = 1.0f / sqrtf(ax * ax + ay * ay + az * az);
|
||||
ax *= recipNorm;
|
||||
ay *= recipNorm;
|
||||
az *= recipNorm;
|
||||
|
||||
// Auxiliary variables to avoid repeated calculations
|
||||
_2q0 = 2.0f * q[0];
|
||||
_2q1 = 2.0f * q[1];
|
||||
_2q2 = 2.0f * q[2];
|
||||
_2q3 = 2.0f * q[3];
|
||||
_4q0 = 4.0f * q[0];
|
||||
_4q1 = 4.0f * q[1];
|
||||
_4q2 = 4.0f * q[2];
|
||||
_8q1 = 8.0f * q[1];
|
||||
_8q2 = 8.0f * q[2];
|
||||
q0q0 = q[0] * q[0];
|
||||
q1q1 = q[1] * q[1];
|
||||
q2q2 = q[2] * q[2];
|
||||
q3q3 = q[3] * q[3];
|
||||
|
||||
// Gradient descent algorithm corrective step
|
||||
s[0] = _4q0 * q2q2 + _2q2 * ax + _4q0 * q1q1 - _2q1 * ay;
|
||||
s[1] = _4q1 * q3q3 - _2q3 * ax + 4.0f * q0q0 * q[1] - _2q0 * ay - _4q1 + _8q1 * q1q1 + _8q1 * q2q2 + _4q1 * az;
|
||||
s[2] = 4.0f * q0q0 * q[2] + _2q0 * ax + _4q2 * q3q3 - _2q3 * ay - _4q2 + _8q2 * q1q1 + _8q2 * q2q2 + _4q2 * az;
|
||||
s[3] = 4.0f * q1q1 * q[3] - _2q1 * ax + 4.0f * q2q2 * q[3] - _2q2 * ay;
|
||||
|
||||
// Normalize step magnitude
|
||||
recipNorm = 1.0f / sqrtf(s[0] * s[0] + s[1] * s[1] + s[2] * s[2] + s[3] * s[3]);
|
||||
s[0] *= recipNorm;
|
||||
s[1] *= recipNorm;
|
||||
s[2] *= recipNorm;
|
||||
s[3] *= recipNorm;
|
||||
|
||||
// Apply feedback step
|
||||
qDot[0] -= filter->beta * s[0];
|
||||
qDot[1] -= filter->beta * s[1];
|
||||
qDot[2] -= filter->beta * s[2];
|
||||
qDot[3] -= filter->beta * s[3];
|
||||
}
|
||||
|
||||
// Integrate rate of change of quaternion
|
||||
float dt = 1.0f / filter->sampleFreq;
|
||||
q[0] += qDot[0] * dt;
|
||||
q[1] += qDot[1] * dt;
|
||||
q[2] += qDot[2] * dt;
|
||||
q[3] += qDot[3] * dt;
|
||||
|
||||
// Normalize quaternion
|
||||
recipNorm = 1.0f / sqrtf(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
|
||||
q[0] *= recipNorm;
|
||||
q[1] *= recipNorm;
|
||||
q[2] *= recipNorm;
|
||||
q[3] *= recipNorm;
|
||||
|
||||
// Update filter state
|
||||
filter->q[0] = q[0];
|
||||
filter->q[1] = q[1];
|
||||
filter->q[2] = q[2];
|
||||
filter->q[3] = q[3];
|
||||
}
|
||||
|
||||
// Convert quaternion to Euler angles (roll, pitch, yaw) in degrees
|
||||
void MadgwickFilter_GetEulerAngles(MadgwickFilter* filter, float* roll, float* pitch, float* yaw) {
|
||||
float q0 = filter->q[0];
|
||||
float q1 = filter->q[1];
|
||||
float q2 = filter->q[2];
|
||||
float q3 = filter->q[3];
|
||||
|
||||
// Roll (x-axis rotation)
|
||||
*roll = atan2f(2.0f * (q0 * q1 + q2 * q3), 1.0f - 2.0f * (q1 * q1 + q2 * q2)) * 57.2958f;
|
||||
|
||||
// Pitch (y-axis rotation)
|
||||
float sinp = 2.0f * (q0 * q2 - q3 * q1);
|
||||
if (fabsf(sinp) >= 1)
|
||||
*pitch = copysignf(M_PI / 2, sinp) * 57.2958f; // Use 90 degrees if out of range
|
||||
else
|
||||
*pitch = asinf(sinp) * 57.2958f;
|
||||
|
||||
// Yaw (z-axis rotation) - Note: Without magnetometer, yaw will drift
|
||||
*yaw = atan2f(2.0f * (q0 * q3 + q1 * q2), 1.0f - 2.0f * (q2 * q2 + q3 * q3)) * 57.2958f;
|
||||
}
|
||||
|
||||
|
||||
#endif // end of #ifdef MADGWICK_IMPLEMENTATION
|
||||
#endif //end of #ifndef MADGWICK_H
|
||||
+968
@@ -0,0 +1,968 @@
|
||||
/* 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_os2.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "usb_device.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
//#include "madgwick.h"
|
||||
#include "MadgwickAHRS.h"
|
||||
#include "sensors.h"
|
||||
#include "bmm350.h"
|
||||
#include "bmm350_defs.h"
|
||||
#include "bmm350_oor.h"
|
||||
|
||||
// CDC functionality
|
||||
#include "usbd_cdc_if.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 ---------------------------------------------------------*/
|
||||
I2C_HandleTypeDef hi2c1;
|
||||
DMA_HandleTypeDef hdma_i2c1_tx;
|
||||
DMA_HandleTypeDef hdma_i2c1_rx;
|
||||
|
||||
IPCC_HandleTypeDef hipcc;
|
||||
|
||||
RTC_HandleTypeDef hrtc;
|
||||
|
||||
SPI_HandleTypeDef hspi1;
|
||||
SPI_HandleTypeDef hspi2;
|
||||
DMA_HandleTypeDef hdma_spi1_tx;
|
||||
DMA_HandleTypeDef hdma_spi1_rx;
|
||||
|
||||
TIM_HandleTypeDef htim2;
|
||||
|
||||
/* Definitions for Task_DataAnalys */
|
||||
osThreadId_t Task_DataAnalysHandle;
|
||||
const osThreadAttr_t Task_DataAnalys_attributes = {
|
||||
.name = "Task_DataAnalys",
|
||||
.priority = (osPriority_t) osPriorityNormal,
|
||||
.stack_size = 512 * 4
|
||||
};
|
||||
/* Definitions for Task_ICM45686 */
|
||||
osThreadId_t Task_ICM45686Handle;
|
||||
const osThreadAttr_t Task_ICM45686_attributes = {
|
||||
.name = "Task_ICM45686",
|
||||
.priority = (osPriority_t) osPriorityNormal,
|
||||
.stack_size = 512 * 4
|
||||
};
|
||||
/* Definitions for Task_BMM350 */
|
||||
osThreadId_t Task_BMM350Handle;
|
||||
const osThreadAttr_t Task_BMM350_attributes = {
|
||||
.name = "Task_BMM350",
|
||||
.priority = (osPriority_t) osPriorityNormal,
|
||||
.stack_size = 512 * 4
|
||||
};
|
||||
/* Definitions for Q_ICM */
|
||||
osMessageQueueId_t Q_ICMHandle;
|
||||
const osMessageQueueAttr_t Q_ICM_attributes = {
|
||||
.name = "Q_ICM"
|
||||
};
|
||||
/* Definitions for Q_BMM */
|
||||
osMessageQueueId_t Q_BMMHandle;
|
||||
const osMessageQueueAttr_t Q_BMM_attributes = {
|
||||
.name = "Q_BMM"
|
||||
};
|
||||
/* USER CODE BEGIN PV */
|
||||
//struct bmm350_dev dev = {0x00};
|
||||
//MadgwickFilter IMUQuat;
|
||||
MadgwickAHRS_Filter IMUQuat;
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
void SystemClock_Config(void);
|
||||
void PeriphCommonClock_Config(void);
|
||||
static void MX_GPIO_Init(void);
|
||||
static void MX_DMA_Init(void);
|
||||
static void MX_I2C1_Init(void);
|
||||
static void MX_SPI1_Init(void);
|
||||
static void MX_SPI2_Init(void);
|
||||
static void MX_TIM2_Init(void);
|
||||
static void MX_IPCC_Init(void);
|
||||
static void MX_RTC_Init(void);
|
||||
static void MX_RF_Init(void);
|
||||
void Start_DataAnalysis(void *argument);
|
||||
void Start_ICM45686(void *argument);
|
||||
void Start_BMM350(void *argument);
|
||||
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
// implementation of printf() functionality through ITM
|
||||
int _write(int file, char *prt, int len) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
ITM_SendChar(*prt++);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/* 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();
|
||||
/* Config code for STM32_WPAN (HSE Tuning must be done before system clock configuration) */
|
||||
MX_APPE_Config();
|
||||
|
||||
/* USER CODE BEGIN Init */
|
||||
|
||||
/* USER CODE END Init */
|
||||
|
||||
/* Configure the system clock */
|
||||
SystemClock_Config();
|
||||
|
||||
/* Configure the peripherals common clocks */
|
||||
PeriphCommonClock_Config();
|
||||
|
||||
/* IPCC initialisation */
|
||||
MX_IPCC_Init();
|
||||
|
||||
/* USER CODE BEGIN SysInit */
|
||||
|
||||
// Initialize DWT for the BMM350 delay function to work properly
|
||||
bmm_init_DWT();
|
||||
/* USER CODE END SysInit */
|
||||
|
||||
/* Initialize all configured peripherals */
|
||||
MX_GPIO_Init();
|
||||
MX_DMA_Init();
|
||||
MX_I2C1_Init();
|
||||
MX_SPI1_Init();
|
||||
MX_SPI2_Init();
|
||||
MX_TIM2_Init();
|
||||
MX_RTC_Init();
|
||||
MX_RF_Init();
|
||||
/* USER CODE BEGIN 2 */
|
||||
|
||||
/* USER CODE END 2 */
|
||||
|
||||
/* Init scheduler */
|
||||
osKernelInitialize();
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* Create the queue(s) */
|
||||
/* creation of Q_ICM */
|
||||
Q_ICMHandle = osMessageQueueNew (1, sizeof(ICM45686_Data), &Q_ICM_attributes);
|
||||
|
||||
/* creation of Q_BMM */
|
||||
Q_BMMHandle = osMessageQueueNew (1, sizeof(struct bmm350_mag_temp_data), &Q_BMM_attributes);
|
||||
|
||||
/* USER CODE BEGIN RTOS_QUEUES */
|
||||
/* add queues, ... */
|
||||
/* USER CODE END RTOS_QUEUES */
|
||||
|
||||
/* Create the thread(s) */
|
||||
/* creation of Task_DataAnalys */
|
||||
Task_DataAnalysHandle = osThreadNew(Start_DataAnalysis, NULL, &Task_DataAnalys_attributes);
|
||||
|
||||
/* creation of Task_ICM45686 */
|
||||
Task_ICM45686Handle = osThreadNew(Start_ICM45686, NULL, &Task_ICM45686_attributes);
|
||||
|
||||
/* creation of Task_BMM350 */
|
||||
Task_BMM350Handle = osThreadNew(Start_BMM350, NULL, &Task_BMM350_attributes);
|
||||
|
||||
/* USER CODE BEGIN RTOS_THREADS */
|
||||
/* add threads, ... */
|
||||
/* USER CODE END RTOS_THREADS */
|
||||
|
||||
/* USER CODE BEGIN RTOS_EVENTS */
|
||||
/* add events, ... */
|
||||
/* USER CODE END RTOS_EVENTS */
|
||||
|
||||
while(LL_HSEM_1StepLock(HSEM, CFG_HW_CLK48_CONFIG_SEMID));
|
||||
|
||||
/* Init code for STM32_WPAN */
|
||||
MX_APPE_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};
|
||||
|
||||
/** Configure LSE Drive Capability
|
||||
*/
|
||||
HAL_PWR_EnableBkUpAccess();
|
||||
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_MEDIUMHIGH);
|
||||
|
||||
/** Configure the main internal regulator output voltage
|
||||
*/
|
||||
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
|
||||
|
||||
/** Initializes the RCC Oscillators according to the specified parameters
|
||||
* in the RCC_OscInitTypeDef structure.
|
||||
*/
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI1
|
||||
|RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE
|
||||
|RCC_OSCILLATORTYPE_MSI;
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
|
||||
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
|
||||
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
|
||||
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
|
||||
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
|
||||
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
|
||||
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
|
||||
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
|
||||
RCC_OscInitStruct.PLL.PLLN = 32;
|
||||
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
|
||||
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
|
||||
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
|
||||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers
|
||||
*/
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK4|RCC_CLOCKTYPE_HCLK2
|
||||
|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_DIV1;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
||||
RCC_ClkInitStruct.AHBCLK2Divider = RCC_SYSCLK_DIV2;
|
||||
RCC_ClkInitStruct.AHBCLK4Divider = RCC_SYSCLK_DIV1;
|
||||
|
||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/** Enable MSI Auto calibration
|
||||
*/
|
||||
HAL_RCCEx_EnableMSIPLLMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Peripherals Common Clock Configuration
|
||||
* @retval None
|
||||
*/
|
||||
void PeriphCommonClock_Config(void)
|
||||
{
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
|
||||
|
||||
/** Initializes the peripherals clock
|
||||
*/
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SMPS|RCC_PERIPHCLK_RFWAKEUP;
|
||||
PeriphClkInitStruct.RFWakeUpClockSelection = RCC_RFWKPCLKSOURCE_HSE_DIV1024;
|
||||
PeriphClkInitStruct.SmpsClockSelection = RCC_SMPSCLKSOURCE_HSI;
|
||||
PeriphClkInitStruct.SmpsDivSelection = RCC_SMPSCLKDIV_RANGE1;
|
||||
|
||||
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN Smps */
|
||||
|
||||
/* USER CODE END Smps */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2C1 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static 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.Timing = 0x10B17DB5;
|
||||
hi2c1.Init.OwnAddress1 = 0;
|
||||
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
|
||||
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
|
||||
hi2c1.Init.OwnAddress2 = 0;
|
||||
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
|
||||
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
|
||||
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
|
||||
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/** Configure Analogue filter
|
||||
*/
|
||||
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/** Configure Digital filter
|
||||
*/
|
||||
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN I2C1_Init 2 */
|
||||
|
||||
/* USER CODE END I2C1_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IPCC Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_IPCC_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN IPCC_Init 0 */
|
||||
|
||||
/* USER CODE END IPCC_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN IPCC_Init 1 */
|
||||
|
||||
/* USER CODE END IPCC_Init 1 */
|
||||
hipcc.Instance = IPCC;
|
||||
if (HAL_IPCC_Init(&hipcc) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN IPCC_Init 2 */
|
||||
|
||||
/* USER CODE END IPCC_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RF Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_RF_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN RF_Init 0 */
|
||||
|
||||
/* USER CODE END RF_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN RF_Init 1 */
|
||||
|
||||
/* USER CODE END RF_Init 1 */
|
||||
/* USER CODE BEGIN RF_Init 2 */
|
||||
|
||||
/* USER CODE END RF_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTC Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_RTC_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN RTC_Init 0 */
|
||||
|
||||
/* USER CODE END RTC_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN RTC_Init 1 */
|
||||
|
||||
/* USER CODE END RTC_Init 1 */
|
||||
|
||||
/** Initialize RTC Only
|
||||
*/
|
||||
hrtc.Instance = RTC;
|
||||
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
|
||||
hrtc.Init.AsynchPrediv = CFG_RTC_ASYNCH_PRESCALER;
|
||||
hrtc.Init.SynchPrediv = CFG_RTC_SYNCH_PRESCALER;
|
||||
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
|
||||
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
|
||||
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
|
||||
hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
|
||||
if (HAL_RTC_Init(&hrtc) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/** Enable the WakeUp
|
||||
*/
|
||||
if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0, RTC_WAKEUPCLOCK_RTCCLK_DIV16) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN RTC_Init 2 */
|
||||
|
||||
/* USER CODE END RTC_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI1 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_SPI1_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN SPI1_Init 0 */
|
||||
|
||||
/* USER CODE END SPI1_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN SPI1_Init 1 */
|
||||
|
||||
/* USER CODE END SPI1_Init 1 */
|
||||
/* SPI1 parameter configuration*/
|
||||
hspi1.Instance = SPI1;
|
||||
hspi1.Init.Mode = SPI_MODE_MASTER;
|
||||
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
|
||||
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
|
||||
hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
|
||||
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
|
||||
hspi1.Init.NSS = SPI_NSS_SOFT;
|
||||
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
|
||||
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
|
||||
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
|
||||
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
|
||||
hspi1.Init.CRCPolynomial = 7;
|
||||
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
|
||||
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
|
||||
if (HAL_SPI_Init(&hspi1) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN SPI1_Init 2 */
|
||||
|
||||
/* USER CODE END SPI1_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI2 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_SPI2_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN SPI2_Init 0 */
|
||||
|
||||
/* USER CODE END SPI2_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN SPI2_Init 1 */
|
||||
|
||||
/* USER CODE END SPI2_Init 1 */
|
||||
/* SPI2 parameter configuration*/
|
||||
hspi2.Instance = SPI2;
|
||||
hspi2.Init.Mode = SPI_MODE_MASTER;
|
||||
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
|
||||
hspi2.Init.DataSize = SPI_DATASIZE_4BIT;
|
||||
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
|
||||
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
|
||||
hspi2.Init.NSS = SPI_NSS_SOFT;
|
||||
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
|
||||
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
|
||||
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
|
||||
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
|
||||
hspi2.Init.CRCPolynomial = 7;
|
||||
hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
|
||||
hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
|
||||
if (HAL_SPI_Init(&hspi2) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN SPI2_Init 2 */
|
||||
|
||||
/* USER CODE END SPI2_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TIM2 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_TIM2_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN TIM2_Init 0 */
|
||||
|
||||
/* USER CODE END TIM2_Init 0 */
|
||||
|
||||
TIM_MasterConfigTypeDef sMasterConfig = {0};
|
||||
TIM_OC_InitTypeDef sConfigOC = {0};
|
||||
|
||||
/* USER CODE BEGIN TIM2_Init 1 */
|
||||
|
||||
/* USER CODE END TIM2_Init 1 */
|
||||
htim2.Instance = TIM2;
|
||||
htim2.Init.Prescaler = 63;
|
||||
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
htim2.Init.Period = 999;
|
||||
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
|
||||
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
|
||||
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
sConfigOC.OCMode = TIM_OCMODE_PWM1;
|
||||
sConfigOC.Pulse = 0;
|
||||
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
|
||||
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
|
||||
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN TIM2_Init 2 */
|
||||
|
||||
/* USER CODE END TIM2_Init 2 */
|
||||
HAL_TIM_MspPostInit(&htim2);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable DMA controller clock
|
||||
*/
|
||||
static void MX_DMA_Init(void)
|
||||
{
|
||||
|
||||
/* DMA controller clock enable */
|
||||
__HAL_RCC_DMAMUX1_CLK_ENABLE();
|
||||
__HAL_RCC_DMA1_CLK_ENABLE();
|
||||
|
||||
/* DMA interrupt init */
|
||||
/* DMA1_Channel1_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
|
||||
/* DMA1_Channel2_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
|
||||
/* DMA1_Channel3_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
|
||||
/* DMA1_Channel4_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPIO Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_GPIO_Init(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
/* USER CODE BEGIN MX_GPIO_Init_1 */
|
||||
|
||||
/* USER CODE END MX_GPIO_Init_1 */
|
||||
|
||||
/* GPIO Ports Clock Enable */
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(GPIO_SPI1_IMU_CS_GPIO_Port, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_SET);
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(GPIOC, GPIO_SPI2_SD_CD_Pin|GPIO_SPI2_SD_CS_Pin, GPIO_PIN_SET);
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(GPIO_SD_LDO_EN_GPIO_Port, GPIO_SD_LDO_EN_Pin, GPIO_PIN_RESET);
|
||||
|
||||
/*Configure GPIO pin : GPIO_SPI1_IMU_CS_Pin */
|
||||
GPIO_InitStruct.Pin = GPIO_SPI1_IMU_CS_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
HAL_GPIO_Init(GPIO_SPI1_IMU_CS_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pins : GPIO_SPI2_SD_CD_Pin GPIO_SPI2_SD_CS_Pin GPIO_SD_LDO_EN_Pin */
|
||||
GPIO_InitStruct.Pin = GPIO_SPI2_SD_CD_Pin|GPIO_SPI2_SD_CS_Pin|GPIO_SD_LDO_EN_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pin : GPIO_IMU_INT_Pin */
|
||||
GPIO_InitStruct.Pin = GPIO_IMU_INT_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(GPIO_IMU_INT_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pin : GPIO_MAGN_INT_Pin */
|
||||
GPIO_InitStruct.Pin = GPIO_MAGN_INT_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(GPIO_MAGN_INT_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN MX_GPIO_Init_2 */
|
||||
|
||||
/* USER CODE END MX_GPIO_Init_2 */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 4 */
|
||||
|
||||
/* USER CODE END 4 */
|
||||
|
||||
/* USER CODE BEGIN Header_Start_DataAnalysis */
|
||||
/**
|
||||
* @brief Function implementing the Task_DataAnalys thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_Start_DataAnalysis */
|
||||
void Start_DataAnalysis(void *argument)
|
||||
{
|
||||
/* init code for USB_Device */
|
||||
MX_USB_Device_Init();
|
||||
/* USER CODE BEGIN 5 */
|
||||
// HAL_StatusTypeDef status;
|
||||
// char output_buffer[128];
|
||||
ICM45686_Data imu_data;
|
||||
struct bmm350_mag_temp_data magn_data;
|
||||
// struct bmm350_raw_mag_data magn_data;
|
||||
QuaternionData Quat_Dat;
|
||||
Quat_Dat.StartByte = PACKET_START_BYTE;
|
||||
Quat_Dat.SensorAddress = BMM350_I2C_ADSEL_SET_LOW;
|
||||
Quat_Dat.EndByte = PACKET_END_BYTE;
|
||||
|
||||
MadgwickAHRS_init(&IMUQuat, 6400.0f, 0.15f);
|
||||
|
||||
/* Infinite loop */
|
||||
for(;;)
|
||||
{
|
||||
|
||||
osMessageQueueGet(Q_BMMHandle, &magn_data, NULL, osWaitForever);
|
||||
osMessageQueueGet(Q_ICMHandle, &imu_data, NULL, osWaitForever);
|
||||
|
||||
// MadgwickAHRS_update(&IMUQuat, imu_data.processed_imu_data[3], imu_data.processed_imu_data[4], imu_data.processed_imu_data[5], //gx, gy, gz
|
||||
// imu_data.processed_imu_data[0], imu_data.processed_imu_data[1], imu_data.processed_imu_data[2], // ax, ay, yz
|
||||
// magn_data.x, magn_data.y, magn_data.z); // mx, my, mz
|
||||
|
||||
MadgwickAHRS_update_IMU(&IMUQuat, imu_data.processed_imu_data[3], imu_data.processed_imu_data[4], imu_data.processed_imu_data[5], //gx, gy, gz
|
||||
imu_data.processed_imu_data[0], imu_data.processed_imu_data[1], imu_data.processed_imu_data[2]); // ax, ay, yz)
|
||||
|
||||
|
||||
Quat_Dat.qw = IMUQuat.q[0];
|
||||
Quat_Dat.qx = IMUQuat.q[1];
|
||||
Quat_Dat.qy = IMUQuat.q[2];
|
||||
Quat_Dat.qz = IMUQuat.q[3];
|
||||
|
||||
CDC_Transmit_FS((uint8_t*)&Quat_Dat, sizeof(Quat_Dat));
|
||||
|
||||
// DEBUG
|
||||
// sprintf(output_buffer, "------------\n");
|
||||
// CDC_Transmit_FS((uint8_t*)output_buffer, (uint16_t)strlen(output_buffer));
|
||||
//
|
||||
// sprintf(output_buffer, "IMUQuat:\tqw: %.2f, qx: %.2f, qy: %.2f, qz: %.2f\n",
|
||||
// IMUQuat.q[0], IMUQuat.q[1], IMUQuat.q[2], IMUQuat.q[3]);
|
||||
// CDC_Transmit_FS((uint8_t*)output_buffer, (uint16_t)strlen(output_buffer));
|
||||
|
||||
// sprintf(output_buffer, "ICM:\ta_x: %.2f a_y: %.2f a_z: %.2f\t g_x: %.2f g_y: %.2f g_z: %.2f temp: %.2f \n", imu_data.processed_imu_data[0], imu_data.processed_imu_data[1], imu_data.processed_imu_data[2],
|
||||
// imu_data.processed_imu_data[3], imu_data.processed_imu_data[4], imu_data.processed_imu_data[5], imu_data.processed_imu_data[6]);
|
||||
// CDC_Transmit_FS((uint8_t*)output_buffer, (uint16_t)strlen(output_buffer));
|
||||
//
|
||||
// // compensated mag data
|
||||
// sprintf(output_buffer, "BMM:\tX: %.2f uT, Y: %.2f uT, Z: %.2f uT, Temp: %.2f C\n",
|
||||
// magn_data.x, magn_data.y, magn_data.z, magn_data.temperature);
|
||||
// CDC_Transmit_FS((uint8_t*)output_buffer, (uint16_t)strlen(output_buffer));
|
||||
//// // raw mag data
|
||||
//// sprintf(output_buffer, "BMM:\tX: %.2f uT, Y: %.2f uT, Z: %.2f uT, Temp: %.2f C\n",
|
||||
//// magn_data.raw_xdata, magn_data.raw_ydata, magn_data.raw_zdata, magn_data.raw_data_t);
|
||||
//// CDC_Transmit_FS((uint8_t*)output_buffer, (uint16_t)strlen(output_buffer));
|
||||
//
|
||||
// sprintf(output_buffer, "Quaternion:\tqw: %.2f, qx: %.2f, qy: %.2f, qz: %.2f\n",
|
||||
// Quat_Dat.qw, Quat_Dat.qx, Quat_Dat.qy, Quat_Dat.qz);
|
||||
// CDC_Transmit_FS((uint8_t*)output_buffer, (uint16_t)strlen(output_buffer));
|
||||
//
|
||||
// sprintf(output_buffer, "------------\n");
|
||||
// CDC_Transmit_FS((uint8_t*)output_buffer, (uint16_t)strlen(output_buffer));
|
||||
osDelay(100);
|
||||
}
|
||||
|
||||
/* USER CODE END 5 */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Header_Start_ICM45686 */
|
||||
/**
|
||||
* @brief Function implementing the Task_ICM45686 thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_Start_ICM45686 */
|
||||
void Start_ICM45686(void *argument)
|
||||
{
|
||||
/* USER CODE BEGIN Start_ICM45686 */
|
||||
HAL_StatusTypeDef status;
|
||||
// char output_buffer[128];
|
||||
xIMU_Task = osThreadGetId();
|
||||
// ICM
|
||||
//uint8_t usb_response;
|
||||
uint8_t raw_imu_data[15];
|
||||
int16_t imu_sensor_data[7];
|
||||
ICM45686_Data processed_data;
|
||||
|
||||
ICM45686_HandleTypeDef imu;
|
||||
imu.hspi = &hspi1;
|
||||
imu.GPIO_Port = GPIO_SPI1_IMU_CS_GPIO_Port;
|
||||
imu.GPIO_Pin = GPIO_SPI1_IMU_CS_Pin;
|
||||
imu.acc_fs = ICM45686_ACC_FS_4G;
|
||||
imu.acc_ssf = ICM45686_ACC_SSF[ICM45686_ACC_FS_4G >> 4];
|
||||
imu.gyro_fs = ICM45686_GYRO_FS_250DPS;
|
||||
imu.gyro_ssf = ICM45686_GYRO_SSF[ICM45686_GYRO_FS_250DPS >> 4];
|
||||
imu.odr = ICM45686_ODR_6_4kHz_LN ;
|
||||
|
||||
uint8_t tx[15] = {0x00};
|
||||
tx[0] = 0x00 | 0x80;
|
||||
|
||||
init_icm(&imu);
|
||||
// calibrate_icm(&imu, 1000);
|
||||
/* Infinite loop */
|
||||
for(;;)
|
||||
{
|
||||
// imu
|
||||
// HAL_GPIO_WritePin(GPIOA, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_RESET);
|
||||
// status = HAL_SPI_TransmitReceive_DMA(&hspi1, tx, raw_imu_data, sizeof(raw_imu_data)); //(&hspi1, tx, raw_imu_data, sizeof(raw_imu_data), 50);
|
||||
status = read_icm_dma(&imu, tx, raw_imu_data);
|
||||
if (status != HAL_OK) {
|
||||
printf("Reading IMU sensordata failed: %d\n", status);
|
||||
}
|
||||
|
||||
imu_sensor_data[0] = (int16_t)(raw_imu_data[1] << 8 | raw_imu_data[2]); // a_x
|
||||
imu_sensor_data[1] = (int16_t)(raw_imu_data[3] << 8 | raw_imu_data[4]); // a_y
|
||||
imu_sensor_data[2] = (int16_t)(raw_imu_data[5] << 8 | raw_imu_data[6]); // a_z
|
||||
imu_sensor_data[3] = (int16_t)(raw_imu_data[7] << 8 | raw_imu_data[8]); // g_x
|
||||
imu_sensor_data[4] = (int16_t)(raw_imu_data[9] << 8 | raw_imu_data[10]); // g_y
|
||||
imu_sensor_data[5] = (int16_t)(raw_imu_data[11] << 8 | raw_imu_data[12]); // g_z
|
||||
imu_sensor_data[6] = (int16_t)(raw_imu_data[13] << 8 | raw_imu_data[14]); // t
|
||||
|
||||
processed_data.processed_imu_data[0] = (float)imu_sensor_data[0] / (float)imu.acc_fs;
|
||||
processed_data.processed_imu_data[1] = (float)imu_sensor_data[1] / (float)imu.acc_fs;
|
||||
processed_data.processed_imu_data[2] = (float)imu_sensor_data[2] / (float)imu.acc_fs;
|
||||
processed_data.processed_imu_data[3] = (float)imu_sensor_data[3] / (float)imu.gyro_ssf;
|
||||
processed_data.processed_imu_data[4] = (float)imu_sensor_data[4] / (float)imu.gyro_ssf;
|
||||
processed_data.processed_imu_data[5] = (float)imu_sensor_data[5] / (float)imu.gyro_ssf;
|
||||
processed_data.processed_imu_data[6] = (float)(imu_sensor_data[6] / 128.0 + 25.0);
|
||||
|
||||
if (imu.calibated) {
|
||||
processed_data.processed_imu_data[0] -= imu.imu_bias[0];
|
||||
processed_data.processed_imu_data[1] -= imu.imu_bias[1];
|
||||
processed_data.processed_imu_data[2] -= imu.imu_bias[2];
|
||||
processed_data.processed_imu_data[3] -= imu.imu_bias[3];
|
||||
processed_data.processed_imu_data[4] -= imu.imu_bias[4];
|
||||
processed_data.processed_imu_data[5] -= imu.imu_bias[5];
|
||||
processed_data.processed_imu_data[6] -= imu.imu_bias[7];
|
||||
|
||||
}
|
||||
// printf("[0]: %.2f [3]: %.2f [6]: %.2f\n", processed_data.processed_imu_data[0], processed_data.processed_imu_data[3], processed_data.processed_imu_data[6]);
|
||||
|
||||
osMessageQueuePut(Q_ICMHandle, &processed_data, 0, 5);
|
||||
osDelay(100);
|
||||
|
||||
|
||||
}
|
||||
/* USER CODE END Start_ICM45686 */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Header_Start_BMM350 */
|
||||
/**
|
||||
* @brief Function implementing the Task_BMM350 thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_Start_BMM350 */
|
||||
void Start_BMM350(void *argument)
|
||||
{
|
||||
/* USER CODE BEGIN Start_BMM350 */
|
||||
// HAL_StatusTypeDef status;
|
||||
// char output_buffer[128];
|
||||
xMagn_Task = osThreadGetId();
|
||||
// BMM
|
||||
struct bmm350_dev dev = {0x00};
|
||||
int8_t rslt;
|
||||
struct bmm350_mag_temp_data mag_data;
|
||||
osDelay(250);
|
||||
// struct bmm350_raw_mag_data mag_data;
|
||||
|
||||
// struct bmm350_mag_temp_data mag_temp_data;
|
||||
// struct bmm350_pmu_cmd_status_0 pmu_cmd_stat_0;
|
||||
|
||||
// ODR: 200HZ, AVG:
|
||||
rslt = init_bmm(&dev);
|
||||
if (rslt != BMM350_OK) {
|
||||
printf("BMM350 initialization failed: %d\n", rslt);
|
||||
printf("Chip id: 0x%02X\n", dev.chip_id);
|
||||
}
|
||||
/* Infinite loop */
|
||||
for(;;)
|
||||
{
|
||||
// magnetometer
|
||||
rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_data, &dev);
|
||||
// rslt = bmm350_read_uncomp_mag_temp_data(&mag_data, &dev);
|
||||
if (rslt == BMM350_OK)
|
||||
{
|
||||
// sprintf(output_buffer, "X: %.2f uT, Y: %.2f uT, Z: %.2f uT, Temp: %.2f C\n",
|
||||
// mag_data.x, mag_data.y, mag_data.z, mag_data.temperature);
|
||||
// CDC_Transmit_FS((uint8_t*)output_buffer, (uint16_t)strlen(output_buffer));
|
||||
osMessageQueuePut(Q_BMMHandle, &mag_data, 0, 5);
|
||||
}
|
||||
|
||||
osDelay(100);
|
||||
|
||||
|
||||
}
|
||||
/* USER CODE END Start_BMM350 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Period elapsed callback in non blocking mode
|
||||
* @note This function is called when TIM16 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 == TIM16)
|
||||
{
|
||||
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 */
|
||||
@@ -0,0 +1,305 @@
|
||||
#include "main.h"
|
||||
#include "sensors.h"
|
||||
//#include "stm32wbxx_hal_i2c.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "cmsis_os2.h"
|
||||
#include "task.h"
|
||||
|
||||
#define HAL_I2C_TIMEOUT 100
|
||||
//extern osThreadId_t defaultTaskHandle;
|
||||
//TaskHandle_t xStartDefaultTask = NULL;
|
||||
//extern osThreadId_t defaultTaskHandle
|
||||
osThreadId_t xIMU_Task = NULL;
|
||||
osThreadId_t xMagn_Task = NULL;
|
||||
//osThreadId_t xData_Task = NULL;
|
||||
|
||||
|
||||
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) {
|
||||
if (hspi->Instance == SPI1) {
|
||||
HAL_GPIO_WritePin(GPIOA, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_SET);
|
||||
|
||||
// notify the task that the data is ready
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
vTaskNotifyGiveFromISR(xIMU_Task, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *I2C_address) {
|
||||
// printf("HAL_I2C_MemRxCpltCallback");
|
||||
if (I2C_address->Instance == I2C1) {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
vTaskNotifyGiveFromISR(xMagn_Task, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
}
|
||||
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *I2C_address) {
|
||||
// printf("HAL_I2C_MemTxCpltCallback");
|
||||
if (I2C_address->Instance == I2C1) {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
vTaskNotifyGiveFromISR(xMagn_Task, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) {
|
||||
if (hi2c->Instance == I2C1) {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
printf("ErrorCallback: %ld", HAL_I2C_GetError(hi2c));
|
||||
vTaskNotifyGiveFromISR(xMagn_Task, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
|
||||
// ICM 45686
|
||||
HAL_StatusTypeDef read_icm (ICM45686_HandleTypeDef *imu, uint8_t tx[], uint8_t rx[]) {
|
||||
HAL_GPIO_WritePin(imu->GPIO_Port, imu->GPIO_Pin, GPIO_PIN_RESET);
|
||||
HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(imu->hspi, tx, rx, sizeof(tx), 50);
|
||||
HAL_GPIO_WritePin(imu->GPIO_Port, imu->GPIO_Pin, GPIO_PIN_SET);
|
||||
return status;
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef read_icm_dma (ICM45686_HandleTypeDef *imu, uint8_t tx[], uint8_t rx[]) {
|
||||
HAL_GPIO_WritePin(imu->GPIO_Port, imu->GPIO_Pin, GPIO_PIN_RESET);
|
||||
HAL_StatusTypeDef status = HAL_SPI_TransmitReceive_DMA(imu->hspi, tx, rx, sizeof(rx));
|
||||
return status;
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef write_icm (ICM45686_HandleTypeDef *imu, uint8_t tx[]) {
|
||||
HAL_GPIO_WritePin(imu->GPIO_Port, imu->GPIO_Pin, GPIO_PIN_RESET);
|
||||
HAL_StatusTypeDef status = HAL_SPI_Transmit(imu->hspi, tx, sizeof(tx), 50);
|
||||
HAL_GPIO_WritePin(imu->GPIO_Port, imu->GPIO_Pin, GPIO_PIN_SET);
|
||||
return status;
|
||||
}
|
||||
|
||||
void init_icm(ICM45686_HandleTypeDef *imu) {
|
||||
// TODO: Add settings as enum to choose from
|
||||
// FIFO
|
||||
// Interrupt
|
||||
// APEX???
|
||||
// EDMP???
|
||||
|
||||
uint8_t tx[2], rx[2];
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
printf("Initializing ICM45686\n");
|
||||
// WHO AM
|
||||
tx[0] = ICM45686_WHO_AM_I | 0x80;
|
||||
// HAL_GPIO_WritePin(imu->GPIO_Port, imu->GPIO_Pin, GPIO_PIN_RESET);
|
||||
// status = HAL_SPI_TransmitReceive(imu->hspi, tx, rx, sizeof(tx), 50);
|
||||
// HAL_GPIO_WritePin(GPIOA, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_SET);
|
||||
status = read_icm(imu, tx, rx);
|
||||
if (status != HAL_OK) {
|
||||
printf("Error in reading WHO AM I:%d\n", status);
|
||||
} else {
|
||||
printf("WHO AM I (0xE9): 0x%02X \n", rx[1]);
|
||||
}
|
||||
|
||||
// acc
|
||||
tx[0] = ICM45686_ACCEL_CONFIG0;
|
||||
tx[1] = imu->acc_fs | imu->odr;
|
||||
// HAL_GPIO_WritePin(GPIOA, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_RESET);
|
||||
// status = HAL_SPI_Transmit(imu->hspi, tx, sizeof(tx), 50);
|
||||
// HAL_GPIO_WritePin(GPIOA, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_SET);
|
||||
status = write_icm(imu, tx);
|
||||
if (status != HAL_OK) {
|
||||
printf("Error in setting ACCEL_CONFIG0:%d\n", status);
|
||||
} else {
|
||||
printf("ACCEL_CONFIG0 wrote: 0x%02X \n", tx[1]);
|
||||
}
|
||||
|
||||
tx[0] = ICM45686_ACCEL_CONFIG0 | 0x80;
|
||||
tx[1] = 0x00;
|
||||
// HAL_GPIO_WritePin(GPIOA, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_RESET);
|
||||
// status = HAL_SPI_TransmitReceive(imu->hspi, tx, rx, sizeof(tx), 50);
|
||||
// HAL_GPIO_WritePin(GPIOA, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_SET);
|
||||
status = read_icm(imu, tx, rx);
|
||||
if (status != HAL_OK) {
|
||||
printf("Error reading ACCEL_CONFIG0:%d\n", status);
|
||||
} else {
|
||||
printf("ACCEL_CONFIG0 read: 0x%02X \n", rx[1]);
|
||||
}
|
||||
|
||||
// gyro
|
||||
tx[0] = ICM45686_GYRO_CONFIG0;
|
||||
tx[1] = imu->gyro_fs | imu->odr;
|
||||
// HAL_GPIO_WritePin(GPIOA, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_RESET);
|
||||
// status = HAL_SPI_Transmit(imu->hspi, tx, sizeof(tx), 50);
|
||||
// HAL_GPIO_WritePin(GPIOA, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_SET);
|
||||
status = write_icm(imu, tx);
|
||||
if (status != HAL_OK) {
|
||||
printf("Error in setting GYRO_CONFIG0:%d\n", status);
|
||||
} else {
|
||||
printf("GYRO_CONFIG0 wrote: 0x%02X \n", tx[1]);
|
||||
}
|
||||
|
||||
tx[0] = ICM45686_GYRO_CONFIG0 | 0x80;
|
||||
tx[1] = 0x00;
|
||||
// HAL_GPIO_WritePin(GPIOA, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_RESET);
|
||||
// status = HAL_SPI_TransmitReceive(imu->hspi, tx, rx, sizeof(tx), 50);
|
||||
// HAL_GPIO_WritePin(GPIOA, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_SET);
|
||||
status = read_icm(imu, tx, rx);
|
||||
if (status != HAL_OK) {
|
||||
printf("Error reading GYRO_CONFIG0:%d\n", status);
|
||||
} else {
|
||||
printf("GYRO_CONFIG0 read: 0x%02X \n", rx[1]);
|
||||
}
|
||||
|
||||
// power settings
|
||||
tx[0] = ICM45686_PWR_MGMT0;
|
||||
tx[1] = 0x0F; //0x10 | 0x03;
|
||||
// HAL_GPIO_WritePin(GPIOA, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_RESET);
|
||||
// status = HAL_SPI_Transmit(imu->hspi, tx, sizeof(tx), 50);
|
||||
// HAL_GPIO_WritePin(GPIOA, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_SET);
|
||||
status = write_icm(imu, tx);
|
||||
if (status != HAL_OK) {
|
||||
printf("Error in setting PWR_MGMT0:%d\n", status);
|
||||
} else {
|
||||
printf("PWR_MGMT0 wrote: 0x%02X \n", tx[1]);
|
||||
}
|
||||
|
||||
tx[0] = ICM45686_PWR_MGMT0 | 0x80;
|
||||
tx[1] = 0x00;
|
||||
// HAL_GPIO_WritePin(GPIOA, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_RESET);
|
||||
// status = HAL_SPI_TransmitReceive(imu->hspi, tx, rx, sizeof(tx), 50);
|
||||
// HAL_GPIO_WritePin(GPIOA, GPIO_SPI1_IMU_CS_Pin, GPIO_PIN_SET);
|
||||
status = read_icm(imu, tx, rx);
|
||||
if (status != HAL_OK) {
|
||||
printf("Error reading PWR_MGMT0:%d\n", status);
|
||||
} else {
|
||||
printf("PWR_MGMT0 read: 0x%02X \n", rx[1]);
|
||||
}
|
||||
|
||||
osDelay(250);
|
||||
}
|
||||
|
||||
void calibrate_icm(ICM45686_HandleTypeDef *imu, int samples) {
|
||||
HAL_StatusTypeDef status;
|
||||
uint8_t raw_data[15];
|
||||
int16_t sensor_data[7] = {0};
|
||||
uint8_t tx[15] = {0x00};
|
||||
tx[0] = 0x00 | 0x80;
|
||||
|
||||
for (int i = 1; i <= samples; i++) {
|
||||
status = read_icm_dma(imu, tx, raw_data);
|
||||
if (status != HAL_OK) {
|
||||
printf("Calibration read ICM failed: %d\n", status);
|
||||
}
|
||||
sensor_data[0] += (int16_t)(raw_data[1] << 8 | raw_data[2]); // a_x
|
||||
sensor_data[1] += (int16_t)(raw_data[3] << 8 | raw_data[4]); // a_y
|
||||
sensor_data[2] += (int16_t)(raw_data[5] << 8 | raw_data[6]); // a_z
|
||||
sensor_data[3] += (int16_t)(raw_data[7] << 8 | raw_data[8]); // g_x
|
||||
sensor_data[4] += (int16_t)(raw_data[9] << 8 | raw_data[10]); // g_y
|
||||
sensor_data[5] += (int16_t)(raw_data[11] << 8 | raw_data[12]); // g_z
|
||||
sensor_data[6] += (int16_t)(raw_data[13] << 8 | raw_data[14]); // t
|
||||
}
|
||||
|
||||
imu->imu_bias[0] = (float)sensor_data[0] / (float)samples;
|
||||
imu->imu_bias[1] = (float)sensor_data[1] / (float)samples;
|
||||
imu->imu_bias[2] = (float)sensor_data[2] / (float)samples;
|
||||
imu->imu_bias[3] = (float)sensor_data[3] / (float)samples;
|
||||
imu->imu_bias[4] = (float)sensor_data[4] / (float)samples;
|
||||
imu->imu_bias[5] = (float)sensor_data[5] / (float)samples;
|
||||
imu->imu_bias[6] = (float)sensor_data[6] / (float)samples;
|
||||
|
||||
// remrove gravity
|
||||
imu->imu_bias[2] -= 1.0f;
|
||||
|
||||
imu->calibated = true;
|
||||
|
||||
printf("Calibration finished of ICM45686\n");
|
||||
printf("a_x: %.2f a_y: %.2f a_z: %.2f g_x: %.2f g_y: %.2f g_z: %.2f t: %.2f\n",
|
||||
imu->imu_bias[0], imu->imu_bias[1], imu->imu_bias[2],
|
||||
imu->imu_bias[3], imu->imu_bias[4], imu->imu_bias[5],
|
||||
imu->imu_bias[6]);
|
||||
|
||||
}
|
||||
|
||||
// BMM350
|
||||
void bmm_init_DWT(void){
|
||||
// Enable trace and debug block (TRCENA)
|
||||
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||
|
||||
// Reset cycle counter
|
||||
DWT->CYCCNT = 0;
|
||||
|
||||
// Enable the cycle counter
|
||||
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
|
||||
}
|
||||
|
||||
BMM350_INTF_RET_TYPE bmm350_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr){
|
||||
// Extract I2C device address from intf_ptr
|
||||
uint8_t device_addr = *(uint8_t*)intf_ptr;
|
||||
|
||||
// STM32 HAL: Write register address, then read data
|
||||
// Device address is left-shifted by 1 for STM32 HAL
|
||||
// if (HAL_I2C_Mem_Read(&hi2c1, device_addr << 1, reg_addr, I2C_MEMADD_SIZE_8BIT, reg_data, length, HAL_I2C_TIMEOUT ) == HAL_OK) {
|
||||
if (HAL_I2C_Mem_Read_DMA(&hi2c1, device_addr << 1, reg_addr, I2C_MEMADD_SIZE_8BIT, reg_data, length) == HAL_OK) {
|
||||
if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(10)) == pdTRUE) {
|
||||
return BMM350_INTF_RET_SUCCESS; // 0
|
||||
}
|
||||
}
|
||||
return -1; // Communication failure
|
||||
|
||||
}
|
||||
|
||||
BMM350_INTF_RET_TYPE bmm350_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr){
|
||||
uint8_t device_addr = *(uint8_t*)intf_ptr;
|
||||
// uint8_t rslt = HAL_I2C_Mem_Write_DMA(&hi2c1, device_addr << 1, reg_addr, I2C_MEMADD_SIZE_8BIT, (uint8_t*)reg_data, length);
|
||||
// printf("rslt write: %d\n", rslt);
|
||||
// // STM32 HAL: Write register address + data
|
||||
if (HAL_I2C_Mem_Write_DMA(&hi2c1, device_addr << 1, reg_addr, I2C_MEMADD_SIZE_8BIT, (uint8_t*)reg_data, length) == HAL_OK) {
|
||||
// if (HAL_I2C_Mem_Write(&hi2c1, device_addr << 1, reg_addr, I2C_MEMADD_SIZE_8BIT, (uint8_t*)reg_data, length, HAL_I2C_TIMEOUT ) == HAL_OK) {
|
||||
// if (rslt == HAL_OK) {
|
||||
if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(10)) == pdTRUE) {
|
||||
return BMM350_INTF_RET_SUCCESS; // 0
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void bmm350_delay(uint32_t period_us, void *intf_ptr){
|
||||
(void)intf_ptr; // Unused
|
||||
|
||||
// For STM32, use DWT cycle counter for accurate microsecond delays
|
||||
uint32_t start = DWT->CYCCNT;
|
||||
uint32_t cycles = period_us * (SystemCoreClock / 1000000);
|
||||
|
||||
while ((DWT->CYCCNT - start) < cycles);
|
||||
}
|
||||
|
||||
// Initialization function
|
||||
int8_t init_bmm(struct bmm350_dev *dev) {
|
||||
int8_t rslt;
|
||||
|
||||
// Static variable to hold I2C device address
|
||||
// Must be static or global because dev.intf_ptr will point to it
|
||||
static uint8_t dev_addr = BMM350_I2C_ADSEL_SET_LOW;
|
||||
// Assign function pointers
|
||||
dev->read = bmm350_i2c_read;
|
||||
dev->write = bmm350_i2c_write;
|
||||
dev->delay_us = bmm350_delay;
|
||||
dev->intf_ptr = &dev_addr;
|
||||
|
||||
printf("Starting up and configuring BMM350\n");
|
||||
|
||||
// Initialize BMM350 driver
|
||||
rslt = bmm350_init(dev);
|
||||
if (rslt != BMM350_OK)
|
||||
{
|
||||
// Handle error: chip ID mismatch, communication failure, etc.
|
||||
return rslt;
|
||||
}
|
||||
printf("Initialization: %d\n", rslt);
|
||||
printf("CHIP_ID (should be 0x33) - Read Register: 0x00 BMM350 Chip ID: 0x%X\n", dev->chip_id);
|
||||
|
||||
// Set powermode, odr and avg
|
||||
rslt = bmm350_set_powermode(BMM350_NORMAL_MODE, dev);
|
||||
printf("Powermode (%d): %d\n", BMM350_NORMAL_MODE, rslt);
|
||||
rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_200HZ, BMM350_AVERAGING_2, dev);
|
||||
printf("ODR(%d) and AVG(%d): %d\n", BMM350_DATA_RATE_200HZ, BMM350_AVERAGING_2, rslt);
|
||||
|
||||
return BMM350_OK;
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
#include "main.h"
|
||||
#include <stdbool.h>
|
||||
#include "bmm350.h"
|
||||
#include "bmm350_defs.h"
|
||||
#include "bmm350_oor.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "cmsis_os2.h"
|
||||
|
||||
|
||||
// I2C Handle
|
||||
extern I2C_HandleTypeDef hi2c1;
|
||||
extern osThreadId_t defaultTaskHandle;
|
||||
extern osThreadId_t xIMU_Task;
|
||||
extern osThreadId_t xMagn_Task;
|
||||
//extern osThreadId_t xData_Task;
|
||||
|
||||
// ICM45686
|
||||
typedef struct {
|
||||
SPI_HandleTypeDef *hspi;
|
||||
GPIO_TypeDef *GPIO_Port;
|
||||
uint16_t GPIO_Pin;
|
||||
|
||||
uint8_t acc_fs;
|
||||
uint8_t gyro_fs;
|
||||
uint8_t odr;
|
||||
float acc_ssf;
|
||||
float gyro_ssf;
|
||||
|
||||
bool calibated;
|
||||
// float accel_bias[3];
|
||||
// float gyro_bias[3];
|
||||
float imu_bias[7];
|
||||
} ICM45686_HandleTypeDef;
|
||||
|
||||
typedef struct {
|
||||
float processed_imu_data[7];
|
||||
} ICM45686_Data;
|
||||
|
||||
// dataframe for sending quaternions over usb
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t StartByte;
|
||||
uint8_t SensorAddress;
|
||||
float qw;
|
||||
float qx;
|
||||
float qy;
|
||||
float qz;
|
||||
uint8_t EndByte;
|
||||
} QuaternionData;
|
||||
|
||||
// enum to hold the packet dataframe data
|
||||
typedef enum {
|
||||
PACKET_START_BYTE = 0xDE,
|
||||
PACKET_END_BYTE = 0xAD
|
||||
} Packet_Bytes;
|
||||
|
||||
|
||||
typedef enum {
|
||||
ICM45686_WHO_AM_I = 0x72, // 0x72 = 01110010, dann den wert NIX(???)) einfach nur lesen
|
||||
ICM45686_ACCEL_CONFIG0 = 0x1B,
|
||||
ICM45686_GYRO_CONFIG0 = 0x1C,
|
||||
ICM45686_FIFO_CONFIG0 = 0x1D,
|
||||
ICM45686_PWR_MGMT0 = 0x10,
|
||||
ICM45686_ODR_DECIMATE_CONFIG = 0x40,
|
||||
ICM45686_ACCEL_DATA = 0x00,
|
||||
ICM45686_GYRO_DATA = 0x06,
|
||||
ICM45686_FIFO_COUNT = 0x12,
|
||||
ICM45686_FIFO_DATA = 0x14
|
||||
} ICM45686_registers;
|
||||
|
||||
typedef enum {
|
||||
ICM45686_ACC_FS_32G = 0x00,
|
||||
ICM45686_ACC_FS_16G = 0x10,
|
||||
ICM45686_ACC_FS_8G = 0x20,
|
||||
ICM45686_ACC_FS_4G = 0x30,
|
||||
ICM45686_ACC_FS_2G = 0x40,
|
||||
} ICM45686_ACC_CONF;
|
||||
|
||||
//typedef enum {
|
||||
// ICM45686_ACC_SSF_32G = 16384.0,
|
||||
// ICM45686_ACC_SSF_16G = 8192.0,
|
||||
// ICM45686_ACC_SSF_8G = 4096.0,
|
||||
// ICM45686_ACC_SSF_4G = 2048.0,
|
||||
// ICM45686_ACC_SSF_2G = 1024.0,
|
||||
//} ICM45686_ACC_FACTORS;
|
||||
|
||||
static const float ICM45686_ACC_SSF [5] = {
|
||||
1024.0f, 2048.0f, 4096.0f, 8192.0f, 16384.0f
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
ICM45686_GYRO_FS_4000DPS = 0x00,
|
||||
ICM45686_GYRO_FS_2000DPS = 0x10,
|
||||
ICM45686_GYRO_FS_1000DPS = 0x20,
|
||||
ICM45686_GYRO_FS_500DPS = 0x30,
|
||||
ICM45686_GYRO_FS_250DPS = 0x40,
|
||||
ICM45686_GYRO_FS_125DPS = 0x50,
|
||||
ICM45686_GYRO_FS_62_5DPS = 0x60,
|
||||
ICM45686_GYRO_FS_31_25DPS = 0x70,
|
||||
ICM45686_GYRO_FS_15_625DPS = 0x80,
|
||||
} ICM45686_GYRO_CONF;
|
||||
|
||||
//typedef enum {
|
||||
// ICM45686_GYRO_SSF_4000DPS = 2097.2,
|
||||
// ICM45686_GYRO_SSF_2000DPS = 1048.6,
|
||||
// ICM45686_GYRO_SSF_1000DPS = 524.3,
|
||||
// ICM45686_GYRO_SSF_500DPS = 262.0,
|
||||
// ICM45686_GYRO_SSF_250DPS = 131.0,
|
||||
// ICM45686_GYRO_SSF_125DPS = 65.8,
|
||||
// ICM45686_GYRO_SSF_62_5DPS = 32.8,
|
||||
// ICM45686_GYRO_SSF_31_25DPS = 16.4,
|
||||
// ICM45686_GYRO_SSF_15_626DPS = 8.2,
|
||||
//} ICM45686_GYRO_FACTORS;
|
||||
|
||||
static const float ICM45686_GYRO_SSF [9] = {
|
||||
8.2f, 16.4f, 32.8f, 65.5f, 131.0f, 262.0f, 524.3f, 1048.6f, 2097.2f
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
ICM45686_ODR_6_4kHz_LN = 0x03 ,
|
||||
ICM45686_ODR_3_2kHz_LN = 0x04,
|
||||
ICM45686_ODR_1_6kHz_LN = 0x05,
|
||||
ICM45686_ODR_800Hz_LN = 0x06,
|
||||
ICM45686_ODR_400Hz_LNLP = 0x07,
|
||||
ICM45686_ODR_200Hz_LNLP = 0x08,
|
||||
ICM45686_ODR_100Hz_LNLP = 0x09,
|
||||
ICM45686_ODR_50Hz_LNLP = 0x0A,
|
||||
ICM45686_ODR_25Hz_LNLP = 0x0B,
|
||||
ICM45686_ODR_12_5Hz_LNLP = 0x0C,
|
||||
ICM45686_ODR_6_26Hz_LP = 0x0D,
|
||||
ICM45686_ODR_3_125Hz_LP = 0x0E,
|
||||
ICM45686_ODR_1_5625Hz_LP = 0x0F
|
||||
} ICM45686_ODR;
|
||||
|
||||
|
||||
|
||||
|
||||
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi);
|
||||
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *I2C_address);
|
||||
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *I2C_address);
|
||||
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c);
|
||||
|
||||
// ICM45686
|
||||
void init_icm(ICM45686_HandleTypeDef *imu);
|
||||
HAL_StatusTypeDef read_icm (ICM45686_HandleTypeDef *imu, uint8_t tx[], uint8_t rx[]);
|
||||
HAL_StatusTypeDef read_icm_dma (ICM45686_HandleTypeDef *imu, uint8_t tx[], uint8_t rx[]);
|
||||
HAL_StatusTypeDef write_icm (ICM45686_HandleTypeDef *imu, uint8_t tx[]);
|
||||
void calibrate_icm (ICM45686_HandleTypeDef * imu, int samples);
|
||||
|
||||
// BMM350 - Declarations of read/write/delay functions for the BMM350 API
|
||||
void bmm_init_DWT(void);
|
||||
BMM350_INTF_RET_TYPE bmm350_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr);
|
||||
BMM350_INTF_RET_TYPE bmm350_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr);
|
||||
void bmm350_delay(uint32_t period_us, void *intf_ptr);
|
||||
int8_t init_bmm(struct bmm350_dev *dev);
|
||||
|
||||
// structs that hold the sensor data
|
||||
typedef struct {
|
||||
uint8_t raw_imu[14];
|
||||
uint8_t raw_magn [9];
|
||||
} raw_sensor_data;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
***************************************************************************************
|
||||
* @file stm32_lpm_if.c
|
||||
* @author MCD Application Team
|
||||
* @brief Low layer function to enter/exit low power modes (stop, sleep).
|
||||
***************************************************************************************
|
||||
* @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 "stm32_lpm_if.h"
|
||||
#include "stm32_lpm.h"
|
||||
#include "app_conf.h"
|
||||
/* USER CODE BEGIN include */
|
||||
|
||||
/* USER CODE END include */
|
||||
|
||||
/* Exported variables --------------------------------------------------------*/
|
||||
const struct UTIL_LPM_Driver_s UTIL_PowerDriver =
|
||||
{
|
||||
PWR_EnterSleepMode,
|
||||
PWR_ExitSleepMode,
|
||||
|
||||
PWR_EnterStopMode,
|
||||
PWR_ExitStopMode,
|
||||
|
||||
PWR_EnterOffMode,
|
||||
PWR_ExitOffMode,
|
||||
};
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static void Switch_On_HSI(void);
|
||||
static void EnterLowPower(void);
|
||||
static void ExitLowPower(void);
|
||||
/* USER CODE BEGIN Private_Function_Prototypes */
|
||||
|
||||
/* USER CODE END Private_Function_Prototypes */
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Private_Typedef */
|
||||
|
||||
/* USER CODE END Private_Typedef */
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Private_Define */
|
||||
|
||||
/* USER CODE END Private_Define */
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Private_Macro */
|
||||
|
||||
/* USER CODE END Private_Macro */
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Private_Variables */
|
||||
|
||||
/* USER CODE END Private_Variables */
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Enters Low Power Off Mode
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_EnterOffMode(void)
|
||||
{
|
||||
/* USER CODE BEGIN PWR_EnterOffMode_1 */
|
||||
|
||||
/* USER CODE END PWR_EnterOffMode_1 */
|
||||
/**
|
||||
* The systick should be disabled for the same reason than when the device enters stop mode because
|
||||
* at this time, the device may enter either OffMode or StopMode.
|
||||
*/
|
||||
HAL_SuspendTick();
|
||||
|
||||
EnterLowPower();
|
||||
|
||||
/************************************************************************************
|
||||
* ENTER OFF MODE
|
||||
***********************************************************************************/
|
||||
/*
|
||||
* There is no risk to clear all the WUF here because in the current implementation, this API is called
|
||||
* in critical section. If an interrupt occurs while in that critical section before that point,
|
||||
* the flag is set and will be cleared here but the system will not enter Off Mode
|
||||
* because an interrupt is pending in the NVIC. The ISR will be executed when moving out
|
||||
* of this critical section
|
||||
*/
|
||||
LL_PWR_ClearFlag_WU();
|
||||
|
||||
LL_PWR_SetPowerMode(LL_PWR_MODE_STANDBY);
|
||||
|
||||
LL_LPM_EnableDeepSleep(); /**< Set SLEEPDEEP bit of Cortex System Control Register */
|
||||
|
||||
/**
|
||||
* This option is used to ensure that store operations are completed
|
||||
*/
|
||||
#if defined (__CC_ARM) || defined (__ARMCC_VERSION)
|
||||
__force_stores();
|
||||
#endif
|
||||
|
||||
__WFI();
|
||||
|
||||
/* USER CODE BEGIN PWR_EnterOffMode_2 */
|
||||
|
||||
/* USER CODE END PWR_EnterOffMode_2 */
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exits Low Power Off Mode
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_ExitOffMode(void)
|
||||
{
|
||||
/* USER CODE BEGIN PWR_ExitOffMode_1 */
|
||||
|
||||
/* USER CODE END PWR_ExitOffMode_1 */
|
||||
HAL_ResumeTick();
|
||||
/* USER CODE BEGIN PWR_ExitOffMode_2 */
|
||||
|
||||
/* USER CODE END PWR_ExitOffMode_2 */
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enters Low Power Stop Mode
|
||||
* @note ARM exists the function when waking up
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_EnterStopMode(void)
|
||||
{
|
||||
/* USER CODE BEGIN PWR_EnterStopMode_1 */
|
||||
|
||||
/* USER CODE END PWR_EnterStopMode_1 */
|
||||
/**
|
||||
* When HAL_DBGMCU_EnableDBGStopMode() is called to keep the debugger active in Stop Mode,
|
||||
* the systick shall be disabled otherwise the cpu may crash when moving out from stop mode
|
||||
*
|
||||
* When in production, the HAL_DBGMCU_EnableDBGStopMode() is not called so that the device can reach best power consumption
|
||||
* However, the systick should be disabled anyway to avoid the case when it is about to expire at the same time the device enters
|
||||
* stop mode (this will abort the Stop Mode entry).
|
||||
*/
|
||||
HAL_SuspendTick();
|
||||
|
||||
/**
|
||||
* This function is called from CRITICAL SECTION
|
||||
*/
|
||||
EnterLowPower();
|
||||
|
||||
/************************************************************************************
|
||||
* ENTER STOP MODE
|
||||
***********************************************************************************/
|
||||
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2);
|
||||
|
||||
LL_LPM_EnableDeepSleep(); /**< Set SLEEPDEEP bit of Cortex System Control Register */
|
||||
|
||||
/**
|
||||
* This option is used to ensure that store operations are completed
|
||||
*/
|
||||
#if defined (__CC_ARM) || defined (__ARMCC_VERSION)
|
||||
__force_stores();
|
||||
#endif
|
||||
|
||||
__WFI();
|
||||
|
||||
/* USER CODE BEGIN PWR_EnterStopMode_2 */
|
||||
|
||||
/* USER CODE END PWR_EnterStopMode_2 */
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exits Low Power Stop Mode
|
||||
* @note Enable the pll at 32MHz
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_ExitStopMode(void)
|
||||
{
|
||||
/* USER CODE BEGIN PWR_ExitStopMode_1 */
|
||||
|
||||
/* USER CODE END PWR_ExitStopMode_1 */
|
||||
/**
|
||||
* This function is called from CRITICAL SECTION
|
||||
*/
|
||||
ExitLowPower();
|
||||
|
||||
HAL_ResumeTick();
|
||||
/* USER CODE BEGIN PWR_ExitStopMode_2 */
|
||||
|
||||
/* USER CODE END PWR_ExitStopMode_2 */
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enters Low Power Sleep Mode
|
||||
* @note ARM exits the function when waking up
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_EnterSleepMode(void)
|
||||
{
|
||||
/* USER CODE BEGIN PWR_EnterSleepMode_1 */
|
||||
|
||||
/* USER CODE END PWR_EnterSleepMode_1 */
|
||||
|
||||
HAL_SuspendTick();
|
||||
|
||||
/************************************************************************************
|
||||
* ENTER SLEEP MODE
|
||||
***********************************************************************************/
|
||||
LL_LPM_EnableSleep(); /**< Clear SLEEPDEEP bit of Cortex System Control Register */
|
||||
|
||||
/**
|
||||
* This option is used to ensure that store operations are completed
|
||||
*/
|
||||
#if defined (__CC_ARM) || defined (__ARMCC_VERSION)
|
||||
__force_stores();
|
||||
#endif
|
||||
|
||||
__WFI();
|
||||
/* USER CODE BEGIN PWR_EnterSleepMode_2 */
|
||||
|
||||
/* USER CODE END PWR_EnterSleepMode_2 */
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exits Low Power Sleep Mode
|
||||
* @note ARM exits the function when waking up
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
void PWR_ExitSleepMode(void)
|
||||
{
|
||||
/* USER CODE BEGIN PWR_ExitSleepMode_1 */
|
||||
|
||||
/* USER CODE END PWR_ExitSleepMode_1 */
|
||||
HAL_ResumeTick();
|
||||
/* USER CODE BEGIN PWR_ExitSleepMode_2 */
|
||||
|
||||
/* USER CODE END PWR_ExitSleepMode_2 */
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* LOCAL FUNCTIONS
|
||||
*
|
||||
*************************************************************/
|
||||
/**
|
||||
* @brief Setup the system to enter either stop or off mode
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
static void EnterLowPower(void)
|
||||
{
|
||||
/**
|
||||
* This function is called from CRITICAL SECTION
|
||||
*/
|
||||
|
||||
while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID));
|
||||
|
||||
if (! LL_HSEM_1StepLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID))
|
||||
{
|
||||
if(LL_PWR_IsActiveFlag_C2DS() || LL_PWR_IsActiveFlag_C2SB())
|
||||
{
|
||||
/* Release ENTRY_STOP_MODE semaphore */
|
||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0);
|
||||
|
||||
Switch_On_HSI();
|
||||
__HAL_FLASH_SET_LATENCY(FLASH_LATENCY_0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Switch_On_HSI();
|
||||
__HAL_FLASH_SET_LATENCY(FLASH_LATENCY_0);
|
||||
}
|
||||
|
||||
/* Release RCC semaphore */
|
||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restore the system to exit stop mode
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
static void ExitLowPower(void)
|
||||
{
|
||||
/* Release ENTRY_STOP_MODE semaphore */
|
||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0);
|
||||
|
||||
while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID));
|
||||
|
||||
if(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSI)
|
||||
{
|
||||
/* Restore the clock configuration of the application in this user section */
|
||||
/* USER CODE BEGIN ExitLowPower_1 */
|
||||
|
||||
/* USER CODE END ExitLowPower_1 */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the application is not running on HSE restore the clock configuration in this user section */
|
||||
/* USER CODE BEGIN ExitLowPower_2 */
|
||||
|
||||
/* USER CODE END ExitLowPower_2 */
|
||||
}
|
||||
|
||||
/* Release RCC semaphore */
|
||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Switch the system clock on HSI
|
||||
* @param none
|
||||
* @retval none
|
||||
*/
|
||||
static void Switch_On_HSI(void)
|
||||
{
|
||||
LL_RCC_HSI_Enable();
|
||||
while(!LL_RCC_HSI_IsReady());
|
||||
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI);
|
||||
LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSI);
|
||||
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI);
|
||||
return;
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Private_Functions */
|
||||
|
||||
/* USER CODE END Private_Functions */
|
||||
|
||||
@@ -0,0 +1,584 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32wbxx_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 */
|
||||
extern DMA_HandleTypeDef hdma_i2c1_tx;
|
||||
|
||||
extern DMA_HandleTypeDef hdma_i2c1_rx;
|
||||
|
||||
extern DMA_HandleTypeDef hdma_spi1_tx;
|
||||
|
||||
extern DMA_HandleTypeDef hdma_spi1_rx;
|
||||
|
||||
/* 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 */
|
||||
|
||||
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
|
||||
/**
|
||||
* Initializes the Global MSP.
|
||||
*/
|
||||
void HAL_MspInit(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN MspInit 0 */
|
||||
|
||||
/* USER CODE END MspInit 0 */
|
||||
|
||||
__HAL_RCC_HSEM_CLK_ENABLE();
|
||||
HAL_PWREx_EnableVddUSB();
|
||||
|
||||
/* System interrupt init*/
|
||||
/* PendSV_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(PendSV_IRQn, 15, 0);
|
||||
|
||||
/* Peripheral interrupt init */
|
||||
/* HSEM_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(HSEM_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(HSEM_IRQn);
|
||||
|
||||
/* USER CODE BEGIN MspInit 1 */
|
||||
|
||||
/* USER CODE END MspInit 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2C MSP Initialization
|
||||
* This function configures the hardware resources used in this example
|
||||
* @param hi2c: I2C handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
|
||||
if(hi2c->Instance==I2C1)
|
||||
{
|
||||
/* USER CODE BEGIN I2C1_MspInit 0 */
|
||||
|
||||
/* USER CODE END I2C1_MspInit 0 */
|
||||
|
||||
/** Initializes the peripherals clock
|
||||
*/
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C1;
|
||||
PeriphClkInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
|
||||
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
/**I2C1 GPIO Configuration
|
||||
PB8 ------> I2C1_SCL
|
||||
PB9 ------> I2C1_SDA
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_I2C1_CLK_ENABLE();
|
||||
|
||||
/* I2C1 DMA Init */
|
||||
/* I2C1_TX Init */
|
||||
hdma_i2c1_tx.Instance = DMA1_Channel3;
|
||||
hdma_i2c1_tx.Init.Request = DMA_REQUEST_I2C1_TX;
|
||||
hdma_i2c1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
hdma_i2c1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_i2c1_tx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_i2c1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
hdma_i2c1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
hdma_i2c1_tx.Init.Mode = DMA_NORMAL;
|
||||
hdma_i2c1_tx.Init.Priority = DMA_PRIORITY_HIGH;
|
||||
if (HAL_DMA_Init(&hdma_i2c1_tx) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
__HAL_LINKDMA(hi2c,hdmatx,hdma_i2c1_tx);
|
||||
|
||||
/* I2C1_RX Init */
|
||||
hdma_i2c1_rx.Instance = DMA1_Channel4;
|
||||
hdma_i2c1_rx.Init.Request = DMA_REQUEST_I2C1_RX;
|
||||
hdma_i2c1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
hdma_i2c1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_i2c1_rx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_i2c1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
hdma_i2c1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
hdma_i2c1_rx.Init.Mode = DMA_NORMAL;
|
||||
hdma_i2c1_rx.Init.Priority = DMA_PRIORITY_HIGH;
|
||||
if (HAL_DMA_Init(&hdma_i2c1_rx) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
__HAL_LINKDMA(hi2c,hdmarx,hdma_i2c1_rx);
|
||||
|
||||
/* I2C1 interrupt Init */
|
||||
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
|
||||
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
|
||||
/* USER CODE BEGIN I2C1_MspInit 1 */
|
||||
|
||||
/* USER CODE END I2C1_MspInit 1 */
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2C MSP De-Initialization
|
||||
* This function freeze the hardware resources used in this example
|
||||
* @param hi2c: I2C handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c)
|
||||
{
|
||||
if(hi2c->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
|
||||
PB8 ------> I2C1_SCL
|
||||
PB9 ------> I2C1_SDA
|
||||
*/
|
||||
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8);
|
||||
|
||||
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9);
|
||||
|
||||
/* I2C1 DMA DeInit */
|
||||
HAL_DMA_DeInit(hi2c->hdmatx);
|
||||
HAL_DMA_DeInit(hi2c->hdmarx);
|
||||
|
||||
/* I2C1 interrupt DeInit */
|
||||
HAL_NVIC_DisableIRQ(I2C1_EV_IRQn);
|
||||
HAL_NVIC_DisableIRQ(I2C1_ER_IRQn);
|
||||
/* USER CODE BEGIN I2C1_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END I2C1_MspDeInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IPCC MSP Initialization
|
||||
* This function configures the hardware resources used in this example
|
||||
* @param hipcc: IPCC handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_IPCC_MspInit(IPCC_HandleTypeDef* hipcc)
|
||||
{
|
||||
if(hipcc->Instance==IPCC)
|
||||
{
|
||||
/* USER CODE BEGIN IPCC_MspInit 0 */
|
||||
|
||||
/* USER CODE END IPCC_MspInit 0 */
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_IPCC_CLK_ENABLE();
|
||||
/* IPCC interrupt Init */
|
||||
HAL_NVIC_SetPriority(IPCC_C1_RX_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(IPCC_C1_RX_IRQn);
|
||||
HAL_NVIC_SetPriority(IPCC_C1_TX_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(IPCC_C1_TX_IRQn);
|
||||
/* USER CODE BEGIN IPCC_MspInit 1 */
|
||||
|
||||
/* USER CODE END IPCC_MspInit 1 */
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IPCC MSP De-Initialization
|
||||
* This function freeze the hardware resources used in this example
|
||||
* @param hipcc: IPCC handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_IPCC_MspDeInit(IPCC_HandleTypeDef* hipcc)
|
||||
{
|
||||
if(hipcc->Instance==IPCC)
|
||||
{
|
||||
/* USER CODE BEGIN IPCC_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END IPCC_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_IPCC_CLK_DISABLE();
|
||||
|
||||
/* IPCC interrupt DeInit */
|
||||
HAL_NVIC_DisableIRQ(IPCC_C1_RX_IRQn);
|
||||
HAL_NVIC_DisableIRQ(IPCC_C1_TX_IRQn);
|
||||
/* USER CODE BEGIN IPCC_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END IPCC_MspDeInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTC MSP Initialization
|
||||
* This function configures the hardware resources used in this example
|
||||
* @param hrtc: RTC handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc)
|
||||
{
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
|
||||
if(hrtc->Instance==RTC)
|
||||
{
|
||||
/* USER CODE BEGIN RTC_MspInit 0 */
|
||||
|
||||
/* USER CODE END RTC_MspInit 0 */
|
||||
|
||||
/** Enable access to the backup domain
|
||||
*/
|
||||
HAL_PWR_EnableBkUpAccess();
|
||||
|
||||
/** Initializes the peripherals clock
|
||||
*/
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
|
||||
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
|
||||
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_RTC_ENABLE();
|
||||
__HAL_RCC_RTCAPB_CLK_ENABLE();
|
||||
/* RTC interrupt Init */
|
||||
HAL_NVIC_SetPriority(RTC_WKUP_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
|
||||
/* USER CODE BEGIN RTC_MspInit 1 */
|
||||
|
||||
/* USER CODE END RTC_MspInit 1 */
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RTC MSP De-Initialization
|
||||
* This function freeze the hardware resources used in this example
|
||||
* @param hrtc: RTC handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RTC_MspDeInit(RTC_HandleTypeDef* hrtc)
|
||||
{
|
||||
if(hrtc->Instance==RTC)
|
||||
{
|
||||
/* USER CODE BEGIN RTC_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END RTC_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_RTC_DISABLE();
|
||||
__HAL_RCC_RTCAPB_CLK_DISABLE();
|
||||
|
||||
/* RTC interrupt DeInit */
|
||||
HAL_NVIC_DisableIRQ(RTC_WKUP_IRQn);
|
||||
/* USER CODE BEGIN RTC_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END RTC_MspDeInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI MSP Initialization
|
||||
* This function configures the hardware resources used in this example
|
||||
* @param hspi: SPI handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
if(hspi->Instance==SPI1)
|
||||
{
|
||||
/* USER CODE BEGIN SPI1_MspInit 0 */
|
||||
|
||||
/* USER CODE END SPI1_MspInit 0 */
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_SPI1_CLK_ENABLE();
|
||||
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
/**SPI1 GPIO Configuration
|
||||
PA5 ------> SPI1_SCK
|
||||
PA6 ------> SPI1_MISO
|
||||
PA7 ------> SPI1_MOSI
|
||||
*/
|
||||
GPIO_InitStruct.Pin = SPI1_IMU_SCK_Pin|SPI1_IMU_MISO_Pin|SPI1_IMU_MOSI_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
/* SPI1 DMA Init */
|
||||
/* SPI1_TX Init */
|
||||
hdma_spi1_tx.Instance = DMA1_Channel1;
|
||||
hdma_spi1_tx.Init.Request = DMA_REQUEST_SPI1_TX;
|
||||
hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
hdma_spi1_tx.Init.Mode = DMA_NORMAL;
|
||||
hdma_spi1_tx.Init.Priority = DMA_PRIORITY_HIGH;
|
||||
if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
__HAL_LINKDMA(hspi,hdmatx,hdma_spi1_tx);
|
||||
|
||||
/* SPI1_RX Init */
|
||||
hdma_spi1_rx.Instance = DMA1_Channel2;
|
||||
hdma_spi1_rx.Init.Request = DMA_REQUEST_SPI1_RX;
|
||||
hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
hdma_spi1_rx.Init.Mode = DMA_NORMAL;
|
||||
hdma_spi1_rx.Init.Priority = DMA_PRIORITY_HIGH;
|
||||
if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
__HAL_LINKDMA(hspi,hdmarx,hdma_spi1_rx);
|
||||
|
||||
/* USER CODE BEGIN SPI1_MspInit 1 */
|
||||
|
||||
/* USER CODE END SPI1_MspInit 1 */
|
||||
}
|
||||
else if(hspi->Instance==SPI2)
|
||||
{
|
||||
/* USER CODE BEGIN SPI2_MspInit 0 */
|
||||
|
||||
/* USER CODE END SPI2_MspInit 0 */
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_SPI2_CLK_ENABLE();
|
||||
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
/**SPI2 GPIO Configuration
|
||||
PC1 ------> SPI2_MOSI
|
||||
PC2 ------> SPI2_MISO
|
||||
PA9 ------> SPI2_SCK
|
||||
*/
|
||||
GPIO_InitStruct.Pin = SPI2_SD_MOSI_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF3_SPI2;
|
||||
HAL_GPIO_Init(SPI2_SD_MOSI_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = SPI2_SD_MISO_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
|
||||
HAL_GPIO_Init(SPI2_SD_MISO_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = SPI2_SD_SCK_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
|
||||
HAL_GPIO_Init(SPI2_SD_SCK_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN SPI2_MspInit 1 */
|
||||
|
||||
/* USER CODE END SPI2_MspInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI MSP De-Initialization
|
||||
* This function freeze the hardware resources used in this example
|
||||
* @param hspi: SPI handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
|
||||
{
|
||||
if(hspi->Instance==SPI1)
|
||||
{
|
||||
/* USER CODE BEGIN SPI1_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END SPI1_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_SPI1_CLK_DISABLE();
|
||||
|
||||
/**SPI1 GPIO Configuration
|
||||
PA5 ------> SPI1_SCK
|
||||
PA6 ------> SPI1_MISO
|
||||
PA7 ------> SPI1_MOSI
|
||||
*/
|
||||
HAL_GPIO_DeInit(GPIOA, SPI1_IMU_SCK_Pin|SPI1_IMU_MISO_Pin|SPI1_IMU_MOSI_Pin);
|
||||
|
||||
/* SPI1 DMA DeInit */
|
||||
HAL_DMA_DeInit(hspi->hdmatx);
|
||||
HAL_DMA_DeInit(hspi->hdmarx);
|
||||
/* USER CODE BEGIN SPI1_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END SPI1_MspDeInit 1 */
|
||||
}
|
||||
else if(hspi->Instance==SPI2)
|
||||
{
|
||||
/* USER CODE BEGIN SPI2_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END SPI2_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_SPI2_CLK_DISABLE();
|
||||
|
||||
/**SPI2 GPIO Configuration
|
||||
PC1 ------> SPI2_MOSI
|
||||
PC2 ------> SPI2_MISO
|
||||
PA9 ------> SPI2_SCK
|
||||
*/
|
||||
HAL_GPIO_DeInit(GPIOC, SPI2_SD_MOSI_Pin|SPI2_SD_MISO_Pin);
|
||||
|
||||
HAL_GPIO_DeInit(SPI2_SD_SCK_GPIO_Port, SPI2_SD_SCK_Pin);
|
||||
|
||||
/* USER CODE BEGIN SPI2_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END SPI2_MspDeInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TIM_PWM MSP Initialization
|
||||
* This function configures the hardware resources used in this example
|
||||
* @param htim_pwm: TIM_PWM handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm)
|
||||
{
|
||||
if(htim_pwm->Instance==TIM2)
|
||||
{
|
||||
/* USER CODE BEGIN TIM2_MspInit 0 */
|
||||
|
||||
/* USER CODE END TIM2_MspInit 0 */
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_TIM2_CLK_ENABLE();
|
||||
/* USER CODE BEGIN TIM2_MspInit 1 */
|
||||
|
||||
/* USER CODE END TIM2_MspInit 1 */
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
if(htim->Instance==TIM2)
|
||||
{
|
||||
/* USER CODE BEGIN TIM2_MspPostInit 0 */
|
||||
|
||||
/* USER CODE END TIM2_MspPostInit 0 */
|
||||
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
/**TIM2 GPIO Configuration
|
||||
PA0 ------> TIM2_CH1
|
||||
PA1 ------> TIM2_CH2
|
||||
PA2 ------> TIM2_CH3
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_CONNECT_LED_Pin|GPIO_STATUS_LED_Pin|GPIO_DEBUG_LED_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN TIM2_MspPostInit 1 */
|
||||
|
||||
/* USER CODE END TIM2_MspPostInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief TIM_PWM MSP De-Initialization
|
||||
* This function freeze the hardware resources used in this example
|
||||
* @param htim_pwm: TIM_PWM handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* htim_pwm)
|
||||
{
|
||||
if(htim_pwm->Instance==TIM2)
|
||||
{
|
||||
/* USER CODE BEGIN TIM2_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END TIM2_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_TIM2_CLK_DISABLE();
|
||||
/* USER CODE BEGIN TIM2_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END TIM2_MspDeInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
@@ -0,0 +1,136 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32wbxx_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 "stm32wbxx_hal.h"
|
||||
#include "stm32wbxx_hal_tim.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
TIM_HandleTypeDef htim16;
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief This function configures the TIM16 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 = 0;
|
||||
uint32_t uwPrescalerValue = 0;
|
||||
uint32_t pFLatency;
|
||||
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/*Configure the TIM16 IRQ priority */
|
||||
HAL_NVIC_SetPriority(TIM1_UP_TIM16_IRQn, TickPriority ,0);
|
||||
/* Enable the TIM16 global Interrupt */
|
||||
HAL_NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);
|
||||
|
||||
/* Enable TIM16 clock */
|
||||
__HAL_RCC_TIM16_CLK_ENABLE();
|
||||
|
||||
/* Get clock configuration */
|
||||
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
|
||||
|
||||
/* Compute TIM16 clock */
|
||||
uwTimclock = HAL_RCC_GetPCLK2Freq();
|
||||
|
||||
/* Compute the prescaler value to have TIM16 counter clock equal to 1MHz */
|
||||
uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U);
|
||||
|
||||
/* Initialize TIM16 */
|
||||
htim16.Instance = TIM16;
|
||||
|
||||
/* Initialize TIMx peripheral as follow:
|
||||
* Period = [(TIM16CLK/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
|
||||
*/
|
||||
htim16.Init.Period = (1000000U / 1000U) - 1U;
|
||||
htim16.Init.Prescaler = uwPrescalerValue;
|
||||
htim16.Init.ClockDivision = 0;
|
||||
htim16.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
|
||||
status = HAL_TIM_Base_Init(&htim16);
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1U)
|
||||
/* Register callback */
|
||||
HAL_TIM_RegisterCallback(&htim16, HAL_TIM_PERIOD_ELAPSED_CB_ID, TimeBase_TIM_PeriodElapsedCallback);
|
||||
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
|
||||
|
||||
/* Start the TIM time Base generation in interrupt mode */
|
||||
status = HAL_TIM_Base_Start_IT(&htim16);
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Enable the TIM16 global Interrupt */
|
||||
HAL_NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);
|
||||
/* Configure the SysTick IRQ priority */
|
||||
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
|
||||
{
|
||||
/* Configure the TIM IRQ priority */
|
||||
HAL_NVIC_SetPriority(TIM1_UP_TIM16_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 TIM16 update interrupt.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SuspendTick(void)
|
||||
{
|
||||
/* Disable TIM16 update Interrupt */
|
||||
__HAL_TIM_DISABLE_IT(&htim16, TIM_IT_UPDATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume Tick increment.
|
||||
* @note Enable the tick increment by Enabling TIM16 update interrupt.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_ResumeTick(void)
|
||||
{
|
||||
/* Enable TIM16 Update interrupt */
|
||||
__HAL_TIM_ENABLE_IT(&htim16, TIM_IT_UPDATE);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,340 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32wbxx_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 "stm32wbxx_it.h"
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN TD */
|
||||
|
||||
/* USER CODE END TD */
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PD */
|
||||
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PM */
|
||||
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
extern PCD_HandleTypeDef hpcd_USB_FS;
|
||||
extern DMA_HandleTypeDef hdma_i2c1_tx;
|
||||
extern DMA_HandleTypeDef hdma_i2c1_rx;
|
||||
extern I2C_HandleTypeDef hi2c1;
|
||||
extern IPCC_HandleTypeDef hipcc;
|
||||
extern RTC_HandleTypeDef hrtc;
|
||||
extern DMA_HandleTypeDef hdma_spi1_tx;
|
||||
extern DMA_HandleTypeDef hdma_spi1_rx;
|
||||
extern TIM_HandleTypeDef htim16;
|
||||
|
||||
/* USER CODE BEGIN EV */
|
||||
|
||||
/* USER CODE END EV */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Cortex 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 */
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* STM32WBxx 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_stm32wbxx.s). */
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief This function handles RTC wake-up interrupt through EXTI line 19.
|
||||
*/
|
||||
void RTC_WKUP_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN RTC_WKUP_IRQn 0 */
|
||||
|
||||
/* USER CODE END RTC_WKUP_IRQn 0 */
|
||||
HAL_RTCEx_WakeUpTimerIRQHandler(&hrtc);
|
||||
/* USER CODE BEGIN RTC_WKUP_IRQn 1 */
|
||||
|
||||
/* USER CODE END RTC_WKUP_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles DMA1 channel1 global interrupt.
|
||||
*/
|
||||
void DMA1_Channel1_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
|
||||
|
||||
/* USER CODE END DMA1_Channel1_IRQn 0 */
|
||||
HAL_DMA_IRQHandler(&hdma_spi1_tx);
|
||||
/* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
|
||||
|
||||
/* USER CODE END DMA1_Channel1_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles DMA1 channel2 global interrupt.
|
||||
*/
|
||||
void DMA1_Channel2_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN DMA1_Channel2_IRQn 0 */
|
||||
|
||||
/* USER CODE END DMA1_Channel2_IRQn 0 */
|
||||
HAL_DMA_IRQHandler(&hdma_spi1_rx);
|
||||
/* USER CODE BEGIN DMA1_Channel2_IRQn 1 */
|
||||
|
||||
/* USER CODE END DMA1_Channel2_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles DMA1 channel3 global interrupt.
|
||||
*/
|
||||
void DMA1_Channel3_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN DMA1_Channel3_IRQn 0 */
|
||||
|
||||
/* USER CODE END DMA1_Channel3_IRQn 0 */
|
||||
HAL_DMA_IRQHandler(&hdma_i2c1_tx);
|
||||
/* USER CODE BEGIN DMA1_Channel3_IRQn 1 */
|
||||
|
||||
/* USER CODE END DMA1_Channel3_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @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_i2c1_rx);
|
||||
/* USER CODE BEGIN DMA1_Channel4_IRQn 1 */
|
||||
|
||||
/* USER CODE END DMA1_Channel4_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles USB low priority interrupt, USB wake-up interrupt through EXTI line 28.
|
||||
*/
|
||||
void USB_LP_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN USB_LP_IRQn 0 */
|
||||
|
||||
/* USER CODE END USB_LP_IRQn 0 */
|
||||
HAL_PCD_IRQHandler(&hpcd_USB_FS);
|
||||
/* USER CODE BEGIN USB_LP_IRQn 1 */
|
||||
|
||||
/* USER CODE END USB_LP_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles TIM1 update interrupt and TIM16 global interrupt.
|
||||
*/
|
||||
void TIM1_UP_TIM16_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN TIM1_UP_TIM16_IRQn 0 */
|
||||
|
||||
/* USER CODE END TIM1_UP_TIM16_IRQn 0 */
|
||||
HAL_TIM_IRQHandler(&htim16);
|
||||
/* USER CODE BEGIN TIM1_UP_TIM16_IRQn 1 */
|
||||
|
||||
/* USER CODE END TIM1_UP_TIM16_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles I2C1 event interrupt.
|
||||
*/
|
||||
void I2C1_EV_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN I2C1_EV_IRQn 0 */
|
||||
|
||||
/* USER CODE END I2C1_EV_IRQn 0 */
|
||||
HAL_I2C_EV_IRQHandler(&hi2c1);
|
||||
/* USER CODE BEGIN I2C1_EV_IRQn 1 */
|
||||
|
||||
/* USER CODE END I2C1_EV_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles I2C1 error interrupt.
|
||||
*/
|
||||
void I2C1_ER_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN I2C1_ER_IRQn 0 */
|
||||
|
||||
/* USER CODE END I2C1_ER_IRQn 0 */
|
||||
HAL_I2C_ER_IRQHandler(&hi2c1);
|
||||
/* USER CODE BEGIN I2C1_ER_IRQn 1 */
|
||||
|
||||
/* USER CODE END I2C1_ER_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles IPCC RX occupied interrupt.
|
||||
*/
|
||||
void IPCC_C1_RX_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN IPCC_C1_RX_IRQn 0 */
|
||||
|
||||
/* USER CODE END IPCC_C1_RX_IRQn 0 */
|
||||
HAL_IPCC_RX_IRQHandler(&hipcc);
|
||||
/* USER CODE BEGIN IPCC_C1_RX_IRQn 1 */
|
||||
|
||||
/* USER CODE END IPCC_C1_RX_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles IPCC TX free interrupt.
|
||||
*/
|
||||
void IPCC_C1_TX_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN IPCC_C1_TX_IRQn 0 */
|
||||
|
||||
/* USER CODE END IPCC_C1_TX_IRQn 0 */
|
||||
HAL_IPCC_TX_IRQHandler(&hipcc);
|
||||
/* USER CODE BEGIN IPCC_C1_TX_IRQn 1 */
|
||||
|
||||
/* USER CODE END IPCC_C1_TX_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles HSEM global interrupt.
|
||||
*/
|
||||
void HSEM_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN HSEM_IRQn 0 */
|
||||
|
||||
/* USER CODE END HSEM_IRQn 0 */
|
||||
HAL_HSEM_IRQHandler();
|
||||
/* USER CODE BEGIN HSEM_IRQn 1 */
|
||||
|
||||
/* USER CODE END HSEM_IRQn 1 */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file syscalls.c
|
||||
* @author Auto-generated by STM32CubeIDE
|
||||
* @brief STM32CubeIDE Minimal System calls file
|
||||
*
|
||||
* For more information about which c-functions
|
||||
* need which of these lowlevel functions
|
||||
* please consult the Newlib libc-manual
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2020-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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/times.h>
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
int _times(struct tms *buf)
|
||||
{
|
||||
(void)buf;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _stat(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;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file sysmem.c
|
||||
* @author Generated by STM32CubeIDE
|
||||
* @brief STM32CubeIDE System Memory calls file
|
||||
*
|
||||
* For more information about which C functions
|
||||
* need which of these lowlevel functions
|
||||
* please consult the newlib libc manual
|
||||
******************************************************************************
|
||||
* @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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -0,0 +1,378 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file system_stm32wbxx.c
|
||||
* @author MCD Application Team
|
||||
* @brief CMSIS Cortex Device Peripheral Access Layer System Source File
|
||||
*
|
||||
* This file provides two functions and one global variable to be called from
|
||||
* user application:
|
||||
* - SystemInit(): This function is called at startup just after reset and
|
||||
* before branch to main program. This call is made inside
|
||||
* the "startup_stm32wbxx.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.
|
||||
*
|
||||
* After each device reset the MSI (4 MHz) is used as system clock source.
|
||||
* Then SystemInit() function is called, in "startup_stm32wbxx.s" file, to
|
||||
* configure the system clock before to branch to main program.
|
||||
*
|
||||
* This file configures the system clock as follows:
|
||||
*=============================================================================
|
||||
*-----------------------------------------------------------------------------
|
||||
* System Clock source | MSI
|
||||
*-----------------------------------------------------------------------------
|
||||
* SYSCLK(Hz) | 4000000
|
||||
*-----------------------------------------------------------------------------
|
||||
* HCLK(Hz) | 4000000
|
||||
*-----------------------------------------------------------------------------
|
||||
* AHB Prescaler | 1
|
||||
*-----------------------------------------------------------------------------
|
||||
* APB1 Prescaler | 1
|
||||
*-----------------------------------------------------------------------------
|
||||
* APB2 Prescaler | 1
|
||||
*-----------------------------------------------------------------------------
|
||||
* PLL_M | 1
|
||||
*-----------------------------------------------------------------------------
|
||||
* PLL_N | 8
|
||||
*-----------------------------------------------------------------------------
|
||||
* PLL_P | 7
|
||||
*-----------------------------------------------------------------------------
|
||||
* PLL_Q | 2
|
||||
*-----------------------------------------------------------------------------
|
||||
* PLL_R | 2
|
||||
*-----------------------------------------------------------------------------
|
||||
* PLLSAI1_P | NA
|
||||
*-----------------------------------------------------------------------------
|
||||
* PLLSAI1_Q | NA
|
||||
*-----------------------------------------------------------------------------
|
||||
* PLLSAI1_R | NA
|
||||
*-----------------------------------------------------------------------------
|
||||
* Require 48MHz for USB OTG FS, | Disabled
|
||||
* SDIO and RNG clock |
|
||||
*-----------------------------------------------------------------------------
|
||||
*=============================================================================
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2019-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 stm32WBxx_system
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup stm32WBxx_System_Private_Includes
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "stm32wbxx.h"
|
||||
|
||||
#if !defined (HSE_VALUE)
|
||||
#define HSE_VALUE (32000000UL) /*!< Value of the External oscillator in Hz */
|
||||
#endif /* HSE_VALUE */
|
||||
|
||||
#if !defined (MSI_VALUE)
|
||||
#define MSI_VALUE (4000000UL) /*!< Value of the Internal oscillator in Hz*/
|
||||
#endif /* MSI_VALUE */
|
||||
|
||||
#if !defined (HSI_VALUE)
|
||||
#define HSI_VALUE (16000000UL) /*!< Value of the Internal oscillator in Hz*/
|
||||
#endif /* HSI_VALUE */
|
||||
|
||||
#if !defined (LSI_VALUE)
|
||||
#define LSI_VALUE (32000UL) /*!< Value of LSI in Hz*/
|
||||
#endif /* LSI_VALUE */
|
||||
|
||||
#if !defined (LSE_VALUE)
|
||||
#if defined(STM32WB5Mxx)
|
||||
#define LSE_VALUE 32774U /*!< Value of the LSE oscillator in Hz */
|
||||
#else
|
||||
#define LSE_VALUE 32768U /*!< Value of the LSE oscillator in Hz */
|
||||
#endif /* STM32WB5Mxx */
|
||||
#endif /* LSE_VALUE */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32WBxx_System_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32WBxx_System_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Note: Following vector table addresses must be defined in line with linker
|
||||
configuration. */
|
||||
/*!< Uncomment the following line if you need to relocate CPU1 CM4 and/or CPU2
|
||||
CM0+ vector table anywhere in Sram or Flash. Else vector table will be kept
|
||||
at address 0x00 which correspond to automatic remap of boot address selected */
|
||||
/* #define USER_VECT_TAB_ADDRESS */
|
||||
#if defined(USER_VECT_TAB_ADDRESS)
|
||||
/*!< Uncomment this line for user vector table remap in Sram else user remap
|
||||
will be done in Flash. */
|
||||
/* #define VECT_TAB_SRAM */
|
||||
#if defined(VECT_TAB_SRAM)
|
||||
#define VECT_TAB_BASE_ADDRESS SRAM1_BASE /*!< Vector Table base address field.
|
||||
This value must be a multiple of 0x200. */
|
||||
#if !defined(VECT_TAB_OFFSET)
|
||||
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table offset field.
|
||||
This value must be a multiple of 0x200. */
|
||||
#endif /* VECT_TAB_OFFSET */
|
||||
|
||||
#else
|
||||
#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field.
|
||||
This value must be a multiple of 0x200. */
|
||||
#if !defined(VECT_TAB_OFFSET)
|
||||
#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table offset field.
|
||||
This value must be a multiple of 0x200. */
|
||||
#endif /* VECT_TAB_OFFSET */
|
||||
|
||||
#endif /* VECT_TAB_SRAM */
|
||||
#endif /* USER_VECT_TAB_ADDRESS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32WBxx_System_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32WBxx_System_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
/* The SystemCoreClock 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 = 4000000UL ; /*CPU1: M4 on MSI clock after startup (4MHz)*/
|
||||
|
||||
const uint32_t AHBPrescTable[16UL] = {1UL, 3UL, 5UL, 1UL, 1UL, 6UL, 10UL, 32UL, 2UL, 4UL, 8UL, 16UL, 64UL, 128UL, 256UL, 512UL};
|
||||
|
||||
const uint32_t APBPrescTable[8UL] = {0UL, 0UL, 0UL, 0UL, 1UL, 2UL, 3UL, 4UL};
|
||||
|
||||
const uint32_t MSIRangeTable[16UL] = {100000UL, 200000UL, 400000UL, 800000UL, 1000000UL, 2000000UL, \
|
||||
4000000UL, 8000000UL, 16000000UL, 24000000UL, 32000000UL, 48000000UL, 0UL, 0UL, 0UL, 0UL
|
||||
}; /* 0UL values are incorrect cases */
|
||||
|
||||
#if defined(STM32WB55xx) || defined(STM32WB5Mxx) || defined(STM32WB35xx) || defined (STM32WB15xx) || defined (STM32WB1Mxx)
|
||||
const uint32_t SmpsPrescalerTable[4UL][6UL] = {{1UL, 3UL, 2UL, 2UL, 1UL, 2UL}, \
|
||||
{2UL, 6UL, 4UL, 3UL, 2UL, 4UL}, \
|
||||
{4UL, 12UL, 8UL, 6UL, 4UL, 8UL}, \
|
||||
{4UL, 12UL, 8UL, 6UL, 4UL, 8UL}
|
||||
};
|
||||
#endif /* STM32WB55xx || STM32WB5Mxx || STM32WB35xx || STM32WB15xx || STM32WB1Mxx */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32WBxx_System_Private_FunctionPrototypes
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup STM32WBxx_System_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Setup the microcontroller system.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void SystemInit(void)
|
||||
{
|
||||
#if defined(USER_VECT_TAB_ADDRESS)
|
||||
/* Configure the Vector Table location add offset address ------------------*/
|
||||
SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET;
|
||||
#endif /* USER_VECT_TAB_ADDRESS */
|
||||
|
||||
/* FPU settings ------------------------------------------------------------*/
|
||||
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
|
||||
SCB->CPACR |= ((3UL << (10UL * 2UL)) | (3UL << (11UL * 2UL))); /* set CP10 and CP11 Full Access */
|
||||
#endif /* FPU */
|
||||
|
||||
/* Reset the RCC clock configuration to the default reset state ------------*/
|
||||
/* Set MSION bit */
|
||||
RCC->CR |= RCC_CR_MSION;
|
||||
|
||||
/* Reset CFGR register */
|
||||
RCC->CFGR = 0x00070000U;
|
||||
|
||||
/* Reset PLLSAI1ON, PLLON, HSECSSON, HSEON, HSION, and MSIPLLON bits */
|
||||
RCC->CR &= (uint32_t)0xFAF6FEFBU;
|
||||
|
||||
/*!< Reset LSI1 and LSI2 bits */
|
||||
RCC->CSR &= (uint32_t)0xFFFFFFFAU;
|
||||
|
||||
/*!< Reset HSI48ON bit */
|
||||
RCC->CRRCR &= (uint32_t)0xFFFFFFFEU;
|
||||
|
||||
/* Reset PLLCFGR register */
|
||||
RCC->PLLCFGR = 0x22041000U;
|
||||
|
||||
#if defined(STM32WB55xx) || defined(STM32WB5Mxx)
|
||||
/* Reset PLLSAI1CFGR register */
|
||||
RCC->PLLSAI1CFGR = 0x22041000U;
|
||||
#endif /* STM32WB55xx || STM32WB5Mxx */
|
||||
|
||||
/* Reset HSEBYP bit */
|
||||
RCC->CR &= 0xFFFBFFFFU;
|
||||
|
||||
/* Disable all interrupts */
|
||||
RCC->CIER = 0x00000000;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 MSI, SystemCoreClock will contain the MSI_VALUE(*)
|
||||
*
|
||||
* - 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(*) or MSI_VALUE(*) multiplied/divided by the PLL factors.
|
||||
*
|
||||
* (*) MSI_VALUE is a constant defined in stm32wbxx_hal.h file (default value
|
||||
* 4 MHz) but the real value may vary depending on the variations
|
||||
* in voltage and temperature.
|
||||
*
|
||||
* (**) HSI_VALUE is a constant defined in stm32wbxx_hal_conf.h file (default value
|
||||
* 16 MHz) but the real value may vary depending on the variations
|
||||
* in voltage and temperature.
|
||||
*
|
||||
* (***) HSE_VALUE is a constant defined in stm32wbxx_hal_conf.h file (default value
|
||||
* 32 MHz), 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, msirange, pllvco, pllr, pllsource, pllm;
|
||||
|
||||
/* Get MSI Range frequency--------------------------------------------------*/
|
||||
|
||||
/*MSI frequency range in Hz*/
|
||||
msirange = MSIRangeTable[(RCC->CR & RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos];
|
||||
|
||||
/* Get SYSCLK source -------------------------------------------------------*/
|
||||
switch (RCC->CFGR & RCC_CFGR_SWS)
|
||||
{
|
||||
case 0x00: /* MSI used as system clock source */
|
||||
SystemCoreClock = msirange;
|
||||
break;
|
||||
|
||||
case 0x04: /* HSI used as system clock source */
|
||||
/* HSI used as system clock source */
|
||||
SystemCoreClock = HSI_VALUE;
|
||||
break;
|
||||
|
||||
case 0x08: /* HSE used as system clock source */
|
||||
SystemCoreClock = HSE_VALUE;
|
||||
break;
|
||||
|
||||
case 0x0C: /* PLL used as system clock source */
|
||||
/* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
|
||||
SYSCLK = PLL_VCO / PLLR
|
||||
*/
|
||||
pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
|
||||
pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1UL ;
|
||||
|
||||
if (pllsource == 0x02UL) /* HSI used as PLL clock source */
|
||||
{
|
||||
pllvco = (HSI_VALUE / pllm);
|
||||
}
|
||||
else if (pllsource == 0x03UL) /* HSE used as PLL clock source */
|
||||
{
|
||||
pllvco = (HSE_VALUE / pllm);
|
||||
}
|
||||
else /* MSI used as PLL clock source */
|
||||
{
|
||||
pllvco = (msirange / pllm);
|
||||
}
|
||||
|
||||
pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
|
||||
pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1UL);
|
||||
|
||||
SystemCoreClock = pllvco / pllr;
|
||||
break;
|
||||
|
||||
default:
|
||||
SystemCoreClock = msirange;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Compute HCLK clock frequency --------------------------------------------*/
|
||||
/* Get HCLK1 prescaler */
|
||||
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos)];
|
||||
|
||||
/* HCLK clock frequency */
|
||||
SystemCoreClock = SystemCoreClock / tmp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "trinity_helperlib.h"
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* trinity_helperlib.h
|
||||
*
|
||||
* Created on: Aug 17, 2026
|
||||
* Author: pima
|
||||
*/
|
||||
|
||||
#ifndef SRC_TRINITY_HELPERLIB_H_
|
||||
#define SRC_TRINITY_HELPERLIB_H_
|
||||
|
||||
|
||||
|
||||
#endif /* SRC_TRINITY_HELPERLIB_H_ */
|
||||
@@ -0,0 +1,447 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file startup_stm32wb55xx_cm4.s
|
||||
* @author MCD Application Team
|
||||
* @brief STM32WB55xx devices vector table GCC toolchain.
|
||||
* This module performs:
|
||||
* - Set the initial SP
|
||||
* - Set the initial PC == Reset_Handler,
|
||||
* - Set the vector table entries with the exceptions ISR address
|
||||
* - Branches to main in the C library (which eventually
|
||||
* calls main()).
|
||||
* After Reset the Cortex-M4 processor is in Thread mode,
|
||||
* priority is Privileged, and the Stack is set to Main.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2019-2022 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
.cpu cortex-m4
|
||||
.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
|
||||
/* start address for the initialization values of the .MB_MEM2 section.
|
||||
defined in linker script */
|
||||
.word _siMB_MEM2
|
||||
/* start address for the .MB_MEM2 section. defined in linker script */
|
||||
.word _sMB_MEM2
|
||||
/* end address for the .MB_MEM2 section. defined in linker script */
|
||||
.word _eMB_MEM2
|
||||
|
||||
/* INIT_BSS macro is used to fill the specified region [start : end] with zeros */
|
||||
.macro INIT_BSS start, end
|
||||
ldr r0, =\start
|
||||
ldr r1, =\end
|
||||
movs r3, #0
|
||||
bl LoopFillZerobss
|
||||
.endm
|
||||
|
||||
/* INIT_DATA macro is used to copy data in the region [start : end] starting from 'src' */
|
||||
.macro INIT_DATA start, end, src
|
||||
ldr r0, =\start
|
||||
ldr r1, =\end
|
||||
ldr r2, =\src
|
||||
movs r3, #0
|
||||
bl LoopCopyDataInit
|
||||
.endm
|
||||
|
||||
.section .text.data_initializers
|
||||
CopyDataInit:
|
||||
ldr r4, [r2, r3]
|
||||
str r4, [r0, r3]
|
||||
adds r3, r3, #4
|
||||
|
||||
LoopCopyDataInit:
|
||||
adds r4, r0, r3
|
||||
cmp r4, r1
|
||||
bcc CopyDataInit
|
||||
bx lr
|
||||
|
||||
FillZerobss:
|
||||
str r3, [r0]
|
||||
adds r0, r0, #4
|
||||
|
||||
LoopFillZerobss:
|
||||
cmp r0, r1
|
||||
bcc FillZerobss
|
||||
bx lr
|
||||
|
||||
.section .text.Reset_Handler
|
||||
.weak Reset_Handler
|
||||
.type Reset_Handler, %function
|
||||
Reset_Handler:
|
||||
ldr r0, =_estack
|
||||
mov sp, r0 /* set stack pointer */
|
||||
/* Call the clock system initialization function.*/
|
||||
bl SystemInit
|
||||
|
||||
/* Copy the data segment initializers from flash to SRAM */
|
||||
INIT_DATA _sdata, _edata, _sidata
|
||||
INIT_DATA _sMB_MEM2, _eMB_MEM2, _siMB_MEM2
|
||||
|
||||
/* Zero fill the bss segments. */
|
||||
INIT_BSS _sbss, _ebss
|
||||
|
||||
/* Call static constructors */
|
||||
bl __libc_init_array
|
||||
/* Call the application s entry point.*/
|
||||
bl main
|
||||
|
||||
LoopForever:
|
||||
b LoopForever
|
||||
|
||||
.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-M4. 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
|
||||
|
||||
|
||||
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_PVM_IRQHandler
|
||||
.word TAMP_STAMP_LSECSS_IRQHandler
|
||||
.word RTC_WKUP_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_IRQHandler
|
||||
.word USB_HP_IRQHandler
|
||||
.word USB_LP_IRQHandler
|
||||
.word C2SEV_PWR_C2H_IRQHandler
|
||||
.word COMP_IRQHandler
|
||||
.word EXTI9_5_IRQHandler
|
||||
.word TIM1_BRK_IRQHandler
|
||||
.word TIM1_UP_TIM16_IRQHandler
|
||||
.word TIM1_TRG_COM_TIM17_IRQHandler
|
||||
.word TIM1_CC_IRQHandler
|
||||
.word TIM2_IRQHandler
|
||||
.word PKA_IRQHandler
|
||||
.word I2C1_EV_IRQHandler
|
||||
.word I2C1_ER_IRQHandler
|
||||
.word I2C3_EV_IRQHandler
|
||||
.word I2C3_ER_IRQHandler
|
||||
.word SPI1_IRQHandler
|
||||
.word SPI2_IRQHandler
|
||||
.word USART1_IRQHandler
|
||||
.word LPUART1_IRQHandler
|
||||
.word SAI1_IRQHandler
|
||||
.word TSC_IRQHandler
|
||||
.word EXTI15_10_IRQHandler
|
||||
.word RTC_Alarm_IRQHandler
|
||||
.word CRS_IRQHandler
|
||||
.word PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler
|
||||
.word IPCC_C1_RX_IRQHandler
|
||||
.word IPCC_C1_TX_IRQHandler
|
||||
.word HSEM_IRQHandler
|
||||
.word LPTIM1_IRQHandler
|
||||
.word LPTIM2_IRQHandler
|
||||
.word LCD_IRQHandler
|
||||
.word QUADSPI_IRQHandler
|
||||
.word AES1_IRQHandler
|
||||
.word AES2_IRQHandler
|
||||
.word RNG_IRQHandler
|
||||
.word FPU_IRQHandler
|
||||
.word DMA2_Channel1_IRQHandler
|
||||
.word DMA2_Channel2_IRQHandler
|
||||
.word DMA2_Channel3_IRQHandler
|
||||
.word DMA2_Channel4_IRQHandler
|
||||
.word DMA2_Channel5_IRQHandler
|
||||
.word DMA2_Channel6_IRQHandler
|
||||
.word DMA2_Channel7_IRQHandler
|
||||
.word DMAMUX1_OVR_IRQHandler
|
||||
|
||||
.size g_pfnVectors, .-g_pfnVectors
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* 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_PVM_IRQHandler
|
||||
.thumb_set PVD_PVM_IRQHandler,Default_Handler
|
||||
|
||||
.weak TAMP_STAMP_LSECSS_IRQHandler
|
||||
.thumb_set TAMP_STAMP_LSECSS_IRQHandler,Default_Handler
|
||||
|
||||
.weak RTC_WKUP_IRQHandler
|
||||
.thumb_set RTC_WKUP_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_IRQHandler
|
||||
.thumb_set ADC1_IRQHandler,Default_Handler
|
||||
|
||||
.weak USB_HP_IRQHandler
|
||||
.thumb_set USB_HP_IRQHandler,Default_Handler
|
||||
|
||||
.weak USB_LP_IRQHandler
|
||||
.thumb_set USB_LP_IRQHandler,Default_Handler
|
||||
|
||||
.weak C2SEV_PWR_C2H_IRQHandler
|
||||
.thumb_set C2SEV_PWR_C2H_IRQHandler,Default_Handler
|
||||
|
||||
.weak COMP_IRQHandler
|
||||
.thumb_set COMP_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_TIM16_IRQHandler
|
||||
.thumb_set TIM1_UP_TIM16_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM1_TRG_COM_TIM17_IRQHandler
|
||||
.thumb_set TIM1_TRG_COM_TIM17_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM1_CC_IRQHandler
|
||||
.thumb_set TIM1_CC_IRQHandler,Default_Handler
|
||||
|
||||
.weak TIM2_IRQHandler
|
||||
.thumb_set TIM2_IRQHandler,Default_Handler
|
||||
|
||||
.weak PKA_IRQHandler
|
||||
.thumb_set PKA_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 I2C3_EV_IRQHandler
|
||||
.thumb_set I2C3_EV_IRQHandler,Default_Handler
|
||||
|
||||
.weak I2C3_ER_IRQHandler
|
||||
.thumb_set I2C3_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 LPUART1_IRQHandler
|
||||
.thumb_set LPUART1_IRQHandler,Default_Handler
|
||||
|
||||
.weak SAI1_IRQHandler
|
||||
.thumb_set SAI1_IRQHandler,Default_Handler
|
||||
|
||||
.weak TSC_IRQHandler
|
||||
.thumb_set TSC_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 CRS_IRQHandler
|
||||
.thumb_set CRS_IRQHandler,Default_Handler
|
||||
|
||||
.weak PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler
|
||||
.thumb_set PWR_SOTF_BLEACT_802ACT_RFPHASE_IRQHandler,Default_Handler
|
||||
|
||||
.weak IPCC_C1_RX_IRQHandler
|
||||
.thumb_set IPCC_C1_RX_IRQHandler,Default_Handler
|
||||
|
||||
.weak IPCC_C1_TX_IRQHandler
|
||||
.thumb_set IPCC_C1_TX_IRQHandler,Default_Handler
|
||||
|
||||
.weak HSEM_IRQHandler
|
||||
.thumb_set HSEM_IRQHandler,Default_Handler
|
||||
|
||||
.weak LPTIM1_IRQHandler
|
||||
.thumb_set LPTIM1_IRQHandler,Default_Handler
|
||||
|
||||
.weak LPTIM2_IRQHandler
|
||||
.thumb_set LPTIM2_IRQHandler,Default_Handler
|
||||
|
||||
.weak LCD_IRQHandler
|
||||
.thumb_set LCD_IRQHandler,Default_Handler
|
||||
|
||||
.weak QUADSPI_IRQHandler
|
||||
.thumb_set QUADSPI_IRQHandler,Default_Handler
|
||||
|
||||
.weak AES1_IRQHandler
|
||||
.thumb_set AES1_IRQHandler,Default_Handler
|
||||
|
||||
.weak AES2_IRQHandler
|
||||
.thumb_set AES2_IRQHandler,Default_Handler
|
||||
|
||||
.weak RNG_IRQHandler
|
||||
.thumb_set RNG_IRQHandler,Default_Handler
|
||||
|
||||
.weak FPU_IRQHandler
|
||||
.thumb_set FPU_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA2_Channel1_IRQHandler
|
||||
.thumb_set DMA2_Channel1_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA2_Channel2_IRQHandler
|
||||
.thumb_set DMA2_Channel2_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA2_Channel3_IRQHandler
|
||||
.thumb_set DMA2_Channel3_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA2_Channel4_IRQHandler
|
||||
.thumb_set DMA2_Channel4_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA2_Channel5_IRQHandler
|
||||
.thumb_set DMA2_Channel5_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA2_Channel6_IRQHandler
|
||||
.thumb_set DMA2_Channel6_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMA2_Channel7_IRQHandler
|
||||
.thumb_set DMA2_Channel7_IRQHandler,Default_Handler
|
||||
|
||||
.weak DMAMUX1_OVR_IRQHandler
|
||||
.thumb_set DMAMUX1_OVR_IRQHandler,Default_Handler
|
||||
|
||||
Reference in New Issue
Block a user