rtt操作系统简介

上传人:豆浆 文档编号:10586857 上传时间:2017-09-02 格式:PDF 页数:15 大小:418.47KB
返回 下载 相关 举报
rtt操作系统简介_第1页
第1页 / 共15页
rtt操作系统简介_第2页
第2页 / 共15页
rtt操作系统简介_第3页
第3页 / 共15页
rtt操作系统简介_第4页
第4页 / 共15页
rtt操作系统简介_第5页
第5页 / 共15页
点击查看更多>>
资源描述

《rtt操作系统简介》由会员分享,可在线阅读,更多相关《rtt操作系统简介(15页珍藏版)》请在金锄头文库上搜索。

1、 对于简单的任务可以设计成串行的程序设计,但对于同时需要处理多个输入输出 的程序串行设计就有点满足不了需求了,这时软件就需求设计成多任并行系统。 并行 设计需要开发人员把一个应用分解成一个个小的,可调度 的。 操作系统的核心就是多任务的创建及任务间调度 管理和任务间通信机制。 Rt-thread操作系统中线程有初始 态、就绪态、运行态、挂起 态、关闭这五种状态, 线程间切换是通过一个调度器来实现的。 RT-Thread共支持 256个优先级 (0-255,数值越小的优先级越高, 0为最高优先级 , 255分配给空闲线程使用;线程总数不受限制,只和能提供给系统的 ram有关 ), 我们 一般通过

2、在 rt_config.h配置文件中将系统配置为 32个 优先级 /* PRIORITY_MAX */ #define RT_THREAD_PRIORITY_MAX 32 同时 rtt还支持相同优先级线程, RT-Thread系统中,不同优先级的线程根据 优先级 顺序 进行调度;相同优先级的线程根据时间片来调度。 一 多任务操作系统介绍: 二 线程接口函数: 设计一个新的应用程序时主要用到的线程接口函数有如下几个: 1. 创建个动态线程 rt_thread_t rt_thread_create(const char* name, void (*entry)(void* parameter),

3、void* parameter, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick); 2.初始化静态线程 注:静态线程必须先初始化,与动态线程序的区别是动态线程在删除后由 调度器自动收回动态分配的内容,而静态线程是一个静态全局的 rt_thread 结构体类型变量,删除后也不收回。 rt_thread_init(struct rt_thread* thread, const char* name, void (*entry)(void* parameter), void* parameter, void* stack_

4、start, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick); 3.动态线程使用函数 rt_thread_delete()删除 4.静态线程使用函数 rt_thread_detach()脱离 注意: rt_thread_delete()与 rt_thread_create()对应, rt_thread_detach() 与 rt_thread_init()对应。 5.启动线程 rt_thread_startup(rt_thread_t thread); 启用线程后线程将变为就绪状态,如果是最高的优先级则进入线程对应的

5、 入口函数 6. rt_thread_self(void) 返回当前线程 7.线程睡眠 rt_err_t rt_thread_sleep(rt_tick_t tick); rt_err_t rt_thread_delay(rt_tick_t tick); 8.线程挂起 rt_thread_suspend (rt_thread_t thread); 9.线程恢复 rt_thread_resume (rt_thread_t thread) 二 调度器接口函数 : 1.初始化调度器 rt_system_scheduler_init(void) 2.启动调度器 rt_system_scheduler_

6、start() 3.执行调度 rt_schedule(void) 4.设置调度器勾子函数 rt_scheduler_sethook(void (*hook)(struct rt_thread* from, struct rt_thread* to) 三 线程间通信 在多任务实时系统中,一项工作的完成往往可以通过多个任务协调的方式共同来完成 ,例如 一个任务从传感器中接收数据并且将数据写到共享内存中,同时另一个任务周期性的 从共享 内存中读取数据并发送去显示(如图两个线程间的数据传递) 。 如图两 个线程间的 数据传递如果 对共享内存的访问不是排他性的,那么各个线程间可能同时访问它。这将引起 数

7、据一致性 的问题,例如,在显示线程试图显示数据之前,传感器线程还未完成数据的写入, 那么 显示将包含不同时间采样的数据,造成显示数据的 迷惑。 正常的操作 序列应该 是在一个线程对共享内存块操作完成后,才允许另一个线程去操作。对于操作 /访问 同一块 区域,称之为临界区。任务的同步方式有很多种,其核心思想都是:在访问临界区的 时候 只允许一个 (或一类 )任务运行。 线程间通信有如下几种形式: 1.关中断 2.调度器 锁 3.信号量 4.互斥 量 5.事件 6.邮箱 7.消息队列 信号量: 信号量有点像停车厂的停车系统,信号量是一个非负整型值,当创建一个信号量后, 一个线程获得了此信号量将使信

8、号量值减 1,如果另一个线程在信号量值为 0时获取 信号量时该线程将被挂起,直到其它获得信号量的线程释放信号量。 初始化 rt_sem_init()(对应静态信号量); 建立 rt_sem_create()(对应动态信号量); 获取 rt_sem_take(); 释放 rt_sem_release(); 脱离 rt_sem_detach()(对应静态信号量); 删除 rt_sem_delete()(对应动态信号量); 注:当初始化信号量的值为 0时,所有试图获得该信号量的线程都将被挂起 , 当 某外部事业触发 了 rt_sem_release()后信号量值进行自加,然后查询是否有等 待的线程,

9、如果有则执行调度。 例: result =rt_sem_init(&key_sem, keysem, 0, RT_IPC_FLAG_FIFO); 线程 1 rt_sem_release(&key_sem); /* 释放一次信号量 */ Led线程 2 rt_sem_take(&key_sem, RT_WAITING_FOREVER); GPIO_ResetBits(led1_gpio,led1_pin|led2_pin|led3_pin|led4_pin); /点灯 互斥锁和信号量很 相似 ,在此就不介绍了 邮箱: 邮箱服务是实时操作系统中一种典型的任务间通信方法,通常开销比较低,效率较高,每

10、一封邮件只能容纳固定的 4字节内容(针对 32位处理系统,刚好能够容纳一个指针)。典型的邮箱也称作交换消息,如下图所示,线程或中断服务例程把一则 4字节长度(典型的是一个指针)的邮件发送到邮箱中。而一个或多个线程可以从邮箱中接收这些邮件进行处理。 RT-Thread采用的邮箱通信机制有点类型传统意义上的管道,用于线程间通讯。它是线程、中断服务、定时器向线程发送消息的有效手段。邮箱与线程对象等之间是相互独立的。线程,中断服务和定时器都可以向邮箱发送消息,但是只有线程能够接收消息(因为当邮箱为空时,线程将有可能被挂起)。 RT-Thread的邮箱中共可存放固定条数的邮件,邮箱容量在创建邮箱时设定,

11、每个邮件大小为 4字节,正好是一个指针的大小。当需要在线程间传递比较大的消息时,可以传递指向一个缓冲区的指针。当邮箱满时,线程等不再发送新邮件,返回 -RT EFULL。当邮箱空时,将可能挂起正在试图接收邮件的线程,使其等待,当邮箱中有新邮件时,再唤醒等待在邮箱上的线程,使其能够接收新邮件并继续后续的处理。 RT-Thread中的邮箱依然是有静态和动态之分,和邮箱有关的操作如下: 初始化 rt_mb_init()(对应静态邮箱); 建立 rt_mb_create()(对应动态邮箱) ; 发送邮件 rt_mb_send(); 接收邮件 rt_mb_recv(); 脱离 rt_mb_detach(

12、)(对应静态邮箱); 删除 rt_mb_delete()(对应动态邮箱); 例子: 初始化静态邮箱 /* 初始化一个静态邮箱 */ result = rt_mb_init(&mb, mbt,/* 名称是 mbt */ &mb_pool0,/* 邮箱用到的内存池是 mb_pool */ sizeof(mb_pool)/4,/* 邮箱中的邮件数目,因为一封邮件占 4字节 */ RT_IPC_FLAG_FIFO);/* 采用 FIFO方式进行线程等待 */ 按键线程 switch(s_KeyCode) case KEY_ALL_NSET &(KEY_UP_PIN):/up key_info4=1;

13、break; case KEY_ALL_NSET &(KEY_DOWN_PIN):/down key_info4 /* 这里我们向邮箱中发一个指针 */ rt_mb_send(&mb,(rt_uint32_t )&key_info0); Led 线程 if(rt_mb_recv(&mb,(rt_uint32_t*)&str, RT_WAITING_FOREVER)= RT_EOK) rt_kprintf(led: get a mail from mailbox, the content:%sn, str); /*判断邮件内容 */ if(str4=1) led_state =0x01; if(

14、str4=2) led_state =0x02; if(str4=3) led_state =0x03; if(str4=4) led_state =0x04; if(led_state=1) GPIO_ResetBits(led1_gpio,led1_pin); 消息队列 : 消息队列是另一种常用的线程间通讯方式,它能够接收来自线程的不固定长度的消息(而邮件只能容纳固定的 4字节内容),并把消息缓存在自己的内存空间中。其他线程也能够从消息队列中读取相应的消息,而当消息队列是空的时候,可以挂起读取线程。而当有新的消息到达时,挂起的线程将被唤醒以接收并处理消息。 /* 初始化消息队列 */ 1.

15、 rt_mq_init(&mq, mqt, &msg_pool0, /* 内存池指向 msg_pool */ 128 - sizeof(void*), /* 每个消息的大小是 128 - void* */ sizeof(msg_pool), /* 内存池的大小是 msg_pool的大小 */ RT_IPC_FLAG_FIFO); /* 如果有多个线程等待,按照 FIFO的方法分配消息 */ 2.rt_mq_recv(&mq, &buf0, sizeof(buf), RT_WAITING_FOREVER) 3.rt_mq_send(&mq, &buf0, sizeof(buf) 4. rt_mq_urgent(&mq, &buf0, sizeof(buf); 事件: RT-Thread中的事件用一个 32位无符号整型变量来表示,变量中的一位代表一个事件,线程通过“逻辑与”或“逻辑或”与一个或多个事件建立关联形成一个事件集。 1. /* 初始化事件对象 */ result = rt_event_init(&event, event, RT_IPC_FLAG_FIFO); 2.按钮扫描线程 rt_event_send(&event,(1

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号