טלאי על הבאג: הסכנה בכשלים שקטים

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

לוח פיתוח למיקרו-בקר ATtiny416
לוח פיתוח למיקרו-בקר ATtiny416

השעונים של הטיינים החדשים

בעולם המיקרו-בקרים יש אינספור וריאציות על נושא מקורות השעון של המערכת. באילו תדרי שעון הג'וק יכול לעבוד (ובאיזה מתח)? כמה דרכים יש לו לייצר, או לקבל מבחוץ, או לעבור בין אותות השעון? בכמה אופנים, אם בכלל, הוא מסוגל לחלק או להכפיל את אות השעון הגולמי? בארדואינו Uno רגיל, למשל, המיקרו-בקר (מדגם ATmega328P) עובד לקצב גביש חיצוני בתדר 16MHz. מי שקנה מיקרו-בקר כזה טרי מהמפעל למד, לפעמים בדרך הקשה, שכברירת מחדל הוא עובד דווקא עם מתנד פנימי בתדר 8MHz, ובנוסף מחלק את האות בשמונה כך שתדר השעון בפועל הוא 1MHz בלבד.

בקר השעונים במיקרו-בקרים ממשפחת TinyAVR 1-Series החדשה שונה מהותית גם מזה של ה-ATmega328P וגם מזה של דגמי ATtiny הישנים. הוא מאפשר לבחור אחד מתוך ארבעה מקורות שעון: מתנד פנימי חסכוני-בחשמל בתדר 32-34.5KHz (תלוי במתח), גביש 32.768KHz חיצוני מדויק, אות שעון חיצוני (שימו לב: אות, לא גביש!) בתדר עד 20MHz, או מתנד פנימי מהיר בתדר 16MHz או 20MHz (את התדר בוחרים באמצעות Fuse בזמן תכנות המיקרו-בקר ואי אפשר לשנות בזמן ריצה). את כל המקורות האלה אפשר להעביר דרך Prescaler שמחלק את התדר ב-2, 4, 6, 8, 10, 12, 16, 24, 32, 48 או 64. לטעמי קצת הגזימו עם רשימת הערכים הזו: ראשית אין בה הגיון בינארי פשוט, מה שיכול לסרבל את התכנות, ושנית, האם אני באמת צריך אפשרות בחירה בין, נניח, 1.25, 1.33, 1.6 ו-1.67 מגהרץ?

להגן על עצמנו מ…?

כיוון שתדר שעון נכון הוא אלמנט קריטי כל כך בפעולה תקינה של מערכת, כך מסביר לנו ה-Datasheet, אי אפשר לשנות את הפרמטרים האלה כלאחר יד. צריך קודם כול לכתוב "קוד הפעלה" לרגיסטר מסוים, ואז – תוך ארבעה מחזורי שעון לכל היותר! – לבצע את השינוי המבוקש. אגב, זו פרקטיקה נפוצה למדי בעולם ה-Embedded; לדוגמה, בג'וקים ממשפחת MSP430 של TI יש הגנה דומה על מודול ה-Watchdog. אבל חכו, יש עוד: אם כותבים "1" לביט נעילה אחר בטייני, אי אפשר יהיה לעשות עוד שום שינוי בהגדרות השעון ויהי מה – עד האתחול הבא של הרכיב כולו.

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

אם כך, הנעילה שומרת עליי כביכול מפני הבאגים של עצמי. הצרה היא שאם אני שם טלאי כזה על באג, מן הסתם אפילו בלי לדעת שהבאג קיים, זה רק טלאי והבעיה האמתית לא נפתרה. מה שעלול להיווצר הוא מצב שנקרא "כשל שקט" (תרגום שלי ל-Silent failure): משהו לא בסדר במערכת, אבל כלפי חוץ לא רואים את זה – לפחות לא בקלות או בזמן אמת. באגים שקטים כאלה הם בין הקשים ביותר לאיתור ופתרון, גם כי הם מתחבאים טוב ומתבטאים בדרכים עקלקלות, וגם כי כשהם מתגלים, זה בדרך כלל בשלב מאוחר בפיתוח, מה שיוצר הרבה לחץ ובלגן.

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

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

להרשמה
הודע לי על
0 Comments
Inline Feedbacks
הראה את כל התגובות