diff --git a/BUGLIST/UCOS移植到stm32,相关文件配置.txt b/BUGLIST/UCOS移植到stm32,相关文件配置.txt new file mode 100644 index 0000000..260aca8 --- /dev/null +++ b/BUGLIST/UCOS移植到stm32,相关文件配置.txt @@ -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 分组中,防止出现编译时重复定义的错误。 diff --git a/BUGLIST/为什么要学习ucos(用操作系统的编程思维来解决硬件开发).txt b/BUGLIST/为什么要学习ucos(用操作系统的编程思维来解决硬件开发).txt new file mode 100644 index 0000000..ea7951c --- /dev/null +++ b/BUGLIST/为什么要学习ucos(用操作系统的编程思维来解决硬件开发).txt @@ -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吧! \ No newline at end of file diff --git a/BUGLIST/硬件编程C语言,含位操作,extern用法,头文件总结.txt b/BUGLIST/硬件编程C语言,含位操作,extern用法,头文件总结.txt index f9f6b61..65b5371 100644 --- a/BUGLIST/硬件编程C语言,含位操作,extern用法,头文件总结.txt +++ b/BUGLIST/硬件编程C语言,含位操作,extern用法,头文件总结.txt @@ -157,6 +157,10 @@ void append(unsigned char dat, BUFFER *b) } } +/ ********************************************************************************************************************************** + +// 函数原型(函数声明)就是告诉编译器这个函数是存在的,让编译器知道这个函数的相关信息。函数原型不要求提供形参名,有类型列表就可以了。 + diff --git a/README.md b/README.md index 7af18f7..5452788 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/UCOSII/CONFIG/includes.h b/UCOSII/CONFIG/includes.h new file mode 100644 index 0000000..f3d2218 --- /dev/null +++ b/UCOSII/CONFIG/includes.h @@ -0,0 +1,55 @@ +/* +************************************************************************************************ +Ҫİļ + + : INCLUDES.C ucosļ + : Jean J. Labrosse +************************************************************************************************ +*/ + +#ifndef __INCLUDES_H__ +#define __INCLUDES_H__ +#include +#include +#include +#include +#include + +#include "ucos_ii.h" +#include "os_cpu.h" +#include "os_cfg.h" + +#include + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/UCOSII/CONFIG/os_cfg.h b/UCOSII/CONFIG/os_cfg.h new file mode 100644 index 0000000..1d44967 --- /dev/null +++ b/UCOSII/CONFIG/os_cfg.h @@ -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 Micrim 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 + diff --git a/UCOSII/CORE/os_core.c b/UCOSII/CORE/os_core.c new file mode 100644 index 0000000..e0a87de --- /dev/null +++ b/UCOSII/CORE/os_core.c @@ -0,0 +1,2029 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* CORE FUNCTIONS +* +* (c) Copyright 1992-2009, Micrium, Weston, FL +* All Rights Reserved +* +* File : OS_CORE.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 Micrim 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 +#define OS_GLOBALS +#include +#endif + +/* +********************************************************************************************************* +* PRIORITY RESOLUTION TABLE +* +* Note: Index into table is bit pattern to resolve highest priority +* Indexed value corresponds to highest priority bit position (i.e. 0..7) +********************************************************************************************************* +*/ + +INT8U const OSUnMapTbl[256] = { + 0u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x00 to 0x0F */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x10 to 0x1F */ + 5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x20 to 0x2F */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x30 to 0x3F */ + 6u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x40 to 0x4F */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x50 to 0x5F */ + 5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x60 to 0x6F */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x70 to 0x7F */ + 7u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x80 to 0x8F */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x90 to 0x9F */ + 5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0xA0 to 0xAF */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0xB0 to 0xBF */ + 6u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0xC0 to 0xCF */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0xD0 to 0xDF */ + 5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0xE0 to 0xEF */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u /* 0xF0 to 0xFF */ +}; + +/*$PAGE*/ +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +static void OS_InitEventList(void); + +static void OS_InitMisc(void); + +static void OS_InitRdyList(void); + +static void OS_InitTaskIdle(void); + +#if OS_TASK_STAT_EN > 0u +static void OS_InitTaskStat(void); +#endif + +static void OS_InitTCBList(void); + +static void OS_SchedNew(void); + +/*$PAGE*/ +/* +********************************************************************************************************* +* GET THE NAME OF A SEMAPHORE, MUTEX, MAILBOX or QUEUE +* +* Description: This function is used to obtain the name assigned to a semaphore, mutex, mailbox or queue. +* +* Arguments : pevent is a pointer to the event group. 'pevent' can point either to a semaphore, +* a mutex, a mailbox or a queue. Where this function is concerned, the actual +* type is irrelevant. +* +* pname is a pointer to a pointer to an ASCII string that will receive the name of the semaphore, +* mutex, mailbox or queue. +* +* 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_EVENT_TYPE if 'pevent' is not pointing to the proper event +* control block type. +* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' +* OS_ERR_PEVENT_NULL if you passed a NULL pointer for 'pevent' +* OS_ERR_NAME_GET_ISR if you are trying to call this function from an ISR +* +* Returns : The length of the string or 0 if the 'pevent' is a NULL pointer. +********************************************************************************************************* +*/ + +#if (OS_EVENT_EN) && (OS_EVENT_NAME_EN > 0u) +INT8U OSEventNameGet (OS_EVENT *pevent, + 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 (pevent == (OS_EVENT *)0) { /* Is 'pevent' a NULL pointer? */ + *perr = OS_ERR_PEVENT_NULL; + 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); + } + switch (pevent->OSEventType) { + case OS_EVENT_TYPE_SEM: + case OS_EVENT_TYPE_MUTEX: + case OS_EVENT_TYPE_MBOX: + case OS_EVENT_TYPE_Q: + break; + + default: + *perr = OS_ERR_EVENT_TYPE; + return (0u); + } + OS_ENTER_CRITICAL(); + *pname = pevent->OSEventName; + len = OS_StrLen(*pname); + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (len); +} +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* ASSIGN A NAME TO A SEMAPHORE, MUTEX, MAILBOX or QUEUE +* +* Description: This function assigns a name to a semaphore, mutex, mailbox or queue. +* +* Arguments : pevent is a pointer to the event group. 'pevent' can point either to a semaphore, +* a mutex, a mailbox or a queue. Where this function is concerned, it doesn't +* matter the actual type. +* +* pname is a pointer to an ASCII string that will be used as the name of the semaphore, +* mutex, mailbox or queue. +* +* perr is a pointer to an error code that can contain one of the following values: +* +* OS_ERR_NONE if the requested task is resumed +* OS_ERR_EVENT_TYPE if 'pevent' is not pointing to the proper event +* control block type. +* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' +* OS_ERR_PEVENT_NULL if you passed a NULL pointer for 'pevent' +* OS_ERR_NAME_SET_ISR if you called this function from an ISR +* +* Returns : None +********************************************************************************************************* +*/ + +#if (OS_EVENT_EN) && (OS_EVENT_NAME_EN > 0u) +void OSEventNameSet (OS_EVENT *pevent, + 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 (pevent == (OS_EVENT *)0) { /* Is 'pevent' a NULL pointer? */ + *perr = OS_ERR_PEVENT_NULL; + 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; + } + switch (pevent->OSEventType) { + case OS_EVENT_TYPE_SEM: + case OS_EVENT_TYPE_MUTEX: + case OS_EVENT_TYPE_MBOX: + case OS_EVENT_TYPE_Q: + break; + + default: + *perr = OS_ERR_EVENT_TYPE; + return; + } + OS_ENTER_CRITICAL(); + pevent->OSEventName = pname; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; +} +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* PEND ON MULTIPLE EVENTS +* +* Description: This function waits for multiple events. If multiple events are ready at the start of the +* pend call, then all available events are returned as ready. If the task must pend on the +* multiple events, then only the first posted or aborted event is returned as ready. +* +* Arguments : pevents_pend is a pointer to a NULL-terminated array of event control blocks to wait for. +* +* pevents_rdy is a pointer to an array to return which event control blocks are available +* or ready. The size of the array MUST be greater than or equal to the size +* of the 'pevents_pend' array, including terminating NULL. +* +* pmsgs_rdy is a pointer to an array to return messages from any available message-type +* events. The size of the array MUST be greater than or equal to the size of +* the 'pevents_pend' array, excluding the terminating NULL. Since NULL +* messages are valid messages, this array cannot be NULL-terminated. Instead, +* every available message-type event returns its messages in the 'pmsgs_rdy' +* array at the same index as the event is returned in the 'pevents_rdy' array. +* All other 'pmsgs_rdy' array indices are filled with NULL messages. +* +* timeout is an optional timeout period (in clock ticks). If non-zero, your task will +* wait for the resources up to the amount of time specified by this argument. +* If you specify 0, however, your task will wait forever for the specified +* events or, until the resources becomes available (or the events occur). +* +* 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 resources +* or, the events you are waiting for occurred; check the +* 'pevents_rdy' array for which events are available. +* OS_ERR_PEND_ABORT The wait on the events was aborted; check the +* 'pevents_rdy' array for which events were aborted. +* OS_ERR_TIMEOUT The events were not received within the specified +* 'timeout'. +* OS_ERR_PEVENT_NULL If 'pevents_pend', 'pevents_rdy', or 'pmsgs_rdy' is a +* NULL pointer. +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to an array of semaphores, +* mailboxes, and/or queues. +* 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 when the scheduler is locked. +* +* Returns : > 0 the number of events returned as ready or aborted. +* == 0 if no events are returned as ready because of timeout or upon error. +* +* Notes : 1) a. Validate 'pevents_pend' array as valid OS_EVENTs : +* +* semaphores, mailboxes, queues +* +* b. Return ALL available events and messages, if any +* +* c. Add current task priority as pending to each events's wait list +* Performed in OS_EventTaskWaitMulti() +* +* d. Wait on any of multiple events +* +* e. Remove current task priority as pending from each events's wait list +* Performed in OS_EventTaskRdy(), if events posted or aborted +* +* f. Return any event posted or aborted, if any +* else +* Return timeout +* +* 2) 'pevents_rdy' initialized to NULL PRIOR to all other validation or function handling in +* case of any error(s). +********************************************************************************************************* +*/ +/*$PAGE*/ +#if ((OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u)) +INT16U OSEventPendMulti (OS_EVENT **pevents_pend, + OS_EVENT **pevents_rdy, + void **pmsgs_rdy, + INT32U timeout, + INT8U *perr) +{ + OS_EVENT **pevents; + OS_EVENT *pevent; +#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) + OS_Q *pq; +#endif + BOOLEAN events_rdy; + INT16U events_rdy_nbr; + INT8U events_stat; +#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 (pevents_pend == (OS_EVENT **)0) { /* Validate 'pevents_pend' */ + *perr = OS_ERR_PEVENT_NULL; + return (0u); + } + if (*pevents_pend == (OS_EVENT *)0) { /* Validate 'pevents_pend' */ + *perr = OS_ERR_PEVENT_NULL; + return (0u); + } + if (pevents_rdy == (OS_EVENT **)0) { /* Validate 'pevents_rdy' */ + *perr = OS_ERR_PEVENT_NULL; + return (0u); + } + if (pmsgs_rdy == (void **)0) { /* Validate 'pmsgs_rdy' */ + *perr = OS_ERR_PEVENT_NULL; + return (0u); + } +#endif + + *pevents_rdy = (OS_EVENT *)0; /* Init array to NULL in case of errors */ + + pevents = pevents_pend; + pevent = *pevents; + while (pevent != (OS_EVENT *)0) { + switch (pevent->OSEventType) { /* Validate event block types */ +#if (OS_SEM_EN > 0u) + case OS_EVENT_TYPE_SEM: + break; +#endif +#if (OS_MBOX_EN > 0u) + case OS_EVENT_TYPE_MBOX: + break; +#endif +#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) + case OS_EVENT_TYPE_Q: + break; +#endif + + case OS_EVENT_TYPE_MUTEX: + case OS_EVENT_TYPE_FLAG: + default: + *perr = OS_ERR_EVENT_TYPE; + return (0u); + } + pevents++; + pevent = *pevents; + } + + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ + return (0u); + } + if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ + *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ + return (0u); + } + +/*$PAGE*/ + OS_ENTER_CRITICAL(); + events_rdy = OS_FALSE; + events_rdy_nbr = 0u; + events_stat = OS_STAT_RDY; + pevents = pevents_pend; + pevent = *pevents; + while (pevent != (OS_EVENT *)0) { /* See if any events already available */ + switch (pevent->OSEventType) { +#if (OS_SEM_EN > 0u) + case OS_EVENT_TYPE_SEM: + if (pevent->OSEventCnt > 0u) { /* If semaphore count > 0, resource available; */ + pevent->OSEventCnt--; /* ... decrement semaphore, ... */ + *pevents_rdy++ = pevent; /* ... and return available semaphore event */ + events_rdy = OS_TRUE; + *pmsgs_rdy++ = (void *)0; /* NO message returned for semaphores */ + events_rdy_nbr++; + + } else { + events_stat |= OS_STAT_SEM; /* Configure multi-pend for semaphore events */ + } + break; +#endif + +#if (OS_MBOX_EN > 0u) + case OS_EVENT_TYPE_MBOX: + if (pevent->OSEventPtr != (void *)0) { /* If mailbox NOT empty; ... */ + /* ... return available message, ... */ + *pmsgs_rdy++ = (void *)pevent->OSEventPtr; + pevent->OSEventPtr = (void *)0; + *pevents_rdy++ = pevent; /* ... and return available mailbox event */ + events_rdy = OS_TRUE; + events_rdy_nbr++; + + } else { + events_stat |= OS_STAT_MBOX; /* Configure multi-pend for mailbox events */ + } + break; +#endif + +#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) + case OS_EVENT_TYPE_Q: + pq = (OS_Q *)pevent->OSEventPtr; + if (pq->OSQEntries > 0u) { /* If queue NOT empty; ... */ + /* ... return available message, ... */ + *pmsgs_rdy++ = (void *)*pq->OSQOut++; + if (pq->OSQOut == pq->OSQEnd) { /* If OUT ptr at queue end, ... */ + pq->OSQOut = pq->OSQStart; /* ... wrap to queue start */ + } + pq->OSQEntries--; /* Update number of queue entries */ + *pevents_rdy++ = pevent; /* ... and return available queue event */ + events_rdy = OS_TRUE; + events_rdy_nbr++; + + } else { + events_stat |= OS_STAT_Q; /* Configure multi-pend for queue events */ + } + break; +#endif + + case OS_EVENT_TYPE_MUTEX: + case OS_EVENT_TYPE_FLAG: + default: + OS_EXIT_CRITICAL(); + *pevents_rdy = (OS_EVENT *)0; /* NULL terminate return event array */ + *perr = OS_ERR_EVENT_TYPE; + return (events_rdy_nbr); + } + pevents++; + pevent = *pevents; + } + + if ( events_rdy == OS_TRUE) { /* Return any events already available */ + *pevents_rdy = (OS_EVENT *)0; /* NULL terminate return event array */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (events_rdy_nbr); + } +/*$PAGE*/ + /* Otherwise, must wait until any event occurs */ + OSTCBCur->OSTCBStat |= events_stat | /* Resource not available, ... */ + OS_STAT_MULTI; /* ... pend on multiple events */ + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; + OSTCBCur->OSTCBDly = timeout; /* Store pend timeout in TCB */ + OS_EventTaskWaitMulti(pevents_pend); /* Suspend task until events or timeout occurs */ + + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find next highest priority task ready */ + OS_ENTER_CRITICAL(); + + switch (OSTCBCur->OSTCBStatPend) { /* Handle event posted, aborted, or timed-out */ + case OS_STAT_PEND_OK: + case OS_STAT_PEND_ABORT: + pevent = OSTCBCur->OSTCBEventPtr; + if (pevent != (OS_EVENT *)0) { /* If task event ptr != NULL, ... */ + *pevents_rdy++ = pevent; /* ... return available event ... */ + *pevents_rdy = (OS_EVENT *)0; /* ... & NULL terminate return event array */ + events_rdy_nbr++; + + } else { /* Else NO event available, handle as timeout */ + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_TO; + OS_EventTaskRemoveMulti(OSTCBCur, pevents_pend); + } + break; + + case OS_STAT_PEND_TO: /* If events timed out, ... */ + default: /* ... remove task from events' wait lists */ + OS_EventTaskRemoveMulti(OSTCBCur, pevents_pend); + break; + } + + switch (OSTCBCur->OSTCBStatPend) { + case OS_STAT_PEND_OK: + switch (pevent->OSEventType) { /* Return event's message */ +#if (OS_SEM_EN > 0u) + case OS_EVENT_TYPE_SEM: + *pmsgs_rdy++ = (void *)0; /* NO message returned for semaphores */ + break; +#endif + +#if ((OS_MBOX_EN > 0u) || \ + ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u))) + case OS_EVENT_TYPE_MBOX: + case OS_EVENT_TYPE_Q: + *pmsgs_rdy++ = (void *)OSTCBCur->OSTCBMsg; /* Return received message */ + break; +#endif + + case OS_EVENT_TYPE_MUTEX: + case OS_EVENT_TYPE_FLAG: + default: + OS_EXIT_CRITICAL(); + *pevents_rdy = (OS_EVENT *)0; /* NULL terminate return event array */ + *perr = OS_ERR_EVENT_TYPE; + return (events_rdy_nbr); + } + *perr = OS_ERR_NONE; + break; + + case OS_STAT_PEND_ABORT: + *pmsgs_rdy++ = (void *)0; /* NO message returned for abort */ + *perr = OS_ERR_PEND_ABORT; /* Indicate that event aborted */ + break; + + case OS_STAT_PEND_TO: + default: + *pmsgs_rdy++ = (void *)0; /* NO message returned for timeout */ + *perr = OS_ERR_TIMEOUT; /* Indicate that events timed out */ + 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 */ + OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0; +#if ((OS_MBOX_EN > 0u) || \ + ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u))) + OSTCBCur->OSTCBMsg = (void *)0; /* Clear task message */ +#endif + OS_EXIT_CRITICAL(); + + return (events_rdy_nbr); +} +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* INITIALIZATION +* +* Description: This function is used to initialize the internals of uC/OS-II and MUST be called prior to +* creating any uC/OS-II object and, prior to calling OSStart(). +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +void OSInit (void) +{ + OSInitHookBegin(); /* Call port specific initialization code */ + + OS_InitMisc(); /* Initialize miscellaneous variables */ + + OS_InitRdyList(); /* Initialize the Ready List */ + + OS_InitTCBList(); /* Initialize the free list of OS_TCBs */ + + OS_InitEventList(); /* Initialize the free list of OS_EVENTs */ + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + OS_FlagInit(); /* Initialize the event flag structures */ +#endif + +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + OS_MemInit(); /* Initialize the memory manager */ +#endif + +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + OS_QInit(); /* Initialize the message queue structures */ +#endif + + OS_InitTaskIdle(); /* Create the Idle Task */ +#if OS_TASK_STAT_EN > 0u + OS_InitTaskStat(); /* Create the Statistic Task */ +#endif + +#if OS_TMR_EN > 0u + OSTmr_Init(); /* Initialize the Timer Manager */ +#endif + + OSInitHookEnd(); /* Call port specific init. code */ + +#if OS_DEBUG_EN > 0u + OSDebugInit(); +#endif +} +/*$PAGE*/ +/* +********************************************************************************************************* +* ENTER ISR +* +* Description: This function is used to notify uC/OS-II that you are about to service an interrupt +* service routine (ISR). This allows uC/OS-II to keep track of interrupt nesting and thus +* only perform rescheduling at the last nested ISR. +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) This function should be called ith interrupts already disabled +* 2) Your ISR can directly increment OSIntNesting without calling this function because +* OSIntNesting has been declared 'global'. +* 3) You MUST still call OSIntExit() even though you increment OSIntNesting directly. +* 4) You MUST invoke OSIntEnter() and OSIntExit() in pair. In other words, for every call +* to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the +* end of the ISR. +* 5) You are allowed to nest interrupts up to 255 levels deep. +* 6) I removed the OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL() around the increment because +* OSIntEnter() is always called with interrupts disabled. +********************************************************************************************************* +*/ + +void OSIntEnter (void) +{ + if (OSRunning == OS_TRUE) { + if (OSIntNesting < 255u) { + OSIntNesting++; /* Increment ISR nesting level */ + } + } +} +/*$PAGE*/ +/* +********************************************************************************************************* +* EXIT ISR +* +* Description: This function is used to notify uC/OS-II that you have completed serviving an ISR. When +* the last nested ISR has completed, uC/OS-II will call the scheduler to determine whether +* a new, high-priority task, is ready to run. +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) You MUST invoke OSIntEnter() and OSIntExit() in pair. In other words, for every call +* to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the +* end of the ISR. +* 2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock()) +********************************************************************************************************* +*/ + +void OSIntExit (void) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + if (OSRunning == OS_TRUE) { + OS_ENTER_CRITICAL(); + if (OSIntNesting > 0u) { /* Prevent OSIntNesting from wrapping */ + OSIntNesting--; + } + if (OSIntNesting == 0u) { /* Reschedule only if all ISRs complete ... */ + if (OSLockNesting == 0u) { /* ... and not locked. */ + OS_SchedNew(); + OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; + if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */ +#if OS_TASK_PROFILE_EN > 0u + OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */ +#endif + OSCtxSwCtr++; /* Keep track of the number of ctx switches */ + OSIntCtxSw(); /* Perform interrupt level ctx switch */ + } + } + } + OS_EXIT_CRITICAL(); + } +} + +/*$PAGE*/ +/* +********************************************************************************************************* +* INDICATE THAT IT'S NO LONGER SAFE TO CREATE OBJECTS +* +* Description: This function is called by the application code to indicate that all initialization has +* been completed and that kernel objects are no longer allowed to be created. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : 1) You should call this function when you no longer want to allow application code to +* create kernel objects. +* 2) You need to define the macro 'OS_SAFETY_CRITICAL_IEC61508' +********************************************************************************************************* +*/ + +#ifdef OS_SAFETY_CRITICAL_IEC61508 +void OSSafetyCriticalStart (void) +{ + OSSafetyCriticalStartFlag = OS_TRUE; +} + +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* PREVENT SCHEDULING +* +* Description: This function is used to prevent rescheduling to take place. This allows your application +* to prevent context switches until you are ready to permit context switching. +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) You MUST invoke OSSchedLock() and OSSchedUnlock() in pair. In other words, for every +* call to OSSchedLock() you MUST have a call to OSSchedUnlock(). +********************************************************************************************************* +*/ + +#if OS_SCHED_LOCK_EN > 0u +void OSSchedLock (void) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + if (OSRunning == OS_TRUE) { /* Make sure multitasking is running */ + OS_ENTER_CRITICAL(); + if (OSIntNesting == 0u) { /* Can't call from an ISR */ + if (OSLockNesting < 255u) { /* Prevent OSLockNesting from wrapping back to 0 */ + OSLockNesting++; /* Increment lock nesting level */ + } + } + OS_EXIT_CRITICAL(); + } +} +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* ENABLE SCHEDULING +* +* Description: This function is used to re-allow rescheduling. +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) You MUST invoke OSSchedLock() and OSSchedUnlock() in pair. In other words, for every +* call to OSSchedLock() you MUST have a call to OSSchedUnlock(). +********************************************************************************************************* +*/ + +#if OS_SCHED_LOCK_EN > 0u +void OSSchedUnlock (void) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + if (OSRunning == OS_TRUE) { /* Make sure multitasking is running */ + OS_ENTER_CRITICAL(); + if (OSLockNesting > 0u) { /* Do not decrement if already 0 */ + OSLockNesting--; /* Decrement lock nesting level */ + if (OSLockNesting == 0u) { /* See if scheduler is enabled and ... */ + if (OSIntNesting == 0u) { /* ... not in an ISR */ + OS_EXIT_CRITICAL(); + OS_Sched(); /* See if a HPT is ready */ + } else { + OS_EXIT_CRITICAL(); + } + } else { + OS_EXIT_CRITICAL(); + } + } else { + OS_EXIT_CRITICAL(); + } + } +} +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* START MULTITASKING +* +* Description: This function is used to start the multitasking process which lets uC/OS-II manages the +* task that you have created. Before you can call OSStart(), you MUST have called OSInit() +* and you MUST have created at least one task. +* +* Arguments : none +* +* Returns : none +* +* Note : OSStartHighRdy() MUST: +* a) Call OSTaskSwHook() then, +* b) Set OSRunning to OS_TRUE. +* c) Load the context of the task pointed to by OSTCBHighRdy. +* d_ Execute the task. +********************************************************************************************************* +*/ + +void OSStart (void) +{ + if (OSRunning == OS_FALSE) { + OS_SchedNew(); /* Find highest priority's task priority number */ + OSPrioCur = OSPrioHighRdy; + OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run */ + OSTCBCur = OSTCBHighRdy; + OSStartHighRdy(); /* Execute target specific code to start task */ + } +} +/*$PAGE*/ +/* +********************************************************************************************************* +* STATISTICS INITIALIZATION +* +* Description: This function is called by your application to establish CPU usage by first determining +* how high a 32-bit counter would count to in 1 second if no other tasks were to execute +* during that time. CPU usage is then determined by a low priority task which keeps track +* of this 32-bit counter every second but this time, with other tasks running. CPU usage is +* determined by: +* +* OSIdleCtr +* CPU Usage (%) = 100 * (1 - ------------) +* OSIdleCtrMax +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TASK_STAT_EN > 0u +void OSStatInit (void) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + OSTimeDly(2u); /* Synchronize with clock tick */ + OS_ENTER_CRITICAL(); + OSIdleCtr = 0uL; /* Clear idle counter */ + OS_EXIT_CRITICAL(); + OSTimeDly(OS_TICKS_PER_SEC / 10u); /* Determine MAX. idle counter value for 1/10 second */ + OS_ENTER_CRITICAL(); + OSIdleCtrMax = OSIdleCtr; /* Store maximum idle counter count in 1/10 second */ + OSStatRdy = OS_TRUE; + OS_EXIT_CRITICAL(); +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* PROCESS SYSTEM TICK +* +* Description: This function is used to signal to uC/OS-II the occurrence of a 'system tick' (also known +* as a 'clock tick'). This function should be called by the ticker ISR but, can also be +* called by a high priority task. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +void OSTimeTick (void) +{ + OS_TCB *ptcb; +#if OS_TICK_STEP_EN > 0u + BOOLEAN step; +#endif +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_TIME_TICK_HOOK_EN > 0u + OSTimeTickHook(); /* Call user definable hook */ +#endif +#if OS_TIME_GET_SET_EN > 0u + OS_ENTER_CRITICAL(); /* Update the 32-bit tick counter */ + OSTime++; + OS_EXIT_CRITICAL(); +#endif + if (OSRunning == OS_TRUE) { +#if OS_TICK_STEP_EN > 0u + switch (OSTickStepState) { /* Determine whether we need to process a tick */ + case OS_TICK_STEP_DIS: /* Yes, stepping is disabled */ + step = OS_TRUE; + break; + + case OS_TICK_STEP_WAIT: /* No, waiting for uC/OS-View to set ... */ + step = OS_FALSE; /* .. OSTickStepState to OS_TICK_STEP_ONCE */ + break; + + case OS_TICK_STEP_ONCE: /* Yes, process tick once and wait for next ... */ + step = OS_TRUE; /* ... step command from uC/OS-View */ + OSTickStepState = OS_TICK_STEP_WAIT; + break; + + default: /* Invalid case, correct situation */ + step = OS_TRUE; + OSTickStepState = OS_TICK_STEP_DIS; + break; + } + if (step == OS_FALSE) { /* Return if waiting for step command */ + return; + } +#endif + ptcb = OSTCBList; /* Point at first TCB in TCB list */ + while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) { /* Go through all TCBs in TCB list */ + OS_ENTER_CRITICAL(); + if (ptcb->OSTCBDly != 0u) { /* No, Delayed or waiting for event with TO */ + ptcb->OSTCBDly--; /* Decrement nbr of ticks to end of delay */ + if (ptcb->OSTCBDly == 0u) { /* Check for timeout */ + + if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) { + ptcb->OSTCBStat &= (INT8U)~(INT8U)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; + } + } + } + ptcb = ptcb->OSTCBNext; /* Point at next TCB in TCB list */ + OS_EXIT_CRITICAL(); + } + } +} + +/*$PAGE*/ +/* +********************************************************************************************************* +* GET VERSION +* +* Description: This function is used to return the version number of uC/OS-II. The returned value +* corresponds to uC/OS-II's version number multiplied by 100. In other words, version 2.00 +* would be returned as 200. +* +* Arguments : none +* +* Returns : the version number of uC/OS-II multiplied by 100. +********************************************************************************************************* +*/ + +INT16U OSVersion (void) +{ + return (OS_VERSION); +} + +/*$PAGE*/ +/* +********************************************************************************************************* +* DUMMY FUNCTION +* +* Description: This function doesn't do anything. It is called by OSTaskDel(). +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TASK_DEL_EN > 0u +void OS_Dummy (void) +{ +} +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* MAKE TASK READY TO RUN BASED ON EVENT OCCURING +* +* Description: This function is called by other uC/OS-II services and is used to ready a task that was +* waiting for an event to occur. +* +* Arguments : pevent is a pointer to the event control block corresponding to the event. +* +* pmsg is a pointer to a message. This pointer is used by message oriented services +* such as MAILBOXEs and QUEUEs. The pointer is not used when called by other +* service functions. +* +* msk is a mask that is used to clear the status byte of the TCB. For example, +* OSSemPost() will pass OS_STAT_SEM, OSMboxPost() will pass OS_STAT_MBOX etc. +* +* pend_stat is used to indicate the readied task's pending status: +* +* OS_STAT_PEND_OK Task ready due to a post (or delete), not a timeout or +* an abort. +* OS_STAT_PEND_ABORT Task ready due to an abort. +* +* Returns : none +* +* Note : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ +#if (OS_EVENT_EN) +INT8U OS_EventTaskRdy (OS_EVENT *pevent, + void *pmsg, + INT8U msk, + INT8U pend_stat) +{ + OS_TCB *ptcb; + INT8U y; + INT8U x; + INT8U prio; +#if OS_LOWEST_PRIO > 63u + OS_PRIO *ptbl; +#endif + + +#if OS_LOWEST_PRIO <= 63u + y = OSUnMapTbl[pevent->OSEventGrp]; /* Find HPT waiting for message */ + x = OSUnMapTbl[pevent->OSEventTbl[y]]; + prio = (INT8U)((y << 3u) + x); /* Find priority of task getting the msg */ +#else + if ((pevent->OSEventGrp & 0xFFu) != 0u) { /* Find HPT waiting for message */ + y = OSUnMapTbl[ pevent->OSEventGrp & 0xFFu]; + } else { + y = OSUnMapTbl[(OS_PRIO)(pevent->OSEventGrp >> 8u) & 0xFFu] + 8u; + } + ptbl = &pevent->OSEventTbl[y]; + if ((*ptbl & 0xFFu) != 0u) { + x = OSUnMapTbl[*ptbl & 0xFFu]; + } else { + x = OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u; + } + prio = (INT8U)((y << 4u) + x); /* Find priority of task getting the msg */ +#endif + + ptcb = OSTCBPrioTbl[prio]; /* Point to this task's OS_TCB */ + ptcb->OSTCBDly = 0u; /* Prevent OSTimeTick() from readying task */ +#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) || (OS_MBOX_EN > 0u) + ptcb->OSTCBMsg = pmsg; /* Send message directly to waiting task */ +#else + pmsg = pmsg; /* Prevent compiler warning if not used */ +#endif + ptcb->OSTCBStat &= (INT8U)~msk; /* Clear bit associated with event type */ + ptcb->OSTCBStatPend = pend_stat; /* Set pend status of post or abort */ + /* See if task is ready (could be susp'd) */ + if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { + OSRdyGrp |= ptcb->OSTCBBitY; /* Put task in the ready to run list */ + OSRdyTbl[y] |= ptcb->OSTCBBitX; + } + + OS_EventTaskRemove(ptcb, pevent); /* Remove this task from event wait list */ +#if (OS_EVENT_MULTI_EN > 0u) + if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) { /* Remove this task from events' wait lists */ + OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr); + ptcb->OSTCBEventPtr = (OS_EVENT *)pevent;/* Return event as first multi-pend event ready*/ + } +#endif + + return (prio); +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* MAKE TASK WAIT FOR EVENT TO OCCUR +* +* Description: This function is called by other uC/OS-II services to suspend a task because an event has +* not occurred. +* +* Arguments : pevent is a pointer to the event control block for which the task will be waiting for. +* +* Returns : none +* +* Note : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ +#if (OS_EVENT_EN) +void OS_EventTaskWait (OS_EVENT *pevent) +{ + INT8U y; + + + OSTCBCur->OSTCBEventPtr = pevent; /* Store ptr to ECB in TCB */ + + pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX; /* Put task in waiting list */ + pevent->OSEventGrp |= OSTCBCur->OSTCBBitY; + + y = OSTCBCur->OSTCBY; /* Task no longer ready */ + OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX; + if (OSRdyTbl[y] == 0u) { /* Clear event grp bit if this was only task pending */ + OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY; + } +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* MAKE TASK WAIT FOR ANY OF MULTIPLE EVENTS TO OCCUR +* +* Description: This function is called by other uC/OS-II services to suspend a task because any one of +* multiple events has not occurred. +* +* Arguments : pevents_wait is a pointer to an array of event control blocks, NULL-terminated, for +* which the task will be waiting for. +* +* Returns : none. +* +* Note : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ +#if ((OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u)) +void OS_EventTaskWaitMulti (OS_EVENT **pevents_wait) +{ + OS_EVENT **pevents; + OS_EVENT *pevent; + INT8U y; + + + OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; + OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)pevents_wait; /* Store ptr to ECBs in TCB */ + + pevents = pevents_wait; + pevent = *pevents; + while (pevent != (OS_EVENT *)0) { /* Put task in waiting lists */ + pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX; + pevent->OSEventGrp |= OSTCBCur->OSTCBBitY; + pevents++; + pevent = *pevents; + } + + y = OSTCBCur->OSTCBY; /* Task no longer ready */ + OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX; + if (OSRdyTbl[y] == 0u) { /* Clear event grp bit if this was only task pending */ + OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY; + } +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* REMOVE TASK FROM EVENT WAIT LIST +* +* Description: Remove a task from an event's wait list. +* +* Arguments : ptcb is a pointer to the task to remove. +* +* pevent is a pointer to the event control block. +* +* Returns : none +* +* Note : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ +#if (OS_EVENT_EN) +void OS_EventTaskRemove (OS_TCB *ptcb, + OS_EVENT *pevent) +{ + INT8U y; + + + y = ptcb->OSTCBY; + pevent->OSEventTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX; /* Remove task from wait list */ + if (pevent->OSEventTbl[y] == 0u) { + pevent->OSEventGrp &= (OS_PRIO)~ptcb->OSTCBBitY; + } +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* REMOVE TASK FROM MULTIPLE EVENTS WAIT LISTS +* +* Description: Remove a task from multiple events' wait lists. +* +* Arguments : ptcb is a pointer to the task to remove. +* +* pevents_multi is a pointer to the array of event control blocks, NULL-terminated. +* +* Returns : none +* +* Note : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ +#if ((OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u)) +void OS_EventTaskRemoveMulti (OS_TCB *ptcb, + OS_EVENT **pevents_multi) +{ + OS_EVENT **pevents; + OS_EVENT *pevent; + INT8U y; + OS_PRIO bity; + OS_PRIO bitx; + + + y = ptcb->OSTCBY; + bity = ptcb->OSTCBBitY; + bitx = ptcb->OSTCBBitX; + pevents = pevents_multi; + pevent = *pevents; + while (pevent != (OS_EVENT *)0) { /* Remove task from all events' wait lists */ + pevent->OSEventTbl[y] &= (OS_PRIO)~bitx; + if (pevent->OSEventTbl[y] == 0u) { + pevent->OSEventGrp &= (OS_PRIO)~bity; + } + pevents++; + pevent = *pevents; + } +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* INITIALIZE EVENT CONTROL BLOCK'S WAIT LIST +* +* Description: This function is called by other uC/OS-II services to initialize the event wait list. +* +* Arguments : pevent is a pointer to the event control block allocated to the event. +* +* Returns : none +* +* Note : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ +#if (OS_EVENT_EN) +void OS_EventWaitListInit (OS_EVENT *pevent) +{ + INT8U i; + + + pevent->OSEventGrp = 0u; /* No task waiting on event */ + for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) { + pevent->OSEventTbl[i] = 0u; + } +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* INITIALIZATION +* INITIALIZE THE FREE LIST OF EVENT CONTROL BLOCKS +* +* Description: This function is called by OSInit() to initialize the free list of event control blocks. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +static void OS_InitEventList (void) +{ +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +#if (OS_MAX_EVENTS > 1u) + INT16U ix; + INT16U ix_next; + OS_EVENT *pevent1; + OS_EVENT *pevent2; + + + OS_MemClr((INT8U *)&OSEventTbl[0], sizeof(OSEventTbl)); /* Clear the event table */ + for (ix = 0u; ix < (OS_MAX_EVENTS - 1u); ix++) { /* Init. list of free EVENT control blocks */ + ix_next = ix + 1u; + pevent1 = &OSEventTbl[ix]; + pevent2 = &OSEventTbl[ix_next]; + pevent1->OSEventType = OS_EVENT_TYPE_UNUSED; + pevent1->OSEventPtr = pevent2; +#if OS_EVENT_NAME_EN > 0u + pevent1->OSEventName = (INT8U *)(void *)"?"; /* Unknown name */ +#endif + } + pevent1 = &OSEventTbl[ix]; + pevent1->OSEventType = OS_EVENT_TYPE_UNUSED; + pevent1->OSEventPtr = (OS_EVENT *)0; +#if OS_EVENT_NAME_EN > 0u + pevent1->OSEventName = (INT8U *)(void *)"?"; /* Unknown name */ +#endif + OSEventFreeList = &OSEventTbl[0]; +#else + OSEventFreeList = &OSEventTbl[0]; /* Only have ONE event control block */ + OSEventFreeList->OSEventType = OS_EVENT_TYPE_UNUSED; + OSEventFreeList->OSEventPtr = (OS_EVENT *)0; +#if OS_EVENT_NAME_EN > 0u + OSEventFreeList->OSEventName = (INT8U *)"?"; /* Unknown name */ +#endif +#endif +#endif +} +/*$PAGE*/ +/* +********************************************************************************************************* +* INITIALIZATION +* INITIALIZE MISCELLANEOUS VARIABLES +* +* Description: This function is called by OSInit() to initialize miscellaneous variables. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +static void OS_InitMisc (void) +{ +#if OS_TIME_GET_SET_EN > 0u + OSTime = 0uL; /* Clear the 32-bit system clock */ +#endif + + OSIntNesting = 0u; /* Clear the interrupt nesting counter */ + OSLockNesting = 0u; /* Clear the scheduling lock counter */ + + OSTaskCtr = 0u; /* Clear the number of tasks */ + + OSRunning = OS_FALSE; /* Indicate that multitasking not started */ + + OSCtxSwCtr = 0u; /* Clear the context switch counter */ + OSIdleCtr = 0uL; /* Clear the 32-bit idle counter */ + +#if OS_TASK_STAT_EN > 0u + OSIdleCtrRun = 0uL; + OSIdleCtrMax = 0uL; + OSStatRdy = OS_FALSE; /* Statistic task is not ready */ +#endif + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + OSSafetyCriticalStartFlag = OS_FALSE; /* Still allow creation of objects */ +#endif +} +/*$PAGE*/ +/* +********************************************************************************************************* +* INITIALIZATION +* INITIALIZE THE READY LIST +* +* Description: This function is called by OSInit() to initialize the Ready List. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +static void OS_InitRdyList (void) +{ + INT8U i; + + + OSRdyGrp = 0u; /* Clear the ready list */ + for (i = 0u; i < OS_RDY_TBL_SIZE; i++) { + OSRdyTbl[i] = 0u; + } + + OSPrioCur = 0u; + OSPrioHighRdy = 0u; + + OSTCBHighRdy = (OS_TCB *)0; + OSTCBCur = (OS_TCB *)0; +} + +/*$PAGE*/ +/* +********************************************************************************************************* +* INITIALIZATION +* CREATING THE IDLE TASK +* +* Description: This function creates the Idle Task. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +static void OS_InitTaskIdle (void) +{ +#if OS_TASK_NAME_EN > 0u + INT8U err; +#endif + + +#if OS_TASK_CREATE_EXT_EN > 0u + #if OS_STK_GROWTH == 1u + (void)OSTaskCreateExt(OS_TaskIdle, + (void *)0, /* No arguments passed to OS_TaskIdle() */ + &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1u],/* Set Top-Of-Stack */ + OS_TASK_IDLE_PRIO, /* Lowest priority level */ + OS_TASK_IDLE_ID, + &OSTaskIdleStk[0], /* Set Bottom-Of-Stack */ + OS_TASK_IDLE_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack */ + #else + (void)OSTaskCreateExt(OS_TaskIdle, + (void *)0, /* No arguments passed to OS_TaskIdle() */ + &OSTaskIdleStk[0], /* Set Top-Of-Stack */ + OS_TASK_IDLE_PRIO, /* Lowest priority level */ + OS_TASK_IDLE_ID, + &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1u],/* Set Bottom-Of-Stack */ + OS_TASK_IDLE_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack */ + #endif +#else + #if OS_STK_GROWTH == 1u + (void)OSTaskCreate(OS_TaskIdle, + (void *)0, + &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1u], + OS_TASK_IDLE_PRIO); + #else + (void)OSTaskCreate(OS_TaskIdle, + (void *)0, + &OSTaskIdleStk[0], + OS_TASK_IDLE_PRIO); + #endif +#endif + +#if OS_TASK_NAME_EN > 0u + OSTaskNameSet(OS_TASK_IDLE_PRIO, (INT8U *)(void *)"uC/OS-II Idle", &err); +#endif +} +/*$PAGE*/ +/* +********************************************************************************************************* +* INITIALIZATION +* CREATING THE STATISTIC TASK +* +* Description: This function creates the Statistic Task. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TASK_STAT_EN > 0u +static void OS_InitTaskStat (void) +{ +#if OS_TASK_NAME_EN > 0u + INT8U err; +#endif + + +#if OS_TASK_CREATE_EXT_EN > 0u + #if OS_STK_GROWTH == 1u + (void)OSTaskCreateExt(OS_TaskStat, + (void *)0, /* No args passed to OS_TaskStat()*/ + &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1u], /* Set Top-Of-Stack */ + OS_TASK_STAT_PRIO, /* One higher than the idle task */ + OS_TASK_STAT_ID, + &OSTaskStatStk[0], /* Set Bottom-Of-Stack */ + OS_TASK_STAT_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear */ + #else + (void)OSTaskCreateExt(OS_TaskStat, + (void *)0, /* No args passed to OS_TaskStat()*/ + &OSTaskStatStk[0], /* Set Top-Of-Stack */ + OS_TASK_STAT_PRIO, /* One higher than the idle task */ + OS_TASK_STAT_ID, + &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1u], /* Set Bottom-Of-Stack */ + OS_TASK_STAT_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear */ + #endif +#else + #if OS_STK_GROWTH == 1u + (void)OSTaskCreate(OS_TaskStat, + (void *)0, /* No args passed to OS_TaskStat()*/ + &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1u], /* Set Top-Of-Stack */ + OS_TASK_STAT_PRIO); /* One higher than the idle task */ + #else + (void)OSTaskCreate(OS_TaskStat, + (void *)0, /* No args passed to OS_TaskStat()*/ + &OSTaskStatStk[0], /* Set Top-Of-Stack */ + OS_TASK_STAT_PRIO); /* One higher than the idle task */ + #endif +#endif + +#if OS_TASK_NAME_EN > 0u + OSTaskNameSet(OS_TASK_STAT_PRIO, (INT8U *)(void *)"uC/OS-II Stat", &err); +#endif +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* INITIALIZATION +* INITIALIZE THE FREE LIST OF TASK CONTROL BLOCKS +* +* Description: This function is called by OSInit() to initialize the free list of OS_TCBs. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +static void OS_InitTCBList (void) +{ + INT8U ix; + INT8U ix_next; + OS_TCB *ptcb1; + OS_TCB *ptcb2; + + + OS_MemClr((INT8U *)&OSTCBTbl[0], sizeof(OSTCBTbl)); /* Clear all the TCBs */ + OS_MemClr((INT8U *)&OSTCBPrioTbl[0], sizeof(OSTCBPrioTbl)); /* Clear the priority table */ + for (ix = 0u; ix < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1u); ix++) { /* Init. list of free TCBs */ + ix_next = ix + 1u; + ptcb1 = &OSTCBTbl[ix]; + ptcb2 = &OSTCBTbl[ix_next]; + ptcb1->OSTCBNext = ptcb2; +#if OS_TASK_NAME_EN > 0u + ptcb1->OSTCBTaskName = (INT8U *)(void *)"?"; /* Unknown name */ +#endif + } + ptcb1 = &OSTCBTbl[ix]; + ptcb1->OSTCBNext = (OS_TCB *)0; /* Last OS_TCB */ +#if OS_TASK_NAME_EN > 0u + ptcb1->OSTCBTaskName = (INT8U *)(void *)"?"; /* Unknown name */ +#endif + OSTCBList = (OS_TCB *)0; /* TCB lists initializations */ + OSTCBFreeList = &OSTCBTbl[0]; +} +/*$PAGE*/ +/* +********************************************************************************************************* +* CLEAR A SECTION OF MEMORY +* +* Description: This function is called by other uC/OS-II services to clear a contiguous block of RAM. +* +* Arguments : pdest is the start of the RAM to clear (i.e. write 0x00 to) +* +* size is the number of bytes to clear. +* +* Returns : none +* +* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +* 2) Note that we can only clear up to 64K bytes of RAM. This is not an issue because none +* of the uses of this function gets close to this limit. +* 3) The clear is done one byte at a time since this will work on any processor irrespective +* of the alignment of the destination. +********************************************************************************************************* +*/ + +void OS_MemClr (INT8U *pdest, + INT16U size) +{ + while (size > 0u) { + *pdest++ = (INT8U)0; + size--; + } +} +/*$PAGE*/ +/* +********************************************************************************************************* +* COPY A BLOCK OF MEMORY +* +* Description: This function is called by other uC/OS-II services to copy a block of memory from one +* location to another. +* +* Arguments : pdest is a pointer to the 'destination' memory block +* +* psrc is a pointer to the 'source' memory block +* +* size is the number of bytes to copy. +* +* Returns : none +* +* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. There is +* no provision to handle overlapping memory copy. However, that's not a problem since this +* is not a situation that will happen. +* 2) Note that we can only copy up to 64K bytes of RAM +* 3) The copy is done one byte at a time since this will work on any processor irrespective +* of the alignment of the source and destination. +********************************************************************************************************* +*/ + +void OS_MemCopy (INT8U *pdest, + INT8U *psrc, + INT16U size) +{ + while (size > 0u) { + *pdest++ = *psrc++; + size--; + } +} +/*$PAGE*/ +/* +********************************************************************************************************* +* SCHEDULER +* +* Description: This function is called by other uC/OS-II services to determine whether a new, high +* priority task has been made ready to run. This function is invoked by TASK level code +* and is not used to reschedule tasks from ISRs (see OSIntExit() for ISR rescheduling). +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +* 2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock()) +********************************************************************************************************* +*/ + +void OS_Sched (void) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + OS_ENTER_CRITICAL(); + if (OSIntNesting == 0u) { /* Schedule only if all ISRs done and ... */ + if (OSLockNesting == 0u) { /* ... scheduler is not locked */ + OS_SchedNew(); + OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; + if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */ +#if OS_TASK_PROFILE_EN > 0u + OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */ +#endif + OSCtxSwCtr++; /* Increment context switch counter */ + OS_TASK_SW(); /* Perform a context switch */ + } + } + } + OS_EXIT_CRITICAL(); +} + + +/* +********************************************************************************************************* +* FIND HIGHEST PRIORITY TASK READY TO RUN +* +* Description: This function is called by other uC/OS-II services to determine the highest priority task +* that is ready to run. The global variable 'OSPrioHighRdy' is changed accordingly. +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +* 2) Interrupts are assumed to be disabled when this function is called. +********************************************************************************************************* +*/ + +static void OS_SchedNew (void) +{ +#if OS_LOWEST_PRIO <= 63u /* See if we support up to 64 tasks */ + INT8U y; + + + y = OSUnMapTbl[OSRdyGrp]; + OSPrioHighRdy = (INT8U)((y << 3u) + OSUnMapTbl[OSRdyTbl[y]]); +#else /* We support up to 256 tasks */ + INT8U y; + OS_PRIO *ptbl; + + + if ((OSRdyGrp & 0xFFu) != 0u) { + y = OSUnMapTbl[OSRdyGrp & 0xFFu]; + } else { + y = OSUnMapTbl[(OS_PRIO)(OSRdyGrp >> 8u) & 0xFFu] + 8u; + } + ptbl = &OSRdyTbl[y]; + if ((*ptbl & 0xFFu) != 0u) { + OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(*ptbl & 0xFFu)]); + } else { + OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u); + } +#endif +} + +/*$PAGE*/ +/* +********************************************************************************************************* +* DETERMINE THE LENGTH OF AN ASCII STRING +* +* Description: This function is called by other uC/OS-II services to determine the size of an ASCII string +* (excluding the NUL character). +* +* Arguments : psrc is a pointer to the string for which we need to know the size. +* +* Returns : The size of the string (excluding the NUL terminating character) +* +* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +* 2) The string to check must be less than 255 characters long. +********************************************************************************************************* +*/ + +#if (OS_EVENT_NAME_EN > 0u) || (OS_FLAG_NAME_EN > 0u) || (OS_MEM_NAME_EN > 0u) || (OS_TASK_NAME_EN > 0u) || (OS_TMR_CFG_NAME_EN > 0u) +INT8U OS_StrLen (INT8U *psrc) +{ + INT8U len; + + + len = 0u; + while (*psrc != OS_ASCII_NUL) { + psrc++; + len++; + } + return (len); +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* IDLE TASK +* +* Description: This task is internal to uC/OS-II and executes whenever no other higher priority tasks +* executes because they are ALL waiting for event(s) to occur. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : 1) OSTaskIdleHook() is called after the critical section to ensure that interrupts will be +* enabled for at least a few instructions. On some processors (ex. Philips XA), enabling +* and then disabling interrupts didn't allow the processor enough time to have interrupts +* enabled before they were disabled again. uC/OS-II would thus never recognize +* interrupts. +* 2) This hook has been added to allow you to do such things as STOP the CPU to conserve +* power. +********************************************************************************************************* +*/ + +void OS_TaskIdle (void *p_arg) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + p_arg = p_arg; /* Prevent compiler warning for not using 'p_arg' */ + for (;;) { + OS_ENTER_CRITICAL(); + OSIdleCtr++; + OS_EXIT_CRITICAL(); + OSTaskIdleHook(); /* Call user definable HOOK */ + } +} +/*$PAGE*/ +/* +********************************************************************************************************* +* STATISTICS TASK +* +* Description: This task is internal to uC/OS-II and is used to compute some statistics about the +* multitasking environment. Specifically, OS_TaskStat() computes the CPU usage. +* CPU usage is determined by: +* +* OSIdleCtr +* OSCPUUsage = 100 * (1 - ------------) (units are in %) +* OSIdleCtrMax +* +* Arguments : parg this pointer is not used at this time. +* +* Returns : none +* +* Notes : 1) This task runs at a priority level higher than the idle task. In fact, it runs at the +* next higher priority, OS_TASK_IDLE_PRIO-1. +* 2) You can disable this task by setting the configuration #define OS_TASK_STAT_EN to 0. +* 3) You MUST have at least a delay of 2/10 seconds to allow for the system to establish the +* maximum value for the idle counter. +********************************************************************************************************* +*/ + +#if OS_TASK_STAT_EN > 0u +void OS_TaskStat (void *p_arg) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + p_arg = p_arg; /* Prevent compiler warning for not using 'p_arg' */ + while (OSStatRdy == OS_FALSE) { + OSTimeDly(2u * OS_TICKS_PER_SEC / 10u); /* Wait until statistic task is ready */ + } + OSIdleCtrMax /= 100uL; + if (OSIdleCtrMax == 0uL) { + OSCPUUsage = 0u; +#if OS_TASK_SUSPEND_EN > 0u + (void)OSTaskSuspend(OS_PRIO_SELF); +#else + for (;;) { + OSTimeDly(OS_TICKS_PER_SEC); + } +#endif + } + for (;;) { + OS_ENTER_CRITICAL(); + OSIdleCtrRun = OSIdleCtr; /* Obtain the of the idle counter for the past second */ + OSIdleCtr = 0uL; /* Reset the idle counter for the next second */ + OS_EXIT_CRITICAL(); + OSCPUUsage = (INT8U)(100uL - OSIdleCtrRun / OSIdleCtrMax); + OSTaskStatHook(); /* Invoke user definable hook */ +#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) + OS_TaskStatStkChk(); /* Check the stacks for each task */ +#endif + OSTimeDly(OS_TICKS_PER_SEC / 10u); /* Accumulate OSIdleCtr for the next 1/10 second */ + } +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* CHECK ALL TASK STACKS +* +* Description: This function is called by OS_TaskStat() to check the stacks of each active task. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) +void OS_TaskStatStkChk (void) +{ + OS_TCB *ptcb; + OS_STK_DATA stk_data; + INT8U err; + INT8U prio; + + + for (prio = 0u; prio <= OS_TASK_IDLE_PRIO; prio++) { + err = OSTaskStkChk(prio, &stk_data); + if (err == OS_ERR_NONE) { + ptcb = OSTCBPrioTbl[prio]; + if (ptcb != (OS_TCB *)0) { /* Make sure task 'ptcb' is ... */ + if (ptcb != OS_TCB_RESERVED) { /* ... still valid. */ +#if OS_TASK_PROFILE_EN > 0u + #if OS_STK_GROWTH == 1u + ptcb->OSTCBStkBase = ptcb->OSTCBStkBottom + ptcb->OSTCBStkSize; + #else + ptcb->OSTCBStkBase = ptcb->OSTCBStkBottom - ptcb->OSTCBStkSize; + #endif + ptcb->OSTCBStkUsed = stk_data.OSUsed; /* Store the number of bytes used */ +#endif + } + } + } + } +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* INITIALIZE TCB +* +* Description: This function is internal to uC/OS-II and is used to initialize a Task Control Block when +* a task is created (see OSTaskCreate() and OSTaskCreateExt()). +* +* Arguments : prio is the priority of the task being created +* +* ptos is a pointer to the task's top-of-stack assuming that the CPU registers +* have been placed on the stack. Note that the top-of-stack corresponds to a +* 'high' memory location is OS_STK_GROWTH is set to 1 and a 'low' memory +* location if OS_STK_GROWTH is set to 0. Note that stack growth is CPU +* specific. +* +* pbos is a pointer to the bottom of stack. A NULL pointer is passed if called by +* 'OSTaskCreate()'. +* +* id is the task's ID (0..65535) +* +* stk_size is the size of the stack (in 'stack units'). If the stack units are INT8Us +* then, 'stk_size' contains the number of bytes for the stack. If the stack +* units are INT32Us then, the stack contains '4 * stk_size' bytes. The stack +* units are established by the #define constant OS_STK which is CPU +* specific. 'stk_size' is 0 if called by 'OSTaskCreate()'. +* +* pext is a pointer to a user supplied memory area that is used to extend the task +* control block. This allows you to store the contents of floating-point +* registers, MMU registers or anything else you could find useful during a +* context switch. You can even assign a name to each task and store this name +* in this TCB extension. A NULL pointer is passed if called by OSTaskCreate(). +* +* opt options as passed to 'OSTaskCreateExt()' or, +* 0 if called from 'OSTaskCreate()'. +* +* Returns : OS_ERR_NONE if the call was successful +* OS_ERR_TASK_NO_MORE_TCB if there are no more free TCBs to be allocated and thus, the task cannot +* be created. +* +* Note : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +INT8U OS_TCBInit (INT8U prio, + OS_STK *ptos, + OS_STK *pbos, + INT16U id, + INT32U stk_size, + void *pext, + INT16U opt) +{ + OS_TCB *ptcb; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif +#if OS_TASK_REG_TBL_SIZE > 0u + INT8U i; +#endif + + + OS_ENTER_CRITICAL(); + ptcb = OSTCBFreeList; /* Get a free TCB from the free TCB list */ + if (ptcb != (OS_TCB *)0) { + OSTCBFreeList = ptcb->OSTCBNext; /* Update pointer to free TCB list */ + OS_EXIT_CRITICAL(); + ptcb->OSTCBStkPtr = ptos; /* Load Stack pointer in TCB */ + ptcb->OSTCBPrio = prio; /* Load task priority into TCB */ + ptcb->OSTCBStat = OS_STAT_RDY; /* Task is ready to run */ + ptcb->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ + ptcb->OSTCBDly = 0u; /* Task is not delayed */ + +#if OS_TASK_CREATE_EXT_EN > 0u + ptcb->OSTCBExtPtr = pext; /* Store pointer to TCB extension */ + ptcb->OSTCBStkSize = stk_size; /* Store stack size */ + ptcb->OSTCBStkBottom = pbos; /* Store pointer to bottom of stack */ + ptcb->OSTCBOpt = opt; /* Store task options */ + ptcb->OSTCBId = id; /* Store task ID */ +#else + pext = pext; /* Prevent compiler warning if not used */ + stk_size = stk_size; + pbos = pbos; + opt = opt; + id = id; +#endif + +#if OS_TASK_DEL_EN > 0u + ptcb->OSTCBDelReq = OS_ERR_NONE; +#endif + +#if OS_LOWEST_PRIO <= 63u /* Pre-compute X, Y */ + ptcb->OSTCBY = (INT8U)(prio >> 3u); + ptcb->OSTCBX = (INT8U)(prio & 0x07u); +#else /* Pre-compute X, Y */ + ptcb->OSTCBY = (INT8U)((INT8U)(prio >> 4u) & 0xFFu); + ptcb->OSTCBX = (INT8U) (prio & 0x0Fu); +#endif + /* Pre-compute BitX and BitY */ + ptcb->OSTCBBitY = (OS_PRIO)(1uL << ptcb->OSTCBY); + ptcb->OSTCBBitX = (OS_PRIO)(1uL << ptcb->OSTCBX); + +#if (OS_EVENT_EN) + ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* Task is not pending on an event */ +#if (OS_EVENT_MULTI_EN > 0u) + ptcb->OSTCBEventMultiPtr = (OS_EVENT **)0; /* Task is not pending on any events */ +#endif +#endif + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) && (OS_TASK_DEL_EN > 0u) + ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; /* Task is not pending on an event flag */ +#endif + +#if (OS_MBOX_EN > 0u) || ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) + ptcb->OSTCBMsg = (void *)0; /* No message received */ +#endif + +#if OS_TASK_PROFILE_EN > 0u + ptcb->OSTCBCtxSwCtr = 0uL; /* Initialize profiling variables */ + ptcb->OSTCBCyclesStart = 0uL; + ptcb->OSTCBCyclesTot = 0uL; + ptcb->OSTCBStkBase = (OS_STK *)0; + ptcb->OSTCBStkUsed = 0uL; +#endif + +#if OS_TASK_NAME_EN > 0u + ptcb->OSTCBTaskName = (INT8U *)(void *)"?"; +#endif + +#if OS_TASK_REG_TBL_SIZE > 0u /* Initialize the task variables */ + for (i = 0u; i < OS_TASK_REG_TBL_SIZE; i++) { + ptcb->OSTCBRegTbl[i] = 0u; + } +#endif + + OSTCBInitHook(ptcb); + + OSTaskCreateHook(ptcb); /* Call user defined hook */ + + OS_ENTER_CRITICAL(); + OSTCBPrioTbl[prio] = ptcb; + ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain */ + ptcb->OSTCBPrev = (OS_TCB *)0; + if (OSTCBList != (OS_TCB *)0) { + OSTCBList->OSTCBPrev = ptcb; + } + OSTCBList = ptcb; + OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */ + OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; + OSTaskCtr++; /* Increment the #tasks counter */ + OS_EXIT_CRITICAL(); + return (OS_ERR_NONE); + } + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NO_MORE_TCB); +} + diff --git a/UCOSII/CORE/os_flag.c b/UCOSII/CORE/os_flag.c new file mode 100644 index 0000000..abd0d1e --- /dev/null +++ b/UCOSII/CORE/os_flag.c @@ -0,0 +1,1215 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* EVENT FLAG MANAGEMENT +* +* (c) Copyright 1992-2009, Micrium, Weston, FL +* All Rights Reserved +* +* File : OS_FLAG.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 Micrim 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 +#endif + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +/* +********************************************************************************************************* +* LOCAL PROTOTYPES +********************************************************************************************************* +*/ + +static void OS_FlagBlock(OS_FLAG_GRP *pgrp, OS_FLAG_NODE *pnode, OS_FLAGS flags, INT8U wait_type, INT32U timeout); +static BOOLEAN OS_FlagTaskRdy(OS_FLAG_NODE *pnode, OS_FLAGS flags_rdy); + +/*$PAGE*/ +/* +********************************************************************************************************* +* CHECK THE STATUS OF FLAGS IN AN EVENT FLAG GROUP +* +* Description: This function is called to check the status of a combination of bits to be set or cleared +* in an event flag group. Your application can check for ANY bit to be set/cleared or ALL +* bits to be set/cleared. +* +* This call does not block if the desired flags are not present. +* +* Arguments : pgrp is a pointer to the desired event flag group. +* +* flags Is a bit pattern indicating which bit(s) (i.e. flags) you wish to check. +* The bits you want are specified by setting the corresponding bits in +* 'flags'. e.g. if your application wants to wait for bits 0 and 1 then +* 'flags' would contain 0x03. +* +* wait_type specifies whether you want ALL bits to be set/cleared or ANY of the bits +* to be set/cleared. +* You can specify the following argument: +* +* OS_FLAG_WAIT_CLR_ALL You will check ALL bits in 'flags' to be clear (0) +* OS_FLAG_WAIT_CLR_ANY You will check ANY bit in 'flags' to be clear (0) +* OS_FLAG_WAIT_SET_ALL You will check ALL bits in 'flags' to be set (1) +* OS_FLAG_WAIT_SET_ANY You will check ANY bit in 'flags' to be set (1) +* +* NOTE: Add OS_FLAG_CONSUME if you want the event flag to be 'consumed' by +* the call. Example, to wait for any flag in a group AND then clear +* the flags that are present, set 'wait_type' to: +* +* OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME +* +* perr is a pointer to an error code and can be: +* OS_ERR_NONE No error +* OS_ERR_EVENT_TYPE You are not pointing to an event flag group +* OS_ERR_FLAG_WAIT_TYPE You didn't specify a proper 'wait_type' argument. +* OS_ERR_FLAG_INVALID_PGRP You passed a NULL pointer instead of the event flag +* group handle. +* OS_ERR_FLAG_NOT_RDY The desired flags you are waiting for are not +* available. +* +* Returns : The flags in the event flag group that made the task ready or, 0 if a timeout or an error +* occurred. +* +* Called from: Task or ISR +* +* Note(s) : 1) IMPORTANT, the behavior of this function has changed from PREVIOUS versions. The +* function NOW returns the flags that were ready INSTEAD of the current state of the +* event flags. +********************************************************************************************************* +*/ + +#if OS_FLAG_ACCEPT_EN > 0u +OS_FLAGS OSFlagAccept (OS_FLAG_GRP *pgrp, + OS_FLAGS flags, + INT8U wait_type, + INT8U *perr) +{ + OS_FLAGS flags_rdy; + INT8U result; + BOOLEAN consume; +#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 (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */ + *perr = OS_ERR_FLAG_INVALID_PGRP; + return ((OS_FLAGS)0); + } +#endif + if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + return ((OS_FLAGS)0); + } + result = (INT8U)(wait_type & OS_FLAG_CONSUME); + if (result != (INT8U)0) { /* See if we need to consume the flags */ + wait_type &= ~OS_FLAG_CONSUME; + consume = OS_TRUE; + } else { + consume = OS_FALSE; + } +/*$PAGE*/ + *perr = OS_ERR_NONE; /* Assume NO error until proven otherwise. */ + OS_ENTER_CRITICAL(); + switch (wait_type) { + case OS_FLAG_WAIT_SET_ALL: /* See if all required flags are set */ + flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /* Extract only the bits we want */ + if (flags_rdy == flags) { /* Must match ALL the bits that we want */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /* Clear ONLY the flags we wanted */ + } + } else { + *perr = OS_ERR_FLAG_NOT_RDY; + } + OS_EXIT_CRITICAL(); + break; + + case OS_FLAG_WAIT_SET_ANY: + flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /* Extract only the bits we want */ + if (flags_rdy != (OS_FLAGS)0) { /* See if any flag set */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /* Clear ONLY the flags we got */ + } + } else { + *perr = OS_ERR_FLAG_NOT_RDY; + } + OS_EXIT_CRITICAL(); + break; + +#if OS_FLAG_WAIT_CLR_EN > 0u + case OS_FLAG_WAIT_CLR_ALL: /* See if all required flags are cleared */ + flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */ + if (flags_rdy == flags) { /* Must match ALL the bits that we want */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we wanted */ + } + } else { + *perr = OS_ERR_FLAG_NOT_RDY; + } + OS_EXIT_CRITICAL(); + break; + + case OS_FLAG_WAIT_CLR_ANY: + flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */ + if (flags_rdy != (OS_FLAGS)0) { /* See if any flag cleared */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we got */ + } + } else { + *perr = OS_ERR_FLAG_NOT_RDY; + } + OS_EXIT_CRITICAL(); + break; +#endif + + default: + OS_EXIT_CRITICAL(); + flags_rdy = (OS_FLAGS)0; + *perr = OS_ERR_FLAG_WAIT_TYPE; + break; + } + return (flags_rdy); +} +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* CREATE AN EVENT FLAG +* +* Description: This function is called to create an event flag group. +* +* Arguments : flags Contains the initial value to store in the event flag group. +* +* 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 an Event Flag from an +* ISR. +* OS_ERR_FLAG_GRP_DEPLETED if there are no more event flag groups +* +* Returns : A pointer to an event flag group or a NULL pointer if no more groups are available. +* +* Called from: Task ONLY +********************************************************************************************************* +*/ + +OS_FLAG_GRP *OSFlagCreate (OS_FLAGS flags, + INT8U *perr) +{ + OS_FLAG_GRP *pgrp; +#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 (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_CREATE_ISR; /* ... can't CREATE from an ISR */ + return ((OS_FLAG_GRP *)0); + } + OS_ENTER_CRITICAL(); + pgrp = OSFlagFreeList; /* Get next free event flag */ + if (pgrp != (OS_FLAG_GRP *)0) { /* See if we have event flag groups available */ + /* Adjust free list */ + OSFlagFreeList = (OS_FLAG_GRP *)OSFlagFreeList->OSFlagWaitList; + pgrp->OSFlagType = OS_EVENT_TYPE_FLAG; /* Set to event flag group type */ + pgrp->OSFlagFlags = flags; /* Set to desired initial value */ + pgrp->OSFlagWaitList = (void *)0; /* Clear list of tasks waiting on flags */ +#if OS_FLAG_NAME_EN > 0u + pgrp->OSFlagName = (INT8U *)(void *)"?"; +#endif + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + } else { + OS_EXIT_CRITICAL(); + *perr = OS_ERR_FLAG_GRP_DEPLETED; + } + return (pgrp); /* Return pointer to event flag group */ +} + +/*$PAGE*/ +/* +********************************************************************************************************* +* DELETE AN EVENT FLAG GROUP +* +* Description: This function deletes an event flag group and readies all tasks pending on the event flag +* group. +* +* Arguments : pgrp is a pointer to the desired event flag group. +* +* opt determines delete options as follows: +* opt == OS_DEL_NO_PEND Deletes the event flag group ONLY if no task pending +* opt == OS_DEL_ALWAYS Deletes the event flag group 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 event flag group was +* deleted +* OS_ERR_DEL_ISR If you attempted to delete the event flag group from +* an ISR +* OS_ERR_FLAG_INVALID_PGRP If 'pgrp' is a NULL pointer. +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to an event flag group +* OS_ERR_INVALID_OPT An invalid option was specified +* OS_ERR_TASK_WAITING One or more tasks were waiting on the event flag +* group. +* +* Returns : pgrp upon error +* (OS_EVENT *)0 if the event flag group was successfully deleted. +* +* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of +* the event flag group MUST check the return code of OSFlagAccept() and OSFlagPend(). +* 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 event flag group. +********************************************************************************************************* +*/ + +#if OS_FLAG_DEL_EN > 0u +OS_FLAG_GRP *OSFlagDel (OS_FLAG_GRP *pgrp, + INT8U opt, + INT8U *perr) +{ + BOOLEAN tasks_waiting; + OS_FLAG_NODE *pnode; + OS_FLAG_GRP *pgrp_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 (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */ + *perr = OS_ERR_FLAG_INVALID_PGRP; + return (pgrp); + } +#endif + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ + return (pgrp); + } + if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event group type */ + *perr = OS_ERR_EVENT_TYPE; + return (pgrp); + } + OS_ENTER_CRITICAL(); + if (pgrp->OSFlagWaitList != (void *)0) { /* See if any tasks waiting on event flags */ + tasks_waiting = OS_TRUE; /* Yes */ + } else { + tasks_waiting = OS_FALSE; /* No */ + } + switch (opt) { + case OS_DEL_NO_PEND: /* Delete group if no task waiting */ + if (tasks_waiting == OS_FALSE) { +#if OS_FLAG_NAME_EN > 0u + pgrp->OSFlagName = (INT8U *)(void *)"?"; +#endif + pgrp->OSFlagType = OS_EVENT_TYPE_UNUSED; + pgrp->OSFlagWaitList = (void *)OSFlagFreeList; /* Return group to free list */ + pgrp->OSFlagFlags = (OS_FLAGS)0; + OSFlagFreeList = pgrp; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + pgrp_return = (OS_FLAG_GRP *)0; /* Event Flag Group has been deleted */ + } else { + OS_EXIT_CRITICAL(); + *perr = OS_ERR_TASK_WAITING; + pgrp_return = pgrp; + } + break; + + case OS_DEL_ALWAYS: /* Always delete the event flag group */ + pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList; + while (pnode != (OS_FLAG_NODE *)0) { /* Ready ALL tasks waiting for flags */ + (void)OS_FlagTaskRdy(pnode, (OS_FLAGS)0); + pnode = (OS_FLAG_NODE *)pnode->OSFlagNodeNext; + } +#if OS_FLAG_NAME_EN > 0u + pgrp->OSFlagName = (INT8U *)(void *)"?"; +#endif + pgrp->OSFlagType = OS_EVENT_TYPE_UNUSED; + pgrp->OSFlagWaitList = (void *)OSFlagFreeList;/* Return group to free list */ + pgrp->OSFlagFlags = (OS_FLAGS)0; + OSFlagFreeList = pgrp; + 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; + pgrp_return = (OS_FLAG_GRP *)0; /* Event Flag Group has been deleted */ + break; + + default: + OS_EXIT_CRITICAL(); + *perr = OS_ERR_INVALID_OPT; + pgrp_return = pgrp; + break; + } + return (pgrp_return); +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* GET THE NAME OF AN EVENT FLAG GROUP +* +* Description: This function is used to obtain the name assigned to an event flag group +* +* Arguments : pgrp is a pointer to the event flag group. +* +* pname is pointer to a pointer to an ASCII string that will receive the name of the event flag +* group. +* +* perr is a pointer to an error code that can contain one of the following values: +* +* OS_ERR_NONE if the requested task is resumed +* OS_ERR_EVENT_TYPE if 'pevent' is not pointing to an event flag group +* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' +* OS_ERR_FLAG_INVALID_PGRP if you passed a NULL pointer for 'pgrp' +* OS_ERR_NAME_GET_ISR if you called this function from an ISR +* +* Returns : The length of the string or 0 if the 'pgrp' is a NULL pointer. +********************************************************************************************************* +*/ + +#if OS_FLAG_NAME_EN > 0u +INT8U OSFlagNameGet (OS_FLAG_GRP *pgrp, + 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 (pgrp == (OS_FLAG_GRP *)0) { /* Is 'pgrp' a NULL pointer? */ + *perr = OS_ERR_FLAG_INVALID_PGRP; + 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(); + if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { + OS_EXIT_CRITICAL(); + *perr = OS_ERR_EVENT_TYPE; + return (0u); + } + *pname = pgrp->OSFlagName; + len = OS_StrLen(*pname); + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (len); +} +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* ASSIGN A NAME TO AN EVENT FLAG GROUP +* +* Description: This function assigns a name to an event flag group. +* +* Arguments : pgrp is a pointer to the event flag group. +* +* pname is a pointer to an ASCII string that will be used as the name of the event flag +* group. +* +* perr is a pointer to an error code that can contain one of the following values: +* +* OS_ERR_NONE if the requested task is resumed +* OS_ERR_EVENT_TYPE if 'pevent' is not pointing to an event flag group +* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' +* OS_ERR_FLAG_INVALID_PGRP if you passed a NULL pointer for 'pgrp' +* OS_ERR_NAME_SET_ISR if you called this function from an ISR +* +* Returns : None +********************************************************************************************************* +*/ + +#if OS_FLAG_NAME_EN > 0u +void OSFlagNameSet (OS_FLAG_GRP *pgrp, + 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 (pgrp == (OS_FLAG_GRP *)0) { /* Is 'pgrp' a NULL pointer? */ + *perr = OS_ERR_FLAG_INVALID_PGRP; + 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(); + if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { + OS_EXIT_CRITICAL(); + *perr = OS_ERR_EVENT_TYPE; + return; + } + pgrp->OSFlagName = pname; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return; +} +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* WAIT ON AN EVENT FLAG GROUP +* +* Description: This function is called to wait for a combination of bits to be set in an event flag +* group. Your application can wait for ANY bit to be set or ALL bits to be set. +* +* Arguments : pgrp is a pointer to the desired event flag group. +* +* flags Is a bit pattern indicating which bit(s) (i.e. flags) you wish to wait for. +* The bits you want are specified by setting the corresponding bits in +* 'flags'. e.g. if your application wants to wait for bits 0 and 1 then +* 'flags' would contain 0x03. +* +* wait_type specifies whether you want ALL bits to be set or ANY of the bits to be set. +* You can specify the following argument: +* +* OS_FLAG_WAIT_CLR_ALL You will wait for ALL bits in 'mask' to be clear (0) +* OS_FLAG_WAIT_SET_ALL You will wait for ALL bits in 'mask' to be set (1) +* OS_FLAG_WAIT_CLR_ANY You will wait for ANY bit in 'mask' to be clear (0) +* OS_FLAG_WAIT_SET_ANY You will wait for ANY bit in 'mask' to be set (1) +* +* NOTE: Add OS_FLAG_CONSUME if you want the event flag to be 'consumed' by +* the call. Example, to wait for any flag in a group AND then clear +* the flags that are present, set 'wait_type' to: +* +* OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME +* +* timeout is an optional timeout (in clock ticks) that your task will wait for the +* desired bit combination. If you specify 0, however, your task will wait +* forever at the specified event flag group or, until a message arrives. +* +* perr is a pointer to an error code and can be: +* OS_ERR_NONE The desired bits have been set within the specified +* 'timeout'. +* OS_ERR_PEND_ISR If you tried to PEND from an ISR +* OS_ERR_FLAG_INVALID_PGRP If 'pgrp' is a NULL pointer. +* OS_ERR_EVENT_TYPE You are not pointing to an event flag group +* OS_ERR_TIMEOUT The bit(s) have not been set in the specified +* 'timeout'. +* OS_ERR_PEND_ABORT The wait on the flag was aborted. +* OS_ERR_FLAG_WAIT_TYPE You didn't specify a proper 'wait_type' argument. +* +* Returns : The flags in the event flag group that made the task ready or, 0 if a timeout or an error +* occurred. +* +* Called from: Task ONLY +* +* Note(s) : 1) IMPORTANT, the behavior of this function has changed from PREVIOUS versions. The +* function NOW returns the flags that were ready INSTEAD of the current state of the +* event flags. +********************************************************************************************************* +*/ + +OS_FLAGS OSFlagPend (OS_FLAG_GRP *pgrp, + OS_FLAGS flags, + INT8U wait_type, + INT32U timeout, + INT8U *perr) +{ + OS_FLAG_NODE node; + OS_FLAGS flags_rdy; + INT8U result; + INT8U pend_stat; + BOOLEAN consume; +#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 (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */ + *perr = OS_ERR_FLAG_INVALID_PGRP; + return ((OS_FLAGS)0); + } +#endif + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ + return ((OS_FLAGS)0); + } + if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ + *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ + return ((OS_FLAGS)0); + } + if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + return ((OS_FLAGS)0); + } + result = (INT8U)(wait_type & OS_FLAG_CONSUME); + if (result != (INT8U)0) { /* See if we need to consume the flags */ + wait_type &= (INT8U)~(INT8U)OS_FLAG_CONSUME; + consume = OS_TRUE; + } else { + consume = OS_FALSE; + } +/*$PAGE*/ + OS_ENTER_CRITICAL(); + switch (wait_type) { + case OS_FLAG_WAIT_SET_ALL: /* See if all required flags are set */ + flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /* Extract only the bits we want */ + if (flags_rdy == flags) { /* Must match ALL the bits that we want */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /* Clear ONLY the flags we wanted */ + } + OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */ + OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ + *perr = OS_ERR_NONE; + return (flags_rdy); + } else { /* Block task until events occur or timeout */ + OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); + OS_EXIT_CRITICAL(); + } + break; + + case OS_FLAG_WAIT_SET_ANY: + flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /* Extract only the bits we want */ + if (flags_rdy != (OS_FLAGS)0) { /* See if any flag set */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /* Clear ONLY the flags that we got */ + } + OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */ + OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ + *perr = OS_ERR_NONE; + return (flags_rdy); + } else { /* Block task until events occur or timeout */ + OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); + OS_EXIT_CRITICAL(); + } + break; + +#if OS_FLAG_WAIT_CLR_EN > 0u + case OS_FLAG_WAIT_CLR_ALL: /* See if all required flags are cleared */ + flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */ + if (flags_rdy == flags) { /* Must match ALL the bits that we want */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we wanted */ + } + OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */ + OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ + *perr = OS_ERR_NONE; + return (flags_rdy); + } else { /* Block task until events occur or timeout */ + OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); + OS_EXIT_CRITICAL(); + } + break; + + case OS_FLAG_WAIT_CLR_ANY: + flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */ + if (flags_rdy != (OS_FLAGS)0) { /* See if any flag cleared */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we got */ + } + OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */ + OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ + *perr = OS_ERR_NONE; + return (flags_rdy); + } else { /* Block task until events occur or timeout */ + OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); + OS_EXIT_CRITICAL(); + } + break; +#endif + + default: + OS_EXIT_CRITICAL(); + flags_rdy = (OS_FLAGS)0; + *perr = OS_ERR_FLAG_WAIT_TYPE; + return (flags_rdy); + } +/*$PAGE*/ + OS_Sched(); /* Find next HPT ready to run */ + OS_ENTER_CRITICAL(); + if (OSTCBCur->OSTCBStatPend != OS_STAT_PEND_OK) { /* Have we timed-out or aborted? */ + pend_stat = OSTCBCur->OSTCBStatPend; + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; + OS_FlagUnlink(&node); + OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Yes, make task ready-to-run */ + OS_EXIT_CRITICAL(); + flags_rdy = (OS_FLAGS)0; + switch (pend_stat) { + case OS_STAT_PEND_ABORT: + *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted waiting */ + break; + + case OS_STAT_PEND_TO: + default: + *perr = OS_ERR_TIMEOUT; /* Indicate that we timed-out waiting */ + break; + } + return (flags_rdy); + } + flags_rdy = OSTCBCur->OSTCBFlagsRdy; + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + switch (wait_type) { + case OS_FLAG_WAIT_SET_ALL: + case OS_FLAG_WAIT_SET_ANY: /* Clear ONLY the flags we got */ + pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; + break; + +#if OS_FLAG_WAIT_CLR_EN > 0u + case OS_FLAG_WAIT_CLR_ALL: + case OS_FLAG_WAIT_CLR_ANY: /* Set ONLY the flags we got */ + pgrp->OSFlagFlags |= flags_rdy; + break; +#endif + default: + OS_EXIT_CRITICAL(); + *perr = OS_ERR_FLAG_WAIT_TYPE; + return ((OS_FLAGS)0); + } + } + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; /* Event(s) must have occurred */ + return (flags_rdy); +} +/*$PAGE*/ +/* +********************************************************************************************************* +* GET FLAGS WHO CAUSED TASK TO BECOME READY +* +* Description: This function is called to obtain the flags that caused the task to become ready to run. +* In other words, this function allows you to tell "Who done it!". +* +* Arguments : None +* +* Returns : The flags that caused the task to be ready. +* +* Called from: Task ONLY +********************************************************************************************************* +*/ + +OS_FLAGS OSFlagPendGetFlagsRdy (void) +{ + OS_FLAGS flags; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + OS_ENTER_CRITICAL(); + flags = OSTCBCur->OSTCBFlagsRdy; + OS_EXIT_CRITICAL(); + return (flags); +} + +/*$PAGE*/ +/* +********************************************************************************************************* +* POST EVENT FLAG BIT(S) +* +* Description: This function is called to set or clear some bits in an event flag group. The bits to +* set or clear are specified by a 'bit mask'. +* +* Arguments : pgrp is a pointer to the desired event flag group. +* +* flags If 'opt' (see below) is OS_FLAG_SET, each bit that is set in 'flags' will +* set the corresponding bit in the event flag group. e.g. to set bits 0, 4 +* and 5 you would set 'flags' to: +* +* 0x31 (note, bit 0 is least significant bit) +* +* If 'opt' (see below) is OS_FLAG_CLR, each bit that is set in 'flags' will +* CLEAR the corresponding bit in the event flag group. e.g. to clear bits 0, +* 4 and 5 you would specify 'flags' as: +* +* 0x31 (note, bit 0 is least significant bit) +* +* opt indicates whether the flags will be: +* set (OS_FLAG_SET) or +* cleared (OS_FLAG_CLR) +* +* perr is a pointer to an error code and can be: +* OS_ERR_NONE The call was successfull +* OS_ERR_FLAG_INVALID_PGRP You passed a NULL pointer +* OS_ERR_EVENT_TYPE You are not pointing to an event flag group +* OS_ERR_FLAG_INVALID_OPT You specified an invalid option +* +* Returns : the new value of the event flags bits that are still set. +* +* Called From: Task or ISR +* +* WARNING(s) : 1) The execution time of this function depends on the number of tasks waiting on the event +* flag group. +* 2) The amount of time interrupts are DISABLED depends on the number of tasks waiting on +* the event flag group. +********************************************************************************************************* +*/ +OS_FLAGS OSFlagPost (OS_FLAG_GRP *pgrp, + OS_FLAGS flags, + INT8U opt, + INT8U *perr) +{ + OS_FLAG_NODE *pnode; + BOOLEAN sched; + OS_FLAGS flags_cur; + OS_FLAGS flags_rdy; + BOOLEAN rdy; +#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 (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */ + *perr = OS_ERR_FLAG_INVALID_PGRP; + return ((OS_FLAGS)0); + } +#endif + if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Make sure we are pointing to an event flag grp */ + *perr = OS_ERR_EVENT_TYPE; + return ((OS_FLAGS)0); + } +/*$PAGE*/ + OS_ENTER_CRITICAL(); + switch (opt) { + case OS_FLAG_CLR: + pgrp->OSFlagFlags &= (OS_FLAGS)~flags; /* Clear the flags specified in the group */ + break; + + case OS_FLAG_SET: + pgrp->OSFlagFlags |= flags; /* Set the flags specified in the group */ + break; + + default: + OS_EXIT_CRITICAL(); /* INVALID option */ + *perr = OS_ERR_FLAG_INVALID_OPT; + return ((OS_FLAGS)0); + } + sched = OS_FALSE; /* Indicate that we don't need rescheduling */ + pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList; + while (pnode != (OS_FLAG_NODE *)0) { /* Go through all tasks waiting on event flag(s) */ + switch (pnode->OSFlagNodeWaitType) { + case OS_FLAG_WAIT_SET_ALL: /* See if all req. flags are set for current node */ + flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & pnode->OSFlagNodeFlags); + if (flags_rdy == pnode->OSFlagNodeFlags) { + rdy = OS_FlagTaskRdy(pnode, flags_rdy); /* Make task RTR, event(s) Rx'd */ + if (rdy == OS_TRUE) { + sched = OS_TRUE; /* When done we will reschedule */ + } + } + break; + + case OS_FLAG_WAIT_SET_ANY: /* See if any flag set */ + flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & pnode->OSFlagNodeFlags); + if (flags_rdy != (OS_FLAGS)0) { + rdy = OS_FlagTaskRdy(pnode, flags_rdy); /* Make task RTR, event(s) Rx'd */ + if (rdy == OS_TRUE) { + sched = OS_TRUE; /* When done we will reschedule */ + } + } + break; + +#if OS_FLAG_WAIT_CLR_EN > 0u + case OS_FLAG_WAIT_CLR_ALL: /* See if all req. flags are set for current node */ + flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & pnode->OSFlagNodeFlags; + if (flags_rdy == pnode->OSFlagNodeFlags) { + rdy = OS_FlagTaskRdy(pnode, flags_rdy); /* Make task RTR, event(s) Rx'd */ + if (rdy == OS_TRUE) { + sched = OS_TRUE; /* When done we will reschedule */ + } + } + break; + + case OS_FLAG_WAIT_CLR_ANY: /* See if any flag set */ + flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & pnode->OSFlagNodeFlags; + if (flags_rdy != (OS_FLAGS)0) { + rdy = OS_FlagTaskRdy(pnode, flags_rdy); /* Make task RTR, event(s) Rx'd */ + if (rdy == OS_TRUE) { + sched = OS_TRUE; /* When done we will reschedule */ + } + } + break; +#endif + default: + OS_EXIT_CRITICAL(); + *perr = OS_ERR_FLAG_WAIT_TYPE; + return ((OS_FLAGS)0); + } + pnode = (OS_FLAG_NODE *)pnode->OSFlagNodeNext; /* Point to next task waiting for event flag(s) */ + } + OS_EXIT_CRITICAL(); + if (sched == OS_TRUE) { + OS_Sched(); + } + OS_ENTER_CRITICAL(); + flags_cur = pgrp->OSFlagFlags; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (flags_cur); +} +/*$PAGE*/ +/* +********************************************************************************************************* +* QUERY EVENT FLAG +* +* Description: This function is used to check the value of the event flag group. +* +* Arguments : pgrp is a pointer to the desired event flag group. +* +* perr is a pointer to an error code returned to the called: +* OS_ERR_NONE The call was successfull +* OS_ERR_FLAG_INVALID_PGRP You passed a NULL pointer +* OS_ERR_EVENT_TYPE You are not pointing to an event flag group +* +* Returns : The current value of the event flag group. +* +* Called From: Task or ISR +********************************************************************************************************* +*/ + +#if OS_FLAG_QUERY_EN > 0u +OS_FLAGS OSFlagQuery (OS_FLAG_GRP *pgrp, + INT8U *perr) +{ + OS_FLAGS flags; +#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 (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */ + *perr = OS_ERR_FLAG_INVALID_PGRP; + return ((OS_FLAGS)0); + } +#endif + if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + return ((OS_FLAGS)0); + } + OS_ENTER_CRITICAL(); + flags = pgrp->OSFlagFlags; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (flags); /* Return the current value of the event flags */ +} +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* SUSPEND TASK UNTIL EVENT FLAG(s) RECEIVED OR TIMEOUT OCCURS +* +* Description: This function is internal to uC/OS-II and is used to put a task to sleep until the desired +* event flag bit(s) are set. +* +* Arguments : pgrp is a pointer to the desired event flag group. +* +* pnode is a pointer to a structure which contains data about the task waiting for +* event flag bit(s) to be set. +* +* flags Is a bit pattern indicating which bit(s) (i.e. flags) you wish to check. +* The bits you want are specified by setting the corresponding bits in +* 'flags'. e.g. if your application wants to wait for bits 0 and 1 then +* 'flags' would contain 0x03. +* +* wait_type specifies whether you want ALL bits to be set/cleared or ANY of the bits +* to be set/cleared. +* You can specify the following argument: +* +* OS_FLAG_WAIT_CLR_ALL You will check ALL bits in 'mask' to be clear (0) +* OS_FLAG_WAIT_CLR_ANY You will check ANY bit in 'mask' to be clear (0) +* OS_FLAG_WAIT_SET_ALL You will check ALL bits in 'mask' to be set (1) +* OS_FLAG_WAIT_SET_ANY You will check ANY bit in 'mask' to be set (1) +* +* timeout is the desired amount of time that the task will wait for the event flag +* bit(s) to be set. +* +* Returns : none +* +* Called by : OSFlagPend() OS_FLAG.C +* +* Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +static void OS_FlagBlock (OS_FLAG_GRP *pgrp, + OS_FLAG_NODE *pnode, + OS_FLAGS flags, + INT8U wait_type, + INT32U timeout) +{ + OS_FLAG_NODE *pnode_next; + INT8U y; + + + OSTCBCur->OSTCBStat |= OS_STAT_FLAG; + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; + OSTCBCur->OSTCBDly = timeout; /* Store timeout in task's TCB */ +#if OS_TASK_DEL_EN > 0u + OSTCBCur->OSTCBFlagNode = pnode; /* TCB to link to node */ +#endif + pnode->OSFlagNodeFlags = flags; /* Save the flags that we need to wait for */ + pnode->OSFlagNodeWaitType = wait_type; /* Save the type of wait we are doing */ + pnode->OSFlagNodeTCB = (void *)OSTCBCur; /* Link to task's TCB */ + pnode->OSFlagNodeNext = pgrp->OSFlagWaitList; /* Add node at beginning of event flag wait list */ + pnode->OSFlagNodePrev = (void *)0; + pnode->OSFlagNodeFlagGrp = (void *)pgrp; /* Link to Event Flag Group */ + pnode_next = (OS_FLAG_NODE *)pgrp->OSFlagWaitList; + if (pnode_next != (void *)0) { /* Is this the first NODE to insert? */ + pnode_next->OSFlagNodePrev = pnode; /* No, link in doubly linked list */ + } + pgrp->OSFlagWaitList = (void *)pnode; + + y = OSTCBCur->OSTCBY; /* Suspend current task until flag(s) received */ + OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX; + if (OSRdyTbl[y] == 0x00u) { + OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY; + } +} + +/*$PAGE*/ +/* +********************************************************************************************************* +* INITIALIZE THE EVENT FLAG MODULE +* +* Description: This function is called by uC/OS-II to initialize the event flag module. Your application +* MUST NOT call this function. In other words, this function is internal to uC/OS-II. +* +* Arguments : none +* +* Returns : none +* +* WARNING : You MUST NOT call this function from your code. This is an INTERNAL function to uC/OS-II. +********************************************************************************************************* +*/ + +void OS_FlagInit (void) +{ +#if OS_MAX_FLAGS == 1u + OSFlagFreeList = (OS_FLAG_GRP *)&OSFlagTbl[0]; /* Only ONE event flag group! */ + OSFlagFreeList->OSFlagType = OS_EVENT_TYPE_UNUSED; + OSFlagFreeList->OSFlagWaitList = (void *)0; + OSFlagFreeList->OSFlagFlags = (OS_FLAGS)0; +#if OS_FLAG_NAME_EN > 0u + OSFlagFreeList->OSFlagName = (INT8U *)"?"; +#endif +#endif + +#if OS_MAX_FLAGS >= 2u + INT16U ix; + INT16U ix_next; + OS_FLAG_GRP *pgrp1; + OS_FLAG_GRP *pgrp2; + + + OS_MemClr((INT8U *)&OSFlagTbl[0], sizeof(OSFlagTbl)); /* Clear the flag group table */ + for (ix = 0u; ix < (OS_MAX_FLAGS - 1u); ix++) { /* Init. list of free EVENT FLAGS */ + ix_next = ix + 1u; + pgrp1 = &OSFlagTbl[ix]; + pgrp2 = &OSFlagTbl[ix_next]; + pgrp1->OSFlagType = OS_EVENT_TYPE_UNUSED; + pgrp1->OSFlagWaitList = (void *)pgrp2; +#if OS_FLAG_NAME_EN > 0u + pgrp1->OSFlagName = (INT8U *)(void *)"?"; /* Unknown name */ +#endif + } + pgrp1 = &OSFlagTbl[ix]; + pgrp1->OSFlagType = OS_EVENT_TYPE_UNUSED; + pgrp1->OSFlagWaitList = (void *)0; +#if OS_FLAG_NAME_EN > 0u + pgrp1->OSFlagName = (INT8U *)(void *)"?"; /* Unknown name */ +#endif + OSFlagFreeList = &OSFlagTbl[0]; +#endif +} + +/*$PAGE*/ +/* +********************************************************************************************************* +* MAKE TASK READY-TO-RUN, EVENT(s) OCCURRED +* +* Description: This function is internal to uC/OS-II and is used to make a task ready-to-run because the +* desired event flag bits have been set. +* +* Arguments : pnode is a pointer to a structure which contains data about the task waiting for +* event flag bit(s) to be set. +* +* flags_rdy contains the bit pattern of the event flags that cause the task to become +* ready-to-run. +* +* Returns : OS_TRUE If the task has been placed in the ready list and thus needs scheduling +* OS_FALSE The task is still not ready to run and thus scheduling is not necessary +* +* Called by : OSFlagsPost() OS_FLAG.C +* +* Note(s) : 1) This function assumes that interrupts are disabled. +* 2) This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +static BOOLEAN OS_FlagTaskRdy (OS_FLAG_NODE *pnode, + OS_FLAGS flags_rdy) +{ + OS_TCB *ptcb; + BOOLEAN sched; + + + ptcb = (OS_TCB *)pnode->OSFlagNodeTCB; /* Point to TCB of waiting task */ + ptcb->OSTCBDly = 0u; + ptcb->OSTCBFlagsRdy = flags_rdy; + ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_FLAG; + ptcb->OSTCBStatPend = OS_STAT_PEND_OK; + if (ptcb->OSTCBStat == OS_STAT_RDY) { /* Task now ready? */ + OSRdyGrp |= ptcb->OSTCBBitY; /* Put task into ready list */ + OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; + sched = OS_TRUE; + } else { + sched = OS_FALSE; + } + OS_FlagUnlink(pnode); + return (sched); +} + +/*$PAGE*/ +/* +********************************************************************************************************* +* UNLINK EVENT FLAG NODE FROM WAITING LIST +* +* Description: This function is internal to uC/OS-II and is used to unlink an event flag node from a +* list of tasks waiting for the event flag. +* +* Arguments : pnode is a pointer to a structure which contains data about the task waiting for +* event flag bit(s) to be set. +* +* Returns : none +* +* Called by : OS_FlagTaskRdy() OS_FLAG.C +* OSFlagPend() OS_FLAG.C +* OSTaskDel() OS_TASK.C +* +* Note(s) : 1) This function assumes that interrupts are disabled. +* 2) This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +void OS_FlagUnlink (OS_FLAG_NODE *pnode) +{ +#if OS_TASK_DEL_EN > 0u + OS_TCB *ptcb; +#endif + OS_FLAG_GRP *pgrp; + OS_FLAG_NODE *pnode_prev; + OS_FLAG_NODE *pnode_next; + + + pnode_prev = (OS_FLAG_NODE *)pnode->OSFlagNodePrev; + pnode_next = (OS_FLAG_NODE *)pnode->OSFlagNodeNext; + if (pnode_prev == (OS_FLAG_NODE *)0) { /* Is it first node in wait list? */ + pgrp = (OS_FLAG_GRP *)pnode->OSFlagNodeFlagGrp; + pgrp->OSFlagWaitList = (void *)pnode_next; /* Update list for new 1st node */ + if (pnode_next != (OS_FLAG_NODE *)0) { + pnode_next->OSFlagNodePrev = (OS_FLAG_NODE *)0; /* Link new 1st node PREV to NULL */ + } + } else { /* No, A node somewhere in the list */ + pnode_prev->OSFlagNodeNext = pnode_next; /* Link around the node to unlink */ + if (pnode_next != (OS_FLAG_NODE *)0) { /* Was this the LAST node? */ + pnode_next->OSFlagNodePrev = pnode_prev; /* No, Link around current node */ + } + } +#if OS_TASK_DEL_EN > 0u + ptcb = (OS_TCB *)pnode->OSFlagNodeTCB; + ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; +#endif +} +#endif + diff --git a/UCOSII/CORE/os_mbox.c b/UCOSII/CORE/os_mbox.c new file mode 100644 index 0000000..506b023 --- /dev/null +++ b/UCOSII/CORE/os_mbox.c @@ -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 Micrim 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 +#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 */ + diff --git a/UCOSII/CORE/os_mem.c b/UCOSII/CORE/os_mem.c new file mode 100644 index 0000000..6a92363 --- /dev/null +++ b/UCOSII/CORE/os_mem.c @@ -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 Micrim 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 +#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 */ + diff --git a/UCOSII/CORE/os_mutex.c b/UCOSII/CORE/os_mutex.c new file mode 100644 index 0000000..c34f38c --- /dev/null +++ b/UCOSII/CORE/os_mutex.c @@ -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 Micrim 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 +#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 */ + diff --git a/UCOSII/CORE/os_q.c b/UCOSII/CORE/os_q.c new file mode 100644 index 0000000..e00da5c --- /dev/null +++ b/UCOSII/CORE/os_q.c @@ -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 Micrim 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 +#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 */ + diff --git a/UCOSII/CORE/os_sem.c b/UCOSII/CORE/os_sem.c new file mode 100644 index 0000000..24ca6cf --- /dev/null +++ b/UCOSII/CORE/os_sem.c @@ -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 Micrim 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 +#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 */ + diff --git a/UCOSII/CORE/os_task.c b/UCOSII/CORE/os_task.c new file mode 100644 index 0000000..421d577 --- /dev/null +++ b/UCOSII/CORE/os_task.c @@ -0,0 +1,1263 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* TASK MANAGEMENT +* +* (c) Copyright 1992-2009, Micrium, Weston, FL +* All Rights Reserved +* +* File : OS_TASK.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 Micrim 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 +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* CHANGE PRIORITY OF A TASK +* +* Description: This function allows you to change the priority of a task dynamically. Note that the new +* priority MUST be available. +* +* Arguments : oldp is the old priority +* +* newp is the new priority +* +* Returns : OS_ERR_NONE is the call was successful +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. >= OS_LOWEST_PRIO) +* OS_ERR_PRIO_EXIST if the new priority already exist. +* OS_ERR_PRIO there is no task with the specified OLD priority (i.e. the OLD task does +* not exist. +* OS_ERR_TASK_NOT_EXIST if the task is assigned to a Mutex PIP. +********************************************************************************************************* +*/ + +#if OS_TASK_CHANGE_PRIO_EN > 0u +INT8U OSTaskChangePrio (INT8U oldprio, + INT8U newprio) +{ +#if (OS_EVENT_EN) + OS_EVENT *pevent; +#if (OS_EVENT_MULTI_EN > 0u) + OS_EVENT **pevents; +#endif +#endif + OS_TCB *ptcb; + INT8U y_new; + INT8U x_new; + INT8U y_old; + OS_PRIO bity_new; + OS_PRIO bitx_new; + OS_PRIO bity_old; + OS_PRIO bitx_old; +#if OS_CRITICAL_METHOD == 3u + OS_CPU_SR cpu_sr = 0u; /* Storage for CPU status register */ +#endif + + +/*$PAGE*/ +#if OS_ARG_CHK_EN > 0u + if (oldprio >= OS_LOWEST_PRIO) { + if (oldprio != OS_PRIO_SELF) { + return (OS_ERR_PRIO_INVALID); + } + } + if (newprio >= OS_LOWEST_PRIO) { + return (OS_ERR_PRIO_INVALID); + } +#endif + OS_ENTER_CRITICAL(); + if (OSTCBPrioTbl[newprio] != (OS_TCB *)0) { /* New priority must not already exist */ + OS_EXIT_CRITICAL(); + return (OS_ERR_PRIO_EXIST); + } + if (oldprio == OS_PRIO_SELF) { /* See if changing self */ + oldprio = OSTCBCur->OSTCBPrio; /* Yes, get priority */ + } + ptcb = OSTCBPrioTbl[oldprio]; + if (ptcb == (OS_TCB *)0) { /* Does task to change exist? */ + OS_EXIT_CRITICAL(); /* No, can't change its priority! */ + return (OS_ERR_PRIO); + } + if (ptcb == OS_TCB_RESERVED) { /* Is task assigned to Mutex */ + OS_EXIT_CRITICAL(); /* No, can't change its priority! */ + return (OS_ERR_TASK_NOT_EXIST); + } +#if OS_LOWEST_PRIO <= 63u + y_new = (INT8U)(newprio >> 3u); /* Yes, compute new TCB fields */ + x_new = (INT8U)(newprio & 0x07u); +#else + y_new = (INT8U)((INT8U)(newprio >> 4u) & 0x0Fu); + x_new = (INT8U)(newprio & 0x0Fu); +#endif + bity_new = (OS_PRIO)(1uL << y_new); + bitx_new = (OS_PRIO)(1uL << x_new); + + OSTCBPrioTbl[oldprio] = (OS_TCB *)0; /* Remove TCB from old priority */ + OSTCBPrioTbl[newprio] = ptcb; /* Place pointer to TCB @ new priority */ + y_old = ptcb->OSTCBY; + bity_old = ptcb->OSTCBBitY; + bitx_old = ptcb->OSTCBBitX; + if ((OSRdyTbl[y_old] & bitx_old) != 0u) { /* If task is ready make it not */ + OSRdyTbl[y_old] &= (OS_PRIO)~bitx_old; + if (OSRdyTbl[y_old] == 0u) { + OSRdyGrp &= (OS_PRIO)~bity_old; + } + OSRdyGrp |= bity_new; /* Make new priority ready to run */ + OSRdyTbl[y_new] |= bitx_new; + } + +#if (OS_EVENT_EN) + pevent = ptcb->OSTCBEventPtr; + if (pevent != (OS_EVENT *)0) { + pevent->OSEventTbl[y_old] &= (OS_PRIO)~bitx_old; /* Remove old task prio from wait list */ + if (pevent->OSEventTbl[y_old] == 0u) { + pevent->OSEventGrp &= (OS_PRIO)~bity_old; + } + pevent->OSEventGrp |= bity_new; /* Add new task prio to wait list */ + pevent->OSEventTbl[y_new] |= bitx_new; + } +#if (OS_EVENT_MULTI_EN > 0u) + if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) { + pevents = ptcb->OSTCBEventMultiPtr; + pevent = *pevents; + while (pevent != (OS_EVENT *)0) { + pevent->OSEventTbl[y_old] &= (OS_PRIO)~bitx_old; /* Remove old task prio from wait lists */ + if (pevent->OSEventTbl[y_old] == 0u) { + pevent->OSEventGrp &= (OS_PRIO)~bity_old; + } + pevent->OSEventGrp |= bity_new; /* Add new task prio to wait lists */ + pevent->OSEventTbl[y_new] |= bitx_new; + pevents++; + pevent = *pevents; + } + } +#endif +#endif + + ptcb->OSTCBPrio = newprio; /* Set new task priority */ + ptcb->OSTCBY = y_new; + ptcb->OSTCBX = x_new; + ptcb->OSTCBBitY = bity_new; + ptcb->OSTCBBitX = bitx_new; + OS_EXIT_CRITICAL(); + if (OSRunning == OS_TRUE) { + OS_Sched(); /* Find new highest priority task */ + } + return (OS_ERR_NONE); +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* CREATE A TASK +* +* Description: This function is used to have uC/OS-II manage the execution of a task. Tasks can either +* be created prior to the start of multitasking or by a running task. A task cannot be +* created by an ISR. +* +* Arguments : task is a pointer to the task's code +* +* p_arg is a pointer to an optional data area which can be used to pass parameters to +* the task when the task first executes. Where the task is concerned it thinks +* it was invoked and passed the argument 'p_arg' as follows: +* +* void Task (void *p_arg) +* { +* for (;;) { +* Task code; +* } +* } +* +* ptos is a pointer to the task's top of stack. If the configuration constant +* OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high +* memory to low memory). 'pstk' will thus point to the highest (valid) memory +* location of the stack. If OS_STK_GROWTH is set to 0, 'pstk' will point to the +* lowest memory location of the stack and the stack will grow with increasing +* memory locations. +* +* prio is the task's priority. A unique priority MUST be assigned to each task and the +* lower the number, the higher the priority. +* +* Returns : OS_ERR_NONE if the function was successful. +* OS_PRIO_EXIT if the task priority already exist +* (each task MUST have a unique priority). +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. >= OS_LOWEST_PRIO) +* OS_ERR_TASK_CREATE_ISR if you tried to create a task from an ISR. +********************************************************************************************************* +*/ + +#if OS_TASK_CREATE_EN > 0u +INT8U OSTaskCreate (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT8U prio) +{ + OS_STK *psp; + INT8U err; +#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 OS_ARG_CHK_EN > 0u + if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */ + return (OS_ERR_PRIO_INVALID); + } +#endif + OS_ENTER_CRITICAL(); + if (OSIntNesting > 0u) { /* Make sure we don't create the task from within an ISR */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_CREATE_ISR); + } + if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */ + OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ... */ + /* ... the same thing until task is created. */ + OS_EXIT_CRITICAL(); + psp = OSTaskStkInit(task, p_arg, ptos, 0u); /* Initialize the task's stack */ + err = OS_TCBInit(prio, psp, (OS_STK *)0, 0u, 0u, (void *)0, 0u); + if (err == OS_ERR_NONE) { + if (OSRunning == OS_TRUE) { /* Find highest priority task if multitasking has started */ + OS_Sched(); + } + } else { + OS_ENTER_CRITICAL(); + OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others */ + OS_EXIT_CRITICAL(); + } + return (err); + } + OS_EXIT_CRITICAL(); + return (OS_ERR_PRIO_EXIST); +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* CREATE A TASK (Extended Version) +* +* Description: This function is used to have uC/OS-II manage the execution of a task. Tasks can either +* be created prior to the start of multitasking or by a running task. A task cannot be +* created by an ISR. This function is similar to OSTaskCreate() except that it allows +* additional information about a task to be specified. +* +* Arguments : task is a pointer to the task's code +* +* p_arg is a pointer to an optional data area which can be used to pass parameters to +* the task when the task first executes. Where the task is concerned it thinks +* it was invoked and passed the argument 'p_arg' as follows: +* +* void Task (void *p_arg) +* { +* for (;;) { +* Task code; +* } +* } +* +* ptos is a pointer to the task's top of stack. If the configuration constant +* OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high +* memory to low memory). 'ptos' will thus point to the highest (valid) memory +* location of the stack. If OS_STK_GROWTH is set to 0, 'ptos' will point to the +* lowest memory location of the stack and the stack will grow with increasing +* memory locations. 'ptos' MUST point to a valid 'free' data item. +* +* prio is the task's priority. A unique priority MUST be assigned to each task and the +* lower the number, the higher the priority. +* +* id is the task's ID (0..65535) +* +* pbos is a pointer to the task's bottom of stack. If the configuration constant +* OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high +* memory to low memory). 'pbos' will thus point to the LOWEST (valid) memory +* location of the stack. If OS_STK_GROWTH is set to 0, 'pbos' will point to the +* HIGHEST memory location of the stack and the stack will grow with increasing +* memory locations. 'pbos' MUST point to a valid 'free' data item. +* +* stk_size is the size of the stack in number of elements. If OS_STK is set to INT8U, +* 'stk_size' corresponds to the number of bytes available. If OS_STK is set to +* INT16U, 'stk_size' contains the number of 16-bit entries available. Finally, if +* OS_STK is set to INT32U, 'stk_size' contains the number of 32-bit entries +* available on the stack. +* +* pext is a pointer to a user supplied memory location which is used as a TCB extension. +* For example, this user memory can hold the contents of floating-point registers +* during a context switch, the time each task takes to execute, the number of times +* the task has been switched-in, etc. +* +* opt contains additional information (or options) about the behavior of the task. The +* LOWER 8-bits are reserved by uC/OS-II while the upper 8 bits can be application +* specific. See OS_TASK_OPT_??? in uCOS-II.H. Current choices are: +* +* OS_TASK_OPT_STK_CHK Stack checking to be allowed for the task +* OS_TASK_OPT_STK_CLR Clear the stack when the task is created +* OS_TASK_OPT_SAVE_FP If the CPU has floating-point registers, save them +* during a context switch. +* +* Returns : OS_ERR_NONE if the function was successful. +* OS_PRIO_EXIT if the task priority already exist +* (each task MUST have a unique priority). +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. > OS_LOWEST_PRIO) +* OS_ERR_TASK_CREATE_ISR if you tried to create a task from an ISR. +********************************************** *********************************************************** +*/ +/*$PAGE*/ +#if OS_TASK_CREATE_EXT_EN > 0u +INT8U OSTaskCreateExt (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT8U prio, + INT16U id, + OS_STK *pbos, + INT32U stk_size, + void *pext, + INT16U opt) +{ + OS_STK *psp; + INT8U err; +#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 OS_ARG_CHK_EN > 0u + if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */ + return (OS_ERR_PRIO_INVALID); + } +#endif + OS_ENTER_CRITICAL(); + if (OSIntNesting > 0u) { /* Make sure we don't create the task from within an ISR */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_CREATE_ISR); + } + if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */ + OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ... */ + /* ... the same thing until task is created. */ + OS_EXIT_CRITICAL(); + +#if (OS_TASK_STAT_STK_CHK_EN > 0u) + OS_TaskStkClr(pbos, stk_size, opt); /* Clear the task stack (if needed) */ +#endif + + psp = OSTaskStkInit(task, p_arg, ptos, opt); /* Initialize the task's stack */ + err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt); + if (err == OS_ERR_NONE) { + if (OSRunning == OS_TRUE) { /* Find HPT if multitasking has started */ + OS_Sched(); + } + } else { + OS_ENTER_CRITICAL(); + OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Make this priority avail. to others */ + OS_EXIT_CRITICAL(); + } + return (err); + } + OS_EXIT_CRITICAL(); + return (OS_ERR_PRIO_EXIST); +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* DELETE A TASK +* +* Description: This function allows you to delete a task. The calling task can delete itself by +* its own priority number. The deleted task is returned to the dormant state and can be +* re-activated by creating the deleted task again. +* +* Arguments : prio is the priority of the task to delete. Note that you can explicitely delete +* the current task without knowing its priority level by setting 'prio' to +* OS_PRIO_SELF. +* +* Returns : OS_ERR_NONE if the call is successful +* OS_ERR_TASK_DEL_IDLE if you attempted to delete uC/OS-II's idle task +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF. +* OS_ERR_TASK_DEL if the task is assigned to a Mutex PIP. +* OS_ERR_TASK_NOT_EXIST if the task you want to delete does not exist. +* OS_ERR_TASK_DEL_ISR if you tried to delete a task from an ISR +* +* Notes : 1) To reduce interrupt latency, OSTaskDel() 'disables' the task: +* a) by making it not ready +* b) by removing it from any wait lists +* c) by preventing OSTimeTick() from making the task ready to run. +* The task can then be 'unlinked' from the miscellaneous structures in uC/OS-II. +* 2) The function OS_Dummy() is called after OS_EXIT_CRITICAL() because, on most processors, +* the next instruction following the enable interrupt instruction is ignored. +* 3) An ISR cannot delete a task. +* 4) The lock nesting counter is incremented because, for a brief instant, if the current +* task is being deleted, the current task would not be able to be rescheduled because it +* is removed from the ready list. Incrementing the nesting counter prevents another task +* from being schedule. This means that an ISR would return to the current task which is +* being deleted. The rest of the deletion would thus be able to be completed. +********************************************************************************************************* +*/ + +#if OS_TASK_DEL_EN > 0u +INT8U OSTaskDel (INT8U prio) +{ +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + OS_FLAG_NODE *pnode; +#endif + OS_TCB *ptcb; +#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 delete from ISR */ + return (OS_ERR_TASK_DEL_ISR); + } + if (prio == OS_TASK_IDLE_PRIO) { /* Not allowed to delete idle task */ + return (OS_ERR_TASK_DEL_IDLE); + } +#if OS_ARG_CHK_EN > 0u + if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ? */ + if (prio != OS_PRIO_SELF) { + return (OS_ERR_PRIO_INVALID); + } + } +#endif + +/*$PAGE*/ + OS_ENTER_CRITICAL(); + if (prio == OS_PRIO_SELF) { /* See if requesting to delete self */ + prio = OSTCBCur->OSTCBPrio; /* Set priority to delete to current */ + } + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Task to delete must exist */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); + } + if (ptcb == OS_TCB_RESERVED) { /* Must not be assigned to Mutex */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_DEL); + } + + OSRdyTbl[ptcb->OSTCBY] &= (OS_PRIO)~ptcb->OSTCBBitX; + if (OSRdyTbl[ptcb->OSTCBY] == 0u) { /* Make task not ready */ + OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY; + } + +#if (OS_EVENT_EN) + if (ptcb->OSTCBEventPtr != (OS_EVENT *)0) { + OS_EventTaskRemove(ptcb, ptcb->OSTCBEventPtr); /* Remove this task from any event wait list */ + } +#if (OS_EVENT_MULTI_EN > 0u) + if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) { /* Remove this task from any events' wait lists*/ + OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr); + } +#endif +#endif + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + pnode = ptcb->OSTCBFlagNode; + if (pnode != (OS_FLAG_NODE *)0) { /* If task is waiting on event flag */ + OS_FlagUnlink(pnode); /* Remove from wait list */ + } +#endif + + ptcb->OSTCBDly = 0u; /* Prevent OSTimeTick() from updating */ + ptcb->OSTCBStat = OS_STAT_RDY; /* Prevent task from being resumed */ + ptcb->OSTCBStatPend = OS_STAT_PEND_OK; + if (OSLockNesting < 255u) { /* Make sure we don't context switch */ + OSLockNesting++; + } + OS_EXIT_CRITICAL(); /* Enabling INT. ignores next instruc. */ + OS_Dummy(); /* ... Dummy ensures that INTs will be */ + OS_ENTER_CRITICAL(); /* ... disabled HERE! */ + if (OSLockNesting > 0u) { /* Remove context switch lock */ + OSLockNesting--; + } + OSTaskDelHook(ptcb); /* Call user defined hook */ + OSTaskCtr--; /* One less task being managed */ + OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Clear old priority entry */ + if (ptcb->OSTCBPrev == (OS_TCB *)0) { /* Remove from TCB chain */ + ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0; + OSTCBList = ptcb->OSTCBNext; + } else { + ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext; + ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev; + } + ptcb->OSTCBNext = OSTCBFreeList; /* Return TCB to free TCB list */ + OSTCBFreeList = ptcb; +#if OS_TASK_NAME_EN > 0u + ptcb->OSTCBTaskName = (INT8U *)(void *)"?"; +#endif + OS_EXIT_CRITICAL(); + if (OSRunning == OS_TRUE) { + OS_Sched(); /* Find new highest priority task */ + } + return (OS_ERR_NONE); +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* REQUEST THAT A TASK DELETE ITSELF +* +* Description: This function is used to: +* a) notify a task to delete itself. +* b) to see if a task requested that the current task delete itself. +* This function is a little tricky to understand. Basically, you have a task that needs +* to be deleted however, this task has resources that it has allocated (memory buffers, +* semaphores, mailboxes, queues etc.). The task cannot be deleted otherwise these +* resources would not be freed. The requesting task calls OSTaskDelReq() to indicate that +* the task needs to be deleted. Deleting of the task is however, deferred to the task to +* be deleted. For example, suppose that task #10 needs to be deleted. The requesting task +* example, task #5, would call OSTaskDelReq(10). When task #10 gets to execute, it calls +* this function by specifying OS_PRIO_SELF and monitors the returned value. If the return +* value is OS_ERR_TASK_DEL_REQ, another task requested a task delete. Task #10 would look like +* this: +* +* void Task(void *p_arg) +* { +* . +* . +* while (1) { +* OSTimeDly(1); +* if (OSTaskDelReq(OS_PRIO_SELF) == OS_ERR_TASK_DEL_REQ) { +* Release any owned resources; +* De-allocate any dynamic memory; +* OSTaskDel(OS_PRIO_SELF); +* } +* } +* } +* +* Arguments : prio is the priority of the task to request the delete from +* +* Returns : OS_ERR_NONE if the task exist and the request has been registered +* OS_ERR_TASK_NOT_EXIST if the task has been deleted. This allows the caller to know whether +* the request has been executed. +* OS_ERR_TASK_DEL if the task is assigned to a Mutex. +* OS_ERR_TASK_DEL_IDLE if you requested to delete uC/OS-II's idle task +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF. +* OS_ERR_TASK_DEL_REQ if a task (possibly another task) requested that the running task be +* deleted. +********************************************************************************************************* +*/ +/*$PAGE*/ +#if OS_TASK_DEL_EN > 0u +INT8U OSTaskDelReq (INT8U prio) +{ + INT8U stat; + OS_TCB *ptcb; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + if (prio == OS_TASK_IDLE_PRIO) { /* Not allowed to delete idle task */ + return (OS_ERR_TASK_DEL_IDLE); + } +#if OS_ARG_CHK_EN > 0u + if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ? */ + if (prio != OS_PRIO_SELF) { + return (OS_ERR_PRIO_INVALID); + } + } +#endif + if (prio == OS_PRIO_SELF) { /* See if a task is requesting to ... */ + OS_ENTER_CRITICAL(); /* ... this task to delete itself */ + stat = OSTCBCur->OSTCBDelReq; /* Return request status to caller */ + OS_EXIT_CRITICAL(); + return (stat); + } + OS_ENTER_CRITICAL(); + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Task to delete must exist */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); /* Task must already be deleted */ + } + if (ptcb == OS_TCB_RESERVED) { /* Must NOT be assigned to a Mutex */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_DEL); + } + ptcb->OSTCBDelReq = OS_ERR_TASK_DEL_REQ; /* Set flag indicating task to be DEL. */ + OS_EXIT_CRITICAL(); + return (OS_ERR_NONE); +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* GET THE NAME OF A TASK +* +* Description: This function is called to obtain the name of a task. +* +* Arguments : prio is the priority of the task that you want to obtain the name from. +* +* pname is a pointer to a pointer to an ASCII string that will receive the name of the task. +* +* perr is a pointer to an error code that can contain one of the following values: +* +* OS_ERR_NONE if the requested task is resumed +* OS_ERR_TASK_NOT_EXIST if the task has not been created or is assigned to a Mutex +* OS_ERR_PRIO_INVALID if you specified an invalid priority: +* A higher value than the idle task or not OS_PRIO_SELF. +* 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 the task does not exist. +********************************************************************************************************* +*/ + +#if OS_TASK_NAME_EN > 0u +INT8U OSTaskNameGet (INT8U prio, + INT8U **pname, + INT8U *perr) +{ + OS_TCB *ptcb; + 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 (prio > OS_LOWEST_PRIO) { /* Task priority valid ? */ + if (prio != OS_PRIO_SELF) { + *perr = OS_ERR_PRIO_INVALID; /* No */ + return (0u); + } + } + if (pname == (INT8U **)0) { /* Is 'pname' a NULL pointer? */ + *perr = OS_ERR_PNAME_NULL; /* Yes */ + 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(); + if (prio == OS_PRIO_SELF) { /* See if caller desires it's own name */ + prio = OSTCBCur->OSTCBPrio; + } + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Does task exist? */ + OS_EXIT_CRITICAL(); /* No */ + *perr = OS_ERR_TASK_NOT_EXIST; + return (0u); + } + if (ptcb == OS_TCB_RESERVED) { /* Task assigned to a Mutex? */ + OS_EXIT_CRITICAL(); /* Yes */ + *perr = OS_ERR_TASK_NOT_EXIST; + return (0u); + } + *pname = ptcb->OSTCBTaskName; + len = OS_StrLen(*pname); + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (len); +} +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* ASSIGN A NAME TO A TASK +* +* Description: This function is used to set the name of a task. +* +* Arguments : prio is the priority of the task that you want the assign a name to. +* +* pname is a pointer to an ASCII string that contains the name of the task. +* +* perr is a pointer to an error code that can contain one of the following values: +* +* OS_ERR_NONE if the requested task is resumed +* OS_ERR_TASK_NOT_EXIST if the task has not been created or is assigned to a Mutex +* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' +* OS_ERR_PRIO_INVALID if you specified an invalid priority: +* A higher value than the idle task or not OS_PRIO_SELF. +* OS_ERR_NAME_SET_ISR if you called this function from an ISR +* +* Returns : None +********************************************************************************************************* +*/ +#if OS_TASK_NAME_EN > 0u +void OSTaskNameSet (INT8U prio, + INT8U *pname, + INT8U *perr) +{ + 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 (prio > OS_LOWEST_PRIO) { /* Task priority valid ? */ + if (prio != OS_PRIO_SELF) { + *perr = OS_ERR_PRIO_INVALID; /* No */ + return; + } + } + if (pname == (INT8U *)0) { /* Is 'pname' a NULL pointer? */ + *perr = OS_ERR_PNAME_NULL; /* Yes */ + return; + } +#endif + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_NAME_SET_ISR; + return; + } + OS_ENTER_CRITICAL(); + if (prio == OS_PRIO_SELF) { /* See if caller desires to set it's own name */ + prio = OSTCBCur->OSTCBPrio; + } + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Does task exist? */ + OS_EXIT_CRITICAL(); /* No */ + *perr = OS_ERR_TASK_NOT_EXIST; + return; + } + if (ptcb == OS_TCB_RESERVED) { /* Task assigned to a Mutex? */ + OS_EXIT_CRITICAL(); /* Yes */ + *perr = OS_ERR_TASK_NOT_EXIST; + return; + } + ptcb->OSTCBTaskName = pname; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; +} +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* RESUME A SUSPENDED TASK +* +* Description: This function is called to resume a previously suspended task. This is the only call that +* will remove an explicit task suspension. +* +* Arguments : prio is the priority of the task to resume. +* +* Returns : OS_ERR_NONE if the requested task is resumed +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. >= OS_LOWEST_PRIO) +* OS_ERR_TASK_RESUME_PRIO if the task to resume does not exist +* OS_ERR_TASK_NOT_EXIST if the task is assigned to a Mutex PIP +* OS_ERR_TASK_NOT_SUSPENDED if the task to resume has not been suspended +********************************************************************************************************* +*/ + +#if OS_TASK_SUSPEND_EN > 0u +INT8U OSTaskResume (INT8U prio) +{ + OS_TCB *ptcb; +#if OS_CRITICAL_METHOD == 3u /* Storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (prio >= OS_LOWEST_PRIO) { /* Make sure task priority is valid */ + return (OS_ERR_PRIO_INVALID); + } +#endif + OS_ENTER_CRITICAL(); + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Task to suspend must exist */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_RESUME_PRIO); + } + if (ptcb == OS_TCB_RESERVED) { /* See if assigned to Mutex */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); + } + if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != OS_STAT_RDY) { /* Task must be suspended */ + ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_SUSPEND; /* Remove suspension */ + if (ptcb->OSTCBStat == OS_STAT_RDY) { /* See if task is now ready */ + if (ptcb->OSTCBDly == 0u) { + OSRdyGrp |= ptcb->OSTCBBitY; /* Yes, Make task ready to run */ + OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; + OS_EXIT_CRITICAL(); + if (OSRunning == OS_TRUE) { + OS_Sched(); /* Find new highest priority task */ + } + } else { + OS_EXIT_CRITICAL(); + } + } else { /* Must be pending on event */ + OS_EXIT_CRITICAL(); + } + return (OS_ERR_NONE); + } + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_SUSPENDED); +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* STACK CHECKING +* +* Description: This function is called to check the amount of free memory left on the specified task's +* stack. +* +* Arguments : prio is the task priority +* +* p_stk_data is a pointer to a data structure of type OS_STK_DATA. +* +* Returns : OS_ERR_NONE upon success +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF. +* OS_ERR_TASK_NOT_EXIST if the desired task has not been created or is assigned to a Mutex PIP +* OS_ERR_TASK_OPT if you did NOT specified OS_TASK_OPT_STK_CHK when the task was created +* OS_ERR_PDATA_NULL if 'p_stk_data' is a NULL pointer +********************************************************************************************************* +*/ +#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) +INT8U OSTaskStkChk (INT8U prio, + OS_STK_DATA *p_stk_data) +{ + OS_TCB *ptcb; + OS_STK *pchk; + INT32U nfree; + INT32U size; +#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 (prio > OS_LOWEST_PRIO) { /* Make sure task priority is valid */ + if (prio != OS_PRIO_SELF) { + return (OS_ERR_PRIO_INVALID); + } + } + if (p_stk_data == (OS_STK_DATA *)0) { /* Validate 'p_stk_data' */ + return (OS_ERR_PDATA_NULL); + } +#endif + p_stk_data->OSFree = 0u; /* Assume failure, set to 0 size */ + p_stk_data->OSUsed = 0u; + OS_ENTER_CRITICAL(); + if (prio == OS_PRIO_SELF) { /* See if check for SELF */ + prio = OSTCBCur->OSTCBPrio; + } + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Make sure task exist */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); + } + if (ptcb == OS_TCB_RESERVED) { + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); + } + if ((ptcb->OSTCBOpt & OS_TASK_OPT_STK_CHK) == 0u) { /* Make sure stack checking option is set */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_OPT); + } + nfree = 0u; + size = ptcb->OSTCBStkSize; + pchk = ptcb->OSTCBStkBottom; + OS_EXIT_CRITICAL(); +#if OS_STK_GROWTH == 1u + while (*pchk++ == (OS_STK)0) { /* Compute the number of zero entries on the stk */ + nfree++; + } +#else + while (*pchk-- == (OS_STK)0) { + nfree++; + } +#endif + p_stk_data->OSFree = nfree * sizeof(OS_STK); /* Compute number of free bytes on the stack */ + p_stk_data->OSUsed = (size - nfree) * sizeof(OS_STK); /* Compute number of bytes used on the stack */ + return (OS_ERR_NONE); +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* SUSPEND A TASK +* +* Description: This function is called to suspend a task. The task can be the calling task if the +* priority passed to OSTaskSuspend() is the priority of the calling task or OS_PRIO_SELF. +* +* Arguments : prio is the priority of the task to suspend. If you specify OS_PRIO_SELF, the +* calling task will suspend itself and rescheduling will occur. +* +* Returns : OS_ERR_NONE if the requested task is suspended +* OS_ERR_TASK_SUSPEND_IDLE if you attempted to suspend the idle task which is not allowed. +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF. +* OS_ERR_TASK_SUSPEND_PRIO if the task to suspend does not exist +* OS_ERR_TASK_NOT_EXITS if the task is assigned to a Mutex PIP +* +* Note : You should use this function with great care. If you suspend a task that is waiting for +* an event (i.e. a message, a semaphore, a queue ...) you will prevent this task from +* running when the event arrives. +********************************************************************************************************* +*/ + +#if OS_TASK_SUSPEND_EN > 0u +INT8U OSTaskSuspend (INT8U prio) +{ + BOOLEAN self; + OS_TCB *ptcb; + INT8U y; +#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 (prio == OS_TASK_IDLE_PRIO) { /* Not allowed to suspend idle task */ + return (OS_ERR_TASK_SUSPEND_IDLE); + } + if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ? */ + if (prio != OS_PRIO_SELF) { + return (OS_ERR_PRIO_INVALID); + } + } +#endif + OS_ENTER_CRITICAL(); + if (prio == OS_PRIO_SELF) { /* See if suspend SELF */ + prio = OSTCBCur->OSTCBPrio; + self = OS_TRUE; + } else if (prio == OSTCBCur->OSTCBPrio) { /* See if suspending self */ + self = OS_TRUE; + } else { + self = OS_FALSE; /* No suspending another task */ + } + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Task to suspend must exist */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_SUSPEND_PRIO); + } + if (ptcb == OS_TCB_RESERVED) { /* See if assigned to Mutex */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); + } + y = ptcb->OSTCBY; + OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX; /* Make task not ready */ + if (OSRdyTbl[y] == 0u) { + OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY; + } + ptcb->OSTCBStat |= OS_STAT_SUSPEND; /* Status of task is 'SUSPENDED' */ + OS_EXIT_CRITICAL(); + if (self == OS_TRUE) { /* Context switch only if SELF */ + OS_Sched(); /* Find new highest priority task */ + } + return (OS_ERR_NONE); +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* QUERY A TASK +* +* Description: This function is called to obtain a copy of the desired task's TCB. +* +* Arguments : prio is the priority of the task to obtain information from. +* +* p_task_data is a pointer to where the desired task's OS_TCB will be stored. +* +* Returns : OS_ERR_NONE if the requested task is suspended +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF. +* OS_ERR_PRIO if the desired task has not been created +* OS_ERR_TASK_NOT_EXIST if the task is assigned to a Mutex PIP +* OS_ERR_PDATA_NULL if 'p_task_data' is a NULL pointer +********************************************************************************************************* +*/ + +#if OS_TASK_QUERY_EN > 0u +INT8U OSTaskQuery (INT8U prio, + OS_TCB *p_task_data) +{ + OS_TCB *ptcb; +#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 (prio > OS_LOWEST_PRIO) { /* Task priority valid ? */ + if (prio != OS_PRIO_SELF) { + return (OS_ERR_PRIO_INVALID); + } + } + if (p_task_data == (OS_TCB *)0) { /* Validate 'p_task_data' */ + return (OS_ERR_PDATA_NULL); + } +#endif + OS_ENTER_CRITICAL(); + if (prio == OS_PRIO_SELF) { /* See if suspend SELF */ + prio = OSTCBCur->OSTCBPrio; + } + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Task to query must exist */ + OS_EXIT_CRITICAL(); + return (OS_ERR_PRIO); + } + if (ptcb == OS_TCB_RESERVED) { /* Task to query must not be assigned to a Mutex */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); + } + /* Copy TCB into user storage area */ + OS_MemCopy((INT8U *)p_task_data, (INT8U *)ptcb, sizeof(OS_TCB)); + OS_EXIT_CRITICAL(); + return (OS_ERR_NONE); +} +#endif +/*$PAGE*/ +/* +********************************************************************************************************* +* GET THE CURRENT VALUE OF A TASK REGISTER +* +* Description: This function is called to obtain the current value of a task register. Task registers +* are application specific and can be used to store task specific values such as 'error +* numbers' (i.e. errno), statistics, etc. Each task register can hold a 32-bit value. +* +* Arguments : prio is the priority of the task you want to get the task register from. If you +* specify OS_PRIO_SELF then the task register of the current task will be obtained. +* +* id is the 'id' of the desired task register. Note that the 'id' must be less +* than OS_TASK_REG_TBL_SIZE +* +* perr is a pointer to a variable that will hold an error code related to this call. +* +* OS_ERR_NONE if the call was successful +* OS_ERR_PRIO_INVALID if you specified an invalid priority +* OS_ERR_ID_INVALID if the 'id' is not between 0 and OS_TASK_REG_TBL_SIZE-1 +* +* Returns : The current value of the task's register or 0 if an error is detected. +* +* Note(s) : The maximum number of task variables is 254 +********************************************************************************************************* +*/ + +#if OS_TASK_REG_TBL_SIZE > 0u +INT32U OSTaskRegGet (INT8U prio, + INT8U id, + INT8U *perr) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + INT32U value; + OS_TCB *ptcb; + + +#if OS_ARG_CHK_EN > 0u + if (prio >= OS_LOWEST_PRIO) { + if (prio != OS_PRIO_SELF) { + *perr = OS_ERR_PRIO_INVALID; + return (0u); + } + } + if (id >= OS_TASK_REG_TBL_SIZE) { + *perr = OS_ERR_ID_INVALID; + return (0u); + } +#endif + OS_ENTER_CRITICAL(); + if (prio == OS_PRIO_SELF) { /* See if need to get register from current task */ + ptcb = OSTCBCur; + } else { + ptcb = OSTCBPrioTbl[prio]; + } + value = ptcb->OSTCBRegTbl[id]; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (value); +} +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* SET THE CURRENT VALUE OF A TASK VARIABLE +* +* Description: This function is called to change the current value of a task register. Task registers +* are application specific and can be used to store task specific values such as 'error +* numbers' (i.e. errno), statistics, etc. Each task register can hold a 32-bit value. +* +* Arguments : prio is the priority of the task you want to set the task register for. If you +* specify OS_PRIO_SELF then the task register of the current task will be obtained. +* +* id is the 'id' of the desired task register. Note that the 'id' must be less +* than OS_TASK_REG_TBL_SIZE +* +* value is the desired value for the task register. +* +* perr is a pointer to a variable that will hold an error code related to this call. +* +* OS_ERR_NONE if the call was successful +* OS_ERR_PRIO_INVALID if you specified an invalid priority +* OS_ERR_ID_INVALID if the 'id' is not between 0 and OS_TASK_REG_TBL_SIZE-1 +* +* Returns : The current value of the task's variable or 0 if an error is detected. +* +* Note(s) : The maximum number of task variables is 254 +********************************************************************************************************* +*/ + +#if OS_TASK_REG_TBL_SIZE > 0u +void OSTaskRegSet (INT8U prio, + INT8U id, + INT32U value, + INT8U *perr) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + OS_TCB *ptcb; + + +#if OS_ARG_CHK_EN > 0u + if (prio >= OS_LOWEST_PRIO) { + if (prio != OS_PRIO_SELF) { + *perr = OS_ERR_PRIO_INVALID; + return; + } + } + if (id >= OS_TASK_REG_TBL_SIZE) { + *perr = OS_ERR_ID_INVALID; + return; + } +#endif + OS_ENTER_CRITICAL(); + if (prio == OS_PRIO_SELF) { /* See if need to get register from current task */ + ptcb = OSTCBCur; + } else { + ptcb = OSTCBPrioTbl[prio]; + } + ptcb->OSTCBRegTbl[id] = value; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; +} +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* CATCH ACCIDENTAL TASK RETURN +* +* Description: This function is called if a task accidentally returns without deleting itself. In other +* words, a task should either be an infinite loop or delete itself if it's done. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +void OS_TaskReturn (void) +{ + OSTaskReturnHook(OSTCBCur); /* Call hook to let user decide on what to do */ + +#if OS_TASK_DEL_EN > 0u + (void)OSTaskDel(OS_PRIO_SELF); /* Delete task if it accidentally returns! */ +#else + for (;;) { + OSTimeDly(OS_TICKS_PER_SEC); + } +#endif +} + +/*$PAGE*/ +/* +********************************************************************************************************* +* CLEAR TASK STACK +* +* Description: This function is used to clear the stack of a task (i.e. write all zeros) +* +* Arguments : pbos is a pointer to the task's bottom of stack. If the configuration constant +* OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high +* memory to low memory). 'pbos' will thus point to the lowest (valid) memory +* location of the stack. If OS_STK_GROWTH is set to 0, 'pbos' will point to the +* highest memory location of the stack and the stack will grow with increasing +* memory locations. 'pbos' MUST point to a valid 'free' data item. +* +* size is the number of 'stack elements' to clear. +* +* opt contains additional information (or options) about the behavior of the task. The +* LOWER 8-bits are reserved by uC/OS-II while the upper 8 bits can be application +* specific. See OS_TASK_OPT_??? in uCOS-II.H. +* +* Returns : none +********************************************************************************************************* +*/ +#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) +void OS_TaskStkClr (OS_STK *pbos, + INT32U size, + INT16U opt) +{ + if ((opt & OS_TASK_OPT_STK_CHK) != 0x0000u) { /* See if stack checking has been enabled */ + if ((opt & OS_TASK_OPT_STK_CLR) != 0x0000u) { /* See if stack needs to be cleared */ +#if OS_STK_GROWTH == 1u + while (size > 0u) { /* Stack grows from HIGH to LOW memory */ + size--; + *pbos++ = (OS_STK)0; /* Clear from bottom of stack and up! */ + } +#else + while (size > 0u) { /* Stack grows from LOW to HIGH memory */ + size--; + *pbos-- = (OS_STK)0; /* Clear from bottom of stack and down */ + } +#endif + } + } +} + +#endif + diff --git a/UCOSII/CORE/os_time.c b/UCOSII/CORE/os_time.c new file mode 100644 index 0000000..1826ffa --- /dev/null +++ b/UCOSII/CORE/os_time.c @@ -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 Micrim 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 +#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 + diff --git a/UCOSII/CORE/os_tmr.c b/UCOSII/CORE/os_tmr.c new file mode 100644 index 0000000..cf7b690 --- /dev/null +++ b/UCOSII/CORE/os_tmr.c @@ -0,0 +1,1073 @@ +/* +************************************************************************************************************************ +* uC/OS-II +* The Real-Time Kernel +* TIMER MANAGEMENT +* +* (c) Copyright 1992-2009, Micrium, Weston, FL +* All Rights Reserved +* +* +* File : OS_TMR.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 Micrim 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 + +/* +************************************************************************************************************************ +* NOTES +* +* 1) Your application MUST define the following #define constants: +* +* OS_TASK_TMR_PRIO The priority of the Timer management task +* OS_TASK_TMR_STK_SIZE The size of the Timer management task's stack +* +* 2) You must call OSTmrSignal() to notify the Timer management task that it's time to update the timers. +************************************************************************************************************************ +*/ + +/* +************************************************************************************************************************ +* CONSTANTS +************************************************************************************************************************ +*/ + +#define OS_TMR_LINK_DLY 0u +#define OS_TMR_LINK_PERIODIC 1u + +/* +************************************************************************************************************************ +* LOCAL PROTOTYPES +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +static OS_TMR *OSTmr_Alloc (void); +static void OSTmr_Free (OS_TMR *ptmr); +static void OSTmr_InitTask (void); +static void OSTmr_Link (OS_TMR *ptmr, INT8U type); +static void OSTmr_Unlink (OS_TMR *ptmr); +static void OSTmr_Task (void *p_arg); +#endif + +/*$PAGE*/ +/* +************************************************************************************************************************ +* CREATE A TIMER +* +* Description: This function is called by your application code to create a timer. +* +* Arguments : dly Initial delay. +* If the timer is configured for ONE-SHOT mode, this is the timeout used +* If the timer is configured for PERIODIC mode, this is the first timeout to wait for +* before the timer starts entering periodic mode +* +* period The 'period' being repeated for the timer. +* If you specified 'OS_TMR_OPT_PERIODIC' as an option, when the timer expires, it will +* automatically restart with the same period. +* +* opt Specifies either: +* OS_TMR_OPT_ONE_SHOT The timer counts down only once +* OS_TMR_OPT_PERIODIC The timer counts down and then reloads itself +* +* callback Is a pointer to a callback function that will be called when the timer expires. The +* callback function must be declared as follows: +* +* void MyCallback (OS_TMR *ptmr, void *p_arg); +* +* callback_arg Is an argument (a pointer) that is passed to the callback function when it is called. +* +* pname Is a pointer to an ASCII string that is used to name the timer. Names are useful for +* debugging. +* +* perr Is a pointer to an error code. '*perr' will contain one of the following: +* OS_ERR_NONE +* OS_ERR_TMR_INVALID_DLY you specified an invalid delay +* OS_ERR_TMR_INVALID_PERIOD you specified an invalid period +* OS_ERR_TMR_INVALID_OPT you specified an invalid option +* OS_ERR_TMR_ISR if the call was made from an ISR +* OS_ERR_TMR_NON_AVAIL if there are no free timers from the timer pool +* +* Returns : A pointer to an OS_TMR data structure. +* This is the 'handle' that your application will use to reference the timer created. +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +OS_TMR *OSTmrCreate (INT32U dly, + INT32U period, + INT8U opt, + OS_TMR_CALLBACK callback, + void *callback_arg, + INT8U *pname, + INT8U *perr) +{ + OS_TMR *ptmr; + + +#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 + switch (opt) { /* Validate arguments */ + case OS_TMR_OPT_PERIODIC: + if (period == 0u) { + *perr = OS_ERR_TMR_INVALID_PERIOD; + return ((OS_TMR *)0); + } + break; + + case OS_TMR_OPT_ONE_SHOT: + if (dly == 0u) { + *perr = OS_ERR_TMR_INVALID_DLY; + return ((OS_TMR *)0); + } + break; + + default: + *perr = OS_ERR_TMR_INVALID_OPT; + return ((OS_TMR *)0); + } +#endif + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_TMR_ISR; + return ((OS_TMR *)0); + } + OSSchedLock(); + ptmr = OSTmr_Alloc(); /* Obtain a timer from the free pool */ + if (ptmr == (OS_TMR *)0) { + OSSchedUnlock(); + *perr = OS_ERR_TMR_NON_AVAIL; + return ((OS_TMR *)0); + } + ptmr->OSTmrState = OS_TMR_STATE_STOPPED; /* Indicate that timer is not running yet */ + ptmr->OSTmrDly = dly; + ptmr->OSTmrPeriod = period; + ptmr->OSTmrOpt = opt; + ptmr->OSTmrCallback = callback; + ptmr->OSTmrCallbackArg = callback_arg; +#if OS_TMR_CFG_NAME_EN > 0u + ptmr->OSTmrName = pname; +#endif + OSSchedUnlock(); + *perr = OS_ERR_NONE; + return (ptmr); +} +#endif + +/*$PAGE*/ +/* +************************************************************************************************************************ +* DELETE A TIMER +* +* Description: This function is called by your application code to delete a timer. +* +* Arguments : ptmr Is a pointer to the timer to stop and delete. +* +* perr Is a pointer to an error code. '*perr' will contain one of the following: +* OS_ERR_NONE +* OS_ERR_TMR_INVALID 'ptmr' is a NULL pointer +* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR +* OS_ERR_TMR_ISR if the function was called from an ISR +* OS_ERR_TMR_INACTIVE if the timer was not created +* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state +* +* Returns : OS_TRUE If the call was successful +* OS_FALSE If not +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +BOOLEAN OSTmrDel (OS_TMR *ptmr, + INT8U *perr) +{ +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (ptmr == (OS_TMR *)0) { + *perr = OS_ERR_TMR_INVALID; + return (OS_FALSE); + } +#endif + if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */ + *perr = OS_ERR_TMR_INVALID_TYPE; + return (OS_FALSE); + } + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_TMR_ISR; + return (OS_FALSE); + } + OSSchedLock(); + switch (ptmr->OSTmrState) { + case OS_TMR_STATE_RUNNING: + OSTmr_Unlink(ptmr); /* Remove from current wheel spoke */ + OSTmr_Free(ptmr); /* Return timer to free list of timers */ + OSSchedUnlock(); + *perr = OS_ERR_NONE; + return (OS_TRUE); + + case OS_TMR_STATE_STOPPED: /* Timer has not started or ... */ + case OS_TMR_STATE_COMPLETED: /* ... timer has completed the ONE-SHOT time */ + OSTmr_Free(ptmr); /* Return timer to free list of timers */ + OSSchedUnlock(); + *perr = OS_ERR_NONE; + return (OS_TRUE); + + case OS_TMR_STATE_UNUSED: /* Already deleted */ + OSSchedUnlock(); + *perr = OS_ERR_TMR_INACTIVE; + return (OS_FALSE); + + default: + OSSchedUnlock(); + *perr = OS_ERR_TMR_INVALID_STATE; + return (OS_FALSE); + } +} +#endif + +/*$PAGE*/ +/* +************************************************************************************************************************ +* GET THE NAME OF A TIMER +* +* Description: This function is called to obtain the name of a timer. +* +* Arguments : ptmr Is a pointer to the timer to obtain the name for +* +* pdest Is a pointer to pointer to where the name of the timer will be placed. +* +* perr Is a pointer to an error code. '*perr' will contain one of the following: +* OS_ERR_NONE The call was successful +* OS_ERR_TMR_INVALID_DEST 'pdest' is a NULL pointer +* OS_ERR_TMR_INVALID 'ptmr' is a NULL pointer +* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR +* OS_ERR_NAME_GET_ISR if the call was made from an ISR +* OS_ERR_TMR_INACTIVE 'ptmr' points to a timer that is not active +* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state +* +* Returns : The length of the string or 0 if the timer does not exist. +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u && OS_TMR_CFG_NAME_EN > 0u +INT8U OSTmrNameGet (OS_TMR *ptmr, + INT8U **pdest, + INT8U *perr) +{ + INT8U len; + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pdest == (INT8U **)0) { + *perr = OS_ERR_TMR_INVALID_DEST; + return (0u); + } + if (ptmr == (OS_TMR *)0) { + *perr = OS_ERR_TMR_INVALID; + return (0u); + } +#endif + if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */ + *perr = OS_ERR_TMR_INVALID_TYPE; + return (0u); + } + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_NAME_GET_ISR; + return (0u); + } + OSSchedLock(); + switch (ptmr->OSTmrState) { + case OS_TMR_STATE_RUNNING: + case OS_TMR_STATE_STOPPED: + case OS_TMR_STATE_COMPLETED: + *pdest = ptmr->OSTmrName; + len = OS_StrLen(*pdest); + OSSchedUnlock(); + *perr = OS_ERR_NONE; + return (len); + + case OS_TMR_STATE_UNUSED: /* Timer is not allocated */ + OSSchedUnlock(); + *perr = OS_ERR_TMR_INACTIVE; + return (0u); + + default: + OSSchedUnlock(); + *perr = OS_ERR_TMR_INVALID_STATE; + return (0u); + } +} +#endif + +/*$PAGE*/ +/* +************************************************************************************************************************ +* GET HOW MUCH TIME IS LEFT BEFORE A TIMER EXPIRES +* +* Description: This function is called to get the number of ticks before a timer times out. +* +* Arguments : ptmr Is a pointer to the timer to obtain the remaining time from. +* +* perr Is a pointer to an error code. '*perr' will contain one of the following: +* OS_ERR_NONE +* OS_ERR_TMR_INVALID 'ptmr' is a NULL pointer +* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR +* OS_ERR_TMR_ISR if the call was made from an ISR +* OS_ERR_TMR_INACTIVE 'ptmr' points to a timer that is not active +* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state +* +* Returns : The time remaining for the timer to expire. The time represents 'timer' increments. In other words, if +* OSTmr_Task() is signaled every 1/10 of a second then the returned value represents the number of 1/10 of +* a second remaining before the timer expires. +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +INT32U OSTmrRemainGet (OS_TMR *ptmr, + INT8U *perr) +{ + INT32U remain; + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (ptmr == (OS_TMR *)0) { + *perr = OS_ERR_TMR_INVALID; + return (0u); + } +#endif + if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */ + *perr = OS_ERR_TMR_INVALID_TYPE; + return (0u); + } + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_TMR_ISR; + return (0u); + } + OSSchedLock(); + switch (ptmr->OSTmrState) { + case OS_TMR_STATE_RUNNING: + remain = ptmr->OSTmrMatch - OSTmrTime; /* Determine how much time is left to timeout */ + OSSchedUnlock(); + *perr = OS_ERR_NONE; + return (remain); + + case OS_TMR_STATE_STOPPED: /* It's assumed that the timer has not started yet */ + switch (ptmr->OSTmrOpt) { + case OS_TMR_OPT_PERIODIC: + if (ptmr->OSTmrDly == 0u) { + remain = ptmr->OSTmrPeriod; + } else { + remain = ptmr->OSTmrDly; + } + OSSchedUnlock(); + *perr = OS_ERR_NONE; + break; + + case OS_TMR_OPT_ONE_SHOT: + default: + remain = ptmr->OSTmrDly; + OSSchedUnlock(); + *perr = OS_ERR_NONE; + break; + } + return (remain); + + case OS_TMR_STATE_COMPLETED: /* Only ONE-SHOT that timed out can be in this state */ + OSSchedUnlock(); + *perr = OS_ERR_NONE; + return (0u); + + case OS_TMR_STATE_UNUSED: + OSSchedUnlock(); + *perr = OS_ERR_TMR_INACTIVE; + return (0u); + + default: + OSSchedUnlock(); + *perr = OS_ERR_TMR_INVALID_STATE; + return (0u); + } +} +#endif + +/*$PAGE*/ +/* +************************************************************************************************************************ +* FIND OUT WHAT STATE A TIMER IS IN +* +* Description: This function is called to determine what state the timer is in: +* +* OS_TMR_STATE_UNUSED the timer has not been created +* OS_TMR_STATE_STOPPED the timer has been created but has not been started or has been stopped +* OS_TMR_COMPLETED the timer is in ONE-SHOT mode and has completed it's timeout +* OS_TMR_RUNNING the timer is currently running +* +* Arguments : ptmr Is a pointer to the desired timer +* +* perr Is a pointer to an error code. '*perr' will contain one of the following: +* OS_ERR_NONE +* OS_ERR_TMR_INVALID 'ptmr' is a NULL pointer +* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR +* OS_ERR_TMR_ISR if the call was made from an ISR +* OS_ERR_TMR_INACTIVE 'ptmr' points to a timer that is not active +* OS_ERR_TMR_INVALID_STATE if the timer is not in a valid state +* +* Returns : The current state of the timer (see description). +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +INT8U OSTmrStateGet (OS_TMR *ptmr, + INT8U *perr) +{ + INT8U state; + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (ptmr == (OS_TMR *)0) { + *perr = OS_ERR_TMR_INVALID; + return (0u); + } +#endif + if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */ + *perr = OS_ERR_TMR_INVALID_TYPE; + return (0u); + } + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_TMR_ISR; + return (0u); + } + OSSchedLock(); + state = ptmr->OSTmrState; + switch (state) { + case OS_TMR_STATE_UNUSED: + case OS_TMR_STATE_STOPPED: + case OS_TMR_STATE_COMPLETED: + case OS_TMR_STATE_RUNNING: + *perr = OS_ERR_NONE; + break; + + default: + *perr = OS_ERR_TMR_INVALID_STATE; + break; + } + OSSchedUnlock(); + return (state); +} +#endif + +/*$PAGE*/ +/* +************************************************************************************************************************ +* START A TIMER +* +* Description: This function is called by your application code to start a timer. +* +* Arguments : ptmr Is a pointer to an OS_TMR +* +* perr Is a pointer to an error code. '*perr' will contain one of the following: +* OS_ERR_NONE +* OS_ERR_TMR_INVALID +* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR +* OS_ERR_TMR_ISR if the call was made from an ISR +* OS_ERR_TMR_INACTIVE if the timer was not created +* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state +* +* Returns : OS_TRUE if the timer was started +* OS_FALSE if an error was detected +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +BOOLEAN OSTmrStart (OS_TMR *ptmr, + INT8U *perr) +{ +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (ptmr == (OS_TMR *)0) { + *perr = OS_ERR_TMR_INVALID; + return (OS_FALSE); + } +#endif + if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */ + *perr = OS_ERR_TMR_INVALID_TYPE; + return (OS_FALSE); + } + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_TMR_ISR; + return (OS_FALSE); + } + OSSchedLock(); + switch (ptmr->OSTmrState) { + case OS_TMR_STATE_RUNNING: /* Restart the timer */ + OSTmr_Unlink(ptmr); /* ... Stop the timer */ + OSTmr_Link(ptmr, OS_TMR_LINK_DLY); /* ... Link timer to timer wheel */ + OSSchedUnlock(); + *perr = OS_ERR_NONE; + return (OS_TRUE); + + case OS_TMR_STATE_STOPPED: /* Start the timer */ + case OS_TMR_STATE_COMPLETED: + OSTmr_Link(ptmr, OS_TMR_LINK_DLY); /* ... Link timer to timer wheel */ + OSSchedUnlock(); + *perr = OS_ERR_NONE; + return (OS_TRUE); + + case OS_TMR_STATE_UNUSED: /* Timer not created */ + OSSchedUnlock(); + *perr = OS_ERR_TMR_INACTIVE; + return (OS_FALSE); + + default: + OSSchedUnlock(); + *perr = OS_ERR_TMR_INVALID_STATE; + return (OS_FALSE); + } +} +#endif + +/*$PAGE*/ +/* +************************************************************************************************************************ +* STOP A TIMER +* +* Description: This function is called by your application code to stop a timer. +* +* Arguments : ptmr Is a pointer to the timer to stop. +* +* opt Allows you to specify an option to this functions which can be: +* +* OS_TMR_OPT_NONE Do nothing special but stop the timer +* OS_TMR_OPT_CALLBACK Execute the callback function, pass it the callback argument +* specified when the timer was created. +* OS_TMR_OPT_CALLBACK_ARG Execute the callback function, pass it the callback argument +* specified in THIS function call +* +* callback_arg Is a pointer to a 'new' callback argument that can be passed to the callback function +* instead of the timer's callback argument. In other words, use 'callback_arg' passed in +* THIS function INSTEAD of ptmr->OSTmrCallbackArg +* +* perr Is a pointer to an error code. '*perr' will contain one of the following: +* OS_ERR_NONE +* OS_ERR_TMR_INVALID 'ptmr' is a NULL pointer +* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR +* OS_ERR_TMR_ISR if the function was called from an ISR +* OS_ERR_TMR_INACTIVE if the timer was not created +* OS_ERR_TMR_INVALID_OPT if you specified an invalid option for 'opt' +* OS_ERR_TMR_STOPPED if the timer was already stopped +* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state +* OS_ERR_TMR_NO_CALLBACK if the timer does not have a callback function defined +* +* Returns : OS_TRUE If we stopped the timer (if the timer is already stopped, we also return OS_TRUE) +* OS_FALSE If not +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +BOOLEAN OSTmrStop (OS_TMR *ptmr, + INT8U opt, + void *callback_arg, + INT8U *perr) +{ + OS_TMR_CALLBACK pfnct; + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (ptmr == (OS_TMR *)0) { + *perr = OS_ERR_TMR_INVALID; + return (OS_FALSE); + } +#endif + if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */ + *perr = OS_ERR_TMR_INVALID_TYPE; + return (OS_FALSE); + } + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_TMR_ISR; + return (OS_FALSE); + } + OSSchedLock(); + switch (ptmr->OSTmrState) { + case OS_TMR_STATE_RUNNING: + OSTmr_Unlink(ptmr); /* Remove from current wheel spoke */ + *perr = OS_ERR_NONE; + switch (opt) { + case OS_TMR_OPT_CALLBACK: + pfnct = ptmr->OSTmrCallback; /* Execute callback function if available ... */ + if (pfnct != (OS_TMR_CALLBACK)0) { + (*pfnct)((void *)ptmr, ptmr->OSTmrCallbackArg); /* Use callback arg when timer was created */ + } else { + *perr = OS_ERR_TMR_NO_CALLBACK; + } + break; + + case OS_TMR_OPT_CALLBACK_ARG: + pfnct = ptmr->OSTmrCallback; /* Execute callback function if available ... */ + if (pfnct != (OS_TMR_CALLBACK)0) { + (*pfnct)((void *)ptmr, callback_arg); /* ... using the 'callback_arg' provided in call */ + } else { + *perr = OS_ERR_TMR_NO_CALLBACK; + } + break; + + case OS_TMR_OPT_NONE: + break; + + default: + *perr = OS_ERR_TMR_INVALID_OPT; + break; + } + OSSchedUnlock(); + return (OS_TRUE); + + case OS_TMR_STATE_COMPLETED: /* Timer has already completed the ONE-SHOT or ... */ + case OS_TMR_STATE_STOPPED: /* ... timer has not started yet. */ + OSSchedUnlock(); + *perr = OS_ERR_TMR_STOPPED; + return (OS_TRUE); + + case OS_TMR_STATE_UNUSED: /* Timer was not created */ + OSSchedUnlock(); + *perr = OS_ERR_TMR_INACTIVE; + return (OS_FALSE); + + default: + OSSchedUnlock(); + *perr = OS_ERR_TMR_INVALID_STATE; + return (OS_FALSE); + } +} +#endif + +/*$PAGE*/ +/* +************************************************************************************************************************ +* SIGNAL THAT IT'S TIME TO UPDATE THE TIMERS +* +* Description: This function is typically called by the ISR that occurs at the timer tick rate and is used to signal to +* OSTmr_Task() that it's time to update the timers. +* +* Arguments : none +* +* Returns : OS_ERR_NONE The call was successful and the timer task was signaled. +* OS_ERR_SEM_OVF If OSTmrSignal() was called more often than OSTmr_Task() can handle the timers. +* This would indicate that your system is heavily loaded. +* OS_ERR_EVENT_TYPE Unlikely you would get this error because the semaphore used for signaling is created +* by uC/OS-II. +* OS_ERR_PEVENT_NULL Again, unlikely you would ever get this error because the semaphore used for signaling +* is created by uC/OS-II. +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +INT8U OSTmrSignal (void) +{ + INT8U err; + + + err = OSSemPost(OSTmrSemSignal); + return (err); +} +#endif + +/*$PAGE*/ +/* +************************************************************************************************************************ +* ALLOCATE AND FREE A TIMER +* +* Description: This function is called to allocate a timer. +* +* Arguments : none +* +* Returns : a pointer to a timer if one is available +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +static OS_TMR *OSTmr_Alloc (void) +{ + OS_TMR *ptmr; + + + if (OSTmrFreeList == (OS_TMR *)0) { + return ((OS_TMR *)0); + } + ptmr = (OS_TMR *)OSTmrFreeList; + OSTmrFreeList = (OS_TMR *)ptmr->OSTmrNext; + ptmr->OSTmrNext = (OS_TCB *)0; + ptmr->OSTmrPrev = (OS_TCB *)0; + OSTmrUsed++; + OSTmrFree--; + return (ptmr); +} +#endif + + +/* +************************************************************************************************************************ +* RETURN A TIMER TO THE FREE LIST +* +* Description: This function is called to return a timer object to the free list of timers. +* +* Arguments : ptmr is a pointer to the timer to free +* +* Returns : none +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +static void OSTmr_Free (OS_TMR *ptmr) +{ + ptmr->OSTmrState = OS_TMR_STATE_UNUSED; /* Clear timer object fields */ + ptmr->OSTmrOpt = OS_TMR_OPT_NONE; + ptmr->OSTmrPeriod = 0u; + ptmr->OSTmrMatch = 0u; + ptmr->OSTmrCallback = (OS_TMR_CALLBACK)0; + ptmr->OSTmrCallbackArg = (void *)0; +#if OS_TMR_CFG_NAME_EN > 0u + ptmr->OSTmrName = (INT8U *)(void *)"?"; +#endif + + ptmr->OSTmrPrev = (OS_TCB *)0; /* Chain timer to free list */ + ptmr->OSTmrNext = OSTmrFreeList; + OSTmrFreeList = ptmr; + + OSTmrUsed--; /* Update timer object statistics */ + OSTmrFree++; +} +#endif + +/*$PAGE*/ +/* +************************************************************************************************************************ +* INITIALIZATION +* INITIALIZE THE FREE LIST OF TIMERS +* +* Description: This function is called by OSInit() to initialize the free list of OS_TMRs. +* +* Arguments : none +* +* Returns : none +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +void OSTmr_Init (void) +{ +#if OS_EVENT_NAME_EN > 0u + INT8U err; +#endif + INT16U ix; + INT16U ix_next; + OS_TMR *ptmr1; + OS_TMR *ptmr2; + + + OS_MemClr((INT8U *)&OSTmrTbl[0], sizeof(OSTmrTbl)); /* Clear all the TMRs */ + OS_MemClr((INT8U *)&OSTmrWheelTbl[0], sizeof(OSTmrWheelTbl)); /* Clear the timer wheel */ + + for (ix = 0u; ix < (OS_TMR_CFG_MAX - 1u); ix++) { /* Init. list of free TMRs */ + ix_next = ix + 1u; + ptmr1 = &OSTmrTbl[ix]; + ptmr2 = &OSTmrTbl[ix_next]; + ptmr1->OSTmrType = OS_TMR_TYPE; + ptmr1->OSTmrState = OS_TMR_STATE_UNUSED; /* Indicate that timer is inactive */ + ptmr1->OSTmrNext = (void *)ptmr2; /* Link to next timer */ +#if OS_TMR_CFG_NAME_EN > 0u + ptmr1->OSTmrName = (INT8U *)(void *)"?"; +#endif + } + ptmr1 = &OSTmrTbl[ix]; + ptmr1->OSTmrType = OS_TMR_TYPE; + ptmr1->OSTmrState = OS_TMR_STATE_UNUSED; /* Indicate that timer is inactive */ + ptmr1->OSTmrNext = (void *)0; /* Last OS_TMR */ +#if OS_TMR_CFG_NAME_EN > 0u + ptmr1->OSTmrName = (INT8U *)(void *)"?"; +#endif + OSTmrTime = 0u; + OSTmrUsed = 0u; + OSTmrFree = OS_TMR_CFG_MAX; + OSTmrFreeList = &OSTmrTbl[0]; + OSTmrSem = OSSemCreate(1u); + OSTmrSemSignal = OSSemCreate(0u); + +#if OS_EVENT_NAME_EN > 0u /* Assign names to semaphores */ + OSEventNameSet(OSTmrSem, (INT8U *)(void *)"uC/OS-II TmrLock", &err); + OSEventNameSet(OSTmrSemSignal, (INT8U *)(void *)"uC/OS-II TmrSignal", &err); +#endif + + OSTmr_InitTask(); +} +#endif + +/*$PAGE*/ +/* +************************************************************************************************************************ +* INITIALIZE THE TIMER MANAGEMENT TASK +* +* Description: This function is called by OSTmrInit() to create the timer management task. +* * Arguments : none +* +* Returns : none +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +static void OSTmr_InitTask (void) +{ +#if OS_TASK_NAME_EN > 0u + INT8U err; +#endif + + +#if OS_TASK_CREATE_EXT_EN > 0u + #if OS_STK_GROWTH == 1u + (void)OSTaskCreateExt(OSTmr_Task, + (void *)0, /* No arguments passed to OSTmrTask() */ + &OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1u], /* Set Top-Of-Stack */ + OS_TASK_TMR_PRIO, + OS_TASK_TMR_ID, + &OSTmrTaskStk[0], /* Set Bottom-Of-Stack */ + OS_TASK_TMR_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear stack */ + #else + (void)OSTaskCreateExt(OSTmr_Task, + (void *)0, /* No arguments passed to OSTmrTask() */ + &OSTmrTaskStk[0], /* Set Top-Of-Stack */ + OS_TASK_TMR_PRIO, + OS_TASK_TMR_ID, + &OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1u], /* Set Bottom-Of-Stack */ + OS_TASK_TMR_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear stack */ + #endif +#else + #if OS_STK_GROWTH == 1u + (void)OSTaskCreate(OSTmr_Task, + (void *)0, + &OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1u], + OS_TASK_TMR_PRIO); + #else + (void)OSTaskCreate(OSTmr_Task, + (void *)0, + &OSTmrTaskStk[0], + OS_TASK_TMR_PRIO); + #endif +#endif + +#if OS_TASK_NAME_EN > 0u + OSTaskNameSet(OS_TASK_TMR_PRIO, (INT8U *)(void *)"uC/OS-II Tmr", &err); +#endif +} +#endif + +/*$PAGE*/ +/* +************************************************************************************************************************ +* INSERT A TIMER INTO THE TIMER WHEEL +* +* Description: This function is called to insert the timer into the timer wheel. The timer is always inserted at the +* beginning of the list. +* +* Arguments : ptmr Is a pointer to the timer to insert. +* +* type Is either: +* OS_TMR_LINK_PERIODIC Means to re-insert the timer after a period expired +* OS_TMR_LINK_DLY Means to insert the timer the first time +* +* Returns : none +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +static void OSTmr_Link (OS_TMR *ptmr, + INT8U type) +{ + OS_TMR *ptmr1; + OS_TMR_WHEEL *pspoke; + INT16U spoke; + + + ptmr->OSTmrState = OS_TMR_STATE_RUNNING; + if (type == OS_TMR_LINK_PERIODIC) { /* Determine when timer will expire */ + ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime; + } else { + if (ptmr->OSTmrDly == 0u) { + ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime; + } else { + ptmr->OSTmrMatch = ptmr->OSTmrDly + OSTmrTime; + } + } + spoke = (INT16U)(ptmr->OSTmrMatch % OS_TMR_CFG_WHEEL_SIZE); + pspoke = &OSTmrWheelTbl[spoke]; + + if (pspoke->OSTmrFirst == (OS_TMR *)0) { /* Link into timer wheel */ + pspoke->OSTmrFirst = ptmr; + ptmr->OSTmrNext = (OS_TMR *)0; + pspoke->OSTmrEntries = 1u; + } else { + ptmr1 = pspoke->OSTmrFirst; /* Point to first timer in the spoke */ + pspoke->OSTmrFirst = ptmr; + ptmr->OSTmrNext = (void *)ptmr1; + ptmr1->OSTmrPrev = (void *)ptmr; + pspoke->OSTmrEntries++; + } + ptmr->OSTmrPrev = (void *)0; /* Timer always inserted as first node in list */ +} +#endif + +/*$PAGE*/ +/* +************************************************************************************************************************ +* REMOVE A TIMER FROM THE TIMER WHEEL +* +* Description: This function is called to remove the timer from the timer wheel. +* +* Arguments : ptmr Is a pointer to the timer to remove. +* +* Returns : none +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +static void OSTmr_Unlink (OS_TMR *ptmr) +{ + OS_TMR *ptmr1; + OS_TMR *ptmr2; + OS_TMR_WHEEL *pspoke; + INT16U spoke; + + + spoke = (INT16U)(ptmr->OSTmrMatch % OS_TMR_CFG_WHEEL_SIZE); + pspoke = &OSTmrWheelTbl[spoke]; + + if (pspoke->OSTmrFirst == ptmr) { /* See if timer to remove is at the beginning of list */ + ptmr1 = (OS_TMR *)ptmr->OSTmrNext; + pspoke->OSTmrFirst = (OS_TMR *)ptmr1; + if (ptmr1 != (OS_TMR *)0) { + ptmr1->OSTmrPrev = (void *)0; + } + } else { + ptmr1 = (OS_TMR *)ptmr->OSTmrPrev; /* Remove timer from somewhere in the list */ + ptmr2 = (OS_TMR *)ptmr->OSTmrNext; + ptmr1->OSTmrNext = ptmr2; + if (ptmr2 != (OS_TMR *)0) { + ptmr2->OSTmrPrev = (void *)ptmr1; + } + } + ptmr->OSTmrState = OS_TMR_STATE_STOPPED; + ptmr->OSTmrNext = (void *)0; + ptmr->OSTmrPrev = (void *)0; + pspoke->OSTmrEntries--; +} +#endif + +/*$PAGE*/ +/* +************************************************************************************************************************ +* TIMER MANAGEMENT TASK +* +* Description: This task is created by OSTmrInit(). +* +* Arguments : none +* +* Returns : none +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +static void OSTmr_Task (void *p_arg) +{ + INT8U err; + OS_TMR *ptmr; + OS_TMR *ptmr_next; + OS_TMR_CALLBACK pfnct; + OS_TMR_WHEEL *pspoke; + INT16U spoke; + + + p_arg = p_arg; /* Prevent compiler warning for not using 'p_arg' */ + for (;;) { + OSSemPend(OSTmrSemSignal, 0u, &err); /* Wait for signal indicating time to update timers */ + OSSchedLock(); + OSTmrTime++; /* Increment the current time */ + spoke = (INT16U)(OSTmrTime % OS_TMR_CFG_WHEEL_SIZE); /* Position on current timer wheel entry */ + pspoke = &OSTmrWheelTbl[spoke]; + ptmr = pspoke->OSTmrFirst; + while (ptmr != (OS_TMR *)0) { + ptmr_next = (OS_TMR *)ptmr->OSTmrNext; /* Point to next timer to update because current ... */ + /* ... timer could get unlinked from the wheel. */ + if (OSTmrTime == ptmr->OSTmrMatch) { /* Process each timer that expires */ + OSTmr_Unlink(ptmr); /* Remove from current wheel spoke */ + if (ptmr->OSTmrOpt == OS_TMR_OPT_PERIODIC) { + OSTmr_Link(ptmr, OS_TMR_LINK_PERIODIC); /* Recalculate new position of timer in wheel */ + } else { + ptmr->OSTmrState = OS_TMR_STATE_COMPLETED; /* Indicate that the timer has completed */ + } + pfnct = ptmr->OSTmrCallback; /* Execute callback function if available */ + if (pfnct != (OS_TMR_CALLBACK)0) { + (*pfnct)((void *)ptmr, ptmr->OSTmrCallbackArg); + } + } + ptmr = ptmr_next; + } + OSSchedUnlock(); + } +} +#endif + diff --git a/UCOSII/CORE/ucos_ii.c b/UCOSII/CORE/ucos_ii.c new file mode 100644 index 0000000..01b1227 --- /dev/null +++ b/UCOSII/CORE/ucos_ii.c @@ -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 Micrim 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 + + +#define OS_MASTER_FILE /* Prevent the following files from including includes.h */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + diff --git a/UCOSII/CORE/ucos_ii.h b/UCOSII/CORE/ucos_ii.h new file mode 100644 index 0000000..a836f74 --- /dev/null +++ b/UCOSII/CORE/ucos_ii.h @@ -0,0 +1,1895 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* (c) Copyright 1992-2009, Micrium, Weston, FL +* All Rights Reserved +* +* File : uCOS_II.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 Micrim 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_uCOS_II_H +#define OS_uCOS_II_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* +********************************************************************************************************* +* uC/OS-II VERSION NUMBER +********************************************************************************************************* +*/ + +#define OS_VERSION 291u /* Version of uC/OS-II (Vx.yy mult. by 100) */ + +/* +********************************************************************************************************* +* INCLUDE HEADER FILES +********************************************************************************************************* +*/ + +#include "includes.h" +#include +#include + +/* +********************************************************************************************************* +* MISCELLANEOUS +********************************************************************************************************* +*/ + +#ifdef OS_GLOBALS +#define OS_EXT +#else +#define OS_EXT extern +#endif + +#ifndef OS_FALSE +#define OS_FALSE 0u +#endif + +#ifndef OS_TRUE +#define OS_TRUE 1u +#endif + +#define OS_ASCII_NUL (INT8U)0 + +#define OS_PRIO_SELF 0xFFu /* Indicate SELF priority */ + +#if OS_TASK_STAT_EN > 0u +#define OS_N_SYS_TASKS 2u /* Number of system tasks */ +#else +#define OS_N_SYS_TASKS 1u +#endif + +#define OS_TASK_STAT_PRIO (OS_LOWEST_PRIO - 1u) /* Statistic task priority */ +#define OS_TASK_IDLE_PRIO (OS_LOWEST_PRIO) /* IDLE task priority */ + +#if OS_LOWEST_PRIO <= 63u +#define OS_EVENT_TBL_SIZE ((OS_LOWEST_PRIO) / 8u + 1u) /* Size of event table */ +#define OS_RDY_TBL_SIZE ((OS_LOWEST_PRIO) / 8u + 1u) /* Size of ready table */ +#else +#define OS_EVENT_TBL_SIZE ((OS_LOWEST_PRIO) / 16u + 1u)/* Size of event table */ +#define OS_RDY_TBL_SIZE ((OS_LOWEST_PRIO) / 16u + 1u)/* Size of ready table */ +#endif + +#define OS_TASK_IDLE_ID 65535u /* ID numbers for Idle, Stat and Timer tasks */ +#define OS_TASK_STAT_ID 65534u +#define OS_TASK_TMR_ID 65533u + +#define OS_EVENT_EN (((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) || (OS_MBOX_EN > 0u) || (OS_SEM_EN > 0u) || (OS_MUTEX_EN > 0u)) + +#define OS_TCB_RESERVED ((OS_TCB *)1) + +/*$PAGE*/ +/* +********************************************************************************************************* +* TASK STATUS (Bit definition for OSTCBStat) +********************************************************************************************************* +*/ +#define OS_STAT_RDY 0x00u /* Ready to run */ +#define OS_STAT_SEM 0x01u /* Pending on semaphore */ +#define OS_STAT_MBOX 0x02u /* Pending on mailbox */ +#define OS_STAT_Q 0x04u /* Pending on queue */ +#define OS_STAT_SUSPEND 0x08u /* Task is suspended */ +#define OS_STAT_MUTEX 0x10u /* Pending on mutual exclusion semaphore */ +#define OS_STAT_FLAG 0x20u /* Pending on event flag group */ +#define OS_STAT_MULTI 0x80u /* Pending on multiple events */ + +#define OS_STAT_PEND_ANY (OS_STAT_SEM | OS_STAT_MBOX | OS_STAT_Q | OS_STAT_MUTEX | OS_STAT_FLAG) + +/* +********************************************************************************************************* +* TASK PEND STATUS (Status codes for OSTCBStatPend) +********************************************************************************************************* +*/ +#define OS_STAT_PEND_OK 0u /* Pending status OK, not pending, or pending complete */ +#define OS_STAT_PEND_TO 1u /* Pending timed out */ +#define OS_STAT_PEND_ABORT 2u /* Pending aborted */ + +/* +********************************************************************************************************* +* OS_EVENT types +********************************************************************************************************* +*/ +#define OS_EVENT_TYPE_UNUSED 0u +#define OS_EVENT_TYPE_MBOX 1u +#define OS_EVENT_TYPE_Q 2u +#define OS_EVENT_TYPE_SEM 3u +#define OS_EVENT_TYPE_MUTEX 4u +#define OS_EVENT_TYPE_FLAG 5u + +#define OS_TMR_TYPE 100u /* Used to identify Timers ... */ + /* ... (Must be different value than OS_EVENT_TYPE_xxx) */ + +/* +********************************************************************************************************* +* EVENT FLAGS +********************************************************************************************************* +*/ +#define OS_FLAG_WAIT_CLR_ALL 0u /* Wait for ALL the bits specified to be CLR (i.e. 0) */ +#define OS_FLAG_WAIT_CLR_AND 0u + +#define OS_FLAG_WAIT_CLR_ANY 1u /* Wait for ANY of the bits specified to be CLR (i.e. 0) */ +#define OS_FLAG_WAIT_CLR_OR 1u + +#define OS_FLAG_WAIT_SET_ALL 2u /* Wait for ALL the bits specified to be SET (i.e. 1) */ +#define OS_FLAG_WAIT_SET_AND 2u + +#define OS_FLAG_WAIT_SET_ANY 3u /* Wait for ANY of the bits specified to be SET (i.e. 1) */ +#define OS_FLAG_WAIT_SET_OR 3u + + +#define OS_FLAG_CONSUME 0x80u /* Consume the flags if condition(s) satisfied */ + + +#define OS_FLAG_CLR 0u +#define OS_FLAG_SET 1u + +/* +********************************************************************************************************* +* Values for OSTickStepState +* +* Note(s): This feature is used by uC/OS-View. +********************************************************************************************************* +*/ + +#if OS_TICK_STEP_EN > 0u +#define OS_TICK_STEP_DIS 0u /* Stepping is disabled, tick runs as mormal */ +#define OS_TICK_STEP_WAIT 1u /* Waiting for uC/OS-View to set OSTickStepState to _ONCE */ +#define OS_TICK_STEP_ONCE 2u /* Process tick once and wait for next cmd from uC/OS-View */ +#endif + +/* +********************************************************************************************************* +* Possible values for 'opt' argument of OSSemDel(), OSMboxDel(), OSQDel() and OSMutexDel() +********************************************************************************************************* +*/ +#define OS_DEL_NO_PEND 0u +#define OS_DEL_ALWAYS 1u + +/* +********************************************************************************************************* +* OS???Pend() OPTIONS +* +* These #defines are used to establish the options for OS???PendAbort(). +********************************************************************************************************* +*/ +#define OS_PEND_OPT_NONE 0u /* NO option selected */ +#define OS_PEND_OPT_BROADCAST 1u /* Broadcast action to ALL tasks waiting */ + +/* +********************************************************************************************************* +* OS???PostOpt() OPTIONS +* +* These #defines are used to establish the options for OSMboxPostOpt() and OSQPostOpt(). +********************************************************************************************************* +*/ +#define OS_POST_OPT_NONE 0x00u /* NO option selected */ +#define OS_POST_OPT_BROADCAST 0x01u /* Broadcast message to ALL tasks waiting */ +#define OS_POST_OPT_FRONT 0x02u /* Post to highest priority task waiting */ +#define OS_POST_OPT_NO_SCHED 0x04u /* Do not call the scheduler if this option is selected */ + +/* +********************************************************************************************************* +* TASK OPTIONS (see OSTaskCreateExt()) +********************************************************************************************************* +*/ +#define OS_TASK_OPT_NONE 0x0000u /* NO option selected */ +#define OS_TASK_OPT_STK_CHK 0x0001u /* Enable stack checking for the task */ +#define OS_TASK_OPT_STK_CLR 0x0002u /* Clear the stack when the task is create */ +#define OS_TASK_OPT_SAVE_FP 0x0004u /* Save the contents of any floating-point registers */ + +/* +********************************************************************************************************* +* TIMER OPTIONS (see OSTmrStart() and OSTmrStop()) +********************************************************************************************************* +*/ +#define OS_TMR_OPT_NONE 0u /* No option selected */ + +#define OS_TMR_OPT_ONE_SHOT 1u /* Timer will not automatically restart when it expires */ +#define OS_TMR_OPT_PERIODIC 2u /* Timer will automatically restart when it expires */ + +#define OS_TMR_OPT_CALLBACK 3u /* OSTmrStop() option to call 'callback' w/ timer arg. */ +#define OS_TMR_OPT_CALLBACK_ARG 4u /* OSTmrStop() option to call 'callback' w/ new arg. */ + +/* +********************************************************************************************************* +* TIMER STATES +********************************************************************************************************* +*/ +#define OS_TMR_STATE_UNUSED 0u +#define OS_TMR_STATE_STOPPED 1u +#define OS_TMR_STATE_COMPLETED 2u +#define OS_TMR_STATE_RUNNING 3u + +/* +********************************************************************************************************* +* ERROR CODES +********************************************************************************************************* +*/ +#define OS_ERR_NONE 0u + +#define OS_ERR_EVENT_TYPE 1u +#define OS_ERR_PEND_ISR 2u +#define OS_ERR_POST_NULL_PTR 3u +#define OS_ERR_PEVENT_NULL 4u +#define OS_ERR_POST_ISR 5u +#define OS_ERR_QUERY_ISR 6u +#define OS_ERR_INVALID_OPT 7u +#define OS_ERR_ID_INVALID 8u +#define OS_ERR_PDATA_NULL 9u + +#define OS_ERR_TIMEOUT 10u +#define OS_ERR_EVENT_NAME_TOO_LONG 11u +#define OS_ERR_PNAME_NULL 12u +#define OS_ERR_PEND_LOCKED 13u +#define OS_ERR_PEND_ABORT 14u +#define OS_ERR_DEL_ISR 15u +#define OS_ERR_CREATE_ISR 16u +#define OS_ERR_NAME_GET_ISR 17u +#define OS_ERR_NAME_SET_ISR 18u +#define OS_ERR_ILLEGAL_CREATE_RUN_TIME 19u + +#define OS_ERR_MBOX_FULL 20u + +#define OS_ERR_Q_FULL 30u +#define OS_ERR_Q_EMPTY 31u + +#define OS_ERR_PRIO_EXIST 40u +#define OS_ERR_PRIO 41u +#define OS_ERR_PRIO_INVALID 42u + +#define OS_ERR_SCHED_LOCKED 50u +#define OS_ERR_SEM_OVF 51u + +#define OS_ERR_TASK_CREATE_ISR 60u +#define OS_ERR_TASK_DEL 61u +#define OS_ERR_TASK_DEL_IDLE 62u +#define OS_ERR_TASK_DEL_REQ 63u +#define OS_ERR_TASK_DEL_ISR 64u +#define OS_ERR_TASK_NAME_TOO_LONG 65u +#define OS_ERR_TASK_NO_MORE_TCB 66u +#define OS_ERR_TASK_NOT_EXIST 67u +#define OS_ERR_TASK_NOT_SUSPENDED 68u +#define OS_ERR_TASK_OPT 69u +#define OS_ERR_TASK_RESUME_PRIO 70u +#define OS_ERR_TASK_SUSPEND_IDLE 71u +#define OS_ERR_TASK_SUSPEND_PRIO 72u +#define OS_ERR_TASK_WAITING 73u + +#define OS_ERR_TIME_NOT_DLY 80u +#define OS_ERR_TIME_INVALID_MINUTES 81u +#define OS_ERR_TIME_INVALID_SECONDS 82u +#define OS_ERR_TIME_INVALID_MS 83u +#define OS_ERR_TIME_ZERO_DLY 84u +#define OS_ERR_TIME_DLY_ISR 85u + +#define OS_ERR_MEM_INVALID_PART 90u +#define OS_ERR_MEM_INVALID_BLKS 91u +#define OS_ERR_MEM_INVALID_SIZE 92u +#define OS_ERR_MEM_NO_FREE_BLKS 93u +#define OS_ERR_MEM_FULL 94u +#define OS_ERR_MEM_INVALID_PBLK 95u +#define OS_ERR_MEM_INVALID_PMEM 96u +#define OS_ERR_MEM_INVALID_PDATA 97u +#define OS_ERR_MEM_INVALID_ADDR 98u +#define OS_ERR_MEM_NAME_TOO_LONG 99u + +#define OS_ERR_NOT_MUTEX_OWNER 100u + +#define OS_ERR_FLAG_INVALID_PGRP 110u +#define OS_ERR_FLAG_WAIT_TYPE 111u +#define OS_ERR_FLAG_NOT_RDY 112u +#define OS_ERR_FLAG_INVALID_OPT 113u +#define OS_ERR_FLAG_GRP_DEPLETED 114u +#define OS_ERR_FLAG_NAME_TOO_LONG 115u + +#define OS_ERR_PIP_LOWER 120u + +#define OS_ERR_TMR_INVALID_DLY 130u +#define OS_ERR_TMR_INVALID_PERIOD 131u +#define OS_ERR_TMR_INVALID_OPT 132u +#define OS_ERR_TMR_INVALID_NAME 133u +#define OS_ERR_TMR_NON_AVAIL 134u +#define OS_ERR_TMR_INACTIVE 135u +#define OS_ERR_TMR_INVALID_DEST 136u +#define OS_ERR_TMR_INVALID_TYPE 137u +#define OS_ERR_TMR_INVALID 138u +#define OS_ERR_TMR_ISR 139u +#define OS_ERR_TMR_NAME_TOO_LONG 140u +#define OS_ERR_TMR_INVALID_STATE 141u +#define OS_ERR_TMR_STOPPED 142u +#define OS_ERR_TMR_NO_CALLBACK 143u + +/*$PAGE*/ +/* +********************************************************************************************************* +* EVENT CONTROL BLOCK +********************************************************************************************************* +*/ + +#if OS_LOWEST_PRIO <= 63u +typedef INT8U OS_PRIO; +#else +typedef INT16U OS_PRIO; +#endif + +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +typedef struct os_event { + INT8U OSEventType; /* Type of event control block (see OS_EVENT_TYPE_xxxx) */ + void *OSEventPtr; /* Pointer to message or queue structure */ + INT16U OSEventCnt; /* Semaphore Count (not used if other EVENT type) */ + OS_PRIO OSEventGrp; /* Group corresponding to tasks waiting for event to occur */ + OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */ + +#if OS_EVENT_NAME_EN > 0u + INT8U *OSEventName; +#endif +} OS_EVENT; +#endif + + +/* +********************************************************************************************************* +* EVENT FLAGS CONTROL BLOCK +********************************************************************************************************* +*/ + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + +#if OS_FLAGS_NBITS == 8u /* Determine the size of OS_FLAGS (8, 16 or 32 bits) */ +typedef INT8U OS_FLAGS; +#endif + +#if OS_FLAGS_NBITS == 16u +typedef INT16U OS_FLAGS; +#endif + +#if OS_FLAGS_NBITS == 32u +typedef INT32U OS_FLAGS; +#endif + + +typedef struct os_flag_grp { /* Event Flag Group */ + INT8U OSFlagType; /* Should be set to OS_EVENT_TYPE_FLAG */ + void *OSFlagWaitList; /* Pointer to first NODE of task waiting on event flag */ + OS_FLAGS OSFlagFlags; /* 8, 16 or 32 bit flags */ +#if OS_FLAG_NAME_EN > 0u + INT8U *OSFlagName; +#endif +} OS_FLAG_GRP; + + + +typedef struct os_flag_node { /* Event Flag Wait List Node */ + void *OSFlagNodeNext; /* Pointer to next NODE in wait list */ + void *OSFlagNodePrev; /* Pointer to previous NODE in wait list */ + void *OSFlagNodeTCB; /* Pointer to TCB of waiting task */ + void *OSFlagNodeFlagGrp; /* Pointer to Event Flag Group */ + OS_FLAGS OSFlagNodeFlags; /* Event flag to wait on */ + INT8U OSFlagNodeWaitType; /* Type of wait: */ + /* OS_FLAG_WAIT_AND */ + /* OS_FLAG_WAIT_ALL */ + /* OS_FLAG_WAIT_OR */ + /* OS_FLAG_WAIT_ANY */ +} OS_FLAG_NODE; +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* MESSAGE MAILBOX DATA +********************************************************************************************************* +*/ + +#if OS_MBOX_EN > 0u +typedef struct os_mbox_data { + void *OSMsg; /* Pointer to message in mailbox */ + OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */ + OS_PRIO OSEventGrp; /* Group corresponding to tasks waiting for event to occur */ +} OS_MBOX_DATA; +#endif + +/* +********************************************************************************************************* +* MEMORY PARTITION DATA STRUCTURES +********************************************************************************************************* +*/ + +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +typedef struct os_mem { /* MEMORY CONTROL BLOCK */ + void *OSMemAddr; /* Pointer to beginning of memory partition */ + void *OSMemFreeList; /* Pointer to list of free memory blocks */ + INT32U OSMemBlkSize; /* Size (in bytes) of each block of memory */ + INT32U OSMemNBlks; /* Total number of blocks in this partition */ + INT32U OSMemNFree; /* Number of memory blocks remaining in this partition */ +#if OS_MEM_NAME_EN > 0u + INT8U *OSMemName; /* Memory partition name */ +#endif +} OS_MEM; + + +typedef struct os_mem_data { + void *OSAddr; /* Pointer to the beginning address of the memory partition */ + void *OSFreeList; /* Pointer to the beginning of the free list of memory blocks */ + INT32U OSBlkSize; /* Size (in bytes) of each memory block */ + INT32U OSNBlks; /* Total number of blocks in the partition */ + INT32U OSNFree; /* Number of memory blocks free */ + INT32U OSNUsed; /* Number of memory blocks used */ +} OS_MEM_DATA; +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* MUTUAL EXCLUSION SEMAPHORE DATA +********************************************************************************************************* +*/ + +#if OS_MUTEX_EN > 0u +typedef struct os_mutex_data { + OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */ + OS_PRIO OSEventGrp; /* Group corresponding to tasks waiting for event to occur */ + BOOLEAN OSValue; /* Mutex value (OS_FALSE = used, OS_TRUE = available) */ + INT8U OSOwnerPrio; /* Mutex owner's task priority or 0xFF if no owner */ + INT8U OSMutexPIP; /* Priority Inheritance Priority or 0xFF if no owner */ +} OS_MUTEX_DATA; +#endif + +/* +********************************************************************************************************* +* MESSAGE QUEUE DATA +********************************************************************************************************* +*/ + +#if OS_Q_EN > 0u +typedef struct os_q { /* QUEUE CONTROL BLOCK */ + struct os_q *OSQPtr; /* Link to next queue control block in list of free blocks */ + void **OSQStart; /* Pointer to start of queue data */ + void **OSQEnd; /* Pointer to end of queue data */ + void **OSQIn; /* Pointer to where next message will be inserted in the Q */ + void **OSQOut; /* Pointer to where next message will be extracted from the Q */ + INT16U OSQSize; /* Size of queue (maximum number of entries) */ + INT16U OSQEntries; /* Current number of entries in the queue */ +} OS_Q; + + +typedef struct os_q_data { + void *OSMsg; /* Pointer to next message to be extracted from queue */ + INT16U OSNMsgs; /* Number of messages in message queue */ + INT16U OSQSize; /* Size of message queue */ + OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */ + OS_PRIO OSEventGrp; /* Group corresponding to tasks waiting for event to occur */ +} OS_Q_DATA; +#endif + +/* +********************************************************************************************************* +* SEMAPHORE DATA +********************************************************************************************************* +*/ + +#if OS_SEM_EN > 0u +typedef struct os_sem_data { + INT16U OSCnt; /* Semaphore count */ + OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */ + OS_PRIO OSEventGrp; /* Group corresponding to tasks waiting for event to occur */ +} OS_SEM_DATA; +#endif + +/* +********************************************************************************************************* +* TASK STACK DATA +********************************************************************************************************* +*/ + +#if OS_TASK_CREATE_EXT_EN > 0u +typedef struct os_stk_data { + INT32U OSFree; /* Number of free bytes on the stack */ + INT32U OSUsed; /* Number of bytes used on the stack */ +} OS_STK_DATA; +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* TASK CONTROL BLOCK +********************************************************************************************************* +*/ + +typedef struct os_tcb { + OS_STK *OSTCBStkPtr; /* Pointer to current top of stack */ + +#if OS_TASK_CREATE_EXT_EN > 0u + void *OSTCBExtPtr; /* Pointer to user definable data for TCB extension */ + OS_STK *OSTCBStkBottom; /* Pointer to bottom of stack */ + INT32U OSTCBStkSize; /* Size of task stack (in number of stack elements) */ + INT16U OSTCBOpt; /* Task options as passed by OSTaskCreateExt() */ + INT16U OSTCBId; /* Task ID (0..65535) */ +#endif + + struct os_tcb *OSTCBNext; /* Pointer to next TCB in the TCB list */ + struct os_tcb *OSTCBPrev; /* Pointer to previous TCB in the TCB list */ + +#if (OS_EVENT_EN) + OS_EVENT *OSTCBEventPtr; /* Pointer to event control block */ +#endif + +#if (OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u) + OS_EVENT **OSTCBEventMultiPtr; /* Pointer to multiple event control blocks */ +#endif + +#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) || (OS_MBOX_EN > 0u) + void *OSTCBMsg; /* Message received from OSMboxPost() or OSQPost() */ +#endif + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +#if OS_TASK_DEL_EN > 0u + OS_FLAG_NODE *OSTCBFlagNode; /* Pointer to event flag node */ +#endif + OS_FLAGS OSTCBFlagsRdy; /* Event flags that made task ready to run */ +#endif + + INT32U OSTCBDly; /* Nbr ticks to delay task or, timeout waiting for event */ + INT8U OSTCBStat; /* Task status */ + INT8U OSTCBStatPend; /* Task PEND status */ + INT8U OSTCBPrio; /* Task priority (0 == highest) */ + + INT8U OSTCBX; /* Bit position in group corresponding to task priority */ + INT8U OSTCBY; /* Index into ready table corresponding to task priority */ + OS_PRIO OSTCBBitX; /* Bit mask to access bit position in ready table */ + OS_PRIO OSTCBBitY; /* Bit mask to access bit position in ready group */ + +#if OS_TASK_DEL_EN > 0u + INT8U OSTCBDelReq; /* Indicates whether a task needs to delete itself */ +#endif + +#if OS_TASK_PROFILE_EN > 0u + INT32U OSTCBCtxSwCtr; /* Number of time the task was switched in */ + INT32U OSTCBCyclesTot; /* Total number of clock cycles the task has been running */ + INT32U OSTCBCyclesStart; /* Snapshot of cycle counter at start of task resumption */ + OS_STK *OSTCBStkBase; /* Pointer to the beginning of the task stack */ + INT32U OSTCBStkUsed; /* Number of bytes used from the stack */ +#endif + +#if OS_TASK_NAME_EN > 0u + INT8U *OSTCBTaskName; +#endif + +#if OS_TASK_REG_TBL_SIZE > 0u + INT32U OSTCBRegTbl[OS_TASK_REG_TBL_SIZE]; +#endif +} OS_TCB; + +/*$PAGE*/ +/* +************************************************************************************************************************ +* TIMER DATA TYPES +************************************************************************************************************************ +*/ + +#if OS_TMR_EN > 0u +typedef void (*OS_TMR_CALLBACK)(void *ptmr, void *parg); + + + +typedef struct os_tmr { + INT8U OSTmrType; /* Should be set to OS_TMR_TYPE */ + OS_TMR_CALLBACK OSTmrCallback; /* Function to call when timer expires */ + void *OSTmrCallbackArg; /* Argument to pass to function when timer expires */ + void *OSTmrNext; /* Double link list pointers */ + void *OSTmrPrev; + INT32U OSTmrMatch; /* Timer expires when OSTmrTime == OSTmrMatch */ + INT32U OSTmrDly; /* Delay time before periodic update starts */ + INT32U OSTmrPeriod; /* Period to repeat timer */ +#if OS_TMR_CFG_NAME_EN > 0u + INT8U *OSTmrName; /* Name to give the timer */ +#endif + INT8U OSTmrOpt; /* Options (see OS_TMR_OPT_xxx) */ + INT8U OSTmrState; /* Indicates the state of the timer: */ + /* OS_TMR_STATE_UNUSED */ + /* OS_TMR_STATE_RUNNING */ + /* OS_TMR_STATE_STOPPED */ +} OS_TMR; + + + +typedef struct os_tmr_wheel { + OS_TMR *OSTmrFirst; /* Pointer to first timer in linked list */ + INT16U OSTmrEntries; +} OS_TMR_WHEEL; +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_EXT INT32U OSCtxSwCtr; /* Counter of number of context switches */ + +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +OS_EXT OS_EVENT *OSEventFreeList; /* Pointer to list of free EVENT control blocks */ +OS_EXT OS_EVENT OSEventTbl[OS_MAX_EVENTS];/* Table of EVENT control blocks */ +#endif + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +OS_EXT OS_FLAG_GRP OSFlagTbl[OS_MAX_FLAGS]; /* Table containing event flag groups */ +OS_EXT OS_FLAG_GRP *OSFlagFreeList; /* Pointer to free list of event flag groups */ +#endif + +#if OS_TASK_STAT_EN > 0u +OS_EXT INT8U OSCPUUsage; /* Percentage of CPU used */ +OS_EXT INT32U OSIdleCtrMax; /* Max. value that idle ctr can take in 1 sec. */ +OS_EXT INT32U OSIdleCtrRun; /* Val. reached by idle ctr at run time in 1 sec. */ +OS_EXT BOOLEAN OSStatRdy; /* Flag indicating that the statistic task is rdy */ +OS_EXT OS_STK OSTaskStatStk[OS_TASK_STAT_STK_SIZE]; /* Statistics task stack */ +#endif + +OS_EXT INT8U OSIntNesting; /* Interrupt nesting level */ + +OS_EXT INT8U OSLockNesting; /* Multitasking lock nesting level */ + +OS_EXT INT8U OSPrioCur; /* Priority of current task */ +OS_EXT INT8U OSPrioHighRdy; /* Priority of highest priority task */ + +OS_EXT OS_PRIO OSRdyGrp; /* Ready list group */ +OS_EXT OS_PRIO OSRdyTbl[OS_RDY_TBL_SIZE]; /* Table of tasks which are ready to run */ + +OS_EXT BOOLEAN OSRunning; /* Flag indicating that kernel is running */ + +OS_EXT INT8U OSTaskCtr; /* Number of tasks created */ + +OS_EXT volatile INT32U OSIdleCtr; /* Idle counter */ + +#ifdef OS_SAFETY_CRITICAL_IEC61508 +OS_EXT BOOLEAN OSSafetyCriticalStartFlag; +#endif + +OS_EXT OS_STK OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE]; /* Idle task stack */ + + +OS_EXT OS_TCB *OSTCBCur; /* Pointer to currently running TCB */ +OS_EXT OS_TCB *OSTCBFreeList; /* Pointer to list of free TCBs */ +OS_EXT OS_TCB *OSTCBHighRdy; /* Pointer to highest priority TCB R-to-R */ +OS_EXT OS_TCB *OSTCBList; /* Pointer to doubly linked list of TCBs */ +OS_EXT OS_TCB *OSTCBPrioTbl[OS_LOWEST_PRIO + 1u]; /* Table of pointers to created TCBs */ +OS_EXT OS_TCB OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS]; /* Table of TCBs */ + +#if OS_TICK_STEP_EN > 0u +OS_EXT INT8U OSTickStepState; /* Indicates the state of the tick step feature */ +#endif + +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +OS_EXT OS_MEM *OSMemFreeList; /* Pointer to free list of memory partitions */ +OS_EXT OS_MEM OSMemTbl[OS_MAX_MEM_PART];/* Storage for memory partition manager */ +#endif + +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +OS_EXT OS_Q *OSQFreeList; /* Pointer to list of free QUEUE control blocks */ +OS_EXT OS_Q OSQTbl[OS_MAX_QS]; /* Table of QUEUE control blocks */ +#endif + +#if OS_TIME_GET_SET_EN > 0u +OS_EXT volatile INT32U OSTime; /* Current value of system time (in ticks) */ +#endif + +#if OS_TMR_EN > 0u +OS_EXT INT16U OSTmrFree; /* Number of free entries in the timer pool */ +OS_EXT INT16U OSTmrUsed; /* Number of timers used */ +OS_EXT INT32U OSTmrTime; /* Current timer time */ + +OS_EXT OS_EVENT *OSTmrSem; /* Sem. used to gain exclusive access to timers */ +OS_EXT OS_EVENT *OSTmrSemSignal; /* Sem. used to signal the update of timers */ + +OS_EXT OS_TMR OSTmrTbl[OS_TMR_CFG_MAX]; /* Table containing pool of timers */ +OS_EXT OS_TMR *OSTmrFreeList; /* Pointer to free list of timers */ +OS_EXT OS_STK OSTmrTaskStk[OS_TASK_TMR_STK_SIZE]; + +OS_EXT OS_TMR_WHEEL OSTmrWheelTbl[OS_TMR_CFG_WHEEL_SIZE]; +#endif + +extern INT8U const OSUnMapTbl[256]; /* Priority->Index lookup table */ + +/*$PAGE*/ +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +* (Target Independent Functions) +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* MISCELLANEOUS +********************************************************************************************************* +*/ + +#if (OS_EVENT_EN) + +#if (OS_EVENT_NAME_EN > 0u) +INT8U OSEventNameGet (OS_EVENT *pevent, + INT8U **pname, + INT8U *perr); + +void OSEventNameSet (OS_EVENT *pevent, + INT8U *pname, + INT8U *perr); +#endif + +#if (OS_EVENT_MULTI_EN > 0u) +INT16U OSEventPendMulti (OS_EVENT **pevents_pend, + OS_EVENT **pevents_rdy, + void **pmsgs_rdy, + INT32U timeout, + INT8U *perr); +#endif + +#endif + +/* +********************************************************************************************************* +* EVENT FLAGS MANAGEMENT +********************************************************************************************************* +*/ + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + +#if OS_FLAG_ACCEPT_EN > 0u +OS_FLAGS OSFlagAccept (OS_FLAG_GRP *pgrp, + OS_FLAGS flags, + INT8U wait_type, + INT8U *perr); +#endif + +OS_FLAG_GRP *OSFlagCreate (OS_FLAGS flags, + INT8U *perr); + +#if OS_FLAG_DEL_EN > 0u +OS_FLAG_GRP *OSFlagDel (OS_FLAG_GRP *pgrp, + INT8U opt, + INT8U *perr); +#endif + +#if (OS_FLAG_EN > 0u) && (OS_FLAG_NAME_EN > 0u) +INT8U OSFlagNameGet (OS_FLAG_GRP *pgrp, + INT8U **pname, + INT8U *perr); + +void OSFlagNameSet (OS_FLAG_GRP *pgrp, + INT8U *pname, + INT8U *perr); +#endif + +OS_FLAGS OSFlagPend (OS_FLAG_GRP *pgrp, + OS_FLAGS flags, + INT8U wait_type, + INT32U timeout, + INT8U *perr); + +OS_FLAGS OSFlagPendGetFlagsRdy (void); +OS_FLAGS OSFlagPost (OS_FLAG_GRP *pgrp, + OS_FLAGS flags, + INT8U opt, + INT8U *perr); + +#if OS_FLAG_QUERY_EN > 0u +OS_FLAGS OSFlagQuery (OS_FLAG_GRP *pgrp, + INT8U *perr); +#endif +#endif + +/* +********************************************************************************************************* +* MESSAGE MAILBOX MANAGEMENT +********************************************************************************************************* +*/ + +#if OS_MBOX_EN > 0u + +#if OS_MBOX_ACCEPT_EN > 0u +void *OSMboxAccept (OS_EVENT *pevent); +#endif + +OS_EVENT *OSMboxCreate (void *pmsg); + +#if OS_MBOX_DEL_EN > 0u +OS_EVENT *OSMboxDel (OS_EVENT *pevent, + INT8U opt, + INT8U *perr); +#endif + +void *OSMboxPend (OS_EVENT *pevent, + INT32U timeout, + INT8U *perr); + +#if OS_MBOX_PEND_ABORT_EN > 0u +INT8U OSMboxPendAbort (OS_EVENT *pevent, + INT8U opt, + INT8U *perr); +#endif + +#if OS_MBOX_POST_EN > 0u +INT8U OSMboxPost (OS_EVENT *pevent, + void *pmsg); +#endif + +#if OS_MBOX_POST_OPT_EN > 0u +INT8U OSMboxPostOpt (OS_EVENT *pevent, + void *pmsg, + INT8U opt); +#endif + +#if OS_MBOX_QUERY_EN > 0u +INT8U OSMboxQuery (OS_EVENT *pevent, + OS_MBOX_DATA *p_mbox_data); +#endif +#endif + +/* +********************************************************************************************************* +* MEMORY MANAGEMENT +********************************************************************************************************* +*/ + +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + +OS_MEM *OSMemCreate (void *addr, + INT32U nblks, + INT32U blksize, + INT8U *perr); + +void *OSMemGet (OS_MEM *pmem, + INT8U *perr); +#if OS_MEM_NAME_EN > 0u +INT8U OSMemNameGet (OS_MEM *pmem, + INT8U **pname, + INT8U *perr); + +void OSMemNameSet (OS_MEM *pmem, + INT8U *pname, + INT8U *perr); +#endif +INT8U OSMemPut (OS_MEM *pmem, + void *pblk); + +#if OS_MEM_QUERY_EN > 0u +INT8U OSMemQuery (OS_MEM *pmem, + OS_MEM_DATA *p_mem_data); +#endif + +#endif + +/* +********************************************************************************************************* +* MUTUAL EXCLUSION SEMAPHORE MANAGEMENT +********************************************************************************************************* +*/ + +#if OS_MUTEX_EN > 0u + +#if OS_MUTEX_ACCEPT_EN > 0u +BOOLEAN OSMutexAccept (OS_EVENT *pevent, + INT8U *perr); +#endif + +OS_EVENT *OSMutexCreate (INT8U prio, + INT8U *perr); + +#if OS_MUTEX_DEL_EN > 0u +OS_EVENT *OSMutexDel (OS_EVENT *pevent, + INT8U opt, + INT8U *perr); +#endif + +void OSMutexPend (OS_EVENT *pevent, + INT32U timeout, + INT8U *perr); + +INT8U OSMutexPost (OS_EVENT *pevent); + +#if OS_MUTEX_QUERY_EN > 0u +INT8U OSMutexQuery (OS_EVENT *pevent, + OS_MUTEX_DATA *p_mutex_data); +#endif + +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* MESSAGE QUEUE MANAGEMENT +********************************************************************************************************* +*/ + +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + +#if OS_Q_ACCEPT_EN > 0u +void *OSQAccept (OS_EVENT *pevent, + INT8U *perr); +#endif + +OS_EVENT *OSQCreate (void **start, + INT16U size); + +#if OS_Q_DEL_EN > 0u +OS_EVENT *OSQDel (OS_EVENT *pevent, + INT8U opt, + INT8U *perr); +#endif + +#if OS_Q_FLUSH_EN > 0u +INT8U OSQFlush (OS_EVENT *pevent); +#endif + +void *OSQPend (OS_EVENT *pevent, + INT32U timeout, + INT8U *perr); + +#if OS_Q_PEND_ABORT_EN > 0u +INT8U OSQPendAbort (OS_EVENT *pevent, + INT8U opt, + INT8U *perr); +#endif + +#if OS_Q_POST_EN > 0u +INT8U OSQPost (OS_EVENT *pevent, + void *pmsg); +#endif + +#if OS_Q_POST_FRONT_EN > 0u +INT8U OSQPostFront (OS_EVENT *pevent, + void *pmsg); +#endif + +#if OS_Q_POST_OPT_EN > 0u +INT8U OSQPostOpt (OS_EVENT *pevent, + void *pmsg, + INT8U opt); +#endif + +#if OS_Q_QUERY_EN > 0u +INT8U OSQQuery (OS_EVENT *pevent, + OS_Q_DATA *p_q_data); +#endif + +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* SEMAPHORE MANAGEMENT +********************************************************************************************************* +*/ +#if OS_SEM_EN > 0u + +#if OS_SEM_ACCEPT_EN > 0u +INT16U OSSemAccept (OS_EVENT *pevent); +#endif + +OS_EVENT *OSSemCreate (INT16U cnt); + +#if OS_SEM_DEL_EN > 0u +OS_EVENT *OSSemDel (OS_EVENT *pevent, + INT8U opt, + INT8U *perr); +#endif + +void OSSemPend (OS_EVENT *pevent, + INT32U timeout, + INT8U *perr); + +#if OS_SEM_PEND_ABORT_EN > 0u +INT8U OSSemPendAbort (OS_EVENT *pevent, + INT8U opt, + INT8U *perr); +#endif + +INT8U OSSemPost (OS_EVENT *pevent); + +#if OS_SEM_QUERY_EN > 0u +INT8U OSSemQuery (OS_EVENT *pevent, + OS_SEM_DATA *p_sem_data); +#endif + +#if OS_SEM_SET_EN > 0u +void OSSemSet (OS_EVENT *pevent, + INT16U cnt, + INT8U *perr); +#endif + +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* TASK MANAGEMENT +********************************************************************************************************* +*/ +#if OS_TASK_CHANGE_PRIO_EN > 0u +INT8U OSTaskChangePrio (INT8U oldprio, + INT8U newprio); +#endif + +#if OS_TASK_CREATE_EN > 0u +INT8U OSTaskCreate (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT8U prio); +#endif + +#if OS_TASK_CREATE_EXT_EN > 0u +INT8U OSTaskCreateExt (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT8U prio, + INT16U id, + OS_STK *pbos, + INT32U stk_size, + void *pext, + INT16U opt); +#endif + +#if OS_TASK_DEL_EN > 0u +INT8U OSTaskDel (INT8U prio); +INT8U OSTaskDelReq (INT8U prio); +#endif + +#if OS_TASK_NAME_EN > 0u +INT8U OSTaskNameGet (INT8U prio, + INT8U **pname, + INT8U *perr); + +void OSTaskNameSet (INT8U prio, + INT8U *pname, + INT8U *perr); +#endif + +#if OS_TASK_SUSPEND_EN > 0u +INT8U OSTaskResume (INT8U prio); +INT8U OSTaskSuspend (INT8U prio); +#endif + +#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) +INT8U OSTaskStkChk (INT8U prio, + OS_STK_DATA *p_stk_data); +#endif + +#if OS_TASK_QUERY_EN > 0u +INT8U OSTaskQuery (INT8U prio, + OS_TCB *p_task_data); +#endif + + + +#if OS_TASK_REG_TBL_SIZE > 0u +INT32U OSTaskRegGet (INT8U prio, + INT8U id, + INT8U *perr); + +void OSTaskRegSet (INT8U prio, + INT8U id, + INT32U value, + INT8U *perr); +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* TIME MANAGEMENT +********************************************************************************************************* +*/ + +void OSTimeDly (INT32U ticks); + +#if OS_TIME_DLY_HMSM_EN > 0u +INT8U OSTimeDlyHMSM (INT8U hours, + INT8U minutes, + INT8U seconds, + INT16U ms); +#endif + +#if OS_TIME_DLY_RESUME_EN > 0u +INT8U OSTimeDlyResume (INT8U prio); +#endif + +#if OS_TIME_GET_SET_EN > 0u +INT32U OSTimeGet (void); +void OSTimeSet (INT32U ticks); +#endif + +void OSTimeTick (void); + +/* +********************************************************************************************************* +* TIMER MANAGEMENT +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +OS_TMR *OSTmrCreate (INT32U dly, + INT32U period, + INT8U opt, + OS_TMR_CALLBACK callback, + void *callback_arg, + INT8U *pname, + INT8U *perr); + +BOOLEAN OSTmrDel (OS_TMR *ptmr, + INT8U *perr); + +#if OS_TMR_CFG_NAME_EN > 0u +INT8U OSTmrNameGet (OS_TMR *ptmr, + INT8U **pdest, + INT8U *perr); +#endif +INT32U OSTmrRemainGet (OS_TMR *ptmr, + INT8U *perr); + +INT8U OSTmrStateGet (OS_TMR *ptmr, + INT8U *perr); + +BOOLEAN OSTmrStart (OS_TMR *ptmr, + INT8U *perr); + +BOOLEAN OSTmrStop (OS_TMR *ptmr, + INT8U opt, + void *callback_arg, + INT8U *perr); + +INT8U OSTmrSignal (void); +#endif + +/* +********************************************************************************************************* +* MISCELLANEOUS +********************************************************************************************************* +*/ + +void OSInit (void); + +void OSIntEnter (void); +void OSIntExit (void); + +#ifdef OS_SAFETY_CRITICAL_IEC61508 +void OSSafetyCriticalStart (void); +#endif + +#if OS_SCHED_LOCK_EN > 0u +void OSSchedLock (void); +void OSSchedUnlock (void); +#endif + +void OSStart (void); + +void OSStatInit (void); + +INT16U OSVersion (void); + +/*$PAGE*/ +/* +********************************************************************************************************* +* INTERNAL FUNCTION PROTOTYPES +* (Your application MUST NOT call these functions) +********************************************************************************************************* +*/ + +#if OS_TASK_DEL_EN > 0u +void OS_Dummy (void); +#endif + +#if (OS_EVENT_EN) +INT8U OS_EventTaskRdy (OS_EVENT *pevent, + void *pmsg, + INT8U msk, + INT8U pend_stat); + +void OS_EventTaskWait (OS_EVENT *pevent); + +void OS_EventTaskRemove (OS_TCB *ptcb, + OS_EVENT *pevent); + +#if (OS_EVENT_MULTI_EN > 0u) +void OS_EventTaskWaitMulti (OS_EVENT **pevents_wait); + +void OS_EventTaskRemoveMulti (OS_TCB *ptcb, + OS_EVENT **pevents_multi); +#endif + +void OS_EventWaitListInit (OS_EVENT *pevent); +#endif + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +void OS_FlagInit (void); +void OS_FlagUnlink (OS_FLAG_NODE *pnode); +#endif + +void OS_MemClr (INT8U *pdest, + INT16U size); + +void OS_MemCopy (INT8U *pdest, + INT8U *psrc, + INT16U size); + +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +void OS_MemInit (void); +#endif + +#if OS_Q_EN > 0u +void OS_QInit (void); +#endif + +void OS_Sched (void); + +#if (OS_EVENT_NAME_EN > 0u) || (OS_FLAG_NAME_EN > 0u) || (OS_MEM_NAME_EN > 0u) || (OS_TASK_NAME_EN > 0u) +INT8U OS_StrLen (INT8U *psrc); +#endif + +void OS_TaskIdle (void *p_arg); + +void OS_TaskReturn (void); + +#if OS_TASK_STAT_EN > 0u +void OS_TaskStat (void *p_arg); +#endif + +#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) +void OS_TaskStkClr (OS_STK *pbos, + INT32U size, + INT16U opt); +#endif + +#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) +void OS_TaskStatStkChk (void); +#endif + +INT8U OS_TCBInit (INT8U prio, + OS_STK *ptos, + OS_STK *pbos, + INT16U id, + INT32U stk_size, + void *pext, + INT16U opt); + +#if OS_TMR_EN > 0u +void OSTmr_Init (void); +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +* (Target Specific Functions) +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void); +#endif + +void OSInitHookBegin (void); +void OSInitHookEnd (void); + +void OSTaskCreateHook (OS_TCB *ptcb); +void OSTaskDelHook (OS_TCB *ptcb); + +void OSTaskIdleHook (void); + +void OSTaskReturnHook (OS_TCB *ptcb); + +void OSTaskStatHook (void); +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT16U opt); + +#if OS_TASK_SW_HOOK_EN > 0u +void OSTaskSwHook (void); +#endif + +void OSTCBInitHook (OS_TCB *ptcb); + +#if OS_TIME_TICK_HOOK_EN > 0u +void OSTimeTickHook (void); +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +* (Application Specific Functions) +********************************************************************************************************* +*/ + +#if OS_APP_HOOKS_EN > 0u +void App_TaskCreateHook (OS_TCB *ptcb); +void App_TaskDelHook (OS_TCB *ptcb); +void App_TaskIdleHook (void); + +void App_TaskReturnHook (OS_TCB *ptcb); + +void App_TaskStatHook (void); + +#if OS_TASK_SW_HOOK_EN > 0u +void App_TaskSwHook (void); +#endif + +void App_TCBInitHook (OS_TCB *ptcb); + +#if OS_TIME_TICK_HOOK_EN > 0u +void App_TimeTickHook (void); +#endif +#endif + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +* +* IMPORTANT: These prototypes MUST be placed in OS_CPU.H +********************************************************************************************************* +*/ + +#if 0 +void OSStartHighRdy (void); +void OSIntCtxSw (void); +void OSCtxSw (void); +#endif + +/*$PAGE*/ +/* +********************************************************************************************************* +* LOOK FOR MISSING #define CONSTANTS +* +* This section is used to generate ERROR messages at compile time if certain #define constants are +* MISSING in OS_CFG.H. This allows you to quickly determine the source of the error. +* +* You SHOULD NOT change this section UNLESS you would like to add more comments as to the source of the +* compile time error. +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* EVENT FLAGS +********************************************************************************************************* +*/ + +#ifndef OS_FLAG_EN +#error "OS_CFG.H, Missing OS_FLAG_EN: Enable (1) or Disable (0) code generation for Event Flags" +#else + #ifndef OS_MAX_FLAGS + #error "OS_CFG.H, Missing OS_MAX_FLAGS: Max. number of Event Flag Groups in your application" + #else + #if OS_MAX_FLAGS > 65500u + #error "OS_CFG.H, OS_MAX_FLAGS must be <= 65500" + #endif + #endif + + #ifndef OS_FLAGS_NBITS + #error "OS_CFG.H, Missing OS_FLAGS_NBITS: Determine #bits used for event flags, MUST be either 8, 16 or 32" + #endif + + #ifndef OS_FLAG_WAIT_CLR_EN + #error "OS_CFG.H, Missing OS_FLAG_WAIT_CLR_EN: Include code for Wait on Clear EVENT FLAGS" + #endif + + #ifndef OS_FLAG_ACCEPT_EN + #error "OS_CFG.H, Missing OS_FLAG_ACCEPT_EN: Include code for OSFlagAccept()" + #endif + + #ifndef OS_FLAG_DEL_EN + #error "OS_CFG.H, Missing OS_FLAG_DEL_EN: Include code for OSFlagDel()" + #endif + + #ifndef OS_FLAG_NAME_EN + #error "OS_CFG.H, Missing OS_FLAG_NAME_EN: Enable flag group names" + #endif + + #ifndef OS_FLAG_QUERY_EN + #error "OS_CFG.H, Missing OS_FLAG_QUERY_EN: Include code for OSFlagQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* MESSAGE MAILBOXES +********************************************************************************************************* +*/ + +#ifndef OS_MBOX_EN +#error "OS_CFG.H, Missing OS_MBOX_EN: Enable (1) or Disable (0) code generation for MAILBOXES" +#else + #ifndef OS_MBOX_ACCEPT_EN + #error "OS_CFG.H, Missing OS_MBOX_ACCEPT_EN: Include code for OSMboxAccept()" + #endif + + #ifndef OS_MBOX_DEL_EN + #error "OS_CFG.H, Missing OS_MBOX_DEL_EN: Include code for OSMboxDel()" + #endif + + #ifndef OS_MBOX_PEND_ABORT_EN + #error "OS_CFG.H, Missing OS_MBOX_PEND_ABORT_EN: Include code for OSMboxPendAbort()" + #endif + + #ifndef OS_MBOX_POST_EN + #error "OS_CFG.H, Missing OS_MBOX_POST_EN: Include code for OSMboxPost()" + #endif + + #ifndef OS_MBOX_POST_OPT_EN + #error "OS_CFG.H, Missing OS_MBOX_POST_OPT_EN: Include code for OSMboxPostOpt()" + #endif + + #ifndef OS_MBOX_QUERY_EN + #error "OS_CFG.H, Missing OS_MBOX_QUERY_EN: Include code for OSMboxQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* MEMORY MANAGEMENT +********************************************************************************************************* +*/ + +#ifndef OS_MEM_EN +#error "OS_CFG.H, Missing OS_MEM_EN: Enable (1) or Disable (0) code generation for MEMORY MANAGER" +#else + #ifndef OS_MAX_MEM_PART + #error "OS_CFG.H, Missing OS_MAX_MEM_PART: Max. number of memory partitions" + #else + #if OS_MAX_MEM_PART > 65500u + #error "OS_CFG.H, OS_MAX_MEM_PART must be <= 65500" + #endif + #endif + + #ifndef OS_MEM_NAME_EN + #error "OS_CFG.H, Missing OS_MEM_NAME_EN: Enable memory partition names" + #endif + + #ifndef OS_MEM_QUERY_EN + #error "OS_CFG.H, Missing OS_MEM_QUERY_EN: Include code for OSMemQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* MUTUAL EXCLUSION SEMAPHORES +********************************************************************************************************* +*/ + +#ifndef OS_MUTEX_EN +#error "OS_CFG.H, Missing OS_MUTEX_EN: Enable (1) or Disable (0) code generation for MUTEX" +#else + #ifndef OS_MUTEX_ACCEPT_EN + #error "OS_CFG.H, Missing OS_MUTEX_ACCEPT_EN: Include code for OSMutexAccept()" + #endif + + #ifndef OS_MUTEX_DEL_EN + #error "OS_CFG.H, Missing OS_MUTEX_DEL_EN: Include code for OSMutexDel()" + #endif + + #ifndef OS_MUTEX_QUERY_EN + #error "OS_CFG.H, Missing OS_MUTEX_QUERY_EN: Include code for OSMutexQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* MESSAGE QUEUES +********************************************************************************************************* +*/ + +#ifndef OS_Q_EN +#error "OS_CFG.H, Missing OS_Q_EN: Enable (1) or Disable (0) code generation for QUEUES" +#else + #ifndef OS_MAX_QS + #error "OS_CFG.H, Missing OS_MAX_QS: Max. number of queue control blocks" + #else + #if OS_MAX_QS > 65500u + #error "OS_CFG.H, OS_MAX_QS must be <= 65500" + #endif + #endif + + #ifndef OS_Q_ACCEPT_EN + #error "OS_CFG.H, Missing OS_Q_ACCEPT_EN: Include code for OSQAccept()" + #endif + + #ifndef OS_Q_DEL_EN + #error "OS_CFG.H, Missing OS_Q_DEL_EN: Include code for OSQDel()" + #endif + + #ifndef OS_Q_FLUSH_EN + #error "OS_CFG.H, Missing OS_Q_FLUSH_EN: Include code for OSQFlush()" + #endif + + #ifndef OS_Q_PEND_ABORT_EN + #error "OS_CFG.H, Missing OS_Q_PEND_ABORT_EN: Include code for OSQPendAbort()" + #endif + + #ifndef OS_Q_POST_EN + #error "OS_CFG.H, Missing OS_Q_POST_EN: Include code for OSQPost()" + #endif + + #ifndef OS_Q_POST_FRONT_EN + #error "OS_CFG.H, Missing OS_Q_POST_FRONT_EN: Include code for OSQPostFront()" + #endif + + #ifndef OS_Q_POST_OPT_EN + #error "OS_CFG.H, Missing OS_Q_POST_OPT_EN: Include code for OSQPostOpt()" + #endif + + #ifndef OS_Q_QUERY_EN + #error "OS_CFG.H, Missing OS_Q_QUERY_EN: Include code for OSQQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* SEMAPHORES +********************************************************************************************************* +*/ + +#ifndef OS_SEM_EN +#error "OS_CFG.H, Missing OS_SEM_EN: Enable (1) or Disable (0) code generation for SEMAPHORES" +#else + #ifndef OS_SEM_ACCEPT_EN + #error "OS_CFG.H, Missing OS_SEM_ACCEPT_EN: Include code for OSSemAccept()" + #endif + + #ifndef OS_SEM_DEL_EN + #error "OS_CFG.H, Missing OS_SEM_DEL_EN: Include code for OSSemDel()" + #endif + + #ifndef OS_SEM_PEND_ABORT_EN + #error "OS_CFG.H, Missing OS_SEM_PEND_ABORT_EN: Include code for OSSemPendAbort()" + #endif + + #ifndef OS_SEM_QUERY_EN + #error "OS_CFG.H, Missing OS_SEM_QUERY_EN: Include code for OSSemQuery()" + #endif + + #ifndef OS_SEM_SET_EN + #error "OS_CFG.H, Missing OS_SEM_SET_EN: Include code for OSSemSet()" + #endif +#endif + +/* +********************************************************************************************************* +* TASK MANAGEMENT +********************************************************************************************************* +*/ + +#ifndef OS_MAX_TASKS +#error "OS_CFG.H, Missing OS_MAX_TASKS: Max. number of tasks in your application" +#else + #if OS_MAX_TASKS < 2u + #error "OS_CFG.H, OS_MAX_TASKS must be >= 2" + #endif + + #if OS_MAX_TASKS > ((OS_LOWEST_PRIO - OS_N_SYS_TASKS) + 1u) + #error "OS_CFG.H, OS_MAX_TASKS must be <= OS_LOWEST_PRIO - OS_N_SYS_TASKS + 1" + #endif + +#endif + +#if OS_LOWEST_PRIO > 254u +#error "OS_CFG.H, OS_LOWEST_PRIO must be <= 254 in V2.8x and higher" +#endif + +#ifndef OS_TASK_IDLE_STK_SIZE +#error "OS_CFG.H, Missing OS_TASK_IDLE_STK_SIZE: Idle task stack size" +#endif + +#ifndef OS_TASK_STAT_EN +#error "OS_CFG.H, Missing OS_TASK_STAT_EN: Enable (1) or Disable(0) the statistics task" +#endif + +#ifndef OS_TASK_STAT_STK_SIZE +#error "OS_CFG.H, Missing OS_TASK_STAT_STK_SIZE: Statistics task stack size" +#endif + +#ifndef OS_TASK_STAT_STK_CHK_EN +#error "OS_CFG.H, Missing OS_TASK_STAT_STK_CHK_EN: Check task stacks from statistics task" +#endif + +#ifndef OS_TASK_CHANGE_PRIO_EN +#error "OS_CFG.H, Missing OS_TASK_CHANGE_PRIO_EN: Include code for OSTaskChangePrio()" +#endif + +#ifndef OS_TASK_CREATE_EN +#error "OS_CFG.H, Missing OS_TASK_CREATE_EN: Include code for OSTaskCreate()" +#endif + +#ifndef OS_TASK_CREATE_EXT_EN +#error "OS_CFG.H, Missing OS_TASK_CREATE_EXT_EN: Include code for OSTaskCreateExt()" +#endif + +#ifndef OS_TASK_DEL_EN +#error "OS_CFG.H, Missing OS_TASK_DEL_EN: Include code for OSTaskDel()" +#endif + +#ifndef OS_TASK_NAME_EN +#error "OS_CFG.H, Missing OS_TASK_NAME_EN: Enable task names" +#endif + +#ifndef OS_TASK_SUSPEND_EN +#error "OS_CFG.H, Missing OS_TASK_SUSPEND_EN: Include code for OSTaskSuspend() and OSTaskResume()" +#endif + +#ifndef OS_TASK_QUERY_EN +#error "OS_CFG.H, Missing OS_TASK_QUERY_EN: Include code for OSTaskQuery()" +#endif + +#ifndef OS_TASK_REG_TBL_SIZE +#error "OS_CFG.H, Missing OS_TASK_REG_TBL_SIZE: Include code for task specific registers" +#else + #if OS_TASK_REG_TBL_SIZE > 255u + #error "OS_CFG.H, OS_TASK_REG_TBL_SIZE must be <= 255" + #endif +#endif + +/* +********************************************************************************************************* +* TIME MANAGEMENT +********************************************************************************************************* +*/ + +#ifndef OS_TICKS_PER_SEC +#error "OS_CFG.H, Missing OS_TICKS_PER_SEC: Sets the number of ticks in one second" +#endif + +#ifndef OS_TIME_DLY_HMSM_EN +#error "OS_CFG.H, Missing OS_TIME_DLY_HMSM_EN: Include code for OSTimeDlyHMSM()" +#endif + +#ifndef OS_TIME_DLY_RESUME_EN +#error "OS_CFG.H, Missing OS_TIME_DLY_RESUME_EN: Include code for OSTimeDlyResume()" +#endif + +#ifndef OS_TIME_GET_SET_EN +#error "OS_CFG.H, Missing OS_TIME_GET_SET_EN: Include code for OSTimeGet() and OSTimeSet()" +#endif + +/* +********************************************************************************************************* +* TIMER MANAGEMENT +********************************************************************************************************* +*/ + +#ifndef OS_TMR_EN +#error "OS_CFG.H, Missing OS_TMR_EN: When (1) enables code generation for Timer Management" +#elif OS_TMR_EN > 0u + #if OS_SEM_EN == 0u + #error "OS_CFG.H, Semaphore management is required (set OS_SEM_EN to 1) when enabling Timer Management." + #error " Timer management require TWO semaphores." + #endif + + #ifndef OS_TMR_CFG_MAX + #error "OS_CFG.H, Missing OS_TMR_CFG_MAX: Determines the total number of timers in an application (2 .. 65500)" + #else + #if OS_TMR_CFG_MAX < 2u + #error "OS_CFG.H, OS_TMR_CFG_MAX should be between 2 and 65500" + #endif + + #if OS_TMR_CFG_MAX > 65500u + #error "OS_CFG.H, OS_TMR_CFG_MAX should be between 2 and 65500" + #endif + #endif + + #ifndef OS_TMR_CFG_WHEEL_SIZE + #error "OS_CFG.H, Missing OS_TMR_CFG_WHEEL_SIZE: Sets the size of the timer wheel (1 .. 1023)" + #else + #if OS_TMR_CFG_WHEEL_SIZE < 2u + #error "OS_CFG.H, OS_TMR_CFG_WHEEL_SIZE should be between 2 and 1024" + #endif + + #if OS_TMR_CFG_WHEEL_SIZE > 1024u + #error "OS_CFG.H, OS_TMR_CFG_WHEEL_SIZE should be between 2 and 1024" + #endif + #endif + + #ifndef OS_TMR_CFG_NAME_EN + #error "OS_CFG.H, Missing OS_TMR_CFG_NAME_EN: Enable Timer names" + #endif + + #ifndef OS_TMR_CFG_TICKS_PER_SEC + #error "OS_CFG.H, Missing OS_TMR_CFG_TICKS_PER_SEC: Determines the rate at which tiem timer management task will run (Hz)" + #endif + + #ifndef OS_TASK_TMR_STK_SIZE + #error "OS_CFG.H, Missing OS_TASK_TMR_STK_SIZE: Determines the size of the Timer Task's stack" + #endif +#endif + + +/* +********************************************************************************************************* +* MISCELLANEOUS +********************************************************************************************************* +*/ + +#ifndef OS_ARG_CHK_EN +#error "OS_CFG.H, Missing OS_ARG_CHK_EN: Enable (1) or Disable (0) argument checking" +#endif + + +#ifndef OS_CPU_HOOKS_EN +#error "OS_CFG.H, Missing OS_CPU_HOOKS_EN: uC/OS-II hooks are found in the processor port files when 1" +#endif + + +#ifndef OS_APP_HOOKS_EN +#error "OS_CFG.H, Missing OS_APP_HOOKS_EN: Application-defined hooks are called from the uC/OS-II hooks" +#endif + + +#ifndef OS_DEBUG_EN +#error "OS_CFG.H, Missing OS_DEBUG_EN: Allows you to include variables for debugging or not" +#endif + + +#ifndef OS_LOWEST_PRIO +#error "OS_CFG.H, Missing OS_LOWEST_PRIO: Defines the lowest priority that can be assigned" +#endif + + +#ifndef OS_MAX_EVENTS +#error "OS_CFG.H, Missing OS_MAX_EVENTS: Max. number of event control blocks in your application" +#else + #if OS_MAX_EVENTS > 65500u + #error "OS_CFG.H, OS_MAX_EVENTS must be <= 65500" + #endif +#endif + + +#ifndef OS_SCHED_LOCK_EN +#error "OS_CFG.H, Missing OS_SCHED_LOCK_EN: Include code for OSSchedLock() and OSSchedUnlock()" +#endif + + +#ifndef OS_EVENT_MULTI_EN +#error "OS_CFG.H, Missing OS_EVENT_MULTI_EN: Include code for OSEventPendMulti()" +#endif + + +#ifndef OS_TASK_PROFILE_EN +#error "OS_CFG.H, Missing OS_TASK_PROFILE_EN: Include data structure for run-time task profiling" +#endif + + +#ifndef OS_TASK_SW_HOOK_EN +#error "OS_CFG.H, Missing OS_TASK_SW_HOOK_EN: Allows you to include the code for OSTaskSwHook() or not" +#endif + + +#ifndef OS_TICK_STEP_EN +#error "OS_CFG.H, Missing OS_TICK_STEP_EN: Allows to 'step' one tick at a time with uC/OS-View" +#endif + + +#ifndef OS_TIME_TICK_HOOK_EN +#error "OS_CFG.H, Missing OS_TIME_TICK_HOOK_EN: Allows you to include the code for OSTimeTickHook() or not" +#endif + +/* +********************************************************************************************************* +* SAFETY CRITICAL USE +********************************************************************************************************* +*/ + +#ifdef SAFETY_CRITICAL_RELEASE + +#if OS_ARG_CHK_EN < 1u +#error "OS_CFG.H, OS_ARG_CHK_EN must be enabled for safety-critical release code" +#endif + +#if OS_APP_HOOKS_EN > 0u +#error "OS_CFG.H, OS_APP_HOOKS_EN must be disabled for safety-critical release code" +#endif + +#if OS_DEBUG_EN > 0u +#error "OS_CFG.H, OS_DEBUG_EN must be disabled for safety-critical release code" +#endif + +#ifdef CANTATA +#error "OS_CFG.H, CANTATA must be disabled for safety-critical release code" +#endif + +#ifdef OS_SCHED_LOCK_EN +#error "OS_CFG.H, OS_SCHED_LOCK_EN must be disabled for safety-critical release code" +#endif + +#ifdef VSC_VALIDATION_MODE +#error "OS_CFG.H, VSC_VALIDATION_MODE must be disabled for safety-critical release code" +#endif + +#if OS_TASK_STAT_EN > 0u +#error "OS_CFG.H, OS_TASK_STAT_EN must be disabled for safety-critical release code" +#endif + +#if OS_TICK_STEP_EN > 0u +#error "OS_CFG.H, OS_TICK_STEP_EN must be disabled for safety-critical release code" +#endif + +#if OS_FLAG_EN > 0u + #if OS_FLAG_DEL_EN > 0 + #error "OS_CFG.H, OS_FLAG_DEL_EN must be disabled for safety-critical release code" + #endif +#endif + +#if OS_MBOX_EN > 0u + #if OS_MBOX_DEL_EN > 0u + #error "OS_CFG.H, OS_MBOX_DEL_EN must be disabled for safety-critical release code" + #endif +#endif + +#if OS_MUTEX_EN > 0u + #if OS_MUTEX_DEL_EN > 0u + #error "OS_CFG.H, OS_MUTEX_DEL_EN must be disabled for safety-critical release code" + #endif +#endif + +#if OS_Q_EN > 0u + #if OS_Q_DEL_EN > 0u + #error "OS_CFG.H, OS_Q_DEL_EN must be disabled for safety-critical release code" + #endif +#endif + +#if OS_SEM_EN > 0u + #if OS_SEM_DEL_EN > 0u + #error "OS_CFG.H, OS_SEM_DEL_EN must be disabled for safety-critical release code" + #endif +#endif + +#if OS_TASK_EN > 0u + #if OS_TASK_DEL_EN > 0u + #error "OS_CFG.H, OS_TASK_DEL_EN must be disabled for safety-critical release code" + #endif +#endif + +#if OS_CRITICAL_METHOD != 3u +#error "OS_CPU.H, OS_CRITICAL_METHOD must be type 3 for safety-critical release code" +#endif + +#endif /* ------------------------ SAFETY_CRITICAL_RELEASE ------------------------ */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/UCOSII/PORT/os_cpu.h b/UCOSII/PORT/os_cpu.h new file mode 100644 index 0000000..ba13d87 --- /dev/null +++ b/UCOSII/PORT/os_cpu.h @@ -0,0 +1,89 @@ +/************************ (C) COPYLEFT 2010 Leafgrass ************************* + +* File Name : os_cpu_c.c +* Author : Librae +* Date : 06/10/2010 +* Description : COS-IISTM32ϵֲCԲ֣ +* ջʼ͹Ӻ + +******************************************************************************/ + +#ifndef __OS_CPU_H__ +#define __OS_CPU_H__ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/****************************************************************************** +* ޹ص +******************************************************************************/ + +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*/ + +//STM3232λλ,OS_STKOS_CPU_SRӦΪ32λ +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 +******************************************************************************* +*/ + + +//ջ. +//CM3,ջɸߵַ͵ַ,OS_STK_GROWTHΪ1 +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on ARM */ +//л,ɻʵ. +#define OS_TASK_SW() OSCtxSw() + +/* +******************************************************************************* +* PROTOTYPES +* (see OS_CPU_A.ASM) +******************************************************************************* +*/ +//OS_CRITICAL_METHOD = 1 :ֱʹôĿжָʵֺ +//OS_CRITICAL_METHOD = 2 :öջͻָCPU״̬ +//OS_CRITICAL_METHOD = 3 :ñչܻó״̬֣ھֲcpu_sr + +#define OS_CRITICAL_METHOD 3 //ٽεķ + +#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 ************************/ diff --git a/UCOSII/PORT/os_cpu_a.asm b/UCOSII/PORT/os_cpu_a.asm new file mode 100644 index 0000000..95eb52d --- /dev/null +++ b/UCOSII/PORT/os_cpu_a.asm @@ -0,0 +1,197 @@ +;/*********************** (C) COPYRIGHT 2010 Libraworks ************************* +;* File Name : os_cpu_a.asm +;* Author : Librae +;* Version : V1.0 +;* Date : 06/10/2010 +;* Description : 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 ; жϿƼĴ +NVIC_SYSPRI2 EQU 0xE000ED20 ; ϵͳȼĴ(2) +NVIC_PENDSV_PRI EQU 0xFFFF0000 ; PendSVжϺϵͳж + ; (Ϊͣ0xff). +NVIC_PENDSVSET EQU 0x10000000 ; жϵֵ. + + + 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 ;ȡPRIMASKR0,R0Ϊֵ + CPSID I ;PRIMASK=1,ж(NMIӲFAULTӦ) + BX LR ; + +OS_CPU_SR_Restore + MSR PRIMASK, R0 ;ȡR0PRIMASK,R0Ϊ + BX LR ; + + +;/************************************************************************************** +;* : OSStartHighRdy +;* +;* : ʹõеһ +;* +;* : None +;* +;* ֵ: 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] + + ;лȼ + 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 + +;/************************************************************************************** +;* : OSCtxSw +;* +;* : л +;* +;* : None +;* +;* ֵ: None +;***************************************************************************************/ + +OSCtxSw + PUSH {R4, R5} + LDR R4, =NVIC_INT_CTRL ;PendSV쳣 (causes context switch) + LDR R5, =NVIC_PENDSVSET + STR R5, [R4] + POP {R4, R5} + BX LR + +;/************************************************************************************** +;* : OSIntCtxSw +;* +;* : жϼл +;* +;* : None +;* +;* ֵ: None +;***************************************************************************************/ + +OSIntCtxSw + PUSH {R4, R5} + LDR R4, =NVIC_INT_CTRL ;PendSV쳣 (causes context switch) + LDR R5, =NVIC_PENDSVSET + STR R5, [R4] + POP {R4, R5} + BX LR + NOP + +;/************************************************************************************** +;* : OSPendSV +;* +;* : OSPendSV is used to cause a context switch. +;* +;* : None +;* +;* ֵ: None +;***************************************************************************************/ + +PendSV_Handler + CPSID I ; Prevent interruption during context switch + MRS R0, PSP ; PSP is process stack pointer PSPջ,ԺԱĴ,οCM3Ȩе˫ջ-ײע + 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 \ No newline at end of file diff --git a/UCOSII/PORT/os_cpu_c.c b/UCOSII/PORT/os_cpu_c.c new file mode 100644 index 0000000..a813406 --- /dev/null +++ b/UCOSII/PORT/os_cpu_c.c @@ -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 -----------------*/ diff --git a/UCOSII/PORT/os_dbg.c b/UCOSII/PORT/os_dbg.c new file mode 100644 index 0000000..dba703c --- /dev/null +++ b/UCOSII/PORT/os_dbg.c @@ -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 + +#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 diff --git a/UCOSII/PORT/os_dbg_r.c b/UCOSII/PORT/os_dbg_r.c new file mode 100644 index 0000000..3ca67ef --- /dev/null +++ b/UCOSII/PORT/os_dbg_r.c @@ -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 Micrim 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 + +/* +********************************************************************************************************* +* 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 + diff --git a/USER/4StepperMotorsDriveBySTM32F103x.uvguix.Seven b/USER/4StepperMotorsDriveBySTM32F103x.uvguix.Seven index 1b75dfc..254adab 100644 --- a/USER/4StepperMotorsDriveBySTM32F103x.uvguix.Seven +++ b/USER/4StepperMotorsDriveBySTM32F103x.uvguix.Seven @@ -75,8 +75,8 @@ 2 3 - -1 - -1 + -32000 + -32000 -1 @@ -92,8 +92,8 @@ 0 - 502 - 01000000040000000100000001000000010000000100000000000000020000000000000001000000010000000000000028000000280000000100000003000000020000000100000057473A5CC7B0BAA3D6D0D6C7CAB5CFB05C666F72204769746875625C34537465707065724D6F746F72734472697665427953544D333246313033785C48415244574152455C49726F6E48616E645C49726F6E48616E642E63000000000A49726F6E48616E642E6300000000F0A0A100FFFFFFFF5B473A5CC7B0BAA3D6D0D6C7CAB5CFB05C666F72204769746875625C34537465707065724D6F746F72734472697665427953544D333246313033785C48415244574152455C4D4F544F525F4354524C5C6D6F746F725F6374726C2E63000000000C6D6F746F725F6374726C2E6300000000BECEA100FFFFFFFF46473A5CC7B0BAA3D6D0D6C7CAB5CFB05C666F72204769746875625C34537465707065724D6F746F72734472697665427953544D333246313033785C555345525C6D61696E2E6300000000066D61696E2E6300000000FFDC7800FFFFFFFF0100000010000000C5D4F200FFDC7800BECEA100F0A0A100BCA8E1009CC1B600F7B88600D9ADC200A5C2D700B3A6BE00EAD6A300F6FA7D00B5E99D005FC3CF00C1838300CACAD500010000000000000002000000290100006600000056050000ED020000 + 60 + 010000000400000001000000010000000100000001000000000000000200000000000000010000000100000000000000280000002800000000000000 @@ -116,7 +116,7 @@ 16 - AE00000066000000F1030000CD000000 + C40100006301000007050000CA010000 @@ -1281,14 +1281,14 @@ 2619 - 000000000B000000000000000020000000000000FFFFFFFFFFFFFFFFAE000000B6000000F1030000BA000000000000000100000004000000010000000000000000000000FFFFFFFF06000000CB00000057010000CC000000F08B00005A01000079070000FFFF02000B004354616262656450616E650020000000000000AE00000066000000F1030000CD000000AE0000004F000000F1030000B60000000000000040280046060000000B446973617373656D626C7900000000CB00000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A6572000000005701000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A657200000000CC00000001000000FFFFFFFFFFFFFFFF0E4C6F67696320416E616C797A657200000000F08B000001000000FFFFFFFFFFFFFFFF0D436F646520436F766572616765000000005A01000001000000FFFFFFFFFFFFFFFF11496E737472756374696F6E205472616365000000007907000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFCB00000001000000FFFFFFFFCB000000000000000040000000000000FFFFFFFFFFFFFFFF430300004F0000004703000086010000000000000200000004000000010000000000000000000000FFFFFFFF17000000E2050000CA0900002D8C00002E8C00002F8C0000308C0000318C0000328C0000338C0000348C0000358C0000368C0000378C0000388C0000398C00003A8C00003B8C00003C8C00003D8C00003E8C00003F8C0000408C0000418C0000018000400000000000004703000066000000F10300009D010000470300004F000000F1030000860100000000000040410046170000000753796D626F6C7300000000E205000001000000FFFFFFFFFFFFFFFF0A5472616365204461746100000000CA09000001000000FFFFFFFFFFFFFFFF00000000002D8C000001000000FFFFFFFFFFFFFFFF00000000002E8C000001000000FFFFFFFFFFFFFFFF00000000002F8C000001000000FFFFFFFFFFFFFFFF0000000000308C000001000000FFFFFFFFFFFFFFFF0000000000318C000001000000FFFFFFFFFFFFFFFF0000000000328C000001000000FFFFFFFFFFFFFFFF0000000000338C000001000000FFFFFFFFFFFFFFFF0000000000348C000001000000FFFFFFFFFFFFFFFF0000000000358C000001000000FFFFFFFFFFFFFFFF0000000000368C000001000000FFFFFFFFFFFFFFFF0000000000378C000001000000FFFFFFFFFFFFFFFF0000000000388C000001000000FFFFFFFFFFFFFFFF0000000000398C000001000000FFFFFFFFFFFFFFFF00000000003A8C000001000000FFFFFFFFFFFFFFFF00000000003B8C000001000000FFFFFFFFFFFFFFFF00000000003C8C000001000000FFFFFFFFFFFFFFFF00000000003D8C000001000000FFFFFFFFFFFFFFFF00000000003E8C000001000000FFFFFFFFFFFFFFFF00000000003F8C000001000000FFFFFFFFFFFFFFFF0000000000408C000001000000FFFFFFFFFFFFFFFF0000000000418C000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFE205000001000000FFFFFFFFE2050000000000000080000000000000FFFFFFFFFFFFFFFF0000000072010000F10300007601000000000000010000000400000001000000000000000000000000000000000000000000000001000000C6000000FFFFFFFF0E0000008F070000930700009407000095070000960700009007000091070000B5010000B8010000B9050000BA050000BB050000BC050000CB09000001800080000000000000000000008D010000F1030000080200000000000076010000F1030000F101000000000000404100460E0000001343616C6C20537461636B202B204C6F63616C73000000008F07000001000000FFFFFFFFFFFFFFFF0755415254202331000000009307000001000000FFFFFFFFFFFFFFFF0755415254202332000000009407000001000000FFFFFFFFFFFFFFFF0755415254202333000000009507000001000000FFFFFFFFFFFFFFFF15446562756720287072696E74662920566965776572000000009607000001000000FFFFFFFFFFFFFFFF0757617463682031000000009007000001000000FFFFFFFFFFFFFFFF0757617463682032000000009107000001000000FFFFFFFFFFFFFFFF10547261636520457863657074696F6E7300000000B501000001000000FFFFFFFFFFFFFFFF0E4576656E7420436F756E7465727300000000B801000001000000FFFFFFFFFFFFFFFF084D656D6F7279203100000000B905000001000000FFFFFFFFFFFFFFFF084D656D6F7279203200000000BA05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203300000000BB05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203400000000BC05000001000000FFFFFFFFFFFFFFFF105472616365204E617669676174696F6E00000000CB09000001000000FFFFFFFFFFFFFFFFFFFFFFFF0000000001000000000000000000000001000000FFFFFFFFF901000076010000FD010000F101000000000000020000000400000000000000000000000000000000000000000000000000000002000000C6000000FFFFFFFF8F07000001000000FFFFFFFF8F07000001000000C6000000000000000080000000000000FFFFFFFFFFFFFFFF29010000C901000056050000CD0100000000000001000000040000000100000090FEFFFF0C010000FFFFFFFF04000000C5000000C7000000B4010000779400000180008000000000000029010000E401000056050000ED02000029010000CD01000056050000D60200000000000040820046040000000C4275696C64204F757470757400000000C500000001000000FFFFFFFFFFFFFFFF0D46696E6420496E2046696C657300000000C700000001000000FFFFFFFFFFFFFFFF0A4572726F72204C69737400000000B401000001000000FFFFFFFFFFFFFFFF0742726F77736572000000007794000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFC500000001000000FFFFFFFFC5000000000000000010000001000000FFFFFFFFFFFFFFFF250100004F00000029010000D6020000010000000200001004000000010000009EFEFFFFE9030000FFFFFFFF05000000ED0300006D000000C3000000C40000007394000001800010000001000000000000006600000025010000ED020000000000004F00000025010000D60200000000000040410056050000000750726F6A65637401000000ED03000001000000FFFFFFFFFFFFFFFF05426F6F6B73010000006D00000001000000FFFFFFFFFFFFFFFF0946756E6374696F6E7301000000C300000001000000FFFFFFFFFFFFFFFF0954656D706C6174657301000000C400000001000000FFFFFFFFFFFFFFFF09526567697374657273000000007394000001000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000001000000FFFFFFFFED03000001000000FFFFFFFFED030000000000000000000000000000 + 000000000B000000000000000020000000000000FFFFFFFFFFFFFFFFAE000000B6000000F1030000BA000000000000000100000004000000010000000000000000000000FFFFFFFF06000000CB00000057010000CC000000F08B00005A01000079070000FFFF02000B004354616262656450616E650020000000000000C40100006301000007050000CA010000AE0000004F000000F1030000B60000000000000040280046060000000B446973617373656D626C7900000000CB00000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A6572000000005701000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A657200000000CC00000001000000FFFFFFFFFFFFFFFF0E4C6F67696320416E616C797A657200000000F08B000001000000FFFFFFFFFFFFFFFF0D436F646520436F766572616765000000005A01000001000000FFFFFFFFFFFFFFFF11496E737472756374696F6E205472616365000000007907000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFCB00000001000000FFFFFFFFCB000000000000000040000000000000FFFFFFFFFFFFFFFF430300004F0000004703000086010000000000000200000004000000010000000000000000000000FFFFFFFF17000000E2050000CA0900002D8C00002E8C00002F8C0000308C0000318C0000328C0000338C0000348C0000358C0000368C0000378C0000388C0000398C00003A8C00003B8C00003C8C00003D8C00003E8C00003F8C0000408C0000418C0000018000400000000000005D04000063010000070500009A020000470300004F000000F1030000860100000000000040410046170000000753796D626F6C7300000000E205000001000000FFFFFFFFFFFFFFFF0A5472616365204461746100000000CA09000001000000FFFFFFFFFFFFFFFF00000000002D8C000001000000FFFFFFFFFFFFFFFF00000000002E8C000001000000FFFFFFFFFFFFFFFF00000000002F8C000001000000FFFFFFFFFFFFFFFF0000000000308C000001000000FFFFFFFFFFFFFFFF0000000000318C000001000000FFFFFFFFFFFFFFFF0000000000328C000001000000FFFFFFFFFFFFFFFF0000000000338C000001000000FFFFFFFFFFFFFFFF0000000000348C000001000000FFFFFFFFFFFFFFFF0000000000358C000001000000FFFFFFFFFFFFFFFF0000000000368C000001000000FFFFFFFFFFFFFFFF0000000000378C000001000000FFFFFFFFFFFFFFFF0000000000388C000001000000FFFFFFFFFFFFFFFF0000000000398C000001000000FFFFFFFFFFFFFFFF00000000003A8C000001000000FFFFFFFFFFFFFFFF00000000003B8C000001000000FFFFFFFFFFFFFFFF00000000003C8C000001000000FFFFFFFFFFFFFFFF00000000003D8C000001000000FFFFFFFFFFFFFFFF00000000003E8C000001000000FFFFFFFFFFFFFFFF00000000003F8C000001000000FFFFFFFFFFFFFFFF0000000000408C000001000000FFFFFFFFFFFFFFFF0000000000418C000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFE205000001000000FFFFFFFFE2050000000000000080000000000000FFFFFFFFFFFFFFFF0000000072010000F10300007601000000000000010000000400000001000000000000000000000000000000000000000000000001000000C6000000FFFFFFFF0E0000008F070000930700009407000095070000960700009007000091070000B5010000B8010000B9050000BA050000BB050000BC050000CB09000001800080000000000000160100008A02000007050000050300000000000076010000F1030000F101000000000000404100460E0000001343616C6C20537461636B202B204C6F63616C73000000008F07000001000000FFFFFFFFFFFFFFFF0755415254202331000000009307000001000000FFFFFFFFFFFFFFFF0755415254202332000000009407000001000000FFFFFFFFFFFFFFFF0755415254202333000000009507000001000000FFFFFFFFFFFFFFFF15446562756720287072696E74662920566965776572000000009607000001000000FFFFFFFFFFFFFFFF0757617463682031000000009007000001000000FFFFFFFFFFFFFFFF0757617463682032000000009107000001000000FFFFFFFFFFFFFFFF10547261636520457863657074696F6E7300000000B501000001000000FFFFFFFFFFFFFFFF0E4576656E7420436F756E7465727300000000B801000001000000FFFFFFFFFFFFFFFF084D656D6F7279203100000000B905000001000000FFFFFFFFFFFFFFFF084D656D6F7279203200000000BA05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203300000000BB05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203400000000BC05000001000000FFFFFFFFFFFFFFFF105472616365204E617669676174696F6E00000000CB09000001000000FFFFFFFFFFFFFFFFFFFFFFFF0000000001000000000000000000000001000000FFFFFFFFF901000076010000FD010000F101000000000000020000000400000000000000000000000000000000000000000000000000000002000000C6000000FFFFFFFF8F07000001000000FFFFFFFF8F07000001000000C6000000000000000080000000000000FFFFFFFFFFFFFFFF29010000C901000056050000CD0100000000000001000000040000000100000090FEFFFF0C010000FFFFFFFF04000000C5000000C7000000B401000077940000018000800000000000003F020000E10200006C060000EA03000029010000CD01000056050000D60200000000000040820046040000000C4275696C64204F757470757400000000C500000001000000FFFFFFFFFFFFFFFF0D46696E6420496E2046696C657300000000C700000001000000FFFFFFFFFFFFFFFF0A4572726F72204C69737400000000B401000001000000FFFFFFFFFFFFFFFF0742726F77736572000000007794000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFC500000001000000FFFFFFFFC5000000000000000010000001000000FFFFFFFFFFFFFFFF250100004F00000029010000D6020000010000000200001004000000010000009EFEFFFFE9030000FFFFFFFF05000000ED0300006D000000C3000000C4000000739400000180001000000100000016010000630100003B020000EA030000000000004F00000025010000D60200000000000040410056050000000750726F6A65637401000000ED03000001000000FFFFFFFFFFFFFFFF05426F6F6B73010000006D00000001000000FFFFFFFFFFFFFFFF0946756E6374696F6E7301000000C300000001000000FFFFFFFFFFFFFFFF0954656D706C6174657301000000C400000001000000FFFFFFFFFFFFFFFF09526567697374657273000000007394000001000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000001000000FFFFFFFFED03000001000000FFFFFFFFED030000000000000000000000000000 59392 File - 2253 - 00200000010000002800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000040004000000000000000000000000000000000100000001000000018022E100000000040005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000000000700000000000000000000000000000000010000000100000001802CE10000000004000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000000000900000000000000000000000000000000010000000100000001807B8A0000000004000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000004000C0000000000000000000000000000000001000000010000000180F4B00000000004000D000000000000000000000000000000000100000001000000018036B10000000004000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF88000000000400460000000000000000000000000000000001000000010000000180FE880000000004004500000000000000000000000000000000010000000100000001800B810000000004001300000000000000000000000000000000010000000100000001800C810000000004001400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F0880000020000000F000000000000000000000000000000000100000001000000FFFF0100120043555646696E64436F6D626F427574746F6EE8030000000000000000000000000000000000000000000000010000000100000096000000020020500000000002333696000000000000001300023336043138303004333630300F5553415254315F52585F434F554E54045445535412E994AEE79B98E79BB8E585B3E58F98E9878F0C6D6F746F72332E4D4F544F780C6D6F746F72322E4D4F544F780C6D6F746F72312E4D4F544F78064D41535445520E67496D6167655F7573725F696D6708444D415F496E697403476169027932034C6364074750494F4C6364054D6F746F72064D6F746F72581154494D5F5365744175746F72656C6F616400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018024E10000000000001100000000000000000000000000000000010000000100000001800A810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018022800000020000001500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000160000000000000000000000000000000001000000010000000180C988000000000400180000000000000000000000000000000001000000010000000180C788000000000000190000000000000000000000000000000001000000010000000180C8880000000000001700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E4C010000020001001A0000000F2650726F6A6563742057696E646F77000000000000000000000000010000000100000000000000000000000100000008002880DD880000000000001A0000000750726F6A656374000000000000000000000000010000000100000000000000000000000100000000002880DC8B0000000000003A00000005426F6F6B73000000000000000000000000010000000100000000000000000000000100000000002880E18B0000000000003B0000000946756E6374696F6E73000000000000000000000000010000000100000000000000000000000100000000002880E28B000000000000400000000954656D706C6174657300000000000000000000000001000000010000000000000000000000010000000000288018890000000000003D0000000E536F757263652042726F777365720000000000000000000000000100000001000000000000000000000001000000000028800000000000000400FFFFFFFF00000000000000000001000000000000000100000000000000000000000100000000002880D988000000000000390000000C4275696C64204F7574707574000000000000000000000000010000000100000000000000000000000100000000002880E38B000000000000410000000B46696E64204F75747075740000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001B000000000000000000000000000000000100000001000000000000000446696C65AC030000 + 2225 + 00200000010000002800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000400020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000040004000000000000000000000000000000000100000001000000018022E100000000040005000000000000000000000000000000000100000001000000018025E10000000004000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000004000700000000000000000000000000000000010000000100000001802CE10000000004000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000004000900000000000000000000000000000000010000000100000001807B8A0000000004000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000004000B000000000000000000000000000000000100000001000000018015B10000000004000C0000000000000000000000000000000001000000010000000180F4B00000000004000D000000000000000000000000000000000100000001000000018036B10000000004000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF88000000000400460000000000000000000000000000000001000000010000000180FE880000000004004500000000000000000000000000000000010000000100000001800B810000000004001300000000000000000000000000000000010000000100000001800C810000000004001400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F0880000020000000F000000000000000000000000000000000100000001000000FFFF0100120043555646696E64436F6D626F427574746F6EE803000000000400000000000000000000000000000000000001000000010000009600000002002050000000000454525545960000000000000011000454525545066B65726E656C043138303004333630300F5553415254315F52585F434F554E54045445535412E994AEE79B98E79BB8E585B3E58F98E9878F0C6D6F746F72332E4D4F544F780C6D6F746F72322E4D4F544F780C6D6F746F72312E4D4F544F78064D41535445520E67496D6167655F7573725F696D6708444D415F496E697403476169027932034C6364074750494F4C63640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018024E10000000000001100000000000000000000000000000000010000000100000001800A810000000004001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018022800000020000001500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000400160000000000000000000000000000000001000000010000000180C988000000000400180000000000000000000000000000000001000000010000000180C788000000000000190000000000000000000000000000000001000000010000000180C8880000000000001700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E4C010000020001001A0000000F2650726F6A6563742057696E646F77000000000000000000000000010000000100000000000000000000000100000008002880DD880000000000001A0000000750726F6A656374000000000000000000000000010000000100000000000000000000000100000000002880DC8B0000000000003A00000005426F6F6B73000000000000000000000000010000000100000000000000000000000100000000002880E18B0000000000003B0000000946756E6374696F6E73000000000000000000000000010000000100000000000000000000000100000000002880E28B000000000000400000000954656D706C6174657300000000000000000000000001000000010000000000000000000000010000000000288018890000000000003D0000000E536F757263652042726F777365720000000000000000000000000100000001000000000000000000000001000000000028800000000000000400FFFFFFFF00000000000000000001000000000000000100000000000000000000000100000000002880D988000000000000390000000C4275696C64204F7574707574000000000000000000000000010000000100000000000000000000000100000000002880E38B000000000000410000000B46696E64204F75747075740000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001B000000000000000000000000000000000100000001000000000000000446696C65AC030000 1423 @@ -1304,7 +1304,7 @@ Build 678 - 00200000010000001000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F0000000000001C0000000000000000000000000000000001000000010000000180D07F0000000000001D000000000000000000000000000000000100000001000000018030800000000000001E00000000000000000000000000000000010000000100000001809E8A0000000000001F0000000000000000000000000000000001000000010000000180D17F0000000004002000000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001804C8A0000000000002100000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001900434D4643546F6F6C426172436F6D626F426F78427574746F6EBA000000000000000000000000000000000000000000000000010000000100000096000000030020500000000008546172676574203196000000000000000100085461726765742031000000000180EB880000000000002200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C07F000000000000230000000000000000000000000000000001000000010000000180B08A000000000400240000000000000000000000000000000001000000010000000180A8010000000000004E00000000000000000000000000000000010000000100000001807202000000000000530000000000000000000000000000000001000000010000000180BE010000000000005000000000000000000000000000000000010000000100000000000000054275696C64CF010000 + 00200000010000001000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F0000000004001C0000000000000000000000000000000001000000010000000180D07F0000000000001D000000000000000000000000000000000100000001000000018030800000000000001E00000000000000000000000000000000010000000100000001809E8A0000000000001F0000000000000000000000000000000001000000010000000180D17F0000000004002000000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001804C8A0000000000002100000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001900434D4643546F6F6C426172436F6D626F426F78427574746F6EBA000000000000000000000000000000000000000000000000010000000100000096000000030020500000000008546172676574203196000000000000000100085461726765742031000000000180EB880000000000002200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C07F000000000000230000000000000000000000000000000001000000010000000180B08A000000000400240000000000000000000000000000000001000000010000000180A8010000000000004E00000000000000000000000000000000010000000100000001807202000000000000530000000000000000000000000000000001000000010000000180BE010000000000005000000000000000000000000000000000010000000100000000000000054275696C64CF010000 583 @@ -1320,7 +1320,7 @@ Debug 2247 - 00200000000000001900FFFF01001100434D4643546F6F6C426172427574746F6ECC880000000000002500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018017800000000000002600000000000000000000000000000000010000000100000001801D800000000000002700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001801A800000000000002800000000000000000000000000000000010000000100000001801B80000000000000290000000000000000000000000000000001000000010000000180E57F0000000000002A00000000000000000000000000000000010000000100000001801C800000000000002B00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018000890000000000002C00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180E48B0000000000002D0000000000000000000000000000000001000000010000000180F07F0000000000002E0000000000000000000000000000000001000000010000000180E8880000000000003700000000000000000000000000000000010000000100000001803B010000000000002F0000000000000000000000000000000001000000010000000180BB8A00000000000030000000000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E0E01000000000000310000000D57617463682057696E646F7773000000000000000000000000010000000100000000000000000000000100000002001380D88B00000000000031000000085761746368202631000000000000000000000000010000000100000000000000000000000100000000001380D98B000000000000310000000857617463682026320000000000000000000000000100000001000000000000000000000001000000000013800F01000000000000320000000E4D656D6F72792057696E646F7773000000000000000000000000010000000100000000000000000000000100000004001380D28B00000000000032000000094D656D6F7279202631000000000000000000000000010000000100000000000000000000000100000000001380D38B00000000000032000000094D656D6F7279202632000000000000000000000000010000000100000000000000000000000100000000001380D48B00000000000032000000094D656D6F7279202633000000000000000000000000010000000100000000000000000000000100000000001380D58B00000000000032000000094D656D6F72792026340000000000000000000000000100000001000000000000000000000001000000000013801001000000000000330000000E53657269616C2057696E646F777300000000000000000000000001000000010000000000000000000000010000000400138093070000000000003300000008554152542023263100000000000000000000000001000000010000000000000000000000010000000000138094070000000000003300000008554152542023263200000000000000000000000001000000010000000000000000000000010000000000138095070000000000003300000008554152542023263300000000000000000000000001000000010000000000000000000000010000000000138096070000000000003300000015446562756720287072696E746629205669657765720000000000000000000000000100000001000000000000000000000001000000000013803C010000000000003400000010416E616C797369732057696E646F7773000000000000000000000000010000000100000000000000000000000100000003001380658A000000000000340000000F264C6F67696320416E616C797A6572000000000000000000000000010000000100000000000000000000000100000000001380DC7F0000000000003E0000001526506572666F726D616E636520416E616C797A6572000000000000000000000000010000000100000000000000000000000100000000001380E788000000000000380000000E26436F646520436F76657261676500000000000000000000000001000000010000000000000000000000010000000000138053010000000000003F0000000D54726163652057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013805401000000000000FFFFFFFF115472616365204D656E7520416E63686F720000000000000000010000000000000001000000000000000000000001000000000013802901000000000000350000001553797374656D205669657765722057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013804B01000000000000FFFFFFFF1453797374656D2056696577657220416E63686F720000000000000000010000000000000001000000000000000000000001000000000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000013800189000000000000360000000F26546F6F6C626F782057696E646F7700000000000000000000000001000000010000000000000000000000010000000300138044C5000000000000FFFFFFFF0E5570646174652057696E646F77730000000000000000010000000000000001000000000000000000000001000000000013800000000000000400FFFFFFFF000000000000000000010000000000000001000000000000000000000001000000000013805B01000000000000FFFFFFFF12546F6F6C626F78204D656E75416E63686F72000000000000000001000000000000000100000000000000000000000100000000000000000005446562756764020000 + 00200000000000001900FFFF01001100434D4643546F6F6C426172427574746F6ECC880000000000002500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018017800000000000002600000000000000000000000000000000010000000100000001801D800000000000002700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001801A800000000000002800000000000000000000000000000000010000000100000001801B80000000000000290000000000000000000000000000000001000000010000000180E57F0000000000002A00000000000000000000000000000000010000000100000001801C800000000000002B00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018000890000000000002C00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180E48B0000000000002D0000000000000000000000000000000001000000010000000180F07F0000000000002E0000000000000000000000000000000001000000010000000180E8880000000000003700000000000000000000000000000000010000000100000001803B010000000000002F0000000000000000000000000000000001000000010000000180BB8A00000000000030000000000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E0E01000000000000310000000D57617463682057696E646F7773000000000000000000000000010000000100000000000000000000000100000002001380D88B00000000000031000000085761746368202631000000000000000000000000010000000100000000000000000000000100000000001380D98B000000000000310000000857617463682026320000000000000000000000000100000001000000000000000000000001000000000013800F01000000000000320000000E4D656D6F72792057696E646F7773000000000000000000000000010000000100000000000000000000000100000004001380D28B00000000000032000000094D656D6F7279202631000000000000000000000000010000000100000000000000000000000100000000001380D38B00000000000032000000094D656D6F7279202632000000000000000000000000010000000100000000000000000000000100000000001380D48B00000000000032000000094D656D6F7279202633000000000000000000000000010000000100000000000000000000000100000000001380D58B00000000000032000000094D656D6F72792026340000000000000000000000000100000001000000000000000000000001000000000013801001000000000000330000000E53657269616C2057696E646F777300000000000000000000000001000000010000000000000000000000010000000400138093070000000000003300000008554152542023263100000000000000000000000001000000010000000000000000000000010000000000138094070000000000003300000008554152542023263200000000000000000000000001000000010000000000000000000000010000000000138095070000000000003300000008554152542023263300000000000000000000000001000000010000000000000000000000010000000000138096070000000000003300000015446562756720287072696E746629205669657765720000000000000000000000000100000001000000000000000000000001000000000013803C010000000000003400000010416E616C797369732057696E646F7773000000000000000000000000010000000100000000000000000000000100000003001380658A000000000000340000000F264C6F67696320416E616C797A6572000000000000000000000000010000000100000000000000000000000100000000001380DC7F0000000000003E0000001526506572666F726D616E636520416E616C797A6572000000000000000000000000010000000100000000000000000000000100000000001380E788000000000000380000000E26436F646520436F76657261676500000000000000000000000001000000010000000000000000000000010000000000138053010000000000003F0000000D54726163652057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013805401000000000000FFFFFFFF115472616365204D656E7520416E63686F720100000000000000010000000000000001000000000000000000000001000000000013802901000000000000350000001553797374656D205669657765722057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013804B01000000000000FFFFFFFF1453797374656D2056696577657220416E63686F720100000000000000010000000000000001000000000000000000000001000000000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000013800189000000000000360000000F26546F6F6C626F782057696E646F7700000000000000000000000001000000010000000000000000000000010000000300138044C5000000000000FFFFFFFF0E5570646174652057696E646F77730100000000000000010000000000000001000000000000000000000001000000000013800000000000000400FFFFFFFF000000000000000000010000000000000001000000000000000000000001000000000013805B01000000000000FFFFFFFF12546F6F6C626F78204D656E75416E63686F72010000000000000001000000000000000100000000000000000000000100000000000000000005446562756764020000 898 @@ -2580,40 +2580,4 @@ - - 1 - 0 - - 100 - 2 - - ..\HARDWARE\IronHand\IronHand.c - 19 - 8 - 34 - 1 - - 0 - - - ..\HARDWARE\MOTOR_CTRL\motor_ctrl.c - 0 - 1 - 1 - 1 - - 0 - - - .\main.c - 27 - 136 - 157 - 1 - - 0 - - - - diff --git a/USER/4StepperMotorsDriveBySTM32F103x.uvoptx b/USER/4StepperMotorsDriveBySTM32F103x.uvoptx index 0d16053..3aaaa45 100644 --- a/USER/4StepperMotorsDriveBySTM32F103x.uvoptx +++ b/USER/4StepperMotorsDriveBySTM32F103x.uvoptx @@ -775,14 +775,233 @@ - ReadMe - 1 + UCOSII-CORE + 0 0 0 0 6 39 + 1 + 0 + 0 + 0 + 0 + ..\UCOSII\CORE\os_core.c + os_core.c + 0 + 0 + + + 6 + 40 + 1 + 0 + 0 + 0 + 0 + ..\UCOSII\CORE\os_flag.c + os_flag.c + 0 + 0 + + + 6 + 41 + 1 + 0 + 0 + 0 + 0 + ..\UCOSII\CORE\os_mbox.c + os_mbox.c + 0 + 0 + + + 6 + 42 + 1 + 0 + 0 + 0 + 0 + ..\UCOSII\CORE\os_mem.c + os_mem.c + 0 + 0 + + + 6 + 43 + 1 + 0 + 0 + 0 + 0 + ..\UCOSII\CORE\os_mutex.c + os_mutex.c + 0 + 0 + + + 6 + 44 + 1 + 0 + 0 + 0 + 0 + ..\UCOSII\CORE\os_q.c + os_q.c + 0 + 0 + + + 6 + 45 + 1 + 0 + 0 + 0 + 0 + ..\UCOSII\CORE\os_sem.c + os_sem.c + 0 + 0 + + + 6 + 46 + 1 + 0 + 0 + 0 + 0 + ..\UCOSII\CORE\os_task.c + os_task.c + 0 + 0 + + + 6 + 47 + 1 + 0 + 0 + 0 + 0 + ..\UCOSII\CORE\os_time.c + os_time.c + 0 + 0 + + + 6 + 48 + 1 + 0 + 0 + 0 + 0 + ..\UCOSII\CORE\os_tmr.c + os_tmr.c + 0 + 0 + + + + + UCOSII-PORT + 0 + 0 + 0 + 0 + + 7 + 49 + 1 + 0 + 0 + 0 + 0 + ..\UCOSII\PORT\os_cpu_c.c + os_cpu_c.c + 0 + 0 + + + 7 + 50 + 5 + 0 + 0 + 0 + 0 + ..\UCOSII\PORT\os_cpu.h + os_cpu.h + 0 + 0 + + + 7 + 51 + 2 + 0 + 0 + 0 + 0 + ..\UCOSII\PORT\os_cpu_a.asm + os_cpu_a.asm + 0 + 0 + + + + + UCOSII-CONFIG + 0 + 0 + 0 + 0 + + 8 + 52 + 5 + 0 + 0 + 0 + 0 + ..\UCOSII\CONFIG\includes.h + includes.h + 0 + 0 + + + 8 + 53 + 5 + 0 + 0 + 0 + 0 + ..\UCOSII\CONFIG\os_cfg.h + os_cfg.h + 0 + 0 + + + + + ReadMe + 0 + 0 + 0 + 0 + + 9 + 54 5 0 0 diff --git a/USER/4StepperMotorsDriveBySTM32F103x.uvprojx b/USER/4StepperMotorsDriveBySTM32F103x.uvprojx index 9560a33..cc1efde 100644 --- a/USER/4StepperMotorsDriveBySTM32F103x.uvprojx +++ b/USER/4StepperMotorsDriveBySTM32F103x.uvprojx @@ -373,7 +373,7 @@ STM32F10X_HD,USE_STDPERIPH_DRIVER - ..\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 + ..\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 @@ -628,6 +628,96 @@ + + UCOSII-CORE + + + os_core.c + 1 + ..\UCOSII\CORE\os_core.c + + + os_flag.c + 1 + ..\UCOSII\CORE\os_flag.c + + + os_mbox.c + 1 + ..\UCOSII\CORE\os_mbox.c + + + os_mem.c + 1 + ..\UCOSII\CORE\os_mem.c + + + os_mutex.c + 1 + ..\UCOSII\CORE\os_mutex.c + + + os_q.c + 1 + ..\UCOSII\CORE\os_q.c + + + os_sem.c + 1 + ..\UCOSII\CORE\os_sem.c + + + os_task.c + 1 + ..\UCOSII\CORE\os_task.c + + + os_time.c + 1 + ..\UCOSII\CORE\os_time.c + + + os_tmr.c + 1 + ..\UCOSII\CORE\os_tmr.c + + + + + UCOSII-PORT + + + os_cpu_c.c + 1 + ..\UCOSII\PORT\os_cpu_c.c + + + os_cpu.h + 5 + ..\UCOSII\PORT\os_cpu.h + + + os_cpu_a.asm + 2 + ..\UCOSII\PORT\os_cpu_a.asm + + + + + UCOSII-CONFIG + + + includes.h + 5 + ..\UCOSII\CONFIG\includes.h + + + os_cfg.h + 5 + ..\UCOSII\CONFIG\os_cfg.h + + + ReadMe diff --git a/USER/Listings/Test_v1_oneMotor.map b/USER/Listings/Test_v1_oneMotor.map index b5984f0..55f980c 100644 --- a/USER/Listings/Test_v1_oneMotor.map +++ b/USER/Listings/Test_v1_oneMotor.map @@ -153,7 +153,7 @@ Section Cross References startup_stm32f10x_md.o(RESET) refers to stm32f10x_it.o(i.UsageFault_Handler) for UsageFault_Handler startup_stm32f10x_md.o(RESET) refers to stm32f10x_it.o(i.SVC_Handler) for SVC_Handler startup_stm32f10x_md.o(RESET) refers to stm32f10x_it.o(i.DebugMon_Handler) for DebugMon_Handler - startup_stm32f10x_md.o(RESET) refers to stm32f10x_it.o(i.PendSV_Handler) for PendSV_Handler + startup_stm32f10x_md.o(RESET) refers to os_cpu_a.o(.text) for PendSV_Handler startup_stm32f10x_md.o(RESET) refers to stm32f10x_it.o(i.SysTick_Handler) for SysTick_Handler startup_stm32f10x_md.o(RESET) refers to timer1.o(i.TIM1_UP_IRQHandler) for TIM1_UP_IRQHandler startup_stm32f10x_md.o(RESET) refers to usart_master.o(i.USART1_IRQHandler) for USART1_IRQHandler @@ -221,6 +221,284 @@ Section Cross References stm32f10x_usart.o(i.USART_DeInit) refers to stm32f10x_rcc.o(i.RCC_APB1PeriphResetCmd) for RCC_APB1PeriphResetCmd stm32f10x_usart.o(i.USART_Init) refers to stm32f10x_rcc.o(i.RCC_GetClocksFreq) for RCC_GetClocksFreq stm32f10x_wwdg.o(i.WWDG_DeInit) refers to stm32f10x_rcc.o(i.RCC_APB1PeriphResetCmd) for RCC_APB1PeriphResetCmd + os_core.o(i.OSInit) refers to os_cpu_c.o(i.OSInitHookBegin) for OSInitHookBegin + os_core.o(i.OSInit) refers to os_core.o(i.OS_InitMisc) for OS_InitMisc + os_core.o(i.OSInit) refers to os_core.o(i.OS_InitRdyList) for OS_InitRdyList + os_core.o(i.OSInit) refers to os_core.o(i.OS_InitTCBList) for OS_InitTCBList + os_core.o(i.OSInit) refers to os_core.o(i.OS_InitEventList) for OS_InitEventList + os_core.o(i.OSInit) refers to os_flag.o(i.OS_FlagInit) for OS_FlagInit + os_core.o(i.OSInit) refers to os_q.o(i.OS_QInit) for OS_QInit + os_core.o(i.OSInit) refers to os_core.o(i.OS_InitTaskIdle) for OS_InitTaskIdle + os_core.o(i.OSInit) refers to os_core.o(i.OS_InitTaskStat) for OS_InitTaskStat + os_core.o(i.OSInit) refers to os_cpu_c.o(i.OSInitHookEnd) for OSInitHookEnd + os_core.o(i.OSIntEnter) refers to os_core.o(.data) for OSRunning + os_core.o(i.OSIntExit) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_core.o(i.OSIntExit) refers to os_core.o(i.OS_SchedNew) for OS_SchedNew + os_core.o(i.OSIntExit) refers to os_core.o(.data) for OSRunning + os_core.o(i.OSIntExit) refers to os_core.o(.bss) for OSTCBPrioTbl + os_core.o(i.OSSchedLock) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_core.o(i.OSSchedLock) refers to os_core.o(.data) for OSRunning + os_core.o(i.OSSchedUnlock) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_core.o(i.OSSchedUnlock) refers to os_core.o(i.OS_Sched) for OS_Sched + os_core.o(i.OSSchedUnlock) refers to os_core.o(.data) for OSRunning + os_core.o(i.OSStart) refers to os_core.o(i.OS_SchedNew) for OS_SchedNew + os_core.o(i.OSStart) refers to os_cpu_a.o(.text) for OSStartHighRdy + os_core.o(i.OSStart) refers to os_core.o(.data) for OSRunning + os_core.o(i.OSStart) refers to os_core.o(.bss) for OSTCBPrioTbl + os_core.o(i.OSStatInit) refers to os_time.o(i.OSTimeDly) for OSTimeDly + os_core.o(i.OSStatInit) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_core.o(i.OSStatInit) refers to os_core.o(.data) for OSIdleCtr + os_core.o(i.OSTimeTick) refers to os_cpu_c.o(i.OSTimeTickHook) for OSTimeTickHook + os_core.o(i.OSTimeTick) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_core.o(i.OSTimeTick) refers to os_core.o(.data) for OSTime + os_core.o(i.OS_EventTaskRdy) refers to os_core.o(i.OS_EventTaskRemove) for OS_EventTaskRemove + os_core.o(i.OS_EventTaskRdy) refers to os_core.o(.constdata) for OSUnMapTbl + os_core.o(i.OS_EventTaskRdy) refers to os_core.o(.bss) for OSTCBPrioTbl + os_core.o(i.OS_EventTaskRdy) refers to os_core.o(.data) for OSRdyGrp + os_core.o(i.OS_EventTaskWait) refers to os_core.o(.data) for OSTCBCur + os_core.o(i.OS_InitEventList) refers to os_core.o(i.OS_MemClr) for OS_MemClr + os_core.o(i.OS_InitEventList) refers to os_core.o(.bss) for OSEventTbl + os_core.o(i.OS_InitEventList) refers to os_core.o(.data) for OSEventFreeList + os_core.o(i.OS_InitMisc) refers to os_core.o(.data) for OSTime + os_core.o(i.OS_InitRdyList) refers to os_core.o(.data) for OSRdyGrp + os_core.o(i.OS_InitTCBList) refers to os_core.o(i.OS_MemClr) for OS_MemClr + os_core.o(i.OS_InitTCBList) refers to os_core.o(.bss) for OSTCBTbl + os_core.o(i.OS_InitTCBList) refers to os_core.o(.data) for OSTCBList + os_core.o(i.OS_InitTaskIdle) refers to os_task.o(i.OSTaskCreateExt) for OSTaskCreateExt + os_core.o(i.OS_InitTaskIdle) refers to os_task.o(i.OSTaskNameSet) for OSTaskNameSet + os_core.o(i.OS_InitTaskIdle) refers to os_core.o(.bss) for OSTaskIdleStk + os_core.o(i.OS_InitTaskIdle) refers to os_core.o(i.OS_TaskIdle) for OS_TaskIdle + os_core.o(i.OS_InitTaskStat) refers to os_task.o(i.OSTaskCreateExt) for OSTaskCreateExt + os_core.o(i.OS_InitTaskStat) refers to os_task.o(i.OSTaskNameSet) for OSTaskNameSet + os_core.o(i.OS_InitTaskStat) refers to os_core.o(.bss) for OSTaskStatStk + os_core.o(i.OS_InitTaskStat) refers to os_core.o(i.OS_TaskStat) for OS_TaskStat + os_core.o(i.OS_Sched) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_core.o(i.OS_Sched) refers to os_core.o(i.OS_SchedNew) for OS_SchedNew + os_core.o(i.OS_Sched) refers to os_core.o(.data) for OSIntNesting + os_core.o(i.OS_Sched) refers to os_core.o(.bss) for OSTCBPrioTbl + os_core.o(i.OS_SchedNew) refers to os_core.o(.constdata) for OSUnMapTbl + os_core.o(i.OS_SchedNew) refers to os_core.o(.data) for OSRdyGrp + os_core.o(i.OS_TCBInit) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_core.o(i.OS_TCBInit) refers to os_cpu_c.o(i.OSTCBInitHook) for OSTCBInitHook + os_core.o(i.OS_TCBInit) refers to os_cpu_c.o(i.OSTaskCreateHook) for OSTaskCreateHook + os_core.o(i.OS_TCBInit) refers to os_core.o(.data) for OSTCBFreeList + os_core.o(i.OS_TCBInit) refers to os_core.o(.bss) for OSTCBPrioTbl + os_core.o(i.OS_TaskIdle) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_core.o(i.OS_TaskIdle) refers to os_cpu_c.o(i.OSTaskIdleHook) for OSTaskIdleHook + os_core.o(i.OS_TaskIdle) refers to os_core.o(.data) for OSIdleCtr + os_core.o(i.OS_TaskStat) refers to os_time.o(i.OSTimeDly) for OSTimeDly + os_core.o(i.OS_TaskStat) refers to os_task.o(i.OSTaskSuspend) for OSTaskSuspend + os_core.o(i.OS_TaskStat) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_core.o(i.OS_TaskStat) refers to os_cpu_c.o(i.OSTaskStatHook) for OSTaskStatHook + os_core.o(i.OS_TaskStat) refers to os_core.o(i.OS_TaskStatStkChk) for OS_TaskStatStkChk + os_core.o(i.OS_TaskStat) refers to os_core.o(.data) for OSStatRdy + os_core.o(i.OS_TaskStatStkChk) refers to os_task.o(i.OSTaskStkChk) for OSTaskStkChk + os_core.o(i.OS_TaskStatStkChk) refers to os_core.o(.bss) for OSTCBPrioTbl + os_flag.o(i.OSFlagAccept) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_flag.o(i.OSFlagCreate) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_flag.o(i.OSFlagCreate) refers to os_core.o(.data) for OSIntNesting + os_flag.o(i.OSFlagDel) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_flag.o(i.OSFlagDel) refers to os_flag.o(i.OS_FlagTaskRdy) for OS_FlagTaskRdy + os_flag.o(i.OSFlagDel) refers to os_core.o(i.OS_Sched) for OS_Sched + os_flag.o(i.OSFlagDel) refers to os_core.o(.data) for OSIntNesting + os_flag.o(i.OSFlagNameGet) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_flag.o(i.OSFlagNameGet) refers to os_core.o(i.OS_StrLen) for OS_StrLen + os_flag.o(i.OSFlagNameGet) refers to os_core.o(.data) for OSIntNesting + os_flag.o(i.OSFlagNameSet) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_flag.o(i.OSFlagNameSet) refers to os_core.o(.data) for OSIntNesting + os_flag.o(i.OSFlagPend) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_flag.o(i.OSFlagPend) refers to os_flag.o(i.OS_FlagBlock) for OS_FlagBlock + os_flag.o(i.OSFlagPend) refers to os_core.o(i.OS_Sched) for OS_Sched + os_flag.o(i.OSFlagPend) refers to os_flag.o(i.OS_FlagUnlink) for OS_FlagUnlink + os_flag.o(i.OSFlagPend) refers to os_core.o(.data) for OSIntNesting + os_flag.o(i.OSFlagPendGetFlagsRdy) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_flag.o(i.OSFlagPendGetFlagsRdy) refers to os_core.o(.data) for OSTCBCur + os_flag.o(i.OSFlagPost) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_flag.o(i.OSFlagPost) refers to os_flag.o(i.OS_FlagTaskRdy) for OS_FlagTaskRdy + os_flag.o(i.OSFlagPost) refers to os_core.o(i.OS_Sched) for OS_Sched + os_flag.o(i.OSFlagQuery) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_flag.o(i.OS_FlagBlock) refers to os_core.o(.data) for OSTCBCur + os_flag.o(i.OS_FlagInit) refers to os_core.o(i.OS_MemClr) for OS_MemClr + os_flag.o(i.OS_FlagInit) refers to os_core.o(.bss) for OSFlagTbl + os_flag.o(i.OS_FlagInit) refers to os_core.o(.data) for OSFlagFreeList + os_flag.o(i.OS_FlagTaskRdy) refers to os_flag.o(i.OS_FlagUnlink) for OS_FlagUnlink + os_flag.o(i.OS_FlagTaskRdy) refers to os_core.o(.data) for OSRdyGrp + os_mbox.o(i.OSMboxAccept) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_mbox.o(i.OSMboxCreate) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_mbox.o(i.OSMboxCreate) refers to os_core.o(i.OS_EventWaitListInit) for OS_EventWaitListInit + os_mbox.o(i.OSMboxCreate) refers to os_core.o(.data) for OSIntNesting + os_mbox.o(i.OSMboxDel) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_mbox.o(i.OSMboxDel) refers to os_core.o(i.OS_EventTaskRdy) for OS_EventTaskRdy + os_mbox.o(i.OSMboxDel) refers to os_core.o(i.OS_Sched) for OS_Sched + os_mbox.o(i.OSMboxDel) refers to os_core.o(.data) for OSIntNesting + os_mbox.o(i.OSMboxPend) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_mbox.o(i.OSMboxPend) refers to os_core.o(i.OS_EventTaskWait) for OS_EventTaskWait + os_mbox.o(i.OSMboxPend) refers to os_core.o(i.OS_Sched) for OS_Sched + os_mbox.o(i.OSMboxPend) refers to os_core.o(i.OS_EventTaskRemove) for OS_EventTaskRemove + os_mbox.o(i.OSMboxPend) refers to os_core.o(.data) for OSIntNesting + os_mbox.o(i.OSMboxPendAbort) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_mbox.o(i.OSMboxPendAbort) refers to os_core.o(i.OS_EventTaskRdy) for OS_EventTaskRdy + os_mbox.o(i.OSMboxPendAbort) refers to os_core.o(i.OS_Sched) for OS_Sched + os_mbox.o(i.OSMboxPost) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_mbox.o(i.OSMboxPost) refers to os_core.o(i.OS_EventTaskRdy) for OS_EventTaskRdy + os_mbox.o(i.OSMboxPost) refers to os_core.o(i.OS_Sched) for OS_Sched + os_mbox.o(i.OSMboxPostOpt) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_mbox.o(i.OSMboxPostOpt) refers to os_core.o(i.OS_EventTaskRdy) for OS_EventTaskRdy + os_mbox.o(i.OSMboxPostOpt) refers to os_core.o(i.OS_Sched) for OS_Sched + os_mbox.o(i.OSMboxQuery) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_mutex.o(i.OSMutexAccept) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_mutex.o(i.OSMutexAccept) refers to os_core.o(.data) for OSIntNesting + os_mutex.o(i.OSMutexCreate) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_mutex.o(i.OSMutexCreate) refers to os_core.o(i.OS_EventWaitListInit) for OS_EventWaitListInit + os_mutex.o(i.OSMutexCreate) refers to os_core.o(.data) for OSIntNesting + os_mutex.o(i.OSMutexCreate) refers to os_core.o(.bss) for OSTCBPrioTbl + os_mutex.o(i.OSMutexDel) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_mutex.o(i.OSMutexDel) refers to os_mutex.o(i.OSMutex_RdyAtPrio) for OSMutex_RdyAtPrio + os_mutex.o(i.OSMutexDel) refers to os_core.o(i.OS_EventTaskRdy) for OS_EventTaskRdy + os_mutex.o(i.OSMutexDel) refers to os_core.o(i.OS_Sched) for OS_Sched + os_mutex.o(i.OSMutexDel) refers to os_core.o(.data) for OSIntNesting + os_mutex.o(i.OSMutexDel) refers to os_core.o(.bss) for OSTCBPrioTbl + os_mutex.o(i.OSMutexPend) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_mutex.o(i.OSMutexPend) refers to os_core.o(i.OS_EventTaskWait) for OS_EventTaskWait + os_mutex.o(i.OSMutexPend) refers to os_core.o(i.OS_Sched) for OS_Sched + os_mutex.o(i.OSMutexPend) refers to os_core.o(i.OS_EventTaskRemove) for OS_EventTaskRemove + os_mutex.o(i.OSMutexPend) refers to os_core.o(.data) for OSIntNesting + os_mutex.o(i.OSMutexPend) refers to os_core.o(.bss) for OSTCBPrioTbl + os_mutex.o(i.OSMutexPost) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_mutex.o(i.OSMutexPost) refers to os_mutex.o(i.OSMutex_RdyAtPrio) for OSMutex_RdyAtPrio + os_mutex.o(i.OSMutexPost) refers to os_core.o(i.OS_EventTaskRdy) for OS_EventTaskRdy + os_mutex.o(i.OSMutexPost) refers to os_core.o(i.OS_Sched) for OS_Sched + os_mutex.o(i.OSMutexPost) refers to os_core.o(.data) for OSIntNesting + os_mutex.o(i.OSMutexPost) refers to os_core.o(.bss) for OSTCBPrioTbl + os_mutex.o(i.OSMutexQuery) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_mutex.o(i.OSMutexQuery) refers to os_core.o(.data) for OSIntNesting + os_mutex.o(i.OSMutex_RdyAtPrio) refers to os_core.o(.data) for OSRdyTbl + os_mutex.o(i.OSMutex_RdyAtPrio) refers to os_core.o(.bss) for OSTCBPrioTbl + os_q.o(i.OSQAccept) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_q.o(i.OSQCreate) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_q.o(i.OSQCreate) refers to os_core.o(i.OS_EventWaitListInit) for OS_EventWaitListInit + os_q.o(i.OSQCreate) refers to os_core.o(.data) for OSIntNesting + os_q.o(i.OSQDel) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_q.o(i.OSQDel) refers to os_core.o(i.OS_EventTaskRdy) for OS_EventTaskRdy + os_q.o(i.OSQDel) refers to os_core.o(i.OS_Sched) for OS_Sched + os_q.o(i.OSQDel) refers to os_core.o(.data) for OSIntNesting + os_q.o(i.OSQFlush) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_q.o(i.OSQPend) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_q.o(i.OSQPend) refers to os_core.o(i.OS_EventTaskWait) for OS_EventTaskWait + os_q.o(i.OSQPend) refers to os_core.o(i.OS_Sched) for OS_Sched + os_q.o(i.OSQPend) refers to os_core.o(i.OS_EventTaskRemove) for OS_EventTaskRemove + os_q.o(i.OSQPend) refers to os_core.o(.data) for OSIntNesting + os_q.o(i.OSQPendAbort) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_q.o(i.OSQPendAbort) refers to os_core.o(i.OS_EventTaskRdy) for OS_EventTaskRdy + os_q.o(i.OSQPendAbort) refers to os_core.o(i.OS_Sched) for OS_Sched + os_q.o(i.OSQPost) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_q.o(i.OSQPost) refers to os_core.o(i.OS_EventTaskRdy) for OS_EventTaskRdy + os_q.o(i.OSQPost) refers to os_core.o(i.OS_Sched) for OS_Sched + os_q.o(i.OSQPostFront) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_q.o(i.OSQPostFront) refers to os_core.o(i.OS_EventTaskRdy) for OS_EventTaskRdy + os_q.o(i.OSQPostFront) refers to os_core.o(i.OS_Sched) for OS_Sched + os_q.o(i.OSQPostOpt) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_q.o(i.OSQPostOpt) refers to os_core.o(i.OS_EventTaskRdy) for OS_EventTaskRdy + os_q.o(i.OSQPostOpt) refers to os_core.o(i.OS_Sched) for OS_Sched + os_q.o(i.OSQQuery) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_q.o(i.OS_QInit) refers to os_core.o(i.OS_MemClr) for OS_MemClr + os_q.o(i.OS_QInit) refers to os_core.o(.bss) for OSQTbl + os_q.o(i.OS_QInit) refers to os_core.o(.data) for OSQFreeList + os_sem.o(i.OSSemAccept) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_sem.o(i.OSSemCreate) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_sem.o(i.OSSemCreate) refers to os_core.o(i.OS_EventWaitListInit) for OS_EventWaitListInit + os_sem.o(i.OSSemCreate) refers to os_core.o(.data) for OSIntNesting + os_sem.o(i.OSSemDel) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_sem.o(i.OSSemDel) refers to os_core.o(i.OS_EventTaskRdy) for OS_EventTaskRdy + os_sem.o(i.OSSemDel) refers to os_core.o(i.OS_Sched) for OS_Sched + os_sem.o(i.OSSemDel) refers to os_core.o(.data) for OSIntNesting + os_sem.o(i.OSSemPend) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_sem.o(i.OSSemPend) refers to os_core.o(i.OS_EventTaskWait) for OS_EventTaskWait + os_sem.o(i.OSSemPend) refers to os_core.o(i.OS_Sched) for OS_Sched + os_sem.o(i.OSSemPend) refers to os_core.o(i.OS_EventTaskRemove) for OS_EventTaskRemove + os_sem.o(i.OSSemPend) refers to os_core.o(.data) for OSIntNesting + os_sem.o(i.OSSemPendAbort) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_sem.o(i.OSSemPendAbort) refers to os_core.o(i.OS_EventTaskRdy) for OS_EventTaskRdy + os_sem.o(i.OSSemPendAbort) refers to os_core.o(i.OS_Sched) for OS_Sched + os_sem.o(i.OSSemPost) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_sem.o(i.OSSemPost) refers to os_core.o(i.OS_EventTaskRdy) for OS_EventTaskRdy + os_sem.o(i.OSSemPost) refers to os_core.o(i.OS_Sched) for OS_Sched + os_sem.o(i.OSSemQuery) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_sem.o(i.OSSemSet) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_task.o(i.OSTaskChangePrio) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_task.o(i.OSTaskChangePrio) refers to os_core.o(i.OS_Sched) for OS_Sched + os_task.o(i.OSTaskChangePrio) refers to os_core.o(.bss) for OSTCBPrioTbl + os_task.o(i.OSTaskChangePrio) refers to os_core.o(.data) for OSTCBCur + os_task.o(i.OSTaskCreate) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_task.o(i.OSTaskCreate) refers to os_cpu_c.o(i.OSTaskStkInit) for OSTaskStkInit + os_task.o(i.OSTaskCreate) refers to os_core.o(i.OS_TCBInit) for OS_TCBInit + os_task.o(i.OSTaskCreate) refers to os_core.o(i.OS_Sched) for OS_Sched + os_task.o(i.OSTaskCreate) refers to os_core.o(.data) for OSIntNesting + os_task.o(i.OSTaskCreate) refers to os_core.o(.bss) for OSTCBPrioTbl + os_task.o(i.OSTaskCreateExt) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_task.o(i.OSTaskCreateExt) refers to os_task.o(i.OS_TaskStkClr) for OS_TaskStkClr + os_task.o(i.OSTaskCreateExt) refers to os_cpu_c.o(i.OSTaskStkInit) for OSTaskStkInit + os_task.o(i.OSTaskCreateExt) refers to os_core.o(i.OS_TCBInit) for OS_TCBInit + os_task.o(i.OSTaskCreateExt) refers to os_core.o(i.OS_Sched) for OS_Sched + os_task.o(i.OSTaskCreateExt) refers to os_core.o(.data) for OSIntNesting + os_task.o(i.OSTaskCreateExt) refers to os_core.o(.bss) for OSTCBPrioTbl + os_task.o(i.OSTaskDel) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_task.o(i.OSTaskDel) refers to os_core.o(i.OS_EventTaskRemove) for OS_EventTaskRemove + os_task.o(i.OSTaskDel) refers to os_flag.o(i.OS_FlagUnlink) for OS_FlagUnlink + os_task.o(i.OSTaskDel) refers to os_core.o(i.OS_Dummy) for OS_Dummy + os_task.o(i.OSTaskDel) refers to os_cpu_c.o(i.OSTaskDelHook) for OSTaskDelHook + os_task.o(i.OSTaskDel) refers to os_core.o(i.OS_Sched) for OS_Sched + os_task.o(i.OSTaskDel) refers to os_core.o(.data) for OSIntNesting + os_task.o(i.OSTaskDel) refers to os_core.o(.bss) for OSTCBPrioTbl + os_task.o(i.OSTaskDelReq) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_task.o(i.OSTaskDelReq) refers to os_core.o(.data) for OSTCBCur + os_task.o(i.OSTaskDelReq) refers to os_core.o(.bss) for OSTCBPrioTbl + os_task.o(i.OSTaskNameGet) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_task.o(i.OSTaskNameGet) refers to os_core.o(i.OS_StrLen) for OS_StrLen + os_task.o(i.OSTaskNameGet) refers to os_core.o(.data) for OSIntNesting + os_task.o(i.OSTaskNameGet) refers to os_core.o(.bss) for OSTCBPrioTbl + os_task.o(i.OSTaskNameSet) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_task.o(i.OSTaskNameSet) refers to os_core.o(.data) for OSIntNesting + os_task.o(i.OSTaskNameSet) refers to os_core.o(.bss) for OSTCBPrioTbl + os_task.o(i.OSTaskQuery) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_task.o(i.OSTaskQuery) refers to os_core.o(i.OS_MemCopy) for OS_MemCopy + os_task.o(i.OSTaskQuery) refers to os_core.o(.data) for OSTCBCur + os_task.o(i.OSTaskQuery) refers to os_core.o(.bss) for OSTCBPrioTbl + os_task.o(i.OSTaskRegGet) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_task.o(i.OSTaskRegGet) refers to os_core.o(.data) for OSTCBCur + os_task.o(i.OSTaskRegGet) refers to os_core.o(.bss) for OSTCBPrioTbl + os_task.o(i.OSTaskRegSet) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_task.o(i.OSTaskRegSet) refers to os_core.o(.data) for OSTCBCur + os_task.o(i.OSTaskRegSet) refers to os_core.o(.bss) for OSTCBPrioTbl + os_task.o(i.OSTaskResume) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_task.o(i.OSTaskResume) refers to os_core.o(i.OS_Sched) for OS_Sched + os_task.o(i.OSTaskResume) refers to os_core.o(.bss) for OSTCBPrioTbl + os_task.o(i.OSTaskResume) refers to os_core.o(.data) for OSRdyGrp + os_task.o(i.OSTaskStkChk) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_task.o(i.OSTaskStkChk) refers to os_core.o(.data) for OSTCBCur + os_task.o(i.OSTaskStkChk) refers to os_core.o(.bss) for OSTCBPrioTbl + os_task.o(i.OSTaskSuspend) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_task.o(i.OSTaskSuspend) refers to os_core.o(i.OS_Sched) for OS_Sched + os_task.o(i.OSTaskSuspend) refers to os_core.o(.data) for OSTCBCur + os_task.o(i.OSTaskSuspend) refers to os_core.o(.bss) for OSTCBPrioTbl + os_task.o(i.OS_TaskReturn) refers to os_cpu_c.o(i.OSTaskReturnHook) for OSTaskReturnHook + os_task.o(i.OS_TaskReturn) refers to os_task.o(i.OSTaskDel) for OSTaskDel + os_task.o(i.OS_TaskReturn) refers to os_core.o(.data) for OSTCBCur + os_time.o(i.OSTimeDly) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_time.o(i.OSTimeDly) refers to os_core.o(i.OS_Sched) for OS_Sched + os_time.o(i.OSTimeDly) refers to os_core.o(.data) for OSIntNesting + os_time.o(i.OSTimeDlyHMSM) refers to os_time.o(i.OSTimeDly) for OSTimeDly + os_time.o(i.OSTimeDlyHMSM) refers to os_core.o(.data) for OSIntNesting + os_time.o(i.OSTimeDlyResume) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_time.o(i.OSTimeDlyResume) refers to os_core.o(i.OS_Sched) for OS_Sched + os_time.o(i.OSTimeDlyResume) refers to os_core.o(.bss) for OSTCBPrioTbl + os_time.o(i.OSTimeDlyResume) refers to os_core.o(.data) for OSRdyGrp + os_time.o(i.OSTimeGet) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_time.o(i.OSTimeGet) refers to os_core.o(.data) for OSTime + os_time.o(i.OSTimeSet) refers to os_cpu_a.o(.text) for OS_CPU_SR_Save + os_time.o(i.OSTimeSet) refers to os_core.o(.data) for OSTime + os_cpu_a.o(.text) refers to os_core.o(.data) for OSRunning + os_cpu_a.o(.text) refers to os_cpu_c.o(i.OSTaskSwHook) for OSTaskSwHook __main.o(!!!main) refers to __rtentry.o(.ARM.Collect$$rtentry$$00000000) for __rt_entry d2f.o(x$fpl$d2f) refers (Special) to usenofp.o(x$fpl$usenofp) for __I$use$fp d2f.o(x$fpl$d2f) refers to fretinf.o(x$fpl$fretinf) for __fpl_fretinf @@ -795,8 +1073,117 @@ Removing Unused input sections from the image. Removing stm32f10x_wwdg.o(i.WWDG_SetCounter), (16 bytes). Removing stm32f10x_wwdg.o(i.WWDG_SetPrescaler), (24 bytes). Removing stm32f10x_wwdg.o(i.WWDG_SetWindowValue), (40 bytes). + Removing os_core.o(i.OSInit), (44 bytes). + Removing os_core.o(i.OSIntEnter), (36 bytes). + Removing os_core.o(i.OSIntExit), (144 bytes). + Removing os_core.o(i.OSSchedLock), (64 bytes). + Removing os_core.o(i.OSSchedUnlock), (96 bytes). + Removing os_core.o(i.OSStart), (72 bytes). + Removing os_core.o(i.OSStatInit), (76 bytes). + Removing os_core.o(i.OSTimeTick), (236 bytes). + Removing os_core.o(i.OSVersion), (6 bytes). + Removing os_core.o(i.OS_Dummy), (2 bytes). + Removing os_core.o(i.OS_EventTaskRdy), (132 bytes). + Removing os_core.o(i.OS_EventTaskRemove), (42 bytes). + Removing os_core.o(i.OS_EventTaskWait), (124 bytes). + Removing os_core.o(i.OS_EventWaitListInit), (28 bytes). + Removing os_core.o(i.OS_InitEventList), (84 bytes). + Removing os_core.o(i.OS_InitMisc), (84 bytes). + Removing os_core.o(i.OS_InitRdyList), (68 bytes). + Removing os_core.o(i.OS_InitTCBList), (128 bytes). + Removing os_core.o(i.OS_InitTaskIdle), (80 bytes). + Removing os_core.o(i.OS_InitTaskStat), (80 bytes). + Removing os_core.o(i.OS_MemClr), (18 bytes). + Removing os_core.o(i.OS_MemCopy), (20 bytes). + Removing os_core.o(i.OS_Sched), (116 bytes). + Removing os_core.o(i.OS_SchedNew), (44 bytes). + Removing os_core.o(i.OS_StrLen), (20 bytes). + Removing os_core.o(i.OS_TCBInit), (308 bytes). + Removing os_core.o(i.OS_TaskIdle), (40 bytes). + Removing os_core.o(i.OS_TaskStat), (136 bytes). + Removing os_core.o(i.OS_TaskStatStkChk), (60 bytes). + Removing os_core.o(.bss), (2688 bytes). + Removing os_core.o(.constdata), (256 bytes). + Removing os_flag.o(i.OSFlagAccept), (252 bytes). + Removing os_flag.o(i.OSFlagCreate), (100 bytes). + Removing os_flag.o(i.OSFlagDel), (228 bytes). + Removing os_flag.o(i.OSFlagNameGet), (84 bytes). + Removing os_flag.o(i.OSFlagNameSet), (72 bytes). + Removing os_flag.o(i.OSFlagPend), (596 bytes). + Removing os_flag.o(i.OSFlagPendGetFlagsRdy), (32 bytes). + Removing os_flag.o(i.OSFlagPost), (312 bytes). + Removing os_flag.o(i.OSFlagQuery), (48 bytes). + Removing os_flag.o(i.OS_FlagBlock), (164 bytes). + Removing os_flag.o(i.OS_FlagInit), (88 bytes). + Removing os_flag.o(i.OS_FlagTaskRdy), (92 bytes). + Removing os_flag.o(i.OS_FlagUnlink), (36 bytes). + Removing os_mbox.o(i.OSMboxAccept), (38 bytes). + Removing os_mbox.o(i.OSMboxCreate), (76 bytes). + Removing os_mbox.o(i.OSMboxDel), (208 bytes). + Removing os_mbox.o(i.OSMboxPend), (260 bytes). + Removing os_mbox.o(i.OSMboxPendAbort), (128 bytes). + Removing os_mbox.o(i.OSMboxPost), (80 bytes). + Removing os_mbox.o(i.OSMboxPostOpt), (120 bytes). + Removing os_mbox.o(i.OSMboxQuery), (76 bytes). + Removing os_mutex.o(i.OSMutexAccept), (144 bytes). + Removing os_mutex.o(i.OSMutexCreate), (148 bytes). + Removing os_mutex.o(i.OSMutexDel), (280 bytes). + Removing os_mutex.o(i.OSMutexPend), (568 bytes). + Removing os_mutex.o(i.OSMutexPost), (200 bytes). + Removing os_mutex.o(i.OSMutexQuery), (112 bytes). + Removing os_mutex.o(i.OSMutex_RdyAtPrio), (132 bytes). + Removing os_q.o(i.OSQAccept), (88 bytes). + Removing os_q.o(i.OSQCreate), (152 bytes). + Removing os_q.o(i.OSQDel), (248 bytes). + Removing os_q.o(i.OSQFlush), (36 bytes). + Removing os_q.o(i.OSQPend), (284 bytes). + Removing os_q.o(i.OSQPendAbort), (128 bytes). + Removing os_q.o(i.OSQPost), (114 bytes). + Removing os_q.o(i.OSQPostFront), (116 bytes). + Removing os_q.o(i.OSQPostOpt), (182 bytes). + Removing os_q.o(i.OSQQuery), (98 bytes). + Removing os_q.o(i.OS_QInit), (80 bytes). + Removing os_sem.o(i.OSSemAccept), (42 bytes). + Removing os_sem.o(i.OSSemCreate), (76 bytes). + Removing os_sem.o(i.OSSemDel), (208 bytes). + Removing os_sem.o(i.OSSemPend), (236 bytes). + Removing os_sem.o(i.OSSemPendAbort), (128 bytes). + Removing os_sem.o(i.OSSemPost), (88 bytes). + Removing os_sem.o(i.OSSemQuery), (76 bytes). + Removing os_sem.o(i.OSSemSet), (66 bytes). + Removing os_task.o(i.OSTaskChangePrio), (328 bytes). + Removing os_task.o(i.OSTaskCreate), (160 bytes). + Removing os_task.o(i.OSTaskCreateExt), (184 bytes). + Removing os_task.o(i.OSTaskDel), (340 bytes). + Removing os_task.o(i.OSTaskDelReq), (108 bytes). + Removing os_task.o(i.OSTaskNameGet), (128 bytes). + Removing os_task.o(i.OSTaskNameSet), (112 bytes). + Removing os_task.o(i.OSTaskQuery), (92 bytes). + Removing os_task.o(i.OSTaskRegGet), (68 bytes). + Removing os_task.o(i.OSTaskRegSet), (72 bytes). + Removing os_task.o(i.OSTaskResume), (172 bytes). + Removing os_task.o(i.OSTaskStkChk), (140 bytes). + Removing os_task.o(i.OSTaskSuspend), (168 bytes). + Removing os_task.o(i.OS_TaskReturn), (24 bytes). + Removing os_task.o(i.OS_TaskStkClr), (26 bytes). + Removing os_time.o(i.OSTimeDly), (120 bytes). + Removing os_time.o(i.OSTimeDlyHMSM), (96 bytes). + Removing os_time.o(i.OSTimeDlyResume), (180 bytes). + Removing os_time.o(i.OSTimeGet), (28 bytes). + Removing os_time.o(i.OSTimeSet), (28 bytes). + Removing os_cpu_c.o(i.OSInitHookBegin), (2 bytes). + Removing os_cpu_c.o(i.OSInitHookEnd), (2 bytes). + Removing os_cpu_c.o(i.OSTCBInitHook), (2 bytes). + Removing os_cpu_c.o(i.OSTaskCreateHook), (2 bytes). + Removing os_cpu_c.o(i.OSTaskDelHook), (2 bytes). + Removing os_cpu_c.o(i.OSTaskIdleHook), (2 bytes). + Removing os_cpu_c.o(i.OSTaskReturnHook), (2 bytes). + Removing os_cpu_c.o(i.OSTaskStatHook), (2 bytes). + Removing os_cpu_c.o(i.OSTaskStkInit), (154 bytes). + Removing os_cpu_c.o(i.OSTimeTickHook), (2 bytes). + Removing os_cpu_c.o(.data), (4 bytes). -453 unused section(s) (total 18136 bytes) removed from the image. +562 unused section(s) (total 33338 bytes) removed from the image. ============================================================================== @@ -806,51 +1193,51 @@ Image Symbol Table Symbol Name Value Ov Type Size Object(Section) - ../clib/angel/boardlib.s 0x00000000 Number 0 boardinit1.o ABSOLUTE ../clib/angel/boardlib.s 0x00000000 Number 0 boardinit3.o ABSOLUTE + ../clib/angel/boardlib.s 0x00000000 Number 0 boardinit1.o ABSOLUTE ../clib/angel/boardlib.s 0x00000000 Number 0 boardinit2.o ABSOLUTE ../clib/angel/boardlib.s 0x00000000 Number 0 boardshut.o ABSOLUTE - ../clib/angel/handlers.s 0x00000000 Number 0 __scatter_zi.o ABSOLUTE ../clib/angel/handlers.s 0x00000000 Number 0 __scatter_copy.o ABSOLUTE - ../clib/angel/kernel.s 0x00000000 Number 0 __rtentry4.o ABSOLUTE - ../clib/angel/kernel.s 0x00000000 Number 0 __rtentry2.o ABSOLUTE + ../clib/angel/handlers.s 0x00000000 Number 0 __scatter_zi.o ABSOLUTE ../clib/angel/kernel.s 0x00000000 Number 0 __rtentry.o ABSOLUTE - ../clib/angel/kernel.s 0x00000000 Number 0 rtexit2.o ABSOLUTE + ../clib/angel/kernel.s 0x00000000 Number 0 __rtentry4.o ABSOLUTE ../clib/angel/kernel.s 0x00000000 Number 0 rtexit.o ABSOLUTE + ../clib/angel/kernel.s 0x00000000 Number 0 rtexit2.o ABSOLUTE + ../clib/angel/kernel.s 0x00000000 Number 0 __rtentry2.o ABSOLUTE ../clib/angel/rt.s 0x00000000 Number 0 rt_raise.o ABSOLUTE ../clib/angel/scatter.s 0x00000000 Number 0 __scatter.o ABSOLUTE ../clib/angel/startup.s 0x00000000 Number 0 __main.o ABSOLUTE - ../clib/angel/sys.s 0x00000000 Number 0 use_no_semi.o ABSOLUTE - ../clib/angel/sys.s 0x00000000 Number 0 indicate_semi.o ABSOLUTE - ../clib/angel/sys.s 0x00000000 Number 0 libspace.o ABSOLUTE ../clib/angel/sys.s 0x00000000 Number 0 sys_stackheap_outer.o ABSOLUTE + ../clib/angel/sys.s 0x00000000 Number 0 libspace.o ABSOLUTE + ../clib/angel/sys.s 0x00000000 Number 0 indicate_semi.o ABSOLUTE + ../clib/angel/sys.s 0x00000000 Number 0 use_no_semi.o ABSOLUTE ../clib/angel/sysapp.c 0x00000000 Number 0 sys_exit.o ABSOLUTE - ../clib/angel/sysapp.c 0x00000000 Number 0 sys_command.o ABSOLUTE ../clib/angel/sysapp.c 0x00000000 Number 0 sys_wrch.o ABSOLUTE + ../clib/angel/sysapp.c 0x00000000 Number 0 sys_command.o ABSOLUTE ../clib/armsys.c 0x00000000 Number 0 argv_veneer.o ABSOLUTE ../clib/armsys.c 0x00000000 Number 0 argv_veneer.o ABSOLUTE - ../clib/armsys.c 0x00000000 Number 0 no_argv.o ABSOLUTE ../clib/armsys.c 0x00000000 Number 0 _get_argv_nomalloc.o ABSOLUTE + ../clib/armsys.c 0x00000000 Number 0 no_argv.o ABSOLUTE ../clib/heapalloc.c 0x00000000 Number 0 hrguard.o ABSOLUTE ../clib/heapaux.c 0x00000000 Number 0 heapauxi.o ABSOLUTE ../clib/libinit.s 0x00000000 Number 0 libinit.o ABSOLUTE - ../clib/libinit.s 0x00000000 Number 0 libshutdown.o ABSOLUTE ../clib/libinit.s 0x00000000 Number 0 libshutdown2.o ABSOLUTE ../clib/libinit.s 0x00000000 Number 0 libinit2.o ABSOLUTE - ../clib/signal.c 0x00000000 Number 0 defsig_rtmem_outer.o ABSOLUTE - ../clib/signal.c 0x00000000 Number 0 defsig_other.o ABSOLUTE - ../clib/signal.c 0x00000000 Number 0 defsig_general.o ABSOLUTE - ../clib/signal.c 0x00000000 Number 0 defsig_segv_inner.o ABSOLUTE - ../clib/signal.c 0x00000000 Number 0 defsig_rtmem_formal.o ABSOLUTE - ../clib/signal.c 0x00000000 Number 0 defsig_rtred_inner.o ABSOLUTE - ../clib/signal.c 0x00000000 Number 0 defsig_cppl_inner.o ABSOLUTE - ../clib/signal.c 0x00000000 Number 0 __raise.o ABSOLUTE - ../clib/signal.c 0x00000000 Number 0 defsig_rtmem_inner.o ABSOLUTE - ../clib/signal.c 0x00000000 Number 0 defsig_pvfn_inner.o ABSOLUTE - ../clib/signal.c 0x00000000 Number 0 defsig_exit.o ABSOLUTE - ../clib/signal.c 0x00000000 Number 0 defsig_abrt_inner.o ABSOLUTE - ../clib/signal.c 0x00000000 Number 0 defsig_stak_inner.o ABSOLUTE + ../clib/libinit.s 0x00000000 Number 0 libshutdown.o ABSOLUTE ../clib/signal.c 0x00000000 Number 0 defsig_fpe_inner.o ABSOLUTE + ../clib/signal.c 0x00000000 Number 0 defsig_other.o ABSOLUTE + ../clib/signal.c 0x00000000 Number 0 defsig_rtmem_inner.o ABSOLUTE + ../clib/signal.c 0x00000000 Number 0 defsig_segv_inner.o ABSOLUTE + ../clib/signal.c 0x00000000 Number 0 defsig_cppl_inner.o ABSOLUTE + ../clib/signal.c 0x00000000 Number 0 defsig_pvfn_inner.o ABSOLUTE + ../clib/signal.c 0x00000000 Number 0 defsig_stak_inner.o ABSOLUTE + ../clib/signal.c 0x00000000 Number 0 defsig_rtred_inner.o ABSOLUTE + ../clib/signal.c 0x00000000 Number 0 defsig_abrt_inner.o ABSOLUTE + ../clib/signal.c 0x00000000 Number 0 defsig_general.o ABSOLUTE + ../clib/signal.c 0x00000000 Number 0 __raise.o ABSOLUTE + ../clib/signal.c 0x00000000 Number 0 defsig_exit.o ABSOLUTE + ../clib/signal.c 0x00000000 Number 0 defsig_rtmem_formal.o ABSOLUTE + ../clib/signal.c 0x00000000 Number 0 defsig_rtmem_outer.o ABSOLUTE ../clib/signal.s 0x00000000 Number 0 defsig.o ABSOLUTE ../clib/stdlib.c 0x00000000 Number 0 exit.o ABSOLUTE ../fplib/d2f.s 0x00000000 Number 0 d2f.o ABSOLUTE @@ -897,6 +1284,18 @@ Image Symbol Table ..\STM32F10x_FWLib\src\stm32f10x_wwdg.c 0x00000000 Number 0 stm32f10x_wwdg.o ABSOLUTE ..\SYSTEM\delay\delay.c 0x00000000 Number 0 delay.o ABSOLUTE ..\SYSTEM\sys\sys.c 0x00000000 Number 0 sys.o ABSOLUTE + ..\UCOSII\CORE\os_core.c 0x00000000 Number 0 os_core.o ABSOLUTE + ..\UCOSII\CORE\os_flag.c 0x00000000 Number 0 os_flag.o ABSOLUTE + ..\UCOSII\CORE\os_mbox.c 0x00000000 Number 0 os_mbox.o ABSOLUTE + ..\UCOSII\CORE\os_mem.c 0x00000000 Number 0 os_mem.o ABSOLUTE + ..\UCOSII\CORE\os_mutex.c 0x00000000 Number 0 os_mutex.o ABSOLUTE + ..\UCOSII\CORE\os_q.c 0x00000000 Number 0 os_q.o ABSOLUTE + ..\UCOSII\CORE\os_sem.c 0x00000000 Number 0 os_sem.o ABSOLUTE + ..\UCOSII\CORE\os_task.c 0x00000000 Number 0 os_task.o ABSOLUTE + ..\UCOSII\CORE\os_time.c 0x00000000 Number 0 os_time.o ABSOLUTE + ..\UCOSII\CORE\os_tmr.c 0x00000000 Number 0 os_tmr.o ABSOLUTE + ..\UCOSII\PORT\os_cpu_a.asm 0x00000000 Number 0 os_cpu_a.o ABSOLUTE + ..\UCOSII\PORT\os_cpu_c.c 0x00000000 Number 0 os_cpu_c.o ABSOLUTE ..\\CORE\\core_cm3.c 0x00000000 Number 0 core_cm3.o ABSOLUTE dc.s 0x00000000 Number 0 dc.o ABSOLUTE main.c 0x00000000 Number 0 main.o ABSOLUTE @@ -949,100 +1348,101 @@ Image Symbol Table .ARM.Collect$$rtexit$$00000003 0x0800017c Section 4 rtexit2.o(.ARM.Collect$$rtexit$$00000003) .ARM.Collect$$rtexit$$00000004 0x08000180 Section 6 rtexit2.o(.ARM.Collect$$rtexit$$00000004) .text 0x08000188 Section 64 startup_stm32f10x_md.o(.text) - .text 0x080001c8 Section 0 heapauxi.o(.text) - .text 0x080001ce Section 74 sys_stackheap_outer.o(.text) - .text 0x08000218 Section 0 exit.o(.text) - .text 0x0800022c Section 8 libspace.o(.text) - .text 0x08000234 Section 0 sys_exit.o(.text) - .text 0x08000240 Section 2 use_no_semi.o(.text) - .text 0x08000242 Section 0 indicate_semi.o(.text) - i.Annex_Seal_By 0x08000242 Section 0 motor_ctrl.o(i.Annex_Seal_By) - i.BusFault_Handler 0x0800025e Section 0 stm32f10x_it.o(i.BusFault_Handler) - i.Check_Null_Buffer 0x08000264 Section 0 usart_master.o(i.Check_Null_Buffer) - i.CloseHand 0x080002c4 Section 0 ironhand.o(i.CloseHand) - i.Compute_Time_Of 0x080002f0 Section 0 main.o(i.Compute_Time_Of) - i.DebugMon_Handler 0x080003f8 Section 0 stm32f10x_it.o(i.DebugMon_Handler) - i.GPIO_Init 0x080003fa Section 0 stm32f10x_gpio.o(i.GPIO_Init) - i.GPIO_IronHand_Init 0x08000510 Section 0 gpio_motor.o(i.GPIO_IronHand_Init) - i.GPIO_Key_Init 0x08000544 Section 0 key8.o(i.GPIO_Key_Init) - i.GPIO_Motor_Init 0x0800056c Section 0 gpio_motor.o(i.GPIO_Motor_Init) - i.GPIO_ResetBits 0x080005cc Section 0 stm32f10x_gpio.o(i.GPIO_ResetBits) - i.GPIO_SetBits 0x080005d0 Section 0 stm32f10x_gpio.o(i.GPIO_SetBits) - i.GPIO_USART1_Init 0x080005d4 Section 0 usart_master.o(i.GPIO_USART1_Init) - i.Get_Motor_RunningState 0x08000618 Section 0 motor_ctrl.o(i.Get_Motor_RunningState) - i.HardFault_Handler 0x08000632 Section 0 stm32f10x_it.o(i.HardFault_Handler) - i.HoldHand 0x08000638 Section 0 ironhand.o(i.HoldHand) - i.Init_Motor_Struct 0x08000650 Section 0 motor.o(i.Init_Motor_Struct) - i.Init_USART1_Buffer 0x080006cc Section 0 usart_master.o(i.Init_USART1_Buffer) - i.Main_Init 0x08000740 Section 0 main.o(i.Main_Init) - i.MemManage_Handler 0x080007f4 Section 0 stm32f10x_it.o(i.MemManage_Handler) - i.NMI_Handler 0x080007f8 Section 0 stm32f10x_it.o(i.NMI_Handler) - i.NVIC_Configuration 0x080007fa Section 0 sys.o(i.NVIC_Configuration) - i.NVIC_Init 0x08000808 Section 0 misc.o(i.NVIC_Init) - i.NVIC_PriorityGroupConfig 0x08000878 Section 0 misc.o(i.NVIC_PriorityGroupConfig) - i.OpenHand 0x0800088c Section 0 ironhand.o(i.OpenHand) - i.PendSV_Handler 0x080008b8 Section 0 stm32f10x_it.o(i.PendSV_Handler) - i.RCC_APB1PeriphClockCmd 0x080008bc Section 0 stm32f10x_rcc.o(i.RCC_APB1PeriphClockCmd) - i.RCC_APB1PeriphResetCmd 0x080008dc Section 0 stm32f10x_rcc.o(i.RCC_APB1PeriphResetCmd) - i.RCC_APB2PeriphClockCmd 0x080008fc Section 0 stm32f10x_rcc.o(i.RCC_APB2PeriphClockCmd) - i.RCC_APB2PeriphResetCmd 0x0800091c Section 0 stm32f10x_rcc.o(i.RCC_APB2PeriphResetCmd) - i.RCC_GetClocksFreq 0x0800093c Section 0 stm32f10x_rcc.o(i.RCC_GetClocksFreq) - i.SVC_Handler 0x08000a10 Section 0 stm32f10x_it.o(i.SVC_Handler) - i.SetSysClock 0x08000a12 Section 0 system_stm32f10x.o(i.SetSysClock) - SetSysClock 0x08000a13 Thumb Code 8 system_stm32f10x.o(i.SetSysClock) - i.SetSysClockTo72 0x08000a1c Section 0 system_stm32f10x.o(i.SetSysClockTo72) - SetSysClockTo72 0x08000a1d Thumb Code 214 system_stm32f10x.o(i.SetSysClockTo72) - i.Set_Motor_Dir 0x08000afc Section 0 motor_ctrl.o(i.Set_Motor_Dir) - i.Set_Motor_EN 0x08000b68 Section 0 motor_ctrl.o(i.Set_Motor_EN) - i.Set_Motor_Speed 0x08000be4 Section 0 motor_ctrl.o(i.Set_Motor_Speed) - i.Start_Motor_withS 0x08000bec Section 0 motor_ctrl.o(i.Start_Motor_withS) - i.Step 0x08000c6c Section 0 main.o(i.Step) - i.Stop_Motor_withS 0x08000df0 Section 0 motor_ctrl.o(i.Stop_Motor_withS) - i.SysTick_CLKSourceConfig 0x08000e74 Section 0 misc.o(i.SysTick_CLKSourceConfig) - i.SysTick_Handler 0x08000e9c Section 0 stm32f10x_it.o(i.SysTick_Handler) - i.SystemInit 0x08000ea0 Section 0 system_stm32f10x.o(i.SystemInit) - i.TIM1Nvic_Config_Init 0x08000f00 Section 0 timer1.o(i.TIM1Nvic_Config_Init) - i.TIM1_Config_Init 0x08000f20 Section 0 timer1.o(i.TIM1_Config_Init) - i.TIM1_UP_IRQHandler 0x08000f78 Section 0 timer1.o(i.TIM1_UP_IRQHandler) - i.TIM2_GPIO_PWM_Init 0x08001014 Section 0 gpio_motor.o(i.TIM2_GPIO_PWM_Init) - i.TIM2_PWM_Config_Init 0x08001040 Section 0 pwm.o(i.TIM2_PWM_Config_Init) - i.TIM3_GPIO_PWM_Init 0x080010b4 Section 0 gpio_motor.o(i.TIM3_GPIO_PWM_Init) - i.TIM3_PWM_Config_Init 0x080010e0 Section 0 pwm.o(i.TIM3_PWM_Config_Init) - i.TIM4_GPIO_PWM_Init 0x08001154 Section 0 gpio_motor.o(i.TIM4_GPIO_PWM_Init) - i.TIM4_PWM_Config_Init 0x08001180 Section 0 pwm.o(i.TIM4_PWM_Config_Init) - i.TIM_ClearFlag 0x080011f4 Section 0 stm32f10x_tim.o(i.TIM_ClearFlag) - i.TIM_ClearITPendingBit 0x080011fa Section 0 stm32f10x_tim.o(i.TIM_ClearITPendingBit) - i.TIM_Cmd 0x08001200 Section 0 stm32f10x_tim.o(i.TIM_Cmd) - i.TIM_GetITStatus 0x08001218 Section 0 stm32f10x_tim.o(i.TIM_GetITStatus) - i.TIM_ITConfig 0x0800123a Section 0 stm32f10x_tim.o(i.TIM_ITConfig) - i.TIM_OC2Init 0x0800124c Section 0 stm32f10x_tim.o(i.TIM_OC2Init) - i.TIM_OC2PreloadConfig 0x080012f0 Section 0 stm32f10x_tim.o(i.TIM_OC2PreloadConfig) - i.TIM_OCENSet 0x0800130a Section 0 motor_ctrl.o(i.TIM_OCENSet) - i.TIM_TimeBaseInit 0x0800132c Section 0 stm32f10x_tim.o(i.TIM_TimeBaseInit) - i.USART1Nvic_Config_Init 0x080013d0 Section 0 usart_master.o(i.USART1Nvic_Config_Init) - i.USART1_IRQHandler 0x080013f0 Section 0 usart_master.o(i.USART1_IRQHandler) - i.USART1_Master_Init 0x08001538 Section 0 usart_master.o(i.USART1_Master_Init) - i.USART_Cmd 0x08001590 Section 0 stm32f10x_usart.o(i.USART_Cmd) - i.USART_DeInit 0x080015a8 Section 0 stm32f10x_usart.o(i.USART_DeInit) - i.USART_GetFlagStatus 0x08001644 Section 0 stm32f10x_usart.o(i.USART_GetFlagStatus) - i.USART_ITConfig 0x0800165e Section 0 stm32f10x_usart.o(i.USART_ITConfig) - i.USART_Init 0x080016a8 Section 0 stm32f10x_usart.o(i.USART_Init) - i.USART_ReceiveData 0x08001780 Section 0 stm32f10x_usart.o(i.USART_ReceiveData) - i.UsageFault_Handler 0x0800178a Section 0 stm32f10x_it.o(i.UsageFault_Handler) - i.delay_init 0x08001790 Section 0 delay.o(i.delay_init) - i.delay_ms 0x080017d4 Section 0 delay.o(i.delay_ms) - i.delay_s 0x08001820 Section 0 delay.o(i.delay_s) - i.main 0x08001838 Section 0 main.o(i.main) - x$fpl$d2f 0x080018cc Section 98 d2f.o(x$fpl$d2f) - x$fpl$ddiv 0x08001930 Section 688 ddiv.o(x$fpl$ddiv) - ddiv_entry 0x08001937 Thumb Code 0 ddiv.o(x$fpl$ddiv) - x$fpl$dflt 0x08001be0 Section 46 dflt_clz.o(x$fpl$dflt) - x$fpl$dmul 0x08001c10 Section 340 dmul.o(x$fpl$dmul) - x$fpl$dnaninf 0x08001d64 Section 156 dnaninf.o(x$fpl$dnaninf) - x$fpl$dretinf 0x08001e00 Section 12 dretinf.o(x$fpl$dretinf) - x$fpl$fretinf 0x08001e0c Section 10 fretinf.o(x$fpl$fretinf) - .constdata 0x08001e16 Section 1730 motor_ctrl.o(.constdata) - x$fpl$usenofp 0x08001e16 Section 0 usenofp.o(x$fpl$usenofp) + .text 0x080001c8 Section 180 os_cpu_a.o(.text) + .text 0x0800027c Section 0 heapauxi.o(.text) + .text 0x08000282 Section 74 sys_stackheap_outer.o(.text) + .text 0x080002cc Section 0 exit.o(.text) + .text 0x080002e0 Section 8 libspace.o(.text) + .text 0x080002e8 Section 0 sys_exit.o(.text) + .text 0x080002f4 Section 2 use_no_semi.o(.text) + .text 0x080002f6 Section 0 indicate_semi.o(.text) + i.Annex_Seal_By 0x080002f6 Section 0 motor_ctrl.o(i.Annex_Seal_By) + i.BusFault_Handler 0x08000312 Section 0 stm32f10x_it.o(i.BusFault_Handler) + i.Check_Null_Buffer 0x08000318 Section 0 usart_master.o(i.Check_Null_Buffer) + i.CloseHand 0x08000378 Section 0 ironhand.o(i.CloseHand) + i.Compute_Time_Of 0x080003a4 Section 0 main.o(i.Compute_Time_Of) + i.DebugMon_Handler 0x080004ac Section 0 stm32f10x_it.o(i.DebugMon_Handler) + i.GPIO_Init 0x080004ae Section 0 stm32f10x_gpio.o(i.GPIO_Init) + i.GPIO_IronHand_Init 0x080005c4 Section 0 gpio_motor.o(i.GPIO_IronHand_Init) + i.GPIO_Key_Init 0x080005f8 Section 0 key8.o(i.GPIO_Key_Init) + i.GPIO_Motor_Init 0x08000620 Section 0 gpio_motor.o(i.GPIO_Motor_Init) + i.GPIO_ResetBits 0x08000680 Section 0 stm32f10x_gpio.o(i.GPIO_ResetBits) + i.GPIO_SetBits 0x08000684 Section 0 stm32f10x_gpio.o(i.GPIO_SetBits) + i.GPIO_USART1_Init 0x08000688 Section 0 usart_master.o(i.GPIO_USART1_Init) + i.Get_Motor_RunningState 0x080006cc Section 0 motor_ctrl.o(i.Get_Motor_RunningState) + i.HardFault_Handler 0x080006e6 Section 0 stm32f10x_it.o(i.HardFault_Handler) + i.HoldHand 0x080006ec Section 0 ironhand.o(i.HoldHand) + i.Init_Motor_Struct 0x08000704 Section 0 motor.o(i.Init_Motor_Struct) + i.Init_USART1_Buffer 0x08000780 Section 0 usart_master.o(i.Init_USART1_Buffer) + i.Main_Init 0x080007f4 Section 0 main.o(i.Main_Init) + i.MemManage_Handler 0x080008a8 Section 0 stm32f10x_it.o(i.MemManage_Handler) + i.NMI_Handler 0x080008ac Section 0 stm32f10x_it.o(i.NMI_Handler) + i.NVIC_Configuration 0x080008ae Section 0 sys.o(i.NVIC_Configuration) + i.NVIC_Init 0x080008bc Section 0 misc.o(i.NVIC_Init) + i.NVIC_PriorityGroupConfig 0x0800092c Section 0 misc.o(i.NVIC_PriorityGroupConfig) + i.OSTaskSwHook 0x08000940 Section 0 os_cpu_c.o(i.OSTaskSwHook) + i.OpenHand 0x08000944 Section 0 ironhand.o(i.OpenHand) + i.RCC_APB1PeriphClockCmd 0x08000970 Section 0 stm32f10x_rcc.o(i.RCC_APB1PeriphClockCmd) + i.RCC_APB1PeriphResetCmd 0x08000990 Section 0 stm32f10x_rcc.o(i.RCC_APB1PeriphResetCmd) + i.RCC_APB2PeriphClockCmd 0x080009b0 Section 0 stm32f10x_rcc.o(i.RCC_APB2PeriphClockCmd) + i.RCC_APB2PeriphResetCmd 0x080009d0 Section 0 stm32f10x_rcc.o(i.RCC_APB2PeriphResetCmd) + i.RCC_GetClocksFreq 0x080009f0 Section 0 stm32f10x_rcc.o(i.RCC_GetClocksFreq) + i.SVC_Handler 0x08000ac4 Section 0 stm32f10x_it.o(i.SVC_Handler) + i.SetSysClock 0x08000ac6 Section 0 system_stm32f10x.o(i.SetSysClock) + SetSysClock 0x08000ac7 Thumb Code 8 system_stm32f10x.o(i.SetSysClock) + i.SetSysClockTo72 0x08000ad0 Section 0 system_stm32f10x.o(i.SetSysClockTo72) + SetSysClockTo72 0x08000ad1 Thumb Code 214 system_stm32f10x.o(i.SetSysClockTo72) + i.Set_Motor_Dir 0x08000bb0 Section 0 motor_ctrl.o(i.Set_Motor_Dir) + i.Set_Motor_EN 0x08000c1c Section 0 motor_ctrl.o(i.Set_Motor_EN) + i.Set_Motor_Speed 0x08000c98 Section 0 motor_ctrl.o(i.Set_Motor_Speed) + i.Start_Motor_withS 0x08000ca0 Section 0 motor_ctrl.o(i.Start_Motor_withS) + i.Step 0x08000d20 Section 0 main.o(i.Step) + i.Stop_Motor_withS 0x08000ea4 Section 0 motor_ctrl.o(i.Stop_Motor_withS) + i.SysTick_CLKSourceConfig 0x08000f28 Section 0 misc.o(i.SysTick_CLKSourceConfig) + i.SysTick_Handler 0x08000f50 Section 0 stm32f10x_it.o(i.SysTick_Handler) + i.SystemInit 0x08000f54 Section 0 system_stm32f10x.o(i.SystemInit) + i.TIM1Nvic_Config_Init 0x08000fb4 Section 0 timer1.o(i.TIM1Nvic_Config_Init) + i.TIM1_Config_Init 0x08000fd4 Section 0 timer1.o(i.TIM1_Config_Init) + i.TIM1_UP_IRQHandler 0x0800102c Section 0 timer1.o(i.TIM1_UP_IRQHandler) + i.TIM2_GPIO_PWM_Init 0x080010c8 Section 0 gpio_motor.o(i.TIM2_GPIO_PWM_Init) + i.TIM2_PWM_Config_Init 0x080010f4 Section 0 pwm.o(i.TIM2_PWM_Config_Init) + i.TIM3_GPIO_PWM_Init 0x08001168 Section 0 gpio_motor.o(i.TIM3_GPIO_PWM_Init) + i.TIM3_PWM_Config_Init 0x08001194 Section 0 pwm.o(i.TIM3_PWM_Config_Init) + i.TIM4_GPIO_PWM_Init 0x08001208 Section 0 gpio_motor.o(i.TIM4_GPIO_PWM_Init) + i.TIM4_PWM_Config_Init 0x08001234 Section 0 pwm.o(i.TIM4_PWM_Config_Init) + i.TIM_ClearFlag 0x080012a8 Section 0 stm32f10x_tim.o(i.TIM_ClearFlag) + i.TIM_ClearITPendingBit 0x080012ae Section 0 stm32f10x_tim.o(i.TIM_ClearITPendingBit) + i.TIM_Cmd 0x080012b4 Section 0 stm32f10x_tim.o(i.TIM_Cmd) + i.TIM_GetITStatus 0x080012cc Section 0 stm32f10x_tim.o(i.TIM_GetITStatus) + i.TIM_ITConfig 0x080012ee Section 0 stm32f10x_tim.o(i.TIM_ITConfig) + i.TIM_OC2Init 0x08001300 Section 0 stm32f10x_tim.o(i.TIM_OC2Init) + i.TIM_OC2PreloadConfig 0x080013a4 Section 0 stm32f10x_tim.o(i.TIM_OC2PreloadConfig) + i.TIM_OCENSet 0x080013be Section 0 motor_ctrl.o(i.TIM_OCENSet) + i.TIM_TimeBaseInit 0x080013e0 Section 0 stm32f10x_tim.o(i.TIM_TimeBaseInit) + i.USART1Nvic_Config_Init 0x08001484 Section 0 usart_master.o(i.USART1Nvic_Config_Init) + i.USART1_IRQHandler 0x080014a4 Section 0 usart_master.o(i.USART1_IRQHandler) + i.USART1_Master_Init 0x080015ec Section 0 usart_master.o(i.USART1_Master_Init) + i.USART_Cmd 0x08001644 Section 0 stm32f10x_usart.o(i.USART_Cmd) + i.USART_DeInit 0x0800165c Section 0 stm32f10x_usart.o(i.USART_DeInit) + i.USART_GetFlagStatus 0x080016f8 Section 0 stm32f10x_usart.o(i.USART_GetFlagStatus) + i.USART_ITConfig 0x08001712 Section 0 stm32f10x_usart.o(i.USART_ITConfig) + i.USART_Init 0x0800175c Section 0 stm32f10x_usart.o(i.USART_Init) + i.USART_ReceiveData 0x08001834 Section 0 stm32f10x_usart.o(i.USART_ReceiveData) + i.UsageFault_Handler 0x0800183e Section 0 stm32f10x_it.o(i.UsageFault_Handler) + i.delay_init 0x08001844 Section 0 delay.o(i.delay_init) + i.delay_ms 0x08001888 Section 0 delay.o(i.delay_ms) + i.delay_s 0x080018d4 Section 0 delay.o(i.delay_s) + i.main 0x080018ec Section 0 main.o(i.main) + x$fpl$d2f 0x08001980 Section 98 d2f.o(x$fpl$d2f) + x$fpl$ddiv 0x080019e4 Section 688 ddiv.o(x$fpl$ddiv) + ddiv_entry 0x080019eb Thumb Code 0 ddiv.o(x$fpl$ddiv) + x$fpl$dflt 0x08001c94 Section 46 dflt_clz.o(x$fpl$dflt) + x$fpl$dmul 0x08001cc4 Section 340 dmul.o(x$fpl$dmul) + x$fpl$dnaninf 0x08001e18 Section 156 dnaninf.o(x$fpl$dnaninf) + x$fpl$dretinf 0x08001eb4 Section 12 dretinf.o(x$fpl$dretinf) + x$fpl$fretinf 0x08001ec0 Section 10 fretinf.o(x$fpl$fretinf) + .constdata 0x08001eca Section 1730 motor_ctrl.o(.constdata) + x$fpl$usenofp 0x08001eca Section 0 usenofp.o(x$fpl$usenofp) .data 0x20000000 Section 12 main.o(.data) i 0x20000004 Data 4 main.o(.data) k 0x20000008 Data 4 main.o(.data) @@ -1053,13 +1453,14 @@ Image Symbol Table .data 0x20000024 Section 20 stm32f10x_rcc.o(.data) APBAHBPrescTable 0x20000024 Data 16 stm32f10x_rcc.o(.data) ADCPrescTable 0x20000034 Data 4 stm32f10x_rcc.o(.data) - .bss 0x20000038 Section 212 main.o(.bss) - .bss 0x2000010c Section 96 libspace.o(.bss) - HEAP 0x20000170 Section 512 startup_stm32f10x_md.o(HEAP) - Heap_Mem 0x20000170 Data 512 startup_stm32f10x_md.o(HEAP) - STACK 0x20000370 Section 1024 startup_stm32f10x_md.o(STACK) - Stack_Mem 0x20000370 Data 1024 startup_stm32f10x_md.o(STACK) - __initial_sp 0x20000770 Data 0 startup_stm32f10x_md.o(STACK) + .data 0x20000038 Section 72 os_core.o(.data) + .bss 0x20000080 Section 212 main.o(.bss) + .bss 0x20000154 Section 96 libspace.o(.bss) + HEAP 0x200001b8 Section 512 startup_stm32f10x_md.o(HEAP) + Heap_Mem 0x200001b8 Data 512 startup_stm32f10x_md.o(HEAP) + STACK 0x200003b8 Section 1024 startup_stm32f10x_md.o(STACK) + Stack_Mem 0x200003b8 Data 1024 startup_stm32f10x_md.o(STACK) + __initial_sp 0x200007b8 Data 0 startup_stm32f10x_md.o(STACK) Global Symbols @@ -1189,118 +1590,147 @@ Image Symbol Table USB_LP_CAN1_RX0_IRQHandler 0x080001a3 Thumb Code 0 startup_stm32f10x_md.o(.text) WWDG_IRQHandler 0x080001a3 Thumb Code 0 startup_stm32f10x_md.o(.text) __user_initial_stackheap 0x080001a5 Thumb Code 0 startup_stm32f10x_md.o(.text) - __use_two_region_memory 0x080001c9 Thumb Code 2 heapauxi.o(.text) - __rt_heap_escrow$2region 0x080001cb Thumb Code 2 heapauxi.o(.text) - __rt_heap_expand$2region 0x080001cd Thumb Code 2 heapauxi.o(.text) - __user_setup_stackheap 0x080001cf Thumb Code 74 sys_stackheap_outer.o(.text) - exit 0x08000219 Thumb Code 18 exit.o(.text) - __user_libspace 0x0800022d Thumb Code 8 libspace.o(.text) - __user_perproc_libspace 0x0800022d Thumb Code 0 libspace.o(.text) - __user_perthread_libspace 0x0800022d Thumb Code 0 libspace.o(.text) - _sys_exit 0x08000235 Thumb Code 8 sys_exit.o(.text) - __I$use$semihosting 0x08000241 Thumb Code 0 use_no_semi.o(.text) - __use_no_semihosting_swi 0x08000241 Thumb Code 2 use_no_semi.o(.text) - Annex_Seal_By 0x08000243 Thumb Code 28 motor_ctrl.o(i.Annex_Seal_By) - __semihosting_library_function 0x08000243 Thumb Code 0 indicate_semi.o(.text) - BusFault_Handler 0x0800025f Thumb Code 4 stm32f10x_it.o(i.BusFault_Handler) - Check_Null_Buffer 0x08000265 Thumb Code 92 usart_master.o(i.Check_Null_Buffer) - CloseHand 0x080002c5 Thumb Code 36 ironhand.o(i.CloseHand) - Compute_Time_Of 0x080002f1 Thumb Code 248 main.o(i.Compute_Time_Of) - DebugMon_Handler 0x080003f9 Thumb Code 2 stm32f10x_it.o(i.DebugMon_Handler) - GPIO_Init 0x080003fb Thumb Code 278 stm32f10x_gpio.o(i.GPIO_Init) - GPIO_IronHand_Init 0x08000511 Thumb Code 46 gpio_motor.o(i.GPIO_IronHand_Init) - GPIO_Key_Init 0x08000545 Thumb Code 34 key8.o(i.GPIO_Key_Init) - GPIO_Motor_Init 0x0800056d Thumb Code 90 gpio_motor.o(i.GPIO_Motor_Init) - GPIO_ResetBits 0x080005cd Thumb Code 4 stm32f10x_gpio.o(i.GPIO_ResetBits) - GPIO_SetBits 0x080005d1 Thumb Code 4 stm32f10x_gpio.o(i.GPIO_SetBits) - GPIO_USART1_Init 0x080005d5 Thumb Code 62 usart_master.o(i.GPIO_USART1_Init) - Get_Motor_RunningState 0x08000619 Thumb Code 26 motor_ctrl.o(i.Get_Motor_RunningState) - HardFault_Handler 0x08000633 Thumb Code 4 stm32f10x_it.o(i.HardFault_Handler) - HoldHand 0x08000639 Thumb Code 14 ironhand.o(i.HoldHand) - Init_Motor_Struct 0x08000651 Thumb Code 104 motor.o(i.Init_Motor_Struct) - Init_USART1_Buffer 0x080006cd Thumb Code 112 usart_master.o(i.Init_USART1_Buffer) - Main_Init 0x08000741 Thumb Code 158 main.o(i.Main_Init) - MemManage_Handler 0x080007f5 Thumb Code 4 stm32f10x_it.o(i.MemManage_Handler) - NMI_Handler 0x080007f9 Thumb Code 2 stm32f10x_it.o(i.NMI_Handler) - NVIC_Configuration 0x080007fb Thumb Code 12 sys.o(i.NVIC_Configuration) - NVIC_Init 0x08000809 Thumb Code 100 misc.o(i.NVIC_Init) - NVIC_PriorityGroupConfig 0x08000879 Thumb Code 10 misc.o(i.NVIC_PriorityGroupConfig) - OpenHand 0x0800088d Thumb Code 36 ironhand.o(i.OpenHand) - PendSV_Handler 0x080008b9 Thumb Code 2 stm32f10x_it.o(i.PendSV_Handler) - RCC_APB1PeriphClockCmd 0x080008bd Thumb Code 26 stm32f10x_rcc.o(i.RCC_APB1PeriphClockCmd) - RCC_APB1PeriphResetCmd 0x080008dd Thumb Code 26 stm32f10x_rcc.o(i.RCC_APB1PeriphResetCmd) - RCC_APB2PeriphClockCmd 0x080008fd Thumb Code 26 stm32f10x_rcc.o(i.RCC_APB2PeriphClockCmd) - RCC_APB2PeriphResetCmd 0x0800091d Thumb Code 26 stm32f10x_rcc.o(i.RCC_APB2PeriphResetCmd) - RCC_GetClocksFreq 0x0800093d Thumb Code 192 stm32f10x_rcc.o(i.RCC_GetClocksFreq) - SVC_Handler 0x08000a11 Thumb Code 2 stm32f10x_it.o(i.SVC_Handler) - Set_Motor_Dir 0x08000afd Thumb Code 94 motor_ctrl.o(i.Set_Motor_Dir) - Set_Motor_EN 0x08000b69 Thumb Code 112 motor_ctrl.o(i.Set_Motor_EN) - Set_Motor_Speed 0x08000be5 Thumb Code 6 motor_ctrl.o(i.Set_Motor_Speed) - Start_Motor_withS 0x08000bed Thumb Code 104 motor_ctrl.o(i.Start_Motor_withS) - Step 0x08000c6d Thumb Code 350 main.o(i.Step) - Stop_Motor_withS 0x08000df1 Thumb Code 102 motor_ctrl.o(i.Stop_Motor_withS) - SysTick_CLKSourceConfig 0x08000e75 Thumb Code 40 misc.o(i.SysTick_CLKSourceConfig) - SysTick_Handler 0x08000e9d Thumb Code 2 stm32f10x_it.o(i.SysTick_Handler) - SystemInit 0x08000ea1 Thumb Code 78 system_stm32f10x.o(i.SystemInit) - TIM1Nvic_Config_Init 0x08000f01 Thumb Code 32 timer1.o(i.TIM1Nvic_Config_Init) - TIM1_Config_Init 0x08000f21 Thumb Code 84 timer1.o(i.TIM1_Config_Init) - TIM1_UP_IRQHandler 0x08000f79 Thumb Code 136 timer1.o(i.TIM1_UP_IRQHandler) - TIM2_GPIO_PWM_Init 0x08001015 Thumb Code 38 gpio_motor.o(i.TIM2_GPIO_PWM_Init) - TIM2_PWM_Config_Init 0x08001041 Thumb Code 116 pwm.o(i.TIM2_PWM_Config_Init) - TIM3_GPIO_PWM_Init 0x080010b5 Thumb Code 38 gpio_motor.o(i.TIM3_GPIO_PWM_Init) - TIM3_PWM_Config_Init 0x080010e1 Thumb Code 112 pwm.o(i.TIM3_PWM_Config_Init) - TIM4_GPIO_PWM_Init 0x08001155 Thumb Code 38 gpio_motor.o(i.TIM4_GPIO_PWM_Init) - TIM4_PWM_Config_Init 0x08001181 Thumb Code 112 pwm.o(i.TIM4_PWM_Config_Init) - TIM_ClearFlag 0x080011f5 Thumb Code 6 stm32f10x_tim.o(i.TIM_ClearFlag) - TIM_ClearITPendingBit 0x080011fb Thumb Code 6 stm32f10x_tim.o(i.TIM_ClearITPendingBit) - TIM_Cmd 0x08001201 Thumb Code 24 stm32f10x_tim.o(i.TIM_Cmd) - TIM_GetITStatus 0x08001219 Thumb Code 34 stm32f10x_tim.o(i.TIM_GetITStatus) - TIM_ITConfig 0x0800123b Thumb Code 18 stm32f10x_tim.o(i.TIM_ITConfig) - TIM_OC2Init 0x0800124d Thumb Code 154 stm32f10x_tim.o(i.TIM_OC2Init) - TIM_OC2PreloadConfig 0x080012f1 Thumb Code 26 stm32f10x_tim.o(i.TIM_OC2PreloadConfig) - TIM_OCENSet 0x0800130b Thumb Code 32 motor_ctrl.o(i.TIM_OCENSet) - TIM_TimeBaseInit 0x0800132d Thumb Code 122 stm32f10x_tim.o(i.TIM_TimeBaseInit) - USART1Nvic_Config_Init 0x080013d1 Thumb Code 30 usart_master.o(i.USART1Nvic_Config_Init) - USART1_IRQHandler 0x080013f1 Thumb Code 320 usart_master.o(i.USART1_IRQHandler) - USART1_Master_Init 0x08001539 Thumb Code 84 usart_master.o(i.USART1_Master_Init) - USART_Cmd 0x08001591 Thumb Code 24 stm32f10x_usart.o(i.USART_Cmd) - USART_DeInit 0x080015a9 Thumb Code 134 stm32f10x_usart.o(i.USART_DeInit) - USART_GetFlagStatus 0x08001645 Thumb Code 26 stm32f10x_usart.o(i.USART_GetFlagStatus) - USART_ITConfig 0x0800165f Thumb Code 74 stm32f10x_usart.o(i.USART_ITConfig) - USART_Init 0x080016a9 Thumb Code 210 stm32f10x_usart.o(i.USART_Init) - USART_ReceiveData 0x08001781 Thumb Code 10 stm32f10x_usart.o(i.USART_ReceiveData) - UsageFault_Handler 0x0800178b Thumb Code 4 stm32f10x_it.o(i.UsageFault_Handler) - delay_init 0x08001791 Thumb Code 50 delay.o(i.delay_init) - delay_ms 0x080017d5 Thumb Code 72 delay.o(i.delay_ms) - delay_s 0x08001821 Thumb Code 24 delay.o(i.delay_s) - main 0x08001839 Thumb Code 124 main.o(i.main) - __aeabi_d2f 0x080018cd Thumb Code 0 d2f.o(x$fpl$d2f) - _d2f 0x080018cd Thumb Code 98 d2f.o(x$fpl$d2f) - __aeabi_ddiv 0x08001931 Thumb Code 0 ddiv.o(x$fpl$ddiv) - _ddiv 0x08001931 Thumb Code 552 ddiv.o(x$fpl$ddiv) - __aeabi_i2d 0x08001be1 Thumb Code 0 dflt_clz.o(x$fpl$dflt) - _dflt 0x08001be1 Thumb Code 46 dflt_clz.o(x$fpl$dflt) - __aeabi_dmul 0x08001c11 Thumb Code 0 dmul.o(x$fpl$dmul) - _dmul 0x08001c11 Thumb Code 332 dmul.o(x$fpl$dmul) - __fpl_dnaninf 0x08001d65 Thumb Code 156 dnaninf.o(x$fpl$dnaninf) - __fpl_dretinf 0x08001e01 Thumb Code 12 dretinf.o(x$fpl$dretinf) - __fpl_fretinf 0x08001e0d Thumb Code 10 fretinf.o(x$fpl$fretinf) - Svalue_length 0x08001e16 Data 2 motor_ctrl.o(.constdata) - __I$use$fp 0x08001e16 Number 0 usenofp.o(x$fpl$usenofp) - AccSvalue 0x08001e18 Data 864 motor_ctrl.o(.constdata) - DecSvalue 0x08002178 Data 864 motor_ctrl.o(.constdata) - Region$$Table$$Base 0x080024d8 Number 0 anon$$obj.o(Region$$Table) - Region$$Table$$Limit 0x080024f8 Number 0 anon$$obj.o(Region$$Table) + OS_CPU_SR_Save 0x080001c9 Thumb Code 0 os_cpu_a.o(.text) + OS_CPU_SR_Restore 0x080001d1 Thumb Code 0 os_cpu_a.o(.text) + OSStartHighRdy 0x080001d7 Thumb Code 0 os_cpu_a.o(.text) + OSCtxSw 0x080001f9 Thumb Code 0 os_cpu_a.o(.text) + OSIntCtxSw 0x08000207 Thumb Code 0 os_cpu_a.o(.text) + PendSV_Handler 0x08000217 Thumb Code 0 os_cpu_a.o(.text) + __use_two_region_memory 0x0800027d Thumb Code 2 heapauxi.o(.text) + __rt_heap_escrow$2region 0x0800027f Thumb Code 2 heapauxi.o(.text) + __rt_heap_expand$2region 0x08000281 Thumb Code 2 heapauxi.o(.text) + __user_setup_stackheap 0x08000283 Thumb Code 74 sys_stackheap_outer.o(.text) + exit 0x080002cd Thumb Code 18 exit.o(.text) + __user_libspace 0x080002e1 Thumb Code 8 libspace.o(.text) + __user_perproc_libspace 0x080002e1 Thumb Code 0 libspace.o(.text) + __user_perthread_libspace 0x080002e1 Thumb Code 0 libspace.o(.text) + _sys_exit 0x080002e9 Thumb Code 8 sys_exit.o(.text) + __I$use$semihosting 0x080002f5 Thumb Code 0 use_no_semi.o(.text) + __use_no_semihosting_swi 0x080002f5 Thumb Code 2 use_no_semi.o(.text) + Annex_Seal_By 0x080002f7 Thumb Code 28 motor_ctrl.o(i.Annex_Seal_By) + __semihosting_library_function 0x080002f7 Thumb Code 0 indicate_semi.o(.text) + BusFault_Handler 0x08000313 Thumb Code 4 stm32f10x_it.o(i.BusFault_Handler) + Check_Null_Buffer 0x08000319 Thumb Code 92 usart_master.o(i.Check_Null_Buffer) + CloseHand 0x08000379 Thumb Code 36 ironhand.o(i.CloseHand) + Compute_Time_Of 0x080003a5 Thumb Code 248 main.o(i.Compute_Time_Of) + DebugMon_Handler 0x080004ad Thumb Code 2 stm32f10x_it.o(i.DebugMon_Handler) + GPIO_Init 0x080004af Thumb Code 278 stm32f10x_gpio.o(i.GPIO_Init) + GPIO_IronHand_Init 0x080005c5 Thumb Code 46 gpio_motor.o(i.GPIO_IronHand_Init) + GPIO_Key_Init 0x080005f9 Thumb Code 34 key8.o(i.GPIO_Key_Init) + GPIO_Motor_Init 0x08000621 Thumb Code 90 gpio_motor.o(i.GPIO_Motor_Init) + GPIO_ResetBits 0x08000681 Thumb Code 4 stm32f10x_gpio.o(i.GPIO_ResetBits) + GPIO_SetBits 0x08000685 Thumb Code 4 stm32f10x_gpio.o(i.GPIO_SetBits) + GPIO_USART1_Init 0x08000689 Thumb Code 62 usart_master.o(i.GPIO_USART1_Init) + Get_Motor_RunningState 0x080006cd Thumb Code 26 motor_ctrl.o(i.Get_Motor_RunningState) + HardFault_Handler 0x080006e7 Thumb Code 4 stm32f10x_it.o(i.HardFault_Handler) + HoldHand 0x080006ed Thumb Code 14 ironhand.o(i.HoldHand) + Init_Motor_Struct 0x08000705 Thumb Code 104 motor.o(i.Init_Motor_Struct) + Init_USART1_Buffer 0x08000781 Thumb Code 112 usart_master.o(i.Init_USART1_Buffer) + Main_Init 0x080007f5 Thumb Code 158 main.o(i.Main_Init) + MemManage_Handler 0x080008a9 Thumb Code 4 stm32f10x_it.o(i.MemManage_Handler) + NMI_Handler 0x080008ad Thumb Code 2 stm32f10x_it.o(i.NMI_Handler) + NVIC_Configuration 0x080008af Thumb Code 12 sys.o(i.NVIC_Configuration) + NVIC_Init 0x080008bd Thumb Code 100 misc.o(i.NVIC_Init) + NVIC_PriorityGroupConfig 0x0800092d Thumb Code 10 misc.o(i.NVIC_PriorityGroupConfig) + OSTaskSwHook 0x08000941 Thumb Code 2 os_cpu_c.o(i.OSTaskSwHook) + OpenHand 0x08000945 Thumb Code 36 ironhand.o(i.OpenHand) + RCC_APB1PeriphClockCmd 0x08000971 Thumb Code 26 stm32f10x_rcc.o(i.RCC_APB1PeriphClockCmd) + RCC_APB1PeriphResetCmd 0x08000991 Thumb Code 26 stm32f10x_rcc.o(i.RCC_APB1PeriphResetCmd) + RCC_APB2PeriphClockCmd 0x080009b1 Thumb Code 26 stm32f10x_rcc.o(i.RCC_APB2PeriphClockCmd) + RCC_APB2PeriphResetCmd 0x080009d1 Thumb Code 26 stm32f10x_rcc.o(i.RCC_APB2PeriphResetCmd) + RCC_GetClocksFreq 0x080009f1 Thumb Code 192 stm32f10x_rcc.o(i.RCC_GetClocksFreq) + SVC_Handler 0x08000ac5 Thumb Code 2 stm32f10x_it.o(i.SVC_Handler) + Set_Motor_Dir 0x08000bb1 Thumb Code 94 motor_ctrl.o(i.Set_Motor_Dir) + Set_Motor_EN 0x08000c1d Thumb Code 112 motor_ctrl.o(i.Set_Motor_EN) + Set_Motor_Speed 0x08000c99 Thumb Code 6 motor_ctrl.o(i.Set_Motor_Speed) + Start_Motor_withS 0x08000ca1 Thumb Code 104 motor_ctrl.o(i.Start_Motor_withS) + Step 0x08000d21 Thumb Code 350 main.o(i.Step) + Stop_Motor_withS 0x08000ea5 Thumb Code 102 motor_ctrl.o(i.Stop_Motor_withS) + SysTick_CLKSourceConfig 0x08000f29 Thumb Code 40 misc.o(i.SysTick_CLKSourceConfig) + SysTick_Handler 0x08000f51 Thumb Code 2 stm32f10x_it.o(i.SysTick_Handler) + SystemInit 0x08000f55 Thumb Code 78 system_stm32f10x.o(i.SystemInit) + TIM1Nvic_Config_Init 0x08000fb5 Thumb Code 32 timer1.o(i.TIM1Nvic_Config_Init) + TIM1_Config_Init 0x08000fd5 Thumb Code 84 timer1.o(i.TIM1_Config_Init) + TIM1_UP_IRQHandler 0x0800102d Thumb Code 136 timer1.o(i.TIM1_UP_IRQHandler) + TIM2_GPIO_PWM_Init 0x080010c9 Thumb Code 38 gpio_motor.o(i.TIM2_GPIO_PWM_Init) + TIM2_PWM_Config_Init 0x080010f5 Thumb Code 116 pwm.o(i.TIM2_PWM_Config_Init) + TIM3_GPIO_PWM_Init 0x08001169 Thumb Code 38 gpio_motor.o(i.TIM3_GPIO_PWM_Init) + TIM3_PWM_Config_Init 0x08001195 Thumb Code 112 pwm.o(i.TIM3_PWM_Config_Init) + TIM4_GPIO_PWM_Init 0x08001209 Thumb Code 38 gpio_motor.o(i.TIM4_GPIO_PWM_Init) + TIM4_PWM_Config_Init 0x08001235 Thumb Code 112 pwm.o(i.TIM4_PWM_Config_Init) + TIM_ClearFlag 0x080012a9 Thumb Code 6 stm32f10x_tim.o(i.TIM_ClearFlag) + TIM_ClearITPendingBit 0x080012af Thumb Code 6 stm32f10x_tim.o(i.TIM_ClearITPendingBit) + TIM_Cmd 0x080012b5 Thumb Code 24 stm32f10x_tim.o(i.TIM_Cmd) + TIM_GetITStatus 0x080012cd Thumb Code 34 stm32f10x_tim.o(i.TIM_GetITStatus) + TIM_ITConfig 0x080012ef Thumb Code 18 stm32f10x_tim.o(i.TIM_ITConfig) + TIM_OC2Init 0x08001301 Thumb Code 154 stm32f10x_tim.o(i.TIM_OC2Init) + TIM_OC2PreloadConfig 0x080013a5 Thumb Code 26 stm32f10x_tim.o(i.TIM_OC2PreloadConfig) + TIM_OCENSet 0x080013bf Thumb Code 32 motor_ctrl.o(i.TIM_OCENSet) + TIM_TimeBaseInit 0x080013e1 Thumb Code 122 stm32f10x_tim.o(i.TIM_TimeBaseInit) + USART1Nvic_Config_Init 0x08001485 Thumb Code 30 usart_master.o(i.USART1Nvic_Config_Init) + USART1_IRQHandler 0x080014a5 Thumb Code 320 usart_master.o(i.USART1_IRQHandler) + USART1_Master_Init 0x080015ed Thumb Code 84 usart_master.o(i.USART1_Master_Init) + USART_Cmd 0x08001645 Thumb Code 24 stm32f10x_usart.o(i.USART_Cmd) + USART_DeInit 0x0800165d Thumb Code 134 stm32f10x_usart.o(i.USART_DeInit) + USART_GetFlagStatus 0x080016f9 Thumb Code 26 stm32f10x_usart.o(i.USART_GetFlagStatus) + USART_ITConfig 0x08001713 Thumb Code 74 stm32f10x_usart.o(i.USART_ITConfig) + USART_Init 0x0800175d Thumb Code 210 stm32f10x_usart.o(i.USART_Init) + USART_ReceiveData 0x08001835 Thumb Code 10 stm32f10x_usart.o(i.USART_ReceiveData) + UsageFault_Handler 0x0800183f Thumb Code 4 stm32f10x_it.o(i.UsageFault_Handler) + delay_init 0x08001845 Thumb Code 50 delay.o(i.delay_init) + delay_ms 0x08001889 Thumb Code 72 delay.o(i.delay_ms) + delay_s 0x080018d5 Thumb Code 24 delay.o(i.delay_s) + main 0x080018ed Thumb Code 124 main.o(i.main) + __aeabi_d2f 0x08001981 Thumb Code 0 d2f.o(x$fpl$d2f) + _d2f 0x08001981 Thumb Code 98 d2f.o(x$fpl$d2f) + __aeabi_ddiv 0x080019e5 Thumb Code 0 ddiv.o(x$fpl$ddiv) + _ddiv 0x080019e5 Thumb Code 552 ddiv.o(x$fpl$ddiv) + __aeabi_i2d 0x08001c95 Thumb Code 0 dflt_clz.o(x$fpl$dflt) + _dflt 0x08001c95 Thumb Code 46 dflt_clz.o(x$fpl$dflt) + __aeabi_dmul 0x08001cc5 Thumb Code 0 dmul.o(x$fpl$dmul) + _dmul 0x08001cc5 Thumb Code 332 dmul.o(x$fpl$dmul) + __fpl_dnaninf 0x08001e19 Thumb Code 156 dnaninf.o(x$fpl$dnaninf) + __fpl_dretinf 0x08001eb5 Thumb Code 12 dretinf.o(x$fpl$dretinf) + __fpl_fretinf 0x08001ec1 Thumb Code 10 fretinf.o(x$fpl$fretinf) + Svalue_length 0x08001eca Data 2 motor_ctrl.o(.constdata) + __I$use$fp 0x08001eca Number 0 usenofp.o(x$fpl$usenofp) + AccSvalue 0x08001ecc Data 864 motor_ctrl.o(.constdata) + DecSvalue 0x0800222c Data 864 motor_ctrl.o(.constdata) + Region$$Table$$Base 0x0800258c Number 0 anon$$obj.o(Region$$Table) + Region$$Table$$Limit 0x080025ac Number 0 anon$$obj.o(Region$$Table) count_time 0x20000000 Data 2 main.o(.data) Key_Flag 0x20000002 Data 2 main.o(.data) SystemCoreClock 0x2000000c Data 4 system_stm32f10x.o(.data) AHBPrescTable 0x20000010 Data 16 system_stm32f10x.o(.data) - rec_buffer 0x20000038 Data 146 main.o(.bss) - motor1 0x200000ca Data 22 main.o(.bss) - motor2 0x200000e0 Data 22 main.o(.bss) - motor3 0x200000f6 Data 22 main.o(.bss) - __libspace_start 0x2000010c Data 96 libspace.o(.bss) - __temporary_stack_top$libspace 0x2000016c Data 0 libspace.o(.bss) + OSCtxSwCtr 0x20000038 Data 4 os_core.o(.data) + OSEventFreeList 0x2000003c Data 4 os_core.o(.data) + OSFlagFreeList 0x20000040 Data 4 os_core.o(.data) + OSCPUUsage 0x20000044 Data 1 os_core.o(.data) + OSIdleCtrMax 0x20000048 Data 4 os_core.o(.data) + OSIdleCtrRun 0x2000004c Data 4 os_core.o(.data) + OSStatRdy 0x20000050 Data 1 os_core.o(.data) + OSIntNesting 0x20000051 Data 1 os_core.o(.data) + OSLockNesting 0x20000052 Data 1 os_core.o(.data) + OSPrioCur 0x20000053 Data 1 os_core.o(.data) + OSPrioHighRdy 0x20000054 Data 1 os_core.o(.data) + OSRdyGrp 0x20000055 Data 1 os_core.o(.data) + OSRdyTbl 0x20000056 Data 8 os_core.o(.data) + OSRunning 0x2000005e Data 1 os_core.o(.data) + OSTaskCtr 0x2000005f Data 1 os_core.o(.data) + OSIdleCtr 0x20000060 Data 4 os_core.o(.data) + OSTCBCur 0x20000064 Data 4 os_core.o(.data) + OSTCBFreeList 0x20000068 Data 4 os_core.o(.data) + OSTCBHighRdy 0x2000006c Data 4 os_core.o(.data) + OSTCBList 0x20000070 Data 4 os_core.o(.data) + OSTickStepState 0x20000074 Data 1 os_core.o(.data) + OSQFreeList 0x20000078 Data 4 os_core.o(.data) + OSTime 0x2000007c Data 4 os_core.o(.data) + rec_buffer 0x20000080 Data 146 main.o(.bss) + motor1 0x20000112 Data 22 main.o(.bss) + motor2 0x20000128 Data 22 main.o(.bss) + motor3 0x2000013e Data 22 main.o(.bss) + __libspace_start 0x20000154 Data 96 libspace.o(.bss) + __temporary_stack_top$libspace 0x200001b4 Data 0 libspace.o(.bss) @@ -1310,181 +1740,183 @@ Memory Map of the image Image Entry point : 0x080000ed - Load Region LR_IROM1 (Base: 0x08000000, Size: 0x00002530, Max: 0x00040000, ABSOLUTE) + Load Region LR_IROM1 (Base: 0x08000000, Size: 0x0000262c, Max: 0x00040000, ABSOLUTE) - Execution Region ER_IROM1 (Base: 0x08000000, Size: 0x000024f8, Max: 0x00040000, ABSOLUTE) + Execution Region ER_IROM1 (Base: 0x08000000, Size: 0x000025ac, Max: 0x00040000, ABSOLUTE) Base Addr Size Type Attr Idx E Section Name Object - 0x08000000 0x000000ec Data RO 541 RESET startup_stm32f10x_md.o - 0x080000ec 0x00000008 Code RO 3568 * !!!main c_w.l(__main.o) - 0x080000f4 0x00000034 Code RO 3746 !!!scatter c_w.l(__scatter.o) - 0x08000128 0x0000001a Code RO 3748 !!handler_copy c_w.l(__scatter_copy.o) + 0x08000000 0x000000ec Data RO 535 RESET startup_stm32f10x_md.o + 0x080000ec 0x00000008 Code RO 4312 * !!!main c_w.l(__main.o) + 0x080000f4 0x00000034 Code RO 4490 !!!scatter c_w.l(__scatter.o) + 0x08000128 0x0000001a Code RO 4492 !!handler_copy c_w.l(__scatter_copy.o) 0x08000142 0x00000002 PAD - 0x08000144 0x0000001c Code RO 3750 !!handler_zi c_w.l(__scatter_zi.o) - 0x08000160 0x00000002 Code RO 3616 .ARM.Collect$$libinit$$00000000 c_w.l(libinit.o) - 0x08000162 0x00000000 Code RO 3623 .ARM.Collect$$libinit$$00000002 c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3625 .ARM.Collect$$libinit$$00000004 c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3628 .ARM.Collect$$libinit$$0000000A c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3630 .ARM.Collect$$libinit$$0000000C c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3632 .ARM.Collect$$libinit$$0000000E c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3635 .ARM.Collect$$libinit$$00000011 c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3637 .ARM.Collect$$libinit$$00000013 c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3639 .ARM.Collect$$libinit$$00000015 c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3641 .ARM.Collect$$libinit$$00000017 c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3643 .ARM.Collect$$libinit$$00000019 c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3645 .ARM.Collect$$libinit$$0000001B c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3647 .ARM.Collect$$libinit$$0000001D c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3649 .ARM.Collect$$libinit$$0000001F c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3651 .ARM.Collect$$libinit$$00000021 c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3653 .ARM.Collect$$libinit$$00000023 c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3655 .ARM.Collect$$libinit$$00000025 c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3659 .ARM.Collect$$libinit$$0000002C c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3661 .ARM.Collect$$libinit$$0000002E c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3663 .ARM.Collect$$libinit$$00000030 c_w.l(libinit2.o) - 0x08000162 0x00000000 Code RO 3665 .ARM.Collect$$libinit$$00000032 c_w.l(libinit2.o) - 0x08000162 0x00000002 Code RO 3666 .ARM.Collect$$libinit$$00000033 c_w.l(libinit2.o) - 0x08000164 0x00000002 Code RO 3686 .ARM.Collect$$libshutdown$$00000000 c_w.l(libshutdown.o) - 0x08000166 0x00000000 Code RO 3699 .ARM.Collect$$libshutdown$$00000002 c_w.l(libshutdown2.o) - 0x08000166 0x00000000 Code RO 3701 .ARM.Collect$$libshutdown$$00000004 c_w.l(libshutdown2.o) - 0x08000166 0x00000000 Code RO 3704 .ARM.Collect$$libshutdown$$00000007 c_w.l(libshutdown2.o) - 0x08000166 0x00000000 Code RO 3707 .ARM.Collect$$libshutdown$$0000000A c_w.l(libshutdown2.o) - 0x08000166 0x00000000 Code RO 3709 .ARM.Collect$$libshutdown$$0000000C c_w.l(libshutdown2.o) - 0x08000166 0x00000000 Code RO 3712 .ARM.Collect$$libshutdown$$0000000F c_w.l(libshutdown2.o) - 0x08000166 0x00000002 Code RO 3713 .ARM.Collect$$libshutdown$$00000010 c_w.l(libshutdown2.o) - 0x08000168 0x00000000 Code RO 3584 .ARM.Collect$$rtentry$$00000000 c_w.l(__rtentry.o) - 0x08000168 0x00000000 Code RO 3593 .ARM.Collect$$rtentry$$00000002 c_w.l(__rtentry2.o) - 0x08000168 0x00000006 Code RO 3605 .ARM.Collect$$rtentry$$00000004 c_w.l(__rtentry4.o) - 0x0800016e 0x00000000 Code RO 3595 .ARM.Collect$$rtentry$$00000009 c_w.l(__rtentry2.o) - 0x0800016e 0x00000004 Code RO 3596 .ARM.Collect$$rtentry$$0000000A c_w.l(__rtentry2.o) - 0x08000172 0x00000000 Code RO 3598 .ARM.Collect$$rtentry$$0000000C c_w.l(__rtentry2.o) - 0x08000172 0x00000008 Code RO 3599 .ARM.Collect$$rtentry$$0000000D c_w.l(__rtentry2.o) - 0x0800017a 0x00000002 Code RO 3620 .ARM.Collect$$rtexit$$00000000 c_w.l(rtexit.o) - 0x0800017c 0x00000000 Code RO 3668 .ARM.Collect$$rtexit$$00000002 c_w.l(rtexit2.o) - 0x0800017c 0x00000004 Code RO 3669 .ARM.Collect$$rtexit$$00000003 c_w.l(rtexit2.o) - 0x08000180 0x00000006 Code RO 3670 .ARM.Collect$$rtexit$$00000004 c_w.l(rtexit2.o) + 0x08000144 0x0000001c Code RO 4494 !!handler_zi c_w.l(__scatter_zi.o) + 0x08000160 0x00000002 Code RO 4360 .ARM.Collect$$libinit$$00000000 c_w.l(libinit.o) + 0x08000162 0x00000000 Code RO 4367 .ARM.Collect$$libinit$$00000002 c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4369 .ARM.Collect$$libinit$$00000004 c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4372 .ARM.Collect$$libinit$$0000000A c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4374 .ARM.Collect$$libinit$$0000000C c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4376 .ARM.Collect$$libinit$$0000000E c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4379 .ARM.Collect$$libinit$$00000011 c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4381 .ARM.Collect$$libinit$$00000013 c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4383 .ARM.Collect$$libinit$$00000015 c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4385 .ARM.Collect$$libinit$$00000017 c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4387 .ARM.Collect$$libinit$$00000019 c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4389 .ARM.Collect$$libinit$$0000001B c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4391 .ARM.Collect$$libinit$$0000001D c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4393 .ARM.Collect$$libinit$$0000001F c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4395 .ARM.Collect$$libinit$$00000021 c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4397 .ARM.Collect$$libinit$$00000023 c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4399 .ARM.Collect$$libinit$$00000025 c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4403 .ARM.Collect$$libinit$$0000002C c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4405 .ARM.Collect$$libinit$$0000002E c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4407 .ARM.Collect$$libinit$$00000030 c_w.l(libinit2.o) + 0x08000162 0x00000000 Code RO 4409 .ARM.Collect$$libinit$$00000032 c_w.l(libinit2.o) + 0x08000162 0x00000002 Code RO 4410 .ARM.Collect$$libinit$$00000033 c_w.l(libinit2.o) + 0x08000164 0x00000002 Code RO 4430 .ARM.Collect$$libshutdown$$00000000 c_w.l(libshutdown.o) + 0x08000166 0x00000000 Code RO 4443 .ARM.Collect$$libshutdown$$00000002 c_w.l(libshutdown2.o) + 0x08000166 0x00000000 Code RO 4445 .ARM.Collect$$libshutdown$$00000004 c_w.l(libshutdown2.o) + 0x08000166 0x00000000 Code RO 4448 .ARM.Collect$$libshutdown$$00000007 c_w.l(libshutdown2.o) + 0x08000166 0x00000000 Code RO 4451 .ARM.Collect$$libshutdown$$0000000A c_w.l(libshutdown2.o) + 0x08000166 0x00000000 Code RO 4453 .ARM.Collect$$libshutdown$$0000000C c_w.l(libshutdown2.o) + 0x08000166 0x00000000 Code RO 4456 .ARM.Collect$$libshutdown$$0000000F c_w.l(libshutdown2.o) + 0x08000166 0x00000002 Code RO 4457 .ARM.Collect$$libshutdown$$00000010 c_w.l(libshutdown2.o) + 0x08000168 0x00000000 Code RO 4328 .ARM.Collect$$rtentry$$00000000 c_w.l(__rtentry.o) + 0x08000168 0x00000000 Code RO 4337 .ARM.Collect$$rtentry$$00000002 c_w.l(__rtentry2.o) + 0x08000168 0x00000006 Code RO 4349 .ARM.Collect$$rtentry$$00000004 c_w.l(__rtentry4.o) + 0x0800016e 0x00000000 Code RO 4339 .ARM.Collect$$rtentry$$00000009 c_w.l(__rtentry2.o) + 0x0800016e 0x00000004 Code RO 4340 .ARM.Collect$$rtentry$$0000000A c_w.l(__rtentry2.o) + 0x08000172 0x00000000 Code RO 4342 .ARM.Collect$$rtentry$$0000000C c_w.l(__rtentry2.o) + 0x08000172 0x00000008 Code RO 4343 .ARM.Collect$$rtentry$$0000000D c_w.l(__rtentry2.o) + 0x0800017a 0x00000002 Code RO 4364 .ARM.Collect$$rtexit$$00000000 c_w.l(rtexit.o) + 0x0800017c 0x00000000 Code RO 4412 .ARM.Collect$$rtexit$$00000002 c_w.l(rtexit2.o) + 0x0800017c 0x00000004 Code RO 4413 .ARM.Collect$$rtexit$$00000003 c_w.l(rtexit2.o) + 0x08000180 0x00000006 Code RO 4414 .ARM.Collect$$rtexit$$00000004 c_w.l(rtexit2.o) 0x08000186 0x00000002 PAD - 0x08000188 0x00000040 Code RO 542 .text startup_stm32f10x_md.o - 0x080001c8 0x00000006 Code RO 3566 .text c_w.l(heapauxi.o) - 0x080001ce 0x0000004a Code RO 3607 .text c_w.l(sys_stackheap_outer.o) - 0x08000218 0x00000012 Code RO 3609 .text c_w.l(exit.o) - 0x0800022a 0x00000002 PAD - 0x0800022c 0x00000008 Code RO 3617 .text c_w.l(libspace.o) - 0x08000234 0x0000000c Code RO 3678 .text c_w.l(sys_exit.o) - 0x08000240 0x00000002 Code RO 3689 .text c_w.l(use_no_semi.o) - 0x08000242 0x00000000 Code RO 3691 .text c_w.l(indicate_semi.o) - 0x08000242 0x0000001c Code RO 357 i.Annex_Seal_By motor_ctrl.o - 0x0800025e 0x00000004 Code RO 156 i.BusFault_Handler stm32f10x_it.o - 0x08000262 0x00000002 PAD - 0x08000264 0x00000060 Code RO 438 i.Check_Null_Buffer usart_master.o - 0x080002c4 0x0000002c Code RO 333 i.CloseHand ironhand.o - 0x080002f0 0x00000108 Code RO 1 i.Compute_Time_Of main.o - 0x080003f8 0x00000002 Code RO 157 i.DebugMon_Handler stm32f10x_it.o - 0x080003fa 0x00000116 Code RO 642 i.GPIO_Init stm32f10x_gpio.o - 0x08000510 0x00000034 Code RO 223 i.GPIO_IronHand_Init gpio_motor.o - 0x08000544 0x00000028 Code RO 315 i.GPIO_Key_Init key8.o - 0x0800056c 0x00000060 Code RO 224 i.GPIO_Motor_Init gpio_motor.o - 0x080005cc 0x00000004 Code RO 649 i.GPIO_ResetBits stm32f10x_gpio.o - 0x080005d0 0x00000004 Code RO 650 i.GPIO_SetBits stm32f10x_gpio.o - 0x080005d4 0x00000044 Code RO 439 i.GPIO_USART1_Init usart_master.o - 0x08000618 0x0000001a Code RO 360 i.Get_Motor_RunningState motor_ctrl.o - 0x08000632 0x00000004 Code RO 158 i.HardFault_Handler stm32f10x_it.o - 0x08000636 0x00000002 PAD - 0x08000638 0x00000018 Code RO 334 i.HoldHand ironhand.o - 0x08000650 0x0000007c Code RO 426 i.Init_Motor_Struct motor.o - 0x080006cc 0x00000074 Code RO 440 i.Init_USART1_Buffer usart_master.o - 0x08000740 0x000000b4 Code RO 2 i.Main_Init main.o - 0x080007f4 0x00000004 Code RO 159 i.MemManage_Handler stm32f10x_it.o - 0x080007f8 0x00000002 Code RO 160 i.NMI_Handler stm32f10x_it.o - 0x080007fa 0x0000000c Code RO 516 i.NVIC_Configuration sys.o - 0x08000806 0x00000002 PAD - 0x08000808 0x00000070 Code RO 546 i.NVIC_Init misc.o - 0x08000878 0x00000014 Code RO 547 i.NVIC_PriorityGroupConfig misc.o - 0x0800088c 0x0000002c Code RO 335 i.OpenHand ironhand.o - 0x080008b8 0x00000002 Code RO 161 i.PendSV_Handler stm32f10x_it.o + 0x08000188 0x00000040 Code RO 536 .text startup_stm32f10x_md.o + 0x080001c8 0x000000b4 Code RO 4305 .text os_cpu_a.o + 0x0800027c 0x00000006 Code RO 4310 .text c_w.l(heapauxi.o) + 0x08000282 0x0000004a Code RO 4351 .text c_w.l(sys_stackheap_outer.o) + 0x080002cc 0x00000012 Code RO 4353 .text c_w.l(exit.o) + 0x080002de 0x00000002 PAD + 0x080002e0 0x00000008 Code RO 4361 .text c_w.l(libspace.o) + 0x080002e8 0x0000000c Code RO 4422 .text c_w.l(sys_exit.o) + 0x080002f4 0x00000002 Code RO 4433 .text c_w.l(use_no_semi.o) + 0x080002f6 0x00000000 Code RO 4435 .text c_w.l(indicate_semi.o) + 0x080002f6 0x0000001c Code RO 351 i.Annex_Seal_By motor_ctrl.o + 0x08000312 0x00000004 Code RO 156 i.BusFault_Handler stm32f10x_it.o + 0x08000316 0x00000002 PAD + 0x08000318 0x00000060 Code RO 432 i.Check_Null_Buffer usart_master.o + 0x08000378 0x0000002c Code RO 327 i.CloseHand ironhand.o + 0x080003a4 0x00000108 Code RO 1 i.Compute_Time_Of main.o + 0x080004ac 0x00000002 Code RO 157 i.DebugMon_Handler stm32f10x_it.o + 0x080004ae 0x00000116 Code RO 636 i.GPIO_Init stm32f10x_gpio.o + 0x080005c4 0x00000034 Code RO 217 i.GPIO_IronHand_Init gpio_motor.o + 0x080005f8 0x00000028 Code RO 309 i.GPIO_Key_Init key8.o + 0x08000620 0x00000060 Code RO 218 i.GPIO_Motor_Init gpio_motor.o + 0x08000680 0x00000004 Code RO 643 i.GPIO_ResetBits stm32f10x_gpio.o + 0x08000684 0x00000004 Code RO 644 i.GPIO_SetBits stm32f10x_gpio.o + 0x08000688 0x00000044 Code RO 433 i.GPIO_USART1_Init usart_master.o + 0x080006cc 0x0000001a Code RO 354 i.Get_Motor_RunningState motor_ctrl.o + 0x080006e6 0x00000004 Code RO 158 i.HardFault_Handler stm32f10x_it.o + 0x080006ea 0x00000002 PAD + 0x080006ec 0x00000018 Code RO 328 i.HoldHand ironhand.o + 0x08000704 0x0000007c Code RO 420 i.Init_Motor_Struct motor.o + 0x08000780 0x00000074 Code RO 434 i.Init_USART1_Buffer usart_master.o + 0x080007f4 0x000000b4 Code RO 2 i.Main_Init main.o + 0x080008a8 0x00000004 Code RO 159 i.MemManage_Handler stm32f10x_it.o + 0x080008ac 0x00000002 Code RO 160 i.NMI_Handler stm32f10x_it.o + 0x080008ae 0x0000000c Code RO 510 i.NVIC_Configuration sys.o 0x080008ba 0x00000002 PAD - 0x080008bc 0x00000020 Code RO 2700 i.RCC_APB1PeriphClockCmd stm32f10x_rcc.o - 0x080008dc 0x00000020 Code RO 2701 i.RCC_APB1PeriphResetCmd stm32f10x_rcc.o - 0x080008fc 0x00000020 Code RO 2702 i.RCC_APB2PeriphClockCmd stm32f10x_rcc.o - 0x0800091c 0x00000020 Code RO 2703 i.RCC_APB2PeriphResetCmd stm32f10x_rcc.o - 0x0800093c 0x000000d4 Code RO 2710 i.RCC_GetClocksFreq stm32f10x_rcc.o - 0x08000a10 0x00000002 Code RO 162 i.SVC_Handler stm32f10x_it.o - 0x08000a12 0x00000008 Code RO 106 i.SetSysClock system_stm32f10x.o - 0x08000a1a 0x00000002 PAD - 0x08000a1c 0x000000e0 Code RO 107 i.SetSysClockTo72 system_stm32f10x.o - 0x08000afc 0x0000006c Code RO 361 i.Set_Motor_Dir motor_ctrl.o - 0x08000b68 0x0000007c Code RO 362 i.Set_Motor_EN motor_ctrl.o - 0x08000be4 0x00000006 Code RO 363 i.Set_Motor_Speed motor_ctrl.o - 0x08000bea 0x00000002 PAD - 0x08000bec 0x00000080 Code RO 364 i.Start_Motor_withS motor_ctrl.o - 0x08000c6c 0x00000184 Code RO 3 i.Step main.o - 0x08000df0 0x00000084 Code RO 365 i.Stop_Motor_withS motor_ctrl.o - 0x08000e74 0x00000028 Code RO 550 i.SysTick_CLKSourceConfig misc.o - 0x08000e9c 0x00000002 Code RO 163 i.SysTick_Handler stm32f10x_it.o - 0x08000e9e 0x00000002 PAD - 0x08000ea0 0x00000060 Code RO 109 i.SystemInit system_stm32f10x.o - 0x08000f00 0x00000020 Code RO 283 i.TIM1Nvic_Config_Init timer1.o - 0x08000f20 0x00000058 Code RO 284 i.TIM1_Config_Init timer1.o - 0x08000f78 0x0000009c Code RO 285 i.TIM1_UP_IRQHandler timer1.o - 0x08001014 0x0000002c Code RO 225 i.TIM2_GPIO_PWM_Init gpio_motor.o - 0x08001040 0x00000074 Code RO 259 i.TIM2_PWM_Config_Init pwm.o - 0x080010b4 0x0000002c Code RO 226 i.TIM3_GPIO_PWM_Init gpio_motor.o - 0x080010e0 0x00000074 Code RO 260 i.TIM3_PWM_Config_Init pwm.o - 0x08001154 0x0000002c Code RO 227 i.TIM4_GPIO_PWM_Init gpio_motor.o - 0x08001180 0x00000074 Code RO 261 i.TIM4_PWM_Config_Init pwm.o - 0x080011f4 0x00000006 Code RO 760 i.TIM_ClearFlag stm32f10x_tim.o - 0x080011fa 0x00000006 Code RO 761 i.TIM_ClearITPendingBit stm32f10x_tim.o - 0x08001200 0x00000018 Code RO 766 i.TIM_Cmd stm32f10x_tim.o - 0x08001218 0x00000022 Code RO 787 i.TIM_GetITStatus stm32f10x_tim.o - 0x0800123a 0x00000012 Code RO 791 i.TIM_ITConfig stm32f10x_tim.o - 0x0800124c 0x000000a4 Code RO 800 i.TIM_OC2Init stm32f10x_tim.o - 0x080012f0 0x0000001a Code RO 803 i.TIM_OC2PreloadConfig stm32f10x_tim.o - 0x0800130a 0x00000020 Code RO 366 i.TIM_OCENSet motor_ctrl.o - 0x0800132a 0x00000002 PAD - 0x0800132c 0x000000a4 Code RO 837 i.TIM_TimeBaseInit stm32f10x_tim.o - 0x080013d0 0x0000001e Code RO 441 i.USART1Nvic_Config_Init usart_master.o - 0x080013ee 0x00000002 PAD - 0x080013f0 0x00000148 Code RO 442 i.USART1_IRQHandler usart_master.o - 0x08001538 0x00000058 Code RO 443 i.USART1_Master_Init usart_master.o - 0x08001590 0x00000018 Code RO 3331 i.USART_Cmd stm32f10x_usart.o - 0x080015a8 0x0000009c Code RO 3333 i.USART_DeInit stm32f10x_usart.o - 0x08001644 0x0000001a Code RO 3334 i.USART_GetFlagStatus stm32f10x_usart.o - 0x0800165e 0x0000004a Code RO 3337 i.USART_ITConfig stm32f10x_usart.o - 0x080016a8 0x000000d8 Code RO 3338 i.USART_Init stm32f10x_usart.o - 0x08001780 0x0000000a Code RO 3345 i.USART_ReceiveData stm32f10x_usart.o - 0x0800178a 0x00000004 Code RO 164 i.UsageFault_Handler stm32f10x_it.o - 0x0800178e 0x00000002 PAD - 0x08001790 0x00000044 Code RO 484 i.delay_init delay.o - 0x080017d4 0x0000004c Code RO 485 i.delay_ms delay.o - 0x08001820 0x00000018 Code RO 486 i.delay_s delay.o - 0x08001838 0x00000094 Code RO 4 i.main main.o - 0x080018cc 0x00000062 Code RO 3570 x$fpl$d2f fz_ws.l(d2f.o) - 0x0800192e 0x00000002 PAD - 0x08001930 0x000002b0 Code RO 3573 x$fpl$ddiv fz_ws.l(ddiv.o) - 0x08001be0 0x0000002e Code RO 3577 x$fpl$dflt fz_ws.l(dflt_clz.o) - 0x08001c0e 0x00000002 PAD - 0x08001c10 0x00000154 Code RO 3582 x$fpl$dmul fz_ws.l(dmul.o) - 0x08001d64 0x0000009c Code RO 3585 x$fpl$dnaninf fz_ws.l(dnaninf.o) - 0x08001e00 0x0000000c Code RO 3587 x$fpl$dretinf fz_ws.l(dretinf.o) - 0x08001e0c 0x0000000a Code RO 3589 x$fpl$fretinf fz_ws.l(fretinf.o) - 0x08001e16 0x00000000 Code RO 3591 x$fpl$usenofp fz_ws.l(usenofp.o) - 0x08001e16 0x000006c2 Data RO 367 .constdata motor_ctrl.o - 0x080024d8 0x00000020 Data RO 3744 Region$$Table anon$$obj.o + 0x080008bc 0x00000070 Code RO 540 i.NVIC_Init misc.o + 0x0800092c 0x00000014 Code RO 541 i.NVIC_PriorityGroupConfig misc.o + 0x08000940 0x00000002 Code RO 4232 i.OSTaskSwHook os_cpu_c.o + 0x08000942 0x00000002 PAD + 0x08000944 0x0000002c Code RO 329 i.OpenHand ironhand.o + 0x08000970 0x00000020 Code RO 2694 i.RCC_APB1PeriphClockCmd stm32f10x_rcc.o + 0x08000990 0x00000020 Code RO 2695 i.RCC_APB1PeriphResetCmd stm32f10x_rcc.o + 0x080009b0 0x00000020 Code RO 2696 i.RCC_APB2PeriphClockCmd stm32f10x_rcc.o + 0x080009d0 0x00000020 Code RO 2697 i.RCC_APB2PeriphResetCmd stm32f10x_rcc.o + 0x080009f0 0x000000d4 Code RO 2704 i.RCC_GetClocksFreq stm32f10x_rcc.o + 0x08000ac4 0x00000002 Code RO 161 i.SVC_Handler stm32f10x_it.o + 0x08000ac6 0x00000008 Code RO 106 i.SetSysClock system_stm32f10x.o + 0x08000ace 0x00000002 PAD + 0x08000ad0 0x000000e0 Code RO 107 i.SetSysClockTo72 system_stm32f10x.o + 0x08000bb0 0x0000006c Code RO 355 i.Set_Motor_Dir motor_ctrl.o + 0x08000c1c 0x0000007c Code RO 356 i.Set_Motor_EN motor_ctrl.o + 0x08000c98 0x00000006 Code RO 357 i.Set_Motor_Speed motor_ctrl.o + 0x08000c9e 0x00000002 PAD + 0x08000ca0 0x00000080 Code RO 358 i.Start_Motor_withS motor_ctrl.o + 0x08000d20 0x00000184 Code RO 3 i.Step main.o + 0x08000ea4 0x00000084 Code RO 359 i.Stop_Motor_withS motor_ctrl.o + 0x08000f28 0x00000028 Code RO 544 i.SysTick_CLKSourceConfig misc.o + 0x08000f50 0x00000002 Code RO 162 i.SysTick_Handler stm32f10x_it.o + 0x08000f52 0x00000002 PAD + 0x08000f54 0x00000060 Code RO 109 i.SystemInit system_stm32f10x.o + 0x08000fb4 0x00000020 Code RO 277 i.TIM1Nvic_Config_Init timer1.o + 0x08000fd4 0x00000058 Code RO 278 i.TIM1_Config_Init timer1.o + 0x0800102c 0x0000009c Code RO 279 i.TIM1_UP_IRQHandler timer1.o + 0x080010c8 0x0000002c Code RO 219 i.TIM2_GPIO_PWM_Init gpio_motor.o + 0x080010f4 0x00000074 Code RO 253 i.TIM2_PWM_Config_Init pwm.o + 0x08001168 0x0000002c Code RO 220 i.TIM3_GPIO_PWM_Init gpio_motor.o + 0x08001194 0x00000074 Code RO 254 i.TIM3_PWM_Config_Init pwm.o + 0x08001208 0x0000002c Code RO 221 i.TIM4_GPIO_PWM_Init gpio_motor.o + 0x08001234 0x00000074 Code RO 255 i.TIM4_PWM_Config_Init pwm.o + 0x080012a8 0x00000006 Code RO 754 i.TIM_ClearFlag stm32f10x_tim.o + 0x080012ae 0x00000006 Code RO 755 i.TIM_ClearITPendingBit stm32f10x_tim.o + 0x080012b4 0x00000018 Code RO 760 i.TIM_Cmd stm32f10x_tim.o + 0x080012cc 0x00000022 Code RO 781 i.TIM_GetITStatus stm32f10x_tim.o + 0x080012ee 0x00000012 Code RO 785 i.TIM_ITConfig stm32f10x_tim.o + 0x08001300 0x000000a4 Code RO 794 i.TIM_OC2Init stm32f10x_tim.o + 0x080013a4 0x0000001a Code RO 797 i.TIM_OC2PreloadConfig stm32f10x_tim.o + 0x080013be 0x00000020 Code RO 360 i.TIM_OCENSet motor_ctrl.o + 0x080013de 0x00000002 PAD + 0x080013e0 0x000000a4 Code RO 831 i.TIM_TimeBaseInit stm32f10x_tim.o + 0x08001484 0x0000001e Code RO 435 i.USART1Nvic_Config_Init usart_master.o + 0x080014a2 0x00000002 PAD + 0x080014a4 0x00000148 Code RO 436 i.USART1_IRQHandler usart_master.o + 0x080015ec 0x00000058 Code RO 437 i.USART1_Master_Init usart_master.o + 0x08001644 0x00000018 Code RO 3325 i.USART_Cmd stm32f10x_usart.o + 0x0800165c 0x0000009c Code RO 3327 i.USART_DeInit stm32f10x_usart.o + 0x080016f8 0x0000001a Code RO 3328 i.USART_GetFlagStatus stm32f10x_usart.o + 0x08001712 0x0000004a Code RO 3331 i.USART_ITConfig stm32f10x_usart.o + 0x0800175c 0x000000d8 Code RO 3332 i.USART_Init stm32f10x_usart.o + 0x08001834 0x0000000a Code RO 3339 i.USART_ReceiveData stm32f10x_usart.o + 0x0800183e 0x00000004 Code RO 163 i.UsageFault_Handler stm32f10x_it.o + 0x08001842 0x00000002 PAD + 0x08001844 0x00000044 Code RO 478 i.delay_init delay.o + 0x08001888 0x0000004c Code RO 479 i.delay_ms delay.o + 0x080018d4 0x00000018 Code RO 480 i.delay_s delay.o + 0x080018ec 0x00000094 Code RO 4 i.main main.o + 0x08001980 0x00000062 Code RO 4314 x$fpl$d2f fz_ws.l(d2f.o) + 0x080019e2 0x00000002 PAD + 0x080019e4 0x000002b0 Code RO 4317 x$fpl$ddiv fz_ws.l(ddiv.o) + 0x08001c94 0x0000002e Code RO 4321 x$fpl$dflt fz_ws.l(dflt_clz.o) + 0x08001cc2 0x00000002 PAD + 0x08001cc4 0x00000154 Code RO 4326 x$fpl$dmul fz_ws.l(dmul.o) + 0x08001e18 0x0000009c Code RO 4329 x$fpl$dnaninf fz_ws.l(dnaninf.o) + 0x08001eb4 0x0000000c Code RO 4331 x$fpl$dretinf fz_ws.l(dretinf.o) + 0x08001ec0 0x0000000a Code RO 4333 x$fpl$fretinf fz_ws.l(fretinf.o) + 0x08001eca 0x00000000 Code RO 4335 x$fpl$usenofp fz_ws.l(usenofp.o) + 0x08001eca 0x000006c2 Data RO 361 .constdata motor_ctrl.o + 0x0800258c 0x00000020 Data RO 4488 Region$$Table anon$$obj.o - Execution Region RW_IRAM1 (Base: 0x20000000, Size: 0x00000770, Max: 0x0000c000, ABSOLUTE) + Execution Region RW_IRAM1 (Base: 0x20000000, Size: 0x000007b8, Max: 0x0000c000, ABSOLUTE) Base Addr Size Type Attr Idx E Section Name Object 0x20000000 0x0000000c Data RW 6 .data main.o 0x2000000c 0x00000014 Data RW 110 .data system_stm32f10x.o - 0x20000020 0x00000004 Data RW 488 .data delay.o - 0x20000024 0x00000014 Data RW 2730 .data stm32f10x_rcc.o - 0x20000038 0x000000d4 Zero RW 5 .bss main.o - 0x2000010c 0x00000060 Zero RW 3618 .bss c_w.l(libspace.o) - 0x2000016c 0x00000004 PAD - 0x20000170 0x00000200 Zero RW 540 HEAP startup_stm32f10x_md.o - 0x20000370 0x00000400 Zero RW 539 STACK startup_stm32f10x_md.o + 0x20000020 0x00000004 Data RW 482 .data delay.o + 0x20000024 0x00000014 Data RW 2724 .data stm32f10x_rcc.o + 0x20000038 0x00000048 Data RW 3589 .data os_core.o + 0x20000080 0x000000d4 Zero RW 5 .bss main.o + 0x20000154 0x00000060 Zero RW 4362 .bss c_w.l(libspace.o) + 0x200001b4 0x00000004 PAD + 0x200001b8 0x00000200 Zero RW 534 HEAP startup_stm32f10x_md.o + 0x200003b8 0x00000400 Zero RW 533 STACK startup_stm32f10x_md.o ============================================================================== @@ -1503,10 +1935,13 @@ Image component sizes 172 22 0 0 0 2033 misc.o 124 20 0 0 0 948 motor.o 584 80 1730 0 0 5679 motor_ctrl.o + 0 0 0 72 0 8917 os_core.o + 180 36 0 0 0 324 os_cpu_a.o + 2 0 0 0 0 423 os_cpu_c.o 348 8 0 0 0 2085 pwm.o 64 26 236 0 1536 792 startup_stm32f10x_md.o 286 0 0 0 0 3012 stm32f10x_gpio.o - 26 0 0 0 0 3662 stm32f10x_it.o + 24 0 0 0 0 3257 stm32f10x_it.o 340 44 0 20 0 5540 stm32f10x_rcc.o 442 52 0 0 0 5335 stm32f10x_tim.o 506 28 0 0 0 5431 stm32f10x_usart.o @@ -1516,7 +1951,7 @@ Image component sizes 726 26 0 0 0 4823 usart_master.o ---------------------------------------------------------------------- - 5834 542 1998 56 1748 308064 Object Totals + 6014 578 1998 128 1748 317323 Object Totals 0 0 32 0 0 0 (incl. Generated) 20 0 0 0 0 0 (incl. Padding) @@ -1574,15 +2009,15 @@ Image component sizes Code (inc. data) RO Data RW Data ZI Data Debug - 7466 718 1998 56 1848 305132 Grand Totals - 7466 718 1998 56 1848 305132 ELF Image Totals - 7466 718 1998 56 0 0 ROM Totals + 7646 754 1998 128 1848 314391 Grand Totals + 7646 754 1998 128 1848 314391 ELF Image Totals + 7646 754 1998 128 0 0 ROM Totals ============================================================================== - Total RO Size (Code + RO Data) 9464 ( 9.24kB) - Total RW Size (RW Data + ZI Data) 1904 ( 1.86kB) - Total ROM Size (Code + RO Data + RW Data) 9520 ( 9.30kB) + Total RO Size (Code + RO Data) 9644 ( 9.42kB) + Total RW Size (RW Data + ZI Data) 1976 ( 1.93kB) + Total ROM Size (Code + RO Data + RW Data) 9772 ( 9.54kB) ============================================================================== diff --git a/USER/Listings/os_cpu_a.lst b/USER/Listings/os_cpu_a.lst new file mode 100644 index 0000000..451d5ef --- /dev/null +++ b/USER/Listings/os_cpu_a.lst @@ -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 : 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 ; жϿƼĴ + 27 00000000 E000ED20 + NVIC_SYSPRI2 + EQU 0xE000ED20 ; ϵͳȼĴ( + 2) + 28 00000000 FFFF0000 + NVIC_PENDSV_PRI + EQU 0xFFFF0000 ; PendSVжϺϵͳ + ж + 29 00000000 ; (Ϊͣ0xff). + 30 00000000 10000000 + NVIC_PENDSVSET + EQU 0x10000000 ; жϵֵ. + + 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 ;ȡPRIMASKR0,R0 + Ϊֵ + 74 00000004 B672 CPSID I ;PRIMASK=1,ж(N + MIӲFAULT + Ӧ) + 75 00000006 4770 BX LR ; + 76 00000008 + 77 00000008 OS_CPU_SR_Restore + 78 00000008 F380 8810 MSR PRIMASK, R0 ;ȡR0PRIMASK, + R0Ϊ + 79 0000000C 4770 BX LR ; + 80 0000000E + 81 0000000E + 82 0000000E ;/****************************************************** + ******************************** + 83 0000000E ;* : OSStartHighRdy + 84 0000000E ;* + 85 0000000E ;* : ʹõеһ + 86 0000000E ;* + + + +ARM Macro Assembler Page 3 + + + 87 0000000E ;* : None + 88 0000000E ;* + 89 0000000E ;* ֵ: 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 ;лȼ + 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 ;* : OSCtxSw + 115 00000030 ;* + 116 00000030 ;* : л + 117 00000030 ;* + 118 00000030 ;* : None + 119 00000030 ;* + 120 00000030 ;* ֵ: None + 121 00000030 ;******************************************************* + ********************************/ + 122 00000030 + 123 00000030 OSCtxSw + 124 00000030 B430 PUSH {R4, R5} + 125 00000032 4C1A LDR R4, =NVIC_INT_CTRL ;PendSV + 쳣 (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 ;* : OSIntCtxSw + 133 0000003E ;* + 134 0000003E ;* : жϼл + 135 0000003E ;* + 136 0000003E ;* : None + 137 0000003E ;* + 138 0000003E ;* ֵ: None + 139 0000003E ;******************************************************* + ********************************/ + 140 0000003E + 141 0000003E OSIntCtxSw + 142 0000003E B430 PUSH {R4, R5} + 143 00000040 4C16 LDR R4, =NVIC_INT_CTRL ;PendSV + 쳣 (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 ;* : OSPendSV + 152 0000004E ;* + 153 0000004E ;* : OSPendSV is used to cause a context switch. + + 154 0000004E ;* + 155 0000004E ;* : None + 156 0000004E ;* + 157 0000004E ;* ֵ: 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 + PSPջ,Ժ + Ĵ,οCM3 + е˫ջ-ײ + + 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:\ǰʵϰ\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 diff --git a/USER/stm32f10x_it.c b/USER/stm32f10x_it.c index 6e7e2df..4370707 100644 --- a/USER/stm32f10x_it.c +++ b/USER/stm32f10x_it.c @@ -47,7 +47,9 @@ #include "stm32f10x_it.h" - +// ʹUCOSIIϵͳ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 + +// ûʹ UCOSII ϵͳŻжϷӳ +#else +// ʹ UCOSII ϵͳʱPendSV_HandlerѾ os-cpu_a.asm ļж +//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 */