בואו להכיר את המיקרו-בקר הסיני החדש, את כלי העבודה ואת הקוד הבסיסי שיאפשרו לנו לנצל את העוצמה של 32-ביט כדי להבהב בלד או שניים!
מי שיחפש היטב בעליאקספרס ואתרים דומים יגלה מבחר מיקרו-בקרים בייצור ובתכנון סיניים, חלקם "תואמים" לדגמים מערביים וחלקם מקוריים. ה-CH32V003 מבית WCH משך לאחרונה תשומת לב, לדעתי משלוש סיבות: כי הוא מבוסס על ליבת RISC-V ("ריסק פייב") שעלתה קצת לכותרות, כי בהתחשב ביכולות שלו הוא זול מאוד, וכי היצרן שלו לא אנונימי לגמרי והספיק לצבור מוניטין מסוים (למשל, סדרת CH340 של שבבי USB to UART היא שלו).
אז כפי שכתבתי בפוסט הקודם, אחרי שהזמנתי צורב, לוח פיתוח ושבבים בודדים, ניצלתי את הצעת החסות של PCBWay ותכננתי עבור השבבים לוח פיתוח משלי. עיצבתי אותו כמין חללית מהסרטים, ובהתאם לכך שמתי עליו שני לדים: אדום משמאל וירוק מימין. כל לד נשלט על ידי פין נפרד של המיקרו-בקר, ובחרתי לתפקיד זה פינים שיש להם מינימום פונקציות חליפיות. בדיעבד הסתבר שזו בחירה מאלפת – עוד נגיע לזה.
סביבת פיתוח
מיקרו-בקר זקוק לקוד, ו-WCH מספקים סביבת פיתוח מבוססת Eclipse משלהם: MounRiver Studio (יש אנגלית באתר, חפשו מימין למעלה). השם המוזר הוא שילוב של Mountain ו-River, בעקבות איזושהי אימרה סינית. הרגשתי חוסר-שקט מסוים בהתקנה של תוכנה סינית על המחשב, וגם תוספי ההגנה של הדפדפן שלי לא מתים על האתר של WCH, אבל כיוון שבפורומים בינלאומיים ראיתי שאנשים התקינו את התוכנה ולא נפגעו (לפחות ככל הידוע להם…) החלטתי שאפשר להסתכן.
בשלב זה הופיעה הבעיה הראשונה. נכון לכתיבת פוסט זה, בדף Download באתר מוצע קובץ התקנה שמסתיים ב-"V185". זהו קובץ שגוי, בלי אופציה להתקנה. צריך ללחוץ על "more>>>" ליד הקישור ולבחור מהרשימה שתיפתח את הקובץ שמסתיים ב-"V184". בו כן יש אפשרות התקנה, ובפעם הראשונה שמפעילים את סביבת הפיתוח היא מזהה שקיים עדכון לגרסה חדשה יותר, מבקשת אישור ומתקינה אותו בעצמה. כנ"ל לגבי הצורב: כשחיברתי אותו למחשב, סביבת הפיתוח הציעה לי לעדכן את הקושחה שלו ועשתה זאת ללא תקלות.
מפרטים ודוגמאות קוד
כדי להשתמש במיקרו-בקר נזדקק גם למפרטים טכניים. בדף המוצר שלו יש שני מסמכים רלוונטיים, Datasheet ו-Reference Manual, עם מידע על הדגם ועל הליבה + המודולים הפריפריאליים. בנוסף, יש שם קובץ ZIP עם מבחר דוגמאות קוד עבור לוח פיתוח מסוים (לא זה שקניתי). לא אמור להיות מסובך להתאים את הדוגמאות ללוחות אחרים, למשל מבחינת הפין שמחובר ללד או ללחצן.
חיבור הצורב
בעליאקספרס, כצפוי, יש כל מיני לוחות פיתוח וצורבים לשבבים של WCH, ורובם לא מקוריים. אם במקרה תשיגו צורב ולוח כמו שאני קניתי, החיבור ביניהם הוא נוח מאוד כפי שרואים בתמונה, והצורב גם דואג לאספקת חשמל כך שלא צריך ספק כוח או חיבור USB נפרד בשביל הלוח בזמן הצריבה:
ממשק הפינים של הצורב כולל גם קווי UART, כך שאפשר לפתוח טרמינל ישירות בסביבת הפיתוח ולבצע בדיקות ודיבוג בנוחות. אבל אם רוצים רק לצרוב קוד חדש, וללוח יש אספקת חשמל משלו, נדרשים למעשה אך ורק שני קווים: אדמה ו-SWDIO.
קוד בלינק
סביבת הפיתוח מגיעה עם קומפיילר מוכן לעבודה (GNU GCC כלשהו), וכאשר יוצרים פרויקט חדש רואים שמצטרפת אליו אוטומטית HAL שלמה (Hardware Abstraction Layer) – קבצים עם אוסף ענק של הגדרות ופונקציות שאמור להקל עלינו את העבודה בכלל ואת הגישה לחומרה בפרט. הבעיה עם HAL, זאת וכל אחת אחרת, היא ש-א) צריך ללמוד אותה, ו-ב) היא מגושמת ותופסת משאבים, כך שאם אפשר להסתדר בלעדיה, עדיף.
כיוון שאני בקושי מכיר את סביבת הפיתוח והאופציות שלה, יצרתי פרויקט חדש רגיל (עם קובצי ה-HAL) אבל סילקתי מ-main.c את ההפניות אליה, וכללתי במקומן רק את הקובץ ch32v00x.h שמכיל את הגדרות הרגיסטרים.
בניגוד למיקרו-בקרים 8-ביט הפשוטים יחסית, כדי להשתמש כאן בפין GPIO כלשהו צריך קודם כל לחבר שעון לפורט שמכיל אותו. כברירת מחדל השעון מנותק כדי לחסוך חשמל. החיבור מתבצע באמצעות כתיבת "1" לביט המתאים ברגיסטר RCC_APB2PCENR, כפי שמצוין ב-Datasheet. למשל, ביט 5 הוא זה שיחבר שעון לפורט D:
כמו בארדואינו או בכל מיקרו-בקר אחר, אנחנו צריכים להגדיר כעת את הפין הרצוי בתור פין פלט. זה נעשה דרך הרגיסטר GPIOx_CFGLR (כש-x הוא הפורט הרצוי). אנחנו צריכים לתת לשני הביטים MODEy של הפין ערך שיגדיר אותו כפלט – יש שלוש "מהירויות" פלט לבחור מתוכן, אגב – ולשני הביטים CNFy ערך שיקבע את תצורת הפלט (רגיל, Open-drain ועוד). ככה נראה הרגיסטר ב-Datasheet:
אם תעשו את חשבון הביטים בראש או על דף, תראו שכברירת מחדל הרגיסטר הזה אמור להיות מלא ברביעיות ביטים "0100", שזה 4 בעשרוני/הקס, ואילו פין פלט "פשוט" במהירות 10MHz אמור להיות "0001", שזה 1 כמובן. לכן, כדי להגדיר את פין 0 של פורט D כפלט, ורק אותו, צריך לכתוב בסביבת הפיתוח את שתי הפקודות הבאות:
RCC->APB2PCENR |= 0x00000020;
GPIOD->CFGLR = 0x44444441;
שימו לב שב-Datasheet שמות הרגיסטרים הם עם קו תחתון, ואילו בקוד בפועל הם מוגדרים בעזרת מבנים ומצביעים כך שאנחנו משתמשים ב-"->".
לסיום, נצטרך לשנות את הפלט של הפין ל-HIGH ול-LOW לסירוגין. יש כמה דרכים לעשות זאת, באמצעות רגיסטרים שונים. הדרך ה"רגילה" היא לשנות את הביט המתאים ברגיסטר GPIOx_OUTDR:
זה בעצם כל מה שצריך בשביל קוד "בלינקי". למיקרו-בקר יש שעון מערכת שפועל אוטומטית אחרי אתחול, ובשלב זה מספיקה לולאת ספירה רגילה כדי ליצור השהייה בין הדלקה וכיבוי של הלד. יש לנו הבהוב!
הטעות שהתגלתה במקרה
כפי שהזכרתי למעלה, בלוח הפיתוח שלי יש שני לדים. את האדום חיברתי לפין PD0 ואת הירוק לפין PA2. הקוד ההתחלתי, שכתבתי לפי פירוט הרגיסטרים למעלה, עבד מצוין לאדום – אבל הירוק נשאר כבוי. וידאתי שכל ה-traces והרכיבים על הלוח שלי מחוברים היטב, ועברתי על הקוד בתשומת לב להבטיח שלא התבלבלתי בביטים. הכול נראה תקין ועדיין הלד סירב להאיר.
אחרי הרבה חיפושים וניסויים, מצאתי את שורש הבעיה. לפינים PA1 ו-PA2, חוץ מתפקוד GPIO, יש פונקציה חליפית של חיבור לגביש חיצוני. לפי ה-Datasheet, הפונקציה הזו מושבתת כברירת מחדל – שימו לב ל-Reset value של ביט 15 ברגיסטר ולהסבר שמופיע ב-Description בטבלה:
[עריכה: חשבתי שזו שגיאה ב-Datasheet, אך הסתבר שיש קוד אתחול אוטומטי מטעם סביבת הפיתוח, שנוגע בביט הזה בלי שביקשנו וגורם ל-PA1 ו-PA2 להיות שמורים לגביש. אפשר לנטרל את הקוד על ידי מחיקת השורה "jal SystemInit" בסוף הקובץ startup_ch32v00x.S. אופציה נוספת היא לכתוב במפורש "0" לביט 15, למשל באמצעות הפקודה הבאה, ואז הפינים "משתחררים" לתפקוד GPIO והלד הירוק יכול לפעול כמתוכנן בלוח שלי.]
AFIO->PCFR1 &= ~0x00008000;
כדאי או לא כדאי?
קשה לעמוד בפני הקסם של מיקרו-בקר שימושי שעולה פחות משקל אחד, וגם העלות של צורב ולוח פיתוח להתנסות היא מצחיקה. טעויות ב-Datasheet? אז מה, זו לא המצאה סינית, וזה חלק בלתי נפרד מחייו של מפתח אמבדד. בצד החיובי נוצרה כאן הזדמנות להתנסות ברכיב מעניין (יש דגמים משוכללים [ויקרים] יותר להתקדם אליהם, למי שירצה) בעלות אפסית ועם כלי עבודה שפועלים כמעט "ישר מהקופסה".
מצד שני, האם זהו כיוון שכדאי להשקיע בו מבחינת התפתחות מקצועית ופרוייקטים מעשיים? נכון, הליבה של השבב היא RISC-V האופנתית, אבל מה זה משנה? הליבה שקופה לנו כמעט לגמרי והיא לא מציעה שום יתרון יוצא דופן. ל-CH32V003, ספציפית, אין יתרונות על פני מיקרו-בקרים מודרניים אחרים: אין לו DAC, יש רק UART אחד, מהירות השעון שלו 48MHz לכל היותר, ואם הבנתי נכון מה-Datasheet אין לו אפילו Hardware multiplier. זאת אומרת, במיקרו-בקר RISC-V אחר של WCH צוין במפורש שיש, אז אני מניח שכאן אין.
והכי חשוב, בינתיים אפשר להשיג אותו רק בעליאקספרס, או בפנייה ישירה למפעל. אפילו ל-LCSC אין אותו במלאי. זה סיכון שפשוט לא שווה לקחת לטווח ארוך, אלא אם יש לכם קשרים טובים בסין ואתם מתכוונים לייצר אלפים רבים של לוחות, שחייבים לחסוך שקל או שניים על כל מיקרו-בקר.