首页 > 其他分享 >[单片机框架][os层] RTX5 中间件 公共函数

[单片机框架][os层] RTX5 中间件 公共函数

时间:2022-10-31 18:36:43浏览次数:132  
标签:thread OS RTX5 中间件 queue 单片机 os id def


Keil RTX5 是一种免版税、确定性、全功能的实时操作系统,它实现了 CMSIS-RTOS API v2,这是一种适用于基于
Cortex-M 处理器的设备的通用 RTOS 接口。功能包括定期激活定时器功能、内存管理和线程之间的消息交换。

现在RTX4和RTX5属于CMSIS软件包的一部分,Apache2.0授权,几乎随意商用。Github开源地址:​​https://github.com/ARM-software/CMSIS_5​

重新封装RTX5函数,以便适配RTX4 / FREERTOS / FREERTOS_NRF_RTC。

特征

开源免费的确定性RTOS。

  • 支持时间片,抢占式和合作式调度。
  • 以低的中断延迟执行高速实时操作(对于M3/M4/M7内核可以实现零中断延迟)。
  • 小的空间占用适用于资源受限的系统。
  • 不限制数量的信号量,互斥信号量,消息邮箱和软定时器。
  • 支持多线程和线程安全操作。
  • 通过MDK的RTE开发环境可以一键添加。
  • 使用MDK基于对话框的配置向导,可以很方便的完成MDK的配置。
  • 零中断延迟

特点和优势

  • 包含在 MDK 中
    Keil RTX5 随 Keil MDK 免费提供。它是完全可配置的,并在 Apache 2.0 许可下在 Github 上公开开发。
  • 便于使用
    Keil RTX5 在 µVision IDE/调试器中得到很好的支持,它具有 RTX 感知工具,使您能够快速调试实时应用程序,从而加快产品开发速度并减少学习时间。
  • 专为嵌入式系统构建
    其较小的内存占用(ROM 中低至 5KB)和高速使 Keil RTX5 成为嵌入式系统的理想选择。从多个内核调度选项中进行选择,以找到最适合您的应用程序的选项。
  • 确定性行为
    Keil RTX5 提供完全确定性的行为,这意味着在预定义的时间范围或期限内处理事件和中断。您的应用程序可以依赖一致且已知的进程计时。
  • 免版税
    没有运行时版税支付或其他隐藏费用。运送基于 RTX 的产品,无需额外费用或经常性成本。
  • 功能安全
    Keil RTX 的合格版本可用于功能安全应用。

RTX5安全认证

TX5的汽车级,工业级,医疗和铁路安全认证已经通过:

  • ISO 26262 (ASIL D) 汽车级最高安全认证
  • IEC 61508 (SIL 3) 工业级认证
  • IEC 62304 (Class C) 医疗认证
  • EN 50128 (SIL 4) 运输/铁路安全认证

超级循环的缺点

必须在中断(ISR)内处理时间关键运算:

  • ISR 函数变得非常复杂,并且需要很长执行时间。
  • ISR 嵌套可能产生不可预测的执行时间和堆栈需求。

超级循环和ISR之间的数据交换是通过全局共享变量进行的:

  • 应用程序的程序员必须确保数据一致性。

超级循环可以与系统计时器轻松同步,如果系统需要多种不同的周期时间,则会很难实现。

  • 超过超级循环周期的耗时函数需要做拆分。
  • 增加软件开销,应用程序难以理解。
  • 超级循环使得应用程序变得非常复杂,因此难以扩展:
  • 一个简单的更改就可能产生不可预测的副作用,对这种副作用进行分析非常耗时。
  • 超级循环 概念的这些缺点可以通过使用实时操作系统 (RTOS) 来解决。

CMSIS-RTOS v2 和 Keil RTX v5 有哪些新变化?

新的 CMSIS-RTOS API v2 解决了新的要求,例如动态对象创建、对 ARMv8-M 的支持以及对 C++ 运行时环境的完全支持。此网络研讨会录音比较了 CMSIS-RTOS API 版本,并展示了如何利用 Keil RTX5 中的新功能,Keil RTX5 是第一个实现新 API 作为其原生 RTOS 接口的实时操作系统,适用于基于 ARM Cortex-M 处理器的设备。

/********************************************************************************
* @file os_api.c
* @author jianqiang.xue
* @Version V1.0.0
* @Date 2021-04-03
* @brief NULL
********************************************************************************/

#include <stdio.h>
#include <string.h>
#include "cmsis_os.h"
#include "cmsis_os2.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_kernel_lock(void)
{
return (os_status)osKernelLock();
}

os_status os_kernel_unlock(void)
{
return (os_status)osKernelUnlock();
}

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

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

/************************************OS_THREAD************************************/
os_thread_id os_thread_create(const os_thread_def_t *thread_def, void *arg)
{
if (thread_def == NULL)
{
return NULL;
}
osThreadAttr_t attr = {0};
attr.name = arg;
attr.priority = osPriorityLow;
if (thread_def->tpriority == OS_PRIORITY_LOW)
{
attr.priority = osPriorityLow;
}
else if (thread_def->tpriority == OS_PRIORITY_NORMAL)
{
attr.priority = osPriorityNormal;
}
else if (thread_def->tpriority == OS_PRIORITY_ABOVENORMAL)
{
attr.priority = osPriorityAboveNormal;
}
else if (thread_def->tpriority == OS_PRIORITY_HIGH)
{
attr.priority = osPriorityHigh;
}
else if (thread_def->tpriority == OS_PRIORITY_REALTIME)
{
attr.priority = osPriorityRealtime;
}
else
{
attr.priority = osPriorityLow;
}
attr.stack_size = thread_def->stacksize;
attr.attr_bits = osThreadDetached;
return (os_thread_id)osThreadNew((osThreadFunc_t)thread_def->pthread, arg, &attr);
}

/************************************OS_TIMER************************************/
os_timer_id os_timer_create(const os_timer_def_t *timer_def, os_timer_t type, void *arg)
{
return osTimerNew((osTimerFunc_t)timer_def->ptimer, (os_timer_type)type, arg, NULL);
}

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)osMessageQueueNew(queue_def->queue_sz, queue_def->item_sz, NULL);
}

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

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

os_status os_mail_put(os_mail_qid queue_id, void *mail)
{
return (os_status)osMessageQueuePut((osMessageQueueId_t)queue_id, mail, NULL, NULL);
}

os_event os_mail_get(os_mail_qid queue_id, uint32_t millisec, void *arg)
{
osStatus_t status;
os_event event_t;
status = osMessageQueueGet((osMessageQueueId_t)queue_id, arg, NULL, millisec);
event_t.status = (os_status)status;
event_t.def.message_id = (os_message_qid)queue_id;
event_t.value.p = arg;
return event_t;
}

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

/************************************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 [消息队列] 创建消息队列空间
* @note NULL
* @param queue_def : 消息队列信息(大小)
* @param thread_id : 线程ID(可以无视不填)
* @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, NULL);
}

/**
* @brief [消息队列] 发送一组消息队列数据
* @note NULL
* @param queue_id: 消息队列ID
* @param info : 消息指针
* @param millisec: 超时时间 0xFFFFFFFF 无限等待
* @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 [消息队列] 得到一组消息队列数据
* @note NULL
* @param queue_id: 消息队列ID
* @param millisec: 等待时间 0xFFFFFFFF 无限等待
* @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;
}

/**
* @brief [消息队列] 得到当前剩余量
* @note NULL
* @param queue_id: 消息队列ID
* @retval 返回当前剩余量
*/
uint8_t os_message_get_space(os_message_qid queue_id)
{
return (uint8_t)osMessageQueueGetSpace(queue_id);
}

/************************************OS_SIGNAL************************************/
int32_t isr_signal_set(os_thread_id thread_id, int32_t signals)
{
return osSignalSet(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);
}

// signals = 0,则等待任意信号.
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


标签:thread,OS,RTX5,中间件,queue,单片机,os,id,def
From: https://blog.51cto.com/xuejianqiang/5810862

相关文章