WARNING L15: MULTIPLE CALL TO SEGMENT 表示函數發生重入:主循環正在執行某函數時,中斷服務程序(ISR)又調用了同一函數。導致該函數的局部變量、參數、返回地址覆蓋,產生不可預測的錯誤。
// 主循環
void main() {
while (1) {
process_data(); // 正在執行
}
}
// 中斷服務程序
void timer_isr() interrupt 1 {
process_data(); // 重入!覆蓋主循環的棧幀
}
reentrant(Keil C51/C166/C251)void process_data(void) reentrant {
// 編譯器為每次調用分配獨立的模擬棧幀(基於內存模型)
}
限制與代價:
bit 類型參數/變量small 模型用 data,large 用 xdata)reentrant 函數不能互調
void process_data_main(void) { /* 實現 */ }
void process_data_isr(void) { /* 完全相同的實現 */ }
主循環調用 process_data_main,ISR 調用 process_data_isr。零開銷,代碼體積翻倍,適用於短小函數。
// 方法 1:#pragma 禁用中斷(需配合 OVERLAY 指令排除覆蓋分析)
#pragma disable
process_data();
#pragma enable
// 方法 2:直接操作 EA 位(8051 內核)
EA = 0;
process_data();
EA = 1;
注意:關中斷時間不宜過長,影響實時性;ISR 內絕不可調用長耗時函數。
__monitor 關鍵字(原子執行)、或手動關中斷__attribute__((interrupt)) ISR 內不調用共享函數;用 atomic 區塊或鎖保護std::atomic_flag 自旋鎖、或無鎖環形緩衝區傳遞數據