תוכן עניינים:

חלק 1 הרכבה ARM TI RSLK רובוטיקה מעבדת תכניות לימוד 7 STM32 Nucleo: 16 שלבים
חלק 1 הרכבה ARM TI RSLK רובוטיקה מעבדת תכניות לימוד 7 STM32 Nucleo: 16 שלבים

וִידֵאוֹ: חלק 1 הרכבה ARM TI RSLK רובוטיקה מעבדת תכניות לימוד 7 STM32 Nucleo: 16 שלבים

וִידֵאוֹ: חלק 1 הרכבה ARM TI RSLK רובוטיקה מעבדת תכניות לימוד 7 STM32 Nucleo: 16 שלבים
וִידֵאוֹ: Fanboy Prewrites the MCU Spider-Man College Trilogy 2024, יולי
Anonim
Image
Image

המוקד של מדריך זה הוא בקר מיקרו STM32 Nucleo. המוטיבציה לכך תוכל ליצור פרויקט הרכבה מעצמות חשופות. זה יעזור לנו להתעמק ולהבין את פרויקט ה- Launchpad MSP432 (TI-RSLK) שכבר היה נושא לכמה הוראות.

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

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

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

נראה שיש הרבה יותר עזרה מקוונת לפרויקטים של הרכבה המשתמשים ב- STM32 MCU, ולכן אנו מתחילים עם מדריך זה, במטרה להשתמש במה שנלמד, ולאחר מכן לפנות ל- MSP432 ולסטודיו קוד מלחין.

בדרך למטרה זו, קיבלנו גם ניסיון עם מיקרו-בקר פופולרי נוסף.

שלב 1: בדיקה ראשונית של המכשיר

בדיקה ראשונית של המכשיר
בדיקה ראשונית של המכשיר
בדיקה ראשונית של המכשיר
בדיקה ראשונית של המכשיר
בדיקה ראשונית של המכשיר
בדיקה ראשונית של המכשיר

שוב, מדוע לבחור בפרט את ה- STM32 Nucleo?

בִּיוֹשֶׁר? מכיוון שחיפשתי מאמרים טובים על פרויקטי הרכבה מתכת חשופה לבקרי ARM, ונתקלתי בסדרה זו. וגם כי נראה ש- STM32 הוא MCU פופולרי.

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

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

נראה שלוח הפיתוח הזה דומה מאוד ל- MSP432 בכך שיש 2 נוריות LED ולחיצת משתמש אחת. ל- MSP432 יש 2 כפתורי משתמש.

כפי שאתה יכול לראות בתמונות, קצת נדהמתי מכך שללוח יש מיני ולא מיקרו USB. היה צריך לרוץ כדי לקנות כבל.

עוד בדיקה טובה היא שכאשר אתה מחבר אותו למחשב שלך (אני משתמש בקופסת לינוקס), הוא מופיע במנהל הקבצים שלי, כמערכת קבצים, הנקראת "NODE_F303RE". פתיחה החושפת שני קבצים, HTML אחד וטקסט אחד.

זהו, אבל לפחות הוא גם אומר שהקישוריות נראית די קלה.

עכשיו אנחנו מוכנים להתחיל.

אני הולך לנסות לא לחזור על המידע הטוב מסדרת המאמרים של IVONOMICON Bare Metal, אלא להגדיל אותו.

שלב 2: היסודות

הדבר הראשון שאנחנו צריכים הוא מהדר.

ואז, אנו זקוקים לאתר באגים:

devchu@chubox: ~ $ sudo apt-get install gdb-arm-none-eabi רשימות חבילות קריאה … בוצע עץ בניית תלות קריאת מידע על מצב … בוצעו החבילות החדשות הבאות יותקנו: gdb-arm-none-eabi 0 משודרג, 1 חדש מותקן, 0 להסרה ו -8 לא משודרג. צריך להשיג 2, 722 kB של ארכיונים. לאחר פעולה זו, ישתמש ב -7, 738 קילו -בייט של שטח דיסק נוסף. קבל: 1 https://us.archive.ubuntu.com/ubuntu xenial/universe amd64 gdb-arm-none-eabi amd64 7.10-1ubuntu3+9 [2, 722 kB] נאסף 2, 722 kB בשניות (1, 988 kB/s) בחירת החבילה שלא נבחרה בעבר gdb-arm-none-eabi. (קורא מסד נתונים … 262428 קבצים וספריות מותקנים כרגע.) מתכונן לפרוק …/gdb-arm-none-eabi_7.10-1ubuntu3+9_amd64.deb… פריקת gdb-arm-none-eabi (7.10-1ubuntu3+9) … עיבוד מפעילים עבור man-db (2.7.5-1) … הגדרת gdb-arm-none-eabi (7.10-1ubuntu3+9) …

שלב 3: היסודות - Windows

השלב לעיל הניח שאנחנו משתמשים ב- Linux. מה אם אנו משתמשים ב- Windows?

אתה יכול להיכנס לאתר מפתחי הזרוע, וישנן מספר אפשרויות הורדה. אני משתמש במכשיר ווינדוס 8.

במהלך ההתקנה בחרתי להתקין אותו בכונן הבסיס "C: \" במקום קבצי התוכנה רק בגלל שאני משתמש גם ב- cygwin, והיה קל יותר ליצור קישור מהסל המקומי שלי לתיקיית root C: מאשר כל בלגן בנתיב קבצי התוכנית (עם רווחים וכו ').

לפיכך, סביבת הנתיב והנתיב שלי וכו 'נראית כך:

C: / cygwin64 / home / bin / arm-none-eabi-gcc, כאשר arm-none-eabi-gcc הוא קישור ל- C: / GNUToolsArmEmbedded / 7.2018.q2.update / bin / arm-none-eabi- gcc.

לאחר מכן יצרתי תיקיית "dev" תחת cygwin home, ושם הנחתי את קובץ core. S והפעלתי את פקודת המהדר. (עיין בהמשך להלן לדברים המהדרים).

עשיתי את אותו הדבר בדיוק עבור gdb (arm-none-eabi-gdb).

שלב 4: מה הם היסודות

אז מהו "gcc-arm-none-eabi"?

מהדר ה- gnu (GCC) ירכז שפות תכנות (כמו C) לקוד מקורי של המכונה שבה הוא פועל. לדוגמה, אם היית אוסף קוד C כלשהו באמצעות GCC במחשב Windows שלך, הוא היה בנוי להפעלה במחשב Windows. קובץ ההפעלה שנוצר לא יפעל (בדרך כלל) על בקר מיקרו ARM.

לכן, על מנת לבנות תוכניות להורדה ולצריבה לתוך מיקרו-בקר ה- ARM (במקרה הנוכחי שלנו זה יהיה ה- STM32 Nucelo), עלינו לתת ל- GCC משהו אחר: היכולת "להלבין צולבים". כלומר, היכולת לייצר קובץ הפעלה, לא עבור המערכת המקורית שלו (והמעבד), אלא עבור מערכת המטרה (מיקרו-בקר ARM). כאן נכנס לתמונה "gcc-arm-none-eabi".

אז מהו "gdb-arm-none-eabi"?

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

לפיכך, gdb-arm-none-eabi הוא ל- GDB, מה ש- gcc-arm-none-eabi הוא ל- GCC.

הצעה נוספת להתקנת חבילה הייתה "libnewlib-arm-none-eabi". מה זה?

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

ולבסוף, החבילה "libstdc ++-arm-none-eabi". זה די ברור; זוהי ספריית C ++ עבור מהדר הצלב; עבור מיקרו-בקרי ARM מוטבעים.

שלב 5: קובץ הקישור

קובץ הלינקר
קובץ הלינקר
קובץ הלינקר
קובץ הלינקר

בואו ניצור סקריפט מקשר.

חלק מרכזי או בלוק אחד בקובץ זה תהיה הפקודה MEMORY.

--- מאת sourceware.org:

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

זיכרון

{name [(attr)]: ORIGIN = מקור, LENGTH = len…}

הדוגמה בכתבה:

/* הגדר את סוף זיכרון ה- RAM ואת גבול זיכרון הערימה* //* (4KB SRAM בקו STM32F031x6, 4096 = 0x1000)*//* (RAM מתחיל בכתובת 0x20000000) _estack = 0x20001000;

זיכרון

{FLASH (rx): ORIGIN = 0x08000000, LENGTH = 32K RAM (rxw): ORIGIN = 0x20000000, LENGTH = 4K}

אז עלינו להבין כמה פלאש (עבור התוכנית והקבועים שלנו וכו ') וכמה זיכרון RAM (לשימוש התוכנית; ערימה וערימה וכו') ללוח הספציפי שלנו. זה נהיה קצת מעניין.

הכרטיס הקטן והנחמד שמגיע עם ה- Nucleo אומר שיש לו זיכרון פלאש הוא 512 Kbytes ו- SRAM הוא 80 Kbytes. עם זאת, כשמחברים אותו ל- USB, הוא מותקן כמערכת קבצים עם שני קבצים, וגם מנהל הקבצים ו- GParted מציינים שיש לו יותר מ- 540 קילו בייט. (RAM?).

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

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

ייתכן שתרצה להשתמש במשהו כמו ממיר זיכרון מקוון זה, כדי לעבור מה- KB הכללי למספר בתים ספציפי.

אז אולי תרצה להשתמש בממיר מקוון עשרוני להקס.

/ * הגדר את סוף זיכרון ה- RAM ואת גבול זיכרון הערימה */

/* (4KB SRAM בקו STM32F031x6, 4096 = 0x1000)* //* הדוגמא*/

/ * שלב 1: (80KB SRAM ב- STM32F303RE, 81920 = 0x14000) * // * הלוח שלנו */

/* שלב 2, הוסף את גודל ה- hex לכתובת ההתחלה המשושה (להלן). */

/ * (RAM מתחיל בכתובת 0x20000000) */

_estack = 0x20001000; /* הדוגמה */

_estack = 0x20014000; / * הלוח שלנו */

זיכרון {

FLASH (rx): ORIGIN = 0x08000000, LENGTH = 512K

זיכרון RAM (rxb): מקור = 0x20000000, אורך = 80K

}

נקרא לקובץ לעיל "linker.script.ld".

שלב 6: טבלת הווקטורים

טבלת הווקטורים
טבלת הווקטורים

עכשיו אנחנו הולכים ליצור קובץ הרכבה קטן (עם הנחיות) לביצוע טיפול בהפרעות בסיסי מאוד. נעקוב אחר דוגמת המאמר וניצור קובץ בשם "core. S".

שוב, הנה תוכן הקובץ לדוגמה, אך ביצעתי שינוי ללוח הספציפי שלנו:

// הוראות אלה מגדירות תכונות של השבב שלנו ו-

// שפת ההרכבה בה נשתמש:.syntax unified /*ראה להלן אחרי אזור קוד זה* //*.cpu cortex-m0* / /*הגיב על שורה זו של הדוגמה* /.cpu cortex-m4 /* הוסף במקום זאת את קליפת המוח של הלוח שלנו. ראה תמונה למעלה בשלב זה * / /*.fpu softvfp * / / *הגיב על שורה זו של הדוגמה * /.fpu vfpv4 / *הוסף במקום הלוח שלנו; יש לו FPU */.thumb // מיקומי זיכרון גלובליים..global vtable.global reset_handler / * * טבלת הווקטורים בפועל. * רק בגודל ה- RAM והמטפל 'איפוס' כלולים * לשם הפשטות. */.type vtable, %object vtable:.word _estack.word reset_handler.size vtable,.-vtable

הממ.. אין הוראת 'יישור'

עם זאת, זה לא קריטי. עוד על זה (אולי) מאוחר יותר.

תחביר אחיד

.syntax [מאוחד | מחולק]

הוראה זו קובעת את תחביר מערך ההוראות כמתואר בסעיף ARM-Instruction-Set

9.4.2.1 תחביר ערכת הוראות שני תחביר מעט שונה הם תמיכה בהנחיות ARM ו- THUMB. ברירת המחדל, המחולקת, משתמשת בסגנון הישן שבו הוראות ARM ו- THUMB היו תחביר משלהן. התחביר החדש, המאוחד, שניתן לבחור באמצעות הוראת.syntax.

.fpu vfpv4

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

אגודל (לעומת.זרוע)

למיקרו בקר ARM אלה יש למעשה שילוב של ערכות הדרכה. אחד הוא זרוע, אחר הוא אגודל. הבדל אחד הוא הוראות 16 סיביות מול הוראות 32 סיביות. לפיכך, הוראה זו אומרת למהדר להתייחס להוראות הבאות כ- THUMB או ARM.

אנחנו הולכים לקחת את שאר הקובץ כפי שהוא מכיוון שמדריכים אלה עדיין לא התעמקו בתכנות הרכבה מונע הפרעות.

שלב 7: גרסת ההרכבה של תוכנית 'שלום עולם'

הדברים הבאים יכולים להיכנס גם לקובץ "core. S" שנוצר בעבר. זה, שוב, מהדוגמה שבמאמר.

/ * * מטפל האיפוס. התקשר באיפוס. */.type reset_handler, %function reset_handler: // הגדר את מצביע הערימה לקצה הערימה. // ערך '_estack' מוגדר בתסריט המקשר שלנו. LDR r0, = _ערימה MOV sp, r0

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

// בבאגים שלנו, נדע שהתוכנית // שלנו נטענת על השבב ועובדת. LDR r7, = 0xDEADBEEF MOVS r0, #0 main_loop: // הוסף 1 לרישום 'r0'. ADDS r0, r0, #1 // לולאה אחורה. B main_loop. גודל reset_handler,.-Reset_handler

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

אם עקבת יחד עם מדריכי ההנחיות בנוגע ל- MSP432 ולקורס/מעבדות TI-RSLK, פחות או יותר כל התוכנית לעיל אמורה להיות מוכרת לך.

הדבר החדש היחיד שאני יכול לראות הוא השימוש ב- "=" בעת טעינת "DEADBEEF" כדי לרשום R7. לא השתמשנו בזה.

קובץ "core. S" המצורף כאן מכיל כעת את המקור המלא.

שלב 8: עריכת הקוד

הגיע הזמן לעשות כמה שורות פקודה. משהו אמיתי, סוף סוף.

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

להלן הקוד לדוגמא:

arm -none -eabi -gcc -x assembler -with -cpp -c -O0 -mcpu = cortex -m0 -mthumb -Wall core. S -o core.o

אם נלך לאתר gnu.org עבור GCC, (במקרה זה גירסה 7.3),

איקס

ה- x הוא ציון השפה. אחרת אם אין -x, המהדר ינסה לנחש באמצעות סיומת הקובץ. (במקרה שלנו, *. S).

הדוגמה לעיל מהמאמר מציינת assembler-with-cpp, אך נוכל פשוט לבצע assembler.

ג

ה- -c אומר הידור אך אל תקשר.

O0

ה- O הוא לקבוע את רמת האופטימיזציה. שימוש ב- -O0 (הו -אפס) אומר "צמצם את זמן הידור וגרם לאיתור באגים לייצר את התוצאות הצפויות. זו ברירת המחדל".

mcpu = קליפת המוח-m0

ה- mcpu מציין את שם מעבד היעד. במקרה שלנו, זה יהיה קליפת המוח m4.

אגודל

ה- -mthumb מציין בחירה בין יצירת קוד המבצע מצבי ARM ו- THUMB.

קִיר

ה- -Wall הוא כמובן מאוד נפוץ וידוע. הוא מדליק את כל דגלי האזהרה.

לבסוף, בסוף הפקודה יש לנו את קובץ הקלט core. S ואת קובץ הפלט core.o.

להלן שורת הפקודה החדשה המתקבלת שתתאים למקרה הספציפי שלנו.

arm -none -eabi -gcc -x assembler -c -O0 -mcpu = קליפת המוח -m4 -אגודל -ליבת קיר S -o core.o

וזה התאסף.

שלב 9: קישור התוכנית

ישירות מהדוגמה במאמר, יש לנו את זה:

arm -none -eabi -gcc core.o -mcpu = cortex -m0 -mthumb -Wall --specs = nosys.specs -nostdlib -lgcc -T./STM32F031K6T6.ld -o main.elf

את רוב האמור לעיל ראית. להלן מה חדש.

specs = nosys.specs

זה קצת מסובך להסביר.

זה קשור ל"הגירה למחצה "ו"מיקוד מחדש", וזה קשור לקלט / פלט. זה קשור גם לשיחות מערכת וספריות.

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

פירושו של Semihosting לאתר באגים (ראה תמונה שלב 11 עם חלק באגים המוקף באדום) יש ערוץ מיוחד ומשתמש בפרוטוקול Semihosting, ותוכל לראות את הפלט של printf () במחשב המארח (באמצעות באגים).

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

אחרי שאמרנו את כל זה, ה- --specs = nosys.specs פירושו שלא נצא למחצה. זה בדרך כלל אומר שאנו ממקדים מחדש. זה מביא אותנו לדגל הבא.

nostdlib

אפשרות הקישור -nostdlib משמשת לקישור תוכנית המיועדת להפעלה עצמאית. -nostdlib מרמז על האפשרויות הבודדות -nodefaultlibs ו- -nostartfiles. להלן אנו דנים בשתי האפשרויות בנפרד, אך השימוש האופייני ביותר הוא רק nostdlib לקניות חד פעמיות. בעת קישור תוכנית מתארחת, ספריות מערכת סטנדרטיות כגון libc מקושרות כברירת מחדל, מה שמאפשר לתוכנית גישה לכל הפונקציות הסטנדרטיות (printf, סטרלן וחברים). אפשרות הקישור -nodefaultlibs מבטלת את הקישור עם ספריות ברירת המחדל האלה; הספריות היחידות המקושרות הן בדיוק אלה שאתה נותן למפרק באופן מפורש באמצעות הדגל -l.

lgcc

libgcc.a היא ספרייה סטנדרטית המספקת תת -שורות פנימיות להתגבר על חסרונות של מכונות מסוימות. לדוגמה, מעבד ה- ARM אינו כולל הוראת חלוקה. גרסת ה- ARM של libgcc.a כוללת פונקציית חלוקה והמהדר פולט שיחות לאותה פונקציה במידת הצורך.

ט

זו רק דרך להגיד למקשר להשתמש בקובץ זה כתסריט המקשר. במקרה שלנו, שם הקובץ הוא linker.script.ld.

o main.elf

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

להלן הגרסה שלנו של שורת הפקודה השלמה, המותאמת למצבנו הספציפי:

arm -none -eabi -gcc core.o -mcpu = cortex -m4 -mthumb -Wall --specs = nosys.specs -nostdlib -lgcc -T./linker.script.ld -o main.elf

אנו מוודאים שקובץ ה- script והקובץ core.o נמצאים שניהם באותה ספרייה, שבה נריץ את שורת הפקודה שלמעלה.

והוא מתקשר ללא בעיות.

צ'ק

לאחר מכן אנו רצים:

arm-none-eabi-nm main.elf

ואנו מקבלים:

devchu@chubox: ~/Development/Atollic/TrueSTUDIO/STM32_workspace_9.1 $ arm-none-eabi-nm main.elf 20014000 A _estack 08000010 t main_loop 08000008 T reset_handler 08000000 T vtable

נראה טוב. הפקודה arm-none-eabi-nm היא דרך לרשום סמלים בתוך קבצי אובייקטים.

שלב 10: בדיקת חיבור ל- STM32 Nucleo-64

בדיקה חיבור ל- STM32 Nucleo-64
בדיקה חיבור ל- STM32 Nucleo-64
בדיקה חיבור ל- STM32 Nucleo-64
בדיקה חיבור ל- STM32 Nucleo-64

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

שימוש ב- Windows

עבור Windows, החלטתי להתקין את TrueSTUDIO מ- Atollic (גרסה חינמית). זו הייתה התקנה ללא כאבים והיא התקינה אוטומטית את מנהל ההתקן כדי שאוכל להשתמש ב- st-link כדי לבדוק את החיבור. לאחר שהתקנתי את TrueSTUDIO ומנהל ההתקנים ראה את המכשיר, הורדתי את הכלים texan/stlink המוצעים במאמר Bare Metal שאנו עוקבים אחריו. שוב הנחתי את התיקייה ישירות תחת "C: \", ושוב יצרתי כמה קישורים מפח הבית המקומי של cygwin לפקודות.

ln -s /c/STM32. MCU/stlink-1.3.0-win64/bin/st-info.exe ~/bin/st-info

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

st-info --probe

וחזרתי:

מצא 1 מתכנתים של stlink

אז עכשיו אנחנו יודעים שאנחנו יכולים לדבר/לבדוק את לוח הפיתוח שלנו.

שימוש בלינוקס

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

שיבוט git

ודא שהתקנת libusb-1.0-0-dev.

רשימה מתאימה | grep -E "*libusb.*dev*"

אתה צריך לראות:

libusb-1.0-0-dev/xenial, עכשיו 2: 1.0.20-1 amd64 [מותקן]

או משהו כזה.

כדי להתקין אותו:

sudo apt-get install libusb-1.0-0-dev

שים לב שהאמור לעיל אינו זהה ל:

sudo apt-get להתקין libusb-dev

Dev libusb הנכון החסר יכול לגרום ל- cmake לבעיות.

שגיאת CMake: המשתנים הבאים משמשים בפרויקט זה, אך הם מוגדרים ל- NOTFOUND. אנא הגדר אותם או ודא שהם מוגדרים ונבדקים כראוי בקבצי CMake: LIBUSB_INCLUDE_DIR (ADVANCED)

שנה לספריית השורש של הפרויקט (… blah /blah /stlink). בצע "עשה שחרור".

לאחר הבנייה, הכלים צריכים להיות תחת ".. /build /Release".

לאחר מכן תוכל להריץ "st-info --probe". הנה הפלט עם ה- Nucleo מחובר, אז לא.

devchu@chubox: ~/Development/stlink $./build/Release/st-info --probe מצא 1 מתכנתים של stlink סידורי: 303636414646353034393535363537 openocd: "\ x30 / x36 / x36 / x41 / x46 / x46 / x35 / x30 / x34 / x39 / x35 / x35 / x36 / x35 / x37 "פלאש: 524288 (גודל עמוד: 2048) sram: 65536 שבב: 0x0446 descr: F303 מכשיר בצפיפות גבוהה devchu@chubox: ~/Development/stlink $./build/Release/st- info --probe נמצא 0 מתכנתים stlink devchu@chubox: ~/פיתוח/stlink $

שלב 11: בואו נשתמש ב- GDB עם לינוקס

בואו להשתמש ב- GDB עם לינוקס
בואו להשתמש ב- GDB עם לינוקס
בואו להשתמש ב- GDB עם לינוקס
בואו להשתמש ב- GDB עם לינוקס

אם ניסית את כל זה והגעת עד כאן - מצוין! מְעוּלֶה. בואו ליהנות קצת עכשיו.

כאשר אתה קונה לוחות פיתוח ARM אלה, בין אם הם לוח ההשקה MSP432 מטקסס אינסטרומנטס, או זה שעליו אנו דנים כעת, ה- Nucleo-F303 (STM32 Nucleo-64), הם בדרך כלל מגיעים כשהם כבר מהבהבים עם תוכנית הפעלה, בדרך כלל איזו תוכנית מהבהבת הכוללת גם לחיצה על מתג לשינוי הקצב שבו הנורות (LED) מהבהבות.

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

עם לינוקס, פתח מסוף, שנה את הספרייה של פרויקט stlink git שבנינו זה עתה ומצא את הכלי st-util.

devchu@chubox: ~/פיתוח/stlink $ find. -name st-util

./build/Release/src/gdbserver/st-util

הפעל את הכלי הזה. מכיוון שכבר בדקנו בעבר את הקשר שלנו עם st-info --probe, אנחנו אמורים לקבל פלט כזה:

devchu@chubox: ~/פיתוח/stlink $./build/Release/src/gdbserver/st-util

st-util 1.4.0-50-g7fafee2 2018-10-20T18: 33: 23 INFO common.c: טוען פרמטרים של מכשיר…. 2018-10-20T18: 33: 23 INFO common.c: מכשיר מחובר הוא: מכשיר F303 בצפיפות גבוהה, מזהה 0x10036446 2018-10-20T18: 33: 23 INFO common.c: גודל SRAM: 0x10000 בתים (64 KiB), פלאש: 0x80000 בתים (512 KiB) בדפים של 2048 בתים 2018-10-20T18: 33: 23 INFO gdb-server.c: מזהה שבב הוא 00000446, מזהה ליבה הוא 2ba01477. 2018-10-20T18: 33: 23 INFO gdb-server.c: האזנה ב *: 4242 …

זהו שרת GDB הפועל כעת, והוא רואה את לוח הפיתוח שלנו, וחשוב מכך, הוא מאזין ליציאה 4242 (יציאת ברירת המחדל).

כעת אנו מוכנים לפטר את לקוח GDB.

ב- Linux, פתח מסוף נוסף, הזן את זה:

arm-none-eabi-gdb -tui

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

יש לנו את לקוח GDB ושרת GDB פועלים. עם זאת, הלקוח אינו מחובר לשרת. כרגע הוא לא יודע כלום על הגרעין שלנו (או הלוח שבחרת). עלינו לספר זאת. במסוף, ההנחיה שלך אמורה כעת להיות "(gdb)". להיכנס:

עזרה למטרה

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

אבל עלינו גם לתת לו את המיקום. אז, בהנחיית (gdb), הזן:

(gdb) יעד מארח מרחוק מרוחק מרחוק: 4242

אתה אמור לקבל תשובה בערך כך:

(gdb) יעד מארח מרחוק מרוחק מרחוק: 4242

איתור באגים מרחוק באמצעות localhost: 4242 0x080028e4 ב ?? ()

בינתיים, במסוף המפעיל את gdbserver st-util, קיבלנו את זה:

2018-10-20T18: 42: 30 INFO gdb-server.c: נמצאו 6 רשימות נקודת שבירה

2018-10-20T18: 42: 30 INFO gdb-server.c: GDB מחובר.

שלב 12: בואו נחזור על הפעולה, בעזרת Windows והבזק התוכנית שלנו

בואו נחזור על הפעולה, עם Windows והבזק התוכנית שלנו
בואו נחזור על הפעולה, עם Windows והבזק התוכנית שלנו
בואו נחזור על הפעולה, עם Windows והבזק התוכנית שלנו
בואו נחזור על הפעולה, עם Windows והבזק התוכנית שלנו
בואו נחזור על הפעולה, עם Windows ו- Flash התוכנית שלנו
בואו נחזור על הפעולה, עם Windows ו- Flash התוכנית שלנו

השלבים להפעלת gdbserver st-util והלקוח arm-none-eabi-gdb הם למעשה זהים לזה שעשינו בשלב הקודם. אתה פותח שני מסופים (cygwin, DOS cmd או Windows Powershell), מוצא את המיקום של ה- st-util, הפעל אותו. במסוף השני, הפעל את לקוח arm-none-eabi-gdb. ההבדל היחיד הוא שמצב ה- -tui (תצוגת טקסט מבוססת מסוף) ככל הנראה אינו נתמך.

אם האמור לעיל עבד ב- Windows, סביר להניח שתצטרך לעצור (רק הלקוח). בשלב זה, איכשהו תצטרך להפעיל את לקוח GDB במקום בו קובץ ה- build שלך נמצא ("core.out"), או להוסיף את כל הנתיב לקובץ זה כארגומנט ללקוח GDB.

פישטתי את חיי באמצעות cygwin ויצירת קישורים מספריית $ HOME // bin המקומית שלי לשני הכלים האלה.

אוקיי, ריכזנו וקישרנו בדיוק כמו בעבר, ויש לנו את הקובץ main.elf מוכן להבזק.

יש לנו ריצה של st-util בחלון אחד. אנו מפעילים מחדש את לקוח GDB, הפעם אנו עושים:

arm-none-eabi-gdb main.elf

נתנו לו להתחיל, מחכים לפקודת (gdb), מבצעים את אותה פקודת חיבור לשרת GDB (st-util), ואנחנו מוכנים להבהב את קובץ ההפעלה. זה מאוד אנטי אקלימי:

(gdb) עומס

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

טעינת קטע טקסט, גודל 0x1c lma 0x8000000 התחל כתובת 0x8000000, גודל טעינה 28 קצב העברה: 1 KB/sec, 28 בתים/כתיבה.

שלב 13: מהבהב עם לינוקס - תגמול נוסף: ד

מהבהב עם לינוקס - יותר מתגמל: ד
מהבהב עם לינוקס - יותר מתגמל: ד

שלב 14: בואו נצלול קצת יותר עמוק

אם הגעת לכאן, מצוין. בוא נמשיך הלאה.

למה לא להסתכל פנימה לתוך קובץ main.elf, ההפעלה? הפעל את הפעולות הבאות:

arm-none-eabi-objdump -d main.elf

אתה אמור לראות פלט בערך כזה:

main.elf: פורמט קובץ elf32-littlearm

פירוק קטע. טקסט:

08000000:

8000000: 00 40 01 20 09 00 00 08.@. ….

08000008:

8000008: 4802 ldr r0, [מחשב, #8]; (8000014) 800000a: 4685 mov sp, r0 800000c: 4f02 ldr r7, [pc, #8]; (8000018) 800000e: 2000 movs r0, #0

08000010:

8000010: 3001 מוסיף r0, #1 8000012: e7fd b.n 8000010 8000014: 20014000.word 0x20014000 8000018: deadbeef.word 0xdeadbeef

אילו גושים קטנים אנו יכולים להשיג מהפלט הנ ל?

אם אתה זוכר כשדיברנו ויצרו את הקובץ linker.script.ld, ציינו שלמכשירי ARM אלה יש זיכרון RAM החל מ- 0x20000000, וכי זיכרון FLASH מתחיל ב- 0x08000000.

לפיכך, אנו יכולים לראות שאכן התוכנית היא כזו שכולה שוכן בזיכרון FLASH.

ואז, למעלה, אבל בשלב מאוחר יותר, כשדיברנו על החלק "עולם שלום", הייתה הצהרה שבה אנו מעמיסים ערך מיידי, קבוע, מילולי ("0xDEADBEEF") לרשם ליבות MCU ("R7").

ההצהרה הייתה:

LDR R7, = 0xDEADBEEF

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

אז המהדר/המקשר החליט איכשהו להבהב לצמיתות את הערך של DEADBEEF לכתובת FLASH, במיקום 0x8000018. ואז, המהדר שינה את הוראת ה- LDR לעיל כך:

LDR R7, [PC, #8]

זה אפילו יצר לנו הערה. כמה נחמד. וזה אומר לנו לקחת את ערך מונה התוכניות הנוכחי (רשם המחשב האישי), להוסיף 0x8 לערך הזה, ושם נשרף DEADBEEF, ולקבל את הערך הזה ולמלא אותו ב- R7.

אז זה גם אומר שמונה התוכניות (PC) הצביע על כתובת 0x8000010, שהיא התחלה של main_loop, וכי ערך DEADBEEF יושב בשתי כתובות לאחר סיום main_loop.

שלב 15: לבסוף, מבט קצר על ריצת התוכנית

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

לאחר שתחבר מחדש את לקוח GDB לשרת GDB, בשורת הפקודה (gdb):

(gdb) רושמי מידע

אתה אמור לראות משהו כזה:

r0 0x0 0

r1 0x0 0 r2 0x0 0 r3 0x0 0 r4 0x0 0 r5 0x0 0 r6 0x0 0 r7 0x0 0 r8 0x0 0 r9 0x0 0 r10 0x0 0 r11 0x0 0 r12 0x0 0 sp 0x20014000 0x20014000 lr 0xffffffff 429496789500

אבל אז, בהנחיית (gdb), הזן:

(gdb) המשך

ומהר מאוד פגע ב- CTRL-C. זה אמור להשהות את התוכנית. הזן שוב את הפקודה "מידע רושם".

הפעם זה נראה אחרת:

(gdb) רושמי מידע

r0 0x350ffa 3477498 r1 0x0 0 r2 0x0 0 r3 0x0 0 r4 0x0 0 r5 0x0 0 r6 0x0 0 r7 0xdeadbeef 3735928559 r8 0x0 0 r9 0x0 0 r10 0x0 0 r11 0x0 0 r12 0x10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0ott ב 0 0 0 0 0 0 4 0 0 0 0 16777216

מה קרה? בדיוק מה שרצינו. DEADBEEF נטען ל- R7, ו- R0 עלה (מהר במיוחד). אם תחזור, תראה שוב R0 עם ערך אחר.

שלב 16: רצינו ליצור מערך לקריאה בלבד ב- Flash

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

.type myarray, %object // השם או התווית 'myarray' מוגדר כסוג אובייקט.

myarray: // זוהי ההתחלה של ההכרזה על 'myarray' // (ממה היא תכלול)..word 0x11111111 // החבר או הערך הראשון הכלול ב- 'myarray'..word 0x22222222 // הערך השני (כתובות רציפות)..word 0x33333333 // וכן הלאה..size myarray,.-myarray // המהדר/המאסף יודע כעת היכן הסוף או // הגבול של 'myarray'.

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

LDR R1, myarray // זה טוען נתונים הכלולים במיקום הראשון של 'myarray'. ' // זה לא מה שאנחנו רוצים.

LDR R1, = myarray // זה טוען את ערך המיקום עצמו (הכתובת הראשונה), // לא הנתונים.. // זה מה שאנחנו רוצים.

MOV R2, #0 // R2 ישמור ספירה כדי לוודא שלא נצא משם

// סוף המערך. LDR R3, = myarrsize // R3 תהיה המקבילה של 'myarrsize'.

// R0 יחזיק את הנתונים שלנו

main_loop:

LDR R0, [R1] // טען את הנתונים שאליהם הצביע R1 ('myarray') לתוך R0. CMP R2, R3 // האם אנחנו בגבול המערך? BEQ main_loop // אם כן, סיימנו, אז פשוט נלחץ לנצח.

ADD R2, #1 // אחרת נוכל להמשיך ולחזור באמצעות מערך.

הוסף R1, מס '4 // הוסף 4 לרישום R1, כך שהוא מצביע כראוי לשלב הבא

// כתובת..

B main_loop // לולאה אחורה.

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

מוּמלָץ: