C Programming on Bare-metal STM32 Microcontrollers — מחזור 2

#1 (2025-03-26)

טוען נגן…

תמלול

## אדמיניסטרציה ואינטרו

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

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

שאלות מקצועיות – איך שזה הולך להתנהל, קבוצת ה-WhatsApp תהיה פעילה 24/7. יהיה לכם assignment, שבשאיפה אור ישביר על זה כבר... מבחינתי, תכינו שיעורי בית ולא תלכו לישון עד שהשיעורי בית לא מוכנים, ואנחנו נתמוך ונעשה מה שצריך כדי שתצליחו. אבל שוב, זה לשיקולכם. המטרה של הקורסים שלנו, למי שלא מכיר את Embedded Academy וזה קורס ראשון שלו, כמו שיש פה כמה פרצופים שכן ראיתי, זה שתצליחו ללמוד בצורה מיטבית את החומר ולא תצאו עם חידות לא פתורות. כלומר, אנחנו ניתן לכם תרגילים, אנחנו נעשה פרויקט, תשקיעו, תחרשו, תחזרו על החומר, תראו את ההקלטות. תשתמשו בזה שיש לכם עכשיו תקופה שגם אור וגם אני לטובתכם, כדי לנצל את זה ולהצליח ללמוד בצורה איכותית. בסדר? תשבו על החומר, תחפרו עליו, תיכנסו. אנחנו לומדים פאקינג Bare-metal. אנחנו לומדים את הברזלים של המיקרו-קונטרולר. זה low-level, שיותר נמוך מזה זה כבר ברמת האטומים, אני כבר לא יודע איך יורדים יותר נמוך מ-register. בסדר? זה דורש שתפעילו את הראש ותדעו שיש המון קרדיט למפתחי embedded בשוק, כי מפתח embedded שמבין ב-low-level, כל השאר קטן עליו. לעשות אפליקציה, לעשות איזשהו שרת ב-back, לשחק באיזשהו, לא יודע, שטות של כל מיני full-stackים ודברים כאלה – once אתם מפתחים חשיבה של איך עובד low-level והמוח שלכם מכוון להבין אלגוריתמיקה, להבין run time בצורה יעילה, כל עולם הפיתוח קטן עליכם. Bare-metal זה העולם הכי אפל, קשוח וסיזיפי שיש. אז תשקיעו את הזמן שלכם, כבר נרשמתם לקורס, תנצלו את זה ותלמדו בצורה המיטבית.

בסדר, אני אתן חצי שנייה על אור. אור כבר מעביר לנו כמה קורסים – Embedded Linux, kernel, Bare-metal, driver development ומועדון המפתחים. FreeRTOS וגם בדרך יש לנו Device Drivers ב-Linux ו-Zephyr OS. אז האקדמיה מאוד אוהבת את אור, הוא מרצה באמת מדהים של שילוב של גם להעביר את החומר בצורה ברורה וגם ידע מפה ועד הודעה חדשה, ואני חושב שמפה אתה תיקח את זה.

## הנחיות ופתיחת השיעור

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

## היכרות עם המשתתפים

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

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

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

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

אני עמית ברון, בן 28. סיימתי עכשיו תואר בהנדסת מכונות. אוהב את התחום ורוצה להתחיל ללמוד אותו כמו שצריך. נתי.

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

סבבה. שומעים אותי? לצערי כרגע אני בלי מצלמה, אני אצטרך לארגן לשיעורים הבאים, אז סלחו לי על זה. אני אופק, בן 20, כרגע חייל סדיר, משרת ברמת המקצוע בעיקרון בתפקיד embedded. כרגע לא מתעסק ממש ב-embedded, יותר בתחום האוטומציה וכל מיני מערכות full-stack כאלה ואחרות בחיל האוויר, אם זה מעניין. בחיל האוויר ב-108.

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

## מבוא לקורס ופילוסופיית הלמידה

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

אז בואו אני אספר קצת על עצמי: אני עם 10 שנים של ניסיון בתעשייה, התחלתי באלקטרוניקה ועברתי לעולם התוכנה, כמו איזשהו מסלול של הרבה אנשים, יש אנשים גם שעושים את המסלול ההפוך. ב-5 השנים האחרונות אני מפתח Embedded Linux, אבל לפני זה עבדתי על מיקרו-קונטרולרים של Silicon Labs ו-STM32, שזה בעצם משפחת המיקרו-קונטרולרים של הקורס.

בעצם הבסיס האלקטרוני שלי היה באמת ב-108 כמו שאמרתי, עבדתי על כמה סטאקים תקשורתיים בחיי – TCP/IP, גם 4G, ואחר כך בסאק של תקשורת לווינית, מה שנקרא אינטרנט לוויני.

אז ההתמחות שלי בגדול הרבה פעמים ב-high performance, multi-threaded בעולם של Embedded Linux עם C, C++. והרבה מאוד עבודה עם דרייברים למשפחות של המיקרו-קונטרולרים שאנחנו נדבר עליהם.

הקורס הוא מכוון למיקרו-קונטרולרים עם ארכיטקטורה של ARM Cortex-M4. אני גם מסביר כל פעם למה, ואני גם נותן רפרנסים ל-TRM של ARM Cortex-M4, הארכיטקטורה. ככה שאם יש לכם בורד שונה מהבורד שלי, או אם יש לכם בורד ממשפחה אחרת, פשוט אתם עושים את ההתאמות – במקום M4 מחפשים M7, ובמקום STM32 F411 מחפשים משהו אחר. רק שימו לב שאם אתם עובדים עם מיקרו-בקרים פחות חזקים, שהם M0 או M3 אפילו, כאילו לא פחות חזקים, אלא משפחות פחות מתקדמות, ההגדרה היא יש יכולות בתוך הארכיטקטורה של ARM... אז שימו לב שחלק מהפונקציונליות של הקורס לא יהיו, אבל לא כזה קריטי כי הרוב מתאים.

הרבה ברינג-אפים של חומרה יצא לי לעשות, הרבה מאוד board level communication, ובעזרת הטולים שאני מתמחה בהם – Linux, GDB, עבודה עם Git, FreeRTOS (שזה בעצם קורס גם שאנחנו עושים כאן, הקורס לאחר מכן, שזו מערכת הפעלה בעצם דינמית שמשתמשים בה), כנ"ל U-Boot, CMake, Yocto, MQTT, ושני קיטים לניהול פקודות שזה DPDK ו-XDP. זה בגדול.

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

השיעורים בנויים בצורה מוגדרת – structured, incremental approach, זאת אומרת שאולי השיעור הזה ייראה לכם מאוד קל, אבל מהשיעור הבא זה כבר מתחיל להתקדם. ואני יכול להגיד שבקורס המקביל שלכם שרץ, שמה אנחנו בשיעור 3, יכול להיות שכבר פיצצתי לכם את המוח בשיעור שאנחנו נמצאים בו.

עוד דבר – כשאתם לומדים, תלמדו ביחד, יש לכם קבוצה...

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

## מטרות הקורס

אז מה המטרות שלנו של הקורס?

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

אוקיי, בעצם אנחנו בקורס הזה אנחנו הולכים לעבור מה-startup code עד ל-memory-mapped registers ועד ל-MCU control. בעצם את ה-MCU שאתם עובדים עליו בסוף הקורס אתם תכירו בצורה... בצורה מאוד נרחבת. אני חושב שגם מה שלא תכירו ב-MCU, הכלים שאני נותן בקורס, אתם תוכלו ממש לדעת גם איך... איך למצוא אותם. זאת אומרת שאם עכשיו יש איזשהו... סתם אני זורק, RNG שיש ל-MCU מקביל ולא על זה למדתם – RNG זה Random Number Generator בחומרה – ואתם כאילו לא יודעים איך ניגשים אליו, אז חלק מהקורס אני גם אלמד אתכם איך אתם ניגשים לפיצ'רים חדשים בתוך Microcontrollers.

אוקיי, אז החלק האחרון, אז הבנה בעצם באמת של Bare-Metal, כמו שאמרתי, להבין גם איך דיבייסים עובדים ברמת ה-Low level. נדבר קצת על clock configuration, אנחנו נגיע ממש ל... למעיים של interrupt handling, מאיפה זה קורה ואיך אנחנו יכולים לשלוט על זה, ונדבר קצת על memory architecture.

## Today's Agenda

אז האג'נדה של היום:

החלק של ה-instructor overview כבר עשינו, אבל נעשה course overview. דיברנו עליי, על הפילוסופיה. אני אתחיל להראות לכם את ה-repository, נדבר על ה-assignments, איך אני מאמין שה-assignments אמורים להיעשות.

נדבר על ה-STM32 Microcontrollers, בעצם על ה-Microcontroller של הקורס, או יותר נכון המשפחה שאנחנו משתמשים. נדבר קצת על real-world applications, בעצם בשביל מה משתמשים בדברים האלה.

ואז נתחיל קצת עם התקנות. להתקין את ה-IDE של הקורס, בעצם ה-IDE ש-ST מספקים. זה בעצם איזשהו IDE, זה Integrated Development Environment, שזו סביבת פיתוח בעברית. נדבר על סביבת הפיתוח שאנחנו הולכים להשתמש בה בקורס, בעצם זו סביבה מבוססת Eclipse. תהיו סבלניים, אבל זו הסביבה בעצם שהאינטגרציה הכי טובה איתה.

נעשה התקנות של GCC על Windows. מי שהוא על Linux, אני חושב שאם אתם על Linux אתם ילדים גדולים, אבל אם צריך עזרה אנחנו נעזור גם עם זה. ונתחיל לעשות איזשהו Alignment בסיסי ל-C. תמיד החרוז הזה מצחיק אותי. ואנחנו נדבר עליו ונתחיל לדבר על מה להכין לקראת השיעור הבא.

## How is the Course Built

אז איך הקורס בנוי? בעצם יהיה לנו שעתיים של שיעור עם מידע טכני, ואחר כך אנחנו נתעסק קצת בדברים hands-on. בעצם גם דוגמאות שאני מספק, וגם אנחנו קצת עושים עריכות לדוגמאות, כותבים קוד. הקורס בנוי בצורה של follow-along friendly. זאת אומרת שאם אתם עוקבים כמו שצריך, אתם פשוט יכולים להמשיך כרגיל כאילו.

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

מה אתם צריכים להכין לפני כל שיעור? אני גם אראה דוגמאות, אז אל תפחדו מהמילה Git. אני לפני כל שיעור אומר לכם לאיזה branch אתם יכולים לעבור. בגדול, מספר ה-branches זה מספר השיעורים. אז לכל שיעור יש את ה-branch שלו. לשיעור הזה, מי שכבר הצליח לעקוב, אז יש לנו את ה-branch שנקרא lesson0.

אפשר לעבור אליו. וזה, אבל זה כשנגיע ל-repo, ל-repository.

בואו, אם אתם יכולים, תנסו לא לדחוף שום דבר ל-Git, כי אני לא רוצה להתמודד עם ה-commits שלכם. זה פתוח, אם אני אראה שיש בעיות אני פשוט אחסום את זה, אבל כרגע לא היו בעיות. אם אתם מסתבכים עם merging ועם הכל, אז או שאנחנו נעשה stash, או שבעצם תצרו לעצמכם branch נפרד ותמרג'ג'ו אליו כל מיני דברים שתעשו, או fork. כאילו, יש הרבה שיטות לעבוד עם זה, בסדר?

בדיוק, אז רשמתי פה, תעשו fork, או שבעצם אתם יכולים לעשות cherry-picking או כל פעם לעדכן את ה-fork.

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

אוקיי, נראה ככה. כתבתי לכם מה לעשות.

## Course Repo

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

אז הקורס repository: בעצם מה יש שם? יש שם את ה-assignments, code examples, ובעצם resources, וגם documents משיעור מסוים.

הלינק ל-repository נמצא לכם פה, זה ה-repository עצמו, אני גם מראה את זה כאן.

אנחנו נדבר קצת על אילו פקודות Git צריך לעשות כדי לקבל את ה-repository הזה אליכם כנגיע לחלק הזה. בואו נמשיך.

## Course Assignments

אוקיי, בדיוק על ה-assignments הזה דיברתי. כנראה שהקדמתי את עצמי. אז שוב, המטרה של זה היא בעצם לקדם את הלמידה שלכם על ידי תרגול.

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

ו-suggested solutions – אם יש איזה משהו מעניין אני גם אתן לזה פתרון שאני עשיתי.

## STM32 Microcontrollers

אז STM32 Microcontrollers.

בואו נדבר על מי אלה ST.

ST זה global semiconductors, בגדול זו משפחת אם. הם יוסדו ב-1987, בעצם ההתמחות שלהם היא ב-Microcontrollers ובגם רכיבים ל-industrial, זאת אומרת שמהם תקנים ספציפיים למשפחות רכבים של automotive ו-personal electronics.

מעבר לזה יש להם גם צ'יפים שהם ספציפיים ל-IoT, ל-Internet of Things, שנותנים אפשרות לחבר את ה-Microcontroller אל האינטרנט. בעצם Internet of Things. אבל יש גם כאלה עם stack אינטרנטי מובנה. זאת אומרת, אם מסתכלים על המשפחות של WB וכאלה, אז בעצם יש איזה מודולטור RF שאפשר להשתמש בו ולממש עליו Wi-Fi, אני לא יודע אם 4G אבל תלוי... כאילו לא יודע אם מודם סלולרי, אז זה תלוי במודולטור עצמו ובעוצמה שהוא יכול לספק, וגם כן BLE ועוד הרבה תקשורות Over-the-Air: Wi-Fi אמרנו, BLE (Bluetooth Low Energy), אחר כך גם יש לנו Zigbee, OpenThread, whatever.

אז בעצם, הם ידועים מאוד בישראל, בעיקר בישראל בגלל הצבא. הרבה פעמים בצבא עובדים עם ה-Microcontrollers שלהם, גם התעשייה האווירית וכל המשפחה. בעצם יש להם משפחה מאוד גדולה של Microcontrollers, סנסורים ו-power management devices, בעצם איזשהם buck converters והרבה מאוד רכיבים. אם יצא לכם להיכנס בעקבות ההודעה ששלחתי לאתר של ST ולהסתכל על ה-boards, אז מעבר ל-boards יש שמה גם הרבה מאוד רכיבים אלקטרוניים שנחמד להשתמש. אני חושב שאם אתם משתמשים בשימוש חובבני, אז אפילו להזמין מהאתר של ST זה מאוד משתלם, כי גם המשלוח יחסית זול וגם ה-boards יחסית זולים.

## 32-bit Microcontrollers & Why We Need Them

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

עכשיו, מה זאת אומרת מיקרו-בקר שהוא 32-bit? זה אומר מיקרו-בקר שמרחב הכתובות שלו, בעצם הזיכרון שהוא יכול להשתמש בו, הוא הרבה יותר גדול. מה זאת אומרת למפות את הזיכרון? אנחנו נלמד את זה עוד שני שיעורים, אבל תחשבו על זה שהוא יכול לגשת מבחינת זיכרון התוכנית להרבה יותר כתובות. מיקרו-בקר של 8-bit יכול לגשת ל-2 בחזקת 8 כתובות. מה זאת אומרת? 256 bytes.

יכול לגשת אליהם, שם נמצא גם הקוד, שם נמצא גם הפריפריאלים אם אתה בכלל יכול למפות אותם במצב כזה, ומזה אתה משתמש כדי לשלוט. במיקרו-קונטרולר של 16-bit יכול עד $2^{16}$, שזה כבר הרבה יותר והרבה יותר חזק, אבל אמרנו מקודם מבחינת המחיר בעולם של היום זה בכלל לא משנה ליצר 32-bit, 16 ו-8. אוקיי.

## Microcontroller vs. CPU

מה ההבדל בין microcontroller ל-CPU?

אני אגיד. אז microcontroller בעצם, microcontroller יש לו גם CPU core על הצ'יפ, בעצם baked in, ויש לו גם memory משלו, בעצם אין לנו פלאש חיצוני ואין לנו גם RAM חיצוני, הכל על הרכיב עצמו. ופריפריאלים שאנחנו לרוב לא היו לנו בתוך ה-CPU. כי CPU זו יחידה, מה? core processing unit, זו היחידה של העיבוד עצמה. אז מה יהיה לנו? יכולים להיות לנו טיימרים, analog-to-digital converter, ורכיבי תקשורת למיניהם, I2C, SPI, whatever, כאילו באמת. אז כל זה על צ'יפ אחד.

למה זה מותאם? זה מותאם בעצם למערכות embedded ושגם מערכות real-time שהכל נמצא קרוב ל-CPU ככה שאנחנו יכולים לגשת להכל מהר. מה הכוונה קרוב? כתרתו משמע קרוב, כאילו על ה-CPU עצמו. אני לא עכשיו צריך להשתמש... בעצם יש לי איזשהו באס מאוד מהיר שאני יכול לגשת להכל בצורה מאוד מהירה.

אז אני לא עכשיו צריך להשתמש באיזושהי תקשורת סריאלית לדוגמה שהיא הרבה יותר איטית, אני בעצם יכול להשתמש בכל מה שאני צריך בצורה מאוד מהירה. נגיד אם הייתי רוצה לגשת ל-RAM, אז אם אני עכשיו... בוא נדבר על... לדוגמה על מיקרו-מעבד, בעצם על SOC, system on chip בעצם של משפחה גדולה יותר, נדבר נגיד על ה-A-series של ARM.

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

רואים מאוד גם את הרגליים שיוצאות ממנו, ובגדול אנחנו נגיע אל הכל.

לעומת זאת CPU, central processing unit, זה אפילו רשום פה, אז לא הייתי צריך לעשות תזכורת לזה, זה בעצם משמש למחשבים ול-servers. יש לו הרבה פעמים external memory כמו שאמרנו, DDR controller שזה הקונטרולר של ה-RAM לדוגמה, ו-input output שהוא צריך להתחבר אליו חיצונית.

למה להשתמש בזה? בעצם הפוקוס שמשתמשים בו זה למערכות עם עיבוד מאוד גדול, עם הרבה מאוד throughput, ומריץ מערכות הפעלה יותר מסובכות. מה הכוונה? לדוגמה על מיקרו-קונטרולרים, לפחות על הרוב, אני לא יכול להריץ Linux. למה? כיוון שאין לי כל מיני רכיבים חומרתיים ספציפיים שאני צריך בשביל Linux וגם אין לי את הזיכרון להריץ Linux. אז או שאני ארוץ בצורה שהיא bare metal, על הברזלים, עם פיצ'רים של מערכת הפעלה שאני מממש בעצמי, שזה חלק מהיופי בלעבוד ב-embedded. הרבה פעמים אתה צריך לממש בעצמך את הדברים שאתה רוצה. אז יש אנשים שמצוחקים על זה "מה, אתה מממש כל פעם linked list?" בגדול לא, אתה מממש linked list פעם אחת ואתה יכול להעתיק בין הפרויקטים.

## Real-World Applications of STM32

אפליקציות של העולם האמיתי, בעצם מה אפשר לעשות עם הדברים האלה.

מבחינת consumer electronics, בעצם מכשירים שאפשר ללבוש, אם זה צמיד חכם, whatever. בעצם ברגע שיש לך צ'יפ מאוד קטן וחסכוני באנרגיה אתה יכול להכניס אותו לבפנים, ואם הוא גם יודע להתחבר לכל מיני דברים, עם BLE, Wi-Fi, מודם סלולרי, whatever, אז הוא גם יכול להיות מאוד חכם. בעצם home appliances, מניח שאתם כבר מכירים, למי אין כבר מטהר אוויר שמתחבר לרשת ושולח מידע על האוויר שלכם לסינים? לכולנו יש. ורכיבי מולטימדיה בעצם... you name it, אני כבר לא יודע מה. רכיבי מולטימדיה אז מצלמה חכמה, מסך נייד, whatever, לכל דבר כמעט.

בעולם ה-industrial, אז אם אנחנו מדברים בעולם שהוא יותר תעשייתי, אז שליטה במנועים, power management בעצם של מערכות קצת גדולות נעשה גם כן עם מיקרו-קונטרולר, שליטה על סנסורים, ו-ECUs.

לגבי IoT, בעצם כל העולם של IoT, רוב העולם של IoT נשען על מיקרו-בקרים. זאת אומרת wireless modules, אינטגרציה של סנסורים, real-time data שמגיע מכל מיני מקומות, הרבה פעמים מתבצע גם באמצעות ה-MCU.

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

## Git Bash for Windows & Basic Git Commands

אז בואו נדבר על איך אנחנו מתקינים Git ל-Windows ול-Linux.

מי שיש לו Linux, אז פשוט תחפשו את ההתקנה של Git למערכת ההפעלה שלכם. אם זה Ubuntu אז `sudo apt install git`. אם זה כל package manager אחר אז פשוט תחפשו ב-package manager שלכם.

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

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

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

מעבר לזה, אני בחרתי ב-Visual Studio Code כ-default editor. אתם יכולים להשתמש... גם Notepad++ זה טוב. שימו לב ש-Notepad++ הוא מאוד מותאם ל-Windows, ככה שאם אתם רוצים לעבוד בסביבה של Linux פחות מומלץ. אם אתם עובדים ב-Vim ואתם מצליחים לצאת ממנו, סבבה, תשתמשו בזה. אני עדיין לא יודע איך לצאת מ-Vim, סתם זו בדיחה. סליחה.

נגעתי בבדיחה, סליחה.

אחר כך יש איזשהו קטע ווקי ל-Git בשנים האחרונות שהוא לא רוצה להשתמש ב-master ו-slave יותר. אנחנו הולכים להשתמש ב-master ו-slave בקורס, אנחנו לא הולכים להשתמש ב-main ו-secondary, ב-whatever. אז פשוט תשתמשו בזה.

- לסמן בקודם?

- לסמן Let Git decide, זאת אומרת שאנחנו נישאר עם master ועם שאר ברנצ'ים כמו שהעולם התכוון לו ולא להמציא גלגל מחדש.

שנייה. בעצם לעשות adjustment של ה-PATH environment, זה יותר רלוונטי... בעצם הכל פה רלוונטי ל-Windows. בעצם לתת לו גישה לכל ה-environment variables. אנחנו נגע בזה בהמשך כשנתקין את GCC על Windows. ככה שפשוט תסמנו ולעבור הלאה. משתמש ב-OpenSSH, אנחנו משתמשים ב-OpenSSH של Git. ואנחנו רוצים להשתמש פה ב-native secure library של Windows.

פה זה מאוד מעניין... יש מישהו פה שעובד עם Linux שמתקין Git Bash? או שלא? אוקיי. אז בגדול, מה שקורה, ההבדל בין Linux לבין Windows מבחינת ירידת שורה, אז ב-Windows יורדים שורה בצורת CRLF וב-Linux יורדים רק באמצעות LF שזה `\n` ב-ASCII. אז בואו נשאיר את זה Check out as-is and commit as-is. ככה שאם אתם עובדים באותה סביבה אז תעבדו ככה. אם הקומיטים שלי עושים לכם בעיות ואתם עובדים ב-Linux, אז יש tool מאוד נחמד שנקרא dos2unix, הוא מגיע לדעתי מובנה במערכת הפעלה אפילו. אז על מה שעושה לכם בעיות, אתם רואים כזה caret sign ואז M בסוף כל שורה, תעשו dos2unix והכל יפתר לכם על הקובץ.

זה בעצם איזשהו טרמינל שאנחנו משתמשים... אתם יכולים לבחור פה כל אחד מהם, אני ממליץ להשתמש בטרמינל של MinGW (MSYS), כי הוא בעצם integrated ל-MinGW ככה שזה בעצם מה שאנחנו הולכים להתקין, ה-GCC של Windows. פה מבחינת ה-git pull תשירו אותו דבר, ו-credential manager גם כן כאן.

עכשיו, symbolic linking - אנחנו כנראה לא נשתמש בזה, אבל יכול להיות ש-STM32Cube יכול להשתמש בזה, תסמנו את זה רק כדי להיות בטוחים. בסך הכל כל מה שזה אומר זה בעצם אפשרות לעשות soft link, בעצם לינק שהוא בעצם... תחשבו עליו כעל pointer שמצביע על הקובץ הבא. ותעשו התקנה. אני לא הולך לעשות התקנה כי אצלי זה כבר מותקן. ואחרי שתעשו התקנה אז אנחנו כבר יכולים לפתוח את ה-Git Bash.

אז לי יש תיקייה במחשב שקראתי לה src או source, תלוי איך אתם רוצים לבטא את זה. ברגע שתסיימו להתקין אז יהיה לכם בעצם ב-Windows את שני החלונות האלה. אם אתם רוצים ללמוד לעבוד עם ה-Git GUI אתם מוזמנים, אני לא לגמרי בטוח איך, אז בואו אנחנו נעשה כרגע clone ל... זה. אז זה בעצם ה-instance שיש לי, אבל אני אעשה איתכם ביחד clone ואני גם אסביר מה אנחנו עושים.

אז ברגע שעשינו כאן ימני ועשינו Open Git Bash Here, שימו לב שה-PATH, בעצם המקום שממנו אני רץ מותקן כאן. הוא מותקן בצורה שונה, כי זה בעצם איזשהו instance... כי זה בעצם איזשהו טרמינל לינוקסי בתוך Windows. אז כדי להגיע ל-slash אני לא עושה יותר `C:\`, אני עושה `/c/source`. אז אם יש לכם תיקיית source סבבה, אם יש לכם תיקייה אחרת גם סבבה, רק תעשו את ההתאמות.

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

- היי, ראיתי את הקישור, פתחתי את הקישור ובחרתי בעצם את הראשון, את הקליק כאן של ה-64-ביט ל-Windows? זה מה ש...

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

- כן, תודה.

אוקיי, אז עכשיו אני מראה איך עושים clone. בעצם יש לי פה את הפקודה, אני אעשה גם... `git clone`. לכם לא יופיע ככה, כי בעצם זה אני מחפש בתוך הזיכרון. אם אתם רוצים לדעת איך לחפש בתוך ה-history, אז Ctrl+R ייתן לכם לחפש בתוך ה-history, ואז ברגע שתתחילו להקליד אז זה יתן לכם את הפקודה. אבל הפקודה היא ככה: `git clone` ואז ה-repository URL.

איך אנחנו מקבלים את ה-Repository URL, ואיך אנחנו מתקינים SSH key? בואו נעשה את זה מהר.

אז יש לי כמה אפשרויות לעבוד. יש לי אפשרות לעבוד ב-HTTPS ולהכניס סיסמה כל פעם שאני רוצה לעשות פעולות שהן מצריכות אוטנטיקציה מול ה-GitHub. אם יש לי user של GitHub, שזה בעצם ה-Git client שאיתו אני משתמש, אז אני יכול לייצר SSH key.

מה זה SSH key? זה בעצם איזשהו מפתח אוטנטיקציה שאני מעביר ל-Git client, בעצם לקליינט הזה כאן, ואז הוא כבר יודע מי אני והוא לא צריך לאשר אותי כל פעם, וככה העבודה שלי יותר מהירה.

יש עוד אפשרות לעבוד עם GitHub CLI, יכולים לנסות. יכול להיות שהשתמשתי בזה אפילו כמה פעמים.

אוקיי, אז כאשר אני רוצה לעשות `git clone`, כדאי שיהיה לי SSH key. איך אני מייצר SSH key?

אז אני פשוט עושה `ssh-keygen`. פשוט ככה, ואז הוא שואל אותי אם אני רוצה ליצור מפתח חדש, אז אני אומר לו כן. ואז הוא שואל אותי אם אני רוצה להכניס empty passphrase, אז אני אומר לו גם כן. ואחר כך עוד כמה אינטרים, ואז אני עושה את זה.

אז אני לא אנסה ליצור מפתח חדש כי אני לא זוכר במה תלוי בזה, אבל פשוט תלחצו כמה יסים, ואז תהיה לכם את התיקייה שבה נמצא ה-SSH key.

אם תעשו `cat`, שזה בעצם להראות לנו preview של הקובץ, ואת ה-path אתם יכולים להעתיק לכאן, ואז יש לכם שני קבצים שמופיעים.

מה הקבצים? הקבצים זה בעצם ה-encryption key, בעצם קבצי encryption. יש קובץ שהוא בשבילנו, המפתח המקומי שלנו, ויש את הקובץ שהוא המפתח שבו אנחנו נותנים לקליינט שירצה להשתמש בשירותים שלנו.

אז נעשה נקודה, ובעצם אנחנו עושים `cat` את ה-path שאוטומטית נוצר ל-SSH, נקודה `pub`. ואז אתם רואים, הוא מוציא לי איזשהו מפתח. זה השם של המחשב שלי בגדול, וזה המפתח עצמו. אותו אני יכול להעתיק.

ואם אתם משתמשים ב-GitHub, אתם הולכים ל-Settings. גם אם אתם משתמשים בכל client של Git, אם זה GitLab או Bitbucket או לא יודע, whatever, משהו של Windows שגם מסייע לעבוד, אז אתם פשוט עושים את זה באותה צורה.

הולכים ל-Settings. ב-Settings יש איזשהו section של SSH keys. אומרים לו תוסיף לי SSH key חדש, מדביקים את הדבר הזה, וקוראים לו בשם, לא יודע, בוא נקרא לו AAA. לי הוא לא ייתן לעשות את זה כי המפתח כבר קיים. תצטרכו להכניס סיסמה. המפתח כבר קיים, אז הוא לא ייתן להכניס את זה. המפתח עצמו, לזה עצמו קראתי בשם הזה בזמנו.

אז זה מה שאנחנו צריכים. אחרי שיש לנו מפתח SSH, אנחנו פשוט יכולים לעשות את ה-clone דרך ה-SSH. זה הרבה יותר נוח, וכל פעם שנרצה לעבוד מול זה, אנחנו נוכל לעשות.

אני אחזור ל-Repository של הקורס. ואני אקח את הקוד ואני אעשה העתקה ל-clipboard של ה-SSH URL. זה URL שהוא שונה.

ואני ארשום `git clone` ואני אדביק. איך אני עושה הדבקה לטרמינל? Shift+Insert, או אפילו Ctrl+V... לא, Shift+Insert.

אז עוד פעם, `git clone`, הדבקה לתוך הטרמינל באמצעות הכפתורים Shift ו-Insert.

ואם אני ארצה לקרוא לתיקייה בשם - כמובן יש לי את השם הקבוע - אז אני אקרא לו בשם שאני הולך להשתמש: `class_test`, זה השם שלו.

ועכשיו הוא יעשה clone ל-`class_test`, לעשות clone ל-repository לתוך תיקיית `class_test`.

אתם רואים שכבר נוצרה לי תיקיית `class_test`. לוקח לו קצת זמן להביא את המידע.

אגב, אני כבר חוויתי את זה, אני לא זוכר איך פתרתי. זה מחשב חדש. בוא נעשה שנייה לראות מה ה-clone השני שעשיתי: `git clone`...

טוב, אז אם זה לא עובד, אתם יכולים תמיד להשתמש ב-HTTPS.

אז `git clone`... `class_test`...

הוא לא יבקש סיסמה, יכול להיות שלא, ואז בעצם תהיה לנו את התיקייה של `class_test` וכל המידע שיש בה.

עכשיו אנחנו נרצה להיכנס לבפנים. אז `cd`, זה Change Directory, תעבור לתיקייה אחרת. נעשה `class_test`, ואפשר להשתמש ב-Tab להשלמה אוטומטית.

ומבפנים אתם רואים שמופיע לי שאני ב-`main`. למה main ולא master? אני לא יודע, הוא בחר, אבל בסדר גמור.

אז זו ההעתקה או השכפול של ה-repository אליכם המקומית.

## Git Commands

עכשיו בואו נדבר שנייה על Git. יש כמה פעולות סטנדרטיות שאנחנו משתמשים. יש הרבה יותר מסובכות, אבל הפעולות הן `git add` והקבצים שאני רוצה.

אז בואו ניצור לדוגמה קובץ: `touch`, יצר קובץ, `test_file`.

בעצם אם אני אעשה `git status`, אני אראה את כל הקבצים ששונו. יראה לי שיש קובץ חדש שנקרא `test_file`.

אז אני אוסיף אותו: `git add`. גם ההשלמה האוטומטית יכול להיות שתעבוד פה, אם אני אלחץ על Tab הוא יציע לי את הקובץ.

עכשיו בעצם יש לי את הקובץ הזה והוא במצב של staging, שהוא מוכן לעשות לו commit. כמו שזה נשמע, מוכן להתחייב עליו.

אז אני אתחייב על הקובץ הזה: `git commit -m`, לתת את ההערה של מה עשיתי פה. אז אני ארשום `added new file for class example`.

ואם אני אעשה עוד פעם `git status`, אז אתם יכולים לראות שיש לי commit, שה-commit הזה הוא לפני ה-`main`. בעצם מה זה ה-main? ה-main שנמצא ב-client עצמו, נמצא ב-remote.

בעצם יש לי commit אחד שהוא מתקדם יותר מה-remote הזה, ואני יכול לדחוף אותו. אני לא הולך לדחוף אותו כי זה לא מה שאנחנו עושים פה.

ברגע שאני אדחוף, אז הוא יופיע לשם. אז ככה עובדים בגדול עם Git.

אתם אל תעשו את זה לתוך ה-repository שלי, כי זה ה-repository של הלימודים, אתם רק תיקחו ממנו.

ומה הכוונה רק שתקחו ממנו? אז אני אסביר. בואו דבר ראשון נמחק את ה-commit הזה, אז `git reset`.

עכשיו חזרנו ל-commit הקודם. איך אני רואה באיזה commit אני נמצא? אני יכול להשתמש ב-`git log`, ו-`git log` יראה לי את ה-commits.

כרגע אנחנו נמצאים אחרי merge שעשיתי ל-`lesson2` ל-`main`.

אבל אנחנו ב-`lesson0`. אז אם אני רוצה לקבל את כל מה שהתעדכן בין שיעור לשיעור, אז אני רוצה לעשות כזה דבר. אני רוצה לעשות:

`git fetch --all --prune`

ואני אסביר בדיוק מה זה אומר. `git fetch` מביא לי את כל המידע שהתעדכן בכל ה-repositories האחרים, בעצם מעדכן את ה-metadata, את כל המידע של Git שנמצא אצלי, והמידע של Git שנמצא ב-client.

ברגע שאני אעשה את זה, אז אני אהיה מעודכן מבחינת ה-remote יותר נכון.

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

אתם עכשיו מבקשים מהמחשב שלכם למשוך את כל המידע שהתעדכן ב-remote: `git fetch`.

`--all` זה כל המידע, ו-`--prune` אומר שאם יש מידע שנמחק והוא כבר לא רלוונטי ל-metadata, המידע שמייצג את המידע, אז הוא ינקה אותו. זאת אומרת שאם היה איזשהו קובץ שנמחק וכבר לא מעניין, אז בעצם כשאני אעשה `--prune`, שזה לנקות, אז הוא ינקה אותו.

ואם אני רוצה לעבור ל-branch, אז איך עובד Git? אני יוצר branch, אני כותב ב-branch את הקוד שבו אני משתמש, את הקוד שאותו אני רוצה לעדכן, ואז אני דוחף אותו בחזרה ל-main.

אם אני רוצה לעבור ל-branch של השיעור הראשון, אז אני עושה `git checkout`, הוא מעביר אותי ל-branch.

ואז יש לי השלמות. `lesson1` רשמתי עם L גדולה לצערי. אז אני עושה... גם `lesson0` עשיתי עם זה. אז `lesson0`, ואז אני יכול לעבור לשם ויהיה לי את המידע של `lesson0`.

אוקיי, עכשיו אני אעבור ל-repository השני, זה היה רק לדוגמה, ואני גם אמחק אותו.

`rm -rf class_test1`

זה ימחק לי את כל התיקייה ואת כל ה-..

אם אני איכנס ל-`bare_metal_programming`, ואני יכול לעבור ממנו שוב ל-`lesson0`, לשיעור הראשון, שזה השיעור שאנחנו נמצאים בו עכשיו.

בעצם יש לנו שני קבצים שנקראים באותו השם, אחד מהם הוא `lesson0`, ואחד מהם הוא השם של ה-branch שנקרא `lesson0`. ו-`checkout` זה גם פעולה שעושים על קבצים.

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

אז `git clone -b` ישר לתוך ה-branch. `-b` זה ישר להיכנס לתוך ה-branch עצמו. זה ה-URL שאנחנו הולכים להשתמש בו.

בסוף נקרא לזה בשם אחר: `class1`.

בסדר גמור. עכשיו אם אני איכנס לתוך `class1`, שימו לב שאני לתוך `lesson0` והבעיה נפתרה.

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

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

סבבה, אז איך אני יודע שיש לי את ה-Git מותקן כמו שצריך אגב? לא דיברנו על זה:

`git --version`

נותן את הגרסה של Git שהתקנתי, ובעצם זה הגרסה הזאתי ל-Windows.

## GCC Installation & Toolchain Setup

נמשיך הלאה. בעצם אנחנו הולכים עכשיו להוריד את ה-toolchain. מה זה toolchain?

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

אנחנו הולכים להתקין toolchain ל-Windows.

Windows, שנקרא MinGW.

ה-toolchain עצמו מכיל גם את ה-GCC שזה ה-GNU C Compiler, גנו C compiler, גם את ה-GDB שזה ה-GNU Debugger. אמרתי פעמיים גנו, אז אני אגיד... סליחה, אני אגיד מה זה גנו. גנו זו איזושהי קבוצה של מהנדסים שמפתחים open source. הם התחילו לפתח ל-Unix בעצם לפני שליינוס יצר את Linux. הם אלה שפיתחו, אלה שמתחזקים את ה-compiler של C הנוכחי, את ה-GCC. יש גם קומפיילרים מתחרים כמו Clang ועוד כאלה, אבל זה לא ממש, כבר off-topic לקורס הזה.

בתוך ה-toolchain הזה שנתקין, אז יהיה לנו את ה-GDB, את ה-GCC, בעצם גם קומפיילר של C++ שנקרא G++. יהיה לנו linker, שאנחנו נדבר על התהליך של קומפילציה בשיעור הבא, במיוחד קומפילציה ספציפית ל-embedded ובעצם אפילו ספציפית למיקרו-קונטרולרים.

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

ברגע שתלחצו על זה, זה יוריד לכם אותו. זה בעצם איזשהו tar file. בתוך ה-tar file הזה יש לנו איזשהו קובץ 7z שאותו אנחנו נפתח לתוך תיקייה שנקראת `C:\mingw64`, בסדר? הקומפיילר הזה הוא גרסת ה-GCC החדשה ביותר, GCC 14.2. למה זה מעניין אותנו להשתמש בגרסה החדשה ביותר? כמה סיבות: גם לקומפיילרים יש באגים, וגם ה-toolchain עצמו הוא מעודכן. אז אם אנחנו מדברים על ה-linker, בעצם מה שמחבר לנו את כל האובייקטים בעצם לבינארי בסוף, אז גם הוא פה מעודכן לגרסה מאוד חדשה. אנחנו מקבלים גם Python 3.12, לא יודע אם הייתי בוחר להשתמש ב-Python שמגיע דרך ה-toolchain הזה, אלא הייתי מתקין ישירות. יש לנו גם GDB חדש ועוד כל מיני features שאנחנו מקבלים.

בינתיים זה סיים לרדת, ואנחנו נפתח אותו. זאת תיקיית ה-Downloads שלי, ובעצם אני אעשה Extract לתוך תיקייה שממנה אני הולך להעתיק ל-`C:\mingw64`, אוקיי? אחרי שאנחנו נעשה את זה, אז אנחנו גם נגדיר את הקומפיילר להיות בתוך ה-PATH של ה-Windows, זאת אומרת שנוכל לגשת אליו מכל מקום.

## התקנה ב-Linux

מי שעובד עם Linux, אז `sudo apt-get install build-essential` אם אנחנו עובדים ב-Ubuntu. זאת הפקודה שנמצאת כאן. בעצם הוא נותן לי גם C++, גם Make, הוא נותן לי בעצם איזשהו toolchain בסיסי. הוא לא ייתן לי GCC 14, וזה גם תלוי במערכת ההפעלה שלכם. אם מערכת ההפעלה שלכם יודעת לתמוך ב-GCC 14 ב-package manager, אז אתם יכולים. אם לא, אתם יכולים לבנות את זה מ-source. זה מאוד פשוט, רק שזה קצת ריקורסיבי. צריכים איזשהו GCC ספציפי כדי שיהיה לכם GCC.

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

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

עשיתי Extraction לתיקייה הזאת, אני פשוט מעתיק אותה, Ctrl+C, ומדביק אותה בתוך המקום שבו אני רוצה. אצלי זה ב-`C:\`, אני ממליץ גם שזה יהיה פה ב-`C:\` כדי שיהיה הרבה יותר קל. אז אחרי שעשיתי את ההעתקה, אני נכנס לתוך התיקייה עצמה. יש לי פה הרבה מאוד תיקיות, ויש לי את התיקייה של ה-binaries, בעצם קובצי הרצה. אז כל ה-toolchain שאני משתמש בו נמצא כאן.

אני מקבל את ה-C++ (שזה בעצם G++), את ה-GCC, יש לי את ה-`gcc-nm` שהוא נותן לי את האפשרות לדעת ממה בנוי כל קובץ, `elfedit` שאני לא זוכר כרגע מה זה, `as` שזה assembly, `gdb` שזה ה-debugger שאני יכול להשתמש בו, `ld` שזה ה-linker, ועוד הרבה מאוד... `readelf` נותן לי את המידע על ה-binaries שאני רוצה (נעשה את זה גם בשיעור הבא שאנחנו נדבר קצת על disassembly ועל הכול), וכן הלאה וכן הלאה. אז זה כל מה שנמצא כאן.

## עדכון משתני הסביבה (PATH)

ועכשיו אני רוצה שה-Windows שלי יכיר את זה מכל מקום. אם אני עושה כאן CMD, אוקיי, אז נניח אני נמצא בתוך `mingw64\bin` ואני אעשה `gcc.exe`, כי אני מדבר על הקובץ הרצה הישיר, ואני אעשה `--version`, אני יכול לראות שהגרסה שמותקנת לי היא 14.2.0. אבל אם אני נמצא בתיקייה אחרת, אני לא רוצה כל פעם לכוון לתיקייה הזאתי כדי שאוכל לגשת ולהתקין. אז בשביל זה מה שאני אעשה, אני בעצם אגדיר את ה-GCC בתוך ה-PATH של ה-Windows.

מה הכוונה? אני אראה לכם עכשיו. את זה אני כן צריך. עשינו את ההתקנה, עשינו את ההעתקה, אז עכשיו בואו נפתח את ה-System Properties, Advanced ו-Environment Variables אם אתם ב-Windows.

אם אתם ב-Linux, יש פקודה של GCC שמוסיפים את זה ל-PATH, או מה שאתם יכולים לעשות זה symbolic link. symbolic link לזה, ואם אתם ב-Ubuntu יחסית חדש, אז יש ממש פקודה של `essential-tools`, חפשו `essential-tools` ו-GCC, ואתם יכולים להגדיר באמצעותה את ה... כמעט ב... כאילו עם איזשהו טרמינל, איזה קומפיילר... איזה גרסת קומפיילר תהיה גרסת הקומפיילר הדיפולטיבית, במקום שתצטרכו לעשות `gcc-14` כדי להגיע ל-GCC 14, תוכלו לעשות פשוט `gcc`. זה ממש אינטראקטיבי. אם לא, אז symbolic link: `ln -s` GCC 14 וה-PATH שלו איפה שהתקנתם את זה, ואז אחר כך אתם צריכים לעשות GCC, אז יצא לכם ה-symbolic link. אם אתם מסתבכים, למרות שאני לא יודע אם מישהו מכם עם Linux כי לא שמעתי, אם אתם מסתבכים, תעדכנו אותי ונסדק.

אז מה אנחנו עושים עכשיו? אנחנו הולכים ל-Environment Variables של ה-Windows. אנחנו יכולים לרשום Advanced, ואנחנו יכולים גם לעשות Edit system environment variables, ואז הוא נותן לי את האפשרות ללכת ישירות לזה. Edit system environment variables, אז הוא פותח לי את החלון הזה, ומתוכו יש לי את ה-Environment Variables. ופה ב-PATH אני רוצה לעדכן. אז אני אלחץ על PATH, דאבל קליק, ואתם רואים, ואני אוסיף ככה בצורה הזאתי: `C:\mingw64\bin`, שזה בדיוק המקום הזה. בסדר?

אחרי שאני אעשה את זה, אני פשוט לוחץ על OK, ו-OK, ו-OK. ואז אני ארצה לבדוק שזה עובד. אז איך אני ארצה לבדוק שזה עובד? אז אני אעשה או מקש חלונות+R, או פשוט CMD או Terminal, whatever, ואני אעשה `gcc`. אז `gcc --version`, ואני רואה שזה עובד.

זה השלב שבו אנחנו נעצור. נעשה הפסקה של בעצם חמש דקות, לעשות קצת פלאשינג, לקום, בעצם להוציא את הפרצוף מהמסך קצת. מישהו נתקע, לא מסתדר לו, לא עובד לו ה... אל תשכחו שצריך גם לעשות reboot או reset ל-Windows, בסדר?

מישהו עוקב?

**תלמיד:** כן, כן, אני עוקב. יש לי שאלות... בקשר לסביבה, אחרי שהורדנו את הקובץ, אני מריץ את זה מתוך ה-Visual Studio Code. השאלה אם אני רוצה להריץ את זה מתוך ה-STM32Cube... כי STM32Cube בעצם משחזר לי את כל ההגדרות של Eclipse לצורך העניין.

**מרצה:** בשביל אפליקציות Windows, בעצם אלה שיהיו דוגמאות של C, אתה לא צריך. אם אתה יודע לעבוד עם הקומפיילר ישירות ולרנדר, סבבא. מה שנוח ב-STM32Cube בעצם, שוב, וזאת אחת הסיבות שהוא מבוסס Eclipse, זה שאנחנו לא צריכים לבנות Makefiles, ואנחנו לא צריכים לעשות כלום. הוא בעצם מג'נרט לנו את כל ה-Makefiles ואת הכול. זה יתרון. חיסרון - זה שהוא פשוט מייצר לנו מלא קבצים שאי אפשר לדעת גם מה צריך ומה לא. אז אתם תסתכלו בעצם שב-Git אני דוחף מלא קבצים שנגיד תגידו, כאילו "למה הוא זורק לנו מלא קבצים, קבצי זבל?". זה כי לנסות לנקות אותם מביא כאב ראש גדול, אז פשוט אני דוחף הרבה קבצים לשם.

**תלמיד:** אז מה עדיף להשתמש? ב-Visual Studio Code, שנגיע כבר עם ה-GCC, ונתקין לך את ה-extension, ואז הוא מייצר לך רק קובץ executable?

**מרצה:** תשמע, לקורס, כדי שיהיה לך יותר קל לעקוב ולא תצטרך תוך כדי שאני מדבר להתחיל לנסות כל מיני זה, תתקין את ה-STM32CubeIDE, אני גם מראה איך לעשות את זה. לחיים עצמם, גם אני לא עובד עם STM32CubeIDE. בפרויקטים שכן עבדתי עם זה, אז IAR, שזה איזשהו סביבת debugging מאוד מוכרת, היא בתשלום אבל היא מאוד נוחה, או סביבות אחרות, סביבות Eclipse אחרות, וכן סבלתי מזה. אבל אין מה לעשות, זאת בעצם האינטגרציה הכי טובה של STM עם ה-STM32Cube, שזה מוצר שלהם, אז סובלים.

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

יכול להיות שאפשר גם עם איזשהו... עם איזשהו, איך זה נקרא? עם איזשהו extension, שהאמת שאני לא מכיר אותו כל כך, אבל יש extension. ממה ששמעתי נגיד ל... שעבדנו עם Silicon לא היה extension נורמלי. גם לא היה extension נורמלי ל-IAR, זה גם לא היה פה. אז יכול להיות שיש איזשהו extension של STM32. אני לא יודע אם הוא שמח כמו STM32Cube, אז אני לא, אפילו לא חקרתי. אבל יש להם extension שלהם. אני מניח שבסופו של דבר הוא מייצר את אותם הקבצים.

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

טוב, נעשה עצירה קטנה, אז ב-8:19 אנחנו נחזור, סבבה?

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

כן, אז אני ממשיך. בעצם אז התקנו את MinGW, התקנו את Git, עכשיו נשארה לנו ההתקנה הקשה ביותר: STM32CubeIDE.

STM32CubeIDE זה בעצם סביבת הפיתוח שמבוססת Eclipse, כמו שכבר אמרנו. בעצם, הסביבה הזאת יש לה את האינטגרציה הטובה ביותר עם גמי המיקרו-בקר (MCU) וגם עם כל מיני add-ons שבעצם פיתחו ST עבור הסביבה הזאת. זאת הסביבה הרשמית, ונראה עכשיו איך מתקינים את זה.

אז שוב, הלינקים נמצאים ב... אז אנחנו לוחצים על הלינק ואנחנו יורדים למטה, אז יש לנו את האפשרויות להתקין. כל אחד ב-OS distribution שלו, Debian או Windows, אז אנחנו בעצם נלחץ על Get Latest.

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

אם זה לא קרה, עוד פעם... הנה, זה קרה. בסדר? אז הוא מוריד לכם את הקובץ עצמו. הקובץ עצמו הולך לתוך Downloads, עושים לו Extract Here, כמו שעשינו מקודם. עושים לו Extract, ואז מגיעים לדבר הזה כאן.

לוחצים על הקובץ ועושים את ההתקנה. כן, אני רוצה להתקין שוב לשם ההדגמה. שוב, Agree, Agree, בוחרים את המיקום שלו. פה אני מסמן את שניהם, אם זה לא מסומן. אתם רואים שהוא צריך 3.5 גיגה, ואז עושים Install. זה לוקח לו איזה דקה, ובסופו של דבר יש לי את ה-STM32.

## STM32CubeIDE

איך אני משתמש ב-STM32CubeIDE? אז אני רושם STM32CubeIDE, ואז לוקח לו איזה שנייה לעלות. אתם רואים שהוא בעצם של ST. ופה אני בוחר את ה-workspace עצמו.

מה זה ה-workspace? ה-workspace זה בעצם יהיה ה-lesson שאני משתמש בו. אז בואו נראה, אם אני בתוך class 1, lesson 1, בואו נפתח את lesson 1 של ה-class הנוכחי. יש לנו Hello World, שעוד שנייה אנחנו נעשה חדש, ו-lesson 1. אז בעצם בוחרים את התיקייה הזאת ועושים Launch. ונותנים לו איזושהי שנייה וזה עולה.

אז זה בעצם סביבת הפיתוח. עכשיו אנחנו נעבור למצב שבו אנחנו רואים את שניהם.

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

את זה אנחנו יכולים לסגור. אנחנו צריכים לעשות Import לסביבה עצמה. איך אני עושה Import? אז אני בעצם עושה Import כאן, ואני אחר כך בוחר Existing Projects into Workspace. אני לוחץ Next, בוחר את ה-workspace שלי. סליחה, ה-workspace עצמו הוא אותה תיקייה. אני מוודא שהכול פה מסומן כמו שצריך. אז יש לנו את ה-workspace של lesson 1. מסמן אותו גם, כדי לדעת מה ה-metadata שהוא קורא פה.

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

ואני ארצה שנעשה פרויקט של Hello World. אז ניצור פרויקט חדש. נבחר בכאן, או שאני יכול לעשות פה New, או בכל מקום שאתם רואים New. אז C/C++ Project, נבחר ב-C Managed Build, בעצם שהוא ינהל את זה כ-C על דעת עצמו, ונמצא לזה איזה שם. בואו נחשוב על שם מאוד מיוחד, אז hello_world.

ופה אני צריך לבחור ב-MinGW GCC. שימו לב שיש לו עוד toolchain שהוא מצפה לו, וזה ה-toolchain שמגיע עם ה-MCU. אז לא לבחור ב-Cross Compilation Toolchain. בעצם Cross Compilation Toolchain זה toolchain שנותן לי במכונה של x86 או איזושהי ארכיטקטורה אחרת לקמפל קוד שהוא מתאים לארכיטקטורה שאליה אני הולך, אם זה ARM. ואני גם אסביר קצת על ארכיטקטורות בהמשך, אז ARM GNU בלי fixed floating point unit או בלי MPU. אז יש להם כל מיני צורות שבהן שככה אנחנו מסבירים מה זה כל ארכיטקטורה.

אבל אנחנו כרגע עובדים על ה-Windows. בשיעור הבא אנחנו נעשה Hello World מה-MCU עצמו, אבל כרגע אנחנו עושים את ה-alignment הזה קצת ל-C, ונמשיך על פי זה.

אז MinGW GCC זה ה-toolchain שאני בוחר.

אז ג'ונרט לי אוטומטית קוד של Hello World. אז בואו נדבר קצת על מה קורה פה. יש לי את ה-Standard Input Output שממנו אני מקבל את putc או printf או whatever, מה שצריך, מה שאנחנו רוצים, וזה בעצם מדפיס לי Hello World from Bare Metal Class.

ואחר כך יש לי את stdlib.h שזה ה-Standard Library, וממנו אני מקבל בעצם את המאקרו הזה שהוא EXIT_SUCCESS. אם אני לוחץ על Ctrl ועליו, אז אני יכול לראות את ה-defines. בעצם בשביל זה הייתי צריך את ה-stdlib.h, ואת ה-stdio.h אני מקבל מ-stdio.h. Standard Input Output אני מקבל את puts. אני לא יודע אם יצא לכם לעבוד עם printf, זה אותו דבר בגדול, כולם משתמשים באותם בספריות שבעצם יש להן ראפרים של glibc, אנחנו עוד ניכנס לזה בקורס הזה.

סבבה. עכשיו איך אני מקמפל את זה? אז אני לוחץ פה ימני, ואז אני עושה Build Project. יש עוד אפשרות עם Ctrl+B.

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

אז אני רואה שהוא עושה gcc, שזה הקומפיילר עצמו שהוא צריך, שהוא דאונלד, -O0, שזה ה-optimization level, -g3, שזה רמת הסימבולים שהוא חושף ל-debugger, -Wall, שזה warnings as errors, -c, זה אומר שאנחנו לא מקמפלים עם main, רק מייצרים קובץ object, ו-fmessage-length... לא זוכר מה זה, -o שזה תייצר לי את זה לסוג של קובץ object שנמצא תחת source, והקובץ עצמו נקרא hello_world, והקבצים שהוא משתמש בהם זה הקבצים שנמצאים בתיקייה שהיא לא התיקייה הנוכחית, התיקייה הקודמת, ב-Source, hello_world.c, שזה בעצם הקובץ הזה.

ואחר כך אנחנו עושים בעצם את התהליך של ה-linking, אז gcc -o, שזה אומר ה-output, hello_world, ואחר כך אנחנו משתמשים ב-hello_world.o, שזה ה-object. אין צורך להתעמק בזה, בשיעור הבא אנחנו נכנסים בתהליך של הקומפילציה, ובמיוחד ל-MCU שלנו, בפירוט.

אז אחרי שקימפלנו את זה, אני רוצה בעצם להדפיס ולראות שהכול עבד. אני עושה זה, ואז אני נזכר ואז אני אומר: רגע, מה קורה פה? לא ככה זה עובד, אז בשביל זה אני הולך לכאן ואני מקנפג את הקובץ קונפיגורציה, או אפשרות הרבה יותר קלה: ימני, Run As, Local C/C++ Application.

והנה, זה ה-terminal שלנו: Hello World from Bare Metal Class! שזה אנחנו.

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

ועכשיו אנחנו נתחיל לעבור על Basic Data Types.

## Basic Data Types

Basic Data Types, בעצם אני אפתח את הדוגמה על הדרך. Basic Data Types...

## Basic Data Types

זה הגדלים הפרימיטיביים של data שבהם התוכנית שלנו משתמשת, וה-compiler יודע לזהות ולהמיר אותם לגדלים האלה בזיכרון.

יש לנו char. char זה בעצם איזשהו משתנה בגודל של byte אחד, שזה 8 bit, והוא יכול להכיל בתוכו תווים. התווים עצמם מיוצגים ב-ASCII, והגודל של התווים הוא מ- -128, אם אנחנו מדברים בצורה של signed, עד 127, או ב-unsigned, שזה ללא סימן, 0 עד 255.

אחר כך יש לנו short, ש-short הוא יותר גדול. למה אני לא אומר את הגודל הספציפי? char בכל מקום הוא byte אחד, אבל short יכול להשתנות, או יותר נכון int יכול להשתנות.

אז short לרוב ובמערכות של 32 bit, אז short בעצם יהיה 2 בתים, זה אומר 16 bit. אז מ-0 עד 2 בחזקת 16 פחות 1 אם אנחנו unsigned. אם אנחנו signed, אז אנחנו מ- -32,768 עד 32,767, שזה בעצם מ-מינוס המספר הזה עד 0 פלוס המספר הזה, זה בעצם יוצא לנו פעמיים המספר שרצינו.

אחר כך יש לנו int. int בעצם מייצג את הצורה ה-native שבה אנחנו שומרים מספרים, בעצם הוא מייצג את הגודל של מילה בזיכרון. מה זה מילה? מילה זו הצורה ה-native שבה אנחנו משתמשים. אם אנחנו במערכת של 32 bit, אז מילה תהיה 32 bit, בעצם זה יהיה גם הגודל של ה-int.

במקרה שלנו, אנחנו בעצם נהיה מ-מינוס המספר הזה עד המספר הזה, ואם אנחנו unsigned, אז 0 עד 2 בחזקת 32 פחות 1, זה הגודל שלו.

long. למה long בקומפיילרים שמקמפלים ל-32 bit הוא אותו גודל של int? כי אין לנו צורך בעצם להגדיל אותו. גם long long יהיה באותו גודל של 4 בתים, כי אנחנו לא יכולים, אין לנו בעצם איזושהי צורה לשלוט עליו. אז אותו דבר כמו int, גם long long.

float. single precision, בעצם התצורה של IEEE לשמור data שהוא float. ב-embedded אנחנו לרוב לא משתמשים ב-float, וב-bare metal במיוחד אנחנו לא משתמשים ב-float, ומן הסתם לא ב-double, כי אנחנו משתמשים בגודל שהוא שלם, ואת הנקודה העשרונית אם צריך, אנחנו גוזרים מהמספר עצמו. אז אם יש לי מספר, חלק ממנו אני מחלק להיות הנקודה העשרונית וחלק לא. אם אני משתמש ב-2 בתים, זה עדיין יותר יעיל לי מאשר לעבוד עם float.

מה שגם, להרבה מאוד מערכות embedded אין Floating Point Unit, בעצם איזשהו hardware שהוא baked in, והחומרה הזאת נותנת לי לעשות פעולות על float בצורה מהירה. כי אם לא, פעולות על float זה משהו שלוקח הרבה מאוד זמן יחסית. Floating Point Unit זה משהו שאין בהרבה. ה-MCU הראשון שיש בו Floating Point Unit זה ה-ARM Cortex-M4, המשפחה הזאת. ל-M3 אין, ל-M0 גם כן אין, ל-M0+ גם כן אין. אז אנחנו לא נעבוד עם float הרבה, אלא אם כן יש משהו ספציפי שאתם צריכים.

למה זה בעצם משנה השימוש הנכון בגדלים? אמרנו שלמיקרו-קונטרולרים מסוג 8 bit אין הרבה זיכרון. גם למיקרו-קונטרולרים מסוג 32 bit, למערכות של היום, אין הרבה זיכרון. אז אנחנו צריכים להיות מאוד מדויקים ב-data types שאנחנו בוחרים, כדי שלא נזלול סתם זיכרון ואז נגיע למצב שאנחנו צריכים עוד external RAM, עוד רכיבים של external RAM כדי שנוכל ניגש לעוד מרחב כתובות, או שייגמר לנו הזיכרון ואנחנו לא יכולים לפתח features כי היינו חזירים בהתחלה ואנחנו לא יודעים מאיפה לקצץ עכשיו כי אין זמן. זה בעצם מה שקורה בהרבה מאוד פרויקטים.

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

עוד שנייה נדבר על גדלים שהם מוגדרים היטב. אבל שתדעו, גדלים בוליאניים אנחנו משתמשים במשתנה שהוא מסוג char כדי לעבוד איתם. אין בעצם מימוש לבוליאני ב-C. אם תעשו include ל-stdbool.h, תיכנסו לתוך הספריה עצמה, תראו שכל מה שיש כאן זה בעצם true שווה ל-1 ו-false שווה ל-0, ואנחנו עושים הגדרה ש-bool שווה ל-_Bool, ובגדול uint8_t, שזה char בגדול, זה הגודל שאנחנו משתמשים בו. אז אם אתם רוצים להשתמש ב-stdbool בשביל הקריאות, סבבה. זה יכול ליצור בעיות. אני פעם הייתי מאוד מדייק בזה וכזה אמרתי "אוקיי, אני אשתמש ב-bool איפה שאני רוצה שזה יהיה bool", אבל היום אני כבר משתמש ב-uint8_t, ובמערכות שאני רוצה שזה יהיה באמת מהיר אז אני משתמש ישירות בצורה ה-native-ית, אבל אנחנו נדבר על זה בשיעור הבא.

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

אם אתם משתמשים בגדלים מאוד גדולים, אתם יכולים לבזבז זיכרון, ואפילו יותר מזה, יכול להיות שאתם מבזבזים CPU cycles. מה זאת אומרת מבזבזים CPU cycles? זאת אומרת שעכשיו אני משתמש בגודל שהוא גדול יותר, אני משתמש ב-4 בתים ומתוכם אני צריך רק חלק אחד. אז יכול להיות שבמקום פשוט לטעון את הגודל שאני רוצה לזיכרון בפעולה אחת, אני אשתמש בשתי פעולות assembly. נראה את זה בשיעור הבא.

אז בואו נסתכל על דוגמה פה שעשיתי. יש לי פה איזושהי תוכנית, אני בעצם מגדיר int, אני מגדיר float, יש לי גם double. שימו לב שאם אני מגדיר float ואני רוצה שיהיה float אז אני צריך לשים f בסוף, ואני מגדיר char של letter. לכל אחד מהם יש איזשהו print specifier, בעצם מה שעושה לי את ה-formatting מהסוג של המשתנה ל-string, לתצורה שבה אני יכול לקרוא.

אז %d עושה לי את ההמרה מ-int ל-string. %2f בעצם נותן לי רק שתי נקודות אחרי הספרה. %lf אני משתמש כשאני רוצה לעבוד עם double, ו-%c ל-char.

בואו נריץ את זה שנייה ונראה שאנחנו שליטים בזה. אז Clean Project אם יש פרויקט שהוא קיים. אחר כך אני רוצה לעשות Build, וכדי להריץ שוב אני הולך לכאן, Run As, Local C/C++ Application.

מה זה בעצם n\? n\ זה ירידת שורה, אבל לא רק. כאשר עובדים עם buffering I/O, בעצם איזשהו I/O שזה המימוש של printf, לפחות ב-Linux וכרגע גם ב-Windows, וכשנדבר על ה-STM אנחנו נראה מה זו הספריה הסטנדרטית.

אז הספריה הסטנדרטית, glibc או libc, נותנת לי את printf ונותנת לי feature שנקרא buffering I/O. מה זה ה-feature הזה? במקום שאני כל פעם אכתוב לדיסק ואבזבז זמן, כי כתיבה לדיסק זה משהו שלוקח זמן, אז הוא עושה לי buffering. ומתי אני עושה flush ל-buffer הזה? כל n\, או כאשר ה-buffer מסתיים. לכן אם אנחנו נרצה לראות כל שורה בנפרד, אנחנו חייבים להשתמש ב-n\ ב-C. אם אנחנו לא משתמשים ב-n\ ב-C, יכול להיות שזה יקרה ויכול להיות שלא. אז best practice בעצם כל סוף שורה לעשות n\.

## Fixed-Width Integers & Limits

מה זה בעצם Fixed-Width Integers & Limits? במצגת הקודמת דיברנו על גדלים, ואם אנחנו רוצים לדבר על גדלים בצורה explicitly, בצורה ברורה, אנחנו נרצה לדבר על גדלים שבהם אנחנו גם מגדירים את מספר הביטים שאנחנו משתמשים בהם. למה זה? בדיוק מהסיבה שאמרנו. אמרנו ש-int מגדיר את המילה ה-native-ית שבה משתמש ה-CPU. בעצם ה-compiler יודע להתאים את זה ל-CPU הספציפי. אז אם אני אשתמש ב-int במקום אחד, ואני אשתמש ב-int במקום אחר — אשתמש ב-int על המחשב PC שלי ולעומת זאת אני אשתמש ב-int על המיקרו-קונטרולר — יש שני גדלים שונים לגמרי. ופה מגיעות בעיות.

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

יש לנו את הגדלים שנראים ככה: int8_t, שזה בעצם אומר שזה signed char. זאת אומרת שאנחנו משתמשים ב-char בצורה שהיא signed, מ- -128 עד 127. ברגע שאני מצהיר על משתנה מסוג int8_t, אני אתפוס 8 בתים בזיכרון והם ייוצגו בצורה עם סימן, signed.

אותו דבר יש לנו את ה-unsigned, אז מ-0 עד זה, וככה זה תמיד מוגדר וזה גם הרבה יותר קריא. יש אנשים שאפילו מגדלים לעשות ועושים typedef — ואנחנו נדבר על typedef בהמשך — עושים בעצם הגדרה שכל int8_t נקרא S8, וכל uint8_t נקרא U8. אז כרגע אנחנו מצהירים על משתנה מסוג int8_t, והשם שלו הוא int8var בצורה הזאתי, והשמה שלו, אז אנחנו משתמשים בספריה שנקראת limits. וב-limits שמה מוגדרים כל הגדלים המקסימליים והמינימליים של כל אחד מהגדלים בכללי.

אז בואו שנייה ניכנס לכאן. הנה, אנחנו מדברים על int8_t אז מוגדר הגודל הזה, אותו דבר כאן. אם אנחנו מדברים על unsigned, אז זה הגודל שמוגדר לנו. וכאן אנחנו רואים שגם מוגדר לנו גודל מקסימלי של 32, אבל בבסיס הקסדצימלי. אם אני מתחיל מספר עם 0x אז הוא בהקסדצימלי, שזה בסיס 16.

אחר כך אנחנו עוברים לדבר על uint16_t. uint16_t זה בדיוק אותו דבר כמו uint8_t, אז זה תמיד 16 bit, זה יהיה גם short במקרה שלנו. ואותו דבר אני יכול להתחיל אותו ככה.

ו-32 גם כן מוגדר באותה צורה, ויש לנו אפילו 64 bit. בעצם 64 bit מוגדר — ונלחץ על זה כאן — הוא מוגדר בעצם איזשהו extension ספציפי של MinGW, שזה unsigned long long, שזה אומר בלי סימן והוא לוקח 64. אם אני אשתמש בספריה הזאתי של limits, ל-STM32 ההגדרה תהיה שונה ובעצם ה-uint64_t יהיה מוגדר במקום אחר.

יצרנו פה איזושהי תוכנית, שהתוכנית הזאתי מגדירה את כל הגדלים האלה, ואת הגדלים האלה אני ארצה להדפיס. איך אני מדפיס בעצם int8_t? אני מדפיס אותה באמצעות %d. כיוון שאין לי תצורה ספציפית להדפסה, יש %c אבל אז הוא ידפיס לי אותו כ-char, אני לא רוצה לראות את התצוגה ה-ASCII-ת שלו. כולם מכירים את טבלת ה-ASCII? אתם צריכים שאני אראה אותה?

לא בעל פה, אבל נשמח לראות.

אז בסדר גמור, אז בוא נפתח שנייה טבלת ASCII.

ASCII table — בעצם ASCII table אומרת שלכל מספר מ-0 עד... תלוי ב-ASCII, אם אנחנו מדברים ב-ASCII המורחב או לא, אבל אם אנחנו מדברים ב-ASCII הלא מורחב, אז מ-0 עד 127 יש תצוגה שהיא בעצם תצוגה צ'ארית (char-ית), בעצם יש לו תו שהוא זה.

אז אם אני אשים בתוך משתנה 48, אם אני אשים בתוך משתנה דצימלי 48 ואני אדפיס אותו בתצוגה הצ'ארית, אז יצא לי '0', מפתיע, נכון? אז זה בעצם ה-ASCII table. בעצם מה הסיבה שזה נקרא char? כי זה מה שהוא מייצג. אם יהיה לי מחרוזת, בעצם אם יהיה לי מערך של char-ים, בעצם הרבה char-ים ברצף, אז יהיה string, שזה מילה או יותר נכון מחרוזת של תווים.

אז זה ה-ASCII table, ושוב אם אני אשתמש ב-type specifier של `%c`, אז יודפס לי פה 127, ו-127 זה הסימן שמייצג DEL, שזה DELETE. אם אני אשתמש ב-0, אז יוצג לי null character, שזה `\0`, שזה גם מה שאומר שסיימתי string, אבל אנחנו קופצים פה קדימה.

אז זה ה-ASCII table, אתם יכולים לרשום פשוט ASCII table ותראו מלא רפרנסים של זה. אתם יכולים לראות גם את ה-ASCII table המורחב, שזה מ-0 עד 255. פשוט תרשמו extended ASCII table. לא רלוונטי כל כך, פשוט עובדים עם זה איך שזה.

אחר כך, אם אני עובד עם unsigned ואני ארצה להדפיס unsigned, אז כדי שאני אגיד לפורמטר של ה-printf (`printf` זה print format), לפורמטר של ה-printf אני רוצה להדפיס משתנה מהסוג הזה, ושזה יהיה באמת הגודל שאני חושב שנמצא שם ולא גודל עם סימן, אז אני צריך להשתמש ב-`%u`. אותו דבר גם אם אני מדפיס סתם איזשהו מספר, זה לא זה. אם אני מדפיס `int32_t`, אז אני משתמש עם `d`. ואם אני משתמש ב-long, אז אני משתמש ב-`ll`, ואם זה signed אז `d`, ואם זה ללא סימן, unsigned, אז `llu`.

עכשיו שוב, ננקה ונבנה את זה. ואנחנו נרצה גם להריץ. בנינו? כן. ואנחנו נרצה גם להריץ. אז אנחנו רואים שמוטפס לנו: `int8_t` הוא שווה ל-127, ו-`INT8_MAX` הוא שווה ל-127. `uint16_t` הוא שווה ל-65535, וגם המקסימום, כי עשינו את ההשמה למקסימום. אותו דבר גם אנחנו מדברים על `int32_t`, אז אתם רואים שזה עם סימן, וזה הגודל המקסימלי של `uint64_t`.

## Operators & Expressions

נעבור הלאה, ואנחנו נתחיל קצת להתקדם. בוא נדבר על אופרטורים ועל expressions.

בעצם יש לנו כמה סוגים של אופרטורים אריתמטיים שאנחנו משתמשים בהם. אז אופרטורים אריתמטיים מתמטיים אנחנו משתמשים ב-`+`, `-`, כפל (`*`), חילוק (`/`) ומודולו (`%`), שזה התוצאה של המודולו, שזה השארית, אופרטור השארית. איך אנחנו משתמשים בהם? אנחנו שמים אותם לפי התצורה, אם בגדול שניהם צריכים שני אופרנדים, אז אנחנו שמים אותם אחד ליד השני.

שימו לב שאם אנחנו עובדים ב-integer, אז בעצם אם אנחנו נעשה חילוק, תהיה לנו חילוק עם טרנקציה (truncation). זאת אומרת שאנחנו נעשה חילוק של `int`-ים, ואת החלק השברי אנחנו פשוט מעיפים, אנחנו חותכים אותו.

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

יש לנו את האופרטורים left shift (`<<`) ו-right shift (`>>`). בעצם משתמשים בהם הרבה כדי לעבוד עם ביט ספציפי או עם איזושהי קבוצה של ביטים ספציפיים, אנחנו בעצם מזיזים באמצעותם את הביטים ימינה ושמאלה, וככה משתמשים.

אז מה כל אחד מהסימנים האלה אומר? כי פה זה היה מאוד ברור. אז יש לנו את הסימן של ה-ampersand (`&`). ampersand הוא AND, AND ביטי, נסתכל עליו עוד רגע. יש לנו OR (`|`), שהוא OR ביטי. יש לנו XOR (`^`), שזה ה-caret sign או כובע. יש לנו את ה-tilde (`~`), שזה הגל, שהוא בעצם אומר NOT. יש לנו right shift (`>>`), שהוא מזיז לנו את הבייט ימינה, ו-left shift (`<<`), שהוא מזיז לנו את הבייט שמאלה. אנחנו נראה את זה בהדגמה עוד רגע.

אופרטורים לוגיים — אז יש לנו AND (`&&`), OR (`||`) ו-NOT (`!`), שזה NOT אחר מאשר ה-NOT הקודם. ה-NOT הזה אנחנו נקרא לו גג, בעצם הוא היפוך ביטי. זאת אומרת שאם אני עושה NOT לביט מסוים, אני לא רק עושה לו NOT, אני גם עושה לו NOT ביחס לגודל שבו הוא נמצא. אם אני עושה על 1 NOT, אז בעצם מה קורה? אני בעצם הופך את ה-1 הזה להיות 0, אבל כל שאר האפסים עד לגודל שהוא נייטיבלי (natively), עד ל-32 ביט אם זה מספר סתמי, אז הם הופכים להיות 1. אז שימו לב לזה ותהיו מודעים, כי זה בעצם מה שגורם לבאגים, ה-ideas האלה.

בואו נדבר על precedence, בעצם על הקדימויות. רגע רגע רגע, סליחה. לפני הכל, הרבה פעמים ב-embedded מאוד חשוב לנו כל עיבוד וכל סייקל של CPU, אנחנו רוצים לחסוך כמה שיותר. אז מה שאנחנו נעשה, אנחנו נשתמש ב-short circuit. מה זה short circuit? זה בעצם אומר שאם אני עושה OR והתנאי הראשון שלי הוא true, כל האוואלואציה (evaluation) של התנאי הלוגי הכולל תהיה true, ואני פשוט נכנס כבר לבפנים. אז לרוב את מה שהוא most likely, אני אשים ראשון.

אותו דבר עם AND. אם יש לי AND והתנאי הראשון של ה-AND הוא שלילי (false), אז כל שאר האוואלואציה של התנאי תהיה שלילית. ולכן אם אני יודע שזה הולך להיות AND ואני לא רוצה להיכנס לשם, אז אני אשים אותו בהתחלה. אז תהיו מודעים ל-short circuit, ותדעו שככה חוסכים פעולות. אם יש לי את האפשרות לשחק עם זה כדי שאני אגיע קודם כל ל-AND כדי להיות 100% false, אני אעשה את זה, או בעצם אם אני יכול להזיז את האופרטורים כדי להיות קודם כל עם OR כדי להיכנס 100% לתוך התנאי, אז אני אעשה את זה גם כן.

בואו נדבר על precedence. בעצם מה precedence עושה? הוא עוזר לנו לעשות אוואלואציה יותר נכונה ולדעת מה התנאים. בעצם אם אנחנו לא יודעים מה קורה לפני מה, אז אנחנו לא יודעים על מה לעבוד.

אז precedence עובד ככה: קודם כל עובדים האופרטורים של כפל, חילוק ומודולו, ויש להם קדימות על האופרטורים של חיבור וחיסור. עד פה, חוץ ממודולו, מה שלמדנו ביסודי. אחר כך יש לנו את האופרטורים של left shift ו-right shift, בעצם מגיעים אחרי חיבור וחיסור. ובסוף יש לנו אופרטורים של השמה ועוד. אם אתם רוצים באמת את כל הטבלה, אני יכול לשלוח לכם. אני רק אגיד שזה good practice לעבוד עם סוגריים, כדי שיהיה ברור לכולם למה אתם התכוונתם שיהיה קודם ולמה לא. ככה בעצם זה הופך את הקוד שלכם להרבה יותר קריא.

אז בואו נעבור פה שוב על הדוגמה ואני אדבר על מה שעשיתי כאן. אז יש לי פה שני משתנים, `a` ו-`b`. בעצם `a` מוגדר בצורה הבינארית הזאתי. אם אני עושה `0b` בהתחלה, זה בעצם אני מגדיר אותו בצורה בינארית. אז `10101010` זה 170 בדצימל. ו-`11001100` זה 204 בדצימל. ואנחנו עובדים עם `uint8_t`, זה אומר שאנחנו עובדים רק עם השמונה באייטים האלה, אין לי עוד באייטים שנמצאים ברקע. ברגע שאני אחבר את זה לתוך `int` כדי שלא יהיה לי overflow, אז אני אקבל את התוספת של שניהם שזה 374. אם אני אחסר בין `a` ל-`b`, אז אני אקבל תוצאה שלילית כי עבדתי עם סימן ב-`int`, שהיא מינוס 34... לא קריטי, זה כבר מתחיל להיות מאוחר.

מה קורה ברגע שאני עובד עם אופרטור של ביטים? אז AND, איך עובד AND? כל מקום שגם ב-`a` יש 1 וגם ב-`b` יש 1, יהיה בסופו של דבר 1. אז במקום הראשון יש לשניהם 0, אז יהיה 0. במקום השני יש רק ל-`a` 1, אז יהיה 0. במקום השלישי יש רק ל-`b` 1, אז יהיה 0. במקום הרביעי יש לשניהם 1, אז בעצם האוואלואציה הסופית תהיה 1. אותו דבר זה קורה עוד הפעם: `0` ו-`0` זה `0`, `0` ו-`1` זה גם כן `0`, `1` ו-`0` זה גם כן `0` ו-`1` ו-`1` זה `1`. אז זו התוצאה הסופית שאנחנו מצפים לה.

מה קורה כאשר נשתמש ב-OR? זה או זה 1 או זה. אז יהיה לנו 1 כאשר אחד משני הביטים הוא 1. אז אם יש לנו 0 ו-0, אז התוצאה הסופית היא 0. 1 ו-0 אז זה 1, 0 ו-1 אז גם כן זה 1, ו-1 ו-1 זה 1, ואותו דבר גם הלאה.

מה קורה כאשר עובדים עם XOR? XOR זה OR אקסקלוסיבי. זה אומר שרק אחד מכל האופרנדים שאני מחבר יכול להיות 1. אז בעצם אנחנו אומרים: 0 ו-0, אז בעצם אף אחד מהם, אז זה 0. 1 ו-0, אז רק ב-`a` יש לנו 1, אז יצא 1. 0 ו-1, אז רק ב-`b` יש לנו 1, יצא 1. ו-1 ו-1, אז יצא לנו 0. למה אנחנו משתמשים ב-XOR? הרבה פעמים משתמשים בו כדי להפוך את הביטים.

ואחר כך אנחנו מדברים על NOT. אז אתם זוכרים שאמרתי שאם אני משתמש ב-NOT, אז אני צריך לדעת מה הגודל שאני יוצא ממנו. כי אם זה מספר סתמי אז זה ה-natively של הזה. אם הייתי אומר עכשיו NOT 3, מה הייתה התוצאה? אז בעצם אני לא יכול לגמרי לדעת. אני ספציפית אמרתי לכם שהוא יקח 3, זאת אומרת שהוא ישים בביט הראשון ובביט השני אחדים וכל השאר יהיו אפסים עד ככה ל-32, וכשאני אעשה NOT אז הוא יפוך את כולם, אז יהיה לי `00` ואחדים עד הסוף. אבל זו לא התנהגות שהיא ברורה, ואנחנו לא משתמשים בזה הרבה פעמים. אז בעצם אנחנו מגדירים את הגודל, או שאנחנו משתמשים ב-const-ים. וב-const-ים, כשמשתמשים ב-const, ואנחנו נדבר על const, אז בעצם הגודל הוא מוגדר, לעומת `#define` ש-define זה מספר סתמי, לכן צריך לדעת להשתמש בזה גם כן נכון כשזה מקרו.

בעצם אז מה קורה כשאני עושה NOT? אז הוא הופך לי כל מקום שהיה 1 ל-0, וכל מקום שהיה 0 ל-1. אז יש לנו `0101`, אז הופך להיות `1010`, וגם בחצי הבייט הבא.

מה קורה כשמשתמשים ב-left shift? left shift הוא בעצם מזיז לי את כל הביטים אחד ימינה, או כמה מספר שאני אציין פה. אז אם `a` היה `01010101`, אז עכשיו הוא הופך להיות `00101010`, והמספר האחרון הוא מושמט. אם זה היה גודל יותר גדול, אז היינו ממשיכים ככה עד הגודל הבא.

shift left זה בעצם `a` בכפול 2 בחזקת 1. אם אני אעשה פה shift left עם 2, אז זה כפול 2 בחזקת 2. left shift עם 3, אז זה 2 בחזקת 3, אז זה `a * 2^3`. וזה אומר בעצם הזזה של 3 קנים.

right shift בעצם זה חלוקה ב-2, נכון? זה היה החזקה של 2. סליחה, זה הכפלה של 2? סורי, חבר'ה, מגיעים למגבלות השעה. אז בואו נראה איך אנחנו בודקים את עצמנו. נפתח את ה-calculator הזה, בעצם אנחנו נעשה את המספר... ניקח איזשהו מספר שאנחנו יודעים, ניקח 2, ונַעֲשֶׂה לו left shift ב...

2 left shift ב-2, יצא לנו 8. בעצם זה אומר שזה כפול 2 בחזקת 2, בסדר? אז בעצם 2 left shift ב-3, אז יצא לנו בעצם 16, שזה 2 כפול 2 בחזקת 3. בסדר? אז זה בעצם לגבי זה.

ועכשיו right shift. אז ניקח 16. 16 ונעשה לו right shift עם 2, אז אנחנו רואים שזה 4. בעצם אז אנחנו עושים חלקי 2 בחזקת 2, בסדר?

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

בוא נבנה את הפרויקט קודם כל. סליחה, ננקה את הפרויקט, נבנה אותו ונריץ, ונראה את מה שיצא בסוף.

אוקיי, אנחנו רואים בעצם את התוצאות. התוצאות כבר הן מזה קודם. סבבה.

## Storage Class Specifiers

Storage Class Specifiers ספציפיים שאנחנו רוצים לדבר עליהם, אוקיי? בעצם מה זה Storage Class Specifier? את ה-precedence אני אתן לכם לעבור עליו לבד, בעצם יש פה את ההסבר של מה קורה וזה. Storage Class Specifiers שאנחנו מדברים עליהם ספציפית, אוקיי? אז יש לנו כמה שאנחנו עובדים איתם.

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

מה קורה כשאני משתמש ב-static בתוך קובץ? זאת אומרת שרק מי שמוגדר בתוך הקובץ יכול לגשת למשתנה הזה. זאת אומרת שהמשתנה הוא גלובלי, אבל הוא ניתן לגישה רק בתוך הקובץ שהוא file אחד, אוקיי?

לאחר מכן, יש לי עוד משתנה שנקרא extern. אוקיי, extern. extern נותן לי אפשרות להשתמש בפונקציות שמוגדרות בקובצי C אחרים, ככה שאני לא משתמש ב-header file.

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

לאחר מכן אנחנו קוראים ל-callDebug. מה callDebug עושה? callDebug קורא ל-debugMessage. מה זה אומר? זאת אומרת שהוא משתמש בפונקציה סטטית. פונקציה סטטית היא קיימת רק בתוך הקובץ הזה. הפונקציה הזאת יש לה משתנה סטטי משלה. והמשתנה הסטטי הזה אז הוא כל פעם יתקדם. אז בפעם הראשונה זה יהיה 0, ואז נקדם אותו ל-1. בפעם השנייה שנקרא למשתנה הזה, אז הוא בעצם יהיה 1, ונקדם אותו ל-2. בפעם השלישית נקדם ל-3.

ועכשיו נעשה את הריצה ככה מהר. ואתם יכולים לראות את ההדפסות כמו שאמרתי שיהיו. 1, 1, ואז יש לנו את ההדפסות של ה-debug עצמו.

extern זה בעצם איזושהי פעולה שהיא באה לעזור לשלב של ה-linking.

## Decision Making in C

Decision Making in C, אוקיי? זה אני חושב שיהיה החלק האחרון שאנחנו נעשה להיום, ואתן לכם להשלים לבד. אז אנחנו עובדים ב-C, יש לנו את if, else if ו-else. אוקיי? אז בוא נעצים פה שנראה את ה-source code של זה.

אוקיי, אז בעצם יש לנו את האפשרות לעשות כמה החלטות בעצם על אותו משתנה. אפשר לעשות אותן בעצם עם if else. מה זאת אומרת? אז אם command שווה ל-0, או command שווה ל-1, או command שווה לזה, כאילו כל פעם אנחנו עושים את זה בצורה כזאת.

וגם יש לנו את האפשרות לעבוד עם switch. בעצם ב-switch אנחנו חייבים לתת case-ים. כל פעם שאני נכנס לתוך case, אז אני אכנס אליו, וצריך לעשות break. אם אני לא אעשה break, אז אני גם יעבור ל-case הבא. בסדר? זה האפשרויות עם switch-ים.

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

לעומת זאת, if-ים לא מוגדרים בצורה כזאת בזיכרון, והפעולה של ה-branching יכולה לקחת הרבה יותר זמן מאשר הפעולה של ה-switching. אז שימו לב שאם אתם יכולים לעבוד עם switch, תעבדו עם switch כי זה הרבה יותר מהיר. אם אתם עובדים עם if-ים, תנסו להעמיד כמה שפחות. אבל כמובן שיש עניינים שאי אפשר לעשות המרה מ-if-ים ישירות ל-switching, אוקיי?

את השיטה שבה זה נעשה, מדברים עליה הרבה ב-embedded, זה נקרא lookup table. זאת אומרת שזו פעולה שחישוב של רוב האפשרויות שלה אני עושה מראש, ואז בזמן הריצה אני פשוט ישר ניגש לתוצאה לפי האינדקס, שבמקרה שלנו זה ה-case.

## סיכום ושאלות

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

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