Ing. Zdeněk Bradáč, Ing. Petr Fiedler,
Ústav automatizace a měření, Vysoké učení technické v Brně
bradac@dame.fee.vutbr.cz, fiedlerp@dame.fee.vutbr.cz
Návrh spolehlivého softwaru pro řídící účely
Článek je věnován problematice tvorby spolehlivého softwaru pro vestavná zařízení určená pro řídící účely. Při aplikaci zásad uvedených v článku by měl být výsledkem práce programátora přehledně uspořádaný software, který lze snadno testovat a validovat a který projde testy s minimálními požadavky na dodatečné úpravy, tj. software, který je zárukou spolehlivé a bezpečné funkce zařízení, pro něž byl sestaven. Autoři vycházejí z požadavků platných norem modifikovaných podle specifických rysů softwaru pro vestavné mikropočítačové systémy.
1. Úvod
V mnoha oblastech lidské činnosti v současné době existuje velké riziko selhání řídicího systému a v návaznosti na nebezpečné technologie prudce vzrůstá riziko ohrožení majetku, přírodních zdrojů a primárně člověka. Vzhledem k nutnosti strukturovat řídicí systém a k finančním omezením jsou často používány, popř. vyvíjeny inteligentní senzory a akční členy připojitelné k řídicímu systému zpravidla přes sériovou komunikační sběrnici. Takovéto řešení často vychází z cenového pohledu příznivěji, avšak mnohdy není možné zaručit dostatečné testování na úrovni hardwaru i softwaru. V článku je uveden stručný přehled prvotních požadavků na bezpečné řešení jednoduchých aplikací založených na mikrořadičích a zásady tvorby softwaru pro takovéto systémy. Doporučení se týkají především způsobu a formy programování zařízení s ohledem na normu IEC 880 [1], resp. ČSN IEC 880 [2]. Jde o normu vztahující se zejména na systémy jaderných elektráren a stanovující požadavky a doporučení týkající se softwaru bezpečnostních systémů, která současně definuje některé zásady tvorby bezpečných systémů. Na etapu návrhu softwaru se dále vztahují také doporučení uváděná např. v mezinárodních normách [3], [4] a [5] (v [5] zejména Part 1: General Framework, Definition, System Software and Hardware Requirements).
2. Zásady tvorby uživatelského softwaru
Vlastní uživatelský software, který je primárně tvořen pro vestavné (embedded) systémy založené na mikrořadičové technice, musí splňovat některá kritéria definovaná s ohledem na zajištění jeho správné funkce. Primárními požadavky jsou zde jednoduchost a přehlednost jako základní předpoklad možnosti testování, ověření správné funkce a konečné validace softwaru. Z ekonomických a mnoha dalších důvodů je při tvorbě softwaru vhodné, aby tvůrce (programátor) používal určitý předem navržený a odsouhlasený způsob tvorby softwaru a tak přímo vytvářel software, který projde testy a validací bez nutnosti následných úprav, jež by mohly být příčinou dalších chyb a poruch.
Základní požadavky, kterými je třeba se řídit při tvorbě spolehlivého softwaru, jsou podle [7] tyto:
- struktura programu má být založena na modulární koncepci;
- struktura programu má být jednoduchá a snadno srozumitelná, bez zpětných skoků, programových triků a zhušťování kódu;
- musí být zajištěna podrobná dokumentace;
- přednost mají problémově orientované jazyky před strojově orientovanými;
- přednostně se používá grafická dokumentace;
- ověření (verifikace) funkcí při programování začíná zkoušením modulů a postupuje programovými prostředky podle strategie zdola nahoru;
- počítačový systém musí kontrolovat ruční vstup z hlediska syntaktické správnosti.
Lze konstatovat, že při dodržení zmíněných zásad je zařízení technicky způsobilé k tomu, aby mohlo být označeno za bezpečné. Skutečně takto označeno však může být pouze za předpokladu úspěšného úplného otestování a celkové validace.
Tab. 1. Návrhové postupy
Návrh shora dolů: |
obecné předchází speciálnímu |
na každé úrovni zpřesnění návrhu je nutné program verifikovat a dokumentovat |
vývoj programu s použitím vyšších úrovní popisného formalismu |
(grafické způsoby mají přednost) |
Mezilehlé ověřování (verifikace): |
návrh je na každé úrovni zpřesnění úplný a konzistentní |
každá úroveň zpřesněného návrhu je konzistentní ve vztahu k předcházející úrovni |
Změny během vývoje: |
před začleněním do systému musí být změněný modul znovu vyzkoušen |
je třeba vyzkoušet, jak na změny v modulu reaguje okolí modul |
|
|
3. Podrobné požadavky na software pro vestavné systémy
Doporučení pro programátora vestavných systémů jsou dále uvedena ve stejné skladbě, jak je definuje norma [1], avšak redukovaná pouze na problematiku týkající se funkčního modulu integrovaného softwaru bezpečného systému. Takovým funkčním modulem je přitom jakékoliv zařízení začleněné do systému se zvýšenými nároky na bezpečnost a spolehlivost. Takto široké vymezení je nezbytné, neboť není možné vytvořit bezpečný a spolehlivý systém na základě nespolehlivých komponent a bez garance jejich funkcí.
Tab. 2. Struktury programových prostředků
Systematické třídění částí programu: |
oddělit aplikační program od řídicích a přístupových aspektů programového prostředku, tedy od:
– řízení,
– zpracování přerušení,
– hodin reálného času,
– utilit,
– mapování standardních funkcí do technického prostředku. |
struktura programu musí umožnit snadné zavedení očekávatelných změn s minimální námahou |
program má pracovat v procesoru sekvenčně |
program má být členěn na moduly po maximálně 100 příkazech |
Moduly: |
jasné a srozumitelné |
každý modul má odpovídat specifické funkci |
modul má mít jen jeden vstup a doporučen je i jen jeden výstup |
modul nemá obsahovat více než 100 příkazů |
rozhraní mezi moduly má být co nejjednodušší |
počet v/v parametrů modulů má být omezen na minimum |
Požadavky na operační systém: |
nejlepší je nepoužívat žádný operační systém |
v případě nutnosti použít jen nezbytné funkce operačního systému |
Doby trvání výpočtu: |
závislosti rozdílů v době trvání výpočtu na vstupních parametrech mají být dokumentovány (technická dokumentace) |
Přerušení: |
použití a maskování přerušení musí být plně dokumentováno |
Aritmetické výrazy: |
akce nesmí záviset na složitém aritmetickém výraz |
Tab. 3. Samokontroly
Kontrola smyslu (defenzivní programování): |
použít opakovací procedury |
správnost výsledků ověřit různými způsoby |
Bezpečný výstup: |
je-li detekována porucha vlastního systému, následná akce musí vést na přesně definovaný výstup |
doporučují se techniky k odstranění chyb (při poškození dat v operační paměti nebo při čtení nebo zápisu dat) |
je-li použita technika odstranění chyb, je nutné o výskytu chyby podat zprávu |
Obsah paměti: |
chránit paměťový prostor konstant a parametrů a sledovat ho ohledně nežádoucích změn |
vyloučit neoprávněný zápis a čtení obsahu paměti |
ochránit před nekvalifikovaným zásahem operátora |
kontrolovat správnost zadávaných hodnot parametr |
Doporučení a postupy vedoucí ke spolehlivému softwaru řídicího systému se pro přehlednost dělí do pěti oblastí, jež jsou podrobněji rozvedeny v připojených tabulkách. Dotýkají se:
- návrhových postupů (tab. 1),
- struktury programových prostředků (tab. 2),
- samokontroly (tab. 3),
- podrobného návrhu a kódování (tab. 4),
- doporučení závislých na jazyku (tab. 5),
Tab. 4. Podrobný návrh a kódování
Větve a smyčky |
používat především sekvenční programování |
vyhýbat se podmíněnému a nepodmíněnému větvení |
namísto zpětného větvení používat příkazy smyček |
nepoužívat větvení ve smyčkách, modulech nebo subrutinách |
smyčky navrhovat jen s konstantním maximálním rozsahem proměnných ve smyčce |
Subrutiny a procedury mají být organizovány co nejjednodušeji |
mají komunikovat s okolím jen prostřednictvím svých parametrů |
subrutina má mít jen jeden vstupní bod |
subrutina se vrací jen k jednomu bodu (výjimku tvoří implicitní výstup) |
bod návratu má následovat ihned za bodem volání |
Struktury vložené do sebe |
vyhýbat se do sebe vloženým makroinstrukcím |
vyhýbat se slučování odlišných typů programových činností pomocí do sebe vložené smyčky |
používat hierarchii procedur a smyček, jestliže vyjasňují strukturu systému |
Adresování a pole |
používat jednoduché techniky adresování dat a polí |
nepoužívat dynamická pole |
Datové struktury |
datové struktury a dohodnutá pojmenování je nutné používat jednotně v celém systému |
identifikovat systémové parametry, které se mohou měnit |
konstanty a proměnné umísťovat na odlišných místech pamět |
Tab. 5. Doporučení závislá na jazyku
Assembler |
větvení instrukcí s použitím substituce adres nesmí být použito; obsah tabulky větvení má zůstat konstantní |
všechna nepřímá adresování mají sledovat stejné schéma |
doporučuje vyhnout se násobným substitucím a násobnému indexování v rámci strojové instrukce |
na návěští se odkazovat jménem (nikoliv absolutní nebo relativní adresou) |
dohodnutá forma volání subrutin má být jednotná v celém systému a specifikovaná dalšími pravidly |
Požadavky na volbu programovacího jazyka, strukturu programu a zásady jeho tvorby, stejně jako požadavky a doporučení týkající se překládače, spojovacího programu (linker), simulátorů a emulátorů jsou obsaženy v příloze D normy [2]. Všeobecně platí:
- přednost se dává vyšším programovacím jazykům před jazyky strojově orientovanými;
- vstupní parametry, výstupní parametry a přechodné parametry mají být syntakticky odlišné.
4. Doporučení k organizaci a obsazení paměti
Má-li systém fungovat spolehlivě a bezpečně, je vhodné se řídit některými doporučeními týkajícími se uložení provozních dat, proměnných a konstant. Jelikož je často vyžadováno úplné oddělení paměťových oblastí obsahujících odlišné informace (např. předem nastavené konstanty, pracovní proměnné atd.), je vhodné přesně definovat jejich dislokaci. Následně je možné testovat integritu obsahu paměťových bloků a odhalovat chyby. Větší bezpečnosti celého zařízení lze dosáhnout zálohováním (mirroring) důležitých bloků paměti. Jestliže to konstrukce zařízení umožňuje, je při duplikaci bloků paměti vhodné ukládat duplikovaná data do jiné fyzické paměti (jiný paměťový čip nebo jiný typ paměti vhodný k zálohování, jako je např. EEPROM).
Podívejme se podrobněji, jak při konstrukci spolehlivého zařízení zacházet s konstantami a primárními parametry a s pracovními proměnnými.
Provozní konstanty a primární parametry jsou předem nastavené konstanty a hodnoty, které slouží k dynamickým výpočtům, ale jejich hodnota se dynamicky nemění. Jejich hodnoty se mění pouze při konfigurování nebo kalibraci zařízení. Doporučuje se:
- Provozní konstanty a primární parametry ukládat (tj. zálohovat) v bloku do externí paměti dat (tzv. primární kopie provozních parametrů). Při výpočtech prováděných programem z tohoto bloku ani nečíst, ani do něj nezapisovat.
- V okamžiku spuštění zařízení pořizovat pracovní kopii provozních konstant a primárních parametrů (sekundární kopie provozních parametrů), určenou pro provádění výpočtů a manipulaci s daty. V průběhu činnosti programu je vhodné ověřovat konzistenci sekundární kopie provozních parametrů nebo porovnávat obsahy primární a sekundární kopie. Zjistí-li se poškození sekundární kopie provozních parametrů, je třeba ji z primární kopie obnovit.
- Ověřovat konzistenci primární kopie provozních parametrů a při jejím poškození ji obnovit z hierarchicky nadřazeného systému.
Pracovní proměnné jsou proměnné určené k výpočtům, řídicí proměnné cyklů, lokální proměnné atd. Doporučuje se:
- Pro uložení pracovních proměnných vymezit jeden souvislý blok paměti.
- Při ukládání do interní paměti dat je třeba brát ohled na její omezenou velikost. Naproti tomu však tato paměť nevyužívá externí sběrnicový subsystém, takže je zde minimalizován vliv rušení.
- Pracovní proměnné lze ukládat i do externí paměti, avšak za cenu pomalejší manipulace s daty a s rizikem rušení.
- Velké spolehlivosti lze dosáhnout při ukládání bloku pracovních proměnných ve dvou kopiích, a to do interní i externí paměti dat. Je však nutné testovat konzistenci a pro výpočty používat hodnoty z neporušené kopie. Toto řešení se jeví jako programově náročnější a není vždy nezbytně nutné.
5. Návrh dohlížecího obvodu
5.1 Funkce dohlížecího obvodu
Primární úlohou tzv. dohlížecího obvodu systémů založených na mikroprocesorovém řízení (watchdog) je informovat o tom, zda v zařízení správně funguje provozní program. Základem činnosti dohlížecího obvodu je periodická kontrola průchodu programu určitou předem místně i funkčně specifikovanou částí, která je do něj úmyslně vložena. Na základě vyhodnocení doby mezi dvěma následujícími průchody je možné zjistit, zda program správně vykonává požadovanou činnost.
5.2 Příčiny chybného chování
Testování popsané v předchozím odstavci je nutné proto, aby bylo možné odhalit nežádoucí stavy v činnosti programu a popř. jim zabránit. Zařízení se přitom může nevhodně chovat z různých příčin. V praxi jsou nejčastější tři základní situace:
- chyba v řídicím algoritmu,
- chyba algoritmu v návaznosti na hardware,
- chyba v důsledku poruchy hardwaru.
Nesprávný řídicí algoritmus znamená chybu v řídicím programu, která může vzniknout nepozorností nebo omylem při analýze řídicí úlohy a tvorbě programu. Zde se doporučuje věnovat patřičnou pozornost analýze úlohy, rozpracování blokové struktury programového prostředí s využitím modulové struktury a standardních metod volání podprogramů (procedur) a testování funkčních schopností programových modulů. Častými projevy chyb tohoto druhu jsou např. „zabloudění“ programu nebo příliš dlouhé (i nekonečně) vykonávání cyklů nebo podprogramů, větvení programu s podmínkami, které nikdy nenastanou atd.
Chyby algoritmu v návaznosti na hardware vznikají především jako důsledek obtížně předvídatelných interakcí softwaru a hardwaru. Příčinou může být např. nedostatečný hardware, zpravidla ve spojení s nepozorností při tvorbě softwaru. Většinou jde o přeplnění zásobníkové paměti a tím ztrátu návratových adres nebo dat. Tato situace může způsobit posunutí v čítači adres a popř. odskok na funkčně nedefinovanou adresu, čímž se přeruší vykonávání programu a může nastat i úplný kolaps řídicího systému.
Poruchou hardwaru se označují situace nastalé v důsledku vlastní poruchy hardwaru zařízení nebo jako důsledek rušení hardwaru vlivy z vnějšího prostředí. Projev může být stejný jako v předchozích případech, tj. porucha ve vykonávání algoritmů a tím havárie systému.
5.3 Řešení dohlížecího obvodu
Při řešení dohlížecího obvodu lze postupovat dvěma diametrálně odlišnými způsoby.
První určuje maximální přípustnou periodu průchodu programu kontrolními body, ve kterých se dohlížecímu obvodu programově hlásí, že do nich program ve své činnosti dospěl. Doporučuje se stanovit periodu průchodu dostatečně krátkou tak, aby kontrolní body musely být umístěny ve všech časově náročnějších oblastech programu a ve všech podprogramech. Za časově náročné oblasti programu lze považovat cykly, rekurzivní volání podprogramů, podprogramy přerušovacího subsystému apod. Toto řešení vyžaduje rozsáhlou analýzu funkce programu a postupu jeho vykonávání. Vzhledem k zpravidla dosti velkému počtu kontrolních bodů lze dosáhnout velmi rychlé reakce na „zabloudění“ programu či chybu v jeho provádění. Nevýhodou je, že při nevhodné volbě kontrolních bodů, jako např. při umístění dovnitř smyčky nebo cyklicky volaného podprogramu přerušení, je test trvale pozitivní, tj. ukazuje, že program správně funguje, i v situaci, kdy tomu tak ve skutečnosti není.
Druhý způsob je založen na určení maximální doby mezi opakovanými průběhy hlavní smyčky hlavního programu, pokud to povaha programového vybavení dovoluje. Tomuto řešení je však vlastní o mnoho pomalejší detekce chybného vykonávání programu. Avšak vzhledem k umístění jednoho, popř. – při několika sekvenčně řazených hlavních smyčkách – několika kontrolních bodů (v porovnání s předchozím způsobem ale řádově méně, neboť se počítá s jedním kontrolním bodem v každé z hlavních smyček) jsou analýza chování programu i kontrola umístění kontrolních bodů jednodušší. Dobu, po jejímž uplynutí se kontroluje průchod kontrolními body, lze volit i delší, což však přirozeně znamená pozdější detekci nesprávné činnosti programu.
Dohlížecí obvod je v současné době možné považovat za standardní součást řídicích systémů ať již v interní podobě, tj. zabudovaný do procesorové jednotky, nebo v podobě externí, tj. vázané na obvody obnovující výchozí nastavení (reset) procesorové jednotky.
Realizuje-li se dohlížecí obvod způsobem založeným na maximální přípustné periodě průchodu programu kontrolními body, lze ho řešit jako interní i jako externí. Perioda průchodu zde trvá řádově milisekundy až několik málo sekund.
Externí dohlížecí obvody je možné vytvořit i tak, aby pracovní perioda mohla být i mnohem delší. Jsou tudíž vhodné pro druhý způsob řešení dohlížecího obvodu, jenž je založen na sledování doby trvání hlavní smyčky činného programu.
Principem dohlížecího obvodu je měření periody obdélníkového signálu odvozeného z kontrolních bodů programu. U některých realizací interního dohlížecího obvodu, který je zabudován do procesorové jednotky, není nutné generovat obdélníkový signál, ale stačí pouze provést zápis na určitou adresu, což zjednodušuje tvorbu kontrolních bodů.
6. Diagnostika zařízení
Diagnostický podsystém mnohdy tvoří nepříliš rozsáhlou, avšak pro vestavná zařízení nezbytnou součást programového vybavení.
Je nutné cyklicky testovat paměť a dohlížecí obvod, zatímco testovat funkceschopnost vlastního procesoru nemusí být, s ohledem na poměrně velkou spolehlivost těchto obvodů, nezbytně nutné. Součástí diagnostiky, resp. dohledu nad správnou činností zařízení, je hlídání podstatných parametrů (konstant), které slouží k výpočtu. Za tím účelem se doporučuje:
- uložit konstanty a proměnné do dvou navzájem oddělených paměťových prostorů;
- průběžně porovnávat jejich hodnoty před použitím ve výpočtu;
- sledovat možné chyby při zadávání, výpočtech a užití hodnot.
Další součástí diagnostického nebo dohlížecího podsystému by měl být systém pro dokumentaci zásahů obsluhy. Měl by být dokumentován čas změny parametrů a jejich hodnota. Mělo by být hlášeno překročení mezí parametrů nad a pod určitými kritickými horními i dolními mezními hodnotami. Rovněž tak by měl být v plném rozsahu veden protokol o případné komunikaci s nadřazeným systémem v decentralizovaných strukturách včetně sledování změn parametrů.
7. Testování softwaru
Ve shodě s normou [2] je třeba zkontrolovat program zařízení z těchto hledisek:
- testování aritmetiky a časování;
- testování všech vstupních proměnných v extrémech;
- otestování statické úlohy a dynamických cest, které jsou reprezentativní pro dané zařízení a odpovídající technologii;
- testování všech úloh a cest, které se mohou v technologickém procesu vyskytnout.
Cesty je přitom třeba testovat takto:
- každý příkaz vykonat alespoň jednou;
- každý výstup každé větve vyzkoušet alespoň jednou;
- každou smyčku spustit s minimální, maximální a alespoň jednou mezilehlou hodnotou;
- každou cestu spustit alespoň jednou;
- každé přiřazení do každého paměťového místa uskutečnit alespoň jednou;
- každý odkaz na každé paměťové místo realizovat alespoň jednou;
- všechna zobrazení ze vstupů na výstup zkusit alespoň jednou pro každé z nich (povinně jen u modulů).
Časování je třeba testovat v tomto rozsahu:
- zkontrolovat všechna časová omezení,
- zkontrolovat maximální možný počet přerušovacích sekvencí,
- prověřit všechny kombinace přerušovacích sekvencí,
- zkontrolovat správné nastavení mezních hodnot vstupních dat,
- zkontrolovat přesnost aritmetických operací,
- ověřit rozhraní modulů a interakce modulů,
- každý modul vyvolat alespoň jednou,
- každé vyvolání modulu vyzkoušet alespoň jednou.
8. Validace a verifikace softwaru
U každého zařízení, od kterého je požadována spolehlivá a bezpečná činnost, je třeba zajistit validaci použitého softwaru (ověřit, zda vlastnosti softwaru zařízení jsou v souladu s požadavky kladenými na zařízení). Při vlastním vývoji softwaru zařízení je požadována verifikace, tj. ověřování, zda výsledek každé fáze tvorby softwaru splňuje všechny požadavky dané předchozí fází.
Verifikace začíná zkoušením modulů a postupuje programovými prostředky podle strategie zdola nahoru. Účelem verifikace na úrovni modulů je ukázat, že každý modul plní žádanou funkci a nevykonává funkce nežádoucí. Musí se rovněž vyzkoušet, zda moduly správně spolupracují navzájem mezi sebou.
9. Závěr
Článek přibližuje dynamicky se rozvíjející oblast technologií, které se stále častěji stávají rizikovými pro člověka, majetek anebo životní prostředí. V takovýchto systémech je třeba klást větší, až velký důraz na spolehlivost řídicího systému, který má svou podstatou omezit riziko kolapsu systému jako celku. Přitom je vhodné vycházet z technických předpisů a norem, které jsou precizním derivátem zkušeností a souhrnem z nich plynoucích doporučení. V článku jsou uvedeny hlavní zásady, které pro tvorbu spolehlivého softwaru pro vestavná zařízení vyplývají z norem. K normám i zmíněným zásadám však není nutné přistupovat jako k neměnnému dogmatu. Normy ponechávají volný prostor k implementacím a aplikacím na konkrétní požadavky. Je proto možné souhlasit s následujícím prohlášením: „Standarts are not black and white or cast in stone – they are open to interpretation. They are also just as prone to be open to mis-interpretation.“ (Gruhn, P. E., Moore Process Automation Solutions).
Literatura:
[1] IEC 880 Software for Computers in the Safety Systems of Nuclear Power Plants. International Electrotechnical Commision. 1986.
[2] ČSN IEC 880 Programové prostředky počítačů bezpečnostních systémů jaderných elektráren. Listopad 1993.
[3] IEC 61508 Functional safety of electrical/electronic/programmable electronic safety related systems. International Electrotechnical Commision. Draft 1998.
[4] ANSI/ISA-S84.01-1996 Applicatin of Safety Instrumented Systems for the Process Industries. Instrumentation Society of America. 1996.
[5] IEC 61511 Functional Safety Instrumented Systems for the Process Sector. International Electrotechnical Commision.
[6] MIL-STD-883C System Safety Program Requirements. 1993.
[7] ZEZULKA, F.: Zásady tvorby software pro boroměr typ PN160. Expertní posudek. 1999.
[8] NAMUR NE 31Safety of Process Plants Using Measurement and Control Equipment. NAMUR 1995.
[9] DIN 19250 Grundlegende Sicherheitsbetrachtungen für MSR-Schutzeinrichtungen. Deutsches Institut für Normung. 1994.
[10] DIN 19251 Process control technology – MC protection equipment – Requirements and measures for safeguarded function. Deutsches Institut für Normung. 1995.
|