HiTakeJobHiTakeJob

מה זה Embedded? הסבר פשוט + כמה משרות פתוחות בישראל

זמן קריאה: 8 דקות

Embedded, בעברית מערכות משובצות, הוא פיתוח תוכנה שרצה בתוך מכשיר ולא על מחשב כללי: בקר של מכונת כביסה, מדחום רפואי, בקר מנוע ברכב או נתב. התוכנה כתובה לחומרה מסוימת ומוגבלת על ידה. בלוח HiTakeJob פתוחות כרגע 21 משרות שמזכירות Embedded C, ו-12 משרות נושאות embedded בכותרת.

מה מבדיל Embedded מפיתוח רגיל

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

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

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

שלוש רמות: bare-metal, RTOS ולינוקס משובץ

הבחירה בין שלוש הרמות היא ההחלטה הארכיטקטונית הראשונה בכל פרויקט, והיא נגזרת מהחומרה ומדרישות הזמן.

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

הבחירה בלינוקס משובץ מזיזה את סט הכישורים הנדרש: Yocto או Buildroot לבניית ההפצה, device tree לתיאור החומרה, וכתיבת דרייברים בגרעין. זו הסיבה ש-91 המשרות שמזכירות Linux בלוח רלוונטיות גם למי שמחפש תפקיד משובץ ולא רק למי שמחפש תשתיות שרת.

פסיקות ומה מותר בתוך ISR

פסיקה היא אות מהחומרה שמפסיק מיד את הקוד הרץ ומקפיץ את המעבד לפונקציית טיפול. זה המנגנון שמאפשר למכשיר להגיב תוך מיקרושניות בלי לבזבז מעבד על בדיקה בלולאה.

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

שני מושגים נגזרים חשובים. הראשון הוא volatile: משתנה שמשותף בין ISR לבין הקוד הרגיל חייב להיות מוצהר כך, אחרת המהדר יניח שאיש לא משנה אותו ויחזיק אותו ברגיסטר. השני הוא אטומיות: קריאה של משתנה בן 32 ביט על מעבד בן 8 ביט אינה פעולה אחת, ולכן פסיקה שנופלת באמצע יכולה להשאיר ערך חצי מעודכן. לכן חוסמים פסיקות סביב הגישה או משתמשים בגישה אטומית.

זיכרון - למה malloc נפסל

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

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

פריפריאלים: הדרך לדבר עם העולם

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

ממשקחוטיםאופישימוש טיפוסי
UARTשניים, ללא שעון משותףאסינכרוני, קצב מוסכם מראשמסוף דיבאג, מודם, GPS
I2Cשניים, נתונים ושעוןסינכרוני, כתובת לכל רכיבחיישנים איטיים, EEPROM
SPIארבעה ומעלהסינכרוני ומהיר, בחירת שבבזיכרון פלאש, מסכים, ממירים

לכל אחד תקלות אופייניות משלו. ב-UART אי התאמה בקצב השידור מייצרת ג'יבריש קריא למחצה, וזו התסמונת הראשונה שבודקים. ב-I2C נעילה של האפיק בגלל רכיב שמחזיק את קו הנתונים למטה משביתה את כולם, ונדרש שחרור בפעימות שעון ידניות; חסרים נפוצים אחרים הם נגדי משיכה ללא ערך מתאים או כתובת כפולה לשני רכיבים. ב-SPI ההגדרה של קוטביות ופאזת השעון היא מקור קבוע לבלבול, וארבעה שילובים אפשריים מייצרים בדיוק ארבע התנהגויות שונות.

טיימרים, DMA וחיסכון בהספק

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

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

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

קרוס-קומפילציה וסביבת הפיתוח

הקוד נכתב על מחשב אחד ורץ על ארכיטקטורה אחרת, ולכן מהדרים אותו בקרוס-קומפיילר שמייצר קוד ליעד. סביבת העבודה כוללת גם קובץ linker script שקובע היכן בזיכרון ממוקמים הקוד, הקבועים והמשתנים - ובמערכות עם עדכון קושחה גם היכן יושב ה-bootloader ואיפה שמור העותק החלופי.

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

איך מדבגים כשאין קונסולה

ברוב המערכות אין מסך ואין לוג. לכן ארגז הכלים נראה אחרת לגמרי.

  • מכשיר דיבאג דרך JTAG או SWD - מאפשר לעצור את המעבד, לקרוא רגיסטרים ולהציב נקודות עצירה, כולל נקודות עצירה על גישה לכתובת זיכרון.
  • מנתח לוגי - מקליט את האותות בפועל על הקווים ומפענח אותם לפי הפרוטוקול. זו הדרך היחידה להכריע אם הבעיה בקוד או בחומרה.
  • אוסילוסקופ - כשהשאלה אנלוגית: רעש, זמני עלייה, נפילת מתח בעת הפעלת עומס.
  • פין ניפוי - הרמת רגל פנויה בכניסה לקטע קוד והורדתה ביציאה, כדי למדוד זמן ריצה בלי להשפיע עליו כמעט.
  • לוג דרך UART - שימושי אך מסוכן: ההדפסה עצמה איטית ועלולה להעלים באג תלוי תזמון.

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

שאלות נפוצות

איזו שפה צריך לדעת?

C היא הבסיס שאין עליו ויכוח, ולצידה תת-קבוצה של ++C בפרויקטים גדולים יותר. Python שימושי לכלי בדיקה ואוטומציה, ו-Rust נכנס בהדרגה בפרויקטים חדשים שמחפשים בטיחות זיכרון. אסמבלי נדרש להבנה ולקריאה, ורק לעיתים נדירות לכתיבה.

מה ההבדל בין Embedded לבין קושחה?

המונחים חופפים ברובם. קושחה מתייחסת בדרך כלל לקוד שרץ ישירות על החומרה בלי מערכת הפעלה מלאה, בעוד Embedded הוא מטריה רחבה יותר שכוללת גם פיתוח על לינוקס משובץ. הרחבנו על כך במאמר על מהנדס קושחה.

צריך רקע בחשמל?

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

האם RTOS זה כמו לינוקס?

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

מה זה watchdog?

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

איפה כדאי לחפש משרות בתחום?

הביקוש בישראל מתפרס על ביטחוני, רפואי, רכב, IoT ותקשורת. נקודות פתיחה טובות בלוח הן 11 המשרות שמזכירות Embedded C ו-91 המשרות שמזכירות Linux. למסלול הקריירה עצמו, כולל דרישות סף ומסלולי התקדמות, כתבנו מדריך נפרד על קריירה בפיתוח Embedded בישראל. כל טווח שכר שמופיע בקהילות הוא הערכת שוק בלבד.

איך מתחילים ללמוד לבד?

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

מאמרים נוספים

המשרות באתר