- מחיקת משימה ב- FreeRTOS Arduino
- מהו התור ב- FreeRTOS?
- יצירת תור ב- FreeRTOS
- תרשים מעגל
- הטמעת תור FreeRTOS ב- Arduino IDE
במדריך הקודם הצגנו את FreeRTOS ב- Arduino Uno ויצרנו משימה עבור ה- LED המהבהב. כעת, במדריך זה, נצלול יותר למושגים מראש של ממשקי API של RTOS ונלמד על תקשורת בין משימות שונות. כאן אנו לומדים גם על תור להעברת נתונים ממשימה אחת לאחרת ולהדגים את פעולתם של ממשקי API לתור על ידי ממשק 16x2 LCD ו- LDR עם ה- Arduino Uno.
לפני שנדון אודות תורים, בואו נראה עוד ממשק API אחד FreeRTOS שעוזר למחוק את המשימות כשתסיים עם העבודה שהוקצתה. לפעמים צריך למחוק את המשימה כדי לפנות את הזיכרון המוקצב. בהמשך להדרכה הקודמת, נשתמש בפונקציית ה- API של vTaskDelete () באותו קוד למחיקת אחת המשימות. משימה יכולה להשתמש בפונקציית ה- API של vTaskDelete () כדי למחוק את עצמה, או כל משימה אחרת.
כדי להשתמש ב- API זה, עליך להגדיר את התצורה של הקובץ FreeRTOSConfig.h . קובץ זה משמש להתאמת FreeRTOS בהתאם ליישום. הוא משמש לשינוי אלגוריתמי התזמון ופרמטרים רבים אחרים. ניתן למצוא את הקובץ בספריית Arduino, הזמינה בדרך כלל בתיקיית המסמכים במחשב האישי שלך. במקרה שלי, הוא זמין ב \ Documents \ Arduino \ ספריות \ FreeRTOS \ src כפי שמוצג להלן.
עכשיו, פתח את הקובץ הזה באמצעות כל עורך טקסט וחפש את #define INCLUDE_vTaskDelete וודא שהערך שלו הוא '1' (1 פירושו הפעלה ו- 0 פירושו מושבת). זה כברירת מחדל 1 אך בודק אותו.
אנו נשתמש בקובץ תצורה זה לעיתים קרובות בהדרכות הבאות שלנו להגדרת הפרמטרים.
עכשיו, בואו נראה כיצד למחוק משימה.
מחיקת משימה ב- FreeRTOS Arduino
כדי למחוק משימה, עלינו להשתמש בפונקציה API של vTaskDelete (). צריך רק ויכוח אחד.
vTaskDelete (TaskHandle_t pxTaskToDelete);
pxTaskToDelete: זוהי הידית של המשימה שיש למחוק. זה אותו הדבר כמו 6 th הטיעון של xTaskCreate () API. במדריך הקודם, טיעון זה מוגדר כ- NULL אך ניתן להעביר את כתובת תוכן המשימה באמצעות כל שם. נניח אם ברצונך להגדיר את משימת המשימות עבור Task2 המוכרז כ-
TaskHandle_t any_name; דוגמה: TaskHandle_t xTask2Handle;
עכשיו, ב vTaskCreate () API להגדיר 6 th הטיעון כפי
xTaskCreate (TaskBlink2, "task2", 128, NULL, 1, & xTask2Handle);
כעת ניתן לגשת לתוכן של משימה זו באמצעות הידית שניתנה על ידך.
כמו כן, משימה יכולה למחוק את עצמה על ידי העברת NULL במקום ידית משימות תקפה.
אם אנו רוצים למחוק את משימה 3 ממשימה 3 עצמה, עליכם לכתוב vTaskDelete (NULL); בתוך פונקציית Task3 אך אם ברצונך למחוק את משימה 3 ממשימה 2, כתוב vTaskDelete (xTask3Handle); בתוך פונקציית task2.
בקוד הדרכה הקודם, כדי למחוק את Task2 מ- task2 עצמו, פשוט הוסף vTaskDelete (NULL); ב ומבוטל TaskBlink2 (pvParameters * void) פונקציה. ואז הפונקציה הנ"ל תיראה כך
בטל TaskBlink2 (בטל * pvParameters) { Serial.println ("משימה 2 פועלת ועומדת למחוק"); vTaskDelete (NULL); pinMode (7, OUTPUT); בעוד (1) { digitalWrite (7, HIGH); vTaskDelay (300 / portTICK_PERIOD_MS); digitalWrite (7, LOW); vTaskDelay (300 / portTICK_PERIOD_MS); } }
כעת העלה את הקוד וראה את נוריות ה- LED והצג הסידורי. תראה שהנורית השנייה לא מהבהבת כעת ו- task2 נמחק לאחר שנתקל ב- API למחיקה.
אז ניתן להשתמש ב- API זה כדי לעצור את ביצוע המשימה הספציפית.
עכשיו, נתחיל בתור.
מהו התור ב- FreeRTOS?
תור הוא מבנה הנתונים שיכול להכיל את המספר הסופי של אלמנטים בגודל קבוע והוא מופעל בתכנית FIFO (First-in First-out). תורים מספקים מנגנון תקשורת משימה למשימה, משימה להפריע ומשימה להפריע למשימה.
המספר המרבי של אלמנטים שיכולים להחזיק בתור נקרא "אורכו". האורך והגודל של כל אלמנט מוגדרים בעת יצירת התור.
דוגמה לאופן השימוש בתור להעברת נתונים מתוארת היטב בתיעוד FreeRTOS שנמצא כאן. אתה יכול להבין בקלות את הדוגמה הנתונה.
</s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s>לאחר הבנת התורים, בואו ננסה להבין את תהליך יצירת התור וננסה ליישם אותו בקוד FreeRTOS שלנו.
יצירת תור ב- FreeRTOS
ראשית, תאר את הצהרת הבעיה שאמורה להיות מיושמת בעזרת התור FreeRTOS ו- Arduino Uno.
אנו רוצים להדפיס את הערך של חיישן LDR על גבי 16 * 2 LCD. אז יש שתי משימות עכשיו
- משימה 1 מקבל ערכים אנלוגיים של LDR.
- Task2 מדפיס את הערך האנלוגי על גבי LCD.
אז, כאן התור ממלא את תפקידו כי לשלוח את הנתונים שנוצרו על ידי task1 ל- task2. ב- task1 נשלח ערך אנלוגי לתור וב- task2 נקבל אותו מהתור.
ישנן שלוש פונקציות לעבודה עם תורים
- יצירת תור
- שליחת נתונים לתור
- קבלת נתונים מתור
ליצירת תור, השתמש ב- API של פונקציית xQueueCreate (). נדרשים שני ויכוחים.
xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
uxQueueLength: המספר המרבי של פריטים שהתור שנוצר יכול להחזיק בכל פעם.
uxItemSize: הגודל בבייטים של כל פריט נתונים שניתן לאחסן בתור.
אם פונקציה זו מחזירה NULL התור לא נוצר בגלל זיכרון לא מספיק ואם היא מחזירה ערך שאינו NULL, התור נוצר בהצלחה. אחסן את ערך ההחזרה הזה למשתנה כדי להשתמש בו כידית לגישה לתור כמוצג להלן.
QueueHandle_t queue1; תור 1 = xQueueCreate (4, sizeof (int));
זה ייצור תור של 4 אלמנטים בזיכרון הערמה בגודל int (2 בתים מכל בלוק) ויאחסן את ערך ההחזרה למשתנה הידית של התור 1 .
2. שליחת נתונים לתור ב- FreeRTOS
כדי לשלוח את הערכים לתור, ל- FreeRTOS יש 2 גרסאות API למטרה זו.
- xQueueSendToBack (): משמש לשליחת נתונים בחלק האחורי (הזנב) של התור.
- xQueueSendToFront (): משמש לשליחת נתונים לחזית (הראש) של התור.
כעת , xQueueSend () שווה ערך, וזהה ל- xQueueSendToBack ().
כל ממשקי ה- API הללו לוקחים 3 ארגומנטים.
xQueueSendToBack (QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
xQueue: ידית התור שאליה נשלחים הנתונים (נכתבים). משתנה זה זהה לזה שמשמש לאחסון ערך ההחזר של ה- API של xQueueCreate.
pvItemToQueue: מצביע לנתונים שיועתקו לתור.
xTicksToWait: משך הזמן המקסימלי שהמשימה צריכה להישאר במצב חסום כדי לחכות למרחב שיהיה זמין בתור.
הגדרת xTicksToWait כדי portMAX_DELAY תגרום משימה לחכות לזמן בלתי מוגבל (ללא שתיסגר), ובלבד INCLUDE_vTaskSuspend מוגדר 1 ב FreeRTOSConfig.h אחר שאתה יכול להשתמש במאקרו pdMS_TO_TICKS () כדי להמיר זמן מוגדר באלפיות השנייה לתוך פרק זמן מוגדר ב קרציות.
3. קבלת נתונים מתור ב- FreeRTOS
כדי לקבל (לקרוא) פריט מתור, נעשה שימוש ב- xQueueReceive (). הפריט שמתקבל מוסר מהתור.
ממשק API זה לוקח שלושה ארגומנטים.
xQueueReceive (QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait);
טיעונים ראשונים ושלישים זהים למשלוח API. רק הטיעון השני שונה.
const pvBuffer: מצביע לזיכרון אליו יועתקו הנתונים שהתקבלו.
מקווה שהבנת את שלושת ה- APIs. כעת ניישם את ממשקי ה- API הללו ב- Arduino IDE וננסה לפתור את הצהרת הבעיה שתיארנו לעיל.
תרשים מעגל
כך זה נראה על קרש הלחם:
הטמעת תור FreeRTOS ב- Arduino IDE
נתחיל לכתוב קוד ליישום שלנו.
1. ראשית, פתח את Arduino IDE וכלל את קובץ הכותרת Arduino_FreeRTOS.h . כעת, אם נעשה שימוש באובייקט גרעין כלשהו כמו תור, כלול את קובץ הכותרת שלו. כאשר אנו משתמשים ב- LCD * 16 * 2, כלול גם את הספרייה עבורו.
# כלול # כלול
2. אתחל ידית תור לאחסון תוכן התור. כמו כן, אתחל מספרי סיכות LCD.
QueueHandle_t que_1; LiquidCrystal lcd (7, 8, 9, 10, 11, 12);
3. בהתקנת החלל (), אתחל את צג ה- LCD והצג הטורי עם קצב שידור 9600 צור תור ושתי משימות באמצעות ממשקי ה- API המתאימים. כאן ניצור תור בגודל 4 עם סוג שלם. צור משימה עם סדרי עדיפויות שווים ובהמשך נסה לשחק עם המספר הזה. לבסוף, התחל את מתזמן כפי שמוצג להלן.
הגדרת חלל () { Serial.begin (9600); lcd.begin (16, 2); תור_1 = xQueueCreate (4, sizeof (int)); אם (queue_1 == NULL) { Serial.println ("לא ניתן ליצור תור"); } xTaskCreate (TaskDisplay, "Display_task", 128, NULL, 1, NULL); xTaskCreate (TaskLDR, "LDR_task", 128, NULL, 1, NULL); vTaskStartScheduler (); }
4. כעת, בצע שתי פונקציות TaskDisplay ו- TaskLDR . בשנת TaskLDR פונקציה, לקרוא אנלוגי סיכת A0 במשתנה כפי שכבר LDR מחובר פיני A0 של UNO Arduino. כעת שלח את הערך המאוחסן במשתנה על ידי העברתו ב- API של xQueueSend ושלח את המשימה לחסימת מצב לאחר שנייה אחת באמצעות ממשק ה- API של vTaskDelay () כמוצג להלן.
void TaskLDR (void * pvParameters) { int current_intensity; ואילו (1) { Serial.println ("משימה 1"); current_intensity = analogRead (A0); Serial.println (הנוכחי_אינטנסיביות); xQueueSend (queue_1, & current_intensity, portMAX_DELAY); vTaskDelay (1000 / portTICK_PERIOD_MS); } }
5. באופן דומה, בצע פונקציה עבור TaskDisplay וקבל את הערכים במשתנה המועבר לפונקציה xQueueReceive . כמו כן, xQueueReceive () מחזירה את pdPASS אם ניתן לקבל את הנתונים בהצלחה מהתור ומחזירה errQUEUE_EMPTY אם התור ריק.
כעת, הציגו את הערכים על גבי LCD בעזרת הפונקציה lcd.print () .
בטל TaskDisplay (חלל * pvParameters) { אינטנסיביות int = 0; ואילו (1) { Serial.println ("משימה 2"); אם (xQueueReceive (תור_1, ועוצמה, portMAX_DELAY) == pdPASS) { lcd.clear (); lcd.setCursor (0, 0); lcd.print ("עוצמה:"); lcd.setCursor (11, 0); lcd.print (עוצמה); } } }
זהו זה. סיימנו את חלק הקידוד של הטמעת התור. קוד מלא עם סרטון עובד ניתן למצוא בסוף.
כעת חבר את ה- LCD ל- LDR עם Arduino UNO על פי תרשים המעגל העלה את הקוד. פתח את המסך הסדרתי והתבונן במטלות. תראה משימות מתחלפות וערכי LDR משתנים בהתאם לעוצמת האור.
הערה: מרבית הספריות המיועדות לחיישנים שונים אינן נתמכות על ידי ליבת FreeRTOS עקב עיכוב בהטמעת פונקציות בתוך הספריות. עיכוב גורם למעבד להפסיק לחלוטין, ולכן גם ליבת FreeRTOS מפסיקה לעבוד והקוד לא יופעל עוד יותר והוא מתחיל להתנהג בצורה לא נכונה. אז עלינו להפוך את הספריות ללא עיכוב לעבוד עם FreeRTOS.