|
本帖最后由 wangpengcheng 于 2014-9-5 11:15 编辑
拿到塔式板了,我的心也实在了,只是莫大说让我发表个测评,这东西我还真没做过,呵呵,不知道如何进行!不过我这个马甲也注册半年了,从最低的注册会员都升到金牌会员了,一直在这里混,接触很多热心的坛友,帮过我很多,尤其是那几个版主,在这里我得谢谢大家!
我是从去年开始接触MQX的,以前学OS是从RTT开始学的,我觉得RTT的应用手册帮了我很大忙,按它一步一步了解OS。在没接触过OS之前,总觉得高上大,好难哦,尤其是LINUX,里面东西好多,根本就看不过来,而且没有实际的项目实战,真难啊。但是从这些小的系统里面,才真正看到OS的核心所在。其实我感觉用起来都差不多,主要是个思想,只是接口函数跟一些内部深入的东西会有一些差别,当然接口函数我们都可以在.h文件中找得到,至于内部比较深的东西,我暂时还没接触到。呵呵,其实我也只是知道个皮毛!
不过最近在坛子里碰到一些坛友,跟我以前一样,对OS没有一个明确的概念,当然,也有许多高手。所以我就有那么一点点想法,从MQX入手,把我理解的OS的概念表述出来!现在又有了塔式板,我想我可以将我这个想法付诸于行动了。如果有的观点大家认同,给个掌声鼓励一下;如果觉得有异议,我们可以一起讨论。
以后我想,如果大家觉得还可以,我会不定期的来做这件事情,这个帖子算是个开头吧。
好吧,废话说了不少,开始我们第一个认识:任务
任务肯定都听说过,这个比较简单,在OS中,任务的作用是把不同的事情分开来做,我把它理解成一个任务就是一个过程,有的过程是一次性的,有的过程是循环进行的!任何一个OS最基本的元素就是任务,OS是做什么的?它是对任务进行调度的,呵呵,我个人理解,它就是个指挥员,它会根据事先定义好的一些规则,来把时间分配给各个任务,并让每个任务顺利进行!它是怎么做的,我不管他,其实我也管不了 ,我只知道他需要什么,我给他就可以了!
现在我打开MQX例子中最简单的一个Hello,它的路径在:..\Freescale\Freescale_MQX_4_1\mqx\examples\hello\build\uv4\hello_twrk60f120m
打开后可以看到里面就一个.c文件,非常简单,它里面有一个任务模板列表:
- const TASK_TEMPLATE_STRUCT MQX_template_list[] =
- {
- /* Task Index, Function, Stack, Priority, Name, Attributes, Param, Time Slice */
- { HELLO_TASK, hello_task, 1500, 8, "hello", MQX_AUTO_START_TASK, 0, 0 },
- { 0 }
- };
复制代码
这个列表是一个结构体数组,它包含的是任务模板结构体,任务模板结构体的定义在MQX.h文件中可以找到。好吧,我们不管结构体了,因为这个列表的注释已经很清楚了:
任务ID:HELLO_TASK
函数名:hello_task
分配栈空间:1500
优先级:8
任务名称:"hello"
任务属性:MQX_AUTO_START_TASK
任务参数:0
任务时间片:0
这些都是MQX操作系统所需要的参数,我们把这些参数给它了,它就知道怎么来调度任务了!
要注意的是以下几个地方:
任务ID:这里要提到一个参数,任务最大数,我看了一下,在MQX.h文件中有定义,16位队列的是255个,32位队列的是65535个,目前用的是16位的,255个任务,太够了!当然,ID定义的时候也是1到255.
任务的栈空间:你要了解,你在任务中,所有的局部变量内存都是从这个空间里分配得到的。所以这个空间大小很重要,如果小了,分配内存会超出栈空间,造成内存混乱而发生不可预知的事情。如果太大了,浪费!
优先级:提到优先级,大家肯定不陌生了,中断都是按优先级来排的,这里是一个道理,你想哪个任务多跑几趟,那就给它高点,呵呵!
任务属性:目前的属性我英文不怎么滴也看明白了,是说这个任务是一个自启动的任务。嗯,说是任务属性当然会有选项了,我找到它定义的地方,肯定有一堆跟他类似的东西,看吧,果真有:
- /*--------------------------------------------------------------------------*/
- /*
- * TASK TEMPLATE ATTRIBUTES FLAGS
- *
- * These are bit flags or'd together to form the creation attributes for
- * a task. This is combined with INTERNAL TASK FLAGS.
- */
- /*
- * Tasks with this attribute will be created automatically at
- * system initialization time.
- */
- #define MQX_AUTO_START_TASK (0x01)
- /*
- * Tasks with this attribute will save the floating point co-processor
- * registers during context switching.
- * If the floating point registers are separate from the normal registers,
- * their context is managed independently during task switching. The registers
- * are saved/restored only when a new floating point task is scheduled to run.
- */
- #define MQX_FLOATING_POINT_TASK (0x02)
- /*
- * Tasks with this attribute will use the time slice
- * scheduler within the kernel
- */
- #if MQX_HAS_TIME_SLICE
- #define MQX_TIME_SLICE_TASK (0x04)
- #endif
- /*
- * Tasks with this attribute will save the DSP co-processor
- * registers during context switching.
- * If the DSP registers are separate from the normal registers,
- * their context is managed independently during task switching. The registers
- * are saved/restored only when a new DSP task is scheduled to run.
- */
- #define MQX_DSP_TASK (0x08)
- #if MQX_ENABLE_USER_MODE
- #define MQX_USER_TASK (0x10)
- #else
- #define MQX_USER_TASK (0)
- #endif
复制代码
看一下,它一共有5个选项可选,它们分别是:
自启动——当MQX 开始运行时,它生成任务的一个实例;
DSP——MQX 保存DSP 协处理器寄存器作为任务现场的一部分;
浮点——MQX 保存浮点寄存器作为任务现场的一部分;
时间片——MQX 为任务使用轮循调度(默认是FIFO 调度);
用户任务——MQX为用户指定的任务
其实上面这些个属性我只用过自启动,其它的都没用过!也不知道什么情况下用,不过不要紧,目前已经够我用了,现在先了解一下,哪天说不定就理解并应用了。
还有其它两个:
任务参数:有时候会有用,但是它是一个(void *)型的指针,用的时候需要进行强制转换,现在不管他
时间片:我也没用过,呵呵
现在再看一下这个任务函数:
- /*TASK*-----------------------------------------------------
- *
- * Task Name : hello_task
- * Comments :
- * This task prints " Hello World "
- *
- *END*-----------------------------------------------------*/
- void hello_task
- (
- uint32_t initial_data
- )
- {
- (void)initial_data; /* disable 'unused variable' warning */
- printf("Hello World\n");
- _task_block();
- }
复制代码
好简单哦,就是打印一个Hello World\n到串口去,然后就退出了。_task_block函数的意思就是切换到其它的任务去,也就是说该任务结束了!
现在我用TWR运行了一下,结果如图所示:
嗯,看来这个任务是只运行一次啊!我想我现在可以修改它,让它变成循环运行,我想让它每一秒就输出一次:
- void hello_task
- (
- uint32_t initial_data
- )
- {
- (void)initial_data; /* disable 'unused variable' warning */
- int i;
- for(i = 0; ;i++)
- {
- printf("Hello World %d time\n", i);
- _time_delay(1000);
- }
- // _task_block();
- }
复制代码
这个代码跟前后台系统的没太大的区别啊,只是加了一个延时1000ms的函数。对的,在这里需要注意的是,每一个任务中,都必须有一个机制,把CPU让出来,如果任务中缺少这个机制,那么CPU就永驻此任务了,别的任务根本运行不到。在这个任务中,我用到延时来处理的。当然还有其它的一些机制,我们以后再说! _time_delay延时函数是MQX系统的一个函数接口,在处理延时的时候,CPU会去做别的事情,一直到该任务延时结束并且没有比它更高优先级的任务就绪,它才会继续运行。所以这个延时函数是一个大概的时间,不能用来精确计时。
在mqx.h文件中,我们可以找到很多关于时间的函数接口,他们定义在一起,都是MQX系统拥有的,可以按场合进行调用。
改完后的任务运行结果如下:
看到了吧,效果是明显的!
再接下来,我又想添加一个任务,让两个任务同时运行,好吧,这回我们既然要添加任务,就要改动任务列表了:
- const TASK_TEMPLATE_STRUCT MQX_template_list[] =
- {
- /* Task Index, Function, Stack, Priority, Name, Attributes, Param, Time Slice */
- { HELLO_TASK, hello_task, 1500, 8, "hello", MQX_AUTO_START_TASK, 0, 0 },
- { YES_TASK, yes_task, 1500, 9, "yes", MQX_AUTO_START_TASK, 0, 0},
- { 0 }
- };
复制代码
在任务列表中,我添加了一个yes任务,当然,任务ID我用宏定义在文件前面已经定义了,它不会凭空出现的,呵呵。这个任务也属于自启动任务,任务函数如下:
- void yes_task(uint32_t para)
- {
- int i;
- for(i = 0; ;i++)
- {
- printf("yes? %d time\n", i);
- _time_delay(1000);
- }
- }
复制代码
我也是让它每一秒输出一次yes,呵呵,既然有人叫,咱就应一下吧,编译下载后,我们看结果是不是叫一秒叫一次,这边应一次:
看到了吧,是真的!呵呵!现在我已经成功的跑起来两个任务了!当然你如果还想加的话,可以随便加哦,只要不超过255个
这个是简单的两个任务,其实还有其它的方法创建任务,比如用MQX接口函数来创建,任务也有一堆接口函数:
- extern _mqx_uint _task_abort(_task_id);
- extern void _task_block(void);
- extern bool _task_check_stack(void);
- extern _task_id _task_create(_processor_number, _mqx_uint, uint32_t);
- extern _task_id _task_create_blocked(_processor_number, _mqx_uint, uint32_t);
- extern _task_id _task_create_at(_processor_number, _mqx_uint,
- uint32_t, void *, _mem_size);
- extern _mqx_uint _task_destroy(_task_id);
- extern void _task_disable_fp(void);
- extern bool _task_enable_fp(void);
- extern _task_id _task_get_creator(void);
- extern void *_task_get_environment(_task_id);
- extern TASK_EXCEPTION_FPTR _task_get_exception_handler(_task_id);
- extern _mqx_uint _task_get_error(void);
- extern _mqx_uint *_task_get_error_ptr(void);
- extern TASK_EXIT_FPTR _task_get_exit_handler(_task_id);
- extern _task_id _task_get_id(void);
- extern _task_id _task_get_id_from_name(char *);
- extern _task_id _task_get_id_from_td(void *);
- extern _mqx_uint _task_get_index_from_id(_task_id);
- extern uint32_t _task_get_parameter(void);
- extern uint32_t _task_get_parameter_for(_task_id);
- extern _processor_number _task_get_processor(_task_id);
- extern _mqx_uint _task_get_priority(_task_id, _mqx_uint_ptr);
- extern void *_task_get_td(_task_id);
- extern _mqx_uint _task_get_template_index(char *);
- extern TASK_TEMPLATE_STRUCT_PTR _task_get_template_ptr(_task_id);
- extern void _task_ready(void *);
- extern _mqx_uint _task_restart(_task_id, uint32_t *, bool);
- extern void *_task_set_environment(_task_id, void *);
- extern _mqx_uint _task_set_error(_mqx_uint);
- extern TASK_EXCEPTION_FPTR _task_set_exception_handler(_task_id,TASK_EXCEPTION_FPTR);
- extern TASK_EXIT_FPTR _task_set_exit_handler(_task_id,TASK_EXIT_FPTR);
- extern uint32_t _task_set_parameter(uint32_t);
- extern uint32_t _task_set_parameter_for(uint32_t, _task_id);
- extern _mqx_uint _task_set_priority(_task_id, _mqx_uint, _mqx_uint_ptr);
- extern void _task_stop_preemption(void);
- extern void _task_start_preemption(void);
- extern _mqx_uint _task_reserve_space(_mqx_uint);
- extern void *_task_get_reserved_base(void);
- #if MQX_ENABLE_USER_MODE
- extern _task_id _usr_task_create(_processor_number, _mqx_uint, uint32_t);
- extern _mqx_uint _usr_task_destroy(_task_id);
- extern _mqx_uint _usr_task_abort(_task_id task_id);
- extern _mqx_uint _usr_task_set_error(_mqx_uint);
- extern void *_usr_task_get_td(_task_id);
- extern void _usr_task_ready(void *);
- #endif
- extern void *_taskq_create(_mqx_uint);
- extern _mqx_uint _taskq_destroy(void *);
- extern _mqx_uint _taskq_resume(void *, bool);
- extern _mqx_uint _taskq_suspend(void *);
- extern _mqx_uint _taskq_suspend_task(_task_id, void *);
- extern _mqx_uint _taskq_test(void **, void **);
- extern _mqx_uint _taskq_get_value(void *);
复制代码
这些都在mqx.h中可以找得到,也在《Freescale MQX实时操作系统用户手册》中有说明,甚至有一些还有例程。我就不再说了!
现在已经把任务跑起来了,下次我想我应该做任务的同步了!
希望能对想学OS的同学有帮助!话说我今天真的把附件用完了,现在想把源文件传上来也传不了了!
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|