מערכות הפעלה בזמן-אמת (RTOS‏) ויישומיהן | DigiKey

מאת ‎Lim Jia Zhi, Senior Embedded Software Engineer

באדיבות ‎DigiKey's North American Editors

מהי מערכת RTOS‏

מערכת הפעלה בזמן-אמת (RTOS) היא מערכת הפעלה קלת-משקל המשמשת להקלת ריבוי-משימות ושילוב-משימות בתכנים מוגבלי משאבים וזמן, שהוא המקרה הרגיל במערכות משובצות. מעבר לכך, המונח "זמן-אמת" מצביע על פרדיקטאביליות/דטרמיניזם בזמן הביצוע ולא על המהירות הגולמית, ולכן ניתן לרוב להוכיח שמערכת RTOS‏ יכולה לעמוד בדרישות זמן-אמת קשות הודות לדטרמיניזם שלה.

עקרונות המפתח של מערכת RTOS‏ הם:

משימות

משימות (יכולות להיקרא גם תהליכים/שרשורים) הן פונקציות עצמאיות הפועלות בחוגים אינסופיים, כאשר בדרך כלל כל אחת מהן אחראית למאפיין אחד. המשימות פועלות באופן בלתי-תלוי בזמן (בידוד בזמן) ובאזור הזיכרון (בידוד במרחב) שלהן. ניתן להבטיח בידוד במרחב בין משימות באמצעות יחידת הגנת זיכרון (MPU) בחומרה, המגבילה את אזור הזיכרון הנגיש ומתניעה חריגות תקלה בעת הפרת גישה. בדרך כלל רכיבים היקפיים פנימיים הם ממופי-זיכרון, כך שניתן להשתמש ב- MPU להגבלת הגישה גם לרכיבים ההיקפיים.

המשימות יכולות להיות במצבים שונים:

  • חסומה - המשימה ממתינה לאירוע (למשל, זמן-קצוב לשיהוי, זמינות נתונים/משאבים)
  • מוכנה - המשימה מוכנה לפעולה במעבד אך עדיין אינה פועלת מכיוון שהמעבד תפוס לביצוע משימה אחרת
  • הרצה - המשימה מוקצית לפעולה במעבד

מתזמנים

המתזמנים במערכת RTOS מבקרים איזו משימה להריץ על המעבד, וקיימים אלגוריתמי תזמון שונים. בדרך כלל הם:

  • מותנים - ביצוע המשימה ניתן לעצירה אם יש משימה מוכנה אחרת שהיא בעדיפות גבוהה יותר
  • בשיתוף - החלפת משימות תתרחש רק אם משימת הריצה הנוכחית מוותרת

תזמון מותנה מאפשר למשימות בעדיפות גבוהה יותר לעצור משימות בעדיפות נמוכה יותר כדי לעמוד באילוצי זמן-אמת, אך המחיר הוא העלות של יותר תקורה במהלך החלפת הקשרים.

תקשורת בין-משימות (ITC‏)

מספר משימות צריכות בדרך כלל לשתף פרטים או אירועים האחת עם השנייה. הדרך הפשוטה ביותר לשתף היא לקרוא/לכתוב ישירות משתנים גלובליים משותפים בזיכרון RAM, אך זה אינו רצוי בשל הסיכון להשחתת נתונים הנגרמת כתוצאה ממצב מרוץ. דרך טובה יותר היא לקרוא/לכתוב משתנים סטטיים בקבצים ייעודיים הנגישים באמצעות פונקציות Setter‏ ו- Getter‏, וניתן למנוע תנאי מרוץ על ידי השבתת פסקים (Interrupts) או שימוש באובייקט הרחקה הדדית (Mutex) בתוך פונקציית Setter/Getter‏. הדרך הנקייה יותר היא להשתמש באובייקטיים מוגני-שרשור של מערכת RTOS כמו תור הודעות כדי להעביר פרטים בין המשימות.

מלבד שיתוף פרטים, אובייקטים של מערכת RTOS‏ מסוגלים גם לסנכרן את ביצוע המשימות, מכיוון שניתן לחסום משימות כדי להמתין לזמינות האובייקטים של ה- RTOS. למרבית מערכת RTOS יש אובייקטים כגון:

  • תור הודעות
    • תור ראשון-נכנס-ראשון-יוצא (FIFO) להעברת נתונים
    • ניתן לשלוח נתונים בהעתקה או בייחוס (פוינטר)
    • משמש לשליחת נתונים בין משימות או בין פסק למשימה
  • סמאפור
    • ניתן לטפל בו כמו מונה ייחוס לרישום זמינות של משאב מסוים
    • יכול להיות סמאפור בינארי או סופר
    • משמש לשמירה על השימוש במשאבים או לסינכרון ביצוע משימות
  • Mutex‏
    • דומה לסמאפור בינארי, ומשמש בדרך כלל לשמירה על שימוש במשאב יחיד (MUTual Exclution‏)
    • ה- FreeRTOS Mutex מגיע עם מנגנון הורשת עדיפות למניעת בעיית היפוך עדיפות (מצב שבו משימה בעדיפות גבוהה נעצרת וממתינה למשימה בעדיפות נמוכה יותר).
  • תיבת דואר
    • מיקום אחסון פשוט לשיתוף משתנה יחיד
    • יכול להיחשב כתור של אלמנט יחיד
  • קבוצת אירועים
    • קבוצת תנאים (זמינות של סמאפור, תור, דגלון אירוע וכו')
    • ניתן לחסום משימה ולחכות למילוי תנאי צירוף ספציפי
    • זמין ב- Zephyr‏ כ- Polling API‏, ב- FreeRTOS כ- QueueSets‏

טיקים (Tick‏) של מערכת

מערכת RTOS זקוקה לבסיס זמן כדי למדוד זמן, בדרך כלל בצורה של משתנה מונה טיקים של המערכת, המתקדם באינקרמנטים של פסקים (Interrupt‏) מחזוריים של קוצב-זמן בחומרה. באמצעות טיק מערכת, יישום יכול להפעיל יותר שירותים מבוססי-זמן (מרווח ביצוע משימות, פסק-זמן המתנה, פילוח זמן) באמצעות קוצב-זמן בחומרה אחד בלבד. עם זאת, קצב טיקים גבוה יותר רק יגדיל את רזולוציית בסיס-הזמן של ה- RTOS אך הוא לא יגרום לתוכנה לפעול מהר יותר.

מדוע להשתמש במערכת RTOS

ארגון

ניתן תמיד לכתוב יישומים ללא מערכת הפעלה (Bare Metal‏), אך ככל שמורכבות הקוד תגדל, עצם קיומו של מבנה כלשהו יעזור בניהול חלקים שונים ביישום תוך שמירה על הפרדה ביניהם. יתר על כן, עם דרך מובנית של פיתוח ושפה תכנון מוכרת, חבר צוות חדש יכול להבין את הקוד ולהתחיל לתרום מהר יותר. חברת RFCOM Technologies‏ פיתחה יישומים המשתמשים במיקרו-בקרים שונים כמו Hercules‏ מבית Texas Instruments‏, RL78‏ ו- RX‏ מבית Renesas‏, ו- STM32‏ מבית STMicroelectronics‏ על מערכות RTOS‏ שונות. דפוסי תכנון דומים מאפשרים לנו לפתח יישומים על מיקרו-בקרים שונים ואפילו על מערכות RTOS‏ שונות.

מודולריות

הפרד ומשול. על ידי הפרדת המאפיינים במשימות השונות, ניתן להוסיף בקלות מאפיינים חדשים מבלי לפגוע במאפיינים אחרים; בתנאי שהמאפיין החדש לא יגרום לעומס-יתר על המשאבים המשותפים כמו המעבד והרכיבים ההיקפיים. פיתוח ללא מערכת RTOS‏ יהיה בדרך כלל בחוג אינסופי שבו כל המאפיינים הם חלק מהחוג. שינוי במאפיין כלשהו בתוך החוג ישפיע על מאפיינים אחרים, ויהיה קשה לשנות את התוכנה ולתחזק אותה.

חבילות פרוטוקולי תקשורת ומנהלי-ההתקנים

חבילות פרוטוקולים ומנהלי-התקנים רבים נוספים כמו TCP/IP‏, USB‏, BLE‏ וספריות גרפיקה מפותחות/מועברות מ-/אל מערכות RTOS‏ קיימות. מפתח יישומים יכול להתמקד בשכבת האפליקציה של התוכנה ולקצר משמעותית את זמן היציאה לשוק.

טיפים

הקצאה סטטית

השימוש בהקצאת זיכרון סטטית עבור אובייקטים של מערכת RTOS פירושו הקצאה בזיכרון RAM עבור כל אובייקט RTOS במהלך הקומפילציה. דוגמה לפונקציה של הקצאה סטטית ב- freeRTOS היא ()xTaskCreateStatic‏. זה מבטיח שאפשר ליצור אובייקט RTOS בהצלחה, ולחסוך את הטרדה של טיפול בהקצאה פגומה אפשרית תוך הפיכת היישום ליותר דטרמיניסטי.

מבחינת ההחלטה על גודל הזיכרון הדרוש עבור משימה, ניתן להפעיל את המשימה עם גודל גדול יותר (יותר ממספיק) ואז ניתן לבדוק את השימוש בזמן הריצה כדי לקבוע את הרף העליון. קיים גם כלי לניתוח הקצאת זיכרון סטטית.

שכבת אבסטרקציה במערכת הפעלה (OSAL‏) ואבסטרקציה בעלת-משמעות

בדיוק כמו שכבת אבסטרקציה בחומרה (HAL‏), השימוש בשכבת אבסטרקציה במערכת RTOS‏ מאפשר לתוכנת האפליקציה לפעול על מערכות RTOS‏ אחרות. המאפיינים של מערכות RTOS‏ הם דומים למדי, כך שיצירת OSAL‏ לא חייבת להיות מסובכת. לדוגמה:

שימוש ב- API של FreeRTOS ישירות:

if( xSemaphoreTake( spiMutex, ( TickType_t ) 10 ) == pdTRUE ) { //dosomething }

הכנסת RTOS API‏ לתוך OSAL‏:

if( osalSemTake( spiMutex, 10 ) == true) { //dosomething }

השימוש בשכבת אבסטרקציה בתקשורת בין-משימות כדי להפוך את הקוד לקריא יותר ולהקטין את ההיקף של אובייקט RTOS:

if( isSpiReadyWithinMs( 10 ) ) { //doSomething }

בנוסף, אבסטרקציה מאפשרת למתכנתים לשנות גם את אובייקט RTOS המשמש להלן (למשל, מ- Mutex לסמאפור סופר) אם קיים יותר ממודול SPI אחד. ה- OSAL ושכבות אבסטרקציה אחרות עוזרות בבדיקות תוכנה גם הודות לפשטות הכנסת פונקציות מדומות במהלך בדיקות יחידות.

בחירת מרווחי טיקים (Tick‏)

באופן אידיאלי, שיעור הטיקים הנמוך יותר הוא טוב יותר בגלל פחות תקורה. כדי לבחור קצב טיקים מתאים, המפתחים יכולים להכין רשימה של מגבלות תזמון של המודולים באפליקציה (המרווחים החוזרים, משך פסקי-הזמן וכו'). אם ישנם כמה מודולים חריגים הזקוקים למרווחים קטנים, ניתן לשקול פסקי קוצב-זמן ייעודיים עבור המודולים החריגים במקום להגדיל את קצב הטיקים של מערכת ה- RTOS כולה. אם פונקציה בתדירות גבוהה היא קצרה מאוד (למשל, כתיבה לאוגר להפעלת/כיבוי נורת LED‏), ניתן לעשות זאת בתוך רוטינת שירות פסק (ISR‏), אחרת ניתן להשתמש בטיפול פסק (Interrupt) דחוי. טיפול פסק דחוי היא טכניקה של דחיית חישוב פסק לתוך משימת RTOS‏, כאשר ה- ISR רק יוצר אירוע דרך אובייקט RTOS‏, ואז משימת ה- RTOS‏ תשוחרר על ידי האירוע ותבצע את החישוב.

שיכוך טיקים לטובת יישומים בהספק נמוך

אופן לא-פעיל ללא-טיקים משבית את הפסקים כאשר המערכת עוברת לאופן לא-פעיל למשך זמן רב יותר. דרך משמעותית אחת עבור קושחה משובצת להפחתת צריכת ההספק היא להעביר את המערכת לאופן הספק נמוך למשך זמן רב ככל האפשר. אופן לא-פעיל ללא-טיקים ממומש על ידי השבתת פסקי הטיקים המחזוריים ואז הגדרת קוצב-זמן מונה-אחורה לפסק כאשר משימה חסומה מוכנה לביצוע. אם אין משימה הממתינה עבור פסק-זמן, ניתן להשבית את פסק הטיקים ללא הגבלת זמן עד שיתרחש פסק נוסף (למשל, לחיצה על כפתור). לדוגמה, במקרה של משואת Bluetooth Low Energy‏ (BLE‏), ניתן להעביר את המיקרו-בקר לאופן שינה עמוקה בין מרווחי הפרסום. כפי שמוצג באיור 1, המשואה מועברת לאופן שינה עמוקה למשך רוב הזמן, תוך צריכת הספק של עשרות µA‏.

גרף צריכת הזרם של משואת BLE‏ (לחצו להגדלה)איור 1‏: צריכת הזרם של משואת BLE‏ (מקור התמונה: RFCOM‏)

סיכום

מערכת הפעלה בזמן-אמת (RTOS‏) מספקת מאפיינים כגון אובייקטי RTOS של מתזמנים, משימות ותקשורת בין-משימות, כמו גם חבילות פרוטוקולי תקשורת ומנהלי-ההתקנים. היא מאפשרת למפתחים להתמקד בשכבת האפליקציה של התוכנה המשובצת, ולתכנן תוכנות ריבוי-משימות בקלות ובמהירות. עם זאת, כמו עם כל הכלים האחרים, יש להשתמש בה כראוי על מנת להפיק ערך רב יותר. כדי ליצור תוכנה משובצת בטוחה, מאובטחת ויעילה, על המפתחים לדעת מתי להשתמש במאפייני ה- RTOS וכיצד להגדיר את תצורת ה- RTOS.

DigiKey logo

מיאון אחריות: דעות, אמונות ונקודות מבט המובעות על ידי מחברים שונים ו/או משתתפי פורום באתר אינטרנט זה לא בהכרח משקפות את הדעות, האמונות ונקודות המבט של חברת DigiKey או את המדיניות הרשמית של חברת DigiKey.

אודות כותב זה

Image of Lim Jia Zhi

Lim Jia Zhi, Senior Embedded Software Engineer

Lim Jia Zhi is an embedded software engineer, holds a degree in Electrical and Electronics Engineering. He has developed software for devices in IoT solution covering edge gateway and battery-powered edge devices, and also involved in developing safety-critical embedded software. Actively learning ways to design efficient and reliable embedded system, like using design pattern and tools, and having software development lifecycle. (jia.zhi.lim@rfcom-tech.com (+65) 6635 4217)

אודות מוציא לאור זה

DigiKey's North American Editors