前后台系统的精髓
有個產品負責把RS485上的通訊轉到電力線(PLC)上。這樣這個產品主要由兩個任務組成:PLC通訊及485通訊。
第一個工程師在裸機上實現了功能!因為當時項目忙,沒空檢查其程序。(唉,現在想起來,公司對軟件項目沒有一套成熟的管理制度,導致那時項目管理非常吃力!)
因為公司待遇低,第一個工程師走了。項目轉給第二個工程師時,工程師報告說兩個通訊老有沖突:忙485時,忙不了PLC。 一檢查:原來程序里幾乎都是在main函數里用分時實現了兩個通訊,還有一大堆的delay調用。于是給第二個工程師指示:這樣不行的,通訊應該盡量使用中斷來收發最低層的數據!
于是第二個工程師開始改程序。完了報告說:不錯,有進步了!
因為公司待遇不理想,第二個工程師很快也走了 (公司把開發工程師的薪水跟生產線工程師來比--你們研發部工程師的薪水是我們公司所有工程師里最高的!)。項目轉給了第三個工程師時,工程師報告說有時485發送的數據PLC還是不理會!一檢查:原來第二個工程師優化程序時竟然把所有的PLC的接收代碼放進了PLC的接收中斷程序,把所有的485接收代碼放進了RXD中斷程序。于是給第三個工程師指示:緊急的事務一定要用中斷處理;中斷只處理緊急事務!
其實,這是前后臺系統最典型的應用(也是任何一個系統必需要注意的):緊急的事務一定要放到前臺(前后臺系統里稱中斷程序是前臺:可實時處理的),讓所有不緊急的事務放到后臺處理(前后臺系統里稱主程序里的死循環為后臺:在后面處理不緊急事務的)。這樣,上面的程序就是這樣了:
主程序:系統初始化-》使能485發送及接收中斷-》使能PLC發送及接收中斷-》主程序的死循環。
死循環內容:
1.如果485接收完成一個數據包:處理它,處理完后可能會開啟一個數據包的發送,開啟發送中斷,讓發送在前臺進行;
2.如果PLC接收完成一個數據包:處理它,處理完后可能會開啟一個數據的包的發送,開啟發送中斷,讓發送在前臺進行;
485接收中斷:把串口接收里的一個字節讀入到內存(也可能是幾個字節,這要看MCU的支持); 如果這是一個包的最后一個字節,用全局變量/信號量的方法通知后臺主程序去處理;
485發送中斷:把下一個字節裝入串口發送寄存器里(也可能是幾個字節,這要看MCU的支持);如果這是一個包的最后一個字節,關掉自己的(中斷),以免下次再進入。
PLC接收中斷:把IO里一個bit的數據讀入到內存;如果這是一個包的最后一個位,用全局變量/信號量的方法通知后臺主程序去處理;
PLC發送中斷:把下一個位從IO口送出;如果這是一個包的最后一個字節,關掉自己的(中斷),以免下次再進入。
這樣,最緊急的收發位/字節都是在前臺中斷完成;對整個包的處理都在后臺主程序完成。沒有delay,沒有干擾,兩個通訊完美地融合在一起!
緊急的事務一定要用中斷處理!中斷只處理緊急事務!
第一個工程師在裸機上實現了功能!因為當時項目忙,沒空檢查其程序。(唉,現在想起來,公司對軟件項目沒有一套成熟的管理制度,導致那時項目管理非常吃力!)
因為公司待遇低,第一個工程師走了。項目轉給第二個工程師時,工程師報告說兩個通訊老有沖突:忙485時,忙不了PLC。 一檢查:原來程序里幾乎都是在main函數里用分時實現了兩個通訊,還有一大堆的delay調用。于是給第二個工程師指示:這樣不行的,通訊應該盡量使用中斷來收發最低層的數據!
于是第二個工程師開始改程序。完了報告說:不錯,有進步了!
因為公司待遇不理想,第二個工程師很快也走了 (公司把開發工程師的薪水跟生產線工程師來比--你們研發部工程師的薪水是我們公司所有工程師里最高的!)。項目轉給了第三個工程師時,工程師報告說有時485發送的數據PLC還是不理會!一檢查:原來第二個工程師優化程序時竟然把所有的PLC的接收代碼放進了PLC的接收中斷程序,把所有的485接收代碼放進了RXD中斷程序。于是給第三個工程師指示:緊急的事務一定要用中斷處理;中斷只處理緊急事務!
其實,這是前后臺系統最典型的應用(也是任何一個系統必需要注意的):緊急的事務一定要放到前臺(前后臺系統里稱中斷程序是前臺:可實時處理的),讓所有不緊急的事務放到后臺處理(前后臺系統里稱主程序里的死循環為后臺:在后面處理不緊急事務的)。這樣,上面的程序就是這樣了:
主程序:系統初始化-》使能485發送及接收中斷-》使能PLC發送及接收中斷-》主程序的死循環。
死循環內容:
1.如果485接收完成一個數據包:處理它,處理完后可能會開啟一個數據包的發送,開啟發送中斷,讓發送在前臺進行;
2.如果PLC接收完成一個數據包:處理它,處理完后可能會開啟一個數據的包的發送,開啟發送中斷,讓發送在前臺進行;
485接收中斷:把串口接收里的一個字節讀入到內存(也可能是幾個字節,這要看MCU的支持); 如果這是一個包的最后一個字節,用全局變量/信號量的方法通知后臺主程序去處理;
485發送中斷:把下一個字節裝入串口發送寄存器里(也可能是幾個字節,這要看MCU的支持);如果這是一個包的最后一個字節,關掉自己的(中斷),以免下次再進入。
PLC接收中斷:把IO里一個bit的數據讀入到內存;如果這是一個包的最后一個位,用全局變量/信號量的方法通知后臺主程序去處理;
PLC發送中斷:把下一個位從IO口送出;如果這是一個包的最后一個字節,關掉自己的(中斷),以免下次再進入。
這樣,最緊急的收發位/字節都是在前臺中斷完成;對整個包的處理都在后臺主程序完成。沒有delay,沒有干擾,兩個通訊完美地融合在一起!
緊急的事務一定要用中斷處理!中斷只處理緊急事務!
總結
- 上一篇: 如何成为一个Linux内核开发者
- 下一篇: 临界区问题的产生