Systemy operacyjne dla systemów wbudowanych
Transkrypt
Systemy operacyjne dla systemów wbudowanych
Programowanie mikroprocesorów jednoukładowych Systemy operacyjne dla systemów wbudowanych Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 1 / 30 Plan I SLOS Inicjalizacja Model pamięci Obsługa przerwań i wyjątków Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 2 / 30 Simple Little Operating System SLOS to mały system operacyjny napisan na rdzeń ARM7TDMI oraz płytę ewaluacyjną Evaluator-7T. Jest prosty w modyfikacji i jest uruchamiany przez Sandstone firmware. Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 3 / 30 Inicjalizacja systemu I Listing 1: Inicjalizacja 1 2 3 4 5 6 7 8 9 10 11 12 13 AREA ENTRYSLOS , CODE, READONLY ENTRY LDR pc , v e c t o r R e s e t LDR pc , v e c t o r U n d e f i n e d LDR pc , v e c t o r S W I LDR pc , v e c t o r P r e f e t c h A b o r t LDR pc , v e c t o r D a t a A b o r t LDR pc , v e c t o r R e s e r v e d LDR pc , v e c t o r I R Q LDR pc , v e c t o r F I Q v e c t o r R e s e t DCD c o r e I n i t i a l i z e v e c t o r U n d e f i n e d DCD c o r e U n d e f i n e d H a n d l e r v e c t o r S W I DCD c o r e S W I H a n d l e r Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 4 / 30 Inicjalizacja systemu II 14 15 16 17 18 v e c t o r P r e f e t c h A b o r t DCD c o r e P r e f e t c h A b o r t H a n d l e r v e c t o r D a t a A b o r t DCD c o r e D a t a A b o r t H a n d l e r v e c t o r R e s e r v e d DCD c o r e R e s e r v e d H a n d l e r v e c t o r I R Q DCD c o r e I R Q H a n d l e r v e c t o r F I Q DCD c o r e F I Q H a n d l e r Listing 2: Ustawienia FIQ 1 2 3 4 5 6 7 8 bringupInitFIQRegisters MOV r2 , r 1 4 ; s a v e r 1 4 BL switchToFIQMode ; ch an g e FIQ mode MOV r8 ,#0 ; r 8 _ f i q =0 MOV r9 ,#0 ; r 9 _ f i q =0 MOV r10 ,#0 ; r 1 0 _ f i q =0 BL switchToSVCMode ; ch a ng e SVC mode MOV pc , r 2 ; r e t u r n Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 5 / 30 Inicjalizacja systemu III 9 coreInitialize 10 BL b r i n g u p I n i t F I Q R e g i s t e r s Listing 3: Ustawienia stosu 1 2 3 4 5 6 MOV MSR MOV MSR MOV MSR sp ,#0 x80000 ; SVC s t a c k cp s r _ c ,# N o I n t | SYS32md sp ,#0 x40000 ; u s e r / s y s t e m s t a c k cp s r _ c ,# N o I n t | IRQ32md sp ,#0 x9000 ; IRQ s t a c k cp s r _ c ,# N o I n t | SVC32md Wyniki działania powyższych listingów: I inicjalizacja niskopoziomowego debugowania I stos dla SVC, IRQ oraz systemu jest ustawiony Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 6 / 30 Inicjalizacja systemu IV Listing 4: Inicjalizacja PCB 1 2 3 4 5 6 7 8 9 ; v o i d pcbSetUp ( v o i d ∗ e n t r y A d d r , v o i d ∗PCB , UINT o f f s e t ) ; pcbSetUp STR r0 , [ r1 ,#−4] ; PCB[ −4]= C_TaskEntry STR r0 , [ r1 ,# −64] ; PCB[ −64]= C_TaskEntry SUB r0 , sp , r 2 STR r0 , [ r1 ,#−8] ; PCB[ −8]= sp−<o f f s e t > MOV r0 ,#0 x50 ; c p s r _ c STR r0 , [ r1 ,# −68] ; PCB[ −68]= i F t _ U s e r MOV pc , l r Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 7 / 30 Inicjalizacja systemu V Listing 5: Ustawienie identyfikatora 1 2 3 4 5 LDR MOV STR LDR MOV r0 ,= PCB_CurrentTask r1 ,#0 r1 , [ r 0 ] l r ,= C_Entry pc , l r ; e n t e r t h e CEntry w o r l d I Inicjalizacja PCB dla wszystkich trzech zadań I Ustawienie aktualnego PCB jako zadania 1 (identyfikator 0) Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 8 / 30 Inicjalizacja systemu VI 1 2 3 4 5 6 void c i n i t _ i n i t ( void ) { eventIODeviceInit (); eventServicesInit (); eventTickInit (2); } 1 i n t C_Entry ( v o i d ) 2 { 3 cinit_init (); 4 eventTickStart (); 5 __asm 6 { 7 MSR cp s r _ c ,#0 x50 Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 9 / 30 Inicjalizacja systemu VII 8 9 10 11 } C_EntryTask1 ( ) ; return 0; } Rezultatem wywołania wszystkich funkcji inicjalizujących napisanych w C jest: I Sterowiniki urządzeń są zainicjalizowane. I Usługi są zainicjalizowane. I Okresowy zegar jest zainicjalizowany i uruchomiony. I Przerwania IRQ są aktywne w rejsterze cpsr. I Procesor jest ustawiony w trybie użytkownika. I Punkt startu zadania pierwszego jest wywołany (np. C_EntryTask1). Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 10 / 30 Model pamięci Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 11 / 30 Obsługa przerwań i wyjątków I Wyjątek Reset SWI IRQ Mariusz Naumowicz Cel inicjalizacja systemu operacyjnego mechanizm dostępu do sterowników mechanizm obsługi zdarzeń Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 12 / 30 Obsługa SWI I 1 2 3 4 5 6 7 8 coreSWIHandler STMFD s p ! , { r0−r12 , r 1 4 } ; s a v e c o n t e x t LDR r10 , [ r14 ,#−4] ; l o a d SWI i n s t r u c t i o n BIC r10 , r10 ,#0 x f f 0 0 0 0 0 0 ; mask o f f t h e MSB 8 b i t s MOV r1 , r 1 3 ; copy r 1 3 _ s v c t o r 1 MRS r2 , s p s r ; copy s p s r t o r 2 STMFD r 1 3 ! , { r 2 } ; s a v e r 2 o n t o t h e s t a c k BL s w i _ j u m p t a b l e ; b r a n c h t o t h e s w i _ j u m p t a b l e 1 LDMFD r 1 3 ! , { r 2 } ; r e s t o r e t h e r 2 ( s p s r ) 2 MSR s p s r _ c x s f , r 2 ; copy r 2 back t o s p s r 3 LDMFD r 1 3 ! , { r0−r12 , pc }^ ; r e s t o r e c o n t e x t and r e t u r n Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 13 / 30 Obsługa SWI II 1 swi_jumptable 2 MOV r0 , r 1 0 ; move t h e SWI number t o r 0 3 B e v e n t s S W I H a n d l e r ; b r a n c h t o SWI h a n d l e r 1 2 3 4 5 6 7 8 9 10 v o i d e v e n t s S W I H a n d l e r ( i n t swi_number , SwiRegs ∗ r ) { i f ( swi_number==SLOS ) { i f ( r−>r [0]== E v e n t _ I O D e v i c e I n i t ) { /∗ do n o t e n a b l e IRQ i n t e r r u p t s . . . . ∗/ io_initialize_drivers (); } else Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 14 / 30 Obsługa SWI III 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 { /∗ i f n o t i n i t i a l i z i n g ch an g e t o s y s t e m mode and e n a b l e IRQs ∗/ i f (STATE!=1) { m o d i f y C o n t r o l C P S R (SYSTEM | IRQoN ) ; } s w i t c h ( r−>r [ 0 ] ) { c a s e /∗ SWI ∗/ Event_IODeviceOpen : r−>r [ 0 ] = ( unsigned i n t ) io_open_driver ( /∗ i n t ∗ ID ∗/ ( UID ∗ ) r−>r [ 1 ] , /∗ u n s i g n e d m a j o r _ d e v i c e ∗/ r−>r [ 2 ] , /∗ u n s i g n e d m i n o r _ d e v i c e ∗/ r−>r [ 3 ] ); break ; Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 15 / 30 Obsługa SWI IV 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 c a s e /∗ /∗ c a l l break ; c a s e /∗ /∗ c a l l break ; c a s e /∗ /∗ c a l l break ; c a s e /∗ /∗ c a l l break ; c a s e /∗ /∗ c a l l break ; Mariusz Naumowicz SWI ∗/ E v e n t _ I O D e v i c e C l o s e : i o _ o p e n _ d r i v e r ∗/ SWI ∗/ E v e n t _ I O D e v i c e W r i t e B y t e : i o _ w r i t e b y t e _ d r i v e r ∗/ SWI ∗/ E v e n t _ I O D e v i c e R e a d B y t e : i o _ r e a d b y t e _ d r i v e r ∗/ SWI ∗/ E v e n t _ I O D e v i c e W r i t e B i t : i o _ w r i t e b i t _ d r i v e r ∗/ SWI ∗/ E v e n t _ I O D e v i c e R e a d B i t : i o _ r e a d b i t _ d r i v e r ∗/ Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 16 / 30 Obsługa SWI V 41 42 43 44 45 46 47 48 49 50 51 52 53 c a s e /∗ SWI ∗/ E v e n t _ I O D e v i c e W r i t e B l o c k : /∗ c a l l i o _ w r i t e b l o c k _ d r i v e r ∗/ break ; c a s e /∗ SWI ∗/ E v e n t _ I O D e v i c e R e a d B l o c k : /∗ c a l l i o _ r e a d b l o c k _ d r i v e r ∗/ break ; } /∗ i f n o t i n i t i a l i z i n g ch an g e back t o s v c mode and d i s a b l e IRQs ∗/ i f (STATE!=1) { m o d i f y C o n t r o l C P S R (SVC | IRQoFF ) ; } } } } Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 17 / 30 Obsługa IRQ I 1 2 3 4 5 6 7 8 9 10 11 12 TICKINT EQU 0 x400 BUTTONINT EQU 0 x001 eventsIRQHandler SUB r14 , r14 , #4 ; r 1 4 _ i r q −=4 STMFD r 1 3 ! , { r0−r3 , r12 , r 1 4 } ; s a v e c o n t e x t LDR r0 , INTPND ; r 0=i n t p e n d i n g r e g LDR r0 , [ r 0 ] ; r 0=memory [ r 0 ] TST r0 ,#TICKINT ; i f t i c k i n t BNE e v e n t s T i c k V e n e e r ; t h e n t i c k ISR TST r0 ,#BUTTONINT ; i f b u t t o n i n t e r r u p t BNE e v e n t s B u t t o n V e n e e r ; t h e n b u t t o n ISR LDMFD r 1 3 ! , { r0−r3 , r12 , pc }^ ; r e t u r n t o t a s k Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 18 / 30 Obsługa IRQ II 1 eventsTickVeneer 2 BL e v e n t s T i c k S e r v i c e ; r e s e t t i c k h a r d w a r e 3 B k e r n e l S c h e d u l e r ; branch to s c h e d u l e r Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 19 / 30 Planista I 1 2 3 4 5 6 7 8 t a s k t =0, t ’ ; scheduler () { t ’ = t + 1; i f t ’ = MAX_NUMBER_OF_TASKS t h e n t ’ = 0 // t h e f i r s t t a s k . end ; ContextSwitch ( t , t ’ ) Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 20 / 30 Przełączanie zadań I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 MaxNumTasks EQU 3 F i r s t T a s k EQU 0 CurrentTask LDR r3 ,= PCB_CurrentTask ; [ 1 ] r 3=PCB_CurrentTask LDR r0 , [ r 3 ] ; r 0= c u r r e n t Task ID LDR r1 ,=PCB_Table ; [ 2 ] r 1=PCB_Table a d d r e s s LDR r1 , [ r1 , r0 , LSL#2] ; r 1=mem32 [ r 1+r 0 << 2 ] LDR r2 ,= PCB_PtrCurrentTask ; [ 3 ] r 2=PCB_PtrCurrentTask STR r1 , [ r 2 ] ; mem32 [ r 2 ]= r 1 : t a s k a d d r ; ∗∗ PCB_PtrCurrentTask − u p d a t e d w i t h t h e a d d r o f t h e c u r r e n t t a s k ; ∗∗ r 2 = PCB_PtrCurrentTask a d d r e s s ; ∗∗ r 1 = c u r r e n t t a s k PCB a d d r e s s ; ∗∗ r 0 = c u r r e n t t a s k ID NextTask ADD r0 , r0 ,#1 ; [ 4 ] r 0 = ( C u r r e n t T a s k I D )+1 Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 21 / 30 Przełączanie zadań II 16 17 18 19 20 21 22 CMP r0 ,#MaxNumTasks ; i f r 0==MaxNumTasks MOVEQ r0 ,# F i r s t T a s k ; t h e n r 0 = F i r s t T a s k ( 0 ) STR r0 , [ r 3 ] ; [ 5 ] mem32 [ r 3 ]= n e x t Task ID LDR r1 ,=PCB_Table ; [ 6 ] r 1=PCB_Table a d d r LDR r1 , [ r1 , r0 , LSL#2] ; r 1=memory [ r 1+r 0 << 2 ] LDR r0 ,= PCB_PtrNextTask ; [ 7 ] r 0=PCB_PtrNextTask STR r1 , [ r 0 ] ; memory [ r 0 ]= n e x t t a s k a d d r Rezultaty uruchomienia powyższego kodu: I PCB_PtrCurrentTask wskazuje na adres aktualnie aktywnego PCB. I PCB_PtrNextTask wskazuje na adres następnego aktywnego PCB. I PCB_CurrentTask przechowuje wartość identyfikatora następnego zadania. Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 22 / 30 Przełączanie kontekstu I 1 2 3 4 5 6 7 8 9 O f f s e t 1 5 R e g s EQU 15∗4 handler_contextswitch LDMFD r 1 3 ! , { r0−r3 , r12 , r 1 4 } ; [ 1 . 1 ] r e s t o r e r e g i s t e r s LDR r13 ,= PCB_PtrCurrentTask ; [ 1 . 2 ] LDR r13 , [ r 1 3 ] ; r 1 3=mem32 [ r 1 3 ] SUB r13 , r13 ,# O f f s e t 1 5 R e g s ; r13 −=15∗Reg : p l a c e r 1 3 STMIA r13 , { r0−r 1 4 }^ ; [ 1 . 3 ] s a v e u s e r mode r e g i s t e r s MRS r0 , s p s r ; copy s p s r STMDB r13 , { r0 , r 1 4 } ; s a v e r 0 ( s p s r ) & r 1 4 ( l r ) Rezultaty zapisu aktualnego kontekstu jest: I Stos IRQ jest resetowany i zapisany do PCB_IRQStack. I Rejestr użytkownika dla zadania t jest zapisany do aktualnego PCB. Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 23 / 30 Wczytywanie kontekstu I 1 2 3 4 5 6 7 8 9 LDR r13 ,= PCB_PtrNextTask ; [ 2 . 1 ] r 1 3=PCB_PtrNextTask LDR r13 , [ r 1 3 ] ; r 1 3=mem32 [ r 1 3 ] : n e x t PCB SUB r13 , r13 ,# O f f s e t 1 5 R e g s ; r13 −=15∗ R e g i s t e r s LDMDB r13 , { r0 , r 1 4 } ; [ 2 . 2 ] l o a d r 0 & r 1 4 MSR s p s r _ c x s f , r 0 ; s p s r = r 0 LDMIA r13 , { r0−r 1 4 }^ ; l o a d r 0 _ u s e r −r 1 4 _ u s e r LDR r13 ,=PCB_IRQStack ; [ 2 . 3 ] r 1 3=IRQ s t a c k a d d r LDR r13 , [ r 1 3 ] ; r 1 3=mem32 [ r 1 3 ] : r e s e t IRQ MOVS pc , r 1 4 ; [ 2 . 4 ] r e t u r n t o n e x t t a s k Rezultaty uruchomienia powyższego kodu: I Przełączanie kontekstu jest wykonane. I Rejestry kolejnego zadania są wczytywane do rejestrów w trybie użytkownika. I Stos IRQ jest przywrócony do stanu wejścia w obsługę przerwania. Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 24 / 30 Device Driver Framework I 1 2 3 4 5 6 7 8 9 10 11 12 13 14 d e v i c e _ t r e e s t r ∗ host ; UID s e r i a l ; h o s t = e v e n t I O D e v i c e O p e n (& s e r i a l , DEVICE_SERIAL_E7T ,COM1 ) ; i f ( h o s t ==0) { /∗ . . . e r r o r d e v i c e d r i v e r n o t f o u n d . . . ∗ / } switch ( s e r i a l ) { c a s e DEVICE_IN_USE : c a s e DEVICE_UNKNOWN: /∗ . . . p r o b l e m w i t h d e v i c e . . . ∗/ } Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 25 / 30 Device Driver Framework II 1 PRE r 0 = Event_IODeviceOpen ( u n s i g n e d i n t ) 2 r 1 = & s e r i a l ( UID ∗u ) 3 r 2 = DEVICE_SERIAL_E7T ( u n s i g n e d i n t m a j o r ) 4 r 3 = COM1 ( u n s i g n e d i n t m i n o r ) 5 SWI 5075 6 POST r 1 = The d a t a p o i n t e d t o by t h e UID p o i n t e r i s u p d a t e d Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 26 / 30 Przełączanie kontekstu I Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 27 / 30 Podsumowanie I Podstawowe komponenty występujące systemach operacyjnych uruchamianych na procesorach ARM są następujące: I Inicjalizacja ustawiająca wszystkie wewnętrzne zmienne, struktury danych oraz urządzenia używane przez system operacyjny. I Obsługa pamięci organizuje przestrzeń dla kernela oraz innych wykonywanych aplikacji. I Wszystkie przerwania i wyjątki wymagają funkcji obsługujących je. Nieużywane przerwania i wyjątki muszą posiadać zainstalowane pozorowane funkcje obsługujące. I Zegar okresowy jest wymagana w systemach przełączających zadania. Zegar produkuje przerwanie wywołujące funkcje planisty. I Planista jest algorytmem, który określa nowe zadania mające być uruchomione. I Przełączanie kontekstu zapisuje stan aktualnego zadania i wczytuje stan następnego zadania. Powyższe komponenty są przykładowo zrealizowane w Simple Little Operating System(SLOS): Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 28 / 30 Podsumowanie II I Initialization-Inicjalizacja ustawoa wszystkie funkcje systemu SLOS, włączając w to tryby pracy stosu, proces kontroli bloków (PCB) dla każdej aplikacji, sterowniki, itd. I Memory model- Jądro SLOS jest umieszczone w niskiej pamięci, każda aplikacja ma swoją własną przestrzeń pamięci oraz stos. Rejestry systemowe mikrokontrolera są umieszczone daleko od pamięci ROM i RAM. I Interrupts and exceptions-SLOS korzysta tylko z trzech zdarzeń. Tymi zdarzeniami są Reset, SWI i IRQ. Pozostałej nieużywane przerwania i wyjątki mają zainstalowane prowizoryczne funkcje obsługi. I Scheduler-SLOS implenentuje prosty algorytm round-robin w planiście. I Context switch-Aktulany kontekst jest zapisywane w PCB, następnie kontekst następnego zadania jest odczytywany z PCB. I Device driver framework-Ochrania system operacyjny przed bezpośrednim dostęp z aplikacji do sprzętu. Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 29 / 30 References Andrew Sloss, Dominic Symes, and Chris Wright. ARM System Developer’s Guide: Designing and Optimizing System Software. Morgan Kaufmann Publishers Inc., San Francisco, CA, USA, 2004. Mariusz Naumowicz Programowanie mikroprocesorów jednoukładowych 13 grudnia 2016 30 / 30