Ucos_II2.52源码中文译注
转:一步一步教你使用uCOS-II

转:⼀步⼀步教你使⽤uCOS-II第⼀篇 UCOS介绍第⼀篇 UCOS介绍这个⼤家都知道。
呵呵。
考虑到咱们学习的完整性还是在这⾥唠叨⼀下。
让⼤家再熟悉⼀下。
⾼⼿们忍耐⼀下吧! uC/OS II(Micro Control Operation System Two)是⼀个可以基于ROM运⾏的、可裁减的、抢占式、实时多任务内核,具有⾼度可移植性,特别适合于微处理器和控制器,是和很多商业操作系统性能相当的实时操作系统(RTOS)。
为了提供最好的移植性能,uC/OS II最⼤程度上使⽤ANSI C语⾔进⾏开发,并且已经移植到近40多种处理器体系上,涵盖了从8位到64位各种CPU(包括DSP)。
uC/OS II可以简单的视为⼀个多任务调度器,在这个任务调度器之上完善并添加了和多任务操作系统相关的系统服务,如信号量、邮箱等。
其主要特点有公开源代码,代码结构清晰、明了,注释详尽,组织有条理,可移植性好,可裁剪,可固化。
内核属于抢占式,最多可以管理60个任务。
µC/OS-II 的前⾝是µC/OS,最早出⾃于1992 年美国嵌⼊式系统专家Jean brosse 在《嵌⼊式系统编程》杂志的5 ⽉和6 ⽉刊上刊登的⽂章连载,并把µC/OS 的源码发布在该杂志的B B S 上。
µC/OS 和µC/OS-II 是专门为计算机的嵌⼊式应⽤设计的,绝⼤部分代码是⽤C语⾔编写的。
CPU 硬件相关部分是⽤汇编语⾔编写的、总量约200⾏的汇编语⾔部分被压缩到最低限度,为的是便于移植到任何⼀种其它的CPU 上。
⽤户只要有标准的ANSI 的C交叉编译器,有汇编器、连接器等软件⼯具,就可以将µC/OS-II嵌⼈到开发的产品中。
µC/OS-II 具有执⾏效率⾼、占⽤空间⼩、实时性能优良和可扩展性强等特点,最⼩内核可编译⾄ 2KB 。
µC/OS-II 已经移植到了⼏乎所有知名的CPU 上。
ucosii中文书邵贝贝

u c o s i i中文书邵贝贝集团标准化工作小组 [Q8QX9QT-X8QQB8Q8-NQ8QJ8-M8QMN]第5章时间管理在节时钟节拍中曾提到,μC/OS-Ⅱ(其它内核也一样)要求用户提供定时中断来实现延时与超时控制等功能。
这个定时中断叫做时钟节拍,它应该每秒发生10至100次。
时钟节拍的实际频率是由用户的应用程序决定的。
时钟节拍的频率越高,系统的负荷就越重。
节讨论了时钟的中断服务子程序和节时钟节函数OSTimeTick——该函数用于通知μC/OS-Ⅱ发生了时钟节拍中断。
本章主要讲述五个与时钟节拍有关的系统服务:OSTimeDly()OSTimeDlyHMSM()OSTimeDlyResume()OSTimeGet()OSTimeSet()本章所提到的函数可以在文件中找到。
5.0任务延时函数,OSTimeDly()μC/OS-Ⅱ提供了这样一个系统服务:申请该服务的任务可以延时一段时间,这段时间的长短是用时钟节拍的数目来确定的。
实现这个系统服务的函数叫做OSTimeDly()。
调用该函数会使μC/OS-Ⅱ进行一次任务调度,并且执行下一个优先级最高的就绪态任务。
任务调用OSTimeDly()后,一旦规定的时间期满或者有其它的任务通过调用OSTimeDlyResume()取消了延时,它就会马上进入就绪状态。
注意,只有当该任务在所有就绪任务中具有最高的优先级时,它才会立即运行。
程序清单所示的是任务延时函数OSTimeDly()的代码。
用户的应用程序是通过提供延时的时钟节拍数——一个1 到65535之间的数,来调用该函数的。
如果用户指定0值[(1)],则表明用户不想延时任务,函数会立即返回到调用者。
非0值会使得任务延时函数OSTimeDly()将当前任务从就绪表中移除[(2)]。
接着,这个延时节拍数会被保存在当前任务的OS_TCB中[(3)],并且通过OSTimeTick()每隔一个时钟节拍就减少一个延时节拍数。
ucosii 内核core代码

******************************************************************************* *************************** uC/OS-II* The Real-Time Kernel* CORE FUNCTIONS** (c) Copyright 1992-2007, Micrium, Weston, FL* All Rights Reserved** File : OS_CORE.C* By : Jean J. Labrosse* Version : V2.86** LICENSING TERMS:* ---------------* uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.* If you plan on using uC/OS-II in a commercial product you need to contact Micri祄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 <ucos_ii.h>#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] = {0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00 to 0x0F */4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x10 to 0x1F */5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x20 to 0x2F */4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x30 to 0x3F */6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x40 to 0x4F */4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x50 to 0x5F */5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x60 to 0x6F */4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x70 to 0x7F */7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x80 to 0x8F */4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x90 to 0x9F */5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xA0 to 0xAF */4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xB0 to 0xBF */6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xC0 to 0xCF */4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xD0 to 0xDF */5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xE0 to 0xEF */4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* 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_STA T_EN > 0static void OS_InitTaskStat(void);#endifstatic 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 an ASCII string that will receive the name of the semaphore,* mutex, mailbox or queue. The string must be able to hold at least * OS_EVENT_NAME_SIZE characters.** 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_SIZE > 1)INT8U OSEventNameGet (OS_EVENT *pevent, INT8U *pname, INT8U *perr){INT8U len;#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0;#endif#if OS_ARG_CHK_EN > 0if (perr == (INT8U *)0) { /* Validate 'perr' */return (0);}if (pevent == (OS_EVENT *)0) { /* Is 'pevent' a NULL pointer? */*perr = OS_ERR_PEVENT_NULL;return (0);}if (pname == (INT8U *)0) { /* Is 'pname' a NULL pointer? */*perr = OS_ERR_PNAME_NULL;return (0);}#endifif (OSIntNesting > 0) { /* See if trying to call from an ISR */*perr = OS_ERR_NAME_GET_ISR;return (0);}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 (0);}OS_ENTER_CRITICAL();len = OS_StrCopy(pname, pevent->OSEventName); /* Copy name from OS_EVENT */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. The string must be able to hold at least * OS_EVENT_NAME_SIZE characters.** 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_SIZE > 1)void OSEventNameSet (OS_EVENT *pevent, INT8U *pname, INT8U *perr){INT8U len;#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0;#endif#if OS_ARG_CHK_EN > 0if (perr == (INT8U *)0) { /* Validate 'perr' */return;}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;}#endifif (OSIntNesting > 0) { /* 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();len = OS_StrLen(pname); /* Can we fit the string in the storage area? */if (len > (OS_EVENT_NAME_SIZE - 1)) { /* No */OS_EXIT_CRITICAL();*perr = OS_ERR_EVENT_NAME_TOO_LONG;return;}(void)OS_StrCopy(pevent->OSEventName, pname); /* Yes, copy name to the event control block */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 > 0))INT16U OSEventPendMulti (OS_EVENT **pevents_pend, OS_EVENT **pevents_rdy, void **pmsgs_rdy, INT16U timeout, INT8U *perr){OS_EVENT **pevents;OS_EVENT *pevent;#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0))OS_Q *pq;#endifBOOLEAN events_rdy;INT16U events_rdy_nbr;INT8U events_stat;#if (OS_CRITICAL_METHOD == 3) /* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0;#endif#if (OS_ARG_CHK_EN > 0)if (perr == (INT8U *)0) { /* Validate 'perr' */return (0);}if (pevents_pend == (OS_EVENT **)0) { /* Validate 'pevents_pend' */*perr = OS_ERR_PEVENT_NULL;return (0);}if (pevents_rdy == (OS_EVENT **)0) { /* Validate 'pevents_rdy' */*perr = OS_ERR_PEVENT_NULL;return (0);}if (pmsgs_rdy == (void **)0) { /* Validate 'pmsgs_rdy' */*perr = OS_ERR_PEVENT_NULL;return (0);}#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 > 0)case OS_EVENT_TYPE_SEM:break;#endif#if (OS_MBOX_EN > 0)case OS_EVENT_TYPE_MBOX:break;#endif#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0))case OS_EVENT_TYPE_Q:break;#endifcase OS_EVENT_TYPE_MUTEX:case OS_EVENT_TYPE_FLAG:default:*perr = OS_ERR_EVENT_TYPE;return (0);}pevents++;pevent = *pevents;}if (OSIntNesting > 0) { /* See if called from ISR ... */*perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */return (0);}if (OSLockNesting > 0) { /* See if called with scheduler locked ... */*perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */return (0);}/*$PAGE*/OS_ENTER_CRITICAL();events_rdy = OS_FALSE;events_rdy_nbr = 0;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 > 0)case OS_EVENT_TYPE_SEM:if (pevent->OSEventCnt > 0) { /* 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 > 0)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 > 0) && (OS_MAX_QS > 0))case OS_EVENT_TYPE_Q:pq = (OS_Q *)pevent->OSEventPtr;if (pq->OSQEntries > 0) { /* 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;#endifcase 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_STA T_PEND_OK:case OS_STA T_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_STA T_PEND_TO:default: /* ... remove task from events' wait lists */OS_EventTaskRemoveMulti(OSTCBCur, pevents_pend);break;}switch (OSTCBCur->OSTCBStatPend) {case OS_STA T_PEND_OK:switch (pevent->OSEventType) { /* Return event's message */#if (OS_SEM_EN > 0)case OS_EVENT_TYPE_SEM:*pmsgs_rdy++ = (void *)0; /* NO message returned for semaphores */break;#endif#if ((OS_MBOX_EN > 0) || \((OS_Q_EN > 0) && (OS_MAX_QS > 0)))case OS_EVENT_TYPE_MBOX:case OS_EVENT_TYPE_Q:*pmsgs_rdy++ = (void *)OSTCBCur->OSTCBMsg; /* Return received message */break;#endifcase 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_STA T_PEND_ABORT:*pmsgs_rdy++ = (void *)0; /* NO message returned for abort */*perr = OS_ERR_PEND_ABORT; /* Indicate that event aborted */break;case OS_STA T_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_STA T_RDY; /* Set task status to ready */OSTCBCur->OSTCBStatPend = OS_STA T_PEND_OK; /* Clear pend status */OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;OSTCBCur->OSTCBMsg = (void *)0; /* Clear task message */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 > 0) && (OS_MAX_FLAGS > 0)OS_FlagInit(); /* Initialize the event flag structures */#endif#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)OS_MemInit(); /* Initialize the memory manager */#endif#if (OS_Q_EN > 0) && (OS_MAX_QS > 0)OS_QInit(); /* Initialize the message queue structures */#endifOS_InitTaskIdle(); /* Create the Idle Task */#if OS_TASK_STA T_EN > 0OS_InitTaskStat(); /* Create the Statistic Task */#endif#if OS_TMR_EN > 0OSTmr_Init(); /* Initialize the Timer Manager */#endifOSInitHookEnd(); /* Call port specific init. code */#if OS_DEBUG_EN > 0OSDebugInit();#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 == 3 /* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0;#endifif (OSRunning == OS_TRUE) {OS_ENTER_CRITICAL();if (OSIntNesting > 0) { /* Prevent OSIntNesting from wrapping */OSIntNesting--;}if (OSIntNesting == 0) { /* Reschedule only if all ISRs complete ... */if (OSLockNesting == 0) { /* ... and not locked. */OS_SchedNew();if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];#if OS_TASK_PROFILE_EN > 0OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */#endifOSCtxSwCtr++; /* Keep track of the number of ctx switches */OSIntCtxSw(); /* Perform interrupt level ctx switch */}}}OS_EXIT_CRITICAL();}}/*$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 > 0void OSSchedLock (void){#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0;#endifif (OSRunning == OS_TRUE) { /* Make sure multitasking is running */OS_ENTER_CRITICAL();if (OSIntNesting == 0) { /* 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 > 0void OSSchedUnlock (void){#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0;#endifif (OSRunning == OS_TRUE) { /* Make sure multitasking is running */OS_ENTER_CRITICAL();if (OSLockNesting > 0) { /* Do not decrement if already 0 */OSLockNesting--; /* Decrement lock nesting level */if (OSLockNesting == 0) { /* See if scheduler is enabled and ... */if (OSIntNesting == 0) { /* ... 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_STA T_EN > 0void OSStatInit (void){#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0;#endifOSTimeDly(2); /* Synchronize with clock tick */OS_ENTER_CRITICAL();OSIdleCtr = 0L; /* Clear idle counter */OS_EXIT_CRITICAL();OSTimeDly(OS_TICKS_PER_SEC / 10); /* Determine MAX. idle counter。
ucosII中文教程

ucosII中文教程(转1)1.01 INCLUDES.H用户将注意到本书中所有的*.C 文件都包括了以下定义:#include "includes.h"INCLUDE.H 可以使用户不必在工程项目中每个*.C文件中都考虑需要什么样的头文件。
换句话说,INCLUDE.H是主头文件。
这样做唯一的缺点是INCLUDES.H中许多头文件在一些*.C文件的编译中是不需要的。
这意味着逐个编译这些文件要花费额外的时间。
这虽有些不便,但代码的可移植性却增加了。
本书中所有的例子使用一个共同的头文件INCLUDES.H,3个副本分别存放在\SOFTWARE\uCOS-II\EX1_x86L,\ SOFTWARE\uCOS-II\EX2_x86L,以及\SOFTWARE\uCOS-II\EX3_x86L 中。
当然可以重新编辑INCLUDES.H以添加用户自己的头文件。
1.02不依赖于编译的数据类型因为不同的微处理器有不同的字长,µC/OS-II的移植文件包括很多类型定义以确保可移植性(参见\SOFTWARE\uCOS-II\Ix86L\OS_CPU.H,它是针对80x86的实模式,在大模式下编译)。
µCOS-II不使用C语言中的short,int,long等数据类型的定义,因为它们与处理器类型有关,隐含着不可移植性。
笔者代之以移植性强的整数数据类型,这样,既直观又可移植,如表L1.1所示。
为了方便起见,还定义了浮点数数据类型,虽然µC/OS- II中没有使用浮点数。
程序清单L1.1 可移植型数据类型。
Typedef unsigned char BOOLEAN;Typedef unsigned char INT8U;Typedef signed char INT8S;Typedef unsigned int INT16U;Typedef signed int INT16S;Typedef unsigned long INT32U;Typedef signed long INT32S;Typedef float FP32;Typedef double FP64;#define BYTE INT8S#define UBYTE INT8U#define WORD INT16S#define UWORD INT16U#define LONG INT32S#define ULONG INT32U以INT16U数据类型为例,它代表16位无符号整数数据类型。
linux在TQ2440上移植5--移植串口传输协议

1、下载rzsz-3.48.tar.gz2、解压tar zxvf rzsz-3.48.tar.gz解压后的文件夹为scr进入scrcd scr3、修改交叉编译器vi MakefileCC = arm-linux-gcc编译 make posix4、把生成的可执行文件拷贝到文件系统的usr/bin下即可rb rc rx rz sb sx sz zcommand zcommandi5、重新制作yaffs2文件下载到板子即可mkyaffs2image fs.yaffs2 root_fs.bin传输文件到板子如下操作:[root@Timo /mnt]# rzrz ready. Type "sz file ..." to your modem programStarting zmodem transfer. Press Ctrl+C to cancel. Transferring S-Boot.bin...100% 15 KB 7 KB/s 00:00:02 0 Errors 妑z 3.48 01-27-98 finished.**** UNREGISTERED COPY *****Please read the License Agreement in rz.doc[root@Timo /mnt]# lsS-Boot.binQQ:917603226,danpianjikaifa@学习视频,电子元件选型指导,PLC 学习指导以及PLC 和DCS 周边产品开发韦东山老师的视频下载地址2440/file/f9beed69b0#.avi QQ:917603226/file/f9690fdc25#第2课QQ:917603226_GPIO实验.avi QQ:917603226/file/f91dd8f3b7#第3课QQ:917603226_存储管理器实验.aviQQ:917603226/file/f926fbcd6#第4课QQ:917603226_MMU实验.aviQQ:917603226/file/f98ccea8a4#第5课QQ:917603226_NAND_FLASH控制器.aviQQ:917603226/file/f9d6474d48#第6课QQ:917603226_中断控制器.aviQQ:917603226/file/f9657f8c96#.aviQQ:917603226/file/t9aa118d81#/file/t9e1c4044e#.aviQQ:917603226/file/t963cbbde3#第9课QQ:917603226第2节_u-boot分析之Makefile结构分析.aviQQ:917603226/file/t9de4dd17f#第9课QQ:917603226第3节_u-boot分析之源码第1阶段.aviQQ:917603226/file/t922115ff9#第9课QQ:917603226第3节_u-boot分析之源码第2阶段.aviQQ:917603226/file/t9114550f1#第9课QQ:917603226第4节_u-boot分析之u-boot命令实现.aviQQ:917603226/file/t99a6e0f29#第9课QQ:917603226第5节_u-boot分析_uboot启动内核.aviQQ:917603226/file/t9820a106e#第10课QQ:917603226第1节_内核启动流程分析之编译体验.aviQQ:917603226/file/t96fa8dc6f#第10课QQ:917603226第2节_内核启动流程分析之配置.aviQQ:917603226/file/t9aa094b45#第10课QQ:917603226第3节_内核启动流程分析之Makefile.aviQQ:917603226/file/t9f4a7ca84#第10课QQ:917603226第4节_内核启动流程分析之内核启动.aviQQ:917603226/file/t9dee089e3#第11课QQ:917603226第1节_构建根文件系统之启动第1个程序.aviQQ:917603226/file/t9d5172739#第11课QQ:917603226第2节_构建根文件系统之init进程分析.aviQQ:917603226/file/t9e7c46b97#第11课QQ:917603226第3节_构建根文件系统之busybox.aviQQ:917603226第 1 页/file/t921e24b83#.aviQQ:917603226/file/f5136718a8#动程序之概念介绍.aviQQ:917603226/file/f57b7907fe#动程序之LED驱动程序_编写编译.aviQQ:917603226 /file/f520effad5#第12课QQ:917603226第2.2节_字符设备驱动程序之LED驱动程序_测试改进.aviQQ:917603226 /file/f52e270acc#第12课QQ:917603226第2.3节_字符设备驱动程序之LED驱动程序_操作LED.aviQQ:917603226 /file/f51a13dc93#第12课QQ:917603226第3节_字符设备驱动程序之查询方式的按键驱第 2 页QQ:917603226,danpianjikaifa@学习视频,电子元件选型指导,PLC 学习指导以及PLC 和DCS 周边产品开发TQ2440开发大全下载linux-2.6.35.3在TQ2440上移植1--建立自己的板子.pdf/source/3227941linux在TQ2440上移植2--Nandflash驱动,MTD分区.pdf/source/3227943linux在TQ2440上移植3--yaffs2+文件系统移植.pdf/source/3227944linux在TQ2440上移植4--yaffs2文件系统制作.pdf/source/3227947linux在TQ2440上移植5--移植串口传输协议.pdf/source/3227948linux在TQ2440上移植6--完善串口驱动.pdf/source/3227950linux在TQ2440上移植7--完善实时时钟RTC.pdf/source/3227951linux在TQ2440上移植8--启动看门狗+.pdf/source/3227965linux在TQ2440上移植9--添加触摸屏.pdf/source/3227952linux在TQ2440上移植10--完善网卡驱动.pdf/source/3227955linux在TQ2440上移植11--完善声卡驱动.pdf/source/3227956linux在TQ2440上移植12--完善SDMMC卡驱动.pdf/source/3227958bootloader编写指南.pdf/source/3227040第 1 页U-boot1.1.6的移植step by step(TQ2440).pdf/source/3227044U-boot1[1][1][1].1.6的移植(TQ2440).pdf/source/3227049/source/3227049U-BOOT-2010.06移植到TQ2440.pdf/source/3227052uboot讲义.pdf/source/3227054uboot阶段1(汇编部分)详细分析.pdf/source/3227057uboot使用说明.pdf/source/3227058Uboot学习笔记.pdf/source/3227060U-boot源代码分析.pdf/source/3227062Uboot源码阅读笔记.pdf/source/3227064在uboot上制作logo的实验.ppt/source/3227067UBOOT之Makefile详解.doc/source/3227068基于TQ2440和Qt的Mp3设计.doc/source/3227074ARM9硬件接口学习之一_WatchDog.pdf/source/3229021ARM9硬件接口学习之二_RTC.pdf/source/3229025.第 2 页ARM9硬件接口学习之三_GPIO.pdf/source/3229026ARM9硬件接口学习之四_CLOCK.pdf/source/3229028ARM9硬件接口学习之五_UART.pdf/source/3229030tq2440ARM学习1/source/3229044ARM学习3流水灯实验.pdf/source/3229048ARM学习4在ADS1.2中新建自己的工程.pdf/source/3229051ARM学习5实现电子相框功能及LCD屏显试验中两个问题/source/3229053ARM学习6LCD屏显实现科比投篮的动画.pdf/source/3229057ARM学习7对于科比投篮实验的轨迹分析.pdf/source/3229058ARM学习8对于画线函数Glib_Line算法的研究.pdf/source/3229059ARM学习14S3C2440 IO口的总结.pdf/source/3229060[原创]自己动手编写嵌入式Bootloader之(1).pdf/source/3230747[原创]自己动手编写嵌入式Bootloader之(2).pdf/source/3230136[原创]自己动手编写嵌入式Bootloader之(3).pdf/source/3230137uC_OS-II实验指导书.pdf第 3 页/source/3231958Ucos_II2.52 源码中文译注.pdf/source/3231960UCOS-II API 参考手册.pdf/source/3231962第 4 页TQ2440裸机开发试验大全TQ2440裸机开发试验之ADC/source/3311703TQ2440裸机开发试验之ebook/source/3311704TQ2440裸机开发试验之interrupt/source/3311708TQ2440裸机开发试验之Mmu_Nand/source/3311761TQ2440裸机开发试验之Mmu_Nand/source/3311763TQ2440裸机开发试验之Nand_1/source/3311765TQ2440裸机开发试验之power_stop/source/3311770TQ2440裸机开发试验之PWM/source/3311772TQ2440裸机开发试验之RTC_LCD/source/3311777TQ2440裸机开发试验之Touch_Panel/source/3311778TQ2440裸机开发试验之UART/source/3311780TQ2440裸机开发试验之write_bios/source/3311783第1篇基础篇第1章Linux简介1.1 Linux系统概述1.2 Linux图形界面操作1.3 Linux字符界面操作1.4 Shell脚本编程基础第1章Linux简介.pdf/source/3312215新手学linux C编程第1章视频/v_show/id_XMjcwMDAxNjYw.html 第2章C语言基础2.1 C语言概述2.2 数据类型、运算符和表达式2.3 基本语句2.4 数组2.5 预处理第2章C语言基础.pdf/source/3312221新手学linux C编程第2章配套源码,可成功运行.rar /source/3312253新手学linux C编程第2章视频/v_show/id_XMjcwMDAxODY0.html第3章指针、函数及自定义数据类型3.1 指针.3.2 函数3.3 结构体、共用体和枚举第3章指针、函数及自定义数据类型.pdf/source/3312229新手学linux C编程第3章配套源码,可成功运行.rar /source/3312254新手学linux C编程第3章视频/v_show/id_XMjcwMDAyMTAw.html第4章数据结构4.1 线性表4.2 栈4.3 队列4.4 二叉树4.5 查找4.6 排序第4章数据结构.pdf/source/3312230新手学linux C编程第4章配套源码,可成功运行.rar /source/3312255第5章文本编辑器5.1 vi编辑器的基本使用5.2 vi编辑器之程序编辑5.3 emacs编辑器的基本使用第5章文本编辑器.pdf/source/3312231新手学linux C编程第5章视频/v_show/id_XMjcwMDA0ODI4.html第6章GCC编译器6.1 GCC简介6.2 GCC的安装6.3 GCC常用选项第6章GCC编译器.pdf/source/3312234新手学linux C编程第6章配套源码,可成功运行.rar /source/3312256新手学linux C编程第6章视频/v_show/id_XMjcwMDA1OTA4.html第7章调试工具7.1 GDB简介及安装7.2 GDB常用命令7.3 GDB调试实例第7章调试工具.pdf/source/3312235新手学linux C编程第7章视频/v_show/id_XMjcwMDA2MDI0.html第9章LinuxC基本应用9.1 字符串操作9.2 数据转换9.3 内存分配与释放9.4 时间和日期9.5 其他应用第9章Linux C基本应用.pdf/source/3312239新手学linux C编程第9章视频/v_show/id_XMjcwMDA2Mjk2.html第10章文件系统缔程10.1 Linux文件系统简介10.2 文件的基本操作10.3 文件的属性10.4 目录文件的操作第10章文件系统编程.pdf/source/3312240新手学linux C编程第10章配套源码,可成功运行.rar /source/3312260新手学linux C编程第10章视频/v_show/id_XMjcwMDA2NDMy.html第11章标准输入输出11.1 标准输入输出的基本操作11.2 非格式化输入输出11.3 格式化输入输出第11章标准输入输出.pdf/source/3312242新手学linux C编程第11章配套源码,可成功运行.rar /source/3312261新手学linux C编程第11章视频/v_show/id_XMjcwMDA2NTYw.html第12章进程操作12.1 进程的概念12.2 Linux进程12.3 进程创建与控制12.4 守护进程第12章进程操作.pdf/source/3312246新手学linux C编程第12章配套源码,可成功运行.rar /source/3312263第13章进程间通信13.1 管道13.2 信号13.3 消息队列13.4 信号量13.5 共享内存第13章进程间通信.pdf/source/3312247新手学linux C编程第13章配套源码,可成功运行.rar /source/3312266新手学linux C编程第13章视频/v_show/id_XMjcwMDA3NDU2.html第14章多线程编程14.1 线程的基本概念14.2 线程的基本操作14.3 线程的同步第14章多线程编程.pdf/source/3312248新手学linux C编程第14章配套源码,可成功运行.rar /source/3312268新手学linux C编程第14章视频/v_show/id_XMjcwMDA3NTU2.html第15章网络编程15.1 网络基础知识15.2 套接字编程基础15.3 服务器模型15.4 域名系统第15章网络编程.pdf/source/3312249新手学linux C编程第15章配套源码,可成功运行.rar /source/3312269新手学linux C编程第15章视频/v_show/id_XMjcwMDA4ODky.html第16章Linux GUI编程16.1 GTK+/Gnome开发简介16.2 常用GTK+构件16.3 GUI生成器Glade第16章Linux GUI编程.pdf/source/3312250新手学linux C编程第16章配套源码,可成功运行.rar/source/3312270新手学linux C编程第16章视频/v_show/id_XMjcwMDA5MTAw.html第17章案例1:Linux命令实现17.1 功能与参数介绍17.2 主函数代码分析17.3 其他函数代码分析第17章案例1:Linux命令实现.pdf/source/3312251新手学linux C编程第17章配套源码,可成功运行.rar /source/3312271新手学linux C编程第17章视频/v_show/id_XMjcwMDA5MjI4.html第18章案例2:客户端/服务器端程序18.1 服务器端程序设计18.2 客户端程序设计第18章案例2:客户端.pdf/source/3312252新手学linux C编程第18章配套源码,可成功运行.rar /source/3312273新手学linux C编程第18章视频/v_show/id_XMjcwMDA5Mzc2.htmlallegro使用经验大全allegro16[1].3版之建立板框(很精彩的图文解释).pdf/source/3313999allogro布线及检查规则设置.pdf/source/3314028allegro中怎么样画原形的板框!.pdf/source/3314027Allegro中如何导入DXF文件.pdf/source/3314024Allegro中丝印及文字的调整管理技巧.pdf/source/3314025allegro怎么样复制板框到另外一块中.pdf/source/3314022Allegro修改元件封装管脚序号.pdf/source/3314020allegro导出dxf文件的方法与步骤.pdf/source/3314018allegro板框设置方法.pdf/source/3314015Allegro 电源,地层分割方法.pdf/source/3314011allegro 导入DXF时/source/3314009allegro allegro使用汇总.pdf/source/3314001怎样在ALLEGRO PCB中修改Net及添加Net.pdf/source/3314037在用ALLEGRO自作PCB时出现过过孔上焊盘而不报错的现象.pdf /source/3314034如何在allegro中更换元件封装.pdf/source/3314032如何看到pin number,并修改它.pdf/source/3314030Cadence中的allegro软件的sub-drawing的用法.pdf/source/3314029allogro布线及检查规则设置.pdf/source/3314028第 1 页做C++的朋友过来看看了啊WINDOWS核心编程.rar/source/3314308vs2008中文教程.rar/source/3314303Visual C++技术内幕第5版.rar/source/3314299MFC深入浅出.rar/source/3314291C++高级参考手册/source/3314289C++Primer第四版中文版(电子版).rar/source/3314286C#完全手册.pdf/source/3314282第 1 页(VB精彩应用之实例001)仿瑞星小狮子界面.rar/source/3321477(VB精彩应用之实例002)控制其他程序成为自己的子窗体.rar/source/3321478(VB精彩应用之实例003)在任务栏上加上程序图标.rar/source/3321479(VB精彩应用之实例004)获取运行程序(控件)名称和内容.rar/source/3321481(VB精彩应用之实例005)锁住Windows直到输入正确的口令.rar/source/3321483(VB精彩应用之实例006)禁止创建快捷方式出现“快捷方式”四个字.rar /source/3321484(VB精彩应用之实例007)更改墙纸显示方式.rar/source/3321486(VB精彩应用之实例008)在任务栏中禁用右键快捷菜单.rar/source/3321488(VB精彩应用之实例009)判断桌面大小.rar/source/3321492(VB精彩应用之实例010)改变Windows图标大小.rar/source/3321495(VB精彩应用之实例011)修改桌面图标背景.rar/source/3321496(VB精彩应用之实例012)动态卷帘式窗体演示.rar/source/3321498(VB精彩应用之实例013)自动更换墙纸.rar/source/3321499(VB精彩应用之实例014)设置窗口在屏幕中的位置.rar/source/3321501(VB精彩应用之实例015)设置窗口置前、置后.rar/source/3321502VB精彩应用之实例016)闪烁窗体标题栏.rar/source/3321504VB精彩应用之实例017)智能窗体放大器.rar/source/3321505(VB精彩应用之实例019)椭圆形窗体.rar/source/3321509(VB精彩应用之实例020)透明窗体.rar/source/3321510(VB精彩应用之实例021)透明窗体动画.rar/source/3321512(VB精彩应用之实例022)动态半透明窗体.rar/source/3321513(VB精彩应用之实例023)关于窗体.rar/source/3321514(VB精彩应用之实例024)MDI窗体.rar/source/3321515(VB精彩应用之实例025)背景渐变的窗体.rar第 1 页/source/3321516(VB精彩应用之实例026)窗体动态形状转换.rar/source/3321517(VB精彩应用之实例027)关闭窗口前提示.rar/source/3321518(实例028)窗体文字效果.rar/source/3321520VB精彩应用之实例029)鼠标右键弹出菜单.rar/source/3321521(VB精彩应用之实例030)带图标的菜单.rar/source/3321522(VB精彩应用之实例032)屏蔽关闭、最大化、最小化按钮.rar /source/3321524(VB精彩应用之实例033)显示多列菜单.rar/source/3321525(VB精彩应用之实例034)List列表拒绝添加重复信息.rar/source/3321527(VB精彩应用之实例035)控件大小随窗体的改变而改变.rar /source/3321530VB精彩应用之实例036)在TextBox中设置新的系统功能菜单.rar /source/3321531(VB精彩应用之实例037)动态改变控件尺寸.rar/source/3321532(VB精彩应用之实例038)程序运行时智能增减控件.rar/source/3321533第 2 页。
uCOS-II源码分析

uC/OS-II源码分析(一)下载地址:/它的特点:1)开源,2)可移植性,绝大部分代码用C写,硬件相关部分用汇编写,3可固化,4)可剪裁,这通过条件编译实现,使用#define语句定义所需要的功能。
5)可剥夺性(总是运行就绪条件下优先级最高的任务),6)多任务(可以管理64个任务,其中保留8个给uC/OS-II,因此用户最多可有56个任务,每个任务优先级不同,也就意味着不支持时间片轮转调度法,因为这种方法适合于优先级平等的任务)。
7)可确定性。
函数调度和服务执行时间具有确定性,除了OSTimeTick()和某些事件标志服务,系统服务执行时间不依赖用户应用程序任务数目的多少。
8)任务栈。
允许每个任务自己单独的栈空间不同,可以使用栈空间检验函数确定所需要的栈空间大小。
9)系统服务。
提供信号量,互斥型信号量,事件标志,消息邮箱,消息队列,块大小固定的内存申请与释放,时间管理函数等服务。
10)中断管理。
中断嵌套层数最多可达到255层。
11)稳定性和可靠性。
OSInit()函数用来初始化内核,必须首先调用。
建立两个任务:空闲任务(其他任务都未就绪时运行),统计任务(计算CPU的利用率).****************************************************************** 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().*****************************************************************void OSInit (void){OSInitHookBegin();/* 调用用户特定的初始化代码(通过一个接口函数实现用户要求的插件式进入系统中)*/OS_InitMisc();/* 初始化变量*/OS_InitRdyList();/* 初始化就绪列表*/OS_InitTCBList();/* 初始化OS_TCB空闲列表*/OS_InitEventList();/* 初始化OS_EVENT空闲列表*/#if(OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)//允许事件标志OS_FlagInit();/* 初始化事件标志结构*/#endif#if(OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)//允许内存管理OS_MemInit();/* 初始化内存管理器*/#endif#if(OS_Q_EN > 0) && (OS_MAX_QS > 0)//允许消息队列OS_QInit();/* 初始化消息队列结构*/#endifOS_InitTaskIdle();/*创建空闲任务*/#if OS_TASK_STAT_EN > 0OS_InitTaskStat();/* 创建统计任务*/#endif#if OS_TMR_EN > 0//允许时间管理OSTmr_Init();/* 初始化时间管理器*/#endifOSInitHookEnd();/*调用用户特定的初始化代码(参考OSInitHookBegin())*/#if OS_DEBUG_EN > 0//允许DebugOSDebugInit();//初始化调试器#endif}******************************************************************************************** * Description: This function is called by OSInit() to initialize miscellaneous variables.********************************************************************************************static void OS_InitMisc (void){#if OS_TIME_GET_SET_EN > 0OSTime = 0L; /* 32位的系统时钟清零*/#endifOSIntNesting = 0; /* 中断嵌套层数计数器清零*/OSLockNesting = 0; /* 调度器锁的嵌套层数计数器清零*/ OSTaskCtr = 0; /* 任务数清零*/OSRunning = OS_FALSE; /*指明多任务未开始*/OSCtxSwCtr = 0; /* 任务切换次数计数器清零*/OSIdleCtr = 0L; /*32位空闲计数器清零*/#if OS_TASK_STAT_EN > 0 /*运行统计任务*/OSIdleCtrRun = 0L;OSIdleCtrMax = 0L;OSStatRdy = OS_FALSE; /* 统计任务未就绪*/#endif}空闲任务和统计任务建立的代码基本一样,只是统计任务的优先级比空闲任务大1,******************************************************************************************** * Description: This function creates the Idle Task.********************************************************************************************static void OS_InitTaskIdle (void){#if OS_TASK_NAME_SIZE > 7 //INT8U err;#endif#if OS_TASK_CREATE_EXT_EN > 0 //使用扩展的OSTaskCreateExt来创建#if OS_STK_GROWTH == 1 //任务堆栈从底部向顶部增长的方向有两种:表示从大到小,表示从小到大(void)OSTaskCreateExt(OS_TaskIdle,(void *)0, /* 没有参数传给OS_TaskIdle() */&OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /*设置堆栈顶*/OS_TASK_IDLE_PRIO, /* 优先级设置为最低*/OS_TASK_IDLE_ID, //设置ID&OSTaskIdleStk[0], /* 设置栈底*/OS_TASK_IDLE_STK_SIZE, //设置栈大小(void *)0, /* 没有TCB扩展数据结构OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* 允许堆栈检测和清空堆栈*/#else(void)OSTaskCreateExt(OS_TaskIdle,(void *)0, /* No arguments passed to OS_TaskIdle() */&OSTaskIdleStk[0], /* Set Top-Of-StackOS_TASK_IDLE_PRIO, /* Lowest priority levelOS_TASK_IDLE_ID,&OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Bottom-Of-Stack */OS_TASK_IDLE_STK_SIZE,(void *)0, /* No TCB extensionOS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack check ing + clear stack */#endif#else//使用不带扩展性的OSTaskCreate创建#if OS_STK_GROWTH == 1(void)OSTaskCreate(OS_TaskIdle,(void *)0,&OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1],OS_TASK_IDLE_PRIO);#else(void)OSTaskCreate(OS_TaskIdle,(void *)0,&OSTaskIdleStk[0],OS_TASK_IDLE_PRIO);#endif#endif//设置任务名称#if OS_TASK_NAME_SIZE > 14OSTaskNameSet(OS_TASK_IDLE_PRIO, (INT8U *)"uC/OS-II Idle", &err); #else#if OS_TASK_NAME_SIZE > 7OSTaskNameSet(OS_TASK_IDLE_PRIO, (INT8U *)"OS-Idle", &err);#endif#endif}uC/OS-II源码分析(二)在真正开始分析源代码前,先来看使用uC/OS-II的三个例子1)使用信号量#define TASK_STK_SIZE 512 /* 每个任务堆栈的大小(以字计算)*/ #define N_TASKS 10 /* 任务数*/OS_STK TaskStk[N_TASKS][TASK_STK_SIZE]; /*任务堆栈*/OS_STK TaskStartStk[TASK_STK_SIZE]; //开始任务的堆栈char TaskData[N_TASKS]; /*传给每个任务的数据*/OS_EVENT *RandomSem; //互斥型信号量void main (void){PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK); /*清空屏幕*/OSInit(); /* 初始化uC/OS-II*/PC_DOSSaveReturn(); /* 保存环境以便稍后可以返回DOS 环境*/PC_VectSet(uCOS, OSCtxSw); /*设置uC/OS-II的切换处理函数*/RandomSem = OSSemCreate(1); /* 建立一个信号量*/OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0);//创建第一个任务,优先级设置为最大值OSStart(); /* 开始多任务*/}void TaskStart (void *pdata){#if OS_CRITICAL_METHOD == 3 /* 为CPU的状态寄存器分配内存*/OS_CPU_SR cpu_sr;#endifchar s[100];INT16S key;pdata = pdata; /* 这步是为了防止编译错误*/TaskStartDispInit(); /* 初始化显示屏*/OS_ENTER_CRITICAL();PC_VectSet(0x08, OSTickISR); /*替换机器的时钟中断函数为uC/OS-II所需要的中断函数*/PC_SetTickRate(OS_TICKS_PER_SEC); /* 调整时钟频率*/OS_EXIT_CRITICAL();OSStatInit(); /* 初始化统计任务*/TaskStartCreateTasks(); /*创建其他任务*/ for (;;) {TaskStartDisp();if (PC_GetKey(&key) == TRUE) { /* 是否按键*/if (key == 0x1B) { /* ESCAPE按下了*/PC_DOSReturn(); /* 返回DOS*/}}OSCtxSwCtr = 0; /* 切换次数计数器清零*/OSTimeDlyHMSM(0, 0, 1, 0); /*挂起秒,让给其他任务运行*/ }}static void TaskStartCreateTasks (void){INT8U i;for (i = 0; i < N_TASKS; i++) { /* 创建N_TASKS个任务*/TaskData[i] = '0' + i; /* 每个任务显示其数据*/OSTaskCreate(Task, (void *)&TaskData[i], &TaskStk[i][TASK_STK_SIZE - 1 ], i + 1);}}void Task (void *pdata){INT8U x;INT8U y;INT8U err;for (;;) {OSSemPend(RandomSem, 0, &err); /* 获取信号量*/x = random(80); /* 计算X坐标*/y = random(16); /* 计算Y坐标*/OSSemPost(RandomSem); /* 释放信号量*//* Display the task number on the screen */PC_DispChar(x, y + 5, *(char *)pdata, DISP_FGND_BLACK + DISP_BGND_ LIGHT_GRAY);OSTimeDly(1); /* 挂起秒,让给其他任务运行*/}}2)使用消息邮箱#define TASK_STK_SIZE 512#define TASK_START_ID 0 /* 任务ID*/#define TASK_CLK_ID 1#define TASK_1_ID 2#define TASK_2_ID 3#define TASK_3_ID 4#define TASK_4_ID 5#define TASK_5_ID 6#define TASK_START_PRIO 10 /* 任务优先级*/#define TASK_CLK_PRIO 11#define TASK_1_PRIO 12#define TASK_2_PRIO 13#define TASK_3_PRIO 14#define TASK_4_PRIO 15#define TASK_5_PRIO 16OS_STK TaskStartStk[TASK_STK_SIZE];OS_STK TaskClkStk[TASK_STK_SIZE];OS_STK Task1Stk[TASK_STK_SIZE];OS_STK Task2Stk[TASK_STK_SIZE];OS_STK Task3Stk[TASK_STK_SIZE];OS_STK Task4Stk[TASK_STK_SIZE];OS_STK Task5Stk[TASK_STK_SIZE];OS_EVENT *AckMbox; /* 任务和使用的消息邮箱*/ OS_EVENT *TxMbox;void main (void){OS_STK *ptos;OS_STK *pbos;INT32U size;PC_DispClrScr(DISP_FGND_WHITE);OSInit();PC_DOSSaveReturn();PC_VectSet(uCOS, OSCtxSw);PC_ElapsedInit();ptos = &TaskStartStk[TASK_STK_SIZE - 1]; pbos = &TaskStartStk[0];size = TASK_STK_SIZE;OSTaskStkInit_FPE_x86(&ptos, &pbos, &size); OSTaskCreateExt(TaskStart,(void *)0,ptos,TASK_START_PRIO,TASK_START_ID,pbos,size,(void *)0,OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); OSStart();}void TaskStart (void *pdata){#if OS_CRITICAL_METHOD == 3OS_CPU_SR cpu_sr;#endifINT16S key;pdata = pdata;TaskStartDispInit();OS_ENTER_CRITICAL();PC_VectSet(0x08, OSTickISR);PC_SetTickRate(OS_TICKS_PER_SEC);OS_EXIT_CRITICAL();OSStatInit();AckMbox = OSMboxCreate((void *)0); /* 创建两个消息邮箱*/ TxMbox = OSMboxCreate((void *)0);TaskStartCreateTasks();for (;;) {TaskStartDisp();if (PC_GetKey(&key)) {if (key == 0x1B) {PC_DOSReturn();}}OSCtxSwCtr = 0;OSTimeDly(OS_TICKS_PER_SEC);}}void Task1 (void *pdata){INT8U err;OS_STK_DATA data; /* 任务堆栈数据*/INT16U time;INT8U i;char s[80];pdata = pdata;for (;;) {for (i = 0; i < 7; i++) {PC_ElapsedStart();err = OSTaskStkChk(TASK_START_PRIO + i, &data);//执行堆栈检查time = PC_ElapsedStop();if (err == OS_NO_ERR) {sprintf(s, "%4ld %4ld %4ld %6d",data.OSFree + data.OSUsed,data.OSFree,data.OSUsed,time);PC_DispStr(19, 12 + i, s, DISP_FGND_BLACK + DISP_BGND_LIGHT_G RAY);}}OSTimeDlyHMSM(0, 0, 0, 100); /* 挂起mS*/}}void Task4 (void *data){char txmsg;INT8U err;data = data;txmsg = 'A';for (;;) {OSMboxPost(TxMbox, (void *)&txmsg); /* 发消息给Task #5*/OSMboxPend(AckMbox, 0, &err); /* 等待Task #5的应答消息*/txmsg++; /*下一个要发的消息数据*/if (txmsg == 'Z') {txmsg = 'A'; /* 循环发送A-Z*/}}}void Task5 (void *data){char *rxmsg;INT8U err;data = data;for (;;) {rxmsg = (char *)OSMboxPend(TxMbox, 0, &err); /* 等待来自Task #4的数据*/PC_DispChar(70, 18, *rxmsg, DISP_FGND_YELLOW + DISP_BGND_BLUE); OSTimeDlyHMSM(0, 0, 1, 0); /* 挂起秒,让给其他任务运行*/OSMboxPost(AckMbox, (void *)1); /*发送接收到数据的应答消息*/}}运行结果:3)使用消息队列#define TASK_STK_SIZE 512#define TASK_START_ID 0#define TASK_CLK_ID 1#define TASK_1_ID 2#define TASK_2_ID 3#define TASK_3_ID 4#define TASK_4_ID 5#define TASK_5_ID 6#define TASK_START_PRIO 10#define TASK_CLK_PRIO 11#define TASK_1_PRIO 12#define TASK_2_PRIO 13#define TASK_3_PRIO 14#define TASK_4_PRIO 15#define TASK_5_PRIO 16#define MSG_QUEUE_SIZE 20 /* 消息队列大小*/ typedef struct {char TaskName[30];INT16U TaskCtr;INT16U TaskExecTime;INT32U TaskTotExecTime;} TASK_USER_DATA;OS_STK TaskStartStk[TASK_STK_SIZE];OS_STK TaskClkStk[TASK_STK_SIZE];OS_STK Task1Stk[TASK_STK_SIZE];OS_STK Task2Stk[TASK_STK_SIZE];OS_STK Task3Stk[TASK_STK_SIZE];OS_STK Task4Stk[TASK_STK_SIZE];OS_STK Task5Stk[TASK_STK_SIZE];TASK_USER_DATA TaskUserData[7];OS_EVENT *MsgQueue; /*消息队列指针*/ void *MsgQueueTbl[20]; /*消息存储*/void main (void){PC_DispClrScr(DISP_BGND_BLACK);OSInit();PC_DOSSaveReturn();PC_VectSet(uCOS, OSCtxSw);PC_ElapsedInit();strcpy(TaskUserData[TASK_START_ID].TaskName, "StartTask"); OSTaskCreateExt(TaskStart,(void *)0,&TaskStartStk[TASK_STK_SIZE - 1],TASK_START_PRIO,TASK_START_ID,&TaskStartStk[0],TASK_STK_SIZE,&TaskUserData[TASK_START_ID],0);OSStart();}void TaskStart (void *pdata){#if OS_CRITICAL_METHOD == 3OS_CPU_SR cpu_sr;#endifINT16S key;pdata = pdata;TaskStartDispInit();OS_ENTER_CRITICAL();PC_VectSet(0x08, OSTickISR);PC_SetTickRate(OS_TICKS_PER_SEC);OS_EXIT_CRITICAL();OSStatInit();MsgQueue = OSQCreate(&MsgQueueTbl[0], MSG_QUEUE_SIZE); /*创建消息队列,大小为*/TaskStartCreateTasks();for (;;) {TaskStartDisp();if (PC_GetKey(&key)) {if (key == 0x1B) {PC_DOSReturn();}}OSCtxSwCtr = 0;OSTimeDly(OS_TICKS_PER_SEC);}}void Task1 (void *pdata){char *msg;INT8U err;pdata = pdata;for (;;) {msg = (char *)OSQPend(MsgQueue, 0, &err);//从消息队列中取消息PC_DispStr(70, 13, msg, DISP_FGND_YELLOW + DISP_BGND_BLUE);OSTimeDlyHMSM(0, 0, 0, 100);}}void Task2 (void *pdata)char msg[20];pdata = pdata;strcpy(&msg[0], "Task 2");for (;;) {OSQPost(MsgQueue, (void *)&msg[0]);//发送消息到队列中 OSTimeDlyHMSM(0, 0, 0, 500);}}void Task3 (void *pdata){char msg[20];pdata = pdata;strcpy(&msg[0], "Task 3");for (;;) {OSQPost(MsgQueue, (void *)&msg[0]);//发送消息到队列中 OSTimeDlyHMSM(0, 0, 0, 500);}}void Task4 (void *pdata){char msg[20];pdata = pdata;strcpy(&msg[0], "Task 4");for (;;) {OSQPost(MsgQueue, (void *)&msg[0]);//发送消息到队列中 OSTimeDlyHMSM(0, 0, 0, 500);}}void OSTaskStatHook (void)char s[80];INT8U i;INT32U total;INT8U pct;total = 0L; /* Totalize TOT. EXEC. TIME for each t askfor (i = 0; i < 7; i++) {total += TaskUserData[i].TaskTotExecTime;DispTaskStat(i); /* Display task data }if (total > 0) {for (i = 0; i < 7; i++) { /* Derive percentage of each task */pct = 100 * TaskUserData[i].TaskTotExecTime / total;sprintf(s, "%3d %%", pct);PC_DispStr(62, i + 11, s, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRA Y);}}if (total > 1000000000L) { /* Reset total time counters at 1 billionfor (i = 0; i < 7; i++) {TaskUserData[i].TaskTotExecTime = 0L;}}}void OSTaskSwHook (void){INT16U time;TASK_USER_DATA *puser;time = PC_ElapsedStop(); /* This task is donePC_ElapsedStart(); /* Start for next task puser = OSTCBCur->OSTCBExtPtr; /* Point to used dataif (puser != (TASK_USER_DATA *)0) {puser->TaskCtr++; /* Increment task counter puser->TaskExecTime = time; /* Update the task's execution timepuser->TaskTotExecTime += time; /* Update the task's total executi on time}}运行结果:uC/OS-II源码分析(三)首先来了解下实时系统的基本概念:1)临界区,共享资源,任务(类似于进程),任务切换,任务调度,可剥夺型内核,可重入函数,动态优先级调度,2)如何处理优先级反转问题。
uCOS-II实时操作系统内核源代码注释

/*********************************************************************************************************** uC/OS-II* 实时操作内核* 内存管理** (c) 版权 1992-2002, Jean J. Labrosse, Weston, FL* All Rights Reserved** 文件名 : OS_MEM.C* 作者 : Jean J. Labrosse* 注释 : 彭森 2007/9/2**********************************************************************************************************/#ifndef OS_MASTER_FILE#include "includes.h"#endif#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)/*********************************************************************************************************** 创建一个内存分区** 说明 : 创建一个固定大小的内存分区,这个内存分区通过uC/OS-II管理。
** 参数 : addr 内存分区的起始地址** nblks 来自分区的内存块的数目.** blksize 每个内存分区中的内存块的大小.** err 指向一个变量包含错误的信息,这个信息通过这个函数或其他来设置:** OS_NO_ERR 内存分区创建正确返回值. * OS_MEM_INVALID_ADDR 指定的是无效地址作为分区的内存存储空间* OS_MEM_INVALID_PART 没有未使用的有用的分区* OS_MEM_INVALID_BLKS 使用者指定一个无效的内存块(必须 >= 2)* OS_MEM_INVALID_SIZE 使用者指定一个无效的内存空间值* (必须大于指针的空间大小) * 返回值 : != (OS_MEM *)0 分区被创建* == (OS_MEM *)0 分区没有被创建由于无效的参数,没有未使用的分区可用**********************************************************************************************************/OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err){#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register 为CPU状态寄存器分配存储空间 */OS_CPU_SR cpu_sr;#endifOS_MEM *pmem;INT8U *pblk;void **plink;INT32U i;#if OS_ARG_CHK_EN > 0if (addr == (void *)0) { /* Must pass a valid address for the memory part. 必须是一个有效的内存部分*/*err = OS_MEM_INVALID_ADDR;return ((OS_MEM *)0);}if (nblks < 2) { /* Must have at least 2 blocks per partition 每个分区至少有两个分区*/*err = OS_MEM_INVALID_BLKS;return ((OS_MEM *)0);}if (blksize < sizeof(void *)) { /* Must contain space for at least a pointer 必须包含空间至少有一个指针*/*err = OS_MEM_INVALID_SIZE;return ((OS_MEM *)0);}#endifOS_ENTER_CRITICAL();pmem = OSMemFreeList; /* Get next free memory partition 得到下一个未使用的内存分区*/if (OSMemFreeList != (OS_MEM *)0) { /* See if pool offree partitions was empty 查看是否有未使用的分区空间是空的*/OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;}OS_EXIT_CRITICAL();if (pmem == (OS_MEM *)0) { /* See if we have a memory partition 查看是否我们有一个内存分区*/*err = OS_MEM_INVALID_PART;return ((OS_MEM *)0);}plink = (void **)addr; /* Create linked list of free memory blocks 创建未使用的内存块的可连接的列表*/pblk = (INT8U *)addr + blksize;for (i = 0; i < (nblks - 1); i++) {*plink = (void *)pblk;plink = (void **)pblk;pblk = pblk + blksize;}*plink = (void *)0; /* Last memory block points to NULL 最后的内存块指针指向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 保存每个内存块的块大小*/*err = OS_NO_ERR;return (pmem);}/*$PAGE*//********************************************************************** ************************************* 得到一个内存控制块** 说明 : 从分区中得到一个内存块** 参数 : pmem 指针指向一个内存分区控制块** err 指向一个变量包含一个错误信息,这个错误信息通过这个函数或其他来设计** OS_NO_ERR 假如内存分区被正确的创建. * OS_MEM_NO_FREE_BLKS 假如没有更多的内存块被分配给调用者* OS_MEM_INVALID_PMEM 假如已经为'pmem'通过一个空指针** 返回值 : 一个指针指向一个内存控制块,假如没有察觉错误* 一个指针指向空指针,假如有错误被察觉到********************************************************************* *************************************/void *OSMemGet (OS_MEM *pmem, INT8U *err){#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register 为CPU状态寄存器分配存储空间 */OS_CPU_SR cpu_sr;#endifvoid *pblk;#if OS_ARG_CHK_EN > 0if (pmem == (OS_MEM *)0) { /* Must point to a valid memory partition 必须指向一个有效的内存分区 */*err = OS_MEM_INVALID_PMEM;return ((OS_MEM *)0);}#endifOS_ENTER_CRITICAL();if (pmem->OSMemNFree > 0) { /* 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--; /* Oneless memory block in this partition 在这个分区中减少一个内存块*/OS_EXIT_CRITICAL();*err = OS_NO_ERR; /* Noerror 没有错误*/return (pblk); /* Return memory block to caller 返回内存控制块给调用者*/}OS_EXIT_CRITICAL();*err = OS_MEM_NO_FREE_BLKS; /* No, Notify caller of empty memory partition 告知调用者是空的内存分区*/return ((void *)0); /* Return NULL pointer to caller 返回NULL个调用者*/}/*$PAGE*//********************************************************************** ************************************* 释放一个内存块** 说明 : 返回一个内存块给分区** 参数 : pmem 指针指向内存分区控制块** pblk 指针指向被保留的内存块.** 返回值 : OS_NO_ERR 假如内存块是被插入的分区* OS_MEM_FULL 假如返回一个已经全部内存分区的内存块* (你释放了更多你分配的内存块!)* OS_MEM_INVALID_PMEM 假如指针'pmem'指向NULL。
uCOSII的源代码

052 INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */
053
054 INT16U const OSLowestPrio = OS_LOWEST_PRIO;
069
070 INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */
071
072 INT16U const OSQEn = OS_Q_EN;
022 */
023
024 INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */
025
026 #if OS_DEBUG_EN > 0
048 INT16U const OSFlagNodeSize = 0;
049 INT16U const OSFlagWidth = 0;
050 #endif
051 INT16U const OSFlagMax = OS_MAX_FLAGS;
083
084 INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */
085
086 INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN;
087 INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN;
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
作者:钟常慰Ucos_II2.52是一份非常完美的嵌入式开发系统,在学习ARM的基础上,嵌入ucos系统并增加自己的源码是一件不错的选择,目前在市面上已经有了大量的ucos嵌入案例,特别是在arm和dsp的应用当中,已经成为一种主流,虽然和其它的嵌入式系统相比,ucos不是很完善,如没有内存分配、任务级别不多;但却是一个代码简短、条理清晰、实时性及安全性能很高的嵌入式操作系统。
Ucos_II2.52对比2.8版的256个任务而言,任务数量相比过少,但却是目前应用量最大的一个版本,相对而言,能够满足我们的基本要求,而且增加了很多消息处理,特别是在优先级别方面,具有不可比拟的优势;我曾试图阅读ecos的源码,但还是失败了,还有挑战linux0.01版源码的想法,最终我不能不被屈服;对于Ucos而言,很多入门者是一个福音,因为它的代码非常的少,而且能够对应贝贝老师的书本直接参考,他的书本对结构方面讲解的极为xian详细。
在学习Ucos的整个过程中,E文的理解是一个致命的打击,原因是我的E文水平很差,不过Ucos还是给了我尝试的动力,在作者的原基础上增加中文译码,也许是一件非常不错的选择,相信在中国和我这种水平的人多不胜数,中文的注解对源码而言,能够具有极高的理解价值,可以在极短的时间内,能够充分了解ucos的真正含义。
整个翻译过程历时4个月,每每在寒冬腊月坐在计算机前面,不断的查阅贝贝老师的书来对整个Uco s进行理解,对每个源码进行逐条翻译,也是一件非常需要勇气的事情,但E文的翻译过程中很多变量是不能完全理解的,所以在翻译过程中不乏错误译文很多,于此带来的错误还请读者纠正,相信克服种种困难一定会有所了解的。
对于经济窘迫的我来说,曾试图希望卖一点资料来养家糊口,但这种做法根本不现实,很多的读者可能和我一样,习惯了拿不收费的资料,并对变相收费有一种深恶痛绝的感觉;想了很多决定还是把它贡献出来,让更多的人来(更容易)了解ucos,贡献自己的一点力量。
希望更多的人能加入这种高尚的学习氛围当中来,共同的来把一套完整的U系列源码译文早一日与我们分享,祝愿大家能够早日实现自己的梦想。
/************************************************************************* ************************** uC/OS-II实时控制内核* 主要的包含文件* 文件: uCOS_II.H ucos内部函数参数设定* 作者: Jean J. Labrosse* 中文注解: 钟常慰zhongcw @ 译注版本:1.0 请尊重原版内容************************************************************************ **************************//************************************************************************* ************************** 混杂的设定************************************************************************ **************************/#define OS_VERSION 251 // 定义uC/OS-II版本号#ifdef OS_GLOBALS //如果OS_GLOBALS 已被声明定义, 紧随代码将会被编译#define OS_EXT //则定义OS_EXT#else#define OS_EXT extern //否则,定义OS_EXT 为extern#endif#ifndef FALSE //是否未定义FALSE#define FALSE 0 //如果是则定义FALSE 为0#endif#ifndef TRUE //是否未定义TRUE#define TRUE 1 //如果是则定义TRUE 为1#endif#define OS_PRIO_SELF 0xFF //定义OS_PRIO_SELF 为0xFF#if OS_TASK_STAT_EN > 0#define OS_N_SYS_TASKS 2 //任务体系号码#else#define OS_N_SYS_TASKS 1#endif#define OS_STAT_PRIO (OS_LOWEST_PRIO - 1) //统计任务优先级#define OS_IDLE_PRIO (OS_LOWEST_PRIO) //空闲任务优先级#define OS_EVENT_TBL_SIZE ((OS_LOWEST_PRIO) / 8 + 1) //事件列表字节#define OS_RDY_TBL_SIZE ((OS_LOWEST_PRIO) / 8 + 1) //就绪列表字节#define OS_TASK_IDLE_ID 65535 /* I.D. numbers for Idle and Stat task s */#define OS_TASK_STAT_ID 65534#define OS_EVENT_EN (((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX _EN > 0) || (OS_SEM_EN > 0) || (OS_MUTEX_EN > 0))/*$PAGE*//************************************************************************* ********************************** 任务状态字TASK STATUS (字节定义在OSTCBStat中)************************************************************************ **********************************/#define OS_STAT_RDY 0x00 // (将任务的状态字)处于完毕状态#define OS_STAT_SEM 0x01 // (将任务的状态字)处于SEM状态#define OS_STAT_MBOX 0x02 // (将任务的状态字)处于MBOX状态#define OS_STAT_Q 0x04 // (将任务的状态字)处于Q状态#define OS_STAT_SUSPEND 0x08 // 表示任务被挂起#define OS_STAT_MUTEX 0x10 // (将任务的状态字)处于MUTEX状态#define OS_STAT_FLAG 0x20 // (将任务的状态字)处于FLAG状态/************************************************************************* ********************************** 事件类型(OS_EVENT types)************************************************************************ **********************************/#define OS_EVENT_TYPE_UNUSED 0 // 定义事件类型的种类(无事件类型------------0) #define OS_EVENT_TYPE_MBOX 1 // 定义事件类型的种类(邮箱为数字序列--------1) #define OS_EVENT_TYPE_Q 2 // 定义事件类型的种类(消息队列为数字序列----2)#define OS_EVENT_TYPE_SEM 3 // 定义事件类型的种类(信号量为数字序列------3) #define OS_EVENT_TYPE_MUTEX 4 // 定义事件类型的种类(互斥型信号量为数字序列4)#define OS_EVENT_TYPE_FLAG 5 // 定义事件类型的种类(事件标志组为数字序列--5) /************************************************************************* ********************************** 事件标志(EVENT FLAGS)************************************************************************ **********************************/#define OS_FLAG_WAIT_CLR_ALL 0 // 定义所有指定事件标志位清0 ------ 0#define OS_FLAG_WAIT_CLR_AND 0 // 同上一样#define OS_FLAG_WAIT_CLR_ANY 1 // 定义任意指定事件标志位清0 ------ 1#define OS_FLAG_WAIT_CLR_OR 1 // 同上一样#define OS_FLAG_WAIT_SET_ALL 2 // 定义所有指定事件标志位置1 ------ 2#define OS_FLAG_WAIT_SET_AND 2 // 同上一样#define OS_FLAG_WAIT_SET_ANY 3 // 定义任意指定事件标志位置1 ------ 3#define OS_FLAG_WAIT_SET_OR 3 // 同上一样// 如果需要在得到期望标志后,恢复该事件标志,加入此常量#define OS_FLAG_CONSUME 0x80 // 定义常量OS_FLAG_CONSUME为0x80 #define OS_FLAG_CLR 0 // 定义OS_FLAG_CLR 为清0#define OS_FLAG_SET 1 // 定义OS_FLAG_SET 为置1/************************************************************************* ********************************** 设置字在'opt'中,适用于OSSemDel(), OSMboxDel(), OSQDel() 和OSMutexDel()函数************************************************************************ **********************************/#define OS_DEL_NO_PEND 0 // 可以选择只能在已经没有任何任务在等待该信号量时,才能删除该信号量#define OS_DEL_ALWAYS 1 // 不管有没有任务在等待该信号量,立即删除该信号量/************************************************************************* ********************************** OS???PostOpt() OPTIONS(设置)** 这个设置适用用OSMboxPostOpt() 和OSQPostOpt()两个函数.************************************************************************ **********************************/#define OS_POST_OPT_NONE 0x00 // 发送一个消息(或邮箱)给一个等待消息的任务#define OS_POST_OPT_BROADCAST 0x01 // 发送消息给所有等待队列消息的任务*/#define OS_POST_OPT_FRONT 0x02 // 以后进先出方式发消息(仿真OSQPostFront ())/************************************************************************* ********************************** 任务设置TASK OPTIONS (查看OSTaskCreateExt())************************************************************************ **********************************/#define OS_TASK_OPT_STK_CHK 0x0001 // 决定是否进行任务堆栈检查#define OS_TASK_OPT_STK_CLR 0x0002 // 决定是否清空堆栈#define OS_TASK_OPT_SAVE_FP 0x0004 // 决定是否保存浮点寄存器的数值。