原博客地址:https://blog.csdn.net/j353838430/article/details/80261346
每次看見自己雜亂無章的模型,總是有一股無力感,看到好的文章,忍不住轉發出來,同時也方便自己日后看。
Simulink模型架構指導
LICENCE: 本文根據《JMAAB V4.01》部分章節進行翻譯和整理,文中只是針對MBD開發方式描述了模型架構的綱要和觀念。由於Simulink提供了多種可以滿足需求的模塊及建模方法,所以很難進行詳盡的描述說明,翻譯和整理由Tomato一人完成,歡迎探討,轉載時需要保留本段文字
1. Simulink 和 Stateflow的角色
所有的系統都可以使用Simulink或Stateflow進行建模。
如果使用Stateflow進行建模,Simulink僅僅作為信號的輸入輸出和仿真,在Stateflow中可以使用多種公式和方法來替代simulink進行處理。如果只用Simulink,可以通過使用Switch-Case塊的方法來替代Stateflow實現復雜的狀態變量。
因此,使用Simulink或Stateflow對於特定部分的建模,是主觀依據開發人員對於哪種表達方法更為理解。應該根據整體的團隊水平來實現如上選擇和建模。
在大多數情況下,Stateflow的RAM效率要比Simulink差。因此,Simulink在使用簡單公式的計算中具有優勢。除此之外,Simulink在使用簡單的觸發和切換系統中,對於狀態變量的使用也更具有優勢。當使用Stateflow所建的模型可以用Simulink進行替代建模時,需要考慮如下因素進而做出決定:
- 確保靜態RAM足夠大,以保證Stateflow 的輸入輸出以及內部變量的正確運行。
- 當使用內部通用計算公式時,要設計防溢出的保護。
- 當外部計算完成時,需要對整體進行分塊,以降低這個模塊的理解難度。
在一些情況下,Stateflow能夠比Simulink進行更接近於C語言的表達方法,但是這樣的模型沒有很好的外觀狀態,並不是很容易理解。在這些情況下,使用S-Function會更有利。
Stateflow 可以計算特定的狀態安排,或進行for-loop的計算,在這些層面上要比Simulink更有效率,但是近些年來,使用Matlab語言進行如上計算,也變得更有效率一些。
當使用Simulink進行建模時,如果處理如下所述的狀態,則可通過使用Stateflow來改善可讀性。
- 同一個輸入有不同的輸出值
- 多個狀態存在 (例如3個及更多)
- 對於定義的一個狀態的意義,不是無限的值而是一個離散的數值。
- 在狀態內部,要求初始化(首次執行)和后面的 執行狀態期間有所不同。
- 除了狀態變量,輸入和輸出變量是可以被可視化的信號.
舉個例子,在觸發器電路中,不同的輸出對應於同一個輸入。而且,狀態變量的值被限定在0和1。 然而,在輸入輸出都為0或1的情況下,仍可以有無限多的狀態分類。此外,在狀態進入和執行兩個動作間沒有區別。換句話說,上訴幾條中僅僅符合第一條,所以這時候應該使用Simulink進行建模。
關於采用Simulink還是Stateflow進行建模可以和幾個人進行溝通協商,並最終取決於需要解決的實際問題。 Stateflow中是采用狀態轉換還是 流程圖函數也需要進行考慮和決定,例如需要 定奪 使用 狀態的轉換和條件分支來 替代 使用狀態的流程圖函數。真值表也被分類為使用條件分支當中的方法。
此外,當使用Stateflow進行如上設計時,需要依據經典的模型樣式進行設計,以便於能夠更好的生成嵌入式代碼。
Stateflow支持生成HDL代碼。在實現HDL編碼器時,應使用Mealy和Moore模式。此外,當需要對內部泄漏進行保護時, Moore 模式更適合。
需要注意,本指南不是針對HDL代碼生成。
2. 模型結構分層
如下示例了模型分層中分割和布局的觀念,可作為開發中的參考。這並不是一個明確的規則,但這是一個建模的基礎方法。
2.1 層的類型
搭建層的方法
- 如果主要目的為調整一層的空間排布,則應盡量避免打包到子系統
- 如下為層次的概念,子系統需要依據此描述進行分層
- 不要使用多余的層
- 一層模型中,允許復合層的建模概念
層概念
名稱 | 層概念 | 層目的 |
---|---|---|
頂層 | 功能層 | 大塊功能部分 |
調度層 | 執行時間的表達(采樣、順序) | |
底層 | 子功能層 | 功能的細節表達部分 |
控制流層 | 根據處理和執行順序划分(input → judgment → output,等) | |
選擇層 | (select output with Merge block) 切換相應被激活的子系統並且執行 | |
數據流層 | 用於不可分離計算的層 |
2.2 頂層划分方法
對於頂層划分,主要有如下三個方法
-
簡單控制模型
表現為功能層和調度層在同一層中,在這樣的模型里,功能 = 執行單元。
例子: 控制模型只有一個采樣周期,並且各功能模塊都按照執行順序進行排列。 -
復雜控制模型 α
調度層放在最頂層
這樣會使手寫代碼更容易集成,但是功能模塊被分割,導致模型可讀性降低。 -
復雜控制模型 β
功能層放在最頂層,並且調度層在各功能模塊下進行構建。
2.3 功能層和子功能層建模方法
- 根據功能划分子系統,每個子系統代表“一個獨立功能”
-
對於執行單元,“一個獨立功能”的子系統是不必要的。因此,各子系統不一定全都設為原子子系統。
(對於如上列出的 type β, 將功能層子系統設為虛擬子系統更合適一些。如果將他們設為原子子系統,則可能會出現代數環。) -
使用注釋,功能概述必須在圖層上描述或包含在子系統概述中,並顯示為注釋。
- 如果模型里有幾個大的功能模塊,則需要考慮使用模型引用。
2.4 調度層建模方法
需要設置周期間隔和優先級及順序。
-
設置多個周期間隔需要注意
在不同周期的連接系統中,有可能發生信號變量會在快周期任務中被調用,此時在慢周期中該信號還沒有被計算出來。當不同周期進行連接時,需要一塊固定的RAM區。因此,需要在頂層為每個不同周期的任務進行進行時間分割,保證底層中沒有不同周期的模塊進行連接。
-
設置優先級
在設計多個不同功能的系統時,優先級設定十分重要。建議盡量根據連接的順序來使系統自動確定運行順序。
對於順序優先級,如下項需要進行設定:不同周期的優先級,和同周期的優先級。
-
周期間隔和優先級的設定方法:
如下描述的方法可大體上分為2種類型。
- 子系統或模塊的執行周期時間和優先級設置。
- 使用條件子系統,用戶設置獨立的排列順序來匹配任務調度。
幾個條件下存在的模式,例如配置單速率或多速率,原子子系統設置,是否使用模型引用等。這其中啟用哪個功能都會直接影響到生成的C代碼,所以需要根據項目的不同情況進行綜合考量。
受影響的典型因素如下:
- 模型方面上
- 是否存在不同的采樣時間?
- 模型是否需要實現幾個獨立的功能?
- 使用模型引用
- 模型數量 (Simulink是否會生成多個源代碼)
- 源代碼方面上
- 是否使用實時操作系統
- 實際采樣周期和理論計算周期的一致性
- 適用范圍 (應用層或基礎軟件)
- 源代碼類型:是否符合/支持 AUTOSAR .
- RAM, ROM 特別是RAM剩余百分比
進行如上考量后,將會對使用的樣式進行調整。
2.5 控制層建模方法
控制層是用於表示所有輸入處理、中間處理、和輸出處理的層。模塊和子系統的排列十分重要。將多個混合的小功能分組,最后排列成3個大組,包括:輸入處理,中間過程處理,輸出處理。這三個大組構成了控制層的概念基礎。與數據流層相似的排列方法是,都使用水平線代表模塊運行順序和方向,與其不同的是控制流層大多是由復合模塊和子系統構成的。
在控制流程,同一水平線上的根據箭頭所指方向進行順序處理,同一垂直方向的代表有相同的優先級。
可以使用Area工具進行框選並標注幾個模塊的部分
控制層可以和具有功能的模塊共存。
這些模塊放置在子功能層和數據流層之間的區域。
當模塊的數量特別多,且都在數據流層進行使用,這時可以使用功能單元打包的方式進行控制層的整合。這樣會使模型更容易理解,同時提高了模型的可維護性。
即使僅由模塊構成,不存在子系統和模塊的混合體,如果模型的水平方向結構能夠划分成 輸入/中間過程/輸出 處理,這樣也可以稱作為控制層。
2.6 選擇層建模方法
選擇層可以垂直或水平方向構建。(There is no significance to which orientation is chosen)
選擇層是和控制層進行混合而成。
下圖紅色框內,根據條件只有一個子系統能夠運行,所以這被稱作為選擇層。這層模型雖然能夠被划分成 initial processing/intermediate processing (conditional control flow)/output processing
這三個處理模塊組,但是稱為控制層並不恰當,因為在控制層,水平方向代表不同的處理,並且具有相同優先級的並行處理在垂直方向上進行排列。而在選擇層,垂直方向上的並不一定是並行處理,而是每次僅選擇其中一個進行運行。
例子:
- Switching of coupled functions between running upwards or downwards, changing in chronological order.
- Switching to setting where the computation switches after the first time (immediately after reset) and second time.
- Switching between destination A and destination B.
2.7 數據流層建模方法
數據流層是在選擇層/控制層之下的一層。
當僅表現為一個功能,並作為輸入/中間過程/輸出處理的具體實現,且不能再進行划分,則這樣的一層被稱作為數據流層。舉個例子,一個持續計算不能被分割的系統。除一些特殊情況下,數據流層不允許出現子系統。
特殊情況:如下情況允許在數據流層出現子系統。
- 子系統被設為重用子系統。
- Simulink 標准庫里存在的子系統。
- 用戶自定義庫中存在的子系統。
簡單數據流層 例子
復雜數據流層 例子
當遇到輸入處理和中間過程處理不能夠清晰進行划分的時候,就如上面的例子所示,展開為數據流層。
當同時計算一個信號的前端反饋和后端反饋時,數據流層會變得復雜。甚至此種情況會有很多模塊在同一層, 但是為了清晰的表達計算,仍舊不能在數據流層進行子系統的創建。當能夠通過划分模型進行整合的時候,應該被打包成控制層而不是數據流層。
2.8 Simulink 模型和嵌入式實現的關系
在真實的嵌入式系統中運行,需要Simulink模型生成嵌入式C代碼。這有很大一部分受到Simulink配置項的影響,根據Simulink針對相關功能進行何種程度的建模,以及如何嵌入和真實系統的時間設定。
如果嵌入式系統里使用的任務與Simulink模型里調度的任務不同,這將產生很嚴重的影響。
3. AUTOSAR 概念
本文中,並不對AUTOSAR標准進行解釋,而會說明AUTOSAR的概念。用戶不必完全符合AUTOSAR標准,但必須了解它,並作為建模中的參考。
3.1 AUTOSAR 軟件平台概念
當設計一個控制模型的時候,必須要遵循AUTOSAR 軟件平台的概念,並要審查所設計的模型是歸類到應用軟件還是基礎軟件。
如果模型混合了應用和基礎軟件,需要在設計階段就進行划分。
AUTOSAR 軟件平台概念
- 高容量,低速,常規的處理在應用軟件層
- 高速,非常規驅動的處理在基礎軟件層
AUTOSAR軟件平台如下圖所示
舉個例子,設計引擎控制模型的時候,不建立以中斷執行任務方式的模型,而是在應用軟件層計算所有氣缸共享的變量。例如,計算當前排放狀態或目標力矩。當不規則中斷從基礎軟件區發生,通過RTE傳遞到應用層時,計算結果能夠被調用,實際的驅動器也能夠被激活。AUTOSTAR的概念使得基礎軟件區的通用計算能夠盡可能簡單的放到應用層。
當Simulink模型全部構建好之后, 建議在中斷服務區添加盡量簡單的計算。中斷服務程序的簡單可以減少其所占時間,這樣能保證系統調用任務時間間隔的准確性。如果可以,中斷中不要包含標准的PID計算,推薦放置僅執行設定動作的函數。當然,不能缺少必要的計算。舉個例子,對於錯誤診斷,即使是復雜計算,在該執行的時刻還是必須要診斷出結果的。
對於那些比中斷服務程序慢的部分,和接收指令要比執行速度快的部分,不應該給出直接執行的代碼,而是要讓目標值或階段值在下一個命令到來之前,通過線性插值的方法傳遞出去。
3.2 RCP 和 AUTOSAR 軟件平台
RCP(Rapid Control Prototyping)快速控制原型,是指使用模型或類模型自動生成原型代碼的方式進行開發。Simulink生成的代碼不僅僅是原型,更接近於整體的解決方案,這種解決方案一般稱之為MBD(Mode based Software Development)基於模型程序開發。
使用RCP等設備建模類似於AUTOSAR中軟件更新的概念。當然,生成的代碼不符合AUTOSAR規范。例如,RCP的I/O軟件允許供應商提供的S函數進行鏈接,並且允許用戶設置應用程序區域。應用程序中用戶自定義函數和S函數能夠在Simulink中直接連接,不需要考慮對RAM等因素的影響。
生成的C代碼在實時操作系統上運行,Simulink 里I/O相關會生成在不同的源代碼文件中,實時操作部分和作為中斷處理的部分會自然分離。用戶不必考慮那些平台;廠商創建的 I/O S-function會在需要的時候運行,並且對於 應用程序建模,不用考慮I/O處理的內容和時間。
具有這種軟件結構的真實的控制模型/軟件,會有更多的優勢。由於RCP能夠集中精力開發應用程序,而不必考慮軟件結構,他們會自然的選擇AUTOSAR 平台。換言之,如果你的產品不滿足AUTOSAR 標准,並且在RCP上使用AUTOSAR的概念進行開發,你必須自定義生成的代碼,並且從MBD開發成果的共享中分離出來。
4. 單任務和多任務
嵌入式軟件調度器設計中,有單任務和多任務的概念。
4.1 單任務
對於單任務,假定基礎周期為2ms,當2ms、8ms、10ms在系統中存在時,這些時間片都是基於2ms的計時器進行創建的。每2ms的執行順序為:8ms的任務下每4個2ms任務后執行一次,10ms就是每5個2ms。需要注意的是,要使用低頻率的任務片來處理復雜的運算,並且2ms、8ms、10ms都是由相同的2ms進行周期計算。因為所有的運算都要在2ms內完成,以便保證嵌入式軟件的實時性,在這種情況下8ms和10ms的任務被分割成了幾段,以保證所有2ms的計算量基本持平。在這種方法下,可以通過分區來減少每個周期的計算量,並且使得CPU負載平均分配。
基於如上原因,10ms的任務片被分成如下幾個部分。
Fundamental frequency | Offset |
---|---|
10ms | 0ms |
10ms | 2ms |
10ms | 4ms |
10ms | 6ms |
10ms | 8ms |
同理可知,8ms的任務片被分割成了4部分。
當然,絕對的平均分配是不現實的,某些運算功能不能夠被分配到所有周期,但重要的是報保證CPU的平均一致的負載率
如何設置任務的運行頻率
設置Tasking mode for periodic sample times 為 Single Tasking
然后在子系統的“Sample Time”中輸入 “sampling period, offset” 的值。可以指定運行周期的子系統為 原子子系統。
4.2 多任務
多任務為使用實時操作系統的情況下,系統支持多任務周期設定。如之前介紹單任務中所述,在單任務系統中,平衡CPU負載率不是自動的,需要進行巧妙的設定。而在多任務系統中,CPU會根據當前狀態進行自動計算,並且不需要進行特殊的任務分配和設定。系統會從優先級高的任務開始計算並給出結果,任務的優先級由開發人員進行設定。大多數情況下,需要快速執行的任務被分配高的優先級。
在周期內完成計算是十分重要的,包括慢任務,和當高優先級任務執行計算且CPU 釋放時,執行下一個優先級任務的計算。高優先級任務會打斷低優先級任務,並會先執行完高優先級的計算。
4.3 不同運行周期的子系統連接后的影響
如果子系統B有20ms的運行周期,使用了10ms運行周期的子系統A的輸出,當B還在進行計算的時候A可能會有不同的輸出。如果在運算過程中發生了值得改變,子系統B可能會運算出一個錯誤的結果。舉個例子,在B中如果存在首次計算值與A的輸出比較的運算,且最終輸出依據比較的結果,此時有可能發生在B計算過程中A的值發生改變,導致最終輸出不正確的情況。為了避免此種情況發生,如果任務主體發生改變,從A得到的輸出值需要在被B使用之前進行固定。換言之,即便在B運算過程中A的輸出值發生改變,因為調用了不同的RAM區,最終的計算結果也不受影響。
當在Simulink中創建模型並且在Simulink中連接了具有不同運行周期的子系統時,Simulink會自動保留所需的RAM。
當然,如果不同運行周期的輸入值獲得是通過 手寫代碼集成的方式,則相應嵌入式軟件工程師需要進行相應RAM區保留的設置。在AUTOSAR中的RTW層,就是在接收和發送出口方面都定義了了不同的RAM。
單任務
2ms循環內信號值相同,但是需要注意不同的2ms運算值和上一個2ms的值可能不同。如果2-1 、 2-2 使用了F 1中的信號A,則 2-1 、 2-2 會使用不同2ms任務計算出的值,此處要進行影響識別。
多任務
對於多任務,不能夠指定使用計算結果的時間點。在多任務系統中,無論是否為不同運行周期,總是需要給信號變量和傳遞變量分配不同的RAM。
在執行任務的新計算之前,所有的值都會一次性復制一遍。