ImageVerifierCode 换一换
格式:DOCX , 页数:32 ,大小:130.51KB ,
资源ID:12064057      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/12064057.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(LXRTRTAI用户空间编程.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

LXRTRTAI用户空间编程.docx

1、LXRTRTAI用户空间编程LXRTRTAI的用户空间编程目录一. rt_task_init_schmod(启用RTAI实时功能/实时任务的创建) 21. 函数 22. 参数 23. 注意 24. 示例代码 2二. 实时任务定时器设置(rt_set_oneshot_mode等) 21. rt_set_oneshot_mode 32. rt_set_periodic_mode 33. start_rt_timer 34. 注意 35. 示例代码 3三. rt_task_make_periodic(定期运行一个任务) 41. 函数 42. 参数 43. 注意 4四. 代码基础框架 41. Make

2、file 42. run 43. .runinfo 44. 代码 4五. 注意事项 71. 所谓的LXRT实即Linux Real Time module,不存在LXRT scheduler 72. LXRT下的硬实时相对于内核态下而言仍有若干微秒的差别 73. 在进入和离开LXRT域这两段时间,系统的实时性是无法保证的。 74. LXRT Tips And Tricks 8六. 管道通讯 81. 发送函数 82. 接收函数 83. 示例代码 9七. 共享内存通讯 121. 创建函数 122. Free函数 12一. rt_task_init_schmod(启用RTAI实时功能/实时任务的创建

3、)实时任务的创建主要完成对代表实时任务实体的任务结构变量的初始化操作,包括分配任务栈、初始化任务栈、初始化链表指针等。1. 函数RT_TASK* rt_task_init(unsigned long name, int priority, int stack_size, int max_msg_size)RT_TASK*rt_task_init_schmod(unsigned long name, int priority, int stack_size, intmax_msg_size, int policy, int cpus_allowed)正如你可以看到的,有两个选项可以用来创建一个用

4、户模式下的实时任务。在用户模式下,rt_task_init被认为是一个更简单但因此有限的捷径。总之他们都可以用于这个特定的目的。只是为了记录第一个被定义为以下的:RTAI_PROTO(RT_TASK *,rt_task_init,(unsigned long name, int priority, int stack_size, int max_msg_size)return rt_task_init_schmod(name, priority, 0, max_msg_size, SCHED_FIFO, 0xFF);它的意思是,它使用SCHED_FIFO策略并且设置cpu允许0XFF。他们创建

5、一个新的实时任务在用户空间,或者更好的说法是,他们在用户空间为LINUX进程/任务创建了一个RTAI任务扩展。2. 参数Name:任务名。Priority:任务优先级,0最高。stack_size:栈大小(不再被使用的遗留参数,只是为了可移植性才保留的)。默认值是512。max_msg_size:可为0,在这种情况下使用一个默认的内部值。默认值为256。为了适合你的需求,有可能需要设置一个更大的值。在这种情况下,要么合理设置宏MSG_SIZE来重新编译sys.c,要么在这里明确分配大点的尺寸。但是,注意这点,消息大小不是关键的。事实上在任何需要的时候,模块都会重新分配它,动态并且设置好了合适的

6、大小。policy:调度策略,默认的是SCHED_FIFO,也可以设置成 RT_SCHED_RR。RR只是在有多个使用相同的优先级并且不释放CPU的任务的时候使用,。在这种情况下,RR政策将会照顾它的平衡cpus_allowed:你想让任务运行的CPU。它是个bit。当RTAI希望一个任务静态地在一个特定的CPU上运行的时候,它是强制性的。注意,如果你想在任务创建之后改变CPU,这一举动将会杀死real_time。如果指定了更多的bit,RTAI通过尽量平衡这工作强迫任务运行在第一个可用的CPU上。/SMP用的3. 注意 消息有个动态内存增加,每次buffer大小溢出时,现有的都会被释放,RT

7、AI real_time heap会新创建一个大约比原来大20%新buffer。这个操作显然是时间消费, 所以为了最好的性能表现,强烈建议从最初始阶段就定义正确的大小。4. 示例代码int main(void)RT_TASK *Main_Task;if (!(Main_Task = rt_task_init_schmod(nam2num(MNTSK), 0, 0, 0, SCHED_FIFO, 0xF) printf(CANNOT INIT MAIN TASKn);exit(1);return 0;二. 实时任务定时器设置(rt_set_oneshot_mode等)在创建实时任务的过程中,主要

8、通过3个函数对定时器进行设置,它们分别是:rt_set_oneshot_mode,rt_set_periodic_mode和start_rt_timer,下面分别对这3个函数进行分析。1. rt_set_oneshot_mode用于将定时器设置为单触发模式,所谓单触发模式,就是说,每当定时器产生一次中断后,系统都要根据目前系统任务对时间精度的要求情况对定时器重新进行编程,设定下一次触发的时间。rt_set_oneshot_mode完成的功能如下:1.调用stop_rt_timer停止定时器的运行;2.设置全局变量oneshot_timer的值为1;在时钟中断函数中,系统会检查oneshot_t

9、imer的值,判断定时器的工作模式,然后根据定时器的模式对定时器进行相应的操作。2. rt_set_periodic_modert_set_periodic_mode的操作与rt_set_oneshot_mode的类似,只不过它将oneshot_timer的值设为0,表示定时器应工作在周期模式;当定时器工作在周期模式下时,系统只要对定时器进行一次初始化,指定定时器产生中断的周期,以后就不再需要对定时器进行编程了。3. start_rt_timer根据设定的定时器运行模式对定时器进行初始化,它完成的主要功能如下:1.调用函数rt_request_timer注册时钟中断服务程序rt_timer_h

10、andler;2.初始化系统用于保存时间信息的结构rt_smp_times(就是前面所说的rt_times);3.调用rt_request_linux_irq注册一个Linux下的中断服务程序recover_jiffies,这个中断程序和Linux的时钟中断服务程序共享时钟中断,recover_jiffies用于补偿Linux所丢失的时钟中断(因为可能由于实时任务的运行,使Linux很长一段时间得不到运行的机会,无法响应时钟中断)。4. 注意 请注意,如果你不设置模式,默认是周期性的。 使用stop_rt_timer停止定时器,会设置定时器返回默认的状态(即周期性的)。如果没有删除在使用的RT

11、AI调度程序,你想确定在多模块上是单触发模式,在每一个start_rt_timer前总要调用rt_set_oneshot_mode。 使用start_rt_timer(0),自动强制进入单触发模式。 rt_is_hard_timer_running API可以知道是否已经有个计时器在运行了,该函数应该小心使用,因为它会形成一个“race”情况。 在使用任何与时间处理相关的函数前调用start_rt_timer API很重要,否则所有的值都被认为是错误的。 实时任务(本文所指的实时任务,如果没有特别说明都是硬实时的)都是以Linux内核模块方式实现的,要实现一个实时任务,在模块初始化的时候要调用

12、RTAI的任务创建函数初始化实时任务相关的数据和环境,指定定时器的运行模式(单触发模式或周期模式),初始化定时器,然后开始执行任务;需要注意的是,当没有加载任何RTAI的实时任务模块的时候,RTAI的任务调度和时钟中断都没有启动。5. 示例代码#define TICK_TIME 1000000if (hard_timer_running = rt_is_hard_timer_running()printf(Skip hard real_timer setting.n);sampling_interval = nano2count(TICK_TIME);elseprintf(Starting r

13、eal time timer.n);rt_set_oneshot_mode();start_rt_timer(0);sampling_interval = nano2count(TICK_TIME);三. rt_task_make_periodic(定期运行一个任务)1. 函数在这个阶段,计时器根据定时器政策选择(单触发vs周期)以适当的周期运行,它允许设置一个实时任务定期调度。这可以用以下API实现:Int rt_task_make_periodic (RT_TASK *task, RTIME start_time, RTTIME period);Int rt_task_make_perio

14、dic (RT_TASK *task, RTIME start_delay, RTTIME period);2. 参数task任务指针,之前由rt_task_init()创建的,当rt_task_wait_period()被调用时,以period为周期执行。start_time:第一次执行时间,是一个以clock ticks测量的绝对值。start_delay:第一次执行时间,相对于当前时间,以纳秒测量。period:任务循环周期。3. 注意 为了更方便的处理clock ticks和纳秒,在rtai_sched.h中有两个宏定义能帮助你,他们是RTIME count2nano (RTIME t

15、imercounts);RTIME nano2count (RTIME nanosecs);,它们只转换时间单位,但是你要记住,计数单位与选择的时间模式(单触发/周期)相关。 Recall that the term clock ticks depends on the mode in which the hard timer runs. So ifthe hard timer was set as periodic a clock tick will last as the period set in start_rt_timer,while if oneshot mode is used

16、a clock tick will last as the inverse of the runningfrequency of the hard timer in use and irrespective of any period used in the call tostart_rt_timer.四. 代码基础框架前面先准备三个文件:1. MakefileTARGET = periodic_task SRCS = periodic_task.c prefix := $(shell rtai-config -prefix)ifeq ($(prefix),)$(error Please ad

17、d /bin to your PATH variable)endifOBJECTS = $(SRCS:.c=.o)CC = $(shell rtai-config -cc)LXRT_CFLAGS = $(shell rtai-config -lxrt-cflags)LXRT_LDFLAGS = $(shell rtai-config -lxrt-ldflagsall: $(TARGET)%.o: %.c $(CC) -c $(LXRT_CFLAGS) $(TARGET) : $(OBJECTS) $(CC) -o $(TARGET) $(LXRT_LDFLAGS) -llxrt $(OBJEC

18、TS)clean: rm -f *.o * core.* $(TARGET).PHONY: clean2. run实际上是调用rtai-load来运行的.$DESTDIR/usr/realtime/bin/rtai-load3. .runinfo隐藏文件rtai-load根据这个来运行prog_name:lxrt+sem+mbx+msg+fifos:!./prog_name; popall:control_c(2 、3步骤可以简化成另一种方式,直接进入RTAI安装目录,然后insmod rtai_hal.ko insmod rtai_sched.ko insmod rtai_lxrt.ko,然

19、后运行程序./prog_name 就行了)4. 代码 单触发模式#include #include #include #include #include #include #include /#include /#include #include #include #include /#include /#include static int thread0;static void *fun0(void *arg)RT_TASK *task;task = rt_task_init_schmod(nam2num(TASK0), 0, 0, 0, SCHED_FIFO, 0xF); mlockal

20、l(MCL_CURRENT | MCL_FUTURE);/设置优先级和调度算法 这里他用SCHED_FIFO,而SCHED_OTHER(基于时间片)优先会低些,这个Name就是实时任务的标识nam2num 是把名字转为name id 以免命名冲突 / 进入硬实时模式,无此语句时,默认的是软实时/rt_make_hard_real_time();/此处添加代码,如下语句/rt_printk(Hello World!n);/将实时任务或者线程返回到标准linux的状态rt_make_soft_real_time();/删除任务rt_task_delete(task); return 0;int m

21、ain(void) RT_TASK *task; / make main thread LXRT soft realtime task = rt_task_init_schmod(nam2num(MYTASK), 9, 0, 0, SCHED_FIFO, 0xF); mlockall(MCL_CURRENT | MCL_FUTURE); / start realtime timer and scheduler rt_set_oneshot_mode(); start_rt_timer(0); / create a linux thread thread0 = rt_thread_create(

22、fun0, NULL, 10000); / wait for end of program printf(TYPE TO TERMINATEn); getchar(); / cleanup stuff stop_rt_timer(); return 0; 周期模式#include #include #include #include #include #include #include #define TICK_TIME 1000000#define CPUMAP 0x1static RT_TASK *main_Task;static RT_TASK *loop_Task;int keep_o

23、n_running = 1;static pthread_t main_thread;static RTIME expected;static RTIME sampling_interval;static void *main_loop()if (!(loop_Task = rt_task_init_schmod(nam2num(RTAI01), 2, 0, 0, SCHED_FIFO, CPUMAP) printf(CANNOT INIT PERIODIC TASKn);exit(1);/mlockall(MCL_CURRENT | MCL_FUTURE);(源代码没有,?)expected

24、 = rt_get_time() + 100*sampling_interval;rt_task_make_periodic(loop_Task, expected, sampling_interval);/rt_make_hard_real_time();while (keep_on_running)/insert your main periodic loop herert_task_wait_period();/set keep_on_running to 0 if you want to exitrt_task_delete(loop_Task);return 0;int main(v

25、oid)RT_TASK *Main_Task;if (!(Main_Task = rt_task_init_schmod(nam2num(MNTSK), 0, 0, 0, SCHED_FIFO, 0xF) printf(CANNOT INIT MAIN TASKn);exit(1);/mlockall(MCL_CURRENT | MCL_FUTURE); (源代码没有,?)if (hard_timer_running = rt_is_hard_timer_running()printf(Skip hard real_timer setting.n);sampling_interval = na

26、no2count(TICK_TIME);elseprintf(Starting real time timer.n);rt_set_oneshot_mode();start_rt_timer(0);/启动计时器 记得用完要关掉sampling_interval = nano2count(TICK_TIME);pthread_create(&main_thread, NULL, main_loop, NULL);while (keep_on_running)sampling_interval = sampling_interval; /do nothing!rt_task_delete(Main

27、_Task);return 0;五. 注意事项1. 所谓的LXRT实即Linux Real Time module,不存在LXRT scheduler所谓的LXRT实即Linux Real Time module,不存在LXRT scheduler。RTAI下只有3种调度器,UP,SMP和MUP。LXRT的存在使得RTAI所有的调度函数都能在Linux进程中直接调用。这样一来,RTAI的实时服务就具备了所谓的“完全对称”在RTAI域和LINUX域中的使用几乎完全一样。也就是说,用户可以在LINUX和LINUX间,RTAI和LINUX间共用内存,发送消息,调用semaphore或时间相关服务,当

28、然,在RTAI和RTAI之间更不是问题。(源自DIAPM RTAI - Beginners Guide,https:/www.rtai.org/index.php?module=documents&JAS_DocumentManager_op=downloadFile&JAS_File_id=32)2. LXRT下的硬实时相对于内核态下而言仍有若干微秒的差别LXRT下的hard real time还是与内核态任务的执行有着本质区别的。RTAI通过其RTAI_PROTO为用户态下进程提供调用内核API的捷径,并由RTAI自身的调度器保证了RTAI任务对中断的优先权。处于中断处理链条终端的LINU

29、X因此不能破坏RTAI任务的实时性能。但无论如何,context switch是需要时间的。在RTAI域内用户态和内核态的切换也免不了牺牲一定的时间开销。RTAI相关的文档指出LXRT下的硬实时相对于内核态下而言仍有若干微秒的差别。笔者也在试验中发现,前者实时性能与后者相比相差约有十几微秒,有时甚至更多。对于一些要求苛刻的实时任务而言,LXRT下的时延(或者还有实时误差?)是无法接受的。3. 在进入和离开LXRT域这两段时间,系统的实时性是无法保证的。也就是说,在时间轴上的这两个区间,所有LXRT任务并非处于真正的硬实时状态,期间任何操作都有可能因其不稳定性导致1020微秒的实时误差(具体数值

30、未做严密测量)。这一点在RTAI自身文档中也有阐述,但因为不引人注意,使得基于RTAI/LXRT的实时控制开发人员非常容易忽略。对这一问题的最简单处理办法就是在调用rt_make_hard_real_time()后随即插入短暂的等待,再进入实时处理阶段。实践中笔者在等待500微秒后得到理想的实时表现。4. stop_rt_timer是全局变量,如果在进程中某个线程结束时候使用,则会结束全部线程的定时器。解决这种情况可以,一,全部用周期,这样既不用去start也不用去stop;二,每个单独启动oneshot定时,然后在最后再结束。5. LXRT Tips And Tricks六. 管道通讯包含头文件#include rtai_sched.h1. 发送函数int rt_mbx_send (MBX* mbx, void*

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1