[单片机框架][os层] RTX4 中间件 公共函数
2022-09-19 来源:csdn
重新封装RTX4函数,以便适配RTX5 / FREERTOS / FREERTOS_NRF_RTC。
Keil RTX是为ARM和Cortex-M设备设计的免版税,确定性的实时操作系统。它允许您创建同时执行多个功能的程序,并帮助创建更好的结构和更容易维护的应用程序。
特征
具有源代码的免版权,确定性RTOS
灵活的调度:循环,抢占和协作
具有低中断延迟的高速实时操作
为资源有限的系统提供小封装
无限数量的任务每个具有254个优先级
无限数量的邮箱,信号量,互斥量和计时器
支持多线程和线程安全操作
内核感知调试支持MDK-ARM
使用μVision配置向导的基于对话框的设置
优点
尽管无需实时操作系统(通过在超级循环中执行一个或多个功能)就可以创建实时程序,这个应该指的是裸机了,但KeilRTX为您解决的RTOS有许多调度,维护和计时问题。
注意事项
所有MDK-ARM版本都包含RTX源代码。
【RTX内核在新工程中的使用步骤】
在keil开发环境搭建好的情况下,设置在工程中使用RTX内核,选择 Project —> Options for Target,然后,为操作系统[ Operating system]选择 RTX kernel 并点击 OK;
从 KeilARMBoardsSTSTM32F10X_EVALRTX_Blinky 文件夹中为目标设备复制 RTX_Config.c 配置文件到 User/ 下;
// 如果没有针对独特设备的文件,那么就从Philips文件夹下面复制文件,并且依照目标设备进行修改。
在 stm32f10x_it.c中注释掉 SVC_Handler() PendSV_Handler() SysTick_Handler()三个函数,因为使用了RTX,为了避免函数名被重复定义,这三个函数必须注释掉,要不RTX就没法运行;
在RTX_Config.c 中的配置选项可以:
指定当前运行任务的数目;
指定使用用户自定堆栈任务的数目;
指定为每个任务分配堆栈的大小;
开启或是禁止堆栈校核;
指定CPU定时器作为系统定时器;
为选中的定时器指定输入的时钟频率;;
指定定时器节拍间隔;
开启或是禁止轮转任务调度;
为轮转任务调度指定时间片;
定义空闲任务操作;
指定用户定时器的数目;
为用户定时器回调函数指定代码;
/********************************************************************************
* @file os_api.c
* @author jianqiang.xue
* @Version V1.0.0
* @Date 2021-04-03
* @brief 大部分RTX系统函数在:**Keil_v5ArmPacksARMCMSIS5.6.0CMSISRTOSRTXSRC
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include #include /* 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 [消息队列] 创建消息队列空间 * @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, thread_id); } /** * @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; } /************************************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); } // 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 #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