[MCU framework] [os layer] common function of RTX4 Middleware

Keywords: Single-Chip Microcomputer stm32 rtx

Reseal RTX4 functions to fit RTX5 / FREERTOS / FREERTOS_NRF_RTC.

Keil RTX is a royalty free, deterministic real-time operating system designed for ARM and Cortex-M devices. It allows you to create programs that perform multiple functions simultaneously and helps create better structured and easier to maintain applications.

features

  • Copyright free source code, deterministic RTOS
  • Flexible scheduling: loop, preemption and collaboration
  • High speed real-time operation with low interrupt delay
  • Provide small packages for systems with limited resources
  • An unlimited number of tasks, each with 254 priorities
  • Unlimited number of mailboxes, semaphores, mutexes, and timers
  • Supports multithreading and thread safe operations
  • Kernel aware debugging supports MDK-ARM
  • use μ Dialog based settings for the Vision Configuration Wizard

advantage

Although real-time programs can be created without a real-time operating system (by executing one or more functions in a super loop), which should refer to bare metal, the RTOS KeilRTX solves for you have many scheduling, maintenance and timing problems.

matters needing attention

All MDK-ARM versions contain RTX source code.



[use steps of RTX kernel in new project]

  1. When the keil development environment is set up, set the RTX kernel to be used in the Project, select Project - > Options for target, then select the RTX kernel for the Operating system [Operating system] and click OK;
  2. From \ keil \ arm \ boards \ St \ stm32f10x_ EVAL\RTX_ Copy RTX for target device in blinky \ folder_ Config. C configuration file to User /;
    //If there is no file for a unique device, copy the file from under the Philips folder and modify it according to the target device.
  3. In stm32f10x_ Comment out SVC in it. C_ Handler() PendSV_ Handler() SysTick_ Because RTX is used for the three functions of handler(), in order to avoid repeated definition of function names, these three functions must be commented out, or RTX cannot run;

In RTX_ The configuration options in config. C can:

  • Specify the number of currently running tasks;
  • Specifies the number of tasks that use a user-defined stack;
  • Specifies the size of the stack allocated to each task;
  • Enable or disable stack checking;
  • Specify CPU timer as system timer;
  • Specify the input clock frequency for the selected timer;;
  • Specify timer beat interval;
  • Enable or disable rotation task scheduling;
  • Specify a time slice for rotating task scheduling;
  • Define idle task operations;
  • Specify the number of user timers;
  • Specify the code for the user timer callback function;
/********************************************************************************
* @file    os_api.c
* @author  jianqiang.xue
* @Version V1.0.0
* @Date    2021-04-03
* @brief   Most RTX system functions are in: * * \ Keil_v5\Arm\Packs\ARM\CMSIS.6.0\CMSIS\RTOS\RTX\SRC
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
/* Private includes ----------------------------------------------------------*/
#include "cmsis_os.h"
#include "os_api.h"

/* Public function prototypes -----------------------------------------------*/
/*********************************OS_KERNEL***********************************/
os_status os_kernel_initialize(void)
{
    return (os_status)osKernelInitialize();
}

os_status os_kernel_start(void)
{
    return (os_status)osKernelStart();
}

os_status os_delay(uint32_t ms)
{
    return (os_status)osDelay(ms);
}

uint32_t os_get_tick(void)
{
    return osKernelSysTick();
}

extern void rt_tsk_lock(void);
os_status os_kernel_lock(void)
{
    rt_tsk_lock();
    return (os_status)0;
}

extern void rt_tsk_unlock(void);
os_status os_kernel_unlock(void)
{
    rt_tsk_unlock();
    return (os_status)0;
}
/************************************OS_THREAD************************************/
os_thread_id os_thread_create(const os_thread_def_t *thread_def, void *arg)
{
    return (os_thread_id)osThreadCreate((const osThreadDef_t *)thread_def, NULL);
}

/************************************OS_TIMER************************************/
os_timer_id os_timer_create(const os_timer_def_t *timer_def, os_timer_t type, void *arg)
{
    return osTimerCreate((const osTimerDef_t *)timer_def, (os_timer_type)type, arg);
}

os_status os_timer_start(os_timer_id timer_id, uint32_t millisec)
{
    return (os_status)osTimerStart(timer_id, millisec);
}

os_status os_timer_stop(os_timer_id timer_id)
{
    return (os_status)osTimerStop(timer_id);
}

/************************************OS_MAIL************************************/
os_mail_qid os_mail_create(const os_mailq_def_t *queue_def, os_thread_id thread_id)
{
    return (os_mail_qid)osMailCreate((const osMailQDef_t *)queue_def, thread_id);
}

void *os_mail_alloc(os_mail_qid queue_id, uint32_t millisec)
{
    return osMailAlloc((osMailQId)queue_id, millisec);
}

void *os_mail_clean_and_alloc(os_mail_qid queue_id, uint32_t millisec)
{
    return osMailCAlloc((osMailQId)queue_id, millisec);
}

os_status os_mail_put(os_mail_qid queue_id, void *mail)
{
    return (os_status)osMailPut((osMailQId)queue_id, mail);
}

os_event os_mail_get(os_mail_qid queue_id, uint32_t millisec, void *arg)
{
    osEvent event;
    os_event event_t;

    event = osMailGet((osMailQId)queue_id, millisec);
    memcpy(&event_t, &event, sizeof(osEvent));
    return event_t;
}

os_status os_mail_free(os_mail_qid queue_id, void *mail)
{
    return (os_status)osMailFree((osMailQId)queue_id, mail);
}

/************************************OS_POOL************************************/
os_pool_id os_pool_create(const os_pool_def_t *pool_def)
{
    return (os_pool_id)osPoolCreate((const osPoolDef_t *)pool_def);
}
void *os_pool_alloc(os_pool_id pool_id)
{
    return osPoolAlloc((osPoolId)pool_id);
}
void *os_pool_calloc(os_pool_id pool_id)
{
   return osPoolCAlloc((osPoolId)pool_id);
}
os_status os_pool_free(os_pool_id pool_id, void *block)
{
    return (os_status)osPoolFree((osPoolId)pool_id, block);
}
/************************************OS_MSG_QUEUE************************************/
/**
 * @brief  [Message queuing] create message queuing space
 * @note   NULL
 * @param  queue_def : Message queue information (size)
 * @param  thread_id : Thread ID (optional)
 * @retval None
 */
os_message_qid os_message_create(const os_messageq_def_t *queue_def, os_thread_id thread_id)
{
    return (os_message_qid)osMessageCreate((const osMessageQDef_t *)queue_def, thread_id);
}

/**
 * @brief  [Message queuing] Send a set of message queuing data
 * @note   NULL
 * @param  queue_id: Message queue ID
 * @param  info    : Message pointer
 * @param  millisec: Timeout 0xFFFFFFFF infinite wait
 * @retval None
 */
os_status os_message_put(os_message_qid queue_id, uint32_t info, uint32_t millisec)
{
    return (os_status)osMessagePut((osMessageQId)queue_id, info, millisec); // Send Message
}

/**
 * @brief  [Message queue] get a set of message queue data
 * @note   NULL
 * @param  queue_id: Message queue ID
 * @param  millisec: Waiting time 0xFFFFFFFF infinite waiting
 * @retval None
 */
os_event os_message_get(os_message_qid queue_id, uint32_t millisec)
{
    osEvent event;
    os_event event_t;
    event = osMessageGet((osMessageQId)queue_id, millisec);
    memcpy(&event_t, &event, sizeof(osEvent));
    return event_t;
}
/************************************OS_SIGNAL************************************/
extern int32_t isrSignalSet(osThreadId thread_id, int32_t signals);
int32_t isr_signal_set(os_thread_id thread_id, int32_t signals)
{
    return isrSignalSet(thread_id, signals);
}

int32_t os_signal_set(os_thread_id thread_id, int32_t signals)
{
    return osSignalSet(thread_id, signals);
}

int32_t os_signal_clear(os_thread_id thread_id, int32_t signals)
{
    return osSignalClear(thread_id, signals);
}

// If signals = 0, wait for any signal
os_event os_signal_wait(int32_t signals, uint32_t millisec)
{
    osEvent event;
    os_event event_t;

    event = osSignalWait(signals, millisec);
    memcpy(&event_t, &event, sizeof(osEvent));
    return event_t;
}

/********************************************************************************
* @file    os_api.h
* @author  jianqiang.xue
* @version V1.0.0
* @date    2021-04-03
* @brief   NULL
********************************************************************************/

#include <stdint.h>
#include "cmsis_os.h"

/// Timeout value.
#define OS_WAIT_FOREVER     0xFFFFFFFFU    ///< wait forever timeout value

/************************************OS_KERNEL************************************/
typedef enum {
    OS_OK                     =     0,       ///< function completed; no error or event occurred.
    OS_EVENT_SIGNAL           =  0x08,       ///< function completed; signal event occurred.
    OS_EVENT_MESSAGE          =  0x10,       ///< function completed; message event occurred.
    OS_EVENT_MAIL             =  0x20,       ///< function completed; mail event occurred.
    OS_EVENT_TIMEOUT          =  0x40,       ///< function completed; timeout occurred.
    OS_ERROR_PARAMETER        =  0x80,       ///< parameter error: a mandatory parameter was missing or specified an incorrect object.
    OS_ERROR_RESOURCE         =  0x81,       ///< resource not available: a specified resource was not available.
    OS_ERROR_TIMEOUTRESOURCE  =  0xC1,       ///< resource not available within given time: a specified resource was not available within the timeout period.
    OS_ERROR_ISR              =  0x82,       ///< not allowed in ISR context: the function cannot be called from interrupt service routines.
    OS_ERROR_ISRRECURSIVE     =  0x83,       ///< function called multiple times from ISR with same object.
    OS_ERROR_PRIORITY         =  0x84,       ///< system cannot determine priority or thread has illegal priority.
    OS_ERROR_NOMEMORY         =  0x85,       ///< system is out of memory: it was impossible to allocate or reserve memory for the operation.
    OS_ERROR_VALUE            =  0x86,       ///< value of a parameter is out of range.
    OS_ERROR_OS               =  0xFF,       ///< unspecified RTOS error: run-time error but no other error message fits.
    OS_STATUS_RESERVED        =  0x7FFFFFFF  ///< prevent from enum down-size compiler optimization.
} os_status;

os_status os_kernel_initialize (void);
os_status os_kernel_start(void);
os_status os_kernel_lock(void);
os_status os_kernel_unlock(void);
os_status os_delay(uint32_t ms);
uint32_t os_get_tick(void);
/************************************OS_EVENT************************************/
typedef struct os_mailq_cb    *os_mail_qid;
typedef struct os_messageq_cb *os_message_qid;

typedef struct  {
    os_status                 status;     ///< status code: event or error information
    union  {
      uint32_t                    v;     ///< message as 32-bit value
      void                       *p;     ///< message or mail as void pointer
      int32_t               signals;     ///< signal flags
    } value;                             ///< event value
    union  {
      os_mail_qid             mail_id;   ///< mail id obtained by \ref osMailCreate
      os_message_qid       message_id;   ///< message id obtained by \ref osMessageCreate
    } def;                               ///< event definition
} os_event;

/************************************OS_THREAD************************************/
#ifndef FREERTOS
typedef enum {
    OS_PRIORITY_IDLE          = -3,          ///< priority: idle (lowest)
    OS_PRIORITY_LOW           = -2,          ///< priority: low
    OS_PRIORITY_BELOWNORMAL   = -1,          ///< priority: below normal
    OS_PRIORITY_NORMAL        =  0,          ///< priority: normal (default)
    OS_PRIORITY_ABOVENORMAL   = +1,          ///< priority: above normal
    OS_PRIORITY_HIGH          = +2,          ///< priority: high
    OS_PRIORITY_REALTIME      = +3,          ///< priority: realtime (highest)
    OS_PRIORITY_ERROR         =  0x84        ///< system cannot determine priority or thread has illegal priority
} os_priority_t;
#else
typedef enum {
    OS_PRIORITY_IDLE          = 0,          ///< priority: idle (lowest)
    OS_PRIORITY_LOW           = 1,          ///< priority: low
    OS_PRIORITY_BELOWNORMAL   = 2,          ///< priority: below normal
    OS_PRIORITY_NORMAL        = 3,          ///< priority: normal (default)
    OS_PRIORITY_ABOVENORMAL   = 4,          ///< priority: above normal
    OS_PRIORITY_HIGH          = 5,          ///< priority: high
    OS_PRIORITY_REALTIME      = 6,          ///< priority: realtime (highest)
    OS_PRIORITY_ERROR         = 0x84        ///< system cannot determine priority or thread has illegal priority
} os_priority_t;
#endif

typedef struct os_thread_cb *os_thread_id;
typedef void (*os_pthread) (void const *argument);

typedef struct {
    os_pthread             pthread;      ///< start address of thread function
    os_priority_t          tpriority;    ///< initial thread priority
    uint32_t               instances;    ///< maximum number of instances of that thread function
    uint32_t               stacksize;    ///< stack size requirements in bytes; 0 is default stack size
} os_thread_def_t;

#define os_thread(name)  &os_thread_def_##name

#define os_thread_def(name, priority, instances, stacksz)  \
const os_thread_def_t os_thread_def_##name = {(name), (priority), (instances), (stacksz)}

os_thread_id os_thread_create(const os_thread_def_t *thread_def, void *arg);

/************************************OS_TIMER************************************/
typedef struct os_timer_cb *os_timer_id;
typedef void (*os_ptimer) (void const *argument);

typedef struct
{
    os_ptimer ptimer; ///< start address of a timer function
    void *timer;      ///< pointer to internal data
} os_timer_def_t;

typedef enum
{
    OS_TIMER_ONCE     = 0,    ///< one-shot timer
    OS_TIMER_PERIODIC = 1     ///< repeating timer
} os_timer_t;

#define os_timer(name) &os_timer_def_##name

#if (osCMSIS < 0x20000U)
#define os_timer_def(name, function) static uint8_t os_timer_cb_##name[40];\
static  os_timer_def_t os_timer_def_##name = {(function), ((void *)os_timer_cb_##name)}
#else
#define os_timer_def(name, function) static const uint8_t os_timer_cb_##name[10];\
static const os_timer_def_t os_timer_def_##name = {(function), ((void *)os_timer_cb_##name)}
#endif

os_timer_id os_timer_create(const os_timer_def_t *timer_def, os_timer_t type, void *arg);
os_status os_timer_start(os_timer_id timer_id, uint32_t millisec);
os_status os_timer_stop(os_timer_id timer_id);

/************************************OS_MAIL************************************/
typedef struct os_mailq_cb *os_mail_qid;
#define os_mail_qdef(name, queue_sz, type)                                        \
    static const uint8_t os_mailq_q_##name[4 + (queue_sz)] = {0};                      \
    static const uint8_t os_mailq_m_##name[3 + ((sizeof(type) + 3) / 4) * (queue_sz)]; \
    static void *os_mailq_p_##name[2] = {(os_mailq_q_##name), os_mailq_m_##name}; \
    static const os_mailq_def_t os_mailq_def_##name = {(queue_sz), sizeof(type), (os_mailq_p_##name)} \

typedef struct os_mailq_def
{
    uint16_t queue_sz; ///< number of elements in the queue
    uint16_t item_sz;  ///< size of an item
    void *pool;        ///< memory array for mail
} os_mailq_def_t;

#define os_mailq(name) &os_mailq_def_##name

os_mail_qid os_mail_create(const os_mailq_def_t *queue_def, os_thread_id thread_id);
void *os_mail_alloc(os_mail_qid queue_id, uint32_t millisec);
void *os_mail_clean_and_alloc(os_mail_qid queue_id, uint32_t millisec);
os_status os_mail_put(os_mail_qid queue_id, void *mail);
os_event os_mail_get(os_mail_qid queue_id, uint32_t millisec, void *arg);
os_status os_mail_free(os_mail_qid queue_id, void *mail);

/************************************OS_MSG_QUEUE************************************/
/// Message ID identifies the message queue (pointer to a message queue control block).
typedef struct os_messageq_cb *os_message_qid;
typedef struct os_messageq_def
{
    uint32_t queue_sz;            ///< number of elements in the queue
#if (osCMSIS < 0x20000U)
    void *pool;                   ///< memory array for messages
#else
    osMessageQueueAttr_t  attr;   ///< message queue attributes
#endif
} os_messageq_def_t;

#if (osCMSIS < 0x20000U)
#define os_message_qdef(name, queue_sz, type)                        \
    static uint8_t os_messageq_q_##name[4 + (queue_sz)] = {0};       \
    static const os_messageq_def_t os_messageq_def_##name = {(queue_sz), ((void *)os_messageq_q_##name)}
#else
#define os_message_qdef(name, queue_sz, type)                        \
    static const os_messageq_def_t os_messageq_def_##name = {(queue_sz), { NULL, 0U, NULL, 0U, NULL, 0U }}
#endif

/// \brief Access a Message Queue Definition.
/// \param         name          name of the queue
#define os_messageq(name)  &os_messageq_def_##name

os_message_qid os_message_create(const os_messageq_def_t *queue_def, os_thread_id thread_id);
os_status os_message_put(os_message_qid queue_id, uint32_t info, uint32_t millisec);
os_event os_message_get(os_message_qid queue_id, uint32_t millisec);
uint8_t os_message_get_space(os_message_qid queue_id);
uint8_t os_message_get_count(os_message_qid queue_id);
/************************************OS_POOL************************************/
/// Pool ID identifies the memory pool (pointer to a memory pool control block).
typedef struct os_pool_cb *os_pool_id;
typedef struct os_pool_deft
{
    uint32_t pool_sz; ///< number of items (elements) in the pool
    uint32_t item_sz; ///< size of an item
    void *pool;       ///< pointer to memory for pool
} os_pool_def_t;

#define os_pool_def(name, no, type)                                                                   \
    static const uint8_t os_pool_m_##name[3 + ((sizeof(type) + 3) / 4) * (no)];                       \
    static const os_pool_def_t os_pool_def_##name = {(no), sizeof(type), (void *)(os_pool_m_##name)}

#define os_pool(name)  &os_pool_def_##name

os_pool_id os_pool_create(const os_pool_def_t *pool_def);
void *os_pool_alloc(os_pool_id pool_id);
void *os_pool_calloc(os_pool_id pool_id);
os_status os_pool_free(os_pool_id pool_id, void *block);
uint8_t os_pool_get_space(os_pool_id pool_id);
/************************************OS_SIGNAL************************************/
int32_t isr_signal_set(os_thread_id thread_id, int32_t signals);
int32_t os_signal_set(os_thread_id thread_id, int32_t signals);
int32_t os_signal_clear(os_thread_id thread_id, int32_t signals);
os_event os_signal_wait(int32_t signals, uint32_t millisec);

#ifdef FREERTOS
void get_task_info(void);
#endif

Posted by Master Zen on Mon, 18 Oct 2021 19:52:20 -0700