diff --git a/.cproject b/.cproject
index 3e952a4..dae76af 100644
--- a/.cproject
+++ b/.cproject
@@ -23,7 +23,7 @@
-
+
@@ -40,11 +40,12 @@
-
+
-
+
-
+
@@ -193,6 +197,7 @@
@@ -229,6 +235,7 @@
diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
index fb4990c..5d25771 100644
--- a/.settings/language.settings.xml
+++ b/.settings/language.settings.xml
@@ -5,7 +5,7 @@
-
+
@@ -16,7 +16,7 @@
-
+
diff --git a/.vscode/settings.json b/.vscode/settings.json
index dfff459..232c089 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -107,7 +107,9 @@
"span": "cpp",
"xs_device_id.h": "c",
"xs_log.h": "c",
- "xs_basic.h": "c"
+ "xs_basic.h": "c",
+ "task.h": "c",
+ "stddef.h": "c"
},
"files.autoGuessEncoding": false,
"files.encoding": "gbk"
diff --git a/Core/Src/gpio.c b/Core/Src/gpio.c
index bbfbb82..646ddd7 100644
--- a/Core/Src/gpio.c
+++ b/Core/Src/gpio.c
@@ -88,11 +88,11 @@ void MX_GPIO_Init(void)
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PB0 PB1 PB2 PB14
- PB15 PB3 PB4 PB6
- PB7 PB8 PB9 */
+ PB15 PB4 PB6 PB7
+ PB8 PB9 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_14
- |GPIO_PIN_15|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_6
- |GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
+ |GPIO_PIN_15|GPIO_PIN_4|GPIO_PIN_6|GPIO_PIN_7
+ |GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
diff --git a/Core/ThreadSafe/newlib_lock_glue.c b/Core/ThreadSafe/newlib_lock_glue.c
new file mode 100644
index 0000000..0bd72c8
--- /dev/null
+++ b/Core/ThreadSafe/newlib_lock_glue.c
@@ -0,0 +1,423 @@
+/**
+ ******************************************************************************
+ * @file newlib_lock_glue.c
+ * @author STMicroelectronics
+ * @brief Implementation of newlib lock interface
+ *
+ * @details This file implements locking glue necessary to protect C library
+ * functions and initialization of local static objects in C++.
+ * Lock strategies are defined in stm32_lock.h that implements
+ * different level of thread-safety.
+ *
+ * For more information about which C functions need which of these
+ * low level functions, please consult the newlib libc manual,
+ * see https://sourceware.org/newlib/libc.html
+ *
+ * For more information about the one-time construction API for C++,
+ * see https://itanium-cxx-abi.github.io/cxx-abi/abi.html#once-ctor
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2024 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.
+ *
+ ******************************************************************************
+ */
+
+#if !defined (__GNUC__) || defined (__CC_ARM)
+#error "newlib_lock_glue.c" should be used with GNU Compilers only
+#endif /* !defined (__GNUC__) || defined (__CC_ARM) */
+
+/* Includes ------------------------------------------------------------------*/
+#include
+
+/* Private functions ---------------------------------------------------------*/
+
+/**
+ * @brief Global Error_Handler
+ */
+__WEAK void Error_Handler(void)
+{
+ /* Not used if it exists in project */
+ while (1);
+}
+
+#ifdef __SINGLE_THREAD__
+#warning C library is in single-threaded mode. Please take care when using C library functions in threaded contexts
+#else
+
+/* Includes ------------------------------------------------------------------*/
+#include
+#include
+#include "stm32_lock.h"
+
+/**
+ * @defgroup _newlib_lock_functions newlib library locks
+ * @see https://sourceware.org/newlib/libc.html
+ * @{
+ */
+
+#if __NEWLIB__ >= 3 && defined (_RETARGETABLE_LOCKING)
+#include
+#include
+#include
+
+/* Private macros ------------------------------------------------------------*/
+/** See struct __lock definition */
+#define STM32_LOCK_PARAMETER(lock) (&(lock)->lock_data)
+
+/* Private variables ---------------------------------------------------------*/
+struct __lock
+{
+ LockingData_t lock_data; /**< The STM32 lock instance */
+};
+
+/** Implementing mutex from newlib/libc/misc/lock.c */
+struct __lock __lock___sinit_recursive_mutex = { LOCKING_DATA_INIT };
+
+/** Implementing mutex from newlib/libc/misc/lock.c */
+struct __lock __lock___sfp_recursive_mutex = { LOCKING_DATA_INIT };
+
+/** Implementing mutex from newlib/libc/misc/lock.c */
+struct __lock __lock___atexit_recursive_mutex = { LOCKING_DATA_INIT };
+
+/** Implementing mutex from newlib/libc/misc/lock.c */
+struct __lock __lock___at_quick_exit_mutex = { LOCKING_DATA_INIT };
+
+/** Implementing mutex from newlib/libc/misc/lock.c */
+struct __lock __lock___malloc_recursive_mutex = { LOCKING_DATA_INIT };
+
+/** Implementing mutex from newlib/libc/misc/lock.c */
+struct __lock __lock___env_recursive_mutex = { LOCKING_DATA_INIT };
+
+/** Implementing mutex from newlib/libc/misc/lock.c */
+struct __lock __lock___tz_mutex = { LOCKING_DATA_INIT };
+
+/** Implementing mutex from newlib/libc/misc/lock.c */
+struct __lock __lock___dd_hash_mutex = { LOCKING_DATA_INIT };
+
+/** Implementing mutex from newlib/libc/misc/lock.c */
+struct __lock __lock___arc4random_mutex = { LOCKING_DATA_INIT };
+
+/* Private functions ---------------------------------------------------------*/
+
+/**
+ * @brief Initialize lock
+ * @param lock The lock
+ */
+void __retarget_lock_init(_LOCK_T *lock)
+{
+ __retarget_lock_init_recursive(lock);
+}
+
+/**
+ * @brief Initialize recursive lock
+ * @param lock The lock
+ */
+void __retarget_lock_init_recursive(_LOCK_T *lock)
+{
+ if (lock == NULL)
+ {
+ errno = EINVAL;
+ return;
+ }
+
+ *lock = (_LOCK_T)malloc(sizeof(struct __lock));
+ if (*lock != NULL)
+ {
+ stm32_lock_init(STM32_LOCK_PARAMETER(*lock));
+ return;
+ }
+
+ /* Unable to allocate memory */
+ STM32_LOCK_BLOCK();
+}
+
+/**
+ * @brief Close lock
+ * @param lock The lock
+ */
+void __retarget_lock_close(_LOCK_T lock)
+{
+ __retarget_lock_close_recursive(lock);
+}
+
+/**
+ * @brief Close recursive lock
+ * @param lock The lock
+ */
+void __retarget_lock_close_recursive(_LOCK_T lock)
+{
+ free(lock);
+}
+
+/**
+ * @brief Acquire lock
+ * @param lock The lock
+ */
+void __retarget_lock_acquire(_LOCK_T lock)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+ stm32_lock_acquire(STM32_LOCK_PARAMETER(lock));
+}
+
+/**
+ * @brief Acquire recursive lock
+ * @param lock The lock
+ */
+void __retarget_lock_acquire_recursive(_LOCK_T lock)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+ stm32_lock_acquire(STM32_LOCK_PARAMETER(lock));
+}
+
+/**
+ * @brief Try acquire lock
+ * @param lock The lock
+ * @return 0 always
+ */
+int __retarget_lock_try_acquire(_LOCK_T lock)
+{
+ __retarget_lock_acquire(lock);
+ return 0;
+}
+
+/**
+ * @brief Try acquire recursive lock
+ * @param lock The lock
+ * @return 0 always
+ */
+int __retarget_lock_try_acquire_recursive(_LOCK_T lock)
+{
+ __retarget_lock_acquire_recursive(lock);
+ return 0;
+}
+
+/**
+ * @brief Release lock
+ * @param lock The lock
+ */
+void __retarget_lock_release(_LOCK_T lock)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+ stm32_lock_release(STM32_LOCK_PARAMETER(lock));
+}
+
+/**
+ * @brief Release recursive lock
+ * @param lock The lock
+ */
+void __retarget_lock_release_recursive(_LOCK_T lock)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+ stm32_lock_release(STM32_LOCK_PARAMETER(lock));
+}
+
+#else
+#warning This makes malloc, env, and TZ calls thread-safe, not the entire newlib
+
+/* Includes ------------------------------------------------------------------*/
+#include
+
+/* Private variables ---------------------------------------------------------*/
+/** Mutex used in __malloc_lock and __malloc_unlock */
+static LockingData_t __lock___malloc_recursive_mutex = LOCKING_DATA_INIT;
+
+/** Mutex used in __env_lock and __env_unlock */
+static LockingData_t __lock___env_recursive_mutex = LOCKING_DATA_INIT;
+
+/** Mutex used in __tz_lock and __tz_unlock */
+static LockingData_t __lock___tz_mutex = LOCKING_DATA_INIT;
+
+/* Private functions ---------------------------------------------------------*/
+
+#if __STD_C
+
+/**
+ * @brief Acquire malloc lock
+ * @param reent The reentrance struct
+ */
+void __malloc_lock(struct _reent *reent)
+{
+ STM32_LOCK_UNUSED(reent);
+ stm32_lock_acquire(&__lock___malloc_recursive_mutex);
+}
+
+/**
+ * @brief Release malloc lock
+ * @param reent The reentrance struct
+ */
+void __malloc_unlock(struct _reent *reent)
+{
+ STM32_LOCK_UNUSED(reent);
+ stm32_lock_release(&__lock___malloc_recursive_mutex);
+}
+
+#else
+
+/**
+ * @brief Acquire malloc lock
+ */
+void __malloc_lock()
+{
+ stm32_lock_acquire(&__lock___malloc_recursive_mutex);
+}
+
+/**
+ * @brief Release malloc lock
+ */
+void __malloc_unlock()
+{
+ stm32_lock_release(&__lock___malloc_recursive_mutex);
+}
+#endif /* __STD_C */
+
+/**
+ * @brief Acquire env lock
+ * @param reent The reentrance struct
+ */
+void __env_lock(struct _reent *reent)
+{
+ STM32_LOCK_UNUSED(reent);
+ stm32_lock_acquire(&__lock___env_recursive_mutex);
+}
+
+/**
+ * @brief Release env lock
+ * @param reent The reentrance struct
+ */
+void __env_unlock(struct _reent *reent)
+{
+ STM32_LOCK_UNUSED(reent);
+ stm32_lock_release(&__lock___env_recursive_mutex);
+}
+
+/**
+ * @brief Acquire tz lock
+ */
+void __tz_lock()
+{
+ stm32_lock_acquire(&__lock___tz_mutex);
+}
+
+/**
+ * @brief Release tz lock
+ */
+void __tz_unlock()
+{
+ stm32_lock_release(&__lock___tz_mutex);
+}
+
+#endif /* __NEWLIB__ >= 3 && defined (_RETARGETABLE_LOCKING) */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup __cxa_guard_ GNU C++ one-time construction API
+ * @see https://itanium-cxx-abi.github.io/cxx-abi/abi.html#once-ctor
+ *
+ * When building for C++, please make sure that -fno-threadsafe-statics is not passed to the compiler
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/** The guard object is created by the C++ compiler and is 32 bit for ARM EABI. */
+typedef struct
+{
+ atomic_uchar initialized; /**< Indicate if object is initialized */
+ uint8_t acquired; /**< Ensure non-recursive lock */
+ uint16_t unused; /**< Padding */
+} __attribute__((packed)) CxaGuardObject_t;
+
+/* Private variables ---------------------------------------------------------*/
+/** Mutex used in __cxa_guard_acquire, __cxa_guard_release and __cxa_guard_abort */
+static LockingData_t __cxa_guard_mutex = LOCKING_DATA_INIT;
+
+/* Private functions ---------------------------------------------------------*/
+
+/**
+ * @brief Acquire __cxa_guard mutex
+ * @param guard_object Guard object
+ * @return 0 if object is initialized, else initialization of object required
+ */
+int __cxa_guard_acquire(CxaGuardObject_t *guard_object)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(guard_object);
+
+ if (atomic_load(&guard_object->initialized) == 0)
+ {
+ /* Object needs initialization, lock threading context */
+ stm32_lock_acquire(&__cxa_guard_mutex);
+ if (atomic_load(&guard_object->initialized) == 0)
+ {
+ /* Object needs initialization */
+ if (guard_object->acquired)
+ {
+ /* Object initialization already in progress */
+ STM32_LOCK_BLOCK();
+ }
+
+ /* Lock acquired */
+ guard_object->acquired = 1;
+ return 1;
+ }
+ else
+ {
+ /* Object initialized in another thread */
+ stm32_lock_release(&__cxa_guard_mutex);
+ }
+ }
+
+ /* Object already initialized */
+ return 0;
+}
+
+/**
+ * @brief Abort __cxa_guard mutex
+ * @param guard_object Guard object
+ */
+void __cxa_guard_abort(CxaGuardObject_t *guard_object)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(guard_object);
+
+ if (guard_object->acquired)
+ {
+ /* Release lock */
+ guard_object->acquired = 0;
+ stm32_lock_release(&__cxa_guard_mutex);
+ }
+ else
+ {
+ /* Trying to release non-acquired lock */
+ STM32_LOCK_BLOCK();
+ }
+}
+
+/**
+ * @brief Release __cxa_guard mutex
+ * @param guard_object Guard object
+ */
+void __cxa_guard_release(CxaGuardObject_t *guard_object)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(guard_object);
+
+ /* Object initialized */
+ atomic_store(&guard_object->initialized, 1);
+
+ /* Release lock */
+ __cxa_guard_abort(guard_object);
+}
+
+/**
+ * @}
+ */
+
+#endif /* __SINGLE_THREAD__ */
diff --git a/Core/ThreadSafe/stm32_lock.h b/Core/ThreadSafe/stm32_lock.h
new file mode 100644
index 0000000..c8a7469
--- /dev/null
+++ b/Core/ThreadSafe/stm32_lock.h
@@ -0,0 +1,375 @@
+/**
+ ******************************************************************************
+ * @file stm32_lock.h
+ * @author STMicroelectronics
+ * @brief STMicroelectronics lock mechanisms
+ *
+ * @details
+ * This implementation supports the following strategies for handling
+ * thread-safe locks. The strategy can be explicitly selected by
+ * defining \STM32_THREAD_SAFE_STRATEGY = \ in the project.
+ * Please look at the '_lock_glue.c' file for more details.
+ *
+ * 1. User defined thread-safe implementation.
+ * User defined solution for handling thread-safety.
+ *
+ * NOTE: The stubs in stm32_lock_user.h needs to be implemented to gain
+ * thread-safety.
+ *
+ * 2. [DEFAULT] Allow lock usage from interrupts.
+ * This implementation will ensure thread-safety by disabling all interrupts
+ * during e.g. calls to malloc.
+ *
+ * NOTE: Disabling all interrupts creates interrupt latency which
+ * might not be desired for this application!
+ *
+ * 3. Deny lock usage from interrupts.
+ * This implementation assumes single thread of execution.
+ *
+ * NOTE: Thread-safety dependent functions will enter an infinity loop
+ * if used in interrupt context.
+ *
+ * 4. Allow lock usage from interrupts. Implemented using FreeRTOS locks.
+ * This implementation will ensure thread-safety by entering RTOS ISR capable
+ * critical sections during e.g. calls to malloc.
+ * By default this implementation supports 2 levels of recursive locking.
+ * Adding additional levels requires 4 bytes per lock per level of RAM.
+ *
+ * NOTE: Interrupts with high priority are not disabled. This implies
+ * that the lock is not thread-safe from high priority interrupts!
+ *
+ * 5. Deny lock usage from interrupts. Implemented using FreeRTOS locks.
+ * This implementation will ensure thread-safety by suspending all tasks
+ * during e.g. calls to malloc.
+ *
+ * NOTE: Thread-safety dependent functions will enter an infinity loop
+ * if used in interrupt context.
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2024 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.
+ *
+ ******************************************************************************
+ */
+
+#ifndef __STM32_LOCK_H__
+#define __STM32_LOCK_H__
+
+/* Includes ------------------------------------------------------------------*/
+#include
+#include
+#include
+
+#ifndef STM32_THREAD_SAFE_STRATEGY
+#define STM32_THREAD_SAFE_STRATEGY 2 /**< Assume strategy 2 if not specified */
+#endif /* STM32_THREAD_SAFE_STRATEGY */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Function prototypes -------------------------------------------------------*/
+void Error_Handler(void);
+
+/* Public macros -------------------------------------------------------------*/
+/** Blocks execution */
+#define STM32_LOCK_BLOCK() \
+ do \
+ { \
+ __disable_irq(); \
+ Error_Handler(); \
+ while (1); \
+ } while (0)
+
+/** Blocks execution if argument is NULL */
+#define STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(x) \
+ do \
+ { \
+ if ((x) == NULL) \
+ { \
+ STM32_LOCK_BLOCK(); \
+ } \
+ } while (0)
+
+/** Blocks execution if in interrupt context */
+#define STM32_LOCK_BLOCK_IF_INTERRUPT_CONTEXT() \
+ do \
+ { \
+ if (__get_IPSR()) \
+ { \
+ STM32_LOCK_BLOCK(); \
+ } \
+ } while (0)
+
+/** Hide unused parameter warning from compiler */
+#define STM32_LOCK_UNUSED(var) (void)var
+
+/** Size of array */
+#define STM32_LOCK_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+
+#if STM32_THREAD_SAFE_STRATEGY == 1
+/*
+ * User defined thread-safe implementation.
+ */
+
+/* Includes ----------------------------------------------------------------*/
+/** STM32 lock API version */
+#define STM32_LOCK_API 1
+#include "stm32_lock_user.h"
+#undef STM32_LOCK_API
+
+#elif STM32_THREAD_SAFE_STRATEGY == 2
+/*
+ * Allow lock usage from interrupts.
+ */
+
+/* Private defines ---------------------------------------------------------*/
+/** Initialize members in instance of LockingData_t
structure */
+#define LOCKING_DATA_INIT { 0, 0 }
+
+/* Private typedef ---------------------------------------------------------*/
+typedef struct
+{
+ uint8_t flag; /**< Backup of PRIMASK.PM at nesting level 0 */
+ uint8_t counter; /**< Nesting level */
+} LockingData_t;
+
+/* Private functions -------------------------------------------------------*/
+
+/**
+ * @brief Initialize STM32 lock
+ * @param lock The lock to init
+ */
+static inline void stm32_lock_init(LockingData_t *lock)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+ lock->flag = 0;
+ lock->counter = 0;
+}
+
+/**
+ * @brief Acquire STM32 lock
+ * @param lock The lock to acquire
+ */
+static inline void stm32_lock_acquire(LockingData_t *lock)
+{
+ uint8_t flag = (uint8_t)(__get_PRIMASK() & 0x1); /* PRIMASK.PM */
+ __disable_irq();
+ __DSB();
+ __ISB();
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+ if (lock->counter == 0)
+ {
+ lock->flag = flag;
+ }
+ else if (lock->counter == UINT8_MAX)
+ {
+ STM32_LOCK_BLOCK();
+ }
+ lock->counter++;
+}
+
+/**
+ * @brief Release STM32 lock
+ * @param lock The lock to release
+ */
+static inline void stm32_lock_release(LockingData_t *lock)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+ if (lock->counter == 0)
+ {
+ STM32_LOCK_BLOCK();
+ }
+ lock->counter--;
+ if (lock->counter == 0 && lock->flag == 0)
+ {
+ __enable_irq();
+ }
+}
+
+#elif STM32_THREAD_SAFE_STRATEGY == 3
+/*
+ * Deny lock usage from interrupts.
+ */
+
+/* Private defines ---------------------------------------------------------*/
+/** Initialize members in instance of LockingData_t
structure */
+#define LOCKING_DATA_INIT 0
+
+/* Private typedef ---------------------------------------------------------*/
+typedef uint8_t LockingData_t; /**< Unused */
+
+/* Private functions -------------------------------------------------------*/
+
+/**
+ * @brief Initialize STM32 lock
+ * @param lock The lock to init
+ */
+static inline void stm32_lock_init(LockingData_t *lock)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+}
+
+/**
+ * @brief Acquire STM32 lock
+ * @param lock The lock to acquire
+ */
+static inline void stm32_lock_acquire(LockingData_t *lock)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+ STM32_LOCK_BLOCK_IF_INTERRUPT_CONTEXT();
+}
+
+/**
+ * @brief Release ST lock
+ * @param lock The lock to release
+ */
+static inline void stm32_lock_release(LockingData_t *lock)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+ STM32_LOCK_BLOCK_IF_INTERRUPT_CONTEXT();
+}
+
+#elif STM32_THREAD_SAFE_STRATEGY == 4
+/*
+ * Allow lock usage from interrupts. Implemented using FreeRTOS locks.
+ */
+
+/* Includes ----------------------------------------------------------------*/
+#include
+#include
+
+#if defined (__GNUC__) && !defined (__CC_ARM) && configUSE_NEWLIB_REENTRANT == 0
+#warning Please set configUSE_NEWLIB_REENTRANT to 1 in FreeRTOSConfig.h, otherwise newlib will not be thread-safe
+#endif /* defined (__GNUC__) && !defined (__CC_ARM) && configUSE_NEWLIB_REENTRANT == 0 */
+
+/* Private defines ---------------------------------------------------------*/
+/** Initialize members in instance of LockingData_t
structure */
+#define LOCKING_DATA_INIT { {0, 0}, 0 }
+#define STM32_LOCK_MAX_NESTED_LEVELS 2 /**< Max nesting level of interrupts */
+typedef struct
+{
+ uint32_t basepri[STM32_LOCK_MAX_NESTED_LEVELS];
+ uint8_t nesting_level;
+} LockingData_t;
+
+/* Private macros ----------------------------------------------------------*/
+/** Blocks execution if reached max nesting level */
+#define STM32_LOCK_ASSERT_VALID_NESTING_LEVEL(lock) \
+ do \
+ { \
+ if (lock->nesting_level >= STM32_LOCK_ARRAY_SIZE(lock->basepri)) \
+ { \
+ STM32_LOCK_BLOCK(); \
+ } \
+ } while (0)
+
+/* Private functions -------------------------------------------------------*/
+
+/**
+ * @brief Initialize STM32 lock
+ * @param lock The lock to init
+ */
+static inline void stm32_lock_init(LockingData_t *lock)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+ for (size_t i = 0; i < STM32_LOCK_ARRAY_SIZE(lock->basepri); i++)
+ {
+ lock->basepri[i] = 0;
+ }
+ lock->nesting_level = 0;
+}
+
+/**
+ * @brief Acquire STM32 lock
+ * @param lock The lock to acquire
+ */
+static inline void stm32_lock_acquire(LockingData_t *lock)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+ STM32_LOCK_ASSERT_VALID_NESTING_LEVEL(lock);
+ lock->basepri[lock->nesting_level++] = taskENTER_CRITICAL_FROM_ISR();
+}
+
+/**
+ * @brief Release STM32 lock
+ * @param lock The lock to release
+ */
+static inline void stm32_lock_release(LockingData_t *lock)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+ lock->nesting_level--;
+ STM32_LOCK_ASSERT_VALID_NESTING_LEVEL(lock);
+ taskEXIT_CRITICAL_FROM_ISR(lock->basepri[lock->nesting_level]);
+}
+
+#undef STM32_LOCK_ASSERT_VALID_NESTING_LEVEL
+#undef STM32_LOCK_MAX_NESTED_LEVELS
+
+#elif STM32_THREAD_SAFE_STRATEGY == 5
+/*
+ * Deny lock usage from interrupts. Implemented using FreeRTOS locks.
+ */
+
+/* Includes ----------------------------------------------------------------*/
+#include
+#include
+#if defined (__GNUC__) && !defined (__CC_ARM) && configUSE_NEWLIB_REENTRANT == 0
+#warning Please set configUSE_NEWLIB_REENTRANT to 1 in FreeRTOSConfig.h, otherwise newlib will not be thread-safe
+#endif /* defined (__GNUC__) && !defined (__CC_ARM) && configUSE_NEWLIB_REENTRANT == 0 */
+
+/* Private defines ---------------------------------------------------------*/
+/** Initialize members in instance of LockingData_t
structure */
+#define LOCKING_DATA_INIT 0
+
+/* Private typedef ---------------------------------------------------------*/
+typedef uint8_t LockingData_t; /**< Unused */
+
+/* Private functions -------------------------------------------------------*/
+
+/**
+ * @brief Initialize STM32 lock
+ * @param lock The lock to init
+ */
+static inline void stm32_lock_init(LockingData_t *lock)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+}
+
+/**
+ * @brief Acquire STM32 lock
+ * @param lock The lock to acquire
+ */
+static inline void stm32_lock_acquire(LockingData_t *lock)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+ STM32_LOCK_BLOCK_IF_INTERRUPT_CONTEXT();
+ vTaskSuspendAll();
+}
+
+/**
+ * @brief Release STM32 lock
+ * @param lock The lock to release
+ */
+static inline void stm32_lock_release(LockingData_t *lock)
+{
+ STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);
+ STM32_LOCK_BLOCK_IF_INTERRUPT_CONTEXT();
+ xTaskResumeAll();
+}
+
+#else
+#error Invalid STM32_THREAD_SAFE_STRATEGY specified
+#endif /* STM32_THREAD_SAFE_STRATEGY */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* __STM32_LOCK_H__ */
diff --git a/LWIP/Target/ethernetif.c b/LWIP/Target/ethernetif.c
index f9a2c5f..14ab9f2 100644
--- a/LWIP/Target/ethernetif.c
+++ b/LWIP/Target/ethernetif.c
@@ -384,14 +384,17 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p)
TxConfig.pData = p;
pbuf_ref(p);
-
- HAL_ETH_Transmit_IT(&heth, &TxConfig);
- while(osSemaphoreWait(TxPktSemaphore, TIME_WAITING_FOR_INPUT)!=osOK)
-
- {
+ HAL_StatusTypeDef halecode = HAL_ETH_Transmit_IT(&heth, &TxConfig);
+ if (halecode == HAL_OK) {
+ if(osSemaphoreWait(TxPktSemaphore, 10) != osOK){
+ errval = ERR_TIMEOUT;
+ }else{
+ }
+ } else {
+ errval = ERR_TIMEOUT;
}
-
HAL_ETH_ReleaseTxPacket(&heth);
+ // printf("low_level_output: TX.....end\n");
return errval;
}
diff --git a/LWIP/Target/lwipopts.h b/LWIP/Target/lwipopts.h
index aa5ac20..444c6bc 100644
--- a/LWIP/Target/lwipopts.h
+++ b/LWIP/Target/lwipopts.h
@@ -1,21 +1,21 @@
/* USER CODE BEGIN Header */
/**
- ******************************************************************************
- * File Name : lwipopts.h
- * Description : This file overrides LwIP stack default configuration
- * done in opt.h file.
- ******************************************************************************
- * @attention
- *
- * Copyright (c) 2023 STMicroelectronics.
- * All rights reserved.
- *
- * This software is licensed under terms that can be found in the LICENSE file
- * in the root directory of this software component.
- * If no LICENSE file comes with this software, it is provided AS-IS.
- *
- ******************************************************************************
- */
+ ******************************************************************************
+ * File Name : lwipopts.h
+ * Description : This file overrides LwIP stack default configuration
+ * done in opt.h file.
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2023 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 --------------------------------------*/
@@ -34,7 +34,7 @@
/* USER CODE END 0 */
#ifdef __cplusplus
- extern "C" {
+extern "C" {
#endif
/* STM32CubeMX Specific Parameters (not defined in opt.h) ---------------------*/
@@ -62,7 +62,7 @@
/*----- Default Value for LWIP_DHCP_AUTOIP_COOP: 0 ---*/
#define LWIP_DHCP_AUTOIP_COOP 1
/*----- Default Value for LWIP_DHCP_AUTOIP_COOP_TRIES: 9 ---*/
-#define LWIP_DHCP_AUTOIP_COOP_TRIES 1
+#define LWIP_DHCP_AUTOIP_COOP_TRIES 0
/*----- Value in opt.h for LWIP_DNS_SECURE: (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT) -*/
#define LWIP_DNS_SECURE 7
/*----- Value in opt.h for TCP_SND_QUEUELEN: (4*TCP_SND_BUF + (TCP_MSS - 1))/TCP_MSS -----*/
@@ -131,9 +131,44 @@
#define CHECKSUM_CHECK_ICMP6 0
/*-----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
-
+// #define LWIP_DEBUG
+#define LWIP_IPV6_SCOPES_DEBUG LWIP_DBG_ON
+#define ETHARP_DEBUG LWIP_DBG_ON
+#define NETIF_DEBUG LWIP_DBG_ON
+#define PBUF_DEBUG LWIP_DBG_ON
+#define API_LIB_DEBUG LWIP_DBG_ON
+#define API_MSG_DEBUG LWIP_DBG_ON
+#define SOCKETS_DEBUG LWIP_DBG_ON
+#define ICMP_DEBUG LWIP_DBG_ON
+#define IGMP_DEBUG LWIP_DBG_ON
+#define INET_DEBUG LWIP_DBG_ON
+#define IP_DEBUG LWIP_DBG_ON
+#define IP_REASS_DEBUG LWIP_DBG_ON
+#define RAW_DEBUG LWIP_DBG_ON
+#define MEM_DEBUG LWIP_DBG_ON
+#define MEMP_DEBUG LWIP_DBG_ON
+#define SYS_DEBUG LWIP_DBG_ON
+#define TIMERS_DEBUG LWIP_DBG_ON
+#define TCP_DEBUG LWIP_DBG_ON
+#define TCP_INPUT_DEBUG LWIP_DBG_ON
+#define TCP_FR_DEBUG LWIP_DBG_ON
+#define TCP_RTO_DEBUG LWIP_DBG_ON
+#define TCP_CWND_DEBUG LWIP_DBG_ON
+#define TCP_WND_DEBUG LWIP_DBG_ON
+#define TCP_OUTPUT_DEBUG LWIP_DBG_ON
+#define TCP_RST_DEBUG LWIP_DBG_ON
+#define TCP_QLEN_DEBUG LWIP_DBG_ON
+#define UDP_DEBUG LWIP_DBG_ON
+#define TCPIP_DEBUG LWIP_DBG_ON
+#define SLIP_DEBUG LWIP_DBG_ON
+#define DHCP_DEBUG LWIP_DBG_ON
+#define AUTOIP_DEBUG LWIP_DBG_ON
+#define DNS_DEBUG LWIP_DBG_ON
+#define IP6_DEBUG LWIP_DBG_ON
+#define DHCP6_DEBUG LWIP_DBG_ON
/* USER CODE END 1 */
+
#ifdef __cplusplus
}
#endif
diff --git a/Middlewares/Third_Party/LwIP/src/include/lwip/arch.h b/Middlewares/Third_Party/LwIP/src/include/lwip/arch.h
index 58dae33..800fb1f 100644
--- a/Middlewares/Third_Party/LwIP/src/include/lwip/arch.h
+++ b/Middlewares/Third_Party/LwIP/src/include/lwip/arch.h
@@ -78,7 +78,7 @@
* systems, this should be defined to something less resource-consuming.
*/
#ifndef LWIP_PLATFORM_DIAG
-#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
+#define LWIP_PLATFORM_DIAG(x) do {printf("%s:%s:%d ",__FILE__,__FUNCTION__,__LINE__); printf x;} while(0)
#include
#include
#endif
diff --git a/Middlewares/Third_Party/LwIP/src/include/lwip/tcpip.h b/Middlewares/Third_Party/LwIP/src/include/lwip/tcpip.h
index 0b8880a..e2f6b19 100644
--- a/Middlewares/Third_Party/LwIP/src/include/lwip/tcpip.h
+++ b/Middlewares/Third_Party/LwIP/src/include/lwip/tcpip.h
@@ -54,9 +54,13 @@ extern "C" {
extern sys_mutex_t lock_tcpip_core;
#if !defined LOCK_TCPIP_CORE || defined __DOXYGEN__
/** Lock lwIP core mutex (needs @ref LWIP_TCPIP_CORE_LOCKING 1) */
-#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core)
+
+// #define LOCK_TCPIP_CORE() { printf("lock %s %d\n",__FUNCTION__,__LINE__); sys_mutex_lock(&lock_tcpip_core);}
+// #define UNLOCK_TCPIP_CORE() {sys_mutex_unlock(&lock_tcpip_core) ;printf("unlock %s %d\n",__FUNCTION__,__LINE__); }
+
+#define LOCK_TCPIP_CORE() { sys_mutex_lock(&lock_tcpip_core);}
+#define UNLOCK_TCPIP_CORE() {sys_mutex_unlock(&lock_tcpip_core) ;}
/** Unlock lwIP core mutex (needs @ref LWIP_TCPIP_CORE_LOCKING 1) */
-#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core)
#endif /* LOCK_TCPIP_CORE */
#else /* LWIP_TCPIP_CORE_LOCKING */
#define LOCK_TCPIP_CORE()
diff --git a/README.md b/README.md
index 3bbea7f..83c79b1 100644
--- a/README.md
+++ b/README.md
@@ -35,4 +35,20 @@ v3.3.5
···
设备ID配置方法:
直接通过
-···
\ No newline at end of file
+···
+
+```
+可能修改的点:
+ 1. 笔记本电脑拔掉电源之后,会频繁出现异常包。
+ 2. 网线拔掉之后,stm32 udp发送线程会阻塞
+
+
+lock tcpip_send_msg_wait_sem 441
+unlock tcpip_send_msg_wait_sem 443
+
+拔掉网线后tcpip_timeouts_mbox_fetch 105没有释放锁
+lock tcpip_timeouts_mbox_fetch 105
+lock tcpip_send_msg_wait_sem 441
+
+
+```
\ No newline at end of file
diff --git a/iflytop_xsync b/iflytop_xsync
index 57a8cff..11d58a6 160000
--- a/iflytop_xsync
+++ b/iflytop_xsync
@@ -1 +1 @@
-Subproject commit 57a8cffbd446853b99604624091ff3204c6278c2
+Subproject commit 11d58a60275a358352f4acb080031187543510b8
diff --git a/usrc/service/report_generator_service.c b/usrc/service/report_generator_service.c
index 30ba7f3..c591fce 100644
--- a/usrc/service/report_generator_service.c
+++ b/usrc/service/report_generator_service.c
@@ -8,6 +8,7 @@
#include "global_flag.h"
#include "iflytop_xsync\xs_udp.h"
#include "reg_manager.h"
+#include "task.h"
static udp_broadcast_handler_t m_udp_camera_sync_sender; //
static udp_broadcast_handler_t m_udp_camera_timecode_sender; //
@@ -20,8 +21,9 @@ static uint32_t m_xsync_workstate_start_sig_irq_pin_off;
static uint32_t m_timecode_trigger_input_off;
static uint32_t m_xync_trigger_input_off;
static uint32_t m_xyns_camera_sync_packet_last_report_tp;
+static uint32_t m_send_packet_difftime;
static bool m_first_frame = true;
-#define TAG "timecode"
+#define TAG "report_gen"
/**
* @brief 构建并发送时间码数据包
*
@@ -29,15 +31,78 @@ static bool m_first_frame = true;
* @param timecode0
* @param timecode1
*/
-
-static void create_and_send_timecode(uint32_t timecode0, uint32_t timecode1, uint32_t frameNum) {
+static bool _create_and_send_timecode(uint32_t timecode0, uint32_t timecode1, uint32_t frameNum) {
static uint8_t txbuf[256];
iflytop_xsync_event_report_packet_t *txpacket = (iflytop_xsync_event_report_packet_t *)txbuf;
txpacket->eventid = ktimecode_report_event;
txpacket->data[0] = timecode0;
txpacket->data[1] = timecode1;
txpacket->data[2] = frameNum;
- xs_udp_broadcast(&m_udp_camera_timecode_sender, IFLYTOP_XSYNC_EVENT_REPORT_PC_PORT, txbuf, sizeof(iflytop_xsync_event_report_packet_t) + 12);
+ txpacket->data[3] = xs_get_ticket();
+ txpacket->data[4] = m_send_packet_difftime;
+
+ ssize_t sendsize = xs_udp_broadcast(&m_udp_camera_timecode_sender, IFLYTOP_XSYNC_EVENT_REPORT_PC_PORT, txbuf, sizeof(iflytop_xsync_event_report_packet_t) + 20);
+ return sendsize == sizeof(iflytop_xsync_event_report_packet_t) + 20;
+}
+
+static void create_and_send_timecode(uint32_t timecode0, uint32_t timecode1, uint32_t frameNum) {
+ static uint32_t exception1_times = 0;
+ static uint32_t exception2_times = 0;
+ static uint32_t restart_times = 0;
+ static uint32_t lasttxtime = 0;
+ static int32_t last_two_packet_diff = 0;
+ static bool connected = false;
+
+ uint32_t tx_begin_time = 0;
+ uint32_t tx_end_time = 0;
+ int32_t two_packet_diff = 0;
+ int32_t send_diff_time = 0;
+ bool txsuc = false;
+
+ tx_begin_time = osKernelSysTick();
+ txsuc = _create_and_send_timecode(timecode0, timecode1, frameNum);
+ tx_end_time = osKernelSysTick();
+
+ if (!connected) {
+ if (txsuc) {
+ exception1_times = 0;
+ exception2_times = 0;
+ connected = true;
+ restart_times++;
+ }
+ } else {
+ if (!txsuc) {
+ connected = false;
+ }
+ }
+
+ if (txsuc) {
+ send_diff_time = tx_end_time - tx_begin_time;
+ two_packet_diff = tx_begin_time - lasttxtime;
+
+ if (abs(two_packet_diff - last_two_packet_diff) > 3) {
+ exception1_times++;
+ }
+
+ if (send_diff_time >= 2) {
+ exception2_times++;
+ }
+
+ ZLOGI(TAG, "now:%d %d senddiff:%d e1:%d e2:%d", tx_begin_time, two_packet_diff, send_diff_time, exception1_times, exception2_times);
+
+ //
+ lasttxtime = tx_begin_time;
+ last_two_packet_diff = two_packet_diff;
+ }
+
+ // if () m_last_diff_time = starttime - m_last_tx_time;
+ // m_last_tx_time = starttime;
+
+ // m_send_packet_difftime = endttime - starttime;
+
+ // if (m_send_packet_difftime >= 2) {
+ // ZLOGI(TAG, "sendsize:%d diff: %d", sendsize, m_send_packet_difftime);
+ // }
}
static void create_and_send_device_online_packet() {
@@ -134,7 +199,10 @@ static void try_report_device_info_packet() {
static void xync_signal_report_thread(void const *argument) {
while (true) {
- osEvent signal = osSignalWait(0x07, 100);
+ osEvent signal = osSignalWait(0x07, 50);
+ // create_and_send_timecode(0, 0, 0);
+ // continue;
+
if (signal.value.signals & 0x01) {
uint32_t tc0;
uint32_t tc1;
diff --git a/xsync_stm32 Debug.launch b/xsync_stm32 Debug.launch
index 632abef..8c43773 100644
--- a/xsync_stm32 Debug.launch
+++ b/xsync_stm32 Debug.launch
@@ -5,7 +5,7 @@
-
+
@@ -43,9 +43,9 @@
-
+
-
+
diff --git a/xsync_stm32.ioc b/xsync_stm32.ioc
index a23ef87..76f38b8 100644
--- a/xsync_stm32.ioc
+++ b/xsync_stm32.ioc
@@ -142,24 +142,25 @@ Mcu.Pin19=PA13
Mcu.Pin2=PC1
Mcu.Pin20=PA14
Mcu.Pin21=PD3
-Mcu.Pin22=PB5
-Mcu.Pin23=VP_CRC_VS_CRC
-Mcu.Pin24=VP_FREERTOS_VS_CMSIS_V1
-Mcu.Pin25=VP_LWIP_VS_Enabled
-Mcu.Pin26=VP_RNG_VS_RNG
-Mcu.Pin27=VP_SYS_VS_tim11
-Mcu.Pin28=VP_TIM1_VS_ClockSourceINT
-Mcu.Pin29=VP_TIM3_VS_ClockSourceINT
+Mcu.Pin22=PB3
+Mcu.Pin23=PB5
+Mcu.Pin24=VP_CRC_VS_CRC
+Mcu.Pin25=VP_FREERTOS_VS_CMSIS_V1
+Mcu.Pin26=VP_LWIP_VS_Enabled
+Mcu.Pin27=VP_RNG_VS_RNG
+Mcu.Pin28=VP_SYS_VS_tim11
+Mcu.Pin29=VP_TIM1_VS_ClockSourceINT
Mcu.Pin3=PC2
-Mcu.Pin30=VP_TIM6_VS_ClockSourceINT
-Mcu.Pin31=VP_TIM7_VS_ClockSourceINT
+Mcu.Pin30=VP_TIM3_VS_ClockSourceINT
+Mcu.Pin31=VP_TIM6_VS_ClockSourceINT
+Mcu.Pin32=VP_TIM7_VS_ClockSourceINT
Mcu.Pin4=PC3
Mcu.Pin5=PA1
Mcu.Pin6=PA2
Mcu.Pin7=PA4
Mcu.Pin8=PA5
Mcu.Pin9=PA6
-Mcu.PinsNb=32
+Mcu.PinsNb=33
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32F407VETx
@@ -196,9 +197,9 @@ PA1.Mode=RMII
PA1.Signal=ETH_REF_CLK
PA10.Mode=Asynchronous
PA10.Signal=USART1_RX
-PA13.Mode=Serial_Wire
+PA13.Mode=Trace_Asynchronous_SW
PA13.Signal=SYS_JTMS-SWDIO
-PA14.Mode=Serial_Wire
+PA14.Mode=Trace_Asynchronous_SW
PA14.Signal=SYS_JTCK-SWCLK
PA2.Mode=RMII
PA2.Signal=ETH_MDIO
@@ -221,6 +222,8 @@ PB12.Mode=RMII
PB12.Signal=ETH_TXD0
PB13.Mode=RMII
PB13.Signal=ETH_TXD1
+PB3.Mode=Trace_Asynchronous_SW
+PB3.Signal=SYS_JTDO-SWO
PB5.Mode=Full_Duplex_Master
PB5.Signal=SPI1_MOSI
PC1.Mode=RMII
@@ -257,6 +260,7 @@ ProjectManager.KeepUserCode=true
ProjectManager.LastFirmware=true
ProjectManager.LibraryCopy=1
ProjectManager.MainLocation=Core/Src
+ProjectManager.MultiThreaded=true
ProjectManager.NoMain=false
ProjectManager.PreviousToolchain=STM32CubeIDE
ProjectManager.ProjectBuild=false
@@ -266,6 +270,7 @@ ProjectManager.ProjectStructure=
ProjectManager.RegisterCallBack=
ProjectManager.StackSize=0x1000
ProjectManager.TargetToolchain=STM32CubeIDE
+ProjectManager.ThreadSafeStrategy=Cortex-M4NS\:Default,
ProjectManager.ToolChainLocation=
ProjectManager.UAScriptAfterPath=
ProjectManager.UAScriptBeforePath=