第 18 篇|Runnable、Event 与 Timing:函数是如何被“触发”的

【Application Layer / RTE】
在上一篇我们说过一句很关键的话:
Runnable 才是 AUTOSAR 应用里真正会执行的函数。
但这句话只说了一半。
另一半是:
Runnable 永远不会“自己跑起来”。
它一定是被某种 Event 触发的。
而 Event,本质上是 RTE 和 OS 之间的一份“触发契约”。
从一个最朴素的问题开始
先不要想 AUTOSAR,我们先想一个最原始的问题:
一个函数,凭什么每 10ms 执行一次?
在裸机或普通 RTOS 里,你可能会写:
while(1)
{
Task_10ms();
Delay(10);
}
或者在 RTOS 里:
- Task 周期 10ms
- 函数直接写在 Task 里
函数 ≈ Task ≈ 时间
三者是绑死的。
而 AUTOSAR 从一开始就刻意把它们拆开:
- Task 是 OS 的概念
- Runnable 是应用的概念
- 时间触发,是 Event 的事
Runnable 不等于周期
这是 AUTOSAR 非常反直觉、但又非常重要的一点。
Runnable 自身没有“时间属性”。
Runnable 只是一个函数:
- 没有周期
- 没有优先级
- 没有上下文
所有“什么时候跑”的信息,都在 Event 里。
Event:Runnable 的“触发原因”
在 Classic AUTOSAR 里,Event 可以理解为:
“当某个条件成立时,RTE 负责触发某个 Runnable。”
这些条件,来自不同层级:
- 时间
- 数据
- 调用
- 系统状态
从工程角度看,你可以把 Event 分成几大类。
TimingEvent:最容易被误解的一类
我们先讲最常见、也最容易被误解的 TimingEvent。
TimingEvent 的真实含义
很多人以为:
TimingEvent = 周期
但更准确的说法是:
TimingEvent = RTE 声明:这个 Runnable 需要“被周期性触发”。
而“周期性”这件事,最终一定是 OS 在做。
也就是说:
- TimingEvent 本身不计时
- 不产生 Tick
- 不配置硬件 Timer
它只是告诉 RTE:
“请你想办法,让这个 Runnable 按这个节奏被调用。”
从 TimingEvent 到 Task 的真实路径
我们用一张完整链路图把这件事说清楚。
#mermaid-svg-5nTlOpIUgwIzTSKO{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-5nTlOpIUgwIzTSKO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-5nTlOpIUgwIzTSKO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-5nTlOpIUgwIzTSKO .error-icon{fill:#552222;}#mermaid-svg-5nTlOpIUgwIzTSKO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-5nTlOpIUgwIzTSKO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-5nTlOpIUgwIzTSKO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-5nTlOpIUgwIzTSKO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-5nTlOpIUgwIzTSKO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-5nTlOpIUgwIzTSKO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-5nTlOpIUgwIzTSKO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-5nTlOpIUgwIzTSKO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-5nTlOpIUgwIzTSKO .marker.cross{stroke:#333333;}#mermaid-svg-5nTlOpIUgwIzTSKO svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-5nTlOpIUgwIzTSKO p{margin:0;}#mermaid-svg-5nTlOpIUgwIzTSKO .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-5nTlOpIUgwIzTSKO .cluster-label text{fill:#333;}#mermaid-svg-5nTlOpIUgwIzTSKO .cluster-label span{color:#333;}#mermaid-svg-5nTlOpIUgwIzTSKO .cluster-label span p{background-color:transparent;}#mermaid-svg-5nTlOpIUgwIzTSKO .label text,#mermaid-svg-5nTlOpIUgwIzTSKO span{fill:#333;color:#333;}#mermaid-svg-5nTlOpIUgwIzTSKO .node rect,#mermaid-svg-5nTlOpIUgwIzTSKO .node circle,#mermaid-svg-5nTlOpIUgwIzTSKO .node ellipse,#mermaid-svg-5nTlOpIUgwIzTSKO .node polygon,#mermaid-svg-5nTlOpIUgwIzTSKO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-5nTlOpIUgwIzTSKO .rough-node .label text,#mermaid-svg-5nTlOpIUgwIzTSKO .node .label text,#mermaid-svg-5nTlOpIUgwIzTSKO .image-shape .label,#mermaid-svg-5nTlOpIUgwIzTSKO .icon-shape .label{text-anchor:middle;}#mermaid-svg-5nTlOpIUgwIzTSKO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-5nTlOpIUgwIzTSKO .rough-node .label,#mermaid-svg-5nTlOpIUgwIzTSKO .node .label,#mermaid-svg-5nTlOpIUgwIzTSKO .image-shape .label,#mermaid-svg-5nTlOpIUgwIzTSKO .icon-shape .label{text-align:center;}#mermaid-svg-5nTlOpIUgwIzTSKO .node.clickable{cursor:pointer;}#mermaid-svg-5nTlOpIUgwIzTSKO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-5nTlOpIUgwIzTSKO .arrowheadPath{fill:#333333;}#mermaid-svg-5nTlOpIUgwIzTSKO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-5nTlOpIUgwIzTSKO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-5nTlOpIUgwIzTSKO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5nTlOpIUgwIzTSKO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-5nTlOpIUgwIzTSKO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5nTlOpIUgwIzTSKO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-5nTlOpIUgwIzTSKO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-5nTlOpIUgwIzTSKO .cluster text{fill:#333;}#mermaid-svg-5nTlOpIUgwIzTSKO .cluster span{color:#333;}#mermaid-svg-5nTlOpIUgwIzTSKO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-5nTlOpIUgwIzTSKO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-5nTlOpIUgwIzTSKO rect.text{fill:none;stroke-width:0;}#mermaid-svg-5nTlOpIUgwIzTSKO .icon-shape,#mermaid-svg-5nTlOpIUgwIzTSKO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-5nTlOpIUgwIzTSKO .icon-shape p,#mermaid-svg-5nTlOpIUgwIzTSKO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-5nTlOpIUgwIzTSKO .icon-shape rect,#mermaid-svg-5nTlOpIUgwIzTSKO .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-5nTlOpIUgwIzTSKO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-5nTlOpIUgwIzTSKO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-5nTlOpIUgwIzTSKO :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
TimingEvent (10ms)
RTE Generated Code
OS Task (10ms)
Runnable_X()
关键点在这里:
- TimingEvent → RTE 配置
- Task → OS 配置
- 两者通过 RTE 生成代码“绑”在一起
所以你在 ARXML 里改 TimingEvent 的周期,
最后一定会体现在:
- Task 的 Alarm
- 或 ScheduleTable
- 或 Task 激活频率
常见误解:一个 TimingEvent = 一个 Task?
这是项目里非常常见的误区。
实际上:
- 一个 Task 可以承载多个 TimingEvent
- 一个 Runnable 也可以被多个 Event 触发(虽然不推荐)
例如:
#mermaid-svg-YvsanzHIcV6c84B0{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YvsanzHIcV6c84B0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YvsanzHIcV6c84B0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YvsanzHIcV6c84B0 .error-icon{fill:#552222;}#mermaid-svg-YvsanzHIcV6c84B0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YvsanzHIcV6c84B0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YvsanzHIcV6c84B0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YvsanzHIcV6c84B0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YvsanzHIcV6c84B0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YvsanzHIcV6c84B0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YvsanzHIcV6c84B0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YvsanzHIcV6c84B0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YvsanzHIcV6c84B0 .marker.cross{stroke:#333333;}#mermaid-svg-YvsanzHIcV6c84B0 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YvsanzHIcV6c84B0 p{margin:0;}#mermaid-svg-YvsanzHIcV6c84B0 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-YvsanzHIcV6c84B0 .cluster-label text{fill:#333;}#mermaid-svg-YvsanzHIcV6c84B0 .cluster-label span{color:#333;}#mermaid-svg-YvsanzHIcV6c84B0 .cluster-label span p{background-color:transparent;}#mermaid-svg-YvsanzHIcV6c84B0 .label text,#mermaid-svg-YvsanzHIcV6c84B0 span{fill:#333;color:#333;}#mermaid-svg-YvsanzHIcV6c84B0 .node rect,#mermaid-svg-YvsanzHIcV6c84B0 .node circle,#mermaid-svg-YvsanzHIcV6c84B0 .node ellipse,#mermaid-svg-YvsanzHIcV6c84B0 .node polygon,#mermaid-svg-YvsanzHIcV6c84B0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YvsanzHIcV6c84B0 .rough-node .label text,#mermaid-svg-YvsanzHIcV6c84B0 .node .label text,#mermaid-svg-YvsanzHIcV6c84B0 .image-shape .label,#mermaid-svg-YvsanzHIcV6c84B0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-YvsanzHIcV6c84B0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-YvsanzHIcV6c84B0 .rough-node .label,#mermaid-svg-YvsanzHIcV6c84B0 .node .label,#mermaid-svg-YvsanzHIcV6c84B0 .image-shape .label,#mermaid-svg-YvsanzHIcV6c84B0 .icon-shape .label{text-align:center;}#mermaid-svg-YvsanzHIcV6c84B0 .node.clickable{cursor:pointer;}#mermaid-svg-YvsanzHIcV6c84B0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-YvsanzHIcV6c84B0 .arrowheadPath{fill:#333333;}#mermaid-svg-YvsanzHIcV6c84B0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-YvsanzHIcV6c84B0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-YvsanzHIcV6c84B0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YvsanzHIcV6c84B0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YvsanzHIcV6c84B0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YvsanzHIcV6c84B0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-YvsanzHIcV6c84B0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-YvsanzHIcV6c84B0 .cluster text{fill:#333;}#mermaid-svg-YvsanzHIcV6c84B0 .cluster span{color:#333;}#mermaid-svg-YvsanzHIcV6c84B0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-YvsanzHIcV6c84B0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YvsanzHIcV6c84B0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-YvsanzHIcV6c84B0 .icon-shape,#mermaid-svg-YvsanzHIcV6c84B0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YvsanzHIcV6c84B0 .icon-shape p,#mermaid-svg-YvsanzHIcV6c84B0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-YvsanzHIcV6c84B0 .icon-shape rect,#mermaid-svg-YvsanzHIcV6c84B0 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YvsanzHIcV6c84B0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-YvsanzHIcV6c84B0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-YvsanzHIcV6c84B0 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Task_10ms
Runnable_A (10ms)
Runnable_B (20ms)
在这种情况下:
- Task 10ms 运行一次
- Runnable_B 通过内部计数或 RTE 逻辑,每 20ms 才真正执行
这也是为什么Task 周期 ≠ Runnable 周期。
DataReceivedEvent:数据驱动,而不是时间驱动
第二类非常重要的 Event 是 DataReceivedEvent。
它描述的不是“时间到了”,而是:
“当某个数据被更新时,触发 Runnable。”
典型场景包括:
- CAN 信号接收
- 状态变化
- 外部 ECU 事件
SWCRTECOMSWCRTECOM#mermaid-svg-znmErmqvuL2O0Ys9{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-znmErmqvuL2O0Ys9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-znmErmqvuL2O0Ys9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-znmErmqvuL2O0Ys9 .error-icon{fill:#552222;}#mermaid-svg-znmErmqvuL2O0Ys9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-znmErmqvuL2O0Ys9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-znmErmqvuL2O0Ys9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-znmErmqvuL2O0Ys9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-znmErmqvuL2O0Ys9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-znmErmqvuL2O0Ys9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-znmErmqvuL2O0Ys9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-znmErmqvuL2O0Ys9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-znmErmqvuL2O0Ys9 .marker.cross{stroke:#333333;}#mermaid-svg-znmErmqvuL2O0Ys9 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-znmErmqvuL2O0Ys9 p{margin:0;}#mermaid-svg-znmErmqvuL2O0Ys9 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-znmErmqvuL2O0Ys9 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-znmErmqvuL2O0Ys9 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-znmErmqvuL2O0Ys9 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-znmErmqvuL2O0Ys9 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-znmErmqvuL2O0Ys9 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-znmErmqvuL2O0Ys9 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-znmErmqvuL2O0Ys9 .sequenceNumber{fill:white;}#mermaid-svg-znmErmqvuL2O0Ys9 #sequencenumber{fill:#333;}#mermaid-svg-znmErmqvuL2O0Ys9 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-znmErmqvuL2O0Ys9 .messageText{fill:#333;stroke:none;}#mermaid-svg-znmErmqvuL2O0Ys9 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-znmErmqvuL2O0Ys9 .labelText,#mermaid-svg-znmErmqvuL2O0Ys9 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-znmErmqvuL2O0Ys9 .loopText,#mermaid-svg-znmErmqvuL2O0Ys9 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-znmErmqvuL2O0Ys9 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-znmErmqvuL2O0Ys9 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-znmErmqvuL2O0Ys9 .noteText,#mermaid-svg-znmErmqvuL2O0Ys9 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-znmErmqvuL2O0Ys9 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-znmErmqvuL2O0Ys9 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-znmErmqvuL2O0Ys9 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-znmErmqvuL2O0Ys9 .actorPopupMenu{position:absolute;}#mermaid-svg-znmErmqvuL2O0Ys9 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-znmErmqvuL2O0Ys9 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-znmErmqvuL2O0Ys9 .actor-man circle,#mermaid-svg-znmErmqvuL2O0Ys9 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-znmErmqvuL2O0Ys9 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}Signal updatedTrigger Runnable_DataIndication
这里有一个非常工程化的差异:
- TimingEvent:OS 先动
- DataReceivedEvent:通信先动
但最终:
- 都是通过 RTE
- 都落到 Runnable
OperationInvokedEvent:Client-Server 的触发方式
当你使用 Client-Server Interface 时,
对应的 Event 就是 OperationInvokedEvent。
你可以把它理解为:
“有人 Call 了我这个接口,所以我要跑。”
ServerSWCRTEClientSWCServerSWCRTEClientSWC#mermaid-svg-vbBqy062ZWflF7pM{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-vbBqy062ZWflF7pM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vbBqy062ZWflF7pM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vbBqy062ZWflF7pM .error-icon{fill:#552222;}#mermaid-svg-vbBqy062ZWflF7pM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-vbBqy062ZWflF7pM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vbBqy062ZWflF7pM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vbBqy062ZWflF7pM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vbBqy062ZWflF7pM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vbBqy062ZWflF7pM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vbBqy062ZWflF7pM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vbBqy062ZWflF7pM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-vbBqy062ZWflF7pM .marker.cross{stroke:#333333;}#mermaid-svg-vbBqy062ZWflF7pM svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-vbBqy062ZWflF7pM p{margin:0;}#mermaid-svg-vbBqy062ZWflF7pM .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-vbBqy062ZWflF7pM text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-vbBqy062ZWflF7pM .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-vbBqy062ZWflF7pM .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-vbBqy062ZWflF7pM .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-vbBqy062ZWflF7pM .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-vbBqy062ZWflF7pM #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-vbBqy062ZWflF7pM .sequenceNumber{fill:white;}#mermaid-svg-vbBqy062ZWflF7pM #sequencenumber{fill:#333;}#mermaid-svg-vbBqy062ZWflF7pM #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-vbBqy062ZWflF7pM .messageText{fill:#333;stroke:none;}#mermaid-svg-vbBqy062ZWflF7pM .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-vbBqy062ZWflF7pM .labelText,#mermaid-svg-vbBqy062ZWflF7pM .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-vbBqy062ZWflF7pM .loopText,#mermaid-svg-vbBqy062ZWflF7pM .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-vbBqy062ZWflF7pM .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-vbBqy062ZWflF7pM .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-vbBqy062ZWflF7pM .noteText,#mermaid-svg-vbBqy062ZWflF7pM .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-vbBqy062ZWflF7pM .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-vbBqy062ZWflF7pM .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-vbBqy062ZWflF7pM .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-vbBqy062ZWflF7pM .actorPopupMenu{position:absolute;}#mermaid-svg-vbBqy062ZWflF7pM .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-vbBqy062ZWflF7pM .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-vbBqy062ZWflF7pM .actor-man circle,#mermaid-svg-vbBqy062ZWflF7pM line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-vbBqy062ZWflF7pM :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}Rte_Call_Service()Runnable_Service()
这个 Runnable:
- 没有周期
- 完全由调用驱动
- 可能运行在调用者 Task 中(同步)
- 也可能被映射到独立 Task(异步)
Runnable 的执行上下文,并不是它自己决定的。
多 Event 触发同一个 Runnable,可以吗?
规范上:可以。
工程上:强烈不推荐。
例如:
- 一个 Runnable 同时被 TimingEvent 和 DataReceivedEvent 触发
- 或同时被多个 TimingEvent 触发
结果往往是:
- 执行时序混乱
- 数据一致性难以保证
- Debug 极其痛苦
Runnable 的一个重要设计原则是:触发原因要单一、可解释。
Runnable 设计的几个“落地原则”
这一部分,我刻意不讲“规范推荐”,而讲项目里踩过坑之后总结出来的原则。
一个 Runnable,只做一类事
不要在一个 Runnable 里同时:
- 采集数据
- 做控制
- 发通信
否则:
- Event 一复杂,你会完全失控
Runnable 不应该关心“为什么现在被调用”
Runnable 的代码里,不应该出现:
- “这是第几次调用”
- “是不是 20ms 才该跑”
- “是不是某个模式下”
这些都应该在:
- Event 配置
- 或上层逻辑里解决
Runnable 的执行时间要可控
因为 Runnable 最终跑在 Task 里:
- 它会影响同 Task 下其他 Runnable
- 也会影响 OS 调度
所以在设计时要非常现实地问一句:
这个 Runnable,最坏情况下要跑多久?
把一切串起来:从配置到执行
我们用一条“从配置到代码”的链路收尾。
#mermaid-svg-ZZB1lLEJPH89ESUG{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZZB1lLEJPH89ESUG .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZZB1lLEJPH89ESUG .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZZB1lLEJPH89ESUG .error-icon{fill:#552222;}#mermaid-svg-ZZB1lLEJPH89ESUG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZZB1lLEJPH89ESUG .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZZB1lLEJPH89ESUG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZZB1lLEJPH89ESUG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZZB1lLEJPH89ESUG .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZZB1lLEJPH89ESUG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZZB1lLEJPH89ESUG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZZB1lLEJPH89ESUG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZZB1lLEJPH89ESUG .marker.cross{stroke:#333333;}#mermaid-svg-ZZB1lLEJPH89ESUG svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZZB1lLEJPH89ESUG p{margin:0;}#mermaid-svg-ZZB1lLEJPH89ESUG .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZZB1lLEJPH89ESUG .cluster-label text{fill:#333;}#mermaid-svg-ZZB1lLEJPH89ESUG .cluster-label span{color:#333;}#mermaid-svg-ZZB1lLEJPH89ESUG .cluster-label span p{background-color:transparent;}#mermaid-svg-ZZB1lLEJPH89ESUG .label text,#mermaid-svg-ZZB1lLEJPH89ESUG span{fill:#333;color:#333;}#mermaid-svg-ZZB1lLEJPH89ESUG .node rect,#mermaid-svg-ZZB1lLEJPH89ESUG .node circle,#mermaid-svg-ZZB1lLEJPH89ESUG .node ellipse,#mermaid-svg-ZZB1lLEJPH89ESUG .node polygon,#mermaid-svg-ZZB1lLEJPH89ESUG .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZZB1lLEJPH89ESUG .rough-node .label text,#mermaid-svg-ZZB1lLEJPH89ESUG .node .label text,#mermaid-svg-ZZB1lLEJPH89ESUG .image-shape .label,#mermaid-svg-ZZB1lLEJPH89ESUG .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZZB1lLEJPH89ESUG .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZZB1lLEJPH89ESUG .rough-node .label,#mermaid-svg-ZZB1lLEJPH89ESUG .node .label,#mermaid-svg-ZZB1lLEJPH89ESUG .image-shape .label,#mermaid-svg-ZZB1lLEJPH89ESUG .icon-shape .label{text-align:center;}#mermaid-svg-ZZB1lLEJPH89ESUG .node.clickable{cursor:pointer;}#mermaid-svg-ZZB1lLEJPH89ESUG .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZZB1lLEJPH89ESUG .arrowheadPath{fill:#333333;}#mermaid-svg-ZZB1lLEJPH89ESUG .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZZB1lLEJPH89ESUG .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZZB1lLEJPH89ESUG .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZZB1lLEJPH89ESUG .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZZB1lLEJPH89ESUG .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZZB1lLEJPH89ESUG .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZZB1lLEJPH89ESUG .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZZB1lLEJPH89ESUG .cluster text{fill:#333;}#mermaid-svg-ZZB1lLEJPH89ESUG .cluster span{color:#333;}#mermaid-svg-ZZB1lLEJPH89ESUG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZZB1lLEJPH89ESUG .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZZB1lLEJPH89ESUG rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZZB1lLEJPH89ESUG .icon-shape,#mermaid-svg-ZZB1lLEJPH89ESUG .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZZB1lLEJPH89ESUG .icon-shape p,#mermaid-svg-ZZB1lLEJPH89ESUG .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZZB1lLEJPH89ESUG .icon-shape rect,#mermaid-svg-ZZB1lLEJPH89ESUG .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZZB1lLEJPH89ESUG .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZZB1lLEJPH89ESUG .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZZB1lLEJPH89ESUG :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
ARXML\\n(Event / Runnable Mapping)
RTE Generator
OS Task
Runnable C Code
当你在项目里遇到:
- Runnable 没跑
- 跑得不准
- 跑的次数不对
排查顺序永远是:
小结
这一篇你只需要记住三句话:
- Runnable 是函数,不是周期
- Event 决定“为什么触发”
- OS 决定“什么时候调度”
AUTOSAR 真正厉害的地方,不是它复杂,
而是它把这些本来混在一起的概念,强行拆开了。
下一篇,我们会继续沿着这条线往下走:
👉 下一篇预告
RTE:看起来很蠢,但不可或缺的胶水层
我们会直接打开 RTE 生成代码,
看看这些 Event 和 Runnable,到底是怎么被“粘”在一起的。