pC/OS



Zu den für Anfänger am schnellsten zu verstehenden Echtzeitbetriebssystemen gehört µC/OS von Jean J. Labrosse. Es kann bis zu 63 Applikationstasks mit je unterschiedlichen Prioritäten verwalten und gehört zu den Echtzeitbetriebssystemen mit dem geringsten Speicherbedarf.
Da die Originalversion aus dem Embedded Systems Programming Magazine(1992) FREI ist, habe ich diesen für Interressierte zum Download hinterlegt.

Da die Firma Micrium Ihre Source-Code Distribution Lizenz-Bedingungen auch für die Originalversion aus dem Embedded Systems Programming Magazine(1992) geändert hat, kann ich hier nur noch einen Link zur Download-Seite des Magazins stellen.

Embedded Systems Programming Magazine(1992) - code area




Da in der Originalversion Daten durch direkte Übergabe von Zeigern zwischen den Tasks ausgetauscht werden, und somit keine Garantie für die freie Verwendbarkeit des Absender-buffers nach Übergabe an einen anderen Task besteht und, viel wichtiger, der Empfänger einen Zeiger in das Datenfeld eines anderen Tasks erhält (Pointer-Fehler / Längen-Fehler / Manipulationen u.a.) habe ich die Mechanismen für Message-Box und Queue entsprechend so geändert, daß nun die Daten über einen Kernel-internen Buffer an den Empfänger übergeben werden. Das bedeutet, daß der Kernel zu übertragende Daten in einen eigenen Buffer kopiert und bei Übergabe an den Empfänger diese auch wieder selber in den durch den Empfänger bereitgestellten Buffer kopiert. Das bringt zwar einen höheren Speicherbedarf je Queue mit sich, sichert aber dafür die Prozesse weitestgehend (für Real-Mode) voneinander ab. Aus Sicherheitsgründen wurden außerdem Kernel-Konstanten in den CODE-Area verlegt. Desweiteren habe ich den Kernel um die Diente Pipe, Eventgroup und dyn. Memorymanagement erweitert.
Um diese Änderungen eindeutig zu deklarieren habe ich den Namen, angelehnt an dem immer größer werdenden Original "µC/OS", auf pC/OS wie "pico-C.." geändert.


Special zu:  Priority Inversion, das Problem und die Lösungsansätze


Um endgültig den Status des pC/OS Kernel basierend auf dem µC/OS 1.00 klarzustellen,
habe ich die alte "V1.00 is FREE" Bestätigungs-email von Jean Labrosse herausgesucht.



pCOS_187b.zip
download pC/OS 1.87b (as ZIP)


Releases:

1.00aMessagebox und Queue geändert sowie Pipe, Eventgroup und dyn. Memorymanagement hinzugefügt.
* Port für Am188ES erstellt
1.00bRevision-Info, Tick-counter, Task-Suspension, Task-Delete, History-Table und OS_QueueFrontPost hinzugefügt (Task-Suspension und Task-Delete aus 1.09 importiert).
Einige BugFixes aus 1.01 bis 1.09 übernommen.
1.00cBeschleunigung der Pipe (bei Taskwechsel auf Grund der Datenübergabe und wenn Pipe leer ist werden die Daten vom Sender-buffer direkt in den Empfänger-buffer kopiert).
Vorab-Implementation einer Wartezeit für Sender (OS_.....Post).
Nicht-warten für Sender und Empfänger mittels OS_NO_SUSP implementiert.
Anlegen von Queue und Pipe (speziell: Zeiger auf Kernel-buffer) überarbeitet.
1.00dkorrekte Implemenierung "timeout" in OS_...Post-Funktionen und OS_QueueClear hinzugefügt.
1.00eAnpassung der Task-Initialisierung und einiger Parameter zur Nutzung der µC/OS-I Port's.
OS_QueueInfo und OS_PipeInfo hinzugefügt.
1.00fBugfix innerhalb der Event-Gruppen.
OS_SemAccept hinzugefügt.
1.00gDual-Source für MSC-8.00 und Keil-C51 generiert. OS_CFG implementiert. Bugfix in Semaphoren.
* Port für 8051 hinzugefügt
1.00hMUTEXes hinzugefügt, Eventgruppen richtig implementiert und Code-cleanup. Cleanup der Ports.
* Port für Rabbit 2000/3000 hinzugefügt
* Port für Philips-XA hinzugefügt
1.40aName auf pC/OS geändert und Revisionsnummer überarbeitet, einige C-fixes.
* Port für ATMega128 hinzugefügt
* Port für AT91SAM7Sxx hinzugefügt
1.41aImplementation von OS_STK_TYPE für Prozessor-konformen Stack incl. Update aller bisherigen Ports.
Keil-Variante des AT91SAM7Sxx-Ports (instabil) hinzugefügt
1.50cKomplettes Update zu U08..U32 Typen.
Implementation von OS_PACKED, OS_PACKED_ATTR und align(x)-Korrekturen.
Kleine Korrektur in OS_TaskSuspend().
* Port für LPC214x hinzugefügt
* Port für LPC236x hinzugefügt
* Port für STR71x hinzugefügt
1.52bSplit MIN_PRIO und MAX_TASKS um RAM in der Task-Verwaltung bei wenige Tasks einzusparen. Verwendung "NULL" als pointer. Eindeutige Task-ID hinzugefügt, um anderen Modulen eine eindeutige Identifizierung des Tasks zu ermöglichen (siehe ChangePrio und Mutex) und damit auch dort RAM zu sparen.
* Port für Cortex-M3 Luminary LM3S811 hinzugefügt
1.60ctemporären reg-holder hinzugefügt um bei Ab- und Anschalten der Interrupte innerhalb einer ISR gegen "neested interrupts" geschützt zu sein, wenn dies unerwünscht ist
* Port für Cortex-M3 STM32 hinzugefügt
1.61ader Memory-Manager arbeitet nun immer MPU-spezifisch aligned
1.65bTimer-Service implementiert, dessen Timer periodisch oder run-once laufen können.
Einige neue API-Funktionen hinzugefügt
1.66ceinige Checks im Timer-Service implementiert, OS_TimerGetState() und OS_TimerGetRemain() hinzugefügt
1.67aMinimierung des RAM-Bedarfs der prio-tables der IPC-Resourcen (SEM/EVG/MUX/Queue/Pipe/..)
* Port für PIC32 hinzugefügt
* Port für MSP430 hinzugefügt
1.68aOS_EvgPendAbbort() hinzugefügt
* Port für AVR32 hinzugefügt
1.70boptionaler Debug Stack-End Check hinzugefügt, Kernel Konfiguration restrukturiert
1.71aoptionaler Stack-Fill zum Debug Stack-End Check hinzugefügt
1.80ceinige Fixes in allen ...Abbort() Funktionen, einige zusätzliche Checks für "mutex in use", OS_TaskGetID() und OS_TaskGetStatus() hinzugefügt, mit der neuen Funktion OS_TaskDestroy() können nun Tasks - wartend an einer IPC - auch gelöscht werden, Source-File splitted für besseres Handling
* Port für ATMega32 hinzugefügt
1.81bdurch eine Erweiterung in der optionalen Funktion OS_TaskDestroy() können nun auch Mutex geschützte Recoursen reinitialisiert werden, die selbst eine User-Verwaltung basierend auf der unique Task-ID beinhalten (wie zB. ein FileSystem)
1.82aOS_TaskDestroy() umbenannt zu OS_TaskIdDestroy(), OS_TaskGetPrio(), OS_TimeDelayIdResume(), OS_TaskIdDelete(), OS_TaskIdGetStatus(), OS_TaskIdSyspend() und OS_TaskIdResume() hinzugefügt plus einige zusätzliche Checks für prio und/oder id
1.83akleiner fix für OS_TaskIdDestroy() in OSIntExit(), wenn der aktuell laufende Task durch eine ISR zerstrört wird
* Port für Cortex-M0 LPC11xx hinzugefügt
* Port für Cortex-M3 LPC13xx hinzugefügt
* Port für Cortex-M3 LPC17xx hinzugefügt
* Port für Cortex-M3 AT91SAM3xxx hinzugefügt
1.83bmini fix in OSTCBInit(..) für fehlenden Compiler-Switch
1.84aÄnderung des Event Parameter in Evengruppen zu Pointer für besseres Handling des OR-modes (mit Event return), kleiner Fix in Pipe für schnellen Daten Prozess-Wechsel
* Port für Cortex-M4 STM32F4xx hinzugefügt
1.85bKorrektur in Evengruppen für mehrere wartenden Tasks an einer gemeinsamen Eventgruppe
1.86aOS_ID_SELF hinzugefügt für OS_TaskIdDelete() und OS_TaskGetPrio()
* Port für Cortex-M0 SAMD21 hinzugefügt
1.87bein Interrupt oder während der sheduler ausgeschalten ist kann ein Sender nicht den fast-mode bei OS_Pipe...Post verwenden, da die Quelle nicht garantiert werden kann.
* Ports für Cortex-M23 und Cortex-M33 (ARMv8M baseline & mainline) hinzugefügt (w/o active TZ support)
* Port für Cortex-M3 TI Luminary LM3S9B92 hinzugefügt
* Port für Cortex-M0 Nuvoton NUC123 hinzugefügt
* Port für Cortex-M0 Freescale MKL25Z128 hinzugefügt
* Port für Cortex-M0 Freescale MKL26Z64 hinzugefügt
* Port für Cortex-M0 Infineon XMC1100 hinzugefügt


Bei Wartezeiten für "OS_...Post" und "OS_...Pend" -Funktionen ist zu Beachten, daß bei einem Aufruf einer Sender-/Empfängerfunktion aus einer ISR heraus NIE mit einer Wartezeit oder sogar Suspendierung gearbeitet werden darf, da dieses die ISR stoppen würde, und somit nichts mehr läuft. Eine Prüfung dieses Zustandes ist integriert worden.

bekannter Bug:
Wenn ein niederpriorisierter Task auf eine Recource wartet, und ein höherpriorisierter Task diese Recource setzt, so wird der schlafende Task in den Ready-state versetzt. Da der höherpriorisierte Task weiterläuft, darf dieser die selbe Recource nicht wieder auslesen, da ansonsten der niederpriorisierte Task bei Ausführung 'vorzeitig' mit dem Return-Code OS_TIMEOUT zurück kommt.



Dienste des pC/OS Version 1.87b (Kurzform)
Die hier aufgeführte Funktionsübersicht dient einzig als Kurzübersicht.
Für detailierte Informationen sehen Sie bitte in Referenz-Manual zu pC/OS nach.


Task-Control:Description
OS_InitInitialisierung des Kernels
OS_StartBeginn der Kernelservices
OS_TaskCreateAnlegen eines Tasks
OS_ChangePrioÄnderung der Priorität des aktiven Tasks
OS_TaskChangePrioÄnderung der Priorität eines aktiven/ready Tasks
OS_TaskDeleteLöschen eines aktiven/ready Tasks
OS_TaskIdDeleteLöschen eines aktiven/ready Tasks via unique ID
OS_TaskGetStatusGibt den aktuellen Status eines Tasks zurück
OS_TaskIdGetStatusGibt den aktuellen Status eines Tasks via unique ID zurück
OS_TaskGetIDGibt die unique ID eines Tasks zurück
OS_TaskGetPrioGibt die Priorität eines Tasks zurück
OS_TaskIdDestroyLöschen eines Tasks via unique ID, auch wenn dieser an einer IPC wartet oder eine Mutex inne hat & freigeben aller Memory Allokationen
OS_TaskSuspendSuspendiert einen Task
OS_TaskIdSuspendSuspendiert einen Task via unique ID
OS_TaskResumeWiederaufwecken eines suspendierten Tasks
OS_TaskIdResumeWiederaufwecken eines suspendierten Tasks via unique ID
OS_TimeDlyLegt laufenden Task für bestimmte Zeit schlafen
OS_TimeDlyResumeWiederaufwecken eines schlafenden Tasks vor Ablauf der eingestellten Zeit
OS_TimeDlyIdResumeWiederaufwecken eines schlafenden Tasks via unique ID vor Ablauf der eingestellten Zeit
OS_LockUnterdrücken des Shedulers (keine Taskwechsel)
OS_UnlockWiederzuschaltung des Shedulers (Taskwechsel bei Ereignis oder Zeit)
OS_GetRevGibt Zeiger auf Kernel-Revision zurück



Dynamic-Memory:Description
OS_MemoryInitErzeugen des Speicherpools
OS_MemAllocAllokieren von Speicher
OS_MemFreeFreigeben von allokiertem Speicher
OS_MemFreeSizeGibt den Freispeicher zurück



Mailboxes:Description
OS_MboxInitAnlegen einer Mailbox
OS_MboxPostSendet Daten an höchstpriorisierten Empfänger dieser Mailbox
OS_MboxPostAbbortBricht Warten eines sendenden Tasks (höchste wartende Prio) an einer Mailbox ab
OS_MboxPendWartet auf Daten aus einer Mailbox
OS_MboxPendAbbortBricht Warten eines empfangenden Tasks (höchste wartende Prio) an einer Mailbox ab



Queues:Description
OS_QueueInitAnlegen einer Queue
OS_QueueInfoInformationen über eine Queue einholen
OS_QueuePostSendet Daten in eine Queue
OS_QueueFrontPostSendet Daten an den Anfang einer Queue
OS_QueuePostAbbortBricht Warten eines sendenden Tasks (höchste wartende Prio) an einer Queue ab
OS_QueuePendWartet auf Daten aus einer Queue
OS_QueuePendAbbortBricht Warten eines empfangenden Tasks (höchste wartende Prio) an einer Queue ab
OS_QueueClearLöscht alle Daten in einer Queue



Pipes:Description
OS_PipeInitAnlegen einer Pipe
OS_PipeInfoInformationen über eine Pipe einholen
OS_PipePostSendet Daten in eine Pipe
OS_PipeFrontPostSendet Daten an den Anfang einer Pipe
OS_PipePostAbbortBricht Warten eines sendenden Tasks (höchste wartende Prio) an einer Pipe ab
OS_PipePendWartet auf Daten aus einer Pipe
OS_PipePendAbbortBricht Warten eines empfangenden Tasks (höchste wartende Prio) an einer Pipe ab
OS_PipeClearLöscht alle Daten in einer Pipe



Semaphores:Description
OS_SemInitAnlegen einer Semaphore
OS_SemAcceptwartet auf Ereignis und gibt Anzahl zurück
OS_SemPostFreigabe einer belegten Semaphore / setzt Ereignis
OS_SemPendBelegt eine Semaphore / wartet auf Ereignis
OS_SemPendAbbortBricht Warten eines Tasks (höchste wartende Prio) an einer Semaphore ab
OS_SemClearLöscht Semaphoren-Counter



Mutexes:Description
OS_MutexCreateAnlegen einer Mutex
OS_MutexPostgibt Mutex wieder frei
OS_MutexPendBesetzt die Mutex
OS_MutexPendAbbortBricht Warten eines Tasks (höchste wartende Prio) an einer Mutex ab



Event-Groups:Description
OS_EvgInitAnlegen einer Eventgruppe
OS_EvgPostSetzt ein/mehrere Events einer Evengruppe
OS_EvgPendWartet auf das Eintreffen eines oder mehrere Events einer Eventgruppe
OS_EvgPendAbbortBricht Warten eines Tasks (höchste wartende Prio) an einer Eventgruppe ab



Timer-Service:Description
OS_TimerCreateAnlegen eines Timers
OS_TimerDeleteLöschen eines angelegten Timers
OS_TimerStart(Re-)Starten eines angelegten Timers
OS_TimerStopStoppen eines angelegten Timers
OS_TimerGetStategibt den Status eines angelegten Timers zurück
OS_TimerGetRemaingibt die verbleibende Zeit eines laufenden Timers zurück



System-Ticks:Description
OS_TimeSetSetzt Ticker auf übergebenen Wert
OS_TimeGetGibt aktuellen Ticker-Wert zurück



Interrupts:Description
OS_IntEnterRegistrierung einer aufgerufenen ISR
OS_IntExitEnde einer aufgerufenen ISR



History:Description
OS_HistoryPostSchreibt Eintrag in History
OS_HistoryReadGibt ersten History-Eintrag und löscht diesen in der Tabelle



Error-Codes:

Name

Decimal_Value

OS_SUCCESS / OS_NO_ERR

0

OS_TIMEOUT

10

OS_MBOX_FULL

20

OS_MBOX_NODATA

21

OS_Q_FULL

30

OS_Q_NODATA

31

OS_Q_CLEAR

32

OS_PRIO_EXIST

40

OS_TASK_NOT_EXIST

41

OS_SEM_ERR

50

OS_SEM_NODATA

51

OS_SEM_OVF

52

OS_MUX_ERR

55

OS_MUX_NOACC

56

OS_MUX_USED

57

OS_P_FULL

60

OS_P_NODATA

61

OS_P_CLEAR

62

OS_P_LEN_ERR

63

OS_MEM_ERR

70

OS_MEM_OVF

71

OS_EVG_ERR

80

OS_EVG_NOE

81

OS_HIS_END

90

OS_SUSPEND_IDLE

100

OS_PRIO_INVALID

101

OS_TIME_NOT_DLY

102

OS_TASK_SUSP_PRIO

103

OS_TASK_NOT_SUSP

104

OS_TASK_NOT_RDY

105

OS_TMR_NO_TIME

106

OS_TMR_NOT_EXIST

107

OS_TMR_EXIST

108




Tip zu ASM-ISR's:

Um Assembler-ISR's im pC/OS manuell zu integrieren, muß bei Einsprung in die ISR folgender Startcode implementiert werden: (Beispiel x86)

EXTRN C OSIntEnter : NEAR EXTRN C OSIntExit : NEAR ... ISR: pusha ; save all used register push es call OSIntEnter ; C-function to register INT-level ...

und am Ende der ISR:

... call OSIntExit ; C-function to unregister INT-Level ; and perform a context-switch is needed pop es ; restore all used register popa iret ; return