ARM学习笔记--初识uC/OS(一)

发布者:脑洞飞扬最新更新时间:2016-07-19 来源: eefocus关键字:ARM 手机看文章 扫描二维码
随时随地手机看文章
下面就直接进程序看吧,首先看mian函数

int main(void)
{
INT8U os_err;//OS error
Bsp_init();//Embedded development board Initialization//开发板初始化
OSInit();//uC/OS initialization//系统初始化
os_err = OSTaskCreateExt((void (*)(void *)) App_Task_LCD,//创建任务
(void * ) 0,
(OS_STK * )&App_TaskLCDStk[APP_TASK_LCD_STK_SIZE-1],
(INT8U ) APP_TASK_LCD_PRIO,
(INT16U ) APP_TASK_LCD_PRIO,
(OS_STK * )&App_TaskLCDStk[0],
(INT32U ) APP_TASK_LCD_STK_SIZE,
(void * ) 0,
(INT16U )(OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK));

OSStart(); //uC/OS start multitasking//开始任务运行
}

开发板的初始化就是对arm单片机的引脚和时钟等等运行必要条件进行初始化,这里就不看了,我们来看看OSInit()

/*
*********************************************************************************************************
* 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().
× 描述:该函数用于uC/OS-II系统的内部初始化,它必须在调用uC/OS-II系统的任何创建对象之前,也必须在
* 函数OSStart()之前执行。也就是说使用uC/OS-II系统的第一步就是执行这个函数,这是一个约定。
*
* 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 */
#endif

OS_InitTaskIdle(); /* Create the Idle Task */
#if OS_TASK_STAT_EN > 0
OS_InitTaskStat(); /* Create the Statistic Task */
#endif

#if OS_TMR_EN > 0
OSTmr_Init(); /* Initialize the Timer Manager */
#endif

OSInitHookEnd(); /* Call port specific init. code */

#if OS_DEBUG_EN > 0
OSDebugInit();
#endif
}

我们学习的时候不用管这个函数里面到底执行了什么,但是我们必须要学会一点:知道这个函数是在使用uC/OS系统前的第一个需要调用的函数,只要知道这个我们就算知道怎么用它了。
看下一个函数OSTaskCreateExt

/*
*********************************************************************************************************
* 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.
* 描述: 该函数用于创建一个 uC/OS-II管理的可执行任务.它不是在多个任务执行前被创建就是在一个运行
* 的任务中被创建.在中断服务函数中不能创建任务(也就是说在ISR中不能调用该函数). 除了该函数允许一
*个任务的附加信息被列出外,该函数类同于函数OSTaskCreate().
*
* 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.
* 传参:task 任务代码的一个指针(指向任务代码段)
*
* p_arg 当task第一次运行时,它代表指向一个用于向task传递参数的可选数据区域的指针.当task
* 在连接数据的时候,它被要求和像下面的例子这样传递参数'p_arg' :
*
* void Task (void *p_arg)
* {
* for (;;) {
* Task code;
* }
* }
*
* ptos 任务栈顶指针.假如OS_STK_GROWTH设置为'1',则栈被认为是向低地址推移的(即从高存储到低
* 存储位置).栈顶指针将指向栈所在的存储器的最高位置.假如OS_STK_GROWTH设置为'0',则栈被
* 认为是向高地址推移的(即从低存储到高存储位置).栈顶指针随内存增加增加. 'ptos'一定指向
* 一个可用的'空闲'的数据项.
*
* prio 任务的优先级. 每个任务都必须有一个唯一的优先级.优先级数字越小,优先级别越高.
*
* id 任务的ID号(0..65535)
*
* pbos 任务的栈底指针. 假如OS_STK_GROWTH设置为'1',则栈被认为是向低地址推移的(即从高存储到低
* 存储位置).栈底指针将指向栈所在的存储器的最低位置.假如OS_STK_GROWTH设置为'0',则栈被
* 认为是向高地址推移的(即从低存储到高存储位置).栈底指针随内存增加增加. 'ptos'一定指向
* 一个可用的'空闲'的数据项.
*
* stk_size 栈的长度.如果OS_STK设置为INT8U,stk_size则为字节数允许.若OS_STK设置为INT16U,stk_size则为十
* 六位数允许.最后若OS_STK设置为INT32U,stk_size则为32位二进制允许.(指明栈的宽度)
*
* pext 是一个指针,指向用户提供的用于TCB扩展部分的内存空间. 例如:通过上下文切换用户存储器能
* 保持住浮点寄存器的内容、每次任务运行的时间、任务被开关的次数等等.
*
* opt 包含任务行为的附加信息(或选项).低八位被uC/OS-II系统作为保留字.高八位作为特殊的应用.这个
* 选项的设置查看uCOS-II.H.中的OS_TASK_OPT_???.当前选项是:
* OS_TASK_OPT_STK_CHK 需要进行栈的检查
* OS_TASK_OPT_STK_CLR 任务创建时清除栈
* OS_TASK_OPT_SAVE_FP 假如处理器有浮点数据,保存它们
*
* 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.
*
* 返回值 : OS_ERR_NONE 函数执行成功范围的内容
* OS_PRIO_EXIT 该任务的优先级已经存在返回该值
* (每个任务都有一个唯一的优先级).
* OS_ERR_PRIO_INVALID 设置的优先级大于最大的优先级别返回该值
* (即 > OS_LOWEST_PRIO)
* OS_ERR_TASK_CREATE_ISR 当在ISR中创建任务时返回该值(ISR中不允许进行任务创建)
*********************************************************************************************************
*/
/*$PAGE*/
#if OS_TASK_CREATE_EXT_EN > 0
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 == 3 /* Allocate storage for CPU status register */
/* 分配CPU状态寄存器的存储 */
OS_CPU_SR cpu_sr = 0;
#endif



#if OS_ARG_CHK_EN > 0
if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */
/* 确保优先级在允许的范围内 */
return (OS_ERR_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
if (OSIntNesting > 0) { /* Make sure we don't create the task from within an ISR */
/* 确保不在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 > 0)
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 */
/* 在多任务开始后发现HPT */
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

学习创建任务这个函数,我们就要了解的更多,首先必须对每一个传参要有所了解,在注释中我已经写清楚了;第二要知道我们在uC/OS中能创建最多64个进程,由于系统占用了4个还有4个备用,所以我们能创建的只有56个;第三也是最终要的,在任务中我们可以创建新的任务,但是在中断函数中绝不能创建新的任务,这将会引起未知错误。
再来看函数OSStart()

/*
*********************************************************************************************************
* 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.
*
×描述:该函数用于开启你已经在uC/OS-II中创建的多任务进程.在调用该函数前,必须已经调用了OSInit()函
* 数和创建了至少一个进程.
×
* 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.
* 说明 : OSStartHighRdy() 函数必须使用:
* a) 然后调用函数OSTaskSwHook(),
* b) 设置 OSRunning为 OS_TRUE.
* c) 加载被OSTCBHighRdy指向的内容.
* d_ 运行任务
*********************************************************************************************************
*/

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 */
}
}

这个函数的学习,我们目前需要知道的只有两点:一、它必须在OSInit()和OSTaskCreate()之后,因为这样才有进程开始;二、就是说明里的内容,这个函数的执行是一个按顺序执行整个动作。现在我们还不用明白它干了什么,只要知道怎么用就行了。这里需要注意为什么在系统中时序,先后执行的顺序这么重要,因为uC/OS系统是一个抢先式的执行系统,如果时序不对,那么就会产生不一样的结果。
 
这就是我才看uC/OS系统的一些理解,在以后的处理过程中,学习到更多的东西,我将会写出来。个人感觉,看注释其实是一个非常好的学习方法,虽然注释是英文很难看懂,但这样更加准确,看懂了我们也就理解了。
关键字:ARM 引用地址:ARM学习笔记--初识uC/OS(一)

上一篇:ARM学习笔记--LPC1788引脚分析
下一篇:ARM学习笔记--GPIO接口

推荐阅读最新更新时间:2024-03-16 15:00

Arm-linux内存管理(4)
上一篇主要是与具体体系有关的数据结构,并最后遗留了个问题: 那么,这些数据结构怎样发挥作用的呢?特别是,ARM-Linux内核怎样根据这些数据结构建立起地址映射呢? 1、从系统的初始化说起。系统引导以后,CPU进入内核的总入口,即代码段的起点stext.在stext中,CPU首先从自身读出CPU的型号及其所在的机型,把有关的信息存放在processor_id和machine_arch_type两个全局变量中,然后就转入start_kernel()。 asmlinkage void __init start_kernel(void) { ...... setup_arch(&command_line); 这个
[单片机]
<font color='red'>Arm</font>-linux内存管理(4)
基于UC3863控制的LLC谐振变换器的设计及仿真
随着通信产品的小型化发展,对开关电源的性能要求方面也越来越高,促使电源向高频、高可靠、低耗和小型化的趋势发展,同时促进开关电源在高新技术领域更加广泛的应用。在开关电源向高频化和小型化的发展过程中,其中开关损耗问题是制约其发展的一个重要因素,软开关技术能够较好的解决开关损耗的问题。 LLC谐振变换器以其拓扑结构简单,可以实现初级开关管零电压开通和次级输出整流管的零电流关断,开关损耗低、可高频化,副边整流二极管电压应力低,在高输出电压应用情况下可以实现较高的效率等优点成为近年来的一个研究热点。但是LLC谐振变换器的拓扑在其实际的应用过程中还存在着许多问题,当出现电路启动、负载过流或短路情况时如何限制电路中的电流以防止电路损坏就是
[单片机]
基于<font color='red'>UC</font>3863控制的LLC谐振变换器的设计及仿真
英特尔进军低端Android平板市场挑战ARM
新浪科技讯 北京时间2月28日下午消息,在巴塞罗那举行的世界移动大会(以下简称“MWC”)上,华硕发布了一款采用x86架构处理器的Android平板电脑,这标志着英特尔开始进军低端Android平板市场,挑战ARM的霸主地位。   进军低端市场   华硕发布了一款搭载英特尔单核凌动Z2420(代号为“Lexington”)处理器的7英寸平板电脑。“Lexington”处理器将目标瞄准了低端智能手机和平板电脑市场。华硕新款平板电脑售价249美元,具有3G语音和数据功能,号称电池续航时间长达9小时。此外,它还配备多个摄像头,以及分辨率为1280X800像素显示屏。   这款平板产品的价格和性能,与搭载ARM处理器的低端7英
[手机便携]
ARM内部逻辑结构见解
从ARM内部逻辑结构【可以从ARM公司里面下载】中可以看出,它比其他微处理器,比如说8051,在进行数据逻辑加减运算时,它有一桶形移位器,它用来做什么的呢,如果对ARM指令了解点的话,应该很清楚它的作用;另外它在读取RAM里面的数据时,要经过一个符号扩展,那么我们在用C写程序,要尽量用32的数据类型,因为如果你不用,比如用的是8位,那么它会有一个符号扩展的处理过程,增加CPU的负荷。
[单片机]
深入理解ARM体系架构(S3C6410)---ad转化实例
本实例是把采集的ad数据转化后显示在lcd屏上,在这直接把自己调试好的源码贴出来 ad转化器相关代码: view plain copy print ? void adc_init() { char preScaler = 66500000/2500000 - 1; //PCLK=66M rADCCON = (1 14)|(preScaler 6)|(0 3)|(0 2);//通道AIN0 // rADCCON =0x44c1;//通道AIN0 } int read_adc() { rAD
[单片机]
基于ARM7 TDMI核的MCU ADuC7020的单电源心电检测系统设计
本文给出的设计采用单电源供电,可以解决上述问题并降低产品成本,同时该设计还在基于ARM核的嵌入式系统中采用了简单实用的算法,能快速准确定位QRS复波(即计算人的心率)。该设计面向广大家庭用户而设计,体积较小,只需要一台个人电脑与之连接,便可实时地操作、观测心电信号。 心电信号采集系统的基本架构如图1所示。人体的心电信号经电极和专用导联线从人体送至系统。通过滤波和放大调节电路,微弱的心电信号被放大到合适的幅值,并处于A/D转换范围之内。 系统的控制和数据的处理由ADI公司基于ARM7 TDMI核的MCU ADuC7020来完成。这款芯片有丰富的片内外围电路,处理速度高达40MIPS,A/D转换速度可达1MSPS,具有很
[单片机]
基于<font color='red'>ARM</font>7 TDMI核的MCU ADuC7020的单电源心电检测系统设计
高效的C编程之:布尔表达式(上)
简介:本章将帮助读者在ARM处理器上编写高效的C代码。本章涉及的一些技术不仅适用于ARM处理器,也适用于其他RISC处理器。(EEFOCUS) 14.4布尔表达式 14.4.1范围检测 通常,布尔表达式被用来检测某个数值是否在特定的范围内。例如,在图形窗口处理程序中,常使用布尔表达式判断屏幕中一个点是否在当前活动窗口范围内。 下面的程序使用结构体定义点坐标并计算坐标的当前位置。 boolPointInRect1(Pointp,Rectangle*r) {return(p.x =r- xmin&&p.x r- xmax&& p.y =r- ymin&&p.y r- ymax); } 上面的功能函数,被
[单片机]
使用uC/OS-II操作系统的短信息电话机
摘要:将μC/OS-II实时嵌入式操作系统移植到EPSON八位单片机上来开发短信息电话机。此电话机除普通电话的通用功能外,还增加了短消息收/发功能、信息浏览与查阅功能、信息点播与信息订阅功能等。 关键词:短信息电话机 实时操作系统 μC/OS-II 1 背 景   后PC时代的到来,使人们开始越来越多地接触到一个新的概念——嵌入式产品。手机、PDA(如商务通)等均属于手持式嵌入式产品,VCD机、机顶盒等也属于嵌入式产品,而车载GPS系统、数控机床、网络冰箱等同样都属于嵌入式产品。信息电器具有信息服务功能,如网络浏览、视频点播、文字处理、电子邮件、个人数字助理等。后PC时代,家用电器将向数字化和网络化发展,计算机都将嵌入到电视
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved