嵌入式内核分析
来源:互联网 发布:win7系统优化设置 编辑:程序博客网 时间:2024/06/06 03:32
嵌入式内核分析
--内核就是我,我就是内核
第一篇 uC/OSII
第一章 内核
第二章 任务管理
第三章 中断和时间
第四章 事件控制块
第五章 信号量管理
第六章 互斥信号量管理
第七章 事件标志组管理
第八章 消息邮箱管理
第九章 消息队列管理
第十章 内存管理
第一章 内核
一 临界段
关中断的时间是实时内核开发商提供的最重要的指标之一。
uC/OSII定义两个宏来关中断和开中断。分别是OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。
有三种不同的方法,见OS_CPU.H中的OS_CRITICAL_METHOD
1 OS_CRITICAL_METHOD==1
最简单方式处理,用处理器指令关中断,用开中断退出
2 OS_CRITICAL_METHOD==2
#define OS_ENTER_CRITICAL()
asm("PUSH PSW")
asm("DI")
#define OS_EXIT_CRITICAL()
asm("POP PSW")
3 OS_CRITICAL_METHOD==3
#define OS_ENTER_CRITICAL()
cpu_sr = get_processer_psw();
disable_interrupts();
#define OS_EXIT_CRITICAL
set_processor_psw(cpu_sr);
二 任务状态
五种状态: 睡眠态、就绪态、运行态、等待状态、中断服务态
1 睡眠态 task dormant
指任务驻留在程序空间,还没有交给操作系统管理,交给操作系统是通过OSTaskCreate()或OSTaskCreateExt()来实现。
2 就绪态
任务一旦建立,就进入就绪态,准备运行。一个任务可以通过OSTaskDel()返回到睡眠态。
3 运行态
调用OSStart()可以启动多任务。该函数运行用户初始化代码中已经建立的、进入就绪态的优秀级最高的任务。
任何时候只有一个任务处于运行态。
就绪的任务只有当所有优先级高于这个任务的任务都转为等待状态,或者是被删除了,才能进入运行态。
4 等待状态
正在运行的任务可以通过调用以下2个函数之一,将自身延迟一段时间,这2个函数是OSTimeDly()或OSTimeDlyHMSM()。
正在运行的任务可能需要等待某一个事件的发生,可以通过调用一下函数之一实现:
OSFlagPend(),OSSemPend(),OSMutexPend(),OSMboxPend(),OSQPend()
当事件发生了或等待超时时,被挂起的任务就进入就绪态
调用延时函数后,会立刻强制执行任务切换,让下一个优先级最高的、并进入了就绪态的任务运行。
5 中断服务态
正在运行的任务是可以被中断的,被中断的任务于是进入了中断服务态(ISR running)。
三 任务控制块
任务控制块是一个数据结构,当任务的CPU使用权被剥夺时,uC/OS-II用它来保存该任务的状态。
typedef struct os_tcb {
OS_STK *OSTCBStkPtr; /* Pointer to current top of stack */
#if OS_TASK_CREATE_EXT_EN > 0
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_FLAG_EN > 0)
OS_EVENT *OSTCBEventPtr; /* Pointer to event control block */
#endif
#if (OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0)
OS_EVENT **OSTCBEventMultiPtr; /* Pointer to multiple event control blocks */
#endif
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
void *OSTCBMsg; /* Message received from OSMboxPost() or OSQPost() */
#endif
#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
#if OS_TASK_DEL_EN > 0
OS_FLAG_NODE *OSTCBFlagNode; /* Pointer to event flag node */
#endif
OS_FLAGS OSTCBFlagsRdy; /* Event flags that made task ready to run */
#endif
INT16U 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 */
#if OS_LOWEST_PRIO <= 63
INT8U OSTCBBitX; /* Bit mask to access bit position in ready table */
INT8U OSTCBBitY; /* Bit mask to access bit position in ready group */
#else
INT16U OSTCBBitX; /* Bit mask to access bit position in ready table */
INT16U OSTCBBitY; /* Bit mask to access bit position in ready group */
#endif
#if OS_TASK_DEL_EN > 0
INT8U OSTCBDelReq; /* Indicates whether a task needs to delete itself */
#endif
#if OS_TASK_PROFILE_EN > 0
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_SIZE > 1
INT8U OSTCBTaskName[OS_TASK_NAME_SIZE];
#endif
} OS_TCB;
参数的意义
1 OSTCBStkPtr 指向当前任务堆栈栈顶的指针。
2 OSTCBExtPtr 指向用户定义的任务控制块扩展。
3 OSTCBStkBottom 指向任务堆栈栈底的指针。
4 OSTCBStkSize 存有栈中可容纳的指针元数目。
5 OSTCBOpt 把“选择项”传给函数OSTaskCreateExt()。
6 OSTCBId 用于存储任务的识别码,目前没用保留。
7 OSTCBNext、OSTCBPrev 用于任务控制块OS_TCB双向链表的前/后链接。
8 OSTCBEventPtr 指向事件控制块的指针。
9 OSTCBMsg 指向传递给任务的消息的指针。
10 OSTCBFlagNode 指向事件标志节点的指针。
11 OSTCBFlagsRdy 当任务等待事件标志组时,OSTCBFlagsRdy是使任务进入就绪态的事件标志。
12 OSTCBDly 当需要把任务延时若干时钟节拍,或者需要把任务挂起一段事件以等待某事件的发生时,需用到这个变量。
13 OSTCBStat 任务的状态字
14 OSTCBPrio 任务的优先级
15 OSTCBX、OSTCBY、OSTCBBitX、OSTCBBitY 用于加速任务进入就绪态的过程或进入等待事件发生状态的过程。
16 OSTCBDelReq 一个布尔量,用于表示该任务是否须删除。
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 == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
OS_ENTER_CRITICAL(); // 1
ptcb = OSTCBFreeList; /* Get a free TCB from the free TCB list */
if (ptcb != (OS_TCB *)0) { // 2
OSTCBFreeList = ptcb->OSTCBNext; /* Update pointer to free TCB list */
OS_EXIT_CRITICAL();
ptcb->OSTCBStkPtr = ptos; // 3 /* 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 = 0; /* Task is not delayed */
#if OS_TASK_CREATE_EXT_EN > 0
ptcb->OSTCBExtPtr = pext; // 4 /* 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 > 0
ptcb->OSTCBDelReq = OS_ERR_NONE; //5
#endif
#if OS_LOWEST_PRIO <= 63
ptcb->OSTCBY = (INT8U)(prio >> 3); // 6 /* Pre-compute X, Y, BitX and BitY */
ptcb->OSTCBX = (INT8U)(prio & 0x07);
ptcb->OSTCBBitY = (INT8U)(1 << ptcb->OSTCBY);
ptcb->OSTCBBitX = (INT8U)(1 << ptcb->OSTCBX);
#else
ptcb->OSTCBY = (INT8U)((prio >> 4) & 0xFF); /* Pre-compute X, Y, BitX and BitY */
ptcb->OSTCBX = (INT8U) (prio & 0x0F);
ptcb->OSTCBBitY = (INT16U)(1 << ptcb->OSTCBY);
ptcb->OSTCBBitX = (INT16U)(1 << ptcb->OSTCBX);
#endif
#if (OS_EVENT_EN)
ptcb->OSTCBEventPtr = (OS_EVENT *)0; // 7 /* Task is not pending on an event */
#if (OS_EVENT_MULTI_EN > 0)
ptcb->OSTCBEventMultiPtr = (OS_EVENT **)0; /* Task is not pending on any events */
#endif
#endif
#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0)
ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; // 8 /* Task is not pending on an event flag */
#endif
#if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0))
ptcb->OSTCBMsg = (void *)0; /* No message received */
#endif
#if OS_TASK_PROFILE_EN > 0
ptcb->OSTCBCtxSwCtr = 0L; /* Initialize profiling variables */
ptcb->OSTCBCyclesStart = 0L;
ptcb->OSTCBCyclesTot = 0L;
ptcb->OSTCBStkBase = (OS_STK *)0;
ptcb->OSTCBStkUsed = 0L;
#endif
#if OS_TASK_NAME_SIZE > 1
ptcb->OSTCBTaskName[0] = '?'; /* Unknown name at task creation */
ptcb->OSTCBTaskName[1] = OS_ASCII_NUL;
#endif
OSTCBInitHook(ptcb); //9
OSTaskCreateHook(ptcb); // 10 /* Call user defined hook */
OS_ENTER_CRITICAL(); // 11
OSTCBPrioTbl[prio] = ptcb; // 12
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; // 13 /* Make task ready to run */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OSTaskCtr++; /* Increment the #tasks counter */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE); // 14
}
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NO_MORE_TCB);
(1、2) 首先试图从OS_TCB缓冲池中得到一个任务控制块
(3) 如果缓冲池中有空余的OS_TCB,就被初始化了
(4) 额外的变元就插入到OS_TCB中了
(5) OS_TCB中是否出现OSTCBDelReq取决于OS_TASK_DEL_EN是否被置1
(6) 以存储空间换取执行时间
(7) 不打算使用信号量等
(8) 初始化为空指针
(9) 增加了对函数OSTCBInitHook()的调用
(10) OS_TCBInit()然后调用OSTaskCreateHook()
(12) 关中断
(14) 最后,让任务进入就绪态
四、 就绪表
每个就绪的任务都放在就绪表中,就绪表中有两个变量,OSRdyGrp和OSRdyTbl[]
它们的关系是: 当OSRdyTbl[i]中的任何一位是1时,OSRdyGrp的第i位置1
五、 任务调度
确定那个任务优先级最高,下面该那个任务运行了,这一工作是有调度器完成的。
void OS_Sched (void)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
OS_ENTER_CRITICAL();
if (OSIntNesting == 0) { /* Schedule only if all ISRs done and ... */
if (OSLockNesting == 0) { // 1 /* ... scheduler is not locked */
OS_SchedNew();
if (OSPrioHighRdy != OSPrioCur) { // 3 /* No Ctx Sw if current task is highest rdy */
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; // 4
#if OS_TASK_PROFILE_EN > 0
OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */
#endif
OSCtxSwCtr++; // 5 /* Increment context switch counter */
OS_TASK_SW(); // 6 /* Perform a context switch */
}
}
}
OS_EXIT_CRITICAL();
}
1 如果调用来自中断服务子程序,或者由于至少调用了一次给任务调度上锁函数,任务调度函数将退出,不做调度任务
3 找到优先级最高的任务后,校验这个优先级最高的任务是否是当前正在运行的任务,以避免不必要的任务调度
4 为实现任务切换,OSTCBHighRdy必须指向优先级最高的任务控制块
5 OSTCBCtxSwCtr加1,以跟踪任务切换次数
6 最后,调用宏OS_TASK_SW,完成实际的任务切换
六 给调度器上锁和开锁
上锁用于禁止任务调度,直到任务完成后,调度给调度器开锁函数。
void OSSchedLock (void)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
if (OSRunning == OS_TRUE) { // 1 /* Make sure multitasking is running */
OS_ENTER_CRITICAL();
if (OSIntNesting == 0) { /* Can't call from an ISR */
if (OSLockNesting < 255u) { // 2 /* Prevent OSLockNesting from wrapping back to 0 */
OSLockNesting++; /* Increment lock nesting level */
}
}
OS_EXIT_CRITICAL();
}
}
1 如果多任务已经启动了,则给调度器上锁才有意义。
2 在给嵌套层数加1之前,须确认嵌套层数没有超界。
void OSSchedUnlock (void)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
if (OSRunning == OS_TRUE) { // 1 /* Make sure multitasking is running */
OS_ENTER_CRITICAL();
if (OSLockNesting > 0) { // 2 /* Do not decrement if already 0 */
OSLockNesting--; // 3 /* Decrement lock nesting level */
if (OSLockNesting == 0) { /* See if scheduler is enabled and ... */
if (OSIntNesting == 0) { // 4 /* ... not in an ISR */
OS_EXIT_CRITICAL();
OS_Sched(); // 5 /* See if a HPT is ready */
} else {
OS_EXIT_CRITICAL();
}
} else {
OS_EXIT_CRITICAL();
}
} else {
OS_EXIT_CRITICAL();
}
}
}
1 如果多任务已经启动了,则给调度器开锁才有意义。
2 确认OSLockNesting还没有回0
3 OSLockNesting减1
七 中断
用户中断服务子程序
保存全部CPU寄存器
调用OSIntEnter()或OSIntNesting直接加1
if(OSIntNesting==1) {
OSTCBCur->OSTCBStkPtr=SP;
}
请中断源
重新开中断
执行用户代码做中断服务
调用OSIntExit()
恢复所有CPU寄存器
执行中断返回指令
- 嵌入式内核分析
- 嵌入式Linux-内核异常分析
- 嵌入式Linux内核移植相关代码分析
- 嵌入式Linux内核移植相关代码分析
- 嵌入式Linux内核移植相关代码分析
- 嵌入式Linux内核移植相关代码分析
- 嵌入式Linux内核移植相关代码分析
- 嵌入式Linux内核移植相关代码分析
- 嵌入式Linux内核移植相关代码分析
- 嵌入式Linux内核启动部分代码分析
- 嵌入式Linux内核移植相关代码分析
- 嵌入式Linux内核移植相关代码分析
- 嵌入式Linux内核移植相关代码分析
- 嵌入式Linux内核移植相关代码分析
- 嵌入式 Linux内核源代码目录结构分析
- 嵌入式linux第六讲 内核分析
- Linux内核源码分析—Linux内核中的嵌入式汇编
- 嵌入式uCLinux内核启动过程分析与设计(ZT)
- oracle 11g 卸载方法之官方deinstall工具完全使用手册
- NOJ284题 坦克大战(Battle City)(bfs+优先)
- Android 桌面Widget开发要点(时间日期Widget)
- C++编译器无法捕捉到的8种错误
- Android ListView控件显示数据库中图片
- 嵌入式内核分析
- RC4加密
- hibernate事物
- 【Android UI设计与开发】第16期:滑动菜单栏(一)开源项目SlidingMenu的使用
- click事件无法触发、div存取数值
- android的dip与px
- 多线程多次查询数据生成一个文件——解决内存溢出
- aChartEngine图表显示(一页显示多张图表)
- setTimeout和setInterval的使用