目录
应用场景
Stateflow实现调度
Stateflow实现优先级控制
在嵌入式ECU开发中,应用层的大部分功能都是周期性任务或中断型任务。例如1ms、5ms、10ms、500ms...的周期性任务,在不同周期任务中实现信号处理、状态管理、故障诊断等。对于一些实时性要求比较高的,例如电机FOC算法,则常会在PWM中断任务中进行处理。
应用层模型中一般都会有信号处理和诊断模块,将各类信号分类成多个子模块,而各类信号的更新速率要求是不同的,例如电流、电压信号我们希望每10ms或者5ms更新一次,而温度信号每500ms或1000ms更新一次就可以了。
如果不加区分的把很多子模块都放在同一个周期任务中运行,子模块很多,且都是些查表、复杂算术运算的话,会使得CPU负载率偏高,需要对各个子功能模块进行适当的调度。
在一些非AUTOSAR架构,且无RTOS的‘裸奔’ECU中,通常会在基础软件中设计一调度器,实现各个功能任务的合理调度,而在应用层模型中我们也可以使用Stateflow来实现一定的模型调度功能
我们可以使用Stateflow创建如下一个调度器:
子系统的调用:
同一周期的任务都会放在同一个Function Call Subsystem里面,再按照一定的顺序执行,例如FunA_B子系统内部有FunA和FunB两个子系统,这里都放在10ms任务中进行调用
假设此模块最终生成一个step函数,代码集成时在基础软件1ms任务中调用此step函数,则可以使用此Timer_Task_Scheduler调度器实现5ms、10ms、100ms...周期任务的调度
上述模型生成代码如下:
这种调度方式,我们可以用以下示意图来表示,可能更直观:
基本采样时间为1ms,function 2-1、2-2、2-3均为5ms任务,function 3-1、3-2、3-3均为10ms任务。function 2-1、2-2、2-3会在同一个5ms任务中依次被调用,而function 3-1、3-2、3-3会在同一个10ms任务中依次被调用
在上面方法的基础上,我们可以再对任务进行‘软分频’,与第一种方法相比,思路基本相同,只是对每个周期性任务,我们可以选择不同的‘起始时刻’
基本采样时间1ms,以5ms任务为例,每当计数器cntr_5_cycle == 1时触发Timer_5msTask1_FunCall任务,计数器cntr_5_cycle == 2时触发Timer_5msTask2_FunCall任务。这两任务的周期均是5ms ,但Timer_5msTask2_FunCall要比Timer_5msTask1_FunCall晚1ms触发 。
例如对以下模块进行调度:
生成的代码如下:
调度器功能示意图:
基本采样时间为1ms,function 2-1、2-2、2-3均为5ms任务,function 3-1、3-2、3-3均为10ms任务。
在单任务情况下,有一个基本采样时间例如1ms,我们就可以使用上述调度器创建5ms、10ms、100ms...等‘伪采样’时间(同理,基本采样时间为2ms时,可以创建4ms、8ms、10ms...‘伪采样’时间),使用这种‘软件分频’的方式,可以实现周期性任务的调度,当然这没有直接使用ECU硬件定时中断触发来的精准。
在选择调度方式时,还需要考虑下各任务模块对信号实时性的要求
Simulink模型中子系统的执行顺序通常会受信号流以及子系统位置的影响,虽然Simulink Subsystem模块提供了Priority属性可以控制子系统的优先级,但很多建模规范中并不推荐使用此方法
我们可以使用Stateflow建立一个优先级控制模块,‘显示’的来控制各个子系统的执行顺序
例如有ResolverHandle旋变信号处理、Cos_Sin三角函数处理、CurrHandle电流采样处理,三个子系统模块,在无优先级控制的情况下,因为ResolverHandle、Cos_Sin有信号传递,生成的代码中Cos_Sin会紧跟着ResolverHandle
为了保证旋变信号和电流信号的采样时刻尽可能的接近,我们希望ResolverHandle函数之后紧跟着的是CurrHandle函数,最后再进行Cos_Sin三角函数运算。
可以使用上述建立的Stateflow优先级控制模块,对这三个子系统进行优先级的‘显示’控制,如下图:
生成的代码:
应用场景:
在嵌入式ECU开发中,应用层的大部分功能都是周期性任务或中断型任务。例如1ms、5ms、10ms、500ms...的周期性任务,在不同周期任务中实现信号处理、状态管理、故障诊断等。对于一些实时性要求比较高的,例如电机FOC算法,则常会在PWM中断任务中进行处理。
应用层模型中一般都会有信号处理和诊断模块,将各类信号分类成多个子模块,而各类信号的更新速率要求是不同的,例如电流、电压信号我们希望每10ms或者5ms更新一次,而温度信号每500ms或1000ms更新一次就可以了。
如果不加区分的把很多子模块都放在同一个周期任务中运行,子模块很多,且都是些查表、复杂算术运算的话,会使得CPU负载率偏高,需要对各个子功能模块进行适当的调度。
在一些非AUTOSAR架构,且无RTOS的‘裸奔’ECU中,通常会在基础软件中设计一调度器,实现各个功能任务的合理调度,而在应用层模型中我们也可以使用Stateflow来实现一定的模型调度功能
Stateflow实现调度:
我们可以使用Stateflow创建如下一个调度器:
子系统的调用:
同一周期的任务都会放在同一个Function Call Subsystem里面,再按照一定的顺序执行,例如FunA_B子系统内部有FunA和FunB两个子系统,这里都放在10ms任务中进行调用
假设此模块最终生成一个step函数,代码集成时在基础软件1ms任务中调用此step函数,则可以使用此Timer_Task_Scheduler调度器实现5ms、10ms、100ms...周期任务的调度
上述模型生成代码如下:
这种调度方式,我们可以用以下示意图来表示,可能更直观:
基本采样时间为1ms,function 2-1、2-2、2-3均为5ms任务,function 3-1、3-2、3-3均为10ms任务。function 2-1、2-2、2-3会在同一个5ms任务中依次被调用,而function 3-1、3-2、3-3会在同一个10ms任务中依次被调用
在上面方法的基础上,我们可以再对任务进行‘软分频’,与第一种方法相比,思路基本相同,只是对每个周期性任务,我们可以选择不同的‘起始时刻’
基本采样时间1ms,以5ms任务为例,每当计数器cntr_5_cycle == 1时触发Timer_5msTask1_FunCall任务,计数器cntr_5_cycle == 2时触发Timer_5msTask2_FunCall任务。这两任务的周期均是5ms ,但Timer_5msTask2_FunCall要比Timer_5msTask1_FunCall晚1ms触发 。
例如对以下模块进行调度:
生成的代码如下:
调度器功能示意图:
基本采样时间为1ms,function 2-1、2-2、2-3均为5ms任务,function 3-1、3-2、3-3均为10ms任务。
在单任务情况下,有一个基本采样时间例如1ms,我们就可以使用上述调度器创建5ms、10ms、100ms...等‘伪采样’时间(同理,基本采样时间为2ms时,可以创建4ms、8ms、10ms...‘伪采样’时间),使用这种‘软件分频’的方式,可以实现周期性任务的调度,当然这没有直接使用ECU硬件定时中断触发来的精准。
在选择调度方式时,还需要考虑下各任务模块对信号实时性的要求
Stateflow实现优先级控制
Simulink模型中子系统的执行顺序通常会受信号流以及子系统位置的影响,虽然Simulink Subsystem模块提供了Priority属性可以控制子系统的优先级,但很多建模规范中并不推荐使用此方法
我们可以使用Stateflow建立一个优先级控制模块,‘显示’的来控制各个子系统的执行顺序
例如有ResolverHandle旋变信号处理、Cos_Sin三角函数处理、CurrHandle电流采样处理,三个子系统模块,在无优先级控制的情况下,因为ResolverHandle、Cos_Sin有信号传递,生成的代码中Cos_Sin会紧跟着ResolverHandle
为了保证旋变信号和电流信号的采样时刻尽可能的接近,我们希望ResolverHandle函数之后紧跟着的是CurrHandle函数,最后再进行Cos_Sin三角函数运算。
可以使用上述建立的Stateflow优先级控制模块,对这三个子系统进行优先级的‘显示’控制,如下图:
生成的代码:
如果你觉得本文能够帮助到你,请长按识别下方二维码关注公众号,另有知乎同名专栏同步更新,欢迎分享转载
文章中的示例模型或代码均可联系小编免费获取,若对文章有任何意见或建议,欢迎在文章下方留言,也可进入公众号选择‘联系方式’,加小编微信进行交流