移植UCOSII系统到STM32上

移植UCOSII系统到STM32上
This commit is contained in:
loveclear
2018-08-07 13:50:57 +08:00
parent f74b3546c3
commit 16f7d3a693
29 changed files with 14355 additions and 460 deletions

View File

@@ -0,0 +1,91 @@
// 学习ucosII操作系统
// 1. 了解ucosII的系统架构与ASCII源码
// 2. 学习ucosII在STM32上的移植
// 提供的 SYSTEM 文件夹里面的系统函数直接支持 ucosII只需要在 sys.h 文件里面将SYSTEM_SUPPORT_UCOS 宏定义改为 1 即可通过 delay_init 函数初始化 ucosII 的系统时钟节拍,为 ucosII 提供时钟节拍。
// 3. 理解ucosII操作系统下实现多任务并发工作的编程原理
// 4. 理解 任务
// 任务其实就是一个死循环函数
void MyTask(void *pdata)
{
// 准备
while(1)
{
// 任务实体代码
OSTimeDlyHMSM(x,x,x,x);//调用任务延时函数释放cpu控制权
// 例如该任务延时1s后释放cpu控制权
}
}
// 5. 理解 任务优先级
// ucos中每个任务都有唯一的一个优先级ucos不支持多个任务优先级相同。
// 任务就绪表中总是优先级最高的任务获得cpu使用权
// ucos中任务优先级 就是 任务 的唯一标识
// 6. 理解 任务堆栈
// 就是存储器中分配了一块连续的存储空间,作为 任务堆栈 使用
// 满足任务切换和响应中断时保存cpu寄存器中的内容以及任务调用其它函数时的需要
// 每个任务都有自己的一个任务堆栈,它是任务创建的一个重要入口参数
// 7. 理解 任务控制块
// 用来记录任务堆栈指针,任务当前状态以及任务优先等级等任务的相关属性
// 包含三个重要参数:任务函数指针、任务堆栈指针、任务优先级
// 8. 理解 任务就绪表
// 记录系统中所有处于就绪状态的任务
// 它是一个位图任务相应位置0或置1表示是否处于就绪状态
// 9. 理解 任务调度
// 在任务就绪表中查找优先级最高的就绪任务
// 实现任务的切换
// 10. 理解ucos中任务的5个状态及其转换关系
// 就绪,运行,等待,睡眠,中断
//********************************************************************************************************************************
// STM32上运行uscoII来进行硬件开发
// 1. 移植 ucosII 到stm32
// 2. 编写任务函数并设置其堆栈大小和优先级等参数
// 3. 初始化ucosII并在ucosII中创建任务
// 4. 启动 ucosII
//********************************************************************************************************************************
// 工程中要添加的文件夹以及文件:
// 1. UCOSII-CORE
---- 添加 ucosII源码 Source 文件夹中除 os_cfg_r.h 和 os_dbg_r.c 文件外的所有文件
// 2. UCOSII-CONFIG
---- 添加 includes.h 和 os_cfg.h 文件
// 3. UCOSII-PORT
---- 添加 os_cpu.h、os_cpu_a.asm、os_cpu_c.c、os_dbg.c、os_dbg_r.c 文件
// 注意:不要添加 ucosii.c 文件到 UCOSII-CORE 分组中,防止出现编译时重复定义的错误。

View File

@@ -0,0 +1,37 @@
// 这是在网上看到的一篇文章,觉得写得还行
// 当然这篇文章也是国内最大的盗版网站CSDN上某人转载的一篇文章
// https://blog.csdn.net/eagle11235/article/details/54620131
// 转载自:微信公众号 嵌入式ARM
// 毕业后做的项目用到过RTX51 uCos linux 当做linux下的项目时研究过一阵子linux的源码后来又一天闲来无事再去看uCos的源码时突然发现uCos里的一些原理对于理解和构建一个操作系统这这么的经典和透彻
// 于是我觉得是时候再好好理解和整理下uCos里的一些原理了。 我觉得第一个要解决的问题是为什么我需要uCos
// 就像最开始学C编程时老师告诉我指针很重要我那时就有一个大的疑问指针到底有什么好
// 还一边在心里嘀咕着我不用指针不一样把程序编出来了现在想想c语言没了指针将寸步难行
// 回到正题我们到底为什么需要uCos
// 一般的简单的嵌入式设备的编程思路是下面这样的main{{处理事务1}{处理事务2}{处理事务3} .......{处理事务N}}isr_server{{处理中断}}
// 这是最一般的思路对于简单的系统当然是够用了但这样的系统实时性是很差的比如“事务1”如果是一个用户输入的检测当用户输入时如果程序正在处理事务1下面的那些事务那么这次用户输入将失效用户的体验是“这个按键不灵敏这个机器很慢”。
// 而我们如果把事务放到中断里去处理,虽然改善了实时性但会导致另外一个问题,有可能会引发中断丢失,这个后果有时候比“慢一点”更加严重和恶劣!
// 又比如事务2是一个只需要1s钟处理一次的任务那么显然事务2会白白浪费CPU的时间。
// 这时我们可能需要改进我们的编程思路一般我们会尝试采用“时间片”的方式。这时候编程会变成下面的方式main{{事务1的时间片到了则处理事务1}{事务2的时间片到了则处理事务2} .......{事务N的时间片到了则处理事务N}}time_isr_server{{判断每个事务的时间片是否到来,并进行标记}}isr_server{{处理中断}}
// 我们可以看到,这种改进后的思路,使得事务的执行时间得到控制,事务只在自己的时间片到来后,才会去执行,但我们发现,这种方式仍然不能彻底解决“实时性”的问题,因为某个事务的时间片到来后,也不能立即就执行,她必须等到当前事务的时间片用完,并且后面的事务时间片没到来,她才有机会获得“执行时间”。
// 这时候我们需要继续改进思路, 为了使得某个事务的时间片到来后能立即执行,我们需要在时钟中断里判断完时间片后,改变程序的返回位置,让程序不返回到刚刚被打断的位置,而从最新获得了时间片的事务处开始执行,这样就彻底解决了事务的实时问题。
// 我们在这个思路上进行改进我们需要在每次进入时钟中断前保存CPU的当前状态和当前事务用到的一些数据然后我们进入时钟中断进行时间片处理若发现有新的更紧急的事务的时间片到来了则我们改变中断的返回的地址并在CPU中恢复这个更紧急的事务的现场然后返回中断开始执行这个更紧急的事务。
// 上面的这段话有些不好读,事实上,这是因为要实现这个过程是有些复杂和麻烦的,这时候我们就需要找一个操作系统(OS)帮我们做这些事了,如果你能自己用代码实现这个过程,事实上你就在自己写操作系统了,其实从这里也可也看出,操作系统的原理其实并不那么神秘,只是一些细节你很难做好。
// uCos就是这样一个操作系统她能帮你完成这些事情而且是很优雅的帮你完成
// uCos的用处远不止帮你完成这个“事务时间片的处理”她还能帮你处理各种超时进行内存管理完成任务间的通信等有了她程序的层次也更加清晰给系统添加功能也更方便这一切在大型项目中越发的明显
// 我们知道了uCos能给我们提供这么多的便利那么我们就开始使用uCos吧

View File

@@ -157,6 +157,10 @@ void append(unsigned char dat, BUFFER *b)
}
}
/ **********************************************************************************************************************************
// 函数原型(函数声明)就是告诉编译器这个函数是存在的,让编译器知道这个函数的相关信息。函数原型不要求提供形参名,有类型列表就可以了。

View File

@@ -147,6 +147,10 @@ TIM_SetAutoreload(TIMx,fpwm_arr)
>          按下K7计时加长;
>
>          按下K8计时减少
### 5. UC/OSII系统使用说明
> sys.h 文件中 SYSTEM_SUPPORT_UCOS 置1
> stm32f10x_it.c 文件中 USE_UCOSII 置1实际 stm32f10x_it.c 这个文件没有在我的项目中用到)
\* @Version: Beta2.0

55
UCOSII/CONFIG/includes.h Normal file
View File

@@ -0,0 +1,55 @@
/*
************************************************************************************************
<EFBFBD><EFBFBD>Ҫ<EFBFBD>İ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
<EFBFBD><EFBFBD> <20><>: INCLUDES.C ucos<6F><73><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
<EFBFBD><EFBFBD> <20><>: Jean J. Labrosse
************************************************************************************************
*/
#ifndef __INCLUDES_H__
#define __INCLUDES_H__
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
#include "ucos_ii.h"
#include "os_cpu.h"
#include "os_cfg.h"
#include <stm32f10x.h>
#endif

144
UCOSII/CONFIG/os_cfg.h Normal file
View File

@@ -0,0 +1,144 @@
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
* uC/OS-II Configuration File for V2.8x
*
* (c) Copyright 2005-2009, Micrium, Weston, FL
* All Rights Reserved
*
*
* File : OS_CFG.H
* By : Jean J. Labrosse
* Version : V2.91
*
* LICENSING TERMS:
* ---------------
* uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
* If you plan on using uC/OS-II in a commercial product you need to contact Micri<72>m to properly license
* its use in your product. We provide ALL the source code for your convenience and to help you experience
* uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a
* licensing fee.
*********************************************************************************************************
*/
#ifndef OS_CFG_H
#define OS_CFG_H
/* ---------------------- MISCELLANEOUS ----------------------- */
#define OS_APP_HOOKS_EN 0u /* Application-defined hooks are called from the uC/OS-II hooks */
#define OS_ARG_CHK_EN 0u /* Enable (1) or Disable (0) argument checking */
#define OS_CPU_HOOKS_EN 1u /* uC/OS-II hooks are found in the processor port files */
#define OS_DEBUG_EN 0u /* Enable(1) debug variables */
#define OS_EVENT_MULTI_EN 0u /* Include code for OSEventPendMulti() */
#define OS_EVENT_NAME_EN 0u /* Enable names for Sem, Mutex, Mbox and Q */
#define OS_LOWEST_PRIO 63u /* Defines the lowest priority that can be assigned ... */
/* ... MUST NEVER be higher than 254! */
#define OS_MAX_EVENTS 10u /* Max. number of event control blocks in your application */
#define OS_MAX_FLAGS 5u /* Max. number of Event Flag Groups in your application */
#define OS_MAX_MEM_PART 0u /* Max. number of memory partitions */
#define OS_MAX_QS 5u /* Max. number of queue control blocks in your application */
#define OS_MAX_TASKS 10u /* Max. number of tasks in your application, MUST be >= 2 */
#define OS_SCHED_LOCK_EN 1u /* Include code for OSSchedLock() and OSSchedUnlock() */
#define OS_TICK_STEP_EN 1u /* Enable tick stepping feature for uC/OS-View */
#define OS_TICKS_PER_SEC 200u /* Set the number of ticks in one second */
/* --------------------- TASK STACK SIZE ---------------------- */
#define OS_TASK_TMR_STK_SIZE 128u /* Timer task stack size (# of OS_STK wide entries) */
#define OS_TASK_STAT_STK_SIZE 128u /* Statistics task stack size (# of OS_STK wide entries) */
#define OS_TASK_IDLE_STK_SIZE 128u /* Idle task stack size (# of OS_STK wide entries) */
/* --------------------- TASK MANAGEMENT ---------------------- */
#define OS_TASK_CHANGE_PRIO_EN 1u /* Include code for OSTaskChangePrio() */
#define OS_TASK_CREATE_EN 1u /* Include code for OSTaskCreate() */
#define OS_TASK_CREATE_EXT_EN 1u /* Include code for OSTaskCreateExt() */
#define OS_TASK_DEL_EN 1u /* Include code for OSTaskDel() */
#define OS_TASK_NAME_EN 1u /* Enable task names */
#define OS_TASK_PROFILE_EN 1u /* Include variables in OS_TCB for profiling */
#define OS_TASK_QUERY_EN 1u /* Include code for OSTaskQuery() */
#define OS_TASK_REG_TBL_SIZE 1u /* Size of task variables array (#of INT32U entries) */
#define OS_TASK_STAT_EN 1u /* Enable (1) or Disable(0) the statistics task */
#define OS_TASK_STAT_STK_CHK_EN 1u /* Check task stacks from statistic task */
#define OS_TASK_SUSPEND_EN 1u /* Include code for OSTaskSuspend() and OSTaskResume() */
#define OS_TASK_SW_HOOK_EN 1u /* Include code for OSTaskSwHook() */
/* ----------------------- EVENT FLAGS ------------------------ */
#define OS_FLAG_EN 1u /* Enable (1) or Disable (0) code generation for EVENT FLAGS */
#define OS_FLAG_ACCEPT_EN 1u /* Include code for OSFlagAccept() */
#define OS_FLAG_DEL_EN 1u /* Include code for OSFlagDel() */
#define OS_FLAG_NAME_EN 1u /* Enable names for event flag group */
#define OS_FLAG_QUERY_EN 1u /* Include code for OSFlagQuery() */
#define OS_FLAG_WAIT_CLR_EN 1u /* Include code for Wait on Clear EVENT FLAGS */
#define OS_FLAGS_NBITS 16u /* Size in #bits of OS_FLAGS data type (8, 16 or 32) */
/* -------------------- MESSAGE MAILBOXES --------------------- */
#define OS_MBOX_EN 1u /* Enable (1) or Disable (0) code generation for MAILBOXES */
#define OS_MBOX_ACCEPT_EN 1u /* Include code for OSMboxAccept() */
#define OS_MBOX_DEL_EN 1u /* Include code for OSMboxDel() */
#define OS_MBOX_PEND_ABORT_EN 1u /* Include code for OSMboxPendAbort() */
#define OS_MBOX_POST_EN 1u /* Include code for OSMboxPost() */
#define OS_MBOX_POST_OPT_EN 1u /* Include code for OSMboxPostOpt() */
#define OS_MBOX_QUERY_EN 1u /* Include code for OSMboxQuery() */
/* --------------------- MEMORY MANAGEMENT -------------------- */
#define OS_MEM_EN 1u /* Enable (1) or Disable (0) code generation for MEMORY MANAGER */
#define OS_MEM_NAME_EN 1u /* Enable memory partition names */
#define OS_MEM_QUERY_EN 1u /* Include code for OSMemQuery() */
/* ---------------- MUTUAL EXCLUSION SEMAPHORES --------------- */
#define OS_MUTEX_EN 1u /* Enable (1) or Disable (0) code generation for MUTEX */
#define OS_MUTEX_ACCEPT_EN 1u /* Include code for OSMutexAccept() */
#define OS_MUTEX_DEL_EN 1u /* Include code for OSMutexDel() */
#define OS_MUTEX_QUERY_EN 1u /* Include code for OSMutexQuery() */
/* ---------------------- MESSAGE QUEUES ---------------------- */
#define OS_Q_EN 1u /* Enable (1) or Disable (0) code generation for QUEUES */
#define OS_Q_ACCEPT_EN 1u /* Include code for OSQAccept() */
#define OS_Q_DEL_EN 1u /* Include code for OSQDel() */
#define OS_Q_FLUSH_EN 1u /* Include code for OSQFlush() */
#define OS_Q_PEND_ABORT_EN 1u /* Include code for OSQPendAbort() */
#define OS_Q_POST_EN 1u /* Include code for OSQPost() */
#define OS_Q_POST_FRONT_EN 1u /* Include code for OSQPostFront() */
#define OS_Q_POST_OPT_EN 1u /* Include code for OSQPostOpt() */
#define OS_Q_QUERY_EN 1u /* Include code for OSQQuery() */
/* ------------------------ SEMAPHORES ------------------------ */
#define OS_SEM_EN 1u /* Enable (1) or Disable (0) code generation for SEMAPHORES */
#define OS_SEM_ACCEPT_EN 1u /* Include code for OSSemAccept() */
#define OS_SEM_DEL_EN 1u /* Include code for OSSemDel() */
#define OS_SEM_PEND_ABORT_EN 1u /* Include code for OSSemPendAbort() */
#define OS_SEM_QUERY_EN 1u /* Include code for OSSemQuery() */
#define OS_SEM_SET_EN 1u /* Include code for OSSemSet() */
/* --------------------- TIME MANAGEMENT ---------------------- */
#define OS_TIME_DLY_HMSM_EN 1u /* Include code for OSTimeDlyHMSM() */
#define OS_TIME_DLY_RESUME_EN 1u /* Include code for OSTimeDlyResume() */
#define OS_TIME_GET_SET_EN 1u /* Include code for OSTimeGet() and OSTimeSet() */
#define OS_TIME_TICK_HOOK_EN 1u /* Include code for OSTimeTickHook() */
/* --------------------- TIMER MANAGEMENT --------------------- */
#define OS_TMR_EN 0u /* Enable (1) or Disable (0) code generation for TIMERS */
#define OS_TMR_CFG_MAX 16u /* Maximum number of timers */
#define OS_TMR_CFG_NAME_EN 1u /* Determine timer names */
#define OS_TMR_CFG_WHEEL_SIZE 8u /* Size of timer wheel (#Spokes) */
#define OS_TMR_CFG_TICKS_PER_SEC 10u /* Rate at which timer management task runs (Hz) */
#endif

2029
UCOSII/CORE/os_core.c Normal file

File diff suppressed because it is too large Load Diff

1215
UCOSII/CORE/os_flag.c Normal file

File diff suppressed because it is too large Load Diff

647
UCOSII/CORE/os_mbox.c Normal file
View File

@@ -0,0 +1,647 @@
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
* MESSAGE MAILBOX MANAGEMENT
*
* (c) Copyright 1992-2009, Micrium, Weston, FL
* All Rights Reserved
*
* File : OS_MBOX.C
* By : Jean J. Labrosse
* Version : V2.91
*
* LICENSING TERMS:
* ---------------
* uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
* If you plan on using uC/OS-II in a commercial product you need to contact Micri<72>m to properly license
* its use in your product. We provide ALL the source code for your convenience and to help you experience
* uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a
* licensing fee.
*********************************************************************************************************
*/
#ifndef OS_MASTER_FILE
#include <ucos_ii.h>
#endif
#if OS_MBOX_EN > 0u
/*
*********************************************************************************************************
* ACCEPT MESSAGE FROM MAILBOX
*
* Description: This function checks the mailbox to see if a message is available. Unlike OSMboxPend(),
* OSMboxAccept() does not suspend the calling task if a message is not available.
*
* Arguments : pevent is a pointer to the event control block
*
* Returns : != (void *)0 is the message in the mailbox if one is available. The mailbox is cleared
* so the next time OSMboxAccept() is called, the mailbox will be empty.
* == (void *)0 if the mailbox is empty or,
* if 'pevent' is a NULL pointer or,
* if you didn't pass the proper event pointer.
*********************************************************************************************************
*/
#if OS_MBOX_ACCEPT_EN > 0u
void *OSMboxAccept (OS_EVENT *pevent)
{
void *pmsg;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return ((void *)0);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
return ((void *)0);
}
OS_ENTER_CRITICAL();
pmsg = pevent->OSEventPtr;
pevent->OSEventPtr = (void *)0; /* Clear the mailbox */
OS_EXIT_CRITICAL();
return (pmsg); /* Return the message received (or NULL) */
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* CREATE A MESSAGE MAILBOX
*
* Description: This function creates a message mailbox if free event control blocks are available.
*
* Arguments : pmsg is a pointer to a message that you wish to deposit in the mailbox. If
* you set this value to the NULL pointer (i.e. (void *)0) then the mailbox
* will be considered empty.
*
* Returns : != (OS_EVENT *)0 is a pointer to the event control clock (OS_EVENT) associated with the
* created mailbox
* == (OS_EVENT *)0 if no event control blocks were available
*********************************************************************************************************
*/
OS_EVENT *OSMboxCreate (void *pmsg)
{
OS_EVENT *pevent;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
if (OSSafetyCriticalStartFlag == OS_TRUE) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
if (OSIntNesting > 0u) { /* See if called from ISR ... */
return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */
}
OS_ENTER_CRITICAL();
pevent = OSEventFreeList; /* Get next free event control block */
if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */
OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
}
OS_EXIT_CRITICAL();
if (pevent != (OS_EVENT *)0) {
pevent->OSEventType = OS_EVENT_TYPE_MBOX;
pevent->OSEventCnt = 0u;
pevent->OSEventPtr = pmsg; /* Deposit message in event control block */
#if OS_EVENT_NAME_EN > 0u
pevent->OSEventName = (INT8U *)(void *)"?";
#endif
OS_EventWaitListInit(pevent);
}
return (pevent); /* Return pointer to event control block */
}
/*$PAGE*/
/*
*********************************************************************************************************
* DELETE A MAIBOX
*
* Description: This function deletes a mailbox and readies all tasks pending on the mailbox.
*
* Arguments : pevent is a pointer to the event control block associated with the desired
* mailbox.
*
* opt determines delete options as follows:
* opt == OS_DEL_NO_PEND Delete the mailbox ONLY if no task pending
* opt == OS_DEL_ALWAYS Deletes the mailbox even if tasks are waiting.
* In this case, all the tasks pending will be readied.
*
* perr is a pointer to an error code that can contain one of the following values:
* OS_ERR_NONE The call was successful and the mailbox was deleted
* OS_ERR_DEL_ISR If you attempted to delete the mailbox from an ISR
* OS_ERR_INVALID_OPT An invalid option was specified
* OS_ERR_TASK_WAITING One or more tasks were waiting on the mailbox
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mailbox
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
*
* Returns : pevent upon error
* (OS_EVENT *)0 if the mailbox was successfully deleted.
*
* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of
* the mailbox MUST check the return code of OSMboxPend().
* 2) OSMboxAccept() callers will not know that the intended mailbox has been deleted!
* 3) This call can potentially disable interrupts for a long time. The interrupt disable
* time is directly proportional to the number of tasks waiting on the mailbox.
* 4) Because ALL tasks pending on the mailbox will be readied, you MUST be careful in
* applications where the mailbox is used for mutual exclusion because the resource(s)
* will no longer be guarded by the mailbox.
*********************************************************************************************************
*/
#if OS_MBOX_DEL_EN > 0u
OS_EVENT *OSMboxDel (OS_EVENT *pevent,
INT8U opt,
INT8U *perr)
{
BOOLEAN tasks_waiting;
OS_EVENT *pevent_return;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*perr = OS_ERR_PEVENT_NULL;
return (pevent);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
*perr = OS_ERR_EVENT_TYPE;
return (pevent);
}
if (OSIntNesting > 0u) { /* See if called from ISR ... */
*perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
return (pevent);
}
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on mailbox */
tasks_waiting = OS_TRUE; /* Yes */
} else {
tasks_waiting = OS_FALSE; /* No */
}
switch (opt) {
case OS_DEL_NO_PEND: /* Delete mailbox only if no task waiting */
if (tasks_waiting == OS_FALSE) {
#if OS_EVENT_NAME_EN > 0u
pevent->OSEventName = (INT8U *)(void *)"?";
#endif
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
pevent->OSEventCnt = 0u;
OSEventFreeList = pevent; /* Get next free event control block */
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
pevent_return = (OS_EVENT *)0; /* Mailbox has been deleted */
} else {
OS_EXIT_CRITICAL();
*perr = OS_ERR_TASK_WAITING;
pevent_return = pevent;
}
break;
case OS_DEL_ALWAYS: /* Always delete the mailbox */
while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for mailbox */
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_OK);
}
#if OS_EVENT_NAME_EN > 0u
pevent->OSEventName = (INT8U *)(void *)"?";
#endif
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
pevent->OSEventCnt = 0u;
OSEventFreeList = pevent; /* Get next free event control block */
OS_EXIT_CRITICAL();
if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */
OS_Sched(); /* Find highest priority task ready to run */
}
*perr = OS_ERR_NONE;
pevent_return = (OS_EVENT *)0; /* Mailbox has been deleted */
break;
default:
OS_EXIT_CRITICAL();
*perr = OS_ERR_INVALID_OPT;
pevent_return = pevent;
break;
}
return (pevent_return);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* PEND ON MAILBOX FOR A MESSAGE
*
* Description: This function waits for a message to be sent to a mailbox
*
* Arguments : pevent is a pointer to the event control block associated with the desired mailbox
*
* timeout is an optional timeout period (in clock ticks). If non-zero, your task will
* wait for a message to arrive at the mailbox up to the amount of time
* specified by this argument. If you specify 0, however, your task will wait
* forever at the specified mailbox or, until a message arrives.
*
* perr is a pointer to where an error message will be deposited. Possible error
* messages are:
*
* OS_ERR_NONE The call was successful and your task received a
* message.
* OS_ERR_TIMEOUT A message was not received within the specified 'timeout'.
* OS_ERR_PEND_ABORT The wait on the mailbox was aborted.
* OS_ERR_EVENT_TYPE Invalid event type
* OS_ERR_PEND_ISR If you called this function from an ISR and the result
* would lead to a suspension.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked
*
* Returns : != (void *)0 is a pointer to the message received
* == (void *)0 if no message was received or,
* if 'pevent' is a NULL pointer or,
* if you didn't pass the proper pointer to the event control block.
*********************************************************************************************************
*/
/*$PAGE*/
void *OSMboxPend (OS_EVENT *pevent,
INT32U timeout,
INT8U *perr)
{
void *pmsg;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*perr = OS_ERR_PEVENT_NULL;
return ((void *)0);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
*perr = OS_ERR_EVENT_TYPE;
return ((void *)0);
}
if (OSIntNesting > 0u) { /* See if called from ISR ... */
*perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return ((void *)0);
}
if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */
*perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */
return ((void *)0);
}
OS_ENTER_CRITICAL();
pmsg = pevent->OSEventPtr;
if (pmsg != (void *)0) { /* See if there is already a message */
pevent->OSEventPtr = (void *)0; /* Clear the mailbox */
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
return (pmsg); /* Return the message received (or NULL) */
}
OSTCBCur->OSTCBStat |= OS_STAT_MBOX; /* Message not available, task will pend */
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;
OSTCBCur->OSTCBDly = timeout; /* Load timeout in TCB */
OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find next highest priority task ready to run */
OS_ENTER_CRITICAL();
switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */
case OS_STAT_PEND_OK:
pmsg = OSTCBCur->OSTCBMsg;
*perr = OS_ERR_NONE;
break;
case OS_STAT_PEND_ABORT:
pmsg = (void *)0;
*perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */
break;
case OS_STAT_PEND_TO:
default:
OS_EventTaskRemove(OSTCBCur, pevent);
pmsg = (void *)0;
*perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */
break;
}
OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */
#if (OS_EVENT_MULTI_EN > 0u)
OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
#endif
OSTCBCur->OSTCBMsg = (void *)0; /* Clear received message */
OS_EXIT_CRITICAL();
return (pmsg); /* Return received message */
}
/*$PAGE*/
/*
*********************************************************************************************************
* ABORT WAITING ON A MESSAGE MAILBOX
*
* Description: This function aborts & readies any tasks currently waiting on a mailbox. This function
* should be used to fault-abort the wait on the mailbox, rather than to normally signal
* the mailbox via OSMboxPost() or OSMboxPostOpt().
*
* Arguments : pevent is a pointer to the event control block associated with the desired mailbox.
*
* opt determines the type of ABORT performed:
* OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the
* mailbox
* OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the
* mailbox
*
* perr is a pointer to where an error message will be deposited. Possible error
* messages are:
*
* OS_ERR_NONE No tasks were waiting on the mailbox.
* OS_ERR_PEND_ABORT At least one task waiting on the mailbox was readied
* and informed of the aborted wait; check return value
* for the number of tasks whose wait on the mailbox
* was aborted.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mailbox.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
*
* Returns : == 0 if no tasks were waiting on the mailbox, or upon error.
* > 0 if one or more tasks waiting on the mailbox are now readied and informed.
*********************************************************************************************************
*/
#if OS_MBOX_PEND_ABORT_EN > 0u
INT8U OSMboxPendAbort (OS_EVENT *pevent,
INT8U opt,
INT8U *perr)
{
INT8U nbr_tasks;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*perr = OS_ERR_PEVENT_NULL;
return (0u);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
*perr = OS_ERR_EVENT_TYPE;
return (0u);
}
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0u) { /* See if any task waiting on mailbox? */
nbr_tasks = 0u;
switch (opt) {
case OS_PEND_OPT_BROADCAST: /* Do we need to abort ALL waiting tasks? */
while (pevent->OSEventGrp != 0u) { /* Yes, ready ALL tasks waiting on mailbox */
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT);
nbr_tasks++;
}
break;
case OS_PEND_OPT_NONE:
default: /* No, ready HPT waiting on mailbox */
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT);
nbr_tasks++;
break;
}
OS_EXIT_CRITICAL();
OS_Sched(); /* Find HPT ready to run */
*perr = OS_ERR_PEND_ABORT;
return (nbr_tasks);
}
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
return (0u); /* No tasks waiting on mailbox */
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* POST MESSAGE TO A MAILBOX
*
* Description: This function sends a message to a mailbox
*
* Arguments : pevent is a pointer to the event control block associated with the desired mailbox
*
* pmsg is a pointer to the message to send. You MUST NOT send a NULL pointer.
*
* Returns : OS_ERR_NONE The call was successful and the message was sent
* OS_ERR_MBOX_FULL If the mailbox already contains a message. You can can only send one
* message at a time and thus, the message MUST be consumed before you
* are allowed to send another one.
* OS_ERR_EVENT_TYPE If you are attempting to post to a non mailbox.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_POST_NULL_PTR If you are attempting to post a NULL pointer
*
* Note(s) : 1) HPT means Highest Priority Task
*********************************************************************************************************
*/
#if OS_MBOX_POST_EN > 0u
INT8U OSMboxPost (OS_EVENT *pevent,
void *pmsg)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (pmsg == (void *)0) { /* Make sure we are not posting a NULL pointer */
return (OS_ERR_POST_NULL_PTR);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0u) { /* See if any task pending on mailbox */
/* Ready HPT waiting on event */
(void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);
OS_EXIT_CRITICAL();
OS_Sched(); /* Find highest priority task ready to run */
return (OS_ERR_NONE);
}
if (pevent->OSEventPtr != (void *)0) { /* Make sure mailbox doesn't already have a msg */
OS_EXIT_CRITICAL();
return (OS_ERR_MBOX_FULL);
}
pevent->OSEventPtr = pmsg; /* Place message in mailbox */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* POST MESSAGE TO A MAILBOX
*
* Description: This function sends a message to a mailbox
*
* Arguments : pevent is a pointer to the event control block associated with the desired mailbox
*
* pmsg is a pointer to the message to send. You MUST NOT send a NULL pointer.
*
* opt determines the type of POST performed:
* OS_POST_OPT_NONE POST to a single waiting task
* (Identical to OSMboxPost())
* OS_POST_OPT_BROADCAST POST to ALL tasks that are waiting on the mailbox
*
* OS_POST_OPT_NO_SCHED Indicates that the scheduler will NOT be invoked
*
* Returns : OS_ERR_NONE The call was successful and the message was sent
* OS_ERR_MBOX_FULL If the mailbox already contains a message. You can can only send one
* message at a time and thus, the message MUST be consumed before you
* are allowed to send another one.
* OS_ERR_EVENT_TYPE If you are attempting to post to a non mailbox.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_POST_NULL_PTR If you are attempting to post a NULL pointer
*
* Note(s) : 1) HPT means Highest Priority Task
*
* Warning : Interrupts can be disabled for a long time if you do a 'broadcast'. In fact, the
* interrupt disable time is proportional to the number of tasks waiting on the mailbox.
*********************************************************************************************************
*/
#if OS_MBOX_POST_OPT_EN > 0u
INT8U OSMboxPostOpt (OS_EVENT *pevent,
void *pmsg,
INT8U opt)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (pmsg == (void *)0) { /* Make sure we are not posting a NULL pointer */
return (OS_ERR_POST_NULL_PTR);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0u) { /* See if any task pending on mailbox */
if ((opt & OS_POST_OPT_BROADCAST) != 0x00u) { /* Do we need to post msg to ALL waiting tasks ? */
while (pevent->OSEventGrp != 0u) { /* Yes, Post to ALL tasks waiting on mailbox */
(void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);
}
} else { /* No, Post to HPT waiting on mbox */
(void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);
}
OS_EXIT_CRITICAL();
if ((opt & OS_POST_OPT_NO_SCHED) == 0u) { /* See if scheduler needs to be invoked */
OS_Sched(); /* Find HPT ready to run */
}
return (OS_ERR_NONE);
}
if (pevent->OSEventPtr != (void *)0) { /* Make sure mailbox doesn't already have a msg */
OS_EXIT_CRITICAL();
return (OS_ERR_MBOX_FULL);
}
pevent->OSEventPtr = pmsg; /* Place message in mailbox */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* QUERY A MESSAGE MAILBOX
*
* Description: This function obtains information about a message mailbox.
*
* Arguments : pevent is a pointer to the event control block associated with the desired mailbox
*
* p_mbox_data is a pointer to a structure that will contain information about the message
* mailbox.
*
* Returns : OS_ERR_NONE The call was successful and the message was sent
* OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non mailbox.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_PDATA_NULL If 'p_mbox_data' is a NULL pointer
*********************************************************************************************************
*/
#if OS_MBOX_QUERY_EN > 0u
INT8U OSMboxQuery (OS_EVENT *pevent,
OS_MBOX_DATA *p_mbox_data)
{
INT8U i;
OS_PRIO *psrc;
OS_PRIO *pdest;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (p_mbox_data == (OS_MBOX_DATA *)0) { /* Validate 'p_mbox_data' */
return (OS_ERR_PDATA_NULL);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
OS_ENTER_CRITICAL();
p_mbox_data->OSEventGrp = pevent->OSEventGrp; /* Copy message mailbox wait list */
psrc = &pevent->OSEventTbl[0];
pdest = &p_mbox_data->OSEventTbl[0];
for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {
*pdest++ = *psrc++;
}
p_mbox_data->OSMsg = pevent->OSEventPtr; /* Get message from mailbox */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
#endif /* OS_MBOX_QUERY_EN */
#endif /* OS_MBOX_EN */

456
UCOSII/CORE/os_mem.c Normal file
View File

@@ -0,0 +1,456 @@
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
* MEMORY MANAGEMENT
*
* (c) Copyright 1992-2009, Micrium, Weston, FL
* All Rights Reserved
*
* File : OS_MEM.C
* By : Jean J. Labrosse
* Version : V2.91
*
* LICENSING TERMS:
* ---------------
* uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
* If you plan on using uC/OS-II in a commercial product you need to contact Micri<72>m to properly license
* its use in your product. We provide ALL the source code for your convenience and to help you experience
* uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a
* licensing fee.
*********************************************************************************************************
*/
#ifndef OS_MASTER_FILE
#include <ucos_ii.h>
#endif
#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
/*
*********************************************************************************************************
* CREATE A MEMORY PARTITION
*
* Description : Create a fixed-sized memory partition that will be managed by uC/OS-II.
*
* Arguments : addr is the starting address of the memory partition
*
* nblks is the number of memory blocks to create from the partition.
*
* blksize is the size (in bytes) of each block in the memory partition.
*
* perr is a pointer to a variable containing an error message which will be set by
* this function to either:
*
* OS_ERR_NONE if the memory partition has been created correctly.
* OS_ERR_MEM_INVALID_ADDR if you are specifying an invalid address for the memory
* storage of the partition or, the block does not align
* on a pointer boundary
* OS_ERR_MEM_INVALID_PART no free partitions available
* OS_ERR_MEM_INVALID_BLKS user specified an invalid number of blocks (must be >= 2)
* OS_ERR_MEM_INVALID_SIZE user specified an invalid block size
* - must be greater than the size of a pointer
* - must be able to hold an integral number of pointers
* Returns : != (OS_MEM *)0 is the partition was created
* == (OS_MEM *)0 if the partition was not created because of invalid arguments or, no
* free partition is available.
*********************************************************************************************************
*/
OS_MEM *OSMemCreate (void *addr,
INT32U nblks,
INT32U blksize,
INT8U *perr)
{
OS_MEM *pmem;
INT8U *pblk;
void **plink;
INT32U loops;
INT32U i;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
if (OSSafetyCriticalStartFlag == OS_TRUE) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (addr == (void *)0) { /* Must pass a valid address for the memory part.*/
*perr = OS_ERR_MEM_INVALID_ADDR;
return ((OS_MEM *)0);
}
if (((INT32U)addr & (sizeof(void *) - 1u)) != 0u){ /* Must be pointer size aligned */
*perr = OS_ERR_MEM_INVALID_ADDR;
return ((OS_MEM *)0);
}
if (nblks < 2u) { /* Must have at least 2 blocks per partition */
*perr = OS_ERR_MEM_INVALID_BLKS;
return ((OS_MEM *)0);
}
if (blksize < sizeof(void *)) { /* Must contain space for at least a pointer */
*perr = OS_ERR_MEM_INVALID_SIZE;
return ((OS_MEM *)0);
}
#endif
OS_ENTER_CRITICAL();
pmem = OSMemFreeList; /* Get next free memory partition */
if (OSMemFreeList != (OS_MEM *)0) { /* See if pool of free partitions was empty */
OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;
}
OS_EXIT_CRITICAL();
if (pmem == (OS_MEM *)0) { /* See if we have a memory partition */
*perr = OS_ERR_MEM_INVALID_PART;
return ((OS_MEM *)0);
}
plink = (void **)addr; /* Create linked list of free memory blocks */
pblk = (INT8U *)addr;
loops = nblks - 1u;
for (i = 0u; i < loops; i++) {
pblk += blksize; /* Point to the FOLLOWING block */
*plink = (void *)pblk; /* Save pointer to NEXT block in CURRENT block */
plink = (void **)pblk; /* Position to NEXT block */
}
*plink = (void *)0; /* Last memory block points to NULL */
pmem->OSMemAddr = addr; /* Store start address of memory partition */
pmem->OSMemFreeList = addr; /* Initialize pointer to pool of free blocks */
pmem->OSMemNFree = nblks; /* Store number of free blocks in MCB */
pmem->OSMemNBlks = nblks;
pmem->OSMemBlkSize = blksize; /* Store block size of each memory blocks */
*perr = OS_ERR_NONE;
return (pmem);
}
/*$PAGE*/
/*
*********************************************************************************************************
* GET A MEMORY BLOCK
*
* Description : Get a memory block from a partition
*
* Arguments : pmem is a pointer to the memory partition control block
*
* perr is a pointer to a variable containing an error message which will be set by this
* function to either:
*
* OS_ERR_NONE if the memory partition has been created correctly.
* OS_ERR_MEM_NO_FREE_BLKS if there are no more free memory blocks to allocate to caller
* OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem'
*
* Returns : A pointer to a memory block if no error is detected
* A pointer to NULL if an error is detected
*********************************************************************************************************
*/
void *OSMemGet (OS_MEM *pmem,
INT8U *perr)
{
void *pblk;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pmem == (OS_MEM *)0) { /* Must point to a valid memory partition */
*perr = OS_ERR_MEM_INVALID_PMEM;
return ((void *)0);
}
#endif
OS_ENTER_CRITICAL();
if (pmem->OSMemNFree > 0u) { /* See if there are any free memory blocks */
pblk = pmem->OSMemFreeList; /* Yes, point to next free memory block */
pmem->OSMemFreeList = *(void **)pblk; /* Adjust pointer to new free list */
pmem->OSMemNFree--; /* One less memory block in this partition */
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE; /* No error */
return (pblk); /* Return memory block to caller */
}
OS_EXIT_CRITICAL();
*perr = OS_ERR_MEM_NO_FREE_BLKS; /* No, Notify caller of empty memory partition */
return ((void *)0); /* Return NULL pointer to caller */
}
/*$PAGE*/
/*
*********************************************************************************************************
* GET THE NAME OF A MEMORY PARTITION
*
* Description: This function is used to obtain the name assigned to a memory partition.
*
* Arguments : pmem is a pointer to the memory partition
*
* pname is a pointer to a pointer to an ASCII string that will receive the name of the memory partition.
*
* perr is a pointer to an error code that can contain one of the following values:
*
* OS_ERR_NONE if the name was copied to 'pname'
* OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem'
* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname'
* OS_ERR_NAME_GET_ISR You called this function from an ISR
*
* Returns : The length of the string or 0 if 'pmem' is a NULL pointer.
*********************************************************************************************************
*/
#if OS_MEM_NAME_EN > 0u
INT8U OSMemNameGet (OS_MEM *pmem,
INT8U **pname,
INT8U *perr)
{
INT8U len;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pmem == (OS_MEM *)0) { /* Is 'pmem' a NULL pointer? */
*perr = OS_ERR_MEM_INVALID_PMEM;
return (0u);
}
if (pname == (INT8U **)0) { /* Is 'pname' a NULL pointer? */
*perr = OS_ERR_PNAME_NULL;
return (0u);
}
#endif
if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
*perr = OS_ERR_NAME_GET_ISR;
return (0u);
}
OS_ENTER_CRITICAL();
*pname = pmem->OSMemName;
len = OS_StrLen(*pname);
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
return (len);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* ASSIGN A NAME TO A MEMORY PARTITION
*
* Description: This function assigns a name to a memory partition.
*
* Arguments : pmem is a pointer to the memory partition
*
* pname is a pointer to an ASCII string that contains the name of the memory partition.
*
* perr is a pointer to an error code that can contain one of the following values:
*
* OS_ERR_NONE if the name was copied to 'pname'
* OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem'
* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname'
* OS_ERR_MEM_NAME_TOO_LONG if the name doesn't fit in the storage area
* OS_ERR_NAME_SET_ISR if you called this function from an ISR
*
* Returns : None
*********************************************************************************************************
*/
#if OS_MEM_NAME_EN > 0u
void OSMemNameSet (OS_MEM *pmem,
INT8U *pname,
INT8U *perr)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pmem == (OS_MEM *)0) { /* Is 'pmem' a NULL pointer? */
*perr = OS_ERR_MEM_INVALID_PMEM;
return;
}
if (pname == (INT8U *)0) { /* Is 'pname' a NULL pointer? */
*perr = OS_ERR_PNAME_NULL;
return;
}
#endif
if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
*perr = OS_ERR_NAME_SET_ISR;
return;
}
OS_ENTER_CRITICAL();
pmem->OSMemName = pname;
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* RELEASE A MEMORY BLOCK
*
* Description : Returns a memory block to a partition
*
* Arguments : pmem is a pointer to the memory partition control block
*
* pblk is a pointer to the memory block being released.
*
* Returns : OS_ERR_NONE if the memory block was inserted into the partition
* OS_ERR_MEM_FULL if you are returning a memory block to an already FULL memory
* partition (You freed more blocks than you allocated!)
* OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem'
* OS_ERR_MEM_INVALID_PBLK if you passed a NULL pointer for the block to release.
*********************************************************************************************************
*/
INT8U OSMemPut (OS_MEM *pmem,
void *pblk)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pmem == (OS_MEM *)0) { /* Must point to a valid memory partition */
return (OS_ERR_MEM_INVALID_PMEM);
}
if (pblk == (void *)0) { /* Must release a valid block */
return (OS_ERR_MEM_INVALID_PBLK);
}
#endif
OS_ENTER_CRITICAL();
if (pmem->OSMemNFree >= pmem->OSMemNBlks) { /* Make sure all blocks not already returned */
OS_EXIT_CRITICAL();
return (OS_ERR_MEM_FULL);
}
*(void **)pblk = pmem->OSMemFreeList; /* Insert released block into free block list */
pmem->OSMemFreeList = pblk;
pmem->OSMemNFree++; /* One more memory block in this partition */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE); /* Notify caller that memory block was released */
}
/*$PAGE*/
/*
*********************************************************************************************************
* QUERY MEMORY PARTITION
*
* Description : This function is used to determine the number of free memory blocks and the number of
* used memory blocks from a memory partition.
*
* Arguments : pmem is a pointer to the memory partition control block
*
* p_mem_data is a pointer to a structure that will contain information about the memory
* partition.
*
* Returns : OS_ERR_NONE if no errors were found.
* OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem'
* OS_ERR_MEM_INVALID_PDATA if you passed a NULL pointer to the data recipient.
*********************************************************************************************************
*/
#if OS_MEM_QUERY_EN > 0u
INT8U OSMemQuery (OS_MEM *pmem,
OS_MEM_DATA *p_mem_data)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pmem == (OS_MEM *)0) { /* Must point to a valid memory partition */
return (OS_ERR_MEM_INVALID_PMEM);
}
if (p_mem_data == (OS_MEM_DATA *)0) { /* Must release a valid storage area for the data */
return (OS_ERR_MEM_INVALID_PDATA);
}
#endif
OS_ENTER_CRITICAL();
p_mem_data->OSAddr = pmem->OSMemAddr;
p_mem_data->OSFreeList = pmem->OSMemFreeList;
p_mem_data->OSBlkSize = pmem->OSMemBlkSize;
p_mem_data->OSNBlks = pmem->OSMemNBlks;
p_mem_data->OSNFree = pmem->OSMemNFree;
OS_EXIT_CRITICAL();
p_mem_data->OSNUsed = p_mem_data->OSNBlks - p_mem_data->OSNFree;
return (OS_ERR_NONE);
}
#endif /* OS_MEM_QUERY_EN */
/*$PAGE*/
/*
*********************************************************************************************************
* INITIALIZE MEMORY PARTITION MANAGER
*
* Description : This function is called by uC/OS-II to initialize the memory partition manager. Your
* application MUST NOT call this function.
*
* Arguments : none
*
* Returns : none
*
* Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it.
*********************************************************************************************************
*/
void OS_MemInit (void)
{
#if OS_MAX_MEM_PART == 1u
OS_MemClr((INT8U *)&OSMemTbl[0], sizeof(OSMemTbl)); /* Clear the memory partition table */
OSMemFreeList = (OS_MEM *)&OSMemTbl[0]; /* Point to beginning of free list */
#if OS_MEM_NAME_EN > 0u
OSMemFreeList->OSMemName = (INT8U *)"?"; /* Unknown name */
#endif
#endif
#if OS_MAX_MEM_PART >= 2u
OS_MEM *pmem;
INT16U i;
OS_MemClr((INT8U *)&OSMemTbl[0], sizeof(OSMemTbl)); /* Clear the memory partition table */
for (i = 0u; i < (OS_MAX_MEM_PART - 1u); i++) { /* Init. list of free memory partitions */
pmem = &OSMemTbl[i]; /* Point to memory control block (MCB) */
pmem->OSMemFreeList = (void *)&OSMemTbl[i + 1u]; /* Chain list of free partitions */
#if OS_MEM_NAME_EN > 0u
pmem->OSMemName = (INT8U *)(void *)"?";
#endif
}
pmem = &OSMemTbl[i];
pmem->OSMemFreeList = (void *)0; /* Initialize last node */
#if OS_MEM_NAME_EN > 0u
pmem->OSMemName = (INT8U *)(void *)"?";
#endif
OSMemFreeList = &OSMemTbl[0]; /* Point to beginning of free list */
#endif
}
#endif /* OS_MEM_EN */

735
UCOSII/CORE/os_mutex.c Normal file
View File

@@ -0,0 +1,735 @@
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
* MUTUAL EXCLUSION SEMAPHORE MANAGEMENT
*
* (c) Copyright 1992-2009, Micrium, Weston, FL
* All Rights Reserved
*
* File : OS_MUTEX.C
* By : Jean J. Labrosse
* Version : V2.91
*
* LICENSING TERMS:
* ---------------
* uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
* If you plan on using uC/OS-II in a commercial product you need to contact Micri<72>m to properly license
* its use in your product. We provide ALL the source code for your convenience and to help you experience
* uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a
* licensing fee.
*********************************************************************************************************
*/
#ifndef OS_MASTER_FILE
#include <ucos_ii.h>
#endif
#if OS_MUTEX_EN > 0u
/*
*********************************************************************************************************
* LOCAL CONSTANTS
*********************************************************************************************************
*/
#define OS_MUTEX_KEEP_LOWER_8 ((INT16U)0x00FFu)
#define OS_MUTEX_KEEP_UPPER_8 ((INT16U)0xFF00u)
#define OS_MUTEX_AVAILABLE ((INT16U)0x00FFu)
/*
*********************************************************************************************************
* LOCAL CONSTANTS
*********************************************************************************************************
*/
static void OSMutex_RdyAtPrio(OS_TCB *ptcb, INT8U prio);
/*$PAGE*/
/*
*********************************************************************************************************
* ACCEPT MUTUAL EXCLUSION SEMAPHORE
*
* Description: This function checks the mutual exclusion semaphore to see if a resource is available.
* Unlike OSMutexPend(), OSMutexAccept() does not suspend the calling task if the resource is
* not available or the event did not occur.
*
* Arguments : pevent is a pointer to the event control block
*
* perr is a pointer to an error code which will be returned to your application:
* OS_ERR_NONE if the call was successful.
* OS_ERR_EVENT_TYPE if 'pevent' is not a pointer to a mutex
* OS_ERR_PEVENT_NULL 'pevent' is a NULL pointer
* OS_ERR_PEND_ISR if you called this function from an ISR
* OS_ERR_PIP_LOWER If the priority of the task that owns the Mutex is
* HIGHER (i.e. a lower number) than the PIP. This error
* indicates that you did not set the PIP higher (lower
* number) than ALL the tasks that compete for the Mutex.
* Unfortunately, this is something that could not be
* detected when the Mutex is created because we don't know
* what tasks will be using the Mutex.
*
* Returns : == OS_TRUE if the resource is available, the mutual exclusion semaphore is acquired
* == OS_FALSE a) if the resource is not available
* b) you didn't pass a pointer to a mutual exclusion semaphore
* c) you called this function from an ISR
*
* Warning(s) : This function CANNOT be called from an ISR because mutual exclusion semaphores are
* intended to be used by tasks only.
*********************************************************************************************************
*/
#if OS_MUTEX_ACCEPT_EN > 0u
BOOLEAN OSMutexAccept (OS_EVENT *pevent,
INT8U *perr)
{
INT8U pip; /* Priority Inheritance Priority (PIP) */
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*perr = OS_ERR_PEVENT_NULL;
return (OS_FALSE);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */
*perr = OS_ERR_EVENT_TYPE;
return (OS_FALSE);
}
if (OSIntNesting > 0u) { /* Make sure it's not called from an ISR */
*perr = OS_ERR_PEND_ISR;
return (OS_FALSE);
}
OS_ENTER_CRITICAL(); /* Get value (0 or 1) of Mutex */
pip = (INT8U)(pevent->OSEventCnt >> 8u); /* Get PIP from mutex */
if ((pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) {
pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8; /* Mask off LSByte (Acquire Mutex) */
pevent->OSEventCnt |= OSTCBCur->OSTCBPrio; /* Save current task priority in LSByte */
pevent->OSEventPtr = (void *)OSTCBCur; /* Link TCB of task owning Mutex */
if (OSTCBCur->OSTCBPrio <= pip) { /* PIP 'must' have a SMALLER prio ... */
OS_EXIT_CRITICAL(); /* ... than current task! */
*perr = OS_ERR_PIP_LOWER;
} else {
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
}
return (OS_TRUE);
}
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
return (OS_FALSE);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* CREATE A MUTUAL EXCLUSION SEMAPHORE
*
* Description: This function creates a mutual exclusion semaphore.
*
* Arguments : prio is the priority to use when accessing the mutual exclusion semaphore. In
* other words, when the semaphore is acquired and a higher priority task
* attempts to obtain the semaphore then the priority of the task owning the
* semaphore is raised to this priority. It is assumed that you will specify
* a priority that is LOWER in value than ANY of the tasks competing for the
* mutex.
*
* perr is a pointer to an error code which will be returned to your application:
* OS_ERR_NONE if the call was successful.
* OS_ERR_CREATE_ISR if you attempted to create a MUTEX from an ISR
* OS_ERR_PRIO_EXIST if a task at the priority inheritance priority
* already exist.
* OS_ERR_PEVENT_NULL No more event control blocks available.
* OS_ERR_PRIO_INVALID if the priority you specify is higher that the
* maximum allowed (i.e. > OS_LOWEST_PRIO)
*
* Returns : != (void *)0 is a pointer to the event control clock (OS_EVENT) associated with the
* created mutex.
* == (void *)0 if an error is detected.
*
* Note(s) : 1) The LEAST significant 8 bits of '.OSEventCnt' are used to hold the priority number
* of the task owning the mutex or 0xFF if no task owns the mutex.
*
* 2) The MOST significant 8 bits of '.OSEventCnt' are used to hold the priority number
* to use to reduce priority inversion.
*********************************************************************************************************
*/
OS_EVENT *OSMutexCreate (INT8U prio,
INT8U *perr)
{
OS_EVENT *pevent;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
if (OSSafetyCriticalStartFlag == OS_TRUE) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (prio >= OS_LOWEST_PRIO) { /* Validate PIP */
*perr = OS_ERR_PRIO_INVALID;
return ((OS_EVENT *)0);
}
#endif
if (OSIntNesting > 0u) { /* See if called from ISR ... */
*perr = OS_ERR_CREATE_ISR; /* ... can't CREATE mutex from an ISR */
return ((OS_EVENT *)0);
}
OS_ENTER_CRITICAL();
if (OSTCBPrioTbl[prio] != (OS_TCB *)0) { /* Mutex priority must not already exist */
OS_EXIT_CRITICAL(); /* Task already exist at priority ... */
*perr = OS_ERR_PRIO_EXIST; /* ... inheritance priority */
return ((OS_EVENT *)0);
}
OSTCBPrioTbl[prio] = OS_TCB_RESERVED; /* Reserve the table entry */
pevent = OSEventFreeList; /* Get next free event control block */
if (pevent == (OS_EVENT *)0) { /* See if an ECB was available */
OSTCBPrioTbl[prio] = (OS_TCB *)0; /* No, Release the table entry */
OS_EXIT_CRITICAL();
*perr = OS_ERR_PEVENT_NULL; /* No more event control blocks */
return (pevent);
}
OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; /* Adjust the free list */
OS_EXIT_CRITICAL();
pevent->OSEventType = OS_EVENT_TYPE_MUTEX;
pevent->OSEventCnt = (INT16U)((INT16U)prio << 8u) | OS_MUTEX_AVAILABLE; /* Resource is avail. */
pevent->OSEventPtr = (void *)0; /* No task owning the mutex */
#if OS_EVENT_NAME_EN > 0u
pevent->OSEventName = (INT8U *)(void *)"?";
#endif
OS_EventWaitListInit(pevent);
*perr = OS_ERR_NONE;
return (pevent);
}
/*$PAGE*/
/*
*********************************************************************************************************
* DELETE A MUTEX
*
* Description: This function deletes a mutual exclusion semaphore and readies all tasks pending on the it.
*
* Arguments : pevent is a pointer to the event control block associated with the desired mutex.
*
* opt determines delete options as follows:
* opt == OS_DEL_NO_PEND Delete mutex ONLY if no task pending
* opt == OS_DEL_ALWAYS Deletes the mutex even if tasks are waiting.
* In this case, all the tasks pending will be readied.
*
* perr is a pointer to an error code that can contain one of the following values:
* OS_ERR_NONE The call was successful and the mutex was deleted
* OS_ERR_DEL_ISR If you attempted to delete the MUTEX from an ISR
* OS_ERR_INVALID_OPT An invalid option was specified
* OS_ERR_TASK_WAITING One or more tasks were waiting on the mutex
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mutex
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
*
* Returns : pevent upon error
* (OS_EVENT *)0 if the mutex was successfully deleted.
*
* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of
* the mutex MUST check the return code of OSMutexPend().
*
* 2) This call can potentially disable interrupts for a long time. The interrupt disable
* time is directly proportional to the number of tasks waiting on the mutex.
*
* 3) Because ALL tasks pending on the mutex will be readied, you MUST be careful because the
* resource(s) will no longer be guarded by the mutex.
*
* 4) IMPORTANT: In the 'OS_DEL_ALWAYS' case, we assume that the owner of the Mutex (if there
* is one) is ready-to-run and is thus NOT pending on another kernel object or
* has delayed itself. In other words, if a task owns the mutex being deleted,
* that task will be made ready-to-run at its original priority.
*********************************************************************************************************
*/
#if OS_MUTEX_DEL_EN > 0u
OS_EVENT *OSMutexDel (OS_EVENT *pevent,
INT8U opt,
INT8U *perr)
{
BOOLEAN tasks_waiting;
OS_EVENT *pevent_return;
INT8U pip; /* Priority inheritance priority */
INT8U prio;
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*perr = OS_ERR_PEVENT_NULL;
return (pevent);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */
*perr = OS_ERR_EVENT_TYPE;
return (pevent);
}
if (OSIntNesting > 0u) { /* See if called from ISR ... */
*perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
return (pevent);
}
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on mutex */
tasks_waiting = OS_TRUE; /* Yes */
} else {
tasks_waiting = OS_FALSE; /* No */
}
switch (opt) {
case OS_DEL_NO_PEND: /* DELETE MUTEX ONLY IF NO TASK WAITING --- */
if (tasks_waiting == OS_FALSE) {
#if OS_EVENT_NAME_EN > 0u
pevent->OSEventName = (INT8U *)(void *)"?";
#endif
pip = (INT8U)(pevent->OSEventCnt >> 8u);
OSTCBPrioTbl[pip] = (OS_TCB *)0; /* Free up the PIP */
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
pevent->OSEventCnt = 0u;
OSEventFreeList = pevent;
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
pevent_return = (OS_EVENT *)0; /* Mutex has been deleted */
} else {
OS_EXIT_CRITICAL();
*perr = OS_ERR_TASK_WAITING;
pevent_return = pevent;
}
break;
case OS_DEL_ALWAYS: /* ALWAYS DELETE THE MUTEX ---------------- */
pip = (INT8U)(pevent->OSEventCnt >> 8u); /* Get PIP of mutex */
prio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* Get owner's original prio */
ptcb = (OS_TCB *)pevent->OSEventPtr;
if (ptcb != (OS_TCB *)0) { /* See if any task owns the mutex */
if (ptcb->OSTCBPrio == pip) { /* See if original prio was changed */
OSMutex_RdyAtPrio(ptcb, prio); /* Yes, Restore the task's original prio */
}
}
while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for mutex */
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX, OS_STAT_PEND_OK);
}
#if OS_EVENT_NAME_EN > 0u
pevent->OSEventName = (INT8U *)(void *)"?";
#endif
pip = (INT8U)(pevent->OSEventCnt >> 8u);
OSTCBPrioTbl[pip] = (OS_TCB *)0; /* Free up the PIP */
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
pevent->OSEventCnt = 0u;
OSEventFreeList = pevent; /* Get next free event control block */
OS_EXIT_CRITICAL();
if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */
OS_Sched(); /* Find highest priority task ready to run */
}
*perr = OS_ERR_NONE;
pevent_return = (OS_EVENT *)0; /* Mutex has been deleted */
break;
default:
OS_EXIT_CRITICAL();
*perr = OS_ERR_INVALID_OPT;
pevent_return = pevent;
break;
}
return (pevent_return);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* PEND ON MUTUAL EXCLUSION SEMAPHORE
*
* Description: This function waits for a mutual exclusion semaphore.
*
* Arguments : pevent is a pointer to the event control block associated with the desired
* mutex.
*
* timeout is an optional timeout period (in clock ticks). If non-zero, your task will
* wait for the resource up to the amount of time specified by this argument.
* If you specify 0, however, your task will wait forever at the specified
* mutex or, until the resource becomes available.
*
* perr is a pointer to where an error message will be deposited. Possible error
* messages are:
* OS_ERR_NONE The call was successful and your task owns the mutex
* OS_ERR_TIMEOUT The mutex was not available within the specified 'timeout'.
* OS_ERR_PEND_ABORT The wait on the mutex was aborted.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mutex
* OS_ERR_PEVENT_NULL 'pevent' is a NULL pointer
* OS_ERR_PEND_ISR If you called this function from an ISR and the result
* would lead to a suspension.
* OS_ERR_PIP_LOWER If the priority of the task that owns the Mutex is
* HIGHER (i.e. a lower number) than the PIP. This error
* indicates that you did not set the PIP higher (lower
* number) than ALL the tasks that compete for the Mutex.
* Unfortunately, this is something that could not be
* detected when the Mutex is created because we don't know
* what tasks will be using the Mutex.
* OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked
*
* Returns : none
*
* Note(s) : 1) The task that owns the Mutex MUST NOT pend on any other event while it owns the mutex.
*
* 2) You MUST NOT change the priority of the task that owns the mutex
*********************************************************************************************************
*/
void OSMutexPend (OS_EVENT *pevent,
INT32U timeout,
INT8U *perr)
{
INT8U pip; /* Priority Inheritance Priority (PIP) */
INT8U mprio; /* Mutex owner priority */
BOOLEAN rdy; /* Flag indicating task was ready */
OS_TCB *ptcb;
OS_EVENT *pevent2;
INT8U y;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*perr = OS_ERR_PEVENT_NULL;
return;
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */
*perr = OS_ERR_EVENT_TYPE;
return;
}
if (OSIntNesting > 0u) { /* See if called from ISR ... */
*perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return;
}
if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */
*perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */
return;
}
/*$PAGE*/
OS_ENTER_CRITICAL();
pip = (INT8U)(pevent->OSEventCnt >> 8u); /* Get PIP from mutex */
/* Is Mutex available? */
if ((INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) {
pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8; /* Yes, Acquire the resource */
pevent->OSEventCnt |= OSTCBCur->OSTCBPrio; /* Save priority of owning task */
pevent->OSEventPtr = (void *)OSTCBCur; /* Point to owning task's OS_TCB */
if (OSTCBCur->OSTCBPrio <= pip) { /* PIP 'must' have a SMALLER prio ... */
OS_EXIT_CRITICAL(); /* ... than current task! */
*perr = OS_ERR_PIP_LOWER;
} else {
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
}
return;
}
mprio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* No, Get priority of mutex owner */
ptcb = (OS_TCB *)(pevent->OSEventPtr); /* Point to TCB of mutex owner */
if (ptcb->OSTCBPrio > pip) { /* Need to promote prio of owner?*/
if (mprio > OSTCBCur->OSTCBPrio) {
y = ptcb->OSTCBY;
if ((OSRdyTbl[y] & ptcb->OSTCBBitX) != 0u) { /* See if mutex owner is ready */
OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX; /* Yes, Remove owner from Rdy ...*/
if (OSRdyTbl[y] == 0u) { /* ... list at current prio */
OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
}
rdy = OS_TRUE;
} else {
pevent2 = ptcb->OSTCBEventPtr;
if (pevent2 != (OS_EVENT *)0) { /* Remove from event wait list */
y = ptcb->OSTCBY;
pevent2->OSEventTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX;
if (pevent2->OSEventTbl[y] == 0u) {
pevent2->OSEventGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
}
}
rdy = OS_FALSE; /* No */
}
ptcb->OSTCBPrio = pip; /* Change owner task prio to PIP */
#if OS_LOWEST_PRIO <= 63u
ptcb->OSTCBY = (INT8U)( ptcb->OSTCBPrio >> 3u);
ptcb->OSTCBX = (INT8U)( ptcb->OSTCBPrio & 0x07u);
#else
ptcb->OSTCBY = (INT8U)((INT8U)(ptcb->OSTCBPrio >> 4u) & 0xFFu);
ptcb->OSTCBX = (INT8U)( ptcb->OSTCBPrio & 0x0Fu);
#endif
ptcb->OSTCBBitY = (OS_PRIO)(1uL << ptcb->OSTCBY);
ptcb->OSTCBBitX = (OS_PRIO)(1uL << ptcb->OSTCBX);
if (rdy == OS_TRUE) { /* If task was ready at owner's priority ...*/
OSRdyGrp |= ptcb->OSTCBBitY; /* ... make it ready at new priority. */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
} else {
pevent2 = ptcb->OSTCBEventPtr;
if (pevent2 != (OS_EVENT *)0) { /* Add to event wait list */
pevent2->OSEventGrp |= ptcb->OSTCBBitY;
pevent2->OSEventTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
}
}
OSTCBPrioTbl[pip] = ptcb;
}
}
OSTCBCur->OSTCBStat |= OS_STAT_MUTEX; /* Mutex not available, pend current task */
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;
OSTCBCur->OSTCBDly = timeout; /* Store timeout in current task's TCB */
OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find next highest priority task ready */
OS_ENTER_CRITICAL();
switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */
case OS_STAT_PEND_OK:
*perr = OS_ERR_NONE;
break;
case OS_STAT_PEND_ABORT:
*perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted getting mutex */
break;
case OS_STAT_PEND_TO:
default:
OS_EventTaskRemove(OSTCBCur, pevent);
*perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get mutex within TO */
break;
}
OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */
#if (OS_EVENT_MULTI_EN > 0u)
OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
#endif
OS_EXIT_CRITICAL();
}
/*$PAGE*/
/*
*********************************************************************************************************
* POST TO A MUTUAL EXCLUSION SEMAPHORE
*
* Description: This function signals a mutual exclusion semaphore
*
* Arguments : pevent is a pointer to the event control block associated with the desired
* mutex.
*
* Returns : OS_ERR_NONE The call was successful and the mutex was signaled.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mutex
* OS_ERR_PEVENT_NULL 'pevent' is a NULL pointer
* OS_ERR_POST_ISR Attempted to post from an ISR (not valid for MUTEXes)
* OS_ERR_NOT_MUTEX_OWNER The task that did the post is NOT the owner of the MUTEX.
* OS_ERR_PIP_LOWER If the priority of the new task that owns the Mutex is
* HIGHER (i.e. a lower number) than the PIP. This error
* indicates that you did not set the PIP higher (lower
* number) than ALL the tasks that compete for the Mutex.
* Unfortunately, this is something that could not be
* detected when the Mutex is created because we don't know
* what tasks will be using the Mutex.
*********************************************************************************************************
*/
INT8U OSMutexPost (OS_EVENT *pevent)
{
INT8U pip; /* Priority inheritance priority */
INT8U prio;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
if (OSIntNesting > 0u) { /* See if called from ISR ... */
return (OS_ERR_POST_ISR); /* ... can't POST mutex from an ISR */
}
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
OS_ENTER_CRITICAL();
pip = (INT8U)(pevent->OSEventCnt >> 8u); /* Get priority inheritance priority of mutex */
prio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* Get owner's original priority */
if (OSTCBCur != (OS_TCB *)pevent->OSEventPtr) { /* See if posting task owns the MUTEX */
OS_EXIT_CRITICAL();
return (OS_ERR_NOT_MUTEX_OWNER);
}
if (OSTCBCur->OSTCBPrio == pip) { /* Did we have to raise current task's priority? */
OSMutex_RdyAtPrio(OSTCBCur, prio); /* Restore the task's original priority */
}
OSTCBPrioTbl[pip] = OS_TCB_RESERVED; /* Reserve table entry */
if (pevent->OSEventGrp != 0u) { /* Any task waiting for the mutex? */
/* Yes, Make HPT waiting for mutex ready */
prio = OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX, OS_STAT_PEND_OK);
pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8; /* Save priority of mutex's new owner */
pevent->OSEventCnt |= prio;
pevent->OSEventPtr = OSTCBPrioTbl[prio]; /* Link to new mutex owner's OS_TCB */
if (prio <= pip) { /* PIP 'must' have a SMALLER prio ... */
OS_EXIT_CRITICAL(); /* ... than current task! */
OS_Sched(); /* Find highest priority task ready to run */
return (OS_ERR_PIP_LOWER);
} else {
OS_EXIT_CRITICAL();
OS_Sched(); /* Find highest priority task ready to run */
return (OS_ERR_NONE);
}
}
pevent->OSEventCnt |= OS_MUTEX_AVAILABLE; /* No, Mutex is now available */
pevent->OSEventPtr = (void *)0;
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
/*$PAGE*/
/*
*********************************************************************************************************
* QUERY A MUTUAL EXCLUSION SEMAPHORE
*
* Description: This function obtains information about a mutex
*
* Arguments : pevent is a pointer to the event control block associated with the desired mutex
*
* p_mutex_data is a pointer to a structure that will contain information about the mutex
*
* Returns : OS_ERR_NONE The call was successful and the message was sent
* OS_ERR_QUERY_ISR If you called this function from an ISR
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_PDATA_NULL If 'p_mutex_data' is a NULL pointer
* OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non mutex.
*********************************************************************************************************
*/
#if OS_MUTEX_QUERY_EN > 0u
INT8U OSMutexQuery (OS_EVENT *pevent,
OS_MUTEX_DATA *p_mutex_data)
{
INT8U i;
OS_PRIO *psrc;
OS_PRIO *pdest;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
if (OSIntNesting > 0u) { /* See if called from ISR ... */
return (OS_ERR_QUERY_ISR); /* ... can't QUERY mutex from an ISR */
}
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (p_mutex_data == (OS_MUTEX_DATA *)0) { /* Validate 'p_mutex_data' */
return (OS_ERR_PDATA_NULL);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
OS_ENTER_CRITICAL();
p_mutex_data->OSMutexPIP = (INT8U)(pevent->OSEventCnt >> 8u);
p_mutex_data->OSOwnerPrio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);
if (p_mutex_data->OSOwnerPrio == 0xFFu) {
p_mutex_data->OSValue = OS_TRUE;
} else {
p_mutex_data->OSValue = OS_FALSE;
}
p_mutex_data->OSEventGrp = pevent->OSEventGrp; /* Copy wait list */
psrc = &pevent->OSEventTbl[0];
pdest = &p_mutex_data->OSEventTbl[0];
for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {
*pdest++ = *psrc++;
}
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
#endif /* OS_MUTEX_QUERY_EN */
/*$PAGE*/
/*
*********************************************************************************************************
* RESTORE A TASK BACK TO ITS ORIGINAL PRIORITY
*
* Description: This function makes a task ready at the specified priority
*
* Arguments : ptcb is a pointer to OS_TCB of the task to make ready
*
* prio is the desired priority
*
* Returns : none
*********************************************************************************************************
*/
static void OSMutex_RdyAtPrio (OS_TCB *ptcb,
INT8U prio)
{
INT8U y;
y = ptcb->OSTCBY; /* Remove owner from ready list at 'pip' */
OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX;
if (OSRdyTbl[y] == 0u) {
OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
}
ptcb->OSTCBPrio = prio;
OSPrioCur = prio; /* The current task is now at this priority */
#if OS_LOWEST_PRIO <= 63u
ptcb->OSTCBY = (INT8U)((INT8U)(prio >> 3u) & 0x07u);
ptcb->OSTCBX = (INT8U)(prio & 0x07u);
#else
ptcb->OSTCBY = (INT8U)((INT8U)(prio >> 4u) & 0x0Fu);
ptcb->OSTCBX = (INT8U) (prio & 0x0Fu);
#endif
ptcb->OSTCBBitY = (OS_PRIO)(1uL << ptcb->OSTCBY);
ptcb->OSTCBBitX = (OS_PRIO)(1uL << ptcb->OSTCBX);
OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready at original priority */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OSTCBPrioTbl[prio] = ptcb;
}
#endif /* OS_MUTEX_EN */

893
UCOSII/CORE/os_q.c Normal file
View File

@@ -0,0 +1,893 @@
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
* MESSAGE QUEUE MANAGEMENT
*
* (c) Copyright 1992-2009, Micrium, Weston, FL
* All Rights Reserved
*
* File : OS_Q.C
* By : Jean J. Labrosse
* Version : V2.91
*
* LICENSING TERMS:
* ---------------
* uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
* If you plan on using uC/OS-II in a commercial product you need to contact Micri<72>m to properly license
* its use in your product. We provide ALL the source code for your convenience and to help you experience
* uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a
* licensing fee.
*********************************************************************************************************
*/
#ifndef OS_MASTER_FILE
#include <ucos_ii.h>
#endif
#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
/*
*********************************************************************************************************
* ACCEPT MESSAGE FROM QUEUE
*
* Description: This function checks the queue to see if a message is available. Unlike OSQPend(),
* OSQAccept() does not suspend the calling task if a message is not available.
*
* Arguments : pevent is a pointer to the event control block
*
* perr is a pointer to where an error message will be deposited. Possible error
* messages are:
*
* OS_ERR_NONE The call was successful and your task received a
* message.
* OS_ERR_EVENT_TYPE You didn't pass a pointer to a queue
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_Q_EMPTY The queue did not contain any messages
*
* Returns : != (void *)0 is the message in the queue if one is available. The message is removed
* from the so the next time OSQAccept() is called, the queue will contain
* one less entry.
* == (void *)0 if you received a NULL pointer message
* if the queue is empty or,
* if 'pevent' is a NULL pointer or,
* if you passed an invalid event type
*
* Note(s) : As of V2.60, you can now pass NULL pointers through queues. Because of this, the argument
* 'perr' has been added to the API to tell you about the outcome of the call.
*********************************************************************************************************
*/
#if OS_Q_ACCEPT_EN > 0u
void *OSQAccept (OS_EVENT *pevent,
INT8U *perr)
{
void *pmsg;
OS_Q *pq;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*perr = OS_ERR_PEVENT_NULL;
return ((void *)0);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* Validate event block type */
*perr = OS_ERR_EVENT_TYPE;
return ((void *)0);
}
OS_ENTER_CRITICAL();
pq = (OS_Q *)pevent->OSEventPtr; /* Point at queue control block */
if (pq->OSQEntries > 0u) { /* See if any messages in the queue */
pmsg = *pq->OSQOut++; /* Yes, extract oldest message from the queue */
pq->OSQEntries--; /* Update the number of entries in the queue */
if (pq->OSQOut == pq->OSQEnd) { /* Wrap OUT pointer if we are at the end of the queue */
pq->OSQOut = pq->OSQStart;
}
*perr = OS_ERR_NONE;
} else {
*perr = OS_ERR_Q_EMPTY;
pmsg = (void *)0; /* Queue is empty */
}
OS_EXIT_CRITICAL();
return (pmsg); /* Return message received (or NULL) */
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* CREATE A MESSAGE QUEUE
*
* Description: This function creates a message queue if free event control blocks are available.
*
* Arguments : start is a pointer to the base address of the message queue storage area. The
* storage area MUST be declared as an array of pointers to 'void' as follows
*
* void *MessageStorage[size]
*
* size is the number of elements in the storage area
*
* Returns : != (OS_EVENT *)0 is a pointer to the event control clock (OS_EVENT) associated with the
* created queue
* == (OS_EVENT *)0 if no event control blocks were available or an error was detected
*********************************************************************************************************
*/
OS_EVENT *OSQCreate (void **start,
INT16U size)
{
OS_EVENT *pevent;
OS_Q *pq;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
if (OSSafetyCriticalStartFlag == OS_TRUE) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
if (OSIntNesting > 0u) { /* See if called from ISR ... */
return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */
}
OS_ENTER_CRITICAL();
pevent = OSEventFreeList; /* Get next free event control block */
if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */
OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
}
OS_EXIT_CRITICAL();
if (pevent != (OS_EVENT *)0) { /* See if we have an event control block */
OS_ENTER_CRITICAL();
pq = OSQFreeList; /* Get a free queue control block */
if (pq != (OS_Q *)0) { /* Were we able to get a queue control block ? */
OSQFreeList = OSQFreeList->OSQPtr; /* Yes, Adjust free list pointer to next free*/
OS_EXIT_CRITICAL();
pq->OSQStart = start; /* Initialize the queue */
pq->OSQEnd = &start[size];
pq->OSQIn = start;
pq->OSQOut = start;
pq->OSQSize = size;
pq->OSQEntries = 0u;
pevent->OSEventType = OS_EVENT_TYPE_Q;
pevent->OSEventCnt = 0u;
pevent->OSEventPtr = pq;
#if OS_EVENT_NAME_EN > 0u
pevent->OSEventName = (INT8U *)(void *)"?";
#endif
OS_EventWaitListInit(pevent); /* Initalize the wait list */
} else {
pevent->OSEventPtr = (void *)OSEventFreeList; /* No, Return event control block on error */
OSEventFreeList = pevent;
OS_EXIT_CRITICAL();
pevent = (OS_EVENT *)0;
}
}
return (pevent);
}
/*$PAGE*/
/*
*********************************************************************************************************
* DELETE A MESSAGE QUEUE
*
* Description: This function deletes a message queue and readies all tasks pending on the queue.
*
* Arguments : pevent is a pointer to the event control block associated with the desired
* queue.
*
* opt determines delete options as follows:
* opt == OS_DEL_NO_PEND Delete the queue ONLY if no task pending
* opt == OS_DEL_ALWAYS Deletes the queue even if tasks are waiting.
* In this case, all the tasks pending will be readied.
*
* perr is a pointer to an error code that can contain one of the following values:
* OS_ERR_NONE The call was successful and the queue was deleted
* OS_ERR_DEL_ISR If you tried to delete the queue from an ISR
* OS_ERR_INVALID_OPT An invalid option was specified
* OS_ERR_TASK_WAITING One or more tasks were waiting on the queue
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
*
* Returns : pevent upon error
* (OS_EVENT *)0 if the queue was successfully deleted.
*
* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of
* the queue MUST check the return code of OSQPend().
* 2) OSQAccept() callers will not know that the intended queue has been deleted unless
* they check 'pevent' to see that it's a NULL pointer.
* 3) This call can potentially disable interrupts for a long time. The interrupt disable
* time is directly proportional to the number of tasks waiting on the queue.
* 4) Because ALL tasks pending on the queue will be readied, you MUST be careful in
* applications where the queue is used for mutual exclusion because the resource(s)
* will no longer be guarded by the queue.
* 5) If the storage for the message queue was allocated dynamically (i.e. using a malloc()
* type call) then your application MUST release the memory storage by call the counterpart
* call of the dynamic allocation scheme used. If the queue storage was created statically
* then, the storage can be reused.
*********************************************************************************************************
*/
#if OS_Q_DEL_EN > 0u
OS_EVENT *OSQDel (OS_EVENT *pevent,
INT8U opt,
INT8U *perr)
{
BOOLEAN tasks_waiting;
OS_EVENT *pevent_return;
OS_Q *pq;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*perr = OS_ERR_PEVENT_NULL;
return (pevent);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
*perr = OS_ERR_EVENT_TYPE;
return (pevent);
}
if (OSIntNesting > 0u) { /* See if called from ISR ... */
*perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
return (pevent);
}
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on queue */
tasks_waiting = OS_TRUE; /* Yes */
} else {
tasks_waiting = OS_FALSE; /* No */
}
switch (opt) {
case OS_DEL_NO_PEND: /* Delete queue only if no task waiting */
if (tasks_waiting == OS_FALSE) {
#if OS_EVENT_NAME_EN > 0u
pevent->OSEventName = (INT8U *)(void *)"?";
#endif
pq = (OS_Q *)pevent->OSEventPtr; /* Return OS_Q to free list */
pq->OSQPtr = OSQFreeList;
OSQFreeList = pq;
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
pevent->OSEventCnt = 0u;
OSEventFreeList = pevent; /* Get next free event control block */
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
pevent_return = (OS_EVENT *)0; /* Queue has been deleted */
} else {
OS_EXIT_CRITICAL();
*perr = OS_ERR_TASK_WAITING;
pevent_return = pevent;
}
break;
case OS_DEL_ALWAYS: /* Always delete the queue */
while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for queue */
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_OK);
}
#if OS_EVENT_NAME_EN > 0u
pevent->OSEventName = (INT8U *)(void *)"?";
#endif
pq = (OS_Q *)pevent->OSEventPtr; /* Return OS_Q to free list */
pq->OSQPtr = OSQFreeList;
OSQFreeList = pq;
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
pevent->OSEventCnt = 0u;
OSEventFreeList = pevent; /* Get next free event control block */
OS_EXIT_CRITICAL();
if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */
OS_Sched(); /* Find highest priority task ready to run */
}
*perr = OS_ERR_NONE;
pevent_return = (OS_EVENT *)0; /* Queue has been deleted */
break;
default:
OS_EXIT_CRITICAL();
*perr = OS_ERR_INVALID_OPT;
pevent_return = pevent;
break;
}
return (pevent_return);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* FLUSH QUEUE
*
* Description : This function is used to flush the contents of the message queue.
*
* Arguments : none
*
* Returns : OS_ERR_NONE upon success
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
*
* WARNING : You should use this function with great care because, when to flush the queue, you LOOSE
* the references to what the queue entries are pointing to and thus, you could cause
* 'memory leaks'. In other words, the data you are pointing to that's being referenced
* by the queue entries should, most likely, need to be de-allocated (i.e. freed).
*********************************************************************************************************
*/
#if OS_Q_FLUSH_EN > 0u
INT8U OSQFlush (OS_EVENT *pevent)
{
OS_Q *pq;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
#endif
OS_ENTER_CRITICAL();
pq = (OS_Q *)pevent->OSEventPtr; /* Point to queue storage structure */
pq->OSQIn = pq->OSQStart;
pq->OSQOut = pq->OSQStart;
pq->OSQEntries = 0u;
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* PEND ON A QUEUE FOR A MESSAGE
*
* Description: This function waits for a message to be sent to a queue
*
* Arguments : pevent is a pointer to the event control block associated with the desired queue
*
* timeout is an optional timeout period (in clock ticks). If non-zero, your task will
* wait for a message to arrive at the queue up to the amount of time
* specified by this argument. If you specify 0, however, your task will wait
* forever at the specified queue or, until a message arrives.
*
* perr is a pointer to where an error message will be deposited. Possible error
* messages are:
*
* OS_ERR_NONE The call was successful and your task received a
* message.
* OS_ERR_TIMEOUT A message was not received within the specified 'timeout'.
* OS_ERR_PEND_ABORT The wait on the queue was aborted.
* OS_ERR_EVENT_TYPE You didn't pass a pointer to a queue
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_PEND_ISR If you called this function from an ISR and the result
* would lead to a suspension.
* OS_ERR_PEND_LOCKED If you called this function with the scheduler is locked
*
* Returns : != (void *)0 is a pointer to the message received
* == (void *)0 if you received a NULL pointer message or,
* if no message was received or,
* if 'pevent' is a NULL pointer or,
* if you didn't pass a pointer to a queue.
*
* Note(s) : As of V2.60, this function allows you to receive NULL pointer messages.
*********************************************************************************************************
*/
void *OSQPend (OS_EVENT *pevent,
INT32U timeout,
INT8U *perr)
{
void *pmsg;
OS_Q *pq;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*perr = OS_ERR_PEVENT_NULL;
return ((void *)0);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* Validate event block type */
*perr = OS_ERR_EVENT_TYPE;
return ((void *)0);
}
if (OSIntNesting > 0u) { /* See if called from ISR ... */
*perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return ((void *)0);
}
if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */
*perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */
return ((void *)0);
}
OS_ENTER_CRITICAL();
pq = (OS_Q *)pevent->OSEventPtr; /* Point at queue control block */
if (pq->OSQEntries > 0u) { /* See if any messages in the queue */
pmsg = *pq->OSQOut++; /* Yes, extract oldest message from the queue */
pq->OSQEntries--; /* Update the number of entries in the queue */
if (pq->OSQOut == pq->OSQEnd) { /* Wrap OUT pointer if we are at the end of the queue */
pq->OSQOut = pq->OSQStart;
}
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
return (pmsg); /* Return message received */
}
OSTCBCur->OSTCBStat |= OS_STAT_Q; /* Task will have to pend for a message to be posted */
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;
OSTCBCur->OSTCBDly = timeout; /* Load timeout into TCB */
OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find next highest priority task ready to run */
OS_ENTER_CRITICAL();
switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */
case OS_STAT_PEND_OK: /* Extract message from TCB (Put there by QPost) */
pmsg = OSTCBCur->OSTCBMsg;
*perr = OS_ERR_NONE;
break;
case OS_STAT_PEND_ABORT:
pmsg = (void *)0;
*perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */
break;
case OS_STAT_PEND_TO:
default:
OS_EventTaskRemove(OSTCBCur, pevent);
pmsg = (void *)0;
*perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */
break;
}
OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */
#if (OS_EVENT_MULTI_EN > 0u)
OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
#endif
OSTCBCur->OSTCBMsg = (void *)0; /* Clear received message */
OS_EXIT_CRITICAL();
return (pmsg); /* Return received message */
}
/*$PAGE*/
/*
*********************************************************************************************************
* ABORT WAITING ON A MESSAGE QUEUE
*
* Description: This function aborts & readies any tasks currently waiting on a queue. This function
* should be used to fault-abort the wait on the queue, rather than to normally signal
* the queue via OSQPost(), OSQPostFront() or OSQPostOpt().
*
* Arguments : pevent is a pointer to the event control block associated with the desired queue.
*
* opt determines the type of ABORT performed:
* OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the
* queue
* OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the
* queue
*
* perr is a pointer to where an error message will be deposited. Possible error
* messages are:
*
* OS_ERR_NONE No tasks were waiting on the queue.
* OS_ERR_PEND_ABORT At least one task waiting on the queue was readied
* and informed of the aborted wait; check return value
* for the number of tasks whose wait on the queue
* was aborted.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
*
* Returns : == 0 if no tasks were waiting on the queue, or upon error.
* > 0 if one or more tasks waiting on the queue are now readied and informed.
*********************************************************************************************************
*/
#if OS_Q_PEND_ABORT_EN > 0u
INT8U OSQPendAbort (OS_EVENT *pevent,
INT8U opt,
INT8U *perr)
{
INT8U nbr_tasks;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*perr = OS_ERR_PEVENT_NULL;
return (0u);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
*perr = OS_ERR_EVENT_TYPE;
return (0u);
}
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0u) { /* See if any task waiting on queue? */
nbr_tasks = 0u;
switch (opt) {
case OS_PEND_OPT_BROADCAST: /* Do we need to abort ALL waiting tasks? */
while (pevent->OSEventGrp != 0u) { /* Yes, ready ALL tasks waiting on queue */
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT);
nbr_tasks++;
}
break;
case OS_PEND_OPT_NONE:
default: /* No, ready HPT waiting on queue */
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT);
nbr_tasks++;
break;
}
OS_EXIT_CRITICAL();
OS_Sched(); /* Find HPT ready to run */
*perr = OS_ERR_PEND_ABORT;
return (nbr_tasks);
}
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
return (0u); /* No tasks waiting on queue */
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* POST MESSAGE TO A QUEUE
*
* Description: This function sends a message to a queue
*
* Arguments : pevent is a pointer to the event control block associated with the desired queue
*
* pmsg is a pointer to the message to send.
*
* Returns : OS_ERR_NONE The call was successful and the message was sent
* OS_ERR_Q_FULL If the queue cannot accept any more messages because it is full.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
*
* Note(s) : As of V2.60, this function allows you to send NULL pointer messages.
*********************************************************************************************************
*/
#if OS_Q_POST_EN > 0u
INT8U OSQPost (OS_EVENT *pevent,
void *pmsg)
{
OS_Q *pq;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0u) { /* See if any task pending on queue */
/* Ready highest priority task waiting on event */
(void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK);
OS_EXIT_CRITICAL();
OS_Sched(); /* Find highest priority task ready to run */
return (OS_ERR_NONE);
}
pq = (OS_Q *)pevent->OSEventPtr; /* Point to queue control block */
if (pq->OSQEntries >= pq->OSQSize) { /* Make sure queue is not full */
OS_EXIT_CRITICAL();
return (OS_ERR_Q_FULL);
}
*pq->OSQIn++ = pmsg; /* Insert message into queue */
pq->OSQEntries++; /* Update the nbr of entries in the queue */
if (pq->OSQIn == pq->OSQEnd) { /* Wrap IN ptr if we are at end of queue */
pq->OSQIn = pq->OSQStart;
}
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* POST MESSAGE TO THE FRONT OF A QUEUE
*
* Description: This function sends a message to a queue but unlike OSQPost(), the message is posted at
* the front instead of the end of the queue. Using OSQPostFront() allows you to send
* 'priority' messages.
*
* Arguments : pevent is a pointer to the event control block associated with the desired queue
*
* pmsg is a pointer to the message to send.
*
* Returns : OS_ERR_NONE The call was successful and the message was sent
* OS_ERR_Q_FULL If the queue cannot accept any more messages because it is full.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
*
* Note(s) : As of V2.60, this function allows you to send NULL pointer messages.
*********************************************************************************************************
*/
#if OS_Q_POST_FRONT_EN > 0u
INT8U OSQPostFront (OS_EVENT *pevent,
void *pmsg)
{
OS_Q *pq;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0u) { /* See if any task pending on queue */
/* Ready highest priority task waiting on event */
(void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK);
OS_EXIT_CRITICAL();
OS_Sched(); /* Find highest priority task ready to run */
return (OS_ERR_NONE);
}
pq = (OS_Q *)pevent->OSEventPtr; /* Point to queue control block */
if (pq->OSQEntries >= pq->OSQSize) { /* Make sure queue is not full */
OS_EXIT_CRITICAL();
return (OS_ERR_Q_FULL);
}
if (pq->OSQOut == pq->OSQStart) { /* Wrap OUT ptr if we are at the 1st queue entry */
pq->OSQOut = pq->OSQEnd;
}
pq->OSQOut--;
*pq->OSQOut = pmsg; /* Insert message into queue */
pq->OSQEntries++; /* Update the nbr of entries in the queue */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* POST MESSAGE TO A QUEUE
*
* Description: This function sends a message to a queue. This call has been added to reduce code size
* since it can replace both OSQPost() and OSQPostFront(). Also, this function adds the
* capability to broadcast a message to ALL tasks waiting on the message queue.
*
* Arguments : pevent is a pointer to the event control block associated with the desired queue
*
* pmsg is a pointer to the message to send.
*
* opt determines the type of POST performed:
* OS_POST_OPT_NONE POST to a single waiting task
* (Identical to OSQPost())
* OS_POST_OPT_BROADCAST POST to ALL tasks that are waiting on the queue
* OS_POST_OPT_FRONT POST as LIFO (Simulates OSQPostFront())
* OS_POST_OPT_NO_SCHED Indicates that the scheduler will NOT be invoked
*
* Returns : OS_ERR_NONE The call was successful and the message was sent
* OS_ERR_Q_FULL If the queue cannot accept any more messages because it is full.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
*
* Warning : Interrupts can be disabled for a long time if you do a 'broadcast'. In fact, the
* interrupt disable time is proportional to the number of tasks waiting on the queue.
*********************************************************************************************************
*/
#if OS_Q_POST_OPT_EN > 0u
INT8U OSQPostOpt (OS_EVENT *pevent,
void *pmsg,
INT8U opt)
{
OS_Q *pq;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00u) { /* See if any task pending on queue */
if ((opt & OS_POST_OPT_BROADCAST) != 0x00u) { /* Do we need to post msg to ALL waiting tasks ? */
while (pevent->OSEventGrp != 0u) { /* Yes, Post to ALL tasks waiting on queue */
(void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK);
}
} else { /* No, Post to HPT waiting on queue */
(void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK);
}
OS_EXIT_CRITICAL();
if ((opt & OS_POST_OPT_NO_SCHED) == 0u) { /* See if scheduler needs to be invoked */
OS_Sched(); /* Find highest priority task ready to run */
}
return (OS_ERR_NONE);
}
pq = (OS_Q *)pevent->OSEventPtr; /* Point to queue control block */
if (pq->OSQEntries >= pq->OSQSize) { /* Make sure queue is not full */
OS_EXIT_CRITICAL();
return (OS_ERR_Q_FULL);
}
if ((opt & OS_POST_OPT_FRONT) != 0x00u) { /* Do we post to the FRONT of the queue? */
if (pq->OSQOut == pq->OSQStart) { /* Yes, Post as LIFO, Wrap OUT pointer if we ... */
pq->OSQOut = pq->OSQEnd; /* ... are at the 1st queue entry */
}
pq->OSQOut--;
*pq->OSQOut = pmsg; /* Insert message into queue */
} else { /* No, Post as FIFO */
*pq->OSQIn++ = pmsg; /* Insert message into queue */
if (pq->OSQIn == pq->OSQEnd) { /* Wrap IN ptr if we are at end of queue */
pq->OSQIn = pq->OSQStart;
}
}
pq->OSQEntries++; /* Update the nbr of entries in the queue */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* QUERY A MESSAGE QUEUE
*
* Description: This function obtains information about a message queue.
*
* Arguments : pevent is a pointer to the event control block associated with the desired queue
*
* p_q_data is a pointer to a structure that will contain information about the message
* queue.
*
* Returns : OS_ERR_NONE The call was successful and the message was sent
* OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non queue.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_PDATA_NULL If 'p_q_data' is a NULL pointer
*********************************************************************************************************
*/
#if OS_Q_QUERY_EN > 0u
INT8U OSQQuery (OS_EVENT *pevent,
OS_Q_DATA *p_q_data)
{
OS_Q *pq;
INT8U i;
OS_PRIO *psrc;
OS_PRIO *pdest;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (p_q_data == (OS_Q_DATA *)0) { /* Validate 'p_q_data' */
return (OS_ERR_PDATA_NULL);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
OS_ENTER_CRITICAL();
p_q_data->OSEventGrp = pevent->OSEventGrp; /* Copy message queue wait list */
psrc = &pevent->OSEventTbl[0];
pdest = &p_q_data->OSEventTbl[0];
for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {
*pdest++ = *psrc++;
}
pq = (OS_Q *)pevent->OSEventPtr;
if (pq->OSQEntries > 0u) {
p_q_data->OSMsg = *pq->OSQOut; /* Get next message to return if available */
} else {
p_q_data->OSMsg = (void *)0;
}
p_q_data->OSNMsgs = pq->OSQEntries;
p_q_data->OSQSize = pq->OSQSize;
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
#endif /* OS_Q_QUERY_EN */
/*$PAGE*/
/*
*********************************************************************************************************
* QUEUE MODULE INITIALIZATION
*
* Description : This function is called by uC/OS-II to initialize the message queue module. Your
* application MUST NOT call this function.
*
* Arguments : none
*
* Returns : none
*
* Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it.
*********************************************************************************************************
*/
void OS_QInit (void)
{
#if OS_MAX_QS == 1u
OSQFreeList = &OSQTbl[0]; /* Only ONE queue! */
OSQFreeList->OSQPtr = (OS_Q *)0;
#endif
#if OS_MAX_QS >= 2u
INT16U ix;
INT16U ix_next;
OS_Q *pq1;
OS_Q *pq2;
OS_MemClr((INT8U *)&OSQTbl[0], sizeof(OSQTbl)); /* Clear the queue table */
for (ix = 0u; ix < (OS_MAX_QS - 1u); ix++) { /* Init. list of free QUEUE control blocks */
ix_next = ix + 1u;
pq1 = &OSQTbl[ix];
pq2 = &OSQTbl[ix_next];
pq1->OSQPtr = pq2;
}
pq1 = &OSQTbl[ix];
pq1->OSQPtr = (OS_Q *)0;
OSQFreeList = &OSQTbl[0];
#endif
}
#endif /* OS_Q_EN */

629
UCOSII/CORE/os_sem.c Normal file
View File

@@ -0,0 +1,629 @@
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
* SEMAPHORE MANAGEMENT
*
* (c) Copyright 1992-2009, Micrium, Weston, FL
* All Rights Reserved
*
* File : OS_SEM.C
* By : Jean J. Labrosse
* Version : V2.91
*
* LICENSING TERMS:
* ---------------
* uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
* If you plan on using uC/OS-II in a commercial product you need to contact Micri<72>m to properly license
* its use in your product. We provide ALL the source code for your convenience and to help you experience
* uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a
* licensing fee.
*********************************************************************************************************
*/
#ifndef OS_MASTER_FILE
#include <ucos_ii.h>
#endif
#if OS_SEM_EN > 0u
/*$PAGE*/
/*
*********************************************************************************************************
* ACCEPT SEMAPHORE
*
* Description: This function checks the semaphore to see if a resource is available or, if an event
* occurred. Unlike OSSemPend(), OSSemAccept() does not suspend the calling task if the
* resource is not available or the event did not occur.
*
* Arguments : pevent is a pointer to the event control block
*
* Returns : > 0 if the resource is available or the event did not occur the semaphore is
* decremented to obtain the resource.
* == 0 if the resource is not available or the event did not occur or,
* if 'pevent' is a NULL pointer or,
* if you didn't pass a pointer to a semaphore
*********************************************************************************************************
*/
#if OS_SEM_ACCEPT_EN > 0u
INT16U OSSemAccept (OS_EVENT *pevent)
{
INT16U cnt;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (0u);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
return (0u);
}
OS_ENTER_CRITICAL();
cnt = pevent->OSEventCnt;
if (cnt > 0u) { /* See if resource is available */
pevent->OSEventCnt--; /* Yes, decrement semaphore and notify caller */
}
OS_EXIT_CRITICAL();
return (cnt); /* Return semaphore count */
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* CREATE A SEMAPHORE
*
* Description: This function creates a semaphore.
*
* Arguments : cnt is the initial value for the semaphore. If the value is 0, no resource is
* available (or no event has occurred). You initialize the semaphore to a
* non-zero value to specify how many resources are available (e.g. if you have
* 10 resources, you would initialize the semaphore to 10).
*
* Returns : != (void *)0 is a pointer to the event control block (OS_EVENT) associated with the
* created semaphore
* == (void *)0 if no event control blocks were available
*********************************************************************************************************
*/
OS_EVENT *OSSemCreate (INT16U cnt)
{
OS_EVENT *pevent;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
if (OSSafetyCriticalStartFlag == OS_TRUE) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
if (OSIntNesting > 0u) { /* See if called from ISR ... */
return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */
}
OS_ENTER_CRITICAL();
pevent = OSEventFreeList; /* Get next free event control block */
if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */
OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
}
OS_EXIT_CRITICAL();
if (pevent != (OS_EVENT *)0) { /* Get an event control block */
pevent->OSEventType = OS_EVENT_TYPE_SEM;
pevent->OSEventCnt = cnt; /* Set semaphore value */
pevent->OSEventPtr = (void *)0; /* Unlink from ECB free list */
#if OS_EVENT_NAME_EN > 0u
pevent->OSEventName = (INT8U *)(void *)"?";
#endif
OS_EventWaitListInit(pevent); /* Initialize to 'nobody waiting' on sem. */
}
return (pevent);
}
/*$PAGE*/
/*
*********************************************************************************************************
* DELETE A SEMAPHORE
*
* Description: This function deletes a semaphore and readies all tasks pending on the semaphore.
*
* Arguments : pevent is a pointer to the event control block associated with the desired
* semaphore.
*
* opt determines delete options as follows:
* opt == OS_DEL_NO_PEND Delete semaphore ONLY if no task pending
* opt == OS_DEL_ALWAYS Deletes the semaphore even if tasks are waiting.
* In this case, all the tasks pending will be readied.
*
* perr is a pointer to an error code that can contain one of the following values:
* OS_ERR_NONE The call was successful and the semaphore was deleted
* OS_ERR_DEL_ISR If you attempted to delete the semaphore from an ISR
* OS_ERR_INVALID_OPT An invalid option was specified
* OS_ERR_TASK_WAITING One or more tasks were waiting on the semaphore
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
*
* Returns : pevent upon error
* (OS_EVENT *)0 if the semaphore was successfully deleted.
*
* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of
* the semaphore MUST check the return code of OSSemPend().
* 2) OSSemAccept() callers will not know that the intended semaphore has been deleted unless
* they check 'pevent' to see that it's a NULL pointer.
* 3) This call can potentially disable interrupts for a long time. The interrupt disable
* time is directly proportional to the number of tasks waiting on the semaphore.
* 4) Because ALL tasks pending on the semaphore will be readied, you MUST be careful in
* applications where the semaphore is used for mutual exclusion because the resource(s)
* will no longer be guarded by the semaphore.
*********************************************************************************************************
*/
#if OS_SEM_DEL_EN > 0u
OS_EVENT *OSSemDel (OS_EVENT *pevent,
INT8U opt,
INT8U *perr)
{
BOOLEAN tasks_waiting;
OS_EVENT *pevent_return;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*perr = OS_ERR_PEVENT_NULL;
return (pevent);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
*perr = OS_ERR_EVENT_TYPE;
return (pevent);
}
if (OSIntNesting > 0u) { /* See if called from ISR ... */
*perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
return (pevent);
}
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on semaphore */
tasks_waiting = OS_TRUE; /* Yes */
} else {
tasks_waiting = OS_FALSE; /* No */
}
switch (opt) {
case OS_DEL_NO_PEND: /* Delete semaphore only if no task waiting */
if (tasks_waiting == OS_FALSE) {
#if OS_EVENT_NAME_EN > 0u
pevent->OSEventName = (INT8U *)(void *)"?";
#endif
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
pevent->OSEventCnt = 0u;
OSEventFreeList = pevent; /* Get next free event control block */
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */
} else {
OS_EXIT_CRITICAL();
*perr = OS_ERR_TASK_WAITING;
pevent_return = pevent;
}
break;
case OS_DEL_ALWAYS: /* Always delete the semaphore */
while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for semaphore */
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK);
}
#if OS_EVENT_NAME_EN > 0u
pevent->OSEventName = (INT8U *)(void *)"?";
#endif
pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
pevent->OSEventCnt = 0u;
OSEventFreeList = pevent; /* Get next free event control block */
OS_EXIT_CRITICAL();
if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */
OS_Sched(); /* Find highest priority task ready to run */
}
*perr = OS_ERR_NONE;
pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */
break;
default:
OS_EXIT_CRITICAL();
*perr = OS_ERR_INVALID_OPT;
pevent_return = pevent;
break;
}
return (pevent_return);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* PEND ON SEMAPHORE
*
* Description: This function waits for a semaphore.
*
* Arguments : pevent is a pointer to the event control block associated with the desired
* semaphore.
*
* timeout is an optional timeout period (in clock ticks). If non-zero, your task will
* wait for the resource up to the amount of time specified by this argument.
* If you specify 0, however, your task will wait forever at the specified
* semaphore or, until the resource becomes available (or the event occurs).
*
* perr is a pointer to where an error message will be deposited. Possible error
* messages are:
*
* OS_ERR_NONE The call was successful and your task owns the resource
* or, the event you are waiting for occurred.
* OS_ERR_TIMEOUT The semaphore was not received within the specified
* 'timeout'.
* OS_ERR_PEND_ABORT The wait on the semaphore was aborted.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore.
* OS_ERR_PEND_ISR If you called this function from an ISR and the result
* would lead to a suspension.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
* OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked
*
* Returns : none
*********************************************************************************************************
*/
/*$PAGE*/
void OSSemPend (OS_EVENT *pevent,
INT32U timeout,
INT8U *perr)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*perr = OS_ERR_PEVENT_NULL;
return;
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
*perr = OS_ERR_EVENT_TYPE;
return;
}
if (OSIntNesting > 0u) { /* See if called from ISR ... */
*perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return;
}
if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */
*perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */
return;
}
OS_ENTER_CRITICAL();
if (pevent->OSEventCnt > 0u) { /* If sem. is positive, resource available ... */
pevent->OSEventCnt--; /* ... decrement semaphore only if positive. */
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
return;
}
/* Otherwise, must wait until event occurs */
OSTCBCur->OSTCBStat |= OS_STAT_SEM; /* Resource not available, pend on semaphore */
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;
OSTCBCur->OSTCBDly = timeout; /* Store pend timeout in TCB */
OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find next highest priority task ready */
OS_ENTER_CRITICAL();
switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */
case OS_STAT_PEND_OK:
*perr = OS_ERR_NONE;
break;
case OS_STAT_PEND_ABORT:
*perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */
break;
case OS_STAT_PEND_TO:
default:
OS_EventTaskRemove(OSTCBCur, pevent);
*perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */
break;
}
OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */
#if (OS_EVENT_MULTI_EN > 0u)
OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
#endif
OS_EXIT_CRITICAL();
}
/*$PAGE*/
/*
*********************************************************************************************************
* ABORT WAITING ON A SEMAPHORE
*
* Description: This function aborts & readies any tasks currently waiting on a semaphore. This function
* should be used to fault-abort the wait on the semaphore, rather than to normally signal
* the semaphore via OSSemPost().
*
* Arguments : pevent is a pointer to the event control block associated with the desired
* semaphore.
*
* opt determines the type of ABORT performed:
* OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the
* semaphore
* OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the
* semaphore
*
* perr is a pointer to where an error message will be deposited. Possible error
* messages are:
*
* OS_ERR_NONE No tasks were waiting on the semaphore.
* OS_ERR_PEND_ABORT At least one task waiting on the semaphore was readied
* and informed of the aborted wait; check return value
* for the number of tasks whose wait on the semaphore
* was aborted.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
*
* Returns : == 0 if no tasks were waiting on the semaphore, or upon error.
* > 0 if one or more tasks waiting on the semaphore are now readied and informed.
*********************************************************************************************************
*/
#if OS_SEM_PEND_ABORT_EN > 0u
INT8U OSSemPendAbort (OS_EVENT *pevent,
INT8U opt,
INT8U *perr)
{
INT8U nbr_tasks;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*perr = OS_ERR_PEVENT_NULL;
return (0u);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
*perr = OS_ERR_EVENT_TYPE;
return (0u);
}
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0u) { /* See if any task waiting on semaphore? */
nbr_tasks = 0u;
switch (opt) {
case OS_PEND_OPT_BROADCAST: /* Do we need to abort ALL waiting tasks? */
while (pevent->OSEventGrp != 0u) { /* Yes, ready ALL tasks waiting on semaphore */
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT);
nbr_tasks++;
}
break;
case OS_PEND_OPT_NONE:
default: /* No, ready HPT waiting on semaphore */
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT);
nbr_tasks++;
break;
}
OS_EXIT_CRITICAL();
OS_Sched(); /* Find HPT ready to run */
*perr = OS_ERR_PEND_ABORT;
return (nbr_tasks);
}
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
return (0u); /* No tasks waiting on semaphore */
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* POST TO A SEMAPHORE
*
* Description: This function signals a semaphore
*
* Arguments : pevent is a pointer to the event control block associated with the desired
* semaphore.
*
* Returns : OS_ERR_NONE The call was successful and the semaphore was signaled.
* OS_ERR_SEM_OVF If the semaphore count exceeded its limit. In other words, you have
* signalled the semaphore more often than you waited on it with either
* OSSemAccept() or OSSemPend().
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
*********************************************************************************************************
*/
INT8U OSSemPost (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0u) { /* See if any task waiting for semaphore */
/* Ready HPT waiting on event */
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK);
OS_EXIT_CRITICAL();
OS_Sched(); /* Find HPT ready to run */
return (OS_ERR_NONE);
}
if (pevent->OSEventCnt < 65535u) { /* Make sure semaphore will not overflow */
pevent->OSEventCnt++; /* Increment semaphore count to register event */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
OS_EXIT_CRITICAL(); /* Semaphore value has reached its maximum */
return (OS_ERR_SEM_OVF);
}
/*$PAGE*/
/*
*********************************************************************************************************
* QUERY A SEMAPHORE
*
* Description: This function obtains information about a semaphore
*
* Arguments : pevent is a pointer to the event control block associated with the desired
* semaphore
*
* p_sem_data is a pointer to a structure that will contain information about the
* semaphore.
*
* Returns : OS_ERR_NONE The call was successful and the message was sent
* OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non semaphore.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
* OS_ERR_PDATA_NULL If 'p_sem_data' is a NULL pointer
*********************************************************************************************************
*/
#if OS_SEM_QUERY_EN > 0u
INT8U OSSemQuery (OS_EVENT *pevent,
OS_SEM_DATA *p_sem_data)
{
INT8U i;
OS_PRIO *psrc;
OS_PRIO *pdest;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
return (OS_ERR_PEVENT_NULL);
}
if (p_sem_data == (OS_SEM_DATA *)0) { /* Validate 'p_sem_data' */
return (OS_ERR_PDATA_NULL);
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
OS_ENTER_CRITICAL();
p_sem_data->OSEventGrp = pevent->OSEventGrp; /* Copy message mailbox wait list */
psrc = &pevent->OSEventTbl[0];
pdest = &p_sem_data->OSEventTbl[0];
for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {
*pdest++ = *psrc++;
}
p_sem_data->OSCnt = pevent->OSEventCnt; /* Get semaphore count */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
#endif /* OS_SEM_QUERY_EN */
/*$PAGE*/
/*
*********************************************************************************************************
* SET SEMAPHORE
*
* Description: This function sets the semaphore count to the value specified as an argument. Typically,
* this value would be 0.
*
* You would typically use this function when a semaphore is used as a signaling mechanism
* and, you want to reset the count value.
*
* Arguments : pevent is a pointer to the event control block
*
* cnt is the new value for the semaphore count. You would pass 0 to reset the
* semaphore count.
*
* perr is a pointer to an error code returned by the function as follows:
*
* OS_ERR_NONE The call was successful and the semaphore value was set.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
* OS_ERR_TASK_WAITING If tasks are waiting on the semaphore.
*********************************************************************************************************
*/
#if OS_SEM_SET_EN > 0u
void OSSemSet (OS_EVENT *pevent,
INT16U cnt,
INT8U *perr)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
}
#endif
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*perr = OS_ERR_PEVENT_NULL;
return;
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
*perr = OS_ERR_EVENT_TYPE;
return;
}
OS_ENTER_CRITICAL();
*perr = OS_ERR_NONE;
if (pevent->OSEventCnt > 0u) { /* See if semaphore already has a count */
pevent->OSEventCnt = cnt; /* Yes, set it to the new value specified. */
} else { /* No */
if (pevent->OSEventGrp == 0u) { /* See if task(s) waiting? */
pevent->OSEventCnt = cnt; /* No, OK to set the value */
} else {
*perr = OS_ERR_TASK_WAITING;
}
}
OS_EXIT_CRITICAL();
}
#endif
#endif /* OS_SEM_EN */

1263
UCOSII/CORE/os_task.c Normal file

File diff suppressed because it is too large Load Diff

264
UCOSII/CORE/os_time.c Normal file
View File

@@ -0,0 +1,264 @@
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
* TIME MANAGEMENT
*
* (c) Copyright 1992-2009, Micrium, Weston, FL
* All Rights Reserved
*
* File : OS_TIME.C
* By : Jean J. Labrosse
* Version : V2.91
*
* LICENSING TERMS:
* ---------------
* uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
* If you plan on using uC/OS-II in a commercial product you need to contact Micri<72>m to properly license
* its use in your product. We provide ALL the source code for your convenience and to help you experience
* uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a
* licensing fee.
*********************************************************************************************************
*/
#ifndef OS_MASTER_FILE
#include <ucos_ii.h>
#endif
/*
*********************************************************************************************************
* DELAY TASK 'n' TICKS
*
* Description: This function is called to delay execution of the currently running task until the
* specified number of system ticks expires. This, of course, directly equates to delaying
* the current task for some time to expire. No delay will result If the specified delay is
* 0. If the specified delay is greater than 0 then, a context switch will result.
*
* Arguments : ticks is the time delay that the task will be suspended in number of clock 'ticks'.
* Note that by specifying 0, the task will not be delayed.
*
* Returns : none
*********************************************************************************************************
*/
void OSTimeDly (INT32U ticks)
{
INT8U y;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
return;
}
if (OSLockNesting > 0u) { /* See if called with scheduler locked */
return;
}
if (ticks > 0u) { /* 0 means no delay! */
OS_ENTER_CRITICAL();
y = OSTCBCur->OSTCBY; /* Delay current task */
OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX;
if (OSRdyTbl[y] == 0u) {
OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;
}
OSTCBCur->OSTCBDly = ticks; /* Load ticks in TCB */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find next task to run! */
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* DELAY TASK FOR SPECIFIED TIME
*
* Description: This function is called to delay execution of the currently running task until some time
* expires. This call allows you to specify the delay time in HOURS, MINUTES, SECONDS and
* MILLISECONDS instead of ticks.
*
* Arguments : hours specifies the number of hours that the task will be delayed (max. is 255)
* minutes specifies the number of minutes (max. 59)
* seconds specifies the number of seconds (max. 59)
* ms specifies the number of milliseconds (max. 999)
*
* Returns : OS_ERR_NONE
* OS_ERR_TIME_INVALID_MINUTES
* OS_ERR_TIME_INVALID_SECONDS
* OS_ERR_TIME_INVALID_MS
* OS_ERR_TIME_ZERO_DLY
* OS_ERR_TIME_DLY_ISR
*
* Note(s) : The resolution on the milliseconds depends on the tick rate. For example, you can't do
* a 10 mS delay if the ticker interrupts every 100 mS. In this case, the delay would be
* set to 0. The actual delay is rounded to the nearest tick.
*********************************************************************************************************
*/
#if OS_TIME_DLY_HMSM_EN > 0u
INT8U OSTimeDlyHMSM (INT8U hours,
INT8U minutes,
INT8U seconds,
INT16U ms)
{
INT32U ticks;
if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
return (OS_ERR_TIME_DLY_ISR);
}
if (OSLockNesting > 0u) { /* See if called with scheduler locked */
return (OS_ERR_SCHED_LOCKED);
}
#if OS_ARG_CHK_EN > 0u
if (hours == 0u) {
if (minutes == 0u) {
if (seconds == 0u) {
if (ms == 0u) {
return (OS_ERR_TIME_ZERO_DLY);
}
}
}
}
if (minutes > 59u) {
return (OS_ERR_TIME_INVALID_MINUTES); /* Validate arguments to be within range */
}
if (seconds > 59u) {
return (OS_ERR_TIME_INVALID_SECONDS);
}
if (ms > 999u) {
return (OS_ERR_TIME_INVALID_MS);
}
#endif
/* Compute the total number of clock ticks required.. */
/* .. (rounded to the nearest tick) */
ticks = ((INT32U)hours * 3600uL + (INT32U)minutes * 60uL + (INT32U)seconds) * OS_TICKS_PER_SEC
+ OS_TICKS_PER_SEC * ((INT32U)ms + 500uL / OS_TICKS_PER_SEC) / 1000uL;
OSTimeDly(ticks);
return (OS_ERR_NONE);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* RESUME A DELAYED TASK
*
* Description: This function is used resume a task that has been delayed through a call to either
* OSTimeDly() or OSTimeDlyHMSM(). Note that you can call this function to resume a
* task that is waiting for an event with timeout. This would make the task look
* like a timeout occurred.
*
* Arguments : prio specifies the priority of the task to resume
*
* Returns : OS_ERR_NONE Task has been resumed
* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed
* (i.e. >= OS_LOWEST_PRIO)
* OS_ERR_TIME_NOT_DLY Task is not waiting for time to expire
* OS_ERR_TASK_NOT_EXIST The desired task has not been created or has been assigned to a Mutex.
*********************************************************************************************************
*/
#if OS_TIME_DLY_RESUME_EN > 0u
INT8U OSTimeDlyResume (INT8U prio)
{
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3u /* Storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
if (prio >= OS_LOWEST_PRIO) {
return (OS_ERR_PRIO_INVALID);
}
OS_ENTER_CRITICAL();
ptcb = OSTCBPrioTbl[prio]; /* Make sure that task exist */
if (ptcb == (OS_TCB *)0) {
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST); /* The task does not exist */
}
if (ptcb == OS_TCB_RESERVED) {
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST); /* The task does not exist */
}
if (ptcb->OSTCBDly == 0u) { /* See if task is delayed */
OS_EXIT_CRITICAL();
return (OS_ERR_TIME_NOT_DLY); /* Indicate that task was not delayed */
}
ptcb->OSTCBDly = 0u; /* Clear the time delay */
if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {
ptcb->OSTCBStat &= ~OS_STAT_PEND_ANY; /* Yes, Clear status flag */
ptcb->OSTCBStatPend = OS_STAT_PEND_TO; /* Indicate PEND timeout */
} else {
ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
}
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { /* Is task suspended? */
OSRdyGrp |= ptcb->OSTCBBitY; /* No, Make ready */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OS_EXIT_CRITICAL();
OS_Sched(); /* See if this is new highest priority */
} else {
OS_EXIT_CRITICAL(); /* Task may be suspended */
}
return (OS_ERR_NONE);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* GET CURRENT SYSTEM TIME
*
* Description: This function is used by your application to obtain the current value of the 32-bit
* counter which keeps track of the number of clock ticks.
*
* Arguments : none
*
* Returns : The current value of OSTime
*********************************************************************************************************
*/
#if OS_TIME_GET_SET_EN > 0u
INT32U OSTimeGet (void)
{
INT32U ticks;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
OS_ENTER_CRITICAL();
ticks = OSTime;
OS_EXIT_CRITICAL();
return (ticks);
}
#endif
/*
*********************************************************************************************************
* SET SYSTEM CLOCK
*
* Description: This function sets the 32-bit counter which keeps track of the number of clock ticks.
*
* Arguments : ticks specifies the new value that OSTime needs to take.
*
* Returns : none
*********************************************************************************************************
*/
#if OS_TIME_GET_SET_EN > 0u
void OSTimeSet (INT32U ticks)
{
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
OS_ENTER_CRITICAL();
OSTime = ticks;
OS_EXIT_CRITICAL();
}
#endif

1073
UCOSII/CORE/os_tmr.c Normal file

File diff suppressed because it is too large Load Diff

38
UCOSII/CORE/ucos_ii.c Normal file
View File

@@ -0,0 +1,38 @@
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
*
* (c) Copyright 1992-2009, Micrium, Weston, FL
* All Rights Reserved
*
* File : uCOS_II.C
* By : Jean J. Labrosse
* Version : V2.91
*
* LICENSING TERMS:
* ---------------
* uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
* If you plan on using uC/OS-II in a commercial product you need to contact Micri<72>m to properly license
* its use in your product. We provide ALL the source code for your convenience and to help you experience
* uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a
* licensing fee.
*********************************************************************************************************
*/
#define OS_GLOBALS /* Declare GLOBAL variables */
#include <ucos_ii.h>
#define OS_MASTER_FILE /* Prevent the following files from including includes.h */
#include <os_core.c>
#include <os_flag.c>
#include <os_mbox.c>
#include <os_mem.c>
#include <os_mutex.c>
#include <os_q.c>
#include <os_sem.c>
#include <os_task.c>
#include <os_time.c>
#include <os_tmr.c>

1895
UCOSII/CORE/ucos_ii.h Normal file

File diff suppressed because it is too large Load Diff

89
UCOSII/PORT/os_cpu.h Normal file
View File

@@ -0,0 +1,89 @@
/************************ (C) COPYLEFT 2010 Leafgrass *************************
* File Name : os_cpu_c.c
* Author : Librae
* Date : 06/10/2010
* Description : <20><>COS-II<49><49>STM32<33>ϵ<EFBFBD><CFB5><EFBFBD>ֲ<EFBFBD><D6B2><EFBFBD><EFBFBD>C<EFBFBD><43><EFBFBD>Բ<EFBFBD><D4B2>֣<EFBFBD>
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͹<EFBFBD><CDB9>Ӻ<EFBFBD><D3BA><EFBFBD><EFBFBD><EFBFBD>
******************************************************************************/
#ifndef __OS_CPU_H__
#define __OS_CPU_H__
#ifdef OS_CPU_GLOBALS
#define OS_CPU_EXT
#else
#define OS_CPU_EXT extern
#endif
/******************************************************************************
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޹ص<DEB9><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
******************************************************************************/
typedef unsigned char BOOLEAN;
typedef unsigned char INT8U; /* Unsigned 8 bit quantity */
typedef signed char INT8S; /* Signed 8 bit quantity */
typedef unsigned short INT16U; /* Unsigned 16 bit quantity */
typedef signed short INT16S; /* Signed 16 bit quantity */
typedef unsigned int INT32U; /* Unsigned 32 bit quantity */
typedef signed int INT32S; /* Signed 32 bit quantity */
typedef float FP32; /* Single precision floating point*/
typedef double FP64; /* Double precision floating point*/
//STM32<33><32>32λλ<CEBB><CEBB><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD>OS_STK<54><4B>OS_CPU_SR<53><52>Ӧ<EFBFBD><D3A6>Ϊ32λ<32><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide*/
typedef unsigned int OS_CPU_SR; /* Define size of CPU status register*/
/*
*******************************************************************************
* Cortex M3
* Critical Section Management
*******************************************************************************
*/
/*
*******************************************************************************
* ARM Miscellaneous
*******************************************************************************
*/
//<2F><><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
//CM3<4D><33><><D5BB><EFBFBD>ɸߵ<C9B8>ַ<EFBFBD><D6B7><EFBFBD>͵<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD>OS_STK_GROWTH<54><48><EFBFBD><EFBFBD>Ϊ1
#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on ARM */
//<2F><><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD>,<2C>ɻ<EFBFBD><C9BB><EFBFBD>ʵ<EFBFBD><CAB5>.
#define OS_TASK_SW() OSCtxSw()
/*
*******************************************************************************
* PROTOTYPES
* (see OS_CPU_A.ASM)
*******************************************************************************
*/
//OS_CRITICAL_METHOD = 1 :ֱ<><D6B1>ʹ<EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>ж<EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>ʵ<EFBFBD>ֺ<EFBFBD>
//OS_CRITICAL_METHOD = 2 :<3A><><EFBFBD>ö<EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>ͻָ<CDBB>CPU<50><55>״̬
//OS_CRITICAL_METHOD = 3 :<3A><><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><D5B9><EFBFBD>ܻ<EFBFBD><DCBB>ó<EFBFBD><C3B3><EFBFBD>״̬<D7B4>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ھֲ<DABE><D6B2><EFBFBD><EFBFBD><EFBFBD>cpu_sr
#define OS_CRITICAL_METHOD 3 //<2F><><EFBFBD><EFBFBD><EFBFBD>ٽ<EFBFBD><D9BD>εķ<CEB5><C4B7><EFBFBD>
#if OS_CRITICAL_METHOD == 3
#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();}
#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);}
#endif
void OSCtxSw(void);
void OSIntCtxSw(void);
void OSStartHighRdy(void);
void OSPendSV(void);
#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */
OS_CPU_SR OS_CPU_SR_Save(void);
void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
#endif
OS_CPU_EXT INT32U OSInterrputSum;
#endif
/************************ (C) COPYLEFT 2010 Leafgrass ************************/

197
UCOSII/PORT/os_cpu_a.asm Normal file
View File

@@ -0,0 +1,197 @@
;/*********************** (C) COPYRIGHT 2010 Libraworks *************************
;* File Name : os_cpu_a.asm
;* Author : Librae
;* Version : V1.0
;* Date : 06/10/2010
;* Description : <20><>COS-II asm port for STM32
;*******************************************************************************/
IMPORT OSRunning ; External references
IMPORT OSPrioCur
IMPORT OSPrioHighRdy
IMPORT OSTCBCur
IMPORT OSTCBHighRdy
IMPORT OSIntNesting
IMPORT OSIntExit
IMPORT OSTaskSwHook
EXPORT OSStartHighRdy
EXPORT OSCtxSw
EXPORT OSIntCtxSw
EXPORT OS_CPU_SR_Save ; Functions declared in this file
EXPORT OS_CPU_SR_Restore
EXPORT PendSV_Handler
NVIC_INT_CTRL EQU 0xE000ED04 ; <20>жϿ<D0B6><CFBF>ƼĴ<C6BC><C4B4><EFBFBD>
NVIC_SYSPRI2 EQU 0xE000ED20 ; ϵͳ<CFB5><CDB3><EFBFBD>ȼ<EFBFBD><C8BC>Ĵ<EFBFBD><C4B4><EFBFBD>(2)
NVIC_PENDSV_PRI EQU 0xFFFF0000 ; PendSV<53>жϺ<D0B6>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
; (<28><>Ϊ<EFBFBD><CEAA><EFBFBD>ͣ<EFBFBD>0xff).
NVIC_PENDSVSET EQU 0x10000000 ; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϵ<D0B6>ֵ.
PRESERVE8
AREA |.text|, CODE, READONLY
THUMB
;********************************************************************************************************
; CRITICAL SECTION METHOD 3 FUNCTIONS
;
; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you
; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to
; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr'
; into the CPU's status register.
;
; Prototypes : OS_CPU_SR OS_CPU_SR_Save(void);
; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
;
;
; Note(s) : 1) These functions are used in general like this:
;
; void Task (void *p_arg)
; {
; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
; OS_CPU_SR cpu_sr;
; #endif
;
; :
; :
; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */
; :
; :
; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */
; :
; :
; }
;********************************************************************************************************
OS_CPU_SR_Save
MRS R0, PRIMASK ;<3B><>ȡPRIMASK<53><4B>R0,R0Ϊ<30><CEAA><EFBFBD><EFBFBD>ֵ
CPSID I ;PRIMASK=1,<2C><><EFBFBD>ж<EFBFBD>(NMI<4D><49>Ӳ<EFBFBD><D3B2>FAULT<4C><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ)
BX LR ;<3B><><EFBFBD><EFBFBD>
OS_CPU_SR_Restore
MSR PRIMASK, R0 ;<3B><>ȡR0<52><30>PRIMASK<53><4B>,R0Ϊ<30><CEAA><EFBFBD><EFBFBD>
BX LR ;<3B><><EFBFBD><EFBFBD>
;/**************************************************************************************
;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: OSStartHighRdy
;*
;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: ʹ<>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
;*
;* <20><> <20><>: None
;*
;* <20><> <20><> ֵ: None
;**************************************************************************************/
OSStartHighRdy
LDR R4, =NVIC_SYSPRI2 ; set the PendSV exception priority
LDR R5, =NVIC_PENDSV_PRI
STR R5, [R4]
MOV R4, #0 ; set the PSP to 0 for initial context switch call
MSR PSP, R4
LDR R4, =OSRunning ; OSRunning = TRUE
MOV R5, #1
STRB R5, [R4]
;<3B>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
LDR R4, =NVIC_INT_CTRL ;rigger the PendSV exception (causes context switch)
LDR R5, =NVIC_PENDSVSET
STR R5, [R4]
CPSIE I ;enable interrupts at processor level
OSStartHang
B OSStartHang ;should never get here
;/**************************************************************************************
;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: OSCtxSw
;*
;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>
;*
;* <20><> <20><>: None
;*
;* <20><> <20><> ֵ: None
;***************************************************************************************/
OSCtxSw
PUSH {R4, R5}
LDR R4, =NVIC_INT_CTRL ;<3B><><EFBFBD><EFBFBD>PendSV<53>쳣 (causes context switch)
LDR R5, =NVIC_PENDSVSET
STR R5, [R4]
POP {R4, R5}
BX LR
;/**************************************************************************************
;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: OSIntCtxSw
;*
;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20>жϼ<D0B6><CFBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>
;*
;* <20><> <20><>: None
;*
;* <20><> <20><> ֵ: None
;***************************************************************************************/
OSIntCtxSw
PUSH {R4, R5}
LDR R4, =NVIC_INT_CTRL ;<3B><><EFBFBD><EFBFBD>PendSV<53>쳣 (causes context switch)
LDR R5, =NVIC_PENDSVSET
STR R5, [R4]
POP {R4, R5}
BX LR
NOP
;/**************************************************************************************
;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: OSPendSV
;*
;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: OSPendSV is used to cause a context switch.
;*
;* <20><> <20><>: None
;*
;* <20><> <20><> ֵ: None
;***************************************************************************************/
PendSV_Handler
CPSID I ; Prevent interruption during context switch
MRS R0, PSP ; PSP is process stack pointer <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PSP<53><50>ջ,<2C><><EFBFBD><EFBFBD><EFBFBD>Ժ<EFBFBD><D4BA>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>,<2C>ο<EFBFBD>CM3Ȩ<33><C8A8><EFBFBD>е<EFBFBD>˫<EFBFBD><CBAB>ջ-<2D>ײ<EFBFBD>ע
CBZ R0, PendSV_Handler_Nosave ; Skip register save the first time
SUBS R0, R0, #0x20 ; Save remaining regs r4-11 on process stack
STM R0, {R4-R11}
LDR R1, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP;
LDR R1, [R1]
STR R0, [R1] ; R0 is SP of process being switched out
; At this point, entire context of process has been saved
PendSV_Handler_Nosave
PUSH {R14} ; Save LR exc_return value
LDR R0, =OSTaskSwHook ; OSTaskSwHook();
BLX R0
POP {R14}
LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy;
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy;
LDR R1, =OSTCBHighRdy
LDR R2, [R1]
STR R2, [R0]
LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
LDM R0, {R4-R11} ; Restore r4-11 from new process stack
ADDS R0, R0, #0x20
MSR PSP, R0 ; Load PSP with new process SP
ORR LR, LR, #0x04 ; Ensure exception return uses process stack
CPSIE I
BX LR ; Exception return will restore remaining context
end

312
UCOSII/PORT/os_cpu_c.c Normal file
View File

@@ -0,0 +1,312 @@
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
*
*
* (c) Copyright 2006, Micrium, Weston, FL
* All Rights Reserved
*
* ARM Cortex-M3 Port
*
* File : OS_CPU_C.C
* Version : V2.86
* By : Jean J. Labrosse
*
* For : ARMv7M Cortex-M3
* Mode : Thumb2
* Toolchain : RealView Development Suite
* RealView Microcontroller Development Kit (MDK)
* ARM Developer Suite (ADS)
* Keil uVision
*********************************************************************************************************
*/
#define OS_CPU_GLOBALS
#include "includes.h"
/*
*********************************************************************************************************
* LOCAL VARIABLES
*********************************************************************************************************
*/
#if OS_TMR_EN > 0
static INT16U OSTmrCtr;
#endif
/*
*********************************************************************************************************
* OS INITIALIZATION HOOK
* (BEGINNING)
*
* Description: This function is called by OSInit() at the beginning of OSInit().
*
* Arguments : none
*
* Note(s) : 1) Interrupts should be disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
void OSInitHookBegin (void)
{
#if OS_TMR_EN > 0
OSTmrCtr = 0;
#endif
}
#endif
/*
*********************************************************************************************************
* OS INITIALIZATION HOOK
* (END)
*
* Description: This function is called by OSInit() at the end of OSInit().
*
* Arguments : none
*
* Note(s) : 1) Interrupts should be disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
void OSInitHookEnd (void)
{
}
#endif
/*
*********************************************************************************************************
* TASK CREATION HOOK
*
* Description: This function is called when a task is created.
*
* Arguments : ptcb is a pointer to the task control block of the task being created.
*
* Note(s) : 1) Interrupts are disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0
void OSTaskCreateHook (OS_TCB *ptcb)
{
#if OS_APP_HOOKS_EN > 0
App_TaskCreateHook(ptcb);
#else
(void)ptcb; /* Prevent compiler warning */
#endif
}
#endif
/*
*********************************************************************************************************
* TASK DELETION HOOK
*
* Description: This function is called when a task is deleted.
*
* Arguments : ptcb is a pointer to the task control block of the task being deleted.
*
* Note(s) : 1) Interrupts are disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0
void OSTaskDelHook (OS_TCB *ptcb)
{
#if OS_APP_HOOKS_EN > 0
App_TaskDelHook(ptcb);
#else
(void)ptcb; /* Prevent compiler warning */
#endif
}
#endif
/*
*********************************************************************************************************
* IDLE TASK HOOK
*
* Description: This function is called by the idle task. This hook has been added to allow you to do
* such things as STOP the CPU to conserve power.
*
* Arguments : none
*
* Note(s) : 1) Interrupts are enabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251
void OSTaskIdleHook (void)
{
#if OS_APP_HOOKS_EN > 0
App_TaskIdleHook();
#endif
}
#endif
/*
*********************************************************************************************************
* STATISTIC TASK HOOK
*
* Description: This function is called every second by uC/OS-II's statistics task. This allows your
* application to add functionality to the statistics task.
*
* Arguments : none
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0
void OSTaskStatHook (void)
{
#if OS_APP_HOOKS_EN > 0
App_TaskStatHook();
#endif
}
#endif
/*
*********************************************************************************************************
* INITIALIZE A TASK'S STACK
*
* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
* stack frame of the task being created. This function is highly processor specific.
*
* Arguments : task is a pointer to the task code
*
* p_arg is a pointer to a user supplied data area that will be passed to the task
* when the task first executes.
*
* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to
* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then
* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if
* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address
* of the stack.
*
* opt specifies options that can be used to alter the behavior of OSTaskStkInit().
* (see uCOS_II.H for OS_TASK_OPT_xxx).
*
* Returns : Always returns the location of the new top-of-stack once the processor registers have
* been placed on the stack in the proper order.
*
* Note(s) : 1) Interrupts are enabled when your task starts executing.
* 2) All tasks run in Thread mode, using process stack.
*********************************************************************************************************
*/
OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
{
OS_STK *stk;
(void)opt; /* 'opt' is not used, prevent warning */
stk = ptos; /* Load stack pointer */
/* Registers stacked as if auto-saved on exception */
*(stk) = (INT32U)0x01000000L; /* xPSR */
*(--stk) = (INT32U)task; /* Entry Point */
*(--stk) = (INT32U)0xFFFFFFFEL; /* R14 (LR) (init value will cause fault if ever used)*/
*(--stk) = (INT32U)0x12121212L; /* R12 */
*(--stk) = (INT32U)0x03030303L; /* R3 */
*(--stk) = (INT32U)0x02020202L; /* R2 */
*(--stk) = (INT32U)0x01010101L; /* R1 */
*(--stk) = (INT32U)p_arg; /* R0 : argument */
/* Remaining registers saved on process stack */
*(--stk) = (INT32U)0x11111111L; /* R11 */
*(--stk) = (INT32U)0x10101010L; /* R10 */
*(--stk) = (INT32U)0x09090909L; /* R9 */
*(--stk) = (INT32U)0x08080808L; /* R8 */
*(--stk) = (INT32U)0x07070707L; /* R7 */
*(--stk) = (INT32U)0x06060606L; /* R6 */
*(--stk) = (INT32U)0x05050505L; /* R5 */
*(--stk) = (INT32U)0x04040404L; /* R4 */
return (stk);
}
/*
*********************************************************************************************************
* TASK SWITCH HOOK
*
* Description: This function is called when a task switch is performed. This allows you to perform other
* operations during a context switch.
*
* Arguments : none
*
* Note(s) : 1) Interrupts are disabled during this call.
* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that
* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the
* task being switched out (i.e. the preempted task).
*********************************************************************************************************
*/
#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0)
void OSTaskSwHook (void)
{
#if OS_APP_HOOKS_EN > 0
App_TaskSwHook();
#endif
}
#endif
/*
*********************************************************************************************************
* OS_TCBInit() HOOK
*
* Description: This function is called by OS_TCBInit() after setting up most of the TCB.
*
* Arguments : ptcb is a pointer to the TCB of the task being created.
*
* Note(s) : 1) Interrupts may or may not be ENABLED during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
void OSTCBInitHook (OS_TCB *ptcb)
{
#if OS_APP_HOOKS_EN > 0
App_TCBInitHook(ptcb);
#else
(void)ptcb; /* Prevent compiler warning */
#endif
}
#endif
/*
*********************************************************************************************************
* TICK HOOK
*
* Description: This function is called every tick.
*
* Arguments : none
*
* Note(s) : 1) Interrupts may or may not be ENABLED during this call.
*********************************************************************************************************
*/
#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0)
void OSTimeTickHook (void)
{
#if OS_APP_HOOKS_EN > 0
App_TimeTickHook();
#endif
#if OS_TMR_EN > 0
OSTmrCtr++;
if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) {
OSTmrCtr = 0;
OSTmrSignal();
}
#endif
}
#endif
#if OS_CPU_HOOKS_EN > 0u && OS_VERSION > 290u
void OSTaskReturnHook(OS_TCB *ptcb)
{
(void)ptcb;
}
#endif
/*----------------------- (C) COPYRIGHT @ 2012 liycobl ----------------- end of file -----------------*/

265
UCOSII/PORT/os_dbg.c Normal file
View File

@@ -0,0 +1,265 @@
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
* DEBUGGER CONSTANTS
*
* (c) Copyright 2006, Micrium, Weston, FL
* All Rights Reserved
*
* ARM Cortex-M3 Port
*
* File : OS_DBG.C
* Version : V2.86
* By : Jean J. Labrosse
*
* For : ARMv7M Cortex-M3
* Mode : Thumb2
* Toolchain : RealView Development Suite
* RealView Microcontroller Development Kit (MDK)
* ARM Developer Suite (ADS)
* Keil uVision
*********************************************************************************************************
*/
#include <ucos_ii.h>
#define OS_COMPILER_OPT
/*
*********************************************************************************************************
* DEBUG DATA
*********************************************************************************************************
*/
OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */
#if OS_DEBUG_EN > 0
OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */
OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */
OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */
OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN;
#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0)
OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */
OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */
#else
OS_COMPILER_OPT INT16U const OSEventSize = 0;
OS_COMPILER_OPT INT16U const OSEventTblSize = 0;
#endif
OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN;
#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */
OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */
OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */
#else
OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0;
OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0;
OS_COMPILER_OPT INT16U const OSFlagWidth = 0;
#endif
OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS;
OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */
OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO;
OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN;
OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN;
OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */
OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */
#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */
OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl);
#else
OS_COMPILER_OPT INT16U const OSMemSize = 0;
OS_COMPILER_OPT INT16U const OSMemTblSize = 0;
#endif
OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN;
OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */
OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN;
OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */
#if (OS_Q_EN > 0) && (OS_MAX_QS > 0)
OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */
#else
OS_COMPILER_OPT INT16U const OSQSize = 0;
#endif
OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */
OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN;
OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */
OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN;
OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN;
OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN;
OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE;
OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN;
OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */
OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */
OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN;
OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE;
OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN;
OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN;
OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */
OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */
OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC;
OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN;
OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION;
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* DEBUG DATA
* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II
*********************************************************************************************************
*/
#if OS_DEBUG_EN > 0
OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr)
#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0)
+ sizeof(OSEventFreeList)
+ sizeof(OSEventTbl)
#endif
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
+ sizeof(OSFlagTbl)
+ sizeof(OSFlagFreeList)
#endif
#if OS_TASK_STAT_EN > 0
+ sizeof(OSCPUUsage)
+ sizeof(OSIdleCtrMax)
+ sizeof(OSIdleCtrRun)
+ sizeof(OSStatRdy)
+ sizeof(OSTaskStatStk)
#endif
#if OS_TICK_STEP_EN > 0
+ sizeof(OSTickStepState)
#endif
#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
+ sizeof(OSMemFreeList)
+ sizeof(OSMemTbl)
#endif
#if (OS_Q_EN > 0) && (OS_MAX_QS > 0)
+ sizeof(OSQFreeList)
+ sizeof(OSQTbl)
#endif
#if OS_TIME_GET_SET_EN > 0
+ sizeof(OSTime)
#endif
+ sizeof(OSIntNesting)
+ sizeof(OSLockNesting)
+ sizeof(OSPrioCur)
+ sizeof(OSPrioHighRdy)
+ sizeof(OSRdyGrp)
+ sizeof(OSRdyTbl)
+ sizeof(OSRunning)
+ sizeof(OSTaskCtr)
+ sizeof(OSIdleCtr)
+ sizeof(OSTaskIdleStk)
+ sizeof(OSTCBCur)
+ sizeof(OSTCBFreeList)
+ sizeof(OSTCBHighRdy)
+ sizeof(OSTCBList)
+ sizeof(OSTCBPrioTbl)
+ sizeof(OSTCBTbl);
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* OS DEBUG INITIALIZAZTION
*
* Description: This function is used to make sure that debug variables that are unused in the application
* are not optimized away. This function might not be necessary for all compilers. In this
* case, you should simply DELETE the code in this function while still leaving the declaration
* of the function itself.
*
* Arguments : none
*
* Returns : none
*
* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out
* the 'const' variables which are declared in this file.
*********************************************************************************************************
*/
#if OS_VERSION >= 270 && OS_DEBUG_EN > 0
void OSDebugInit (void)
{
void *ptemp;
ptemp = (void *)&OSDebugEn;
ptemp = (void *)&OSEndiannessTest;
ptemp = (void *)&OSEventMax;
ptemp = (void *)&OSEventNameSize;
ptemp = (void *)&OSEventEn;
ptemp = (void *)&OSEventSize;
ptemp = (void *)&OSEventTblSize;
ptemp = (void *)&OSFlagEn;
ptemp = (void *)&OSFlagGrpSize;
ptemp = (void *)&OSFlagNodeSize;
ptemp = (void *)&OSFlagWidth;
ptemp = (void *)&OSFlagMax;
ptemp = (void *)&OSFlagNameSize;
ptemp = (void *)&OSLowestPrio;
ptemp = (void *)&OSMboxEn;
ptemp = (void *)&OSMemEn;
ptemp = (void *)&OSMemMax;
ptemp = (void *)&OSMemNameSize;
ptemp = (void *)&OSMemSize;
ptemp = (void *)&OSMemTblSize;
ptemp = (void *)&OSMutexEn;
ptemp = (void *)&OSPtrSize;
ptemp = (void *)&OSQEn;
ptemp = (void *)&OSQMax;
ptemp = (void *)&OSQSize;
ptemp = (void *)&OSRdyTblSize;
ptemp = (void *)&OSSemEn;
ptemp = (void *)&OSStkWidth;
ptemp = (void *)&OSTaskCreateEn;
ptemp = (void *)&OSTaskCreateExtEn;
ptemp = (void *)&OSTaskDelEn;
ptemp = (void *)&OSTaskIdleStkSize;
ptemp = (void *)&OSTaskProfileEn;
ptemp = (void *)&OSTaskMax;
ptemp = (void *)&OSTaskNameSize;
ptemp = (void *)&OSTaskStatEn;
ptemp = (void *)&OSTaskStatStkSize;
ptemp = (void *)&OSTaskStatStkChkEn;
ptemp = (void *)&OSTaskSwHookEn;
ptemp = (void *)&OSTCBPrioTblMax;
ptemp = (void *)&OSTCBSize;
ptemp = (void *)&OSTicksPerSec;
ptemp = (void *)&OSTimeTickHookEn;
ptemp = (void *)&OSVersionNbr;
ptemp = (void *)&OSDataSize;
ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */
}
#endif

314
UCOSII/PORT/os_dbg_r.c Normal file
View File

@@ -0,0 +1,314 @@
/*
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
* DEBUGGER CONSTANTS
*
* (c) Copyright 1992-2009, Micrium, Weston, FL
* All Rights Reserved
*
* File : OS_DBG.C
* By : Jean J. Labrosse
* Version : V2.91
*
* LICENSING TERMS:
* ---------------
* uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
* If you plan on using uC/OS-II in a commercial product you need to contact Micri<72>m to properly license
* its use in your product. We provide ALL the source code for your convenience and to help you experience
* uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a
* licensing fee.
*********************************************************************************************************
*/
#include <ucos_ii.h>
/*
*********************************************************************************************************
* DEBUG DATA
*********************************************************************************************************
*/
INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */
#if OS_DEBUG_EN > 0u
INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */
INT16U const OSEventEn = OS_EVENT_EN;
INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */
INT16U const OSEventNameEn = OS_EVENT_NAME_EN;
#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u)
INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */
INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */
#else
INT16U const OSEventSize = 0u;
INT16U const OSEventTblSize = 0u;
#endif
INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN;
INT16U const OSFlagEn = OS_FLAG_EN;
#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */
INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */
INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */
#else
INT16U const OSFlagGrpSize = 0u;
INT16U const OSFlagNodeSize = 0u;
INT16U const OSFlagWidth = 0u;
#endif
INT16U const OSFlagMax = OS_MAX_FLAGS;
INT16U const OSFlagNameEn = OS_FLAG_NAME_EN;
INT16U const OSLowestPrio = OS_LOWEST_PRIO;
INT16U const OSMboxEn = OS_MBOX_EN;
INT16U const OSMemEn = OS_MEM_EN;
INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */
INT16U const OSMemNameEn = OS_MEM_NAME_EN;
#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */
INT16U const OSMemTblSize = sizeof(OSMemTbl);
#else
INT16U const OSMemSize = 0u;
INT16U const OSMemTblSize = 0u;
#endif
INT16U const OSMutexEn = OS_MUTEX_EN;
INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */
INT16U const OSQEn = OS_Q_EN;
INT16U const OSQMax = OS_MAX_QS; /* Number of queues */
#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */
#else
INT16U const OSQSize = 0u;
#endif
INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */
INT16U const OSSemEn = OS_SEM_EN;
INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */
INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN;
INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN;
INT16U const OSTaskDelEn = OS_TASK_DEL_EN;
INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE;
INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN;
INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */
INT16U const OSTaskNameEn = OS_TASK_NAME_EN;
INT16U const OSTaskStatEn = OS_TASK_STAT_EN;
INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE;
INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN;
INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN;
INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE;
INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */
INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */
INT16U const OSTicksPerSec = OS_TICKS_PER_SEC;
INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN;
INT16U const OSVersionNbr = OS_VERSION;
INT16U const OSTmrEn = OS_TMR_EN;
INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX;
INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN;
INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE;
INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC;
#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u)
INT16U const OSTmrSize = sizeof(OS_TMR);
INT16U const OSTmrTblSize = sizeof(OSTmrTbl);
INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL);
INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl);
#else
INT16U const OSTmrSize = 0u;
INT16U const OSTmrTblSize = 0u;
INT16U const OSTmrWheelSize = 0u;
INT16U const OSTmrWheelTblSize = 0u;
#endif
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* DEBUG DATA
* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II
*********************************************************************************************************
*/
#if OS_DEBUG_EN > 0u
INT16U const OSDataSize = sizeof(OSCtxSwCtr)
#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u)
+ sizeof(OSEventFreeList)
+ sizeof(OSEventTbl)
#endif
#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
+ sizeof(OSFlagTbl)
+ sizeof(OSFlagFreeList)
#endif
#if OS_TASK_STAT_EN > 0u
+ sizeof(OSCPUUsage)
+ sizeof(OSIdleCtrMax)
+ sizeof(OSIdleCtrRun)
+ sizeof(OSStatRdy)
+ sizeof(OSTaskStatStk)
#endif
#if OS_TICK_STEP_EN > 0u
+ sizeof(OSTickStepState)
#endif
#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
+ sizeof(OSMemFreeList)
+ sizeof(OSMemTbl)
#endif
#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
+ sizeof(OSQFreeList)
+ sizeof(OSQTbl)
#endif
#if OS_TIME_GET_SET_EN > 0u
+ sizeof(OSTime)
#endif
#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u)
+ sizeof(OSTmrFree)
+ sizeof(OSTmrUsed)
+ sizeof(OSTmrTime)
+ sizeof(OSTmrSem)
+ sizeof(OSTmrSemSignal)
+ sizeof(OSTmrTbl)
+ sizeof(OSTmrFreeList)
+ sizeof(OSTmrTaskStk)
+ sizeof(OSTmrWheelTbl)
#endif
+ sizeof(OSIntNesting)
+ sizeof(OSLockNesting)
+ sizeof(OSPrioCur)
+ sizeof(OSPrioHighRdy)
+ sizeof(OSRdyGrp)
+ sizeof(OSRdyTbl)
+ sizeof(OSRunning)
+ sizeof(OSTaskCtr)
+ sizeof(OSIdleCtr)
+ sizeof(OSTaskIdleStk)
+ sizeof(OSTCBCur)
+ sizeof(OSTCBFreeList)
+ sizeof(OSTCBHighRdy)
+ sizeof(OSTCBList)
+ sizeof(OSTCBPrioTbl)
+ sizeof(OSTCBTbl);
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* OS DEBUG INITIALIZATION
*
* Description: This function is used to make sure that debug variables that are unused in the application
* are not optimized away. This function might not be necessary for all compilers. In this
* case, you should simply DELETE the code in this function while still leaving the declaration
* of the function itself.
*
* Arguments : none
*
* Returns : none
*
* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out
* the 'const' variables which are declared in this file.
* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function
* if your compiler DOES NOT optimize out the 'const' variables above.
*********************************************************************************************************
*/
#if OS_DEBUG_EN > 0u
void OSDebugInit (void)
{
void const *ptemp;
ptemp = (void const *)&OSDebugEn;
ptemp = (void const *)&OSEndiannessTest;
ptemp = (void const *)&OSEventMax;
ptemp = (void const *)&OSEventNameEn;
ptemp = (void const *)&OSEventEn;
ptemp = (void const *)&OSEventSize;
ptemp = (void const *)&OSEventTblSize;
ptemp = (void const *)&OSEventMultiEn;
ptemp = (void const *)&OSFlagEn;
ptemp = (void const *)&OSFlagGrpSize;
ptemp = (void const *)&OSFlagNodeSize;
ptemp = (void const *)&OSFlagWidth;
ptemp = (void const *)&OSFlagMax;
ptemp = (void const *)&OSFlagNameEn;
ptemp = (void const *)&OSLowestPrio;
ptemp = (void const *)&OSMboxEn;
ptemp = (void const *)&OSMemEn;
ptemp = (void const *)&OSMemMax;
ptemp = (void const *)&OSMemNameEn;
ptemp = (void const *)&OSMemSize;
ptemp = (void const *)&OSMemTblSize;
ptemp = (void const *)&OSMutexEn;
ptemp = (void const *)&OSPtrSize;
ptemp = (void const *)&OSQEn;
ptemp = (void const *)&OSQMax;
ptemp = (void const *)&OSQSize;
ptemp = (void const *)&OSRdyTblSize;
ptemp = (void const *)&OSSemEn;
ptemp = (void const *)&OSStkWidth;
ptemp = (void const *)&OSTaskCreateEn;
ptemp = (void const *)&OSTaskCreateExtEn;
ptemp = (void const *)&OSTaskDelEn;
ptemp = (void const *)&OSTaskIdleStkSize;
ptemp = (void const *)&OSTaskProfileEn;
ptemp = (void const *)&OSTaskMax;
ptemp = (void const *)&OSTaskNameEn;
ptemp = (void const *)&OSTaskStatEn;
ptemp = (void const *)&OSTaskStatStkSize;
ptemp = (void const *)&OSTaskStatStkChkEn;
ptemp = (void const *)&OSTaskSwHookEn;
ptemp = (void const *)&OSTCBPrioTblMax;
ptemp = (void const *)&OSTCBSize;
ptemp = (void const *)&OSTicksPerSec;
ptemp = (void const *)&OSTimeTickHookEn;
#if OS_TMR_EN > 0u
ptemp = (void const *)&OSTmrTbl[0];
ptemp = (void const *)&OSTmrWheelTbl[0];
ptemp = (void const *)&OSTmrEn;
ptemp = (void const *)&OSTmrCfgMax;
ptemp = (void const *)&OSTmrCfgNameEn;
ptemp = (void const *)&OSTmrCfgWheelSize;
ptemp = (void const *)&OSTmrCfgTicksPerSec;
ptemp = (void const *)&OSTmrSize;
ptemp = (void const *)&OSTmrTblSize;
ptemp = (void const *)&OSTmrWheelSize;
ptemp = (void const *)&OSTmrWheelTblSize;
#endif
ptemp = (void const *)&OSVersionNbr;
ptemp = (void const *)&OSDataSize;
ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */
}
#endif

File diff suppressed because one or more lines are too long

View File

@@ -775,14 +775,233 @@
</Group>
<Group>
<GroupName>ReadMe</GroupName>
<tvExp>1</tvExp>
<GroupName>UCOSII-CORE</GroupName>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>39</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\UCOSII\CORE\os_core.c</PathWithFileName>
<FilenameWithoutPath>os_core.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>40</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\UCOSII\CORE\os_flag.c</PathWithFileName>
<FilenameWithoutPath>os_flag.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>41</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\UCOSII\CORE\os_mbox.c</PathWithFileName>
<FilenameWithoutPath>os_mbox.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>42</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\UCOSII\CORE\os_mem.c</PathWithFileName>
<FilenameWithoutPath>os_mem.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>43</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\UCOSII\CORE\os_mutex.c</PathWithFileName>
<FilenameWithoutPath>os_mutex.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>44</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\UCOSII\CORE\os_q.c</PathWithFileName>
<FilenameWithoutPath>os_q.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>45</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\UCOSII\CORE\os_sem.c</PathWithFileName>
<FilenameWithoutPath>os_sem.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>46</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\UCOSII\CORE\os_task.c</PathWithFileName>
<FilenameWithoutPath>os_task.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>47</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\UCOSII\CORE\os_time.c</PathWithFileName>
<FilenameWithoutPath>os_time.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>48</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\UCOSII\CORE\os_tmr.c</PathWithFileName>
<FilenameWithoutPath>os_tmr.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>UCOSII-PORT</GroupName>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>49</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\UCOSII\PORT\os_cpu_c.c</PathWithFileName>
<FilenameWithoutPath>os_cpu_c.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>50</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\UCOSII\PORT\os_cpu.h</PathWithFileName>
<FilenameWithoutPath>os_cpu.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>51</FileNumber>
<FileType>2</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\UCOSII\PORT\os_cpu_a.asm</PathWithFileName>
<FilenameWithoutPath>os_cpu_a.asm</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>UCOSII-CONFIG</GroupName>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>52</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\UCOSII\CONFIG\includes.h</PathWithFileName>
<FilenameWithoutPath>includes.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>53</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\UCOSII\CONFIG\os_cfg.h</PathWithFileName>
<FilenameWithoutPath>os_cfg.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>ReadMe</GroupName>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>54</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<Focus>0</Focus>

View File

@@ -373,7 +373,7 @@
<MiscControls></MiscControls>
<Define>STM32F10X_HD,USE_STDPERIPH_DRIVER</Define>
<Undefine></Undefine>
<IncludePath>..\USER;..\SYSTEM\delay;..\SYSTEM\sys;..\SYSTEM\usart;..\STM32F10x_FWLib\inc;..\CORE;..\HARDWARE\GPIO_Motor;..\HARDWARE\TIMER;..\HARDWARE\KEY;..\HARDWARE\EXTI;..\HARDWARE\PWM;..\HARDWARE\IronHand;..\HARDWARE\MOTOR_CTRL;..\HARDWARE\USART</IncludePath>
<IncludePath>..\USER;..\SYSTEM\delay;..\SYSTEM\sys;..\SYSTEM\usart;..\STM32F10x_FWLib\inc;..\CORE;..\HARDWARE\GPIO_Motor;..\HARDWARE\TIMER;..\HARDWARE\KEY;..\HARDWARE\EXTI;..\HARDWARE\PWM;..\HARDWARE\IronHand;..\HARDWARE\MOTOR_CTRL;..\HARDWARE\USART;..\UCOSII\CONFIG;..\UCOSII\CORE;..\UCOSII\PORT</IncludePath>
</VariousControls>
</Cads>
<Aads>
@@ -628,6 +628,96 @@
</File>
</Files>
</Group>
<Group>
<GroupName>UCOSII-CORE</GroupName>
<Files>
<File>
<FileName>os_core.c</FileName>
<FileType>1</FileType>
<FilePath>..\UCOSII\CORE\os_core.c</FilePath>
</File>
<File>
<FileName>os_flag.c</FileName>
<FileType>1</FileType>
<FilePath>..\UCOSII\CORE\os_flag.c</FilePath>
</File>
<File>
<FileName>os_mbox.c</FileName>
<FileType>1</FileType>
<FilePath>..\UCOSII\CORE\os_mbox.c</FilePath>
</File>
<File>
<FileName>os_mem.c</FileName>
<FileType>1</FileType>
<FilePath>..\UCOSII\CORE\os_mem.c</FilePath>
</File>
<File>
<FileName>os_mutex.c</FileName>
<FileType>1</FileType>
<FilePath>..\UCOSII\CORE\os_mutex.c</FilePath>
</File>
<File>
<FileName>os_q.c</FileName>
<FileType>1</FileType>
<FilePath>..\UCOSII\CORE\os_q.c</FilePath>
</File>
<File>
<FileName>os_sem.c</FileName>
<FileType>1</FileType>
<FilePath>..\UCOSII\CORE\os_sem.c</FilePath>
</File>
<File>
<FileName>os_task.c</FileName>
<FileType>1</FileType>
<FilePath>..\UCOSII\CORE\os_task.c</FilePath>
</File>
<File>
<FileName>os_time.c</FileName>
<FileType>1</FileType>
<FilePath>..\UCOSII\CORE\os_time.c</FilePath>
</File>
<File>
<FileName>os_tmr.c</FileName>
<FileType>1</FileType>
<FilePath>..\UCOSII\CORE\os_tmr.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>UCOSII-PORT</GroupName>
<Files>
<File>
<FileName>os_cpu_c.c</FileName>
<FileType>1</FileType>
<FilePath>..\UCOSII\PORT\os_cpu_c.c</FilePath>
</File>
<File>
<FileName>os_cpu.h</FileName>
<FileType>5</FileType>
<FilePath>..\UCOSII\PORT\os_cpu.h</FilePath>
</File>
<File>
<FileName>os_cpu_a.asm</FileName>
<FileType>2</FileType>
<FilePath>..\UCOSII\PORT\os_cpu_a.asm</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>UCOSII-CONFIG</GroupName>
<Files>
<File>
<FileName>includes.h</FileName>
<FileType>5</FileType>
<FilePath>..\UCOSII\CONFIG\includes.h</FilePath>
</File>
<File>
<FileName>os_cfg.h</FileName>
<FileType>5</FileType>
<FilePath>..\UCOSII\CONFIG\os_cfg.h</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>ReadMe</GroupName>
<Files>

File diff suppressed because it is too large Load Diff

531
USER/Listings/os_cpu_a.lst Normal file
View File

@@ -0,0 +1,531 @@
ARM Macro Assembler Page 1
1 00000000 ;/*********************** (C) COPYRIGHT 2010 Libraworks
*************************
2 00000000 ;* File Name : os_cpu_a.asm
3 00000000 ;* Author : Librae
4 00000000 ;* Version : V1.0
5 00000000 ;* Date : 06/10/2010
6 00000000 ;* Description : <20><>COS-II asm port for STM32
7 00000000 ;*******************************************************
************************/
8 00000000
9 00000000 IMPORT OSRunning ; External referenc
es
10 00000000 IMPORT OSPrioCur
11 00000000 IMPORT OSPrioHighRdy
12 00000000 IMPORT OSTCBCur
13 00000000 IMPORT OSTCBHighRdy
14 00000000 IMPORT OSIntNesting
15 00000000 IMPORT OSIntExit
16 00000000 IMPORT OSTaskSwHook
17 00000000
18 00000000 EXPORT OSStartHighRdy
19 00000000 EXPORT OSCtxSw
20 00000000 EXPORT OSIntCtxSw
21 00000000 EXPORT OS_CPU_SR_Save ; Functions decl
ared in this file
22 00000000 EXPORT OS_CPU_SR_Restore
23 00000000 EXPORT PendSV_Handler
24 00000000
25 00000000
26 00000000 E000ED04
NVIC_INT_CTRL
EQU 0xE000ED04 ; <20>жϿ<D0B6><CFBF>ƼĴ<C6BC><C4B4><EFBFBD>
27 00000000 E000ED20
NVIC_SYSPRI2
EQU 0xE000ED20 ; ϵͳ<CFB5><CDB3><EFBFBD>ȼ<EFBFBD><C8BC>Ĵ<EFBFBD><C4B4><EFBFBD>(
2)
28 00000000 FFFF0000
NVIC_PENDSV_PRI
EQU 0xFFFF0000 ; PendSV<53>жϺ<D0B6>ϵͳ<CFB5>
<20><><EFBFBD><EFBFBD>ж<EFBFBD>
29 00000000 ; (<28><>Ϊ<EFBFBD><CEAA><EFBFBD>ͣ<EFBFBD>0xff).
30 00000000 10000000
NVIC_PENDSVSET
EQU 0x10000000 ; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϵ<D0B6>ֵ.
31 00000000
32 00000000
33 00000000 PRESERVE8
34 00000000
35 00000000 AREA |.text|, CODE, READONLY
36 00000000 THUMB
37 00000000
38 00000000
39 00000000
40 00000000 ;*******************************************************
*************************************************
41 00000000 ; CRITICAL SECTION MET
HOD 3 FUNCTIONS
42 00000000 ;
ARM Macro Assembler Page 2
43 00000000 ; Description: Disable/Enable interrupts by preserving t
he state of interrupts. Generally speaking you
44 00000000 ; would store the state of the interrupt di
sable flag in the local variable 'cpu_sr' and then
45 00000000 ; disable interrupts. 'cpu_sr' is allocate
d in all of uC/OS-II's functions that need to
46 00000000 ; disable interrupts. You would restore th
e interrupt disable state by copying back 'cpu_sr'
47 00000000 ; into the CPU's status register.
48 00000000 ;
49 00000000 ; Prototypes : OS_CPU_SR OS_CPU_SR_Save(void);
50 00000000 ; void OS_CPU_SR_Restore(OS_CPU_S
R cpu_sr);
51 00000000 ;
52 00000000 ;
53 00000000 ; Note(s) : 1) These functions are used in general li
ke this:
54 00000000 ;
55 00000000 ; void Task (void *p_arg)
56 00000000 ; {
57 00000000 ; #if OS_CRITICAL_METHOD == 3 /
* Allocate storage for CPU status register */
58 00000000 ; OS_CPU_SR cpu_sr;
59 00000000 ; #endif
60 00000000 ;
61 00000000 ; :
62 00000000 ; :
63 00000000 ; OS_ENTER_CRITICAL(); /
* cpu_sr = OS_CPU_SaveSR(); */
64 00000000 ; :
65 00000000 ; :
66 00000000 ; OS_EXIT_CRITICAL(); /
* OS_CPU_RestoreSR(cpu_sr); */
67 00000000 ; :
68 00000000 ; :
69 00000000 ; }
70 00000000 ;*******************************************************
*************************************************
71 00000000
72 00000000 OS_CPU_SR_Save
73 00000000 F3EF 8010 MRS R0, PRIMASK ;<3B><>ȡPRIMASK<53><4B>R0,R0
Ϊ<><CEAA><EFBFBD><EFBFBD>ֵ
74 00000004 B672 CPSID I ;PRIMASK=1,<2C><><EFBFBD>ж<EFBFBD>(N
MI<4D><49>Ӳ<EFBFBD><D3B2>FAULT<4C><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Ӧ)
75 00000006 4770 BX LR ;<3B><><EFBFBD><EFBFBD>
76 00000008
77 00000008 OS_CPU_SR_Restore
78 00000008 F380 8810 MSR PRIMASK, R0 ;<3B><>ȡR0<52><30>PRIMASK<53><4B>,
R0Ϊ<30><CEAA><EFBFBD><EFBFBD>
79 0000000C 4770 BX LR ;<3B><><EFBFBD><EFBFBD>
80 0000000E
81 0000000E
82 0000000E ;/******************************************************
********************************
83 0000000E ;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: OSStartHighRdy
84 0000000E ;*
85 0000000E ;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: ʹ<>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
86 0000000E ;*
ARM Macro Assembler Page 3
87 0000000E ;* <20><> <20><>: None
88 0000000E ;*
89 0000000E ;* <20><> <20><> ֵ: None
90 0000000E ;*******************************************************
*******************************/
91 0000000E
92 0000000E OSStartHighRdy
93 0000000E 4C20 LDR R4, =NVIC_SYSPRI2 ; set the Pen
dSV exception prior
ity
94 00000010 4D20 LDR R5, =NVIC_PENDSV_PRI
95 00000012 6025 STR R5, [R4]
96 00000014
97 00000014 F04F 0400 MOV R4, #0 ; set the PSP to 0
for initial context
switch call
98 00000018 F384 8809 MSR PSP, R4
99 0000001C
100 0000001C 4C1E LDR R4, =OSRunning
; OSRunning = TRUE
101 0000001E F04F 0501 MOV R5, #1
102 00000022 7025 STRB R5, [R4]
103 00000024
104 00000024 ;<3B>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
105 00000024 4C1D LDR R4, =NVIC_INT_CTRL ;rigger the
PendSV exception (c
auses context switc
h)
106 00000026 F04F 5580 LDR R5, =NVIC_PENDSVSET
107 0000002A 6025 STR R5, [R4]
108 0000002C
109 0000002C B662 CPSIE I ;enable interrupts
at processor level
110 0000002E OSStartHang
111 0000002E E7FE B OSStartHang ;should never get h
ere
112 00000030
113 00000030 ;/******************************************************
********************************
114 00000030 ;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: OSCtxSw
115 00000030 ;*
116 00000030 ;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>
117 00000030 ;*
118 00000030 ;* <20><> <20><>: None
119 00000030 ;*
120 00000030 ;* <20><> <20><> ֵ: None
121 00000030 ;*******************************************************
********************************/
122 00000030
123 00000030 OSCtxSw
124 00000030 B430 PUSH {R4, R5}
125 00000032 4C1A LDR R4, =NVIC_INT_CTRL ;<3B><><EFBFBD><EFBFBD>PendSV<53>
쳣 (causes context
switch)
126 00000034 F04F 5580 LDR R5, =NVIC_PENDSVSET
127 00000038 6025 STR R5, [R4]
128 0000003A BC30 POP {R4, R5}
129 0000003C 4770 BX LR
130 0000003E
ARM Macro Assembler Page 4
131 0000003E ;/******************************************************
********************************
132 0000003E ;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: OSIntCtxSw
133 0000003E ;*
134 0000003E ;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20>жϼ<D0B6><CFBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>
135 0000003E ;*
136 0000003E ;* <20><> <20><>: None
137 0000003E ;*
138 0000003E ;* <20><> <20><> ֵ: None
139 0000003E ;*******************************************************
********************************/
140 0000003E
141 0000003E OSIntCtxSw
142 0000003E B430 PUSH {R4, R5}
143 00000040 4C16 LDR R4, =NVIC_INT_CTRL ;<3B><><EFBFBD><EFBFBD>PendSV<53>
쳣 (causes context
switch)
144 00000042 F04F 5580 LDR R5, =NVIC_PENDSVSET
145 00000046 6025 STR R5, [R4]
146 00000048 BC30 POP {R4, R5}
147 0000004A 4770 BX LR
148 0000004C BF00 NOP
149 0000004E
150 0000004E ;/******************************************************
********************************
151 0000004E ;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: OSPendSV
152 0000004E ;*
153 0000004E ;* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: OSPendSV is used to cause a context switch.
154 0000004E ;*
155 0000004E ;* <20><> <20><>: None
156 0000004E ;*
157 0000004E ;* <20><> <20><> ֵ: None
158 0000004E ;*******************************************************
********************************/
159 0000004E
160 0000004E PendSV_Handler
161 0000004E B672 CPSID I ; Prevent interrupt
ion during context
switch
162 00000050 F3EF 8009 MRS R0, PSP ; PSP is process st
ack pointer <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<20>PSP<53><50>ջ,<2C><><EFBFBD><EFBFBD><EFBFBD>Ժ<EFBFBD><D4BA><EFBFBD>
<20><><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>,<2C>ο<EFBFBD>CM3<4D>
<20><><EFBFBD><EFBFBD>е<EFBFBD>˫<EFBFBD><CBAB>ջ-<2D>ײ<EFBFBD><D7B2>
<20>
163 00000054 B128 CBZ R0, PendSV_Handler_Nosave ; Ski
p register save the
first time
164 00000056
165 00000056 3820 SUBS R0, R0, #0x20 ; Save remaining
regs r4-11 on proce
ss stack
166 00000058 E880 0FF0 STM R0, {R4-R11}
167 0000005C
168 0000005C 4910 LDR R1, =OSTCBCur ; OSTCBCur->OSTCB
StkPtr = SP;
169 0000005E 6809 LDR R1, [R1]
170 00000060 6008 STR R0, [R1] ; R0 is SP of proce
ARM Macro Assembler Page 5
ss being switched o
ut
171 00000062
172 00000062 ; At this point, entire context of process has been save
d
173 00000062 PendSV_Handler_Nosave
174 00000062 B500 PUSH {R14} ; Save LR exc_retur
n value
175 00000064 480F LDR R0, =OSTaskSwHook
; OSTaskSwHook();
176 00000066 4780 BLX R0
177 00000068 F85D EB04 POP {R14}
178 0000006C
179 0000006C 480E LDR R0, =OSPrioCur ; OSPrioCur = OS
PrioHighRdy;
180 0000006E 490F LDR R1, =OSPrioHighRdy
181 00000070 780A LDRB R2, [R1]
182 00000072 7002 STRB R2, [R0]
183 00000074
184 00000074 480A LDR R0, =OSTCBCur ; OSTCBCur = OST
CBHighRdy;
185 00000076 490E LDR R1, =OSTCBHighRdy
186 00000078 680A LDR R2, [R1]
187 0000007A 6002 STR R2, [R0]
188 0000007C
189 0000007C 6810 LDR R0, [R2] ; R0 is new process
SP; SP = OSTCBHigh
Rdy->OSTCBStkPtr;
190 0000007E E890 0FF0 LDM R0, {R4-R11} ; Restore r4-11 fr
om new process stac
k
191 00000082 3020 ADDS R0, R0, #0x20
192 00000084 F380 8809 MSR PSP, R0 ; Load PSP with new
process SP
193 00000088 F04E 0E04 ORR LR, LR, #0x04 ; Ensure exceptio
n return uses proce
ss stack
194 0000008C B662 CPSIE I
195 0000008E 4770 BX LR ; Exception return
will restore remain
ing context
196 00000090
197 00000090 end
E000ED20
FFFF0000
00000000
E000ED04
00000000
00000000
00000000
00000000
00000000
Command Line: --debug --xref --diag_suppress=9931 --cpu=Cortex-M3 --apcs=interw
ork --depend=..\obj\os_cpu_a.d -o..\obj\os_cpu_a.o -I"G:\ǰ<><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵϰ\for Githu
b\4StepperMotorsDriveBySTM32F103x\USER\RTE" -IE:\Keil5\ARM\PACK\Keil\STM32F1xx_
DFP\1.0.2\Device\Include -IE:\Keil5\ARM\CMSIS\Include --predefine="__UVISION_VE
RSION SETA 516" --predefine="STM32F10X_HD SETA 1" --list=.\listings\os_cpu_a.ls
t ..\UCOSII\PORT\os_cpu_a.asm
ARM Macro Assembler Page 1 Alphabetic symbol ordering
Relocatable symbols
.text 00000000
Symbol: .text
Definitions
At line 35 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
None
Comment: .text unused
OSCtxSw 00000030
Symbol: OSCtxSw
Definitions
At line 123 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 19 in file ..\UCOSII\PORT\os_cpu_a.asm
Comment: OSCtxSw used once
OSIntCtxSw 0000003E
Symbol: OSIntCtxSw
Definitions
At line 141 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 20 in file ..\UCOSII\PORT\os_cpu_a.asm
Comment: OSIntCtxSw used once
OSStartHang 0000002E
Symbol: OSStartHang
Definitions
At line 110 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 111 in file ..\UCOSII\PORT\os_cpu_a.asm
Comment: OSStartHang used once
OSStartHighRdy 0000000E
Symbol: OSStartHighRdy
Definitions
At line 92 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 18 in file ..\UCOSII\PORT\os_cpu_a.asm
Comment: OSStartHighRdy used once
OS_CPU_SR_Restore 00000008
Symbol: OS_CPU_SR_Restore
Definitions
At line 77 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 22 in file ..\UCOSII\PORT\os_cpu_a.asm
Comment: OS_CPU_SR_Restore used once
OS_CPU_SR_Save 00000000
Symbol: OS_CPU_SR_Save
Definitions
At line 72 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 21 in file ..\UCOSII\PORT\os_cpu_a.asm
Comment: OS_CPU_SR_Save used once
PendSV_Handler 0000004E
Symbol: PendSV_Handler
ARM Macro Assembler Page 2 Alphabetic symbol ordering
Relocatable symbols
Definitions
At line 160 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 23 in file ..\UCOSII\PORT\os_cpu_a.asm
Comment: PendSV_Handler used once
PendSV_Handler_Nosave 00000062
Symbol: PendSV_Handler_Nosave
Definitions
At line 173 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 163 in file ..\UCOSII\PORT\os_cpu_a.asm
Comment: PendSV_Handler_Nosave used once
9 symbols
ARM Macro Assembler Page 1 Alphabetic symbol ordering
Absolute symbols
NVIC_INT_CTRL E000ED04
Symbol: NVIC_INT_CTRL
Definitions
At line 26 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 105 in file ..\UCOSII\PORT\os_cpu_a.asm
At line 125 in file ..\UCOSII\PORT\os_cpu_a.asm
At line 143 in file ..\UCOSII\PORT\os_cpu_a.asm
NVIC_PENDSVSET 10000000
Symbol: NVIC_PENDSVSET
Definitions
At line 30 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 106 in file ..\UCOSII\PORT\os_cpu_a.asm
At line 126 in file ..\UCOSII\PORT\os_cpu_a.asm
At line 144 in file ..\UCOSII\PORT\os_cpu_a.asm
NVIC_PENDSV_PRI FFFF0000
Symbol: NVIC_PENDSV_PRI
Definitions
At line 28 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 94 in file ..\UCOSII\PORT\os_cpu_a.asm
Comment: NVIC_PENDSV_PRI used once
NVIC_SYSPRI2 E000ED20
Symbol: NVIC_SYSPRI2
Definitions
At line 27 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 93 in file ..\UCOSII\PORT\os_cpu_a.asm
Comment: NVIC_SYSPRI2 used once
4 symbols
ARM Macro Assembler Page 1 Alphabetic symbol ordering
External symbols
OSIntExit 00000000
Symbol: OSIntExit
Definitions
At line 15 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
None
Comment: OSIntExit unused
OSIntNesting 00000000
Symbol: OSIntNesting
Definitions
At line 14 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
None
Comment: OSIntNesting unused
OSPrioCur 00000000
Symbol: OSPrioCur
Definitions
At line 10 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 179 in file ..\UCOSII\PORT\os_cpu_a.asm
Comment: OSPrioCur used once
OSPrioHighRdy 00000000
Symbol: OSPrioHighRdy
Definitions
At line 11 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 180 in file ..\UCOSII\PORT\os_cpu_a.asm
Comment: OSPrioHighRdy used once
OSRunning 00000000
Symbol: OSRunning
Definitions
At line 9 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 100 in file ..\UCOSII\PORT\os_cpu_a.asm
Comment: OSRunning used once
OSTCBCur 00000000
Symbol: OSTCBCur
Definitions
At line 12 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 168 in file ..\UCOSII\PORT\os_cpu_a.asm
At line 184 in file ..\UCOSII\PORT\os_cpu_a.asm
OSTCBHighRdy 00000000
Symbol: OSTCBHighRdy
Definitions
At line 13 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 185 in file ..\UCOSII\PORT\os_cpu_a.asm
Comment: OSTCBHighRdy used once
OSTaskSwHook 00000000
ARM Macro Assembler Page 2 Alphabetic symbol ordering
External symbols
Symbol: OSTaskSwHook
Definitions
At line 16 in file ..\UCOSII\PORT\os_cpu_a.asm
Uses
At line 175 in file ..\UCOSII\PORT\os_cpu_a.asm
Comment: OSTaskSwHook used once
8 symbols
355 symbols in table

View File

@@ -47,7 +47,9 @@
#include "stm32f10x_it.h"
// <20><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>UCOSIIϵͳ<CFB5><CDB3>1
#define USE_UCOSII 0
void NMI_Handler(void)
{
}
@@ -92,15 +94,20 @@ void SVC_Handler(void)
void DebugMon_Handler(void)
{
}
void PendSV_Handler(void)
{
}
#if USE_UCOSII
// <20><><EFBFBD><EFBFBD>û<EFBFBD><C3BB>ʹ<EFBFBD><CAB9> UCOSII <20><><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD>Ż<EFBFBD><C5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϷ<D0B6><CFB7><EFBFBD><EFBFBD>ӳ<EFBFBD><D3B3><EFBFBD>
#else
// ʹ<><CAB9> UCOSII ϵͳʱ<CDB3><CAB1>PendSV_Handler<65>Ѿ<EFBFBD><D1BE><EFBFBD> os-cpu_a.asm <20>ļ<EFBFBD><C4BC>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD>
//void PendSV_Handler(void)
//{
//}
void SysTick_Handler(void)
{
}
#endif
/******************************************************************************/
/* STM32F10x Peripherals Interrupt Handlers */
/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */