前言
在《AUTOSAR架构下CanTrcv休眠唤醒问题再探》一问中我们粗略的介绍了CanTrcv中的ICU唤醒相关的功能,但是关于ICU唤醒ECU的描述还不够详细清晰,且含存在很多疑问。本文就来详细梳理下如何通过ICU唤醒ECU,且回答以下问题:
问题1:通过ICU唤醒ECU时,以下3组API有个差异,在什么时机调用他们, 都需要用户手写代码调用么?
Icu_EnableNotification
Icu_EnableNotification
Icu_EnableWakeup
Icu_DisableWakeup
Icu_EnableEdgeDetection
Icu_DisableEdgeDetection
问题2:Icu_SetMode在什么时候调用,有何作用?
问题3:Icu_CheckWakeup在什么时候调用,有何作用?
问题4:不同芯片平台(TC3xx, RH850F1KM, NXPS32K1xx)通过ICU唤醒后的行为有何差异?
目录
注:本文章引用了一些第三方工具和文档,若有侵权,请联系作者删除!
正文
本文假设我们的ECU系统是深度休眠系统(没有SBC,EcuM下电走GoSleep的Go Halt Sequence)。通过CAN Transceiver作为唤醒源及ICU作为中断捕获模块来唤醒ECU,具体硬件逻辑图如下所示:
1)如果使用T1J1043/T1J1145收发器,则使用收发器的INH引脚作为硬件唤醒引脚,且将INH连接到MCU的INT中断引脚,该INT中断引脚也是ICU模块一个Channel(ICU_MODE_SIGNAL_EDGE_DETECT模式)的引用引脚。
2)如果使用T1J1044收发器,则使用收发器的Rx引脚作为硬件唤醒引脚,且将收发器的Rx连接到MCU的INT中断引脚(也是MCU CAN控制器的Rx引脚),该INT中断引脚也是ICU模块一个Channel(ICU_MODE_SIGNAL_EDGE_DETECT模式)的引用引脚。
、
本文假定使用ECU T1J1043收发器。
RH850-F1KM芯片进入深度休眠(DeepSTOP)后,通过中断唤醒(Wakeup-factor 1)后,芯片切换到RUN模式,且整个软件从Reset地址开始重新运行。
NXP-S32K1xx芯片进入深度休眠(STOP mode or VLPS)后,通过中断唤醒后,芯片切换到RUN模式,软件从进入休眠的指令地址接着运行。
从单个CPU角度来讲,PM模块能够管理的CPU的两个电源模式:
. CPU Run Mode
. CPU Idle Mode
关于PMS模块管理的两个CPU Mode的描述入下表所示:
注意IDLE模式的进入和退出条件,通过寄存器设置进入IDLE模式,中断或者Trap退出IDLE模式。
站在整个芯片的角度来看,CPU模式分为Master CPU(CPU0)模式和Slave CPU(CPUx, x=0,1,2,3,4,5…)模式。
CPU0 modes: CPU0复位后,CPU0自动切换到RUN模式,RUN和IDLE模式之间可以通过PMS模块的PMCSR0寄存器的REQSLP位域控制切换。
CPUx modes: CPUx复位后,CPU自动进入到Halt模式(CPUx是不工作的),从Halt模式单向切换到RUN模式需要控制SYSCON.BHALT = 0,RUN和IDLE模式之间可以通过PMS模块的PMCSR0寄存器的REQSLP位域控制切换。
从系统(System)角度来讲,PM模块能够管理系统的三个电源模式:
. System Run Mode
. System Sleep Mode
. System Standby Mode
关于PMS模块管理的System Mode的描述入下表所示:
需要注意的是系统Standby Mode会因硬件的设计的不同(供电模式)而不同,VEXT和VERSB如果是同一个外部供电则进入Standby Mode后VEXT和VERSB都还有供电,如果VEXT和VERSB是单独供电,则进入Standby Mode后会切断VEXT的供电只有VERSB供电,这样进入和退出Standby模式的条件所有不同。
1)系统模式进入到Reset模式,则所有的CPU模式也进入到Reset模式。
2)系统模式进入到RUN模式,则Master Core(CPU 0)一定处于RUN模式。
3)系统从RUN模式进入到SLEEP模式可以通过Master CPU或者Slave CPU设置。也就是说,系统进入到SLEEP模式后,起码有一个CPU进入到了IDLE模式。
4)系统进入到Standby模式后,CPU Core都下电了,所以系统在Standby Mode下不用考虑CPU模式。
Standby模式比Sleep模式的低功耗做的更彻底。
TC3xx芯片平台的ECU下电可以选择进入到SLEEP模式(CPU模式为IDLE模式),或者进入到Standby模式。
ECU下电进入到SLEEP模式(CPU进入到IDLE模式)后,CPU代码执行停止。通过外部中断可以唤醒CPU,CPU被唤醒后进入到唤醒中断处理函数,然后程序接着Halt的地方继续往下运行。
ECU下电进入到Standby模式(CPU被下电了)后。通过唤醒请求可以唤醒CPU,CPU被唤醒后会从Reset出开始运行。
也就是说,TC3xx平台可以根据ECU系统设计下电进入SLEEP或者STANDBY模式,ECU下电被唤醒后则可能继续运行代码或者复位重跑。
.
CanTrcv驱动程序应使用ICU驱动程序提供的以下API来启用和禁用唤醒事件通知:
- Icu_EnableNotification
- Icu_DisableNotification
仅当为参数CanTrcvIcuChannelRef配置了参考时,CanTrcv驱动程序才应启用/禁用ICU通道。
CanTrcv驱动器应确保以下事项,以避免唤醒事件丢失:
当收发器转换到待机模式(CANTRCV_Standby)时,它应启用ICU信道。
CanTrcv_SetOpMode(uint8 CanTrcvIndex, CanTrcv_TrcvModeType OpMode)
{
/*Other Logic*/
Switch(OpMode)
{
Case CANTRCV_OP_MODE_NORMAL:
Icu_DisableNotification(CanTrcvIcuChannelRef);
Break;
Case CANTRCV_OP_MODE_STANDBY:
Icu_EnableNotification(CanTrcvIcuChannelRef);
Break;
/*Other logic*/
}
}
当收发器转换到正常模式(CANTRCV_Normal)时,它应禁用ICU信道。
EcuM中关于CanTrcv唤醒ECU后ECU通过ICU来捕获唤醒源的过程描述分为以下三个部分:
1)第一部分,ECU满足休眠条件后走GoSleep Sequeuece, EcuM会调用EcuM_EnableWakeupSources这个callout函数,EcuM_EnableWakeupSources -> CanIf_SetTrcvWakeupMode -> CanTrcv_SetWakeupMode使能CanTrcv的唤醒检测功能。EcuM_EnableWakeupSources -> Icu_EnableWakeup使能ICU模块的唤醒功能。最后EcuM调用Mcu_SetMode设置MCU到Halt模式。
注意:Halt模式,对应RH850-F1KM新的DeepStop模式,NXP-S32K1xx芯片的VLPS模式,对应TC3xx芯片的SLEEP模式。
2)第二部分,外部报文通过CanTrcv的INH引脚唤醒ECU,因为INH引脚接到了ICU的Port Pin上,也就是ICU会识别到Edge Detecton产生中断,ICU的中断处理函数中会调用EcuM_CheckWakeup来检测唤醒源。EcuM_CheckWakeup是一个callout函数,EcuM_CheckWakeup -> CanIf_CheckWakeup -> CanTrcv_CheckWakeup最后还是通过CanTrcv_CheckWakeup函数来检车CanTrcv的唤醒事件,如果检测到唤醒事件CanTrcv_CheckWakeup会调用EcuM_SetWakeupEvent来通知EcuM模块。
注意1:因为我们这里介绍CanTrcv的唤醒过程,所以EcuM_CheckWakeup这个callout里面应该调用CanIf_CheckWakeup,如果是其他的外设作为唤醒源头,那么EcuM_CheckWakeup应该调用
注意2:这个过程和具体的芯片强相关,按照第二章节的描述,只有NXP_S32K1xx芯片设置到VLPS模式或者TC3xx芯片设置到SLEEP模式,才会产生这个中断处理函数调用,也就有上诉的中断函数调用过程。如果是RH850_F1KM设置到DeepStop模式或者TC3xx芯片设置到Standby模式,CanTrcv的唤醒事件会触发芯片复位(软件从Reset地址开始运行),也就是没有这个中断函数调用过程了。
3)第三部分,有第二部分才有第三部分。ECU从Halt状态唤醒后,EcuM从代码halt的地方继续往下走Wakeup的Sequence.首先调用Mcu_SetMode设置芯片到Normal状态(RUN状态)。然后EcuM调用EcuM_DisableWakeupSources -> Icu_DisableWakeup关闭ICU的唤醒功能。
注意:实际工程中(个人接触到项目中),无论芯片是否支持Halt状态唤醒后继续往下执行程序都不会选择继续执行,而是通过软件复位或者芯片硬件本身复位后从Reset地址开始从头运行。这样能避免很多不可知的问题(因为唤醒后继续运行,意味着ECU只要不下电就没有主动复位的机会,对ECU的设计要求很高)。也就是说,AUTOSAR的标准流程下的EcuM_DisableWakeupSources这个callout函数可能是永远不能被调用到,所以需要ECU设计者在ECU启动的某个合适的地方调用EcuM_DisableWakeupSources这个函数。
ICU模块有两个模式:
nICU_MODE_NORMAL
nICU_MODE_SLEEP
在ICU_MODE_NORMAL模式下:
• 所有通知都可以通过服务ICU_SetActivationCondition()或IcuDefaultStartEdge配置。
• 在调用ICU_SetMode()之前或之后,所有通知都可以通过ICU_DisableNotification()和ICU_EnableNotification()服务选择。
在ICU_MODE_SLEEP模式下:
• 只有那些配置为可唤醒的唤醒事件可用,在Icu_Init()之后通过Icu_EnableWakeup()启用,并且没有通过服务Icu_DisableWakeup()禁用。
• 由该模块处理的所有其他中断都被禁用并且如果事件发生则不会导致退出MCU的低功率模式状态(例如空闲Idle、停止Halt)。
• 除满足以下条件的这些通道外,所有通道均已停止: - 它们已被配置为具有唤醒功能(wakeup capable),并 - 通过调用Icu_EnableTakeup明确启用。
Icu_SetMode
Icu_DisableWakeup
Icu_EnableWakeup
Icu_DisableNotification
Icu_EnableNotification
Icu_EnableEdgeDetection
Icu_DisableEdgeDetection
ICU模块的以上API和ICU的唤醒功能相关,具体每个函数的使用及其调用Sequence在AUTOSAR官方文档上都有详细的介绍,这里仅介绍Icu_EnableWakeup的Sequence.
上图的核心内容就是:在ICU模块处于ICU_MODE_SLEEP模式下时,只有配置了Wake up capable且调用了Icu_EnableWakeup的ICU Channel才能通过Wake up event产生Wake-up notification (也就是中断)。
注意:ICU_MODE_SLEEP模式下,只有产生了Wake-up notification(通过Icu_EnableWakeup使能)后才能产生Rising/Fail edge notification(通过Icu_EnableNotification使能).
1) Icu_SetMode用来设置ICU的模式,在ICU_MODE_SLEEP模式只有配置了Wakeup Capability为True且调用了Icu_EnableWakeup的通道(Channel)才能产生唤醒中断(唤醒MCU).
2)Icu_EnableWakeup和Icu_DisableWakeup用来Enable/Disable通道的唤醒能力,一般在ICU进入到ICU_MODE_SLEEP模式后Enable对应通道的唤醒功能,在ICU_MODE_NORMAL模式下Disable其唤醒功能。
3)Icu_EnableNotification和Icu_EnableNotification用来Enable/Disable通道在上升沿/下降沿/双边沿是否产生Notificaltion通知(也会产生中断),且这两个API只有Channel为ICU_MODE_SIGNAL_EDGE_DETECT模式时才能调用。
4)ICU唤醒功能的Channel一般都配置为ICU_MODE_SIGNAL_EDGE_DETECT模式,Icu_EnableEdgeDetection和Icu_DisableEdgeDetection用来Enable/Disable通道的边沿检测。也就是说,Enable Edge Detection是 Enable Wakeup和Enable Notification的前置条件。
总结下以下三组函数的区别: I
Icu_EnableNotification
Icu_EnableNotification
Icu_EnableWakeup
Icu_DisableWakeup
Icu_EnableEdgeDetection
Icu_DisableEdgeDetection
ICU唤醒的Channel一般使用ICU_MODE_SIGNAL_EDGE_DETECT模式,所以,首先要调用Icu_EnableEdgeDetection使能唤醒检测,然后如果要在ICU信号的上升沿/下降沿产生Notification的话就需要调用Icu_EnableNotification使能Notification(这个是可选的),ICU进入到ICU_MODE_SLEEP模式需要调用Icu_EnableWakeup使能唤醒功能。
注意:Icu_EnableWakeup和Icu_EnableNotification都会产生中断,Icu_EnableNotification的中断用于ICU信号的边沿检测通知,ICU_MODE_SLEEP模式的中断用于ICU处于ICU_MODE_SLEEP模式的唤醒。
猜测:Icu_EnableWakeup和Icu_EnableNotification产生的可能是同一个中断,产生中断后只是通过软件逻辑来实现API的逻辑功能。比如,ICU_MODE_NORMAL模式下仅调用Icu_EnableNotification后再调用ICU_SetMode设置ICU到ICU_MODE_SLEEP模式,因为没有调用Icu_EnableWakeup使能唤醒,ICU的中断应该是被Disable的,这个时候ICU通道上有上升沿/下降沿信号也不会产生中断(如果MCU进入休眠状态,也就唤不醒MCU)。
从第2章节我们知道,有些芯片在进入到Halt模式(DeepStop)后被中断唤醒后是从Reset地址重跑,有些芯片是接着Halt地址处接着往下运行。实际工程中,如果芯片是接着Halt地址处接着往下运行我们也会让其软件复位重新跑,这样能减少软件的实现难度。
也就是说,实际工程中EcuM中WAKEUP 1阶段是没有的。
所以实际工程项目中使用ICU唤醒(Cantrcv作为外设唤醒)的步骤一般如下(以RH850-F1KM为例):
1)配置Port模块:配置用于ICU唤醒的Port pin的复用功能,需要选择器INT功能。
查看软硬件接口表找到硬件唤醒脚,Davinci中配置Port模块的唤醒Pin的属性。
配置中断唤醒Pin的电平触发模式。
2)配置MCU模式。
添加一个Mcu深度休眠模式。
添加MCU唤醒Pin。
3)配置ICU模块:Channel配置为Icu_EnableEdgeDetection模式,根据需要配置其他Notification的Callout函数,且配置其Wakeup Capability为True.
4)配置Cantrcv模块:根据需要引用ICU Channel (需要Cantrcv在进入到Standby模式时调用Icu_EnableNotification且进入到Normal模式时调用Icu_DisableNotification就引用).
5)实现EcuM_EnableWakeupSource这个Callout函数:
EcuM_EnableWakeupSource(EcuM_WakeupSourceType wakeupSource)
{
If(ICU_Wakeu_Source == wakeupSource)
{
Icu_EnableEdgeDetection(Icu_wakeup_channelId); Icu_EnableEdgeDetection(Icu_wakeup_channelId);
Icu_SetMode(ICU_MODE_SLEEP);
}
}
注意:EcuM_EnableWakeupSource这个Callout函数在EcuM的GoSleep Sequence中会被调用。也就是说不用用户手动调用。
6)实现EcuM_DisableWakeupSource这个Callout函数:
EcuM_EnableWakeupSource(EcuM_WakeupSourceType wakeupSource)
{
If(ICU_Wakeu_Source == wakeupSource)
{
Icu_DisableEdgeDetection(Icu_wakeup_channelId); Icu_DisableEdgeDetection(Icu_wakeup_channelId);
Icu_SetMode(ICU_MODE_NORMAL);
}
}
注意:EcuM_EnableWakeupSource这个Callout函数理论上在EcuM的WAKEUP 1 Sequence中会被调用。但是,实际情况中是不会有这个Sequence存在,也就是需要开发者在EcuM的上电流程中手动调用。
问题1:通过ICU唤醒ECU时,以下3组API有个差异,在什么时机调用他们, 都需要用户手写代码调用么?
Icu_EnableNotification
Icu_EnableNotification
Icu_EnableWakeup
Icu_DisableWakeup
Icu_EnableEdgeDetection
Icu_DisableEdgeDetection
答:见3.2章节和第4章节。
问题2:Icu_SetMode在什么时候调用,有何作用?
答:见3.2章节和第4章节。
问题3:Icu_CheckWakeup在什么时候调用,有何作用?
答:如果有其他外设(类似Cantrcv)通过ICU来唤醒ECU时,可以借用Icu_CheckWakeup来检测唤醒源。在EcuM_CheckWakeup这个Callout函数中调用Icu_CheckWakeup.
问题4:不同芯片平台(TC3xx, RH850F1KM, NXPS32K1xx)通过ICU唤醒后的行为有何差异?
答:第2章节。
End
「汽车电子嵌入式在CSDN上同步推出AUTOSAR精进之路专栏,本专栏每个模块完全按实际项目中开发及维护过程来详细介绍。模块核心概念介绍、实际需求描述、实际工程配置、特殊需求介绍及背后原理、实际工程使用经验总结。目的是让读者看完每一个章节后能理解原理后根据需求完成一个模块的配置或者解决一个问题。」
点击文章最后左下角的阅读原文可以获取更多信息
或者复制如下链接到浏览器获取更多信息
https://blog.csdn.net/qq_36056498/article/details/132125693
文末福利
2.为便于技术交流,创建了汽车电子嵌入式技术交流群,可尽情探讨AP,CP,DDS,SOME/IP等前沿热点话题,后台回复“加群”即可加入;
注:本文引用了一些第三方工具和文档,若有侵权,请联系作者删除!
推荐阅读
汽车电子嵌入式精彩文章汇总第一期:20210530-20230703
汽车电子嵌入式精彩文章汇总第2期
汽车电子嵌入式精彩文章汇总第3期
【OS】AUTOSAR OS Event实现原理
【OS】AUTOSAR OS Spinlock实现原理(下篇)
【OS】AUTOSAR OS Spinlock实现原理(上篇)
CanNm处于PBS状态下接收到一帧诊断报文DCM会响应吗
TC3xx芯片CAN模块详解
AUTOSAR OS Alarm实现原理
AUTOSAR OsTask切换原理
TC3xx 芯片SPI模块详解
AUTSOAR ComStack如何实现PDU只收不发的
AUTOSAR OsStack监控原理
End
欢迎点赞,关注,转发,在看,您的每一次鼓励,都是我最大的动力!
汽车电子嵌入式
微信
扫描二维码,关注我的公众号