כפי שהבטחתי, בפוסט זה אראה איך לממש Blink על מיקרו-בקר ממשפחת PSoC 4, באמצעות סביבת הפיתוח הויזואלית PSoC Creator 3.3. לפני שנתחיל בפרויקט עצמו, אספר קצת על החומרה איתה אני עובד כרגע.
כשכתבתי את הפוסטים הקודמים בנושא, החומרה היחידה ברשותי היתה CY8CKIT-049-42XX – לוח חביב וזול מאד (לא כולל המשלוח). אך מודול התכנות שלו עובד באמצעות Bootloader בלבד, והרגשתי שאם אני רוצה להתקדם ברצינות עם המיקרו-בקרים האלה, באיזשהו שלב אצטרך צורב אמתי. הפתרון הופיע בדמות CY8CKIT-043 (מחיר $10), לוח דומה אך משוכלל יותר – ושמודול התכנות שלו הוא צורב/דיבאגר מלא.
צירפתי להזמנה גם מיקרו-בקר מדגם CY8C4245PVI-482 (ראו בתמונה בתחילת הפוסט), מאותה משפחה, כדי להלחים אותו למתאם SSOP-to-DIP שכבר היה לי במקרה. זו היתה ההלחמה הכי עדינה שלי עד היום (הפינים במארז הספציפי הזה קטנים וצפופים עוד יותר מג'וקים SMD אחרים שעבדתי איתם), אך בדרך פלא היא עברה ללא תקלות. על בסיס הג'וק והמתאם אילתרתי "לוח פיתוח" בסיסי עם חיבור לצורב של ה-CY8CKIT-043:
עד כאן החומרה, ועכשיו קדימה ל-Blink. נפתח את PSoC Creator ונבחר בתפריט File->New->Project. ייפתח חלון בו נתבקש לבחור את התקן היעד:
אם סביבת הפיתוח הותקנה מתוך הורדה ספציפית ללוח פיתוח מסוים, הלוח הזה יופיע בתפריט הנפתח של Target Hardware. אחרת, אפשר לבחור ישירות את המיקרו-בקר אם מסמנים את Target Device ובתפריט הנפתח בוחרים בפריט האחרון, Launch Device Selector.
בחלון הבא נבחר Empty Schematic כדי ליצור פרויקט ריק…
ניצור Workspace חדש לפרויקט (עוד לא הבנתי איך משכנעים את המערכת לעבוד ב-Workspace קיים)
והגענו סוף כל סוף לתכל'ס. הפאנל האמצעי הוא המשטח הגרפי עליו נציב את המודולים השונים שדרושים ל-Blink, והפאנל מימינו הוא הקטלוג של המודולים עצמם. נאתר ונגרור אל המשטח הגרפי את המודול Digital Output Pin, את PWM (TCPWM Mode) ואת Clock. אפשר להקליד חלק משם אלמנט בתיבת "Search for" כדי להחיל מסנן על "עץ" הרכיבים ולמצוא אותו ביתר קלות. בפוסט הקודם הבטחתי אמנם שאשתמש בטיימר, אבל עם PWM זה קצת יותר פשוט. עכשיו, סביבת הפיתוח אמורה להיראות כך:
אפשר "להתקרב" למשטח הגרפי עם Ctrl וגלגלת העכבר, או סמלי זכוכית המגדלת שמעליו.
כעת נגדיר את הפרמטרים לכל אחד מהמודולים. נתחיל בשעון: נעמיד עליו את סמן העכבר, נלחץ על לחצן העכבר הימני ובתפריט שנפתח נבחר "Configure". יופיע חלון עם הגדרות ברירת המחדל:
מה שנבחר כאן לא ממש קריטי – פשוט נצטרך להתחשב בזה בהמשך, אז נגדיר מספר עגול ונוח של 10KHz (כן, קילוהרץ). למידע נוסף על מודול השעון, אפשר ללחוץ על כפתור Datasheet והוא יוביל אותנו ישירות לדף המתאים. נלחץ על OK כדי לצאת ולהמשיך, ונפתח באותה שיטה את חלון ההגדרות של מודול ה-PWM. בלשונית Configuration הפתוחה כבר מסומן PWM, אז נעבור ללשונית PWM:
מה שמעניין אותנו כרגע הוא התיבה מימין באמצע. הפרמטר Period קובע את משך המחזור השלם (נמדד באותות שעון), ואילו Compare הוא נקודת המעבר מ-HIGH ל-LOW. הערך המרבי לכל אחד מהם, על פי ה-Datasheet, הוא 65,535. אנחנו עומדים לחבר את המודול הזה לשעון שעובד ב-10KHz, אז כדי להבהב פעם בשניה באופן הפשוט ביותר, נגדיר את Period כ-10,000 ואת Compare כ-5000. אגב, אם נגלול למורד הלשונית, נראה אפילו שרטוט מעודכן של הסיגנל שייצא מהיציאות השונות של המודול!
בהגדרות של פין הפלט לא צריך למעשה לגעת – ברירות המחדל מתאימות לנו, אז הנה החלון רק כדי שתכירו. זה אולי זמן טוב לשנות את השם הגנרי "Pin_1" למשהו קריא ומשמעותי יותר…
כעת נעבור לחיבורים. נלחץ על סמל "Wire Tool" משמאל למשטח הגרפי (או נקיש W במקלדת), והסמן יהפוך לצלב שיאפשר לנו לחבר נקודות במודולים זו לזו. ברגע שעומדים על נקודת חיבור חוקית, הצלב הופך ל-X. ניצור חיבור אחד בין מודול השעון לכניסה Clock של מודול ה-PWM, וחיבור אחד בין יציאת Line של מודול ה-PWM לפין הפלט. חשוב מאד: אם תוך כדי חיבור הקו נוגע בכניסות או יציאות אחרות, הוא יקצר את כולן וזה לא מה שאנחנו רוצים. במקרה כזה, אפשר לסמן עם העכבר קווים שגויים ולמחוק אותם בעזרת המקש Delete.
לא לשכוח לשמור את הקובץ. עכשיו צריך לקשר בין פין הפלט הווירטואלי שבשרטוט לבין פין פלט ספציפי בחומרה. בפאנל השמאלי בסביבת העבודה, ה-Workspace Explorer, נאתר את הקובץ עם הסיומת cywdr ונקליק עליו פעמיים כדי לפתוח אותו (פעולה 1 בתמונה למטה). במרכז המסך יופיע שרטוט של המיקרו-בקר שבחרנו, ומימין רשימה של הפינים הווירטואליים שצריך לקשר אליו. נתפוס עם העכבר את הפין שהגדרנו (פעולה 2) ונגרור אותו לפין החומרה הרצוי בשרטוט. במקרה של הלוח שבניתי, זה הפין העליון משמאל (פעולה 3).
התהליך הזה הוא אחד הדברים המעניינים ב-PSoC (ובמיקרו-בקרים מתקדמים אחרים): במקום שהחומרה תכתיב לנו איזו פונקציה יכולה להתחבר לאיזה פין, אנחנו מקצים פונקציות לפינים הפיזיים לפי מה שנוח לנו, והחומרה דואגת לבצע את החיבורים הפנימיים המתאימים.
הפרויקט כמעט מוכן. הדבר האחרון שנותר הוא, בקוד התוכנה, להפעיל את מודול ה-PWM שכבוי כברירת מחדל. מה-Workspace Explorer נפתח את main.c, ולפני לולאת ה-for נכתוב את הקריאה לפונקציה
PWM_1_Start();
השם של הפונקציה מורכב מהשם שהגדרנו למודול ה-PWM, אחריו קו תחתון, ולסיום המילה Start. הסוגריים ריקים, ללא פרמטרים.
שימו לב שיש סימון שגיאה בשורה 12. הוא מופיע שם כי עוד לא ביצענו Build לפרויקט – ואת זה עושים דרך תפריט Build, או Shift+F6. אם הכל הוגדר כשורה, נקבל בסופו של דבר בחלון Output למטה את ההודעה Build Succeeded בתוספת תאריך ושעה.
נחבר את הצורב – הדרייברים שלו הותקנו אוטומטית בלי בעיה עם החיבור הראשון למחשב – ונלחץ על סמל "Program" (אייקון של ג'וק עם ביטים, או פשוט להקיש Ctrl+F5). נורית החיווי על הצורב תהבהב לזמן קצר, וה-Blink שלנו יתחיל לרוץ, כמודגם בסרטון הזה:
דבר אחד מדאיג בכל העסק – שלא תפסתי בסרטון – זה שהקוד המקומפל, גם בגרסת Debug וגם בגרסת Release שאמורה להיות "רזה" יותר, תופס כ-35% מתוך 4 הקילובייטים של זיכרון SRAM שיש למיקרו-בקר, וכמעט שני קילובייטים FLASH מתוך 32. אלה מספרים הרבה יותר מדי גבוהים בשביל יישום צנוע שכזה, ובהחלט הייתי רוצה להבין מאיפה הם מגיעים…
אני חושב שכל המקום שתפוס בתוך הזיכרון של הבקר הוא בגלל כל הספריות שהפרוייקט משתמש. אני אסביר את זה ככה:
אני עובד עם STM32CUBEMX(הזכרת את התוכנה הזו בפוסט הקודם בסדרה) וכשאני יוצר את הקוד לפרוייקט, בתוך הספריות שנכללות יש את כל הספריות של הפונקציות של כל הטיימרים, ADC-ים, WD, וכו'. כל הספריות האלו נקראות (HAL (hardware abstraction layer -שכבת הפשטת חומרה.
בגלל שיש הרבה ספריות אז כולן תופסות הרבה מקום(מסיבה כלשהי היוצר קוד כולל את כולן).לדוגמא, הקוד בלינק תופס 3052 בייטים מתוך 64 KB של זיכרון בתוך השבב שאני משתמש(השבב הוא STM32F051R8T6).
זו בדיוק הבעיה. כל קומפיילר עם חצי גרם של היגיון יודע להיפטר אוטומטית מקוד שלא נמצא בשימוש, ולא יכול להיות שבאמת חייבים כל כך הרבה זיכרון רק בשביל להגדיר שעון, PWM ופין פלט. אז או שהקומפיילר ממש עצלן, או שקורה שם משהו אחר עקום לגמרי.