一、背景:
应用实时性:应用程序1以固定周期执行实时算法;
应用程序2以固定周期,执行串口收发;
驱动实时性:驱动sdio接口,实现与FPGA数据交互,实现串口数据收发。
二、实时性保证:
1、linux系统:
打上rt_preempt补丁,早起的内核版本支持CONFIG_RT_BASE内核配置,后来的内核版本直接去掉了,只存在CONFIG_RT_FULL内核配置;前者表示只把中断函数线程化,后者表示原子锁互斥化+中断函数线程化。
被线程化的中断函数,使用一个内核线程来实现中断下半部处理,调度策略为RR,优先级为50。
2、linux驱动:
sdio以工作队列方式发起sdio请求,工作队列选取hi优先级,绑定固定core3;并且通过bootargs参数中增加isolate=8方式隔离core3。然后通过中断和workqueue绑定到core3,以保证底层的数据收发不被应用干扰。
3、linux应用:
deadline调度策略,保证应用程序的实时调度。
sysctl -w kernel.sched_rt_runtime_us=-1
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
-
- struct sched_attr {
- uint32_t size;
-
- uint32_t sched_policy;
- uint64_t sched_flags;
-
- /* SCHED_NORMAL, SCHED_BATCH */
- int32_t sched_nice;
-
- /* SCHED_FIFO, SCHED_RR */
- uint32_t sched_priority;
-
- /* SCHED_DEADLINE (nsec) */
- uint64_t sched_runtime;
- uint64_t sched_deadline;
- uint64_t sched_period;
- };
-
- int sched_setattr(pid_t pid, const struct sched_attr *attr, unsigned int flags)
- {
- return syscall(__NR_sched_setattr, pid, attr, flags);
- }
-
- pthread1_main()
- {
- struct sched_attr attr;
- attr.size = sizeof(attr);
- attr.sched_flags = 0;
- attr.sched_nice = 0;
- attr.sched_priority = 0;
-
- /* This creates a 300us/500us reservation */
- attr.sched_policy = SCHED_DEADLINE;
- attr.sched_runtime = 300 * 1000;
- attr.sched_period = attr.sched_deadline = 500 * 1000;
- tid = syscall(SYS_gettid);
- ret = sched_setattr(tid, &attr, 0);
- if (ret != 0)
- {
- perror("sched_setattr");
- printf("exit!\n");
- exit(-1);
- }
- while(1)
- {
- ..........
- sched_yield();
- }
- }
4、系统接口:
使用异步接口,mmap方式共享内核内存。
三、场景复杂性:
实时的应用程序占用CPU会比较高,特别是应用中的实时任务比较多,会占用CPU大概到60%左右,导致系统负载过大。基于RT_FULL的kernel_patch,甚至会导致cpu stall现象出现。