一、核心关系一句话概括
Com_SendSignal负责"更新信号值 + 设置发送请求标志(TMS) ";
Com_MainFunctionTx(周期性任务)负责"定期扫描 TMS 标志,决定是否调用 PduR_ComTransmit 发送 PDU "。两者通过 TMS 标志 解耦,实现异步协作。
二、Com_SendSignal 做的事(信号更新时)
-
错误检测(信号 ID、指针有效性)。
-
根据 传输属性(
ComTransferProperty):-
PENDING:只更新信号值到 I-PDU 缓冲区,不触发任何后续流程(结束)。 -
TRIGGERED/TRIGGERED_ON_CHANGE等:进入发送触发流程。
-
-
计算该信号的 TMC :应用配置的滤波机制(如
ALWAYS、NEW_IS_OUTSIDE等),得到布尔值。 -
若 TMC ==
TRUE→ 将所在 I-PDU 的 TMS 标志置为TRUE(逻辑或累积)。 -
更新信号值到 I-PDU 缓冲区。
-
立即返回
E_OK,不调用 PduR_ComTransmit。
注意 :
Com_SendSignal永远不会直接触发 PDU 发送,它只是"贴标签"。
三、Com_MainFunctionTx 做的事(周期性任务)
通常由 OSEK OS 或 AUTOSAR 调度表以固定周期(如 10ms)调用。
对每个激活的 I-PDU,执行:
-
重新计算该 PDU 的 TMS
-
TMS = TMC_sig1 OR TMC_sig2 OR ... OR TMC_sigN
-
每个信号的 TMC 根据最新信号值重新评估。
-
-
决定是否发送:
-
若 TMS ==
TRUE→ 需要发送(事件触发)。 -
若配置了 周期发送 (如
ComTxModeFalse为 PERIODIC)且定时器到期 → 也需要发送。 -
否则跳过。
-
-
选择发送策略:
-
若 TMS ==
TRUE→ 选择ComTxModeTrue(通常配置为立即发送、N 次重发等)。 -
若 TMS ==
FALSE但周期到期 → 选择ComTxModeFalse(通常配置为 PERIODIC、NONE 等)。
-
-
调用
PduR_ComTransmit(pdu, mode),将数据向下层传递。 -
清除 TMS 标志(若本次发送由事件触发)。
四、时间轴示例(异步关系)
假设:
-
PDU_X 包含
SigA(Triggered, TMC=ALWAYS) 和SigB(Pending) -
Com_MainFunctionTx周期 = 10 ms
| 时间(ms) | 事件 | TMS 标志 | 实际发送 |
|---|---|---|---|
| 0 | Com_SendSignal(SigA) 更新,TMC=TRUE |
置为 TRUE | 无(等主函数) |
| 10 | Com_MainFunctionTx 执行 |
读取到 TRUE → 发送 → 清除 | PDU 发出 |
| 15 | Com_SendSignal(SigB) (Pending) |
不变(FALSE) | 无 |
| 20 | Com_MainFunctionTx 执行 |
FALSE,无周期要求 | 无发送 |
关键 :
Com_SendSignal在 0ms 只是"请求",真正发送在 10ms 才发生。
五、流程图(Mermaid)

六、波形图
图例:
-
↑事件发生时刻 -
──状态保持 -
时间轴每个
·代表 1ms,每 5ms 标一个数字
时间(ms) 0 5 10 15 20 25 30
│ │ │ │ │ │ │
波形: ·····|·····|·····|·····|·····|·····
SigA值: ──────────────────────────────────
3000─────────────────────────────
Call_SendSignal(SigA):
↑ (t=0)
SigA TMC: TRUE────────────────────────────
TMS标志: ──┬─────────────────────────────
TRUE
│
│ (等待主函数)
│
↓
Com_MainFunctionTx 执行:
↑ (t=10)
PduR_ComTransmit: ↑ (t=10, 因为 TMS=TRUE)
TMS被清除: │
└── FALSE────────────────
Call_SendSignal(SigB):
↑ (t=25)
SigB TMC: FALSE (Pending)
TMS标志: 仍为 FALSE─────
Com_MainFunctionTx 执行:
↑ (t=30)
无发送 (TMS=FALSE)
说明:
-
时间轴
t=0, 5, 10, 15, 20, 25, 30每个箭头对应一个整数毫秒时刻。 -
Com_MainFunctionTx在t=10, 20, 30, ...执行(周期 10ms)。图中只画了t=10和t=30,t=20省略但道理相同(TMS 当时为 FALSE)。 -
Com_SendSignal(SigA)在t=0发生,将 TMS 设为TRUE,但直到t=10主函数才真正发送。 -
Com_SendSignal(SigB)在t=25发生,由于是 Pending 属性,不改变 TMS,所以t=30主函数不发送。
| 时刻 (ms) | 事件 | TMS 值 | 说明 |
|---|---|---|---|
| 0 | Com_SendSignal(SigA) 调用 |
从 FALSE → TRUE | Triggered 信号,TMC=TRUE,标记请求 |
| 0~9.999 | 无主函数执行 | TRUE | 等待发送 |
| 10 | Com_MainFunctionTx 执行 |
TRUE → FALSE | 检测到 TMS=TRUE,调用 PduR_ComTransmit,然后清除 TMS |
| 10~19.999 | 无新触发 | FALSE | 空闲 |
| 20 | Com_MainFunctionTx 执行 |
FALSE | TMS=FALSE,无周期要求,跳过 |
| 25 | Com_SendSignal(SigB) 调用 |
保持 FALSE | Pending 信号,不触发 TMS |
| 25~29.999 | 无变化 | FALSE | 仍无请求 |
| 30 | Com_MainFunctionTx 执行 |
FALSE | 跳过 |
七、TMS 标志的关键特性
-
生产者 :
Com_SendSignal(当 Triggered 信号且 TMC=TRUE 时置位)。 -
消费者 :
Com_MainFunctionTx(读取并清除)。 -
多信号 OR 逻辑:只要 PDU 内任一信号的 TMC=TRUE,TMS 就为 TRUE。
-
原子操作:TMS 的修改和读取通常需要临界区保护(关中断或互斥)。
八、常见误解澄清
| 误解 | 正解 |
|---|---|
Com_SendSignal 会立即发送 PDU |
不会。它只更新 TMS 标志和数据缓冲区。 |
| Pending 信号永远发不出去 | Pending 信号不能触发发送,但当 PDU 因其他原因被发送时,其最新值会被包含在报文中。 |
| TMS 只在信号更新时计算 | 在 Com_MainFunctionTx 中会重新计算所有信号的 TMC,确保 TMS 反映最新状态。 |
| Triggered 信号总是会触发发送 | 不一定。若 TMC=FALSE,不会将 TMS 置 TRUE,因此可能不会触发发送(除非周期到期)。 |
九、总结表
| 概念 | 作用层级 | 计算/判断时机 | 输出 |
|---|---|---|---|
| 传输属性 | 信号 | Com_SendSignal 入口 |
是否进入触发流程 |
| TMC | 信号 | Com_SendSignal 中(Triggered) Com_MainFunctionTx 中重算 |
该信号是否"需要发送" |
| TMS | PDU | Com_MainFunctionTx 中(所有 TMC 的 OR) |
PDU 是否需要发送 |
| ComTxModeTrue/False | PDU | TMS 确定后选择其一 | 具体发送策略(DIRECT/PERIODIC等) |
| PduR_ComTransmit | PDU | 决策需要发送时调用 | 将 PDU 传递到下层 |
最终理解要点 :
Com_SendSignal 只是"写请求",Com_MainFunctionTx 才是"执行者"。两者通过 TMS 标志异步协作,实现了信号更新与 PDU 发送的解耦。