eric2013 发表于 2020-8-11 10:44:56

ThreadX专门为IAR的C库函数做的互斥接口文件,通过宏定义TX_ENABLE_IAR_LIBRARY_SUPPORT可以使能



程序在ThreadX内核代码的6.0.1里面有,对应文件tx_iar.c

http://www.armbbs.cn/forum.php?mod=viewthread&tid=97925

/**************************************************************************/
/*                                                                        */
/*       Copyright (c) Microsoft Corporation. All rights reserved.      */
/*                                                                        */
/*       This software is licensed under the Microsoft Software License   */
/*       Terms for Microsoft Azure RTOS. Full text of the license can be*/
/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
/*       and in the root directory of this software.                      */
/*                                                                        */
/**************************************************************************/


/**************************************************************************/
/**************************************************************************/
/**                                                                     */
/** ThreadX Component                                                   */
/**                                                                     */
/**   IAR Multithreaded Library Support                                 */
/**                                                                     */
/**************************************************************************/
/**************************************************************************/

#define TX_SOURCE_CODE


/* Define IAR library for tools prior to version 8.*/

#if (__VER__ < 8000000)


/* IAR version 7 and below.*/

/* Include necessary system files.*/

#include "tx_api.h"
#include "tx_initialize.h"
#include "tx_thread.h"
#include "tx_mutex.h"


/* This implementation requires that the following macros are defined in the
   tx_port.h file and <yvals.h> is included with the following code segments:
   
#ifdefTX_ENABLE_IAR_LIBRARY_SUPPORT
#include <yvals.h>
#endif

#ifdefTX_ENABLE_IAR_LIBRARY_SUPPORT
#define TX_THREAD_EXTENSION_2         VOID    *tx_thread_iar_tls_pointer;         
#else
#define TX_THREAD_EXTENSION_2         
#endif

#ifdefTX_ENABLE_IAR_LIBRARY_SUPPORT
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)                      thread_ptr -> tx_thread_iar_tls_pointer =__iar_dlib_perthread_allocate();                                 
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)                      __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
                                                                  thread_ptr -> tx_thread_iar_tls_pointer =TX_NULL;            
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION               __iar_dlib_perthread_access(0);
#else
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)                                 
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)                                 
#endif

    This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the
    application.

    Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected.
*/

#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT

#include <yvals.h>


#if _MULTI_THREAD

TX_MUTEX    __tx_iar_system_lock_mutexes;
UINT      __tx_iar_system_lock_next_free_mutex =0;


/* Define error counters, just for debug purposes.*/

UINT      __tx_iar_system_lock_no_mutexes;
UINT      __tx_iar_system_lock_internal_errors;
UINT      __tx_iar_system_lock_isr_caller;


/* Define the TLS access function for the IAR library.*/

void _DLIB_TLS_MEMORY *__iar_dlib_perthread_access(void _DLIB_TLS_MEMORY *symbp)
{

char _DLIB_TLS_MEMORY   *p = 0;
   
    /* Is there a current thread?*/
    if (_tx_thread_current_ptr)
      p = (char _DLIB_TLS_MEMORY *) _tx_thread_current_ptr -> tx_thread_iar_tls_pointer;
    else
      p = (void _DLIB_TLS_MEMORY *) __segment_begin("__DLIB_PERTHREAD");
    p += __IAR_DLIB_PERTHREAD_SYMBOL_OFFSET(symbp);
    return (void _DLIB_TLS_MEMORY *) p;
}


/* Define mutexes for IAR library.*/

void __iar_system_Mtxinit(__iar_Rmtx *m)
{

UINT      i;
UINT      status;
TX_MUTEX    *mutex_ptr;


    /* First, find a free mutex in the list.*/
    for (i = 0; i < _MAX_LOCK; i++)
    {

      /* Setup a pointer to the start of the next free mutex.*/
      mutex_ptr =&__tx_iar_system_lock_mutexes;
   
      /* Check for wrap-around on the next free mutex.*/
      if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK)
      {
      
            /* Yes, set the free index back to 0.*/
            __tx_iar_system_lock_next_free_mutex =0;
      }
   
      /* Is this mutex free?*/
      if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
      {
      
            /* Yes, this mutex is free, get out of the loop!*/
            break;
      }
    }

    /* Determine if a free mutex was found.   */
    if (i >= _MAX_LOCK)
    {
   
      /* Error!No more free mutexes!*/
      
      /* Increment the no mutexes error counter.*/
      __tx_iar_system_lock_no_mutexes++;
      
      /* Set return pointer to NULL.*/
      *m =TX_NULL;
      
      /* Return.*/
      return;
    }
   
    /* Now create the ThreadX mutex for the IAR library.*/
    status =_tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT);
   
    /* Determine if the creation was successful.*/
    if (status == TX_SUCCESS)
    {
   
      /* Yes, successful creation, return mutex pointer.*/
      *m =(VOID *) mutex_ptr;
    }
    else
    {
   
      /* Increment the internal error counter.*/
      __tx_iar_system_lock_internal_errors++;
   
      /* Return a NULL pointer to indicate an error.*/
      *m =TX_NULL;
    }
}

void __iar_system_Mtxdst(__iar_Rmtx *m)
{

    /* Simply delete the mutex.*/
    _tx_mutex_delete((TX_MUTEX *) *m);
}

void __iar_system_Mtxlock(__iar_Rmtx *m)
{

UINT    status;


    /* Determine the caller's context. Mutex locks are only available from initialization and
       threads.*/
    if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
    {
   
      /* Get the mutex.*/
      status =_tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);

      /* Check the status of the mutex release.*/
      if (status)
      {
      
            /* Internal error, increment the counter.*/
            __tx_iar_system_lock_internal_errors++;
      }
    }
    else
    {
      
      /* Increment the ISR caller error.*/
      __tx_iar_system_lock_isr_caller++;
    }
}

void __iar_system_Mtxunlock(__iar_Rmtx *m)
{

UINT    status;


    /* Determine the caller's context. Mutex unlocks are only available from initialization and
       threads.*/
    if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
    {
   
      /* Release the mutex.*/
      status =_tx_mutex_put((TX_MUTEX *) *m);
      
      /* Check the status of the mutex release.*/
      if (status)
      {
      
            /* Internal error, increment the counter.*/
            __tx_iar_system_lock_internal_errors++;
      }
    }
    else
    {
      
      /* Increment the ISR caller error.*/
      __tx_iar_system_lock_isr_caller++;
    }
}


#if _DLIB_FILE_DESCRIPTOR

TX_MUTEX    __tx_iar_file_lock_mutexes;
UINT      __tx_iar_file_lock_next_free_mutex =0;


/* Define error counters, just for debug purposes.*/

UINT      __tx_iar_file_lock_no_mutexes;
UINT      __tx_iar_file_lock_internal_errors;
UINT      __tx_iar_file_lock_isr_caller;


void __iar_file_Mtxinit(__iar_Rmtx *m)
{

UINT      i;
UINT      status;
TX_MUTEX    *mutex_ptr;


    /* First, find a free mutex in the list.*/
    for (i = 0; i < _MAX_FLOCK; i++)
    {

      /* Setup a pointer to the start of the next free mutex.*/
      mutex_ptr =&__tx_iar_file_lock_mutexes;
   
      /* Check for wrap-around on the next free mutex.*/
      if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK)
      {
      
            /* Yes, set the free index back to 0.*/
            __tx_iar_file_lock_next_free_mutex =0;
      }
   
      /* Is this mutex free?*/
      if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
      {
      
            /* Yes, this mutex is free, get out of the loop!*/
            break;
      }
    }

    /* Determine if a free mutex was found.   */
    if (i >= _MAX_LOCK)
    {
   
      /* Error!No more free mutexes!*/
      
      /* Increment the no mutexes error counter.*/
      __tx_iar_file_lock_no_mutexes++;
      
      /* Set return pointer to NULL.*/
      *m =TX_NULL;
      
      /* Return.*/
      return;
    }
   
    /* Now create the ThreadX mutex for the IAR library.*/
    status =_tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT);
   
    /* Determine if the creation was successful.*/
    if (status == TX_SUCCESS)
    {
   
      /* Yes, successful creation, return mutex pointer.*/
      *m =(VOID *) mutex_ptr;
    }
    else
    {
   
      /* Increment the internal error counter.*/
      __tx_iar_file_lock_internal_errors++;
   
      /* Return a NULL pointer to indicate an error.*/
      *m =TX_NULL;
    }
}

void __iar_file_Mtxdst(__iar_Rmtx *m)
{

    /* Simply delete the mutex.*/
    _tx_mutex_delete((TX_MUTEX *) *m);
}

void __iar_file_Mtxlock(__iar_Rmtx *m)
{

UINT    status;


    /* Determine the caller's context. Mutex locks are only available from initialization and
       threads.*/
    if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
    {
   
      /* Get the mutex.*/
      status =_tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);

      /* Check the status of the mutex release.*/
      if (status)
      {
      
            /* Internal error, increment the counter.*/
            __tx_iar_file_lock_internal_errors++;
      }
    }
    else
    {
      
      /* Increment the ISR caller error.*/
      __tx_iar_file_lock_isr_caller++;
    }
}

void __iar_file_Mtxunlock(__iar_Rmtx *m)
{

UINT    status;


    /* Determine the caller's context. Mutex unlocks are only available from initialization and
       threads.*/
    if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
    {
   
      /* Release the mutex.*/
      status =_tx_mutex_put((TX_MUTEX *) *m);
      
      /* Check the status of the mutex release.*/
      if (status)
      {
      
            /* Internal error, increment the counter.*/
            __tx_iar_file_lock_internal_errors++;
      }
    }
    else
    {
      
      /* Increment the ISR caller error.*/
      __tx_iar_file_lock_isr_caller++;
    }
}
#endif/* _DLIB_FILE_DESCRIPTOR */

#endif/* _MULTI_THREAD*/

#endif/* TX_ENABLE_IAR_LIBRARY_SUPPORT*/

#else   /* IAR version 8 and above.*/


/* Include necessary system files.*/

#include "tx_api.h"
#include "tx_initialize.h"
#include "tx_thread.h"
#include "tx_mutex.h"

/* This implementation requires that the following macros are defined in the
   tx_port.h file and <yvals.h> is included with the following code segments:
   
#ifdefTX_ENABLE_IAR_LIBRARY_SUPPORT
#include <yvals.h>
#endif

#ifdefTX_ENABLE_IAR_LIBRARY_SUPPORT
#define TX_THREAD_EXTENSION_2         VOID    *tx_thread_iar_tls_pointer;         
#else
#define TX_THREAD_EXTENSION_2         
#endif

#ifdefTX_ENABLE_IAR_LIBRARY_SUPPORT
void    *_tx_iar_create_per_thread_tls_area(void);
void    _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
void    __iar_Initlocks(void);

#define TX_THREAD_CREATE_EXTENSION(thread_ptr)                      thread_ptr -> tx_thread_iar_tls_pointer =__iar_dlib_perthread_allocate();                                 
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)                      do {__iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
                                                                        thread_ptr -> tx_thread_iar_tls_pointer =TX_NULL; } while(0);
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION               do {__iar_Initlocks();} while(0);
#else
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)                                 
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)                                 
#endif

    This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the
    application.

    Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected.
*/

#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT

#include <DLib_threads.h>


void * __aeabi_read_tp();

void* _tx_iar_create_per_thread_tls_area();
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);

#pragma section="__iar_tls$DATA"

/* Define the TLS access function for the IAR library.*/
void * __aeabi_read_tp(void)
{
void *p = 0;
TX_THREAD *thread_ptr = _tx_thread_current_ptr;
if (thread_ptr)
{
    p = thread_ptr->tx_thread_iar_tls_pointer;      
}
else
{
    p = __section_begin("__iar_tls$DATA");
}
return p;
}

/* Define the TLS creation and destruction to use malloc/free.*/

void* _tx_iar_create_per_thread_tls_area()
{
UINT tls_size = __iar_tls_size();

/* Get memory for TLS.*/
void *p = malloc(tls_size);

/* Initialize TLS-area and run constructors for objects in TLS */
__iar_tls_init(p);
return p;
}

void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr)
{
/* Destroy objects living in TLS */
__call_thread_dtors();
free(tls_ptr);
}

#ifndef _MAX_LOCK
#define _MAX_LOCK 4
#endif

static TX_MUTEX    __tx_iar_system_lock_mutexes;
static UINT      __tx_iar_system_lock_next_free_mutex =0;


/* Define error counters, just for debug purposes.*/

UINT      __tx_iar_system_lock_no_mutexes;
UINT      __tx_iar_system_lock_internal_errors;
UINT      __tx_iar_system_lock_isr_caller;


/* Define mutexes for IAR library.*/

void __iar_system_Mtxinit(__iar_Rmtx *m)
{

UINT      i;
UINT      status;
TX_MUTEX    *mutex_ptr;


    /* First, find a free mutex in the list.*/
    for (i = 0; i < _MAX_LOCK; i++)
    {

      /* Setup a pointer to the start of the next free mutex.*/
      mutex_ptr =&__tx_iar_system_lock_mutexes;
   
      /* Check for wrap-around on the next free mutex.*/
      if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK)
      {
      
            /* Yes, set the free index back to 0.*/
            __tx_iar_system_lock_next_free_mutex =0;
      }
   
      /* Is this mutex free?*/
      if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
      {
      
            /* Yes, this mutex is free, get out of the loop!*/
            break;
      }
    }

    /* Determine if a free mutex was found.   */
    if (i >= _MAX_LOCK)
    {
   
      /* Error!No more free mutexes!*/
      
      /* Increment the no mutexes error counter.*/
      __tx_iar_system_lock_no_mutexes++;
      
      /* Set return pointer to NULL.*/
      *m =TX_NULL;
      
      /* Return.*/
      return;
    }
   
    /* Now create the ThreadX mutex for the IAR library.*/
    status =_tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT);
   
    /* Determine if the creation was successful.*/
    if (status == TX_SUCCESS)
    {
   
      /* Yes, successful creation, return mutex pointer.*/
      *m =(VOID *) mutex_ptr;
    }
    else
    {
   
      /* Increment the internal error counter.*/
      __tx_iar_system_lock_internal_errors++;
   
      /* Return a NULL pointer to indicate an error.*/
      *m =TX_NULL;
    }
}

void __iar_system_Mtxdst(__iar_Rmtx *m)
{

    /* Simply delete the mutex.*/
    _tx_mutex_delete((TX_MUTEX *) *m);
}

void __iar_system_Mtxlock(__iar_Rmtx *m)
{
if (*m)
{
    UINT    status;

    /* Determine the caller's context. Mutex locks are only available from initialization and
       threads.*/
    if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
    {
   
      /* Get the mutex.*/
      status =_tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);

      /* Check the status of the mutex release.*/
      if (status)
      {
      
            /* Internal error, increment the counter.*/
            __tx_iar_system_lock_internal_errors++;
      }
    }
    else
    {
      
      /* Increment the ISR caller error.*/
      __tx_iar_system_lock_isr_caller++;
    }
}
}

void __iar_system_Mtxunlock(__iar_Rmtx *m)
{
if (*m)
{
    UINT    status;

    /* Determine the caller's context. Mutex unlocks are only available from initialization and
       threads.*/
    if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
    {
   
      /* Release the mutex.*/
      status =_tx_mutex_put((TX_MUTEX *) *m);
      
      /* Check the status of the mutex release.*/
      if (status)
      {
      
            /* Internal error, increment the counter.*/
            __tx_iar_system_lock_internal_errors++;
      }
    }
    else
    {
      
      /* Increment the ISR caller error.*/
      __tx_iar_system_lock_isr_caller++;
    }
}
}


#if _DLIB_FILE_DESCRIPTOR

#include <stdio.h>                        /* Added to get access to FOPEN_MAX */
#ifndef _MAX_FLOCK
#define _MAX_FLOCK FOPEN_MAX            /* Define _MAX_FLOCK as the maximum number of open files */
#endif


TX_MUTEX    __tx_iar_file_lock_mutexes;
UINT      __tx_iar_file_lock_next_free_mutex =0;


/* Define error counters, just for debug purposes.*/

UINT      __tx_iar_file_lock_no_mutexes;
UINT      __tx_iar_file_lock_internal_errors;
UINT      __tx_iar_file_lock_isr_caller;


void __iar_file_Mtxinit(__iar_Rmtx *m)
{

UINT      i;
UINT      status;
TX_MUTEX    *mutex_ptr;


    /* First, find a free mutex in the list.*/
    for (i = 0; i < _MAX_FLOCK; i++)
    {

      /* Setup a pointer to the start of the next free mutex.*/
      mutex_ptr =&__tx_iar_file_lock_mutexes;
   
      /* Check for wrap-around on the next free mutex.*/
      if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK)
      {
      
            /* Yes, set the free index back to 0.*/
            __tx_iar_file_lock_next_free_mutex =0;
      }
   
      /* Is this mutex free?*/
      if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
      {
      
            /* Yes, this mutex is free, get out of the loop!*/
            break;
      }
    }

    /* Determine if a free mutex was found.   */
    if (i >= _MAX_LOCK)
    {
   
      /* Error!No more free mutexes!*/
      
      /* Increment the no mutexes error counter.*/
      __tx_iar_file_lock_no_mutexes++;
      
      /* Set return pointer to NULL.*/
      *m =TX_NULL;
      
      /* Return.*/
      return;
    }
   
    /* Now create the ThreadX mutex for the IAR library.*/
    status =_tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT);
   
    /* Determine if the creation was successful.*/
    if (status == TX_SUCCESS)
    {
   
      /* Yes, successful creation, return mutex pointer.*/
      *m =(VOID *) mutex_ptr;
    }
    else
    {
   
      /* Increment the internal error counter.*/
      __tx_iar_file_lock_internal_errors++;
   
      /* Return a NULL pointer to indicate an error.*/
      *m =TX_NULL;
    }
}

void __iar_file_Mtxdst(__iar_Rmtx *m)
{

    /* Simply delete the mutex.*/
    _tx_mutex_delete((TX_MUTEX *) *m);
}

void __iar_file_Mtxlock(__iar_Rmtx *m)
{

UINT    status;


    /* Determine the caller's context. Mutex locks are only available from initialization and
       threads.*/
    if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
    {
   
      /* Get the mutex.*/
      status =_tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);

      /* Check the status of the mutex release.*/
      if (status)
      {
      
            /* Internal error, increment the counter.*/
            __tx_iar_file_lock_internal_errors++;
      }
    }
    else
    {
      
      /* Increment the ISR caller error.*/
      __tx_iar_file_lock_isr_caller++;
    }
}

void __iar_file_Mtxunlock(__iar_Rmtx *m)
{

UINT    status;


    /* Determine the caller's context. Mutex unlocks are only available from initialization and
       threads.*/
    if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
    {
   
      /* Release the mutex.*/
      status =_tx_mutex_put((TX_MUTEX *) *m);
      
      /* Check the status of the mutex release.*/
      if (status)
      {
      
            /* Internal error, increment the counter.*/
            __tx_iar_file_lock_internal_errors++;
      }
    }
    else
    {
      
      /* Increment the ISR caller error.*/
      __tx_iar_file_lock_isr_caller++;
    }
}
#endif/* _DLIB_FILE_DESCRIPTOR */

#endif/* TX_ENABLE_IAR_LIBRARY_SUPPORT*/

#endif /* IAR version 8 and above.*/


zhang0352505 发表于 2024-3-15 10:51:26

本帖最后由 zhang0352505 于 2024-3-15 10:53 编辑

这个奇怪的支持,需要在编译设置中打开iar的thread support library。
刚开始老是要报错,不明白为什么,报错如下

然后试了一些设置,最后打开如下设置才编译成功

eric2013 发表于 2024-3-16 09:54:39

zhang0352505 发表于 2024-3-15 10:51
这个奇怪的支持,需要在编译设置中打开iar的thread support library。
刚开始老是要报错,不明白为什么, ...

谢谢分享,我都没测试过这个。
页: [1]
查看完整版本: ThreadX专门为IAR的C库函数做的互斥接口文件,通过宏定义TX_ENABLE_IAR_LIBRARY_SUPPORT可以使能