תעביר את זה הלאה: הקצאת פינים דינמית במיקרו-בקרים

אחד הדברים הראשונים שמשתמשי ארדואינו לומדים הוא לקשר מספרי פינים מסוימים עם פונקציות ספציפיות: פינים 0 ו-1 הם RX ו-TX של Serial, פין 5 הוא אחד מהשישה שמסוגלים להוציא פלט PWM, וכן הלאה. במיקרו-בקרים מודרניים יותר, מוסכמות כאלה לא תמיד תופסות – לטוב ולרע. הנה כמה הסברים ודוגמאות.

הקצאת פינים דינמית (אילוסטרציה)
הקצאת פינים דינמית (אילוסטרציה)

המודל ה"רגיל"

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

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

בלוחות ארדואינו Uno, למשל, החליטו שפינים PB6 ו-PB7 של המיקרו-בקר ATmega328P יהיו מחוברים למתנד הגבישי החיצוני; אילו היו בוחרים להסתמך על המתנד הפנימי האיטי יותר (והפחות יציב), היינו מקבלים בתמורה גישה לשני פיני פלט/קלט דיגיטליים נוספים.

הקצאה דינמית של פינים

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

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

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

שיטות ניתוב דינמיות נפוצות

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

בדגמי PIC Mid-range החדשים-יחסית, ב-AVR XMEGA שאף אחד לא מדבר עליהם, ומן הסתם גם במקומות נוספים, נקטו גישה אחרת: לכל פונקציה יש פין אחד שאליו היא מקושרת כברירת מחדל, אבל על ידי שינוי ביט כזה או אחר ברגיסטר מסוים אפשר להפנות חלק מהפונקציות לפין חלופי. למשל, ב-PIC12F1840 הקטן, פונקציונליות RX של מודול ה-UART "יושבת" על פין RA0 כברירת מחדל. אם כותבים 1 לביט RXDTSEL ברגיסטר APFCON, הפונקציה הזו עוברת לפין RA5, שנמצא בצד השני של הג'וק. בחירה מוגבלת שכזו מספיקה לרוב היישומים, והיא הרבה יותר פשוטה להבנה ולשימוש מאשר ניתוב חופשי לגמרי.

…ואחת מוזרה במיוחד

השיטה יוצאת הדופן ביותר שנתקלתי בה עד היום היא ה-Crossbar, שקיים במיקרו-בקרים בארכיטקטורת 8051 של חברת Silicon Labs. בשיטת ה-Crossbar, בעת האתחול רוב הפונקציות המיוחדות של המיקרו-בקר עומדות בסבלנות במין תור קבוע מראש. אנחנו יכולים להוציא פונקציות מהתור הזה אם אנחנו לא צריכים אותן, אבל האחרות שומרות על הסדר. ברגע שאנחנו מפעילים את ה-Crossbar (על ידי כתיבת 1 לביט מסוים ברגיסטר מסוים), הפונקציות שנשארו בתור "משתלטות" בזו אחר זו על הפינים הפנויים.

דוגמה לפעולת ה-Crossbar (מתוך ה-Reference Manual של EFM8BB1)
דוגמה לפעולת ה-Crossbar (מתוך ה-Reference Manual של EFM8BB1)

נניח שיש לנו שלוש פונקציות מיוחדות: X (שצריכה שני פינים), Y (שצריכה אחד) ו-Z (שצריכה שלושה). אם כולן בתור, אז X תיקח לעצמה את פינים 1 ו-2, Y תיקח את 3 ו-Z תיקח את 4, 5 ו-6. אבל אם נוציא מהתור את X, אז Y תיקח את פין 1, ו-Z תיקח את 2, 3 ו-4.

בנוסף, אנחנו יכולים לחסום פינים כך שה-Crossbar ידלג עליהם בזמן ההקצאה. למשל, בדוגמה האחרונה, אם נחסום את פין 3, אז פונקציה Y תיקח את פין 1, ופונקציה Z תיקח את 2, 4 ו-5.

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

סיכום

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

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