From 19ccd747adc144007f5e9cbaa9160f6931b15485 Mon Sep 17 00:00:00 2001 From: zhaohe Date: Thu, 13 Jun 2024 21:11:59 +0800 Subject: [PATCH] update --- .cproject | 16 +- .settings/language.settings.xml | 4 +- .vscode/settings.json | 4 +- Core/Src/gpio.c | 8 +- Core/ThreadSafe/newlib_lock_glue.c | 423 +++++++++++++++++++++ Core/ThreadSafe/stm32_lock.h | 375 ++++++++++++++++++ LWIP/Target/ethernetif.c | 15 +- LWIP/Target/lwipopts.h | 73 +++- .../Third_Party/LwIP/src/include/lwip/arch.h | 2 +- .../Third_Party/LwIP/src/include/lwip/tcpip.h | 8 +- README.md | 18 +- iflytop_xsync | 2 +- usrc/service/report_generator_service.c | 78 +++- xsync_stm32 Debug.launch | 6 +- xsync_stm32.ioc | 31 +- 15 files changed, 1001 insertions(+), 62 deletions(-) create mode 100644 Core/ThreadSafe/newlib_lock_glue.c create mode 100644 Core/ThreadSafe/stm32_lock.h diff --git a/.cproject b/.cproject index 3e952a4..dae76af 100644 --- a/.cproject +++ b/.cproject @@ -23,7 +23,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=