eric2013 发表于 2023-10-1 00:37:09

STM32CubeMX生成的用于C库API多任务调用的MDK, IAR和GCC接口文件

勾选这个:



MDK:

/**
******************************************************************************
* @file      armlib_lock_glue.c
* @author    STMicroelectronics
* @brief   Implementation of ARM C library lock interface
*
* @details   For more information about which C functions
*            need which of these lowlevel functions
*            please consult the "Arm C and C++ Libraries and
*            Floating-Point Support User Guide"
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*                        opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/

#if !defined(__CC_ARM) && !(defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
#error "armlib_lock_glue.c" should be used with ARM Compilers only
#endif /* !defined(__CC_ARM) && !(defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) */

/* Includes ------------------------------------------------------------------*/
#include <cmsis_compiler.h>

/* Private functions ---------------------------------------------------------*/

/**
* @brief Global Error_Handler
*/
__WEAK void Error_Handler(void)
{
/* Not used if it exists in project */
while (1);
}

#ifdef __MICROLIB
#warning Microlib does not provide mutex locks to guard against code that is not thread safe
#else

/* Includes ------------------------------------------------------------------*/
#include "stm32_lock.h"

/* Private typedef -----------------------------------------------------------*/
typedef void *mutex_t;

struct __lock
{
uint8_t initialized; /**< Flag to indicate that lock is initialized */
LockingData_t lock_data; /**< The locking data */
};

/* Private defines -----------------------------------------------------------*/
/** Maximal number of static allocated locks */
#define MAX_LOCK 8

/* Private macros ------------------------------------------------------------*/
/** Convert pointer to pointer to instance of struct __lock */
#define STM32_GET_LOCK_PTR(mutex_ptr) ((struct __lock *) *(mutex_ptr))

/** See struct __lock definition */
#define STM32_LOCK_PARAMETER(lock_ptr) (&(lock_ptr)->lock_data)

/** See struct __lock definition */
#define STM32_LOCK_INITIALIZED(lock_ptr) ((lock_ptr)->initialized)

/* Private variables ---------------------------------------------------------*/
/** Maximum system locks allowed by armlib */
static struct __lock static_lock;

/** Lock for static_lock array */
static LockingData_t static_list_lock = LOCKING_DATA_INIT;

/* Private functions ---------------------------------------------------------*/

/**
* @brief Thread safety Initialization, called before main
*/
__attribute__ ((constructor)) void __armlib_thread_safety_init()
{
uint32_t index;

/* Mark all system locks as not initialized */
stm32_lock_acquire(&static_list_lock);
for (index = 0; index < STM32_LOCK_ARRAY_SIZE(static_lock); index++)
{
    STM32_LOCK_INITIALIZED(&static_lock) = 0;
}
stm32_lock_release(&static_list_lock);
}

/**
* @defgroup _mutex_functions ARM library locks
* @{
*/

/**
* @brief Initialize lock mutex
* @param lock The lock
* @return 0 on failure
*/
__attribute__((used)) int _mutex_initialize(mutex_t *lock)
{
if (lock != NULL)
{
    uint32_t index;

    stm32_lock_acquire(&static_list_lock);
    for (index = 0; index < STM32_LOCK_ARRAY_SIZE(static_lock); index++)
    {
      if (STM32_LOCK_INITIALIZED(&static_lock) == 0)
      {
      *lock = &static_lock;
      STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) = 1;
      stm32_lock_init(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
      stm32_lock_release(&static_list_lock);
      return 1;
      }
    }
    stm32_lock_release(&static_list_lock);
}

/* Not enough mutexes, MAX_LOCK should be incremented */
return 0;
}

/**
* @brief Acquire lock mutex
* @param lock The lock
*/
__attribute__((used)) void _mutex_acquire(mutex_t *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);

stm32_lock_acquire(&static_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
    stm32_lock_acquire(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
}
else
{
    STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_list_lock);
}

/**
* @brief Release lock mutex
* @param lock The lock
*/
__attribute__((used)) void _mutex_release(mutex_t *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);

stm32_lock_acquire(&static_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
    stm32_lock_release(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
}
else
{
    STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_list_lock);
}

/**
* @brief Free lock mutex
* @param lock The lock
*/
__attribute__((used)) void _mutex_free(mutex_t *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);

stm32_lock_acquire(&static_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
    STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) = 0;
}
else
{
    STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_list_lock);
}

/**
* @}
*/

#endif /* __MICROLIB */


IAR:

/**
******************************************************************************
* @file      dlib_lock_glue.c
* @author    STMicroelectronics
* @brief   Implementation of IAR DLib 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 lowlevel functions
* please consult the IAR C/C++ Development Guide
* and DLib_Threads.h
*
* @see http://ftp.iar.se/WWWfiles/arm/webic/doc/EWARM_DevelopmentGuide.ENU.pdf
*
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*                        opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/

#ifndef __ICCARM__
#error "dlib_lock_glue.c" should be used with IAR DLib only
#endif /* __ICCARM__ */

/* Includes ------------------------------------------------------------------*/
#include <DLib_Threads.h>
#include <stdio.h>
#include <stdlib.h>
#include "stm32_lock.h"

/* Private functions ---------------------------------------------------------*/

/**
* @brief Global Error_Handler
*/
__WEAK void Error_Handler(void)
{
/* Not used if it exists in project */
while (1);
}

/* Private typedef -----------------------------------------------------------*/
struct __lock
{
uint8_t initialized; /**< Flag to indicate that lock is initialized */
LockingData_t lock_data; /**< The locking data */
};

/* Private macros ------------------------------------------------------------*/
/** Convert pointer to pointer to instance of struct __lock */
#define STM32_GET_LOCK_PTR(iar_Rmtx_ptr) ((struct __lock *) *(iar_Rmtx_ptr))

/** See struct __lock definition */
#define STM32_LOCK_PARAMETER(lock_ptr) (&(lock_ptr)->lock_data)

/** See struct __lock definition */
#define STM32_LOCK_INITIALIZED(lock_ptr) ((lock_ptr)->initialized)

/** Size of array */
#define STM32_LOCK_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)))

/* Private variables ---------------------------------------------------------*/
/** Maximum system locks allowed by DLib */
static __no_init struct __lock static_system_lock;

/** Lock for static_system_lock array */
static LockingData_t static_system_list_lock = LOCKING_DATA_INIT;

#ifdef FOPEN_MAX
/** Maximum file locks allowed by DLib */
static __no_init struct __lock static_file_lock;

/** Lock for static_file_lock array */
static LockingData_t static_file_list_lock = LOCKING_DATA_INIT;
#endif /* FOPEN_MAX */

/* Private functions ---------------------------------------------------------*/

/**
* @brief Thread safety Initialization, called before main
*/
__attribute__ ((constructor)) void __dlib_thread_safety_init()
{
uint32_t index;

/* Mark all system locks as not initialized */
stm32_lock_acquire(&static_system_list_lock);
for (index = 0; index < STM32_LOCK_ARRAY_SIZE(static_system_lock); index++)
{
    STM32_LOCK_INITIALIZED(&static_system_lock) = 0;
}
stm32_lock_release(&static_system_list_lock);

/* Mark all file locks as not initialized */
#ifdef FOPEN_MAX
stm32_lock_acquire(&static_file_list_lock);
for (index = 0; index < STM32_LOCK_ARRAY_SIZE(static_file_lock); index++)
{
    STM32_LOCK_INITIALIZED(&static_file_lock) = 0;
}
stm32_lock_release(&static_file_list_lock);
#endif /* FOPEN_MAX */

/* Initialize system and file locks */
__iar_Initlocks();

/* Run the C++ global object constructors */
#ifdef __cplusplus
extern void __iar_dynamic_initialization();
__iar_dynamic_initialization();
#endif /* __cplusplus */
}

/**
* @defgroup __iar_system_Mtx_Functions IAR system locks
* @{
*/

/**
* @brief Initialize a system lock
* @param lock The lock
*/
void __iar_system_Mtxinit(__iar_Rmtx *lock)
{
uint32_t index;

STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);

stm32_lock_acquire(&static_system_list_lock);
for (index = 0; index < STM32_LOCK_ARRAY_SIZE(static_system_lock); index++)
{
    if (STM32_LOCK_INITIALIZED(&static_system_lock) == 0)
    {
      *lock = &static_system_lock;
      STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) = 1;
      stm32_lock_init(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
      stm32_lock_release(&static_system_list_lock);
      return;
    }
}

/* Not enough mutexes, this should never happen */
STM32_LOCK_BLOCK();

/* Release of static_system_list_lock, not possible since STM32_LOCK_BLOCK is invoked */
}

/**
* @brief Lock a system lock
* @param lock The lock
*/
void __iar_system_Mtxlock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);

stm32_lock_acquire(&static_system_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
    stm32_lock_acquire(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
}
else
{
    STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_system_list_lock);
}

/**
* @brief Unlock a system lock
* @param lock The lock
*/
void __iar_system_Mtxunlock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);

stm32_lock_acquire(&static_system_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
    stm32_lock_release(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
}
else
{
    STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_system_list_lock);
}

/**
* @brief Destroy a system lock
* @param lock The lock
*/
void __iar_system_Mtxdst(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);

stm32_lock_acquire(&static_system_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
    STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) = 0;
}
else
{
    STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_system_list_lock);
}

/**
* @}
*/

/**
* @defgroup __iar_file_Mtx_Functions IAR file locks
* @{
*/

/**
* @brief Initialize a file lock
* @param lock The lock
*/
void __iar_file_Mtxinit(__iar_Rmtx *lock)
{
#ifdef FOPEN_MAX
uint32_t index;

STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);

stm32_lock_acquire(&static_file_list_lock);
for (index = 0; index < STM32_LOCK_ARRAY_SIZE(static_file_lock); index++)
{
    if (STM32_LOCK_INITIALIZED(&static_file_lock) == 0)
    {
      *lock = &static_file_lock;
      STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) = 1;
      stm32_lock_init(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
      stm32_lock_release(&static_file_list_lock);
      return;
    }
}

/* Not enough mutexes, this should never happen */
STM32_LOCK_BLOCK();

/* Release of static_file_lock, not possible since STM32_LOCK_BLOCK is invoked */
#else
STM32_LOCK_UNUSED(lock);

/* Not enough mutexes, this should never happen */
STM32_LOCK_BLOCK();
#endif /* FOPEN_MAX */
}

/**
* @brief Lock a file lock
* @param lock The lock
*/
void __iar_file_Mtxlock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);

#ifdef FOPEN_MAX
stm32_lock_acquire(&static_file_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
    stm32_lock_acquire(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
}
else
{
    STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_file_list_lock);
#else
STM32_LOCK_BLOCK();
#endif /* FOPEN_MAX */
}

/**
* @brief Unlock a file lock
* @param lock The lock
*/
void __iar_file_Mtxunlock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);

#ifdef FOPEN_MAX
stm32_lock_acquire(&static_file_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
    stm32_lock_release(STM32_LOCK_PARAMETER(STM32_GET_LOCK_PTR(lock)));
}
else
{
    STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_file_list_lock);
#else
STM32_LOCK_BLOCK();
#endif /* FOPEN_MAX */
}

/**
* @brief Destroy a file lock
* @param lock The lock
*/
void __iar_file_Mtxdst(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);

#ifdef FOPEN_MAX
stm32_lock_acquire(&static_file_list_lock);
if (STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) == 1)
{
    STM32_LOCK_INITIALIZED(STM32_GET_LOCK_PTR(lock)) = 0;
}
else
{
    STM32_LOCK_BLOCK();
}
stm32_lock_release(&static_file_list_lock);
#else
STM32_LOCK_BLOCK();
#endif /* FOPEN_MAX */
}

/**
* @}
*/

/**
* @defgroup __iar_dynamic_Mtx_Functions IAR C++ dynamic locks
* @{
*/

/**
* @brief Initialize a C++ dynamic lock
* @param lock The lock
*/
void __iar_Initdynamiclock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);

*lock = malloc(sizeof(LockingData_t));
if (*lock != NULL)
{
    stm32_lock_init(*lock);
}
else
{
    /* Cannot allocate memory for a new mutex */
    STM32_LOCK_BLOCK();
}
}

/**
* @brief Lock a C++ dynamic lock
* @param lock The lock
*/
void __iar_Lockdynamiclock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);

if (*lock != NULL)
{
    stm32_lock_acquire(*lock);
}
else
{
    STM32_LOCK_BLOCK();
}
}

/**
* @brief Unlock a C++ dynamic lock
* @param lock The lock
*/
void __iar_Unlockdynamiclock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);

if (*lock != NULL)
{
    stm32_lock_release(*lock);
}
else
{
    STM32_LOCK_BLOCK();
}
}

/**
* @brief Destroy a C++ dynamic lock
* @param lock The lock
*/
void __iar_Dstdynamiclock(__iar_Rmtx *lock)
{
STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock);

free(*lock);
*lock = NULL;
}

/**
* @}
*/



GCC:

/**
******************************************************************************
* @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) 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.
*
******************************************************************************
*/

#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 <cmsis_compiler.h>

/* 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 <newlib.h>
#include <stdatomic.h>
#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 <errno.h>
#include <stdlib.h>
#include <sys/lock.h>

/* 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 <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___sinit_recursive_mutex = { LOCKING_DATA_INIT };

/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___sfp_recursive_mutex = { LOCKING_DATA_INIT };

/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___atexit_recursive_mutex = { LOCKING_DATA_INIT };

/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___at_quick_exit_mutex = { LOCKING_DATA_INIT };

/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___malloc_recursive_mutex = { LOCKING_DATA_INIT };

/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___env_recursive_mutex = { LOCKING_DATA_INIT };

/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___tz_mutex = { LOCKING_DATA_INIT };

/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
struct __lock __lock___dd_hash_mutex = { LOCKING_DATA_INIT };

/** Implementing mutex from <a href="https://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/misc/lock.c">newlib/libc/misc/lock.c</a> */
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 <reent.h>

/* 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 <tt>-fno-threadsafe-statics</tt> 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__ */

页: [1]
查看完整版本: STM32CubeMX生成的用于C库API多任务调用的MDK, IAR和GCC接口文件