Πίνακας περιεχομένων:

Μέρος 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 Steps
Μέρος 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 Steps

Βίντεο: Μέρος 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 Steps

Βίντεο: Μέρος 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 Steps
Βίντεο: Part 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo 2024, Ιούλιος
Anonim
Image
Image

Το επίκεντρο αυτού του Instructable είναι ο μικροελεγκτής STM32 Nucleo. Το κίνητρο για αυτό είναι σε θέση να δημιουργήσει ένα έργο συναρμολόγησης από γυμνά κόκαλα. Αυτό θα μας βοηθήσει να εμβαθύνουμε και να κατανοήσουμε το έργο MSP432 Launchpad (το TI-RSLK) που έχει ήδη γίνει το θέμα αρκετών οδηγιών.

Δεν υπάρχει μεγάλη βοήθεια στο διαδίκτυο για τη δημιουργία ενός έργου μόνο για συναρμολόγηση για το MSP432, χρησιμοποιώντας το Code Composer Studio. Μέχρι τώρα κάναμε αντιγραφή/επικόλληση από ένα προϋπάρχον έργο συναρμολόγησης. Αυτή η προσέγγιση μας έχει εξυπηρετήσει καλά.

Ωστόσο, τώρα, για το Lab 7, αντιμετωπίσαμε ένα μικρό πρόβλημα. Or τουλάχιστον ένας προσωρινός λόξυγκας. Το εργαστήριο 7 εισάγει μηχανές πεπερασμένης κατάστασης και το πρώτο πράγμα που συναντάμε είναι η ανάγκη δημιουργίας και χρήσης ενός πίνακα τιμών. Δεδομένου ότι το μάθημα TI χρησιμοποιεί κυρίως προγραμματισμό C - αυτό δεν είναι πρόβλημα. Αλλά αυτά τα Instructables έχουν επικεντρωθεί στη συναρμολόγηση και όχι στο C.

Επιπλέον, δεδομένου ότι ο πίνακας έχει τιμές μόνο για ανάγνωση, καλό θα ήταν να το τοποθετήσετε σε μνήμη flash και όχι RAM.

Φαίνεται ότι υπάρχει πολύ περισσότερη βοήθεια στο διαδίκτυο για έργα συναρμολόγησης που χρησιμοποιούν το STM32 MCU, επομένως, ξεκινάμε με αυτό το Instructable, με στόχο να χρησιμοποιήσουμε όσα μαθαίνουμε, για να εφαρμόσουμε στη συνέχεια στο MSP432 και στο Code Composer Studio.

Στο δρόμο προς αυτόν τον στόχο, θα έχουμε επίσης εμπειρία με ένα άλλο, δημοφιλές μικροελεγκτή.

Βήμα 1: Αρχική δοκιμή συσκευής

Αρχική δοκιμή συσκευής
Αρχική δοκιμή συσκευής
Αρχική δοκιμή συσκευής
Αρχική δοκιμή συσκευής
Αρχική δοκιμή συσκευής
Αρχική δοκιμή συσκευής

Και πάλι, γιατί να επιλέξετε το STM32 Nucleo συγκεκριμένα;

Τίμια? Επειδή έψαχνα για καλά άρθρα για έργα συναρμολόγησης γυμνού μετάλλου για ελεγκτές ARM και συνάντησα αυτή τη σειρά. Και επίσης επειδή το STM32 φαίνεται να είναι ένα δημοφιλές MCU.

Έκανα κάποια έρευνα (υπάρχουν πολλές εκδόσεις για να διαλέξετε - δείτε την εικόνα παραπάνω), αλλά τελικά έγινε αυτό που μπορώ πραγματικά να πάρω, αφού επρόκειτο να χρησιμοποιήσω το Amazon (στις ΗΠΑ).

Έρχεται σε ένα απλό αλλά επαγγελματικό πακέτο, με κάποιες οδηγίες εκκίνησης. Funnyταν λίγο αστείο να βλέπουμε ότι το demo που κάηκε στο χειριστήριο ήταν σχεδόν αυτό που κάναμε στο παρελθόν Instructables - ένα LED αναβοσβήνει και αλλάζει ταχύτητα σύμφωνα με το πάτημα ενός κουμπιού.

Φαίνεται ότι αυτός ο πίνακας ανάπτυξης είναι πολύ παρόμοιος με τον MSP432 στο ότι υπάρχουν 2 LED και ένα κουμπί χρήστη. Το MSP432 διαθέτει 2 κουμπιά χρήστη.

Όπως μπορείτε να δείτε στις φωτογραφίες, ξαφνιάστηκα λίγο που ο πίνακας έχει μίνι και όχι micro USB. Έπρεπε να τελειώσει για να αγοράσει ένα κορδόνι.

Μια άλλη καλή δοκιμή είναι ότι όταν το συνδέετε στον υπολογιστή σας (χρησιμοποιώ ένα πλαίσιο Linux), εμφανίζεται στον διαχειριστή αρχείων μου, ως σύστημα αρχείων, που ονομάζεται "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 kB πρόσθετου χώρου στο δίσκο. Λήψη: 1 https://us.archive.ubuntu.com/ubuntu xenial/univers amd64 gdb-arm-none-eabi amd64 7.10-1ubuntu3+9 [2, 722 kB] Λήψη 2, 722 kB σε 1s (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;

Μπορείτε να μεταβείτε στον ιστότοπο arm Developer και υπάρχουν πολλές διαθέσιμες επιλογές λήψης. Χρησιμοποιώ μηχάνημα Windows 8.

Κατά την εγκατάσταση, επέλεξα να το εγκαταστήσω στη ριζική μονάδα δίσκου "C: \" αντί για Αρχεία προγράμματος μόνο επειδή χρησιμοποιώ επίσης το cygwin και ήταν ευκολότερο να δημιουργήσω έναν σύνδεσμο από τον τοπικό μου κάδο σε έναν φάκελο ρίζας C: από όλους τους ανακατέψτε τη διαδρομή προς Αρχεία προγράμματος (με κενά, κλπ).

Έτσι, το περιβάλλον και η πορεία του cygwin, κλπ, μοιάζει με αυτό:

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 κάτι άλλο: τη δυνατότητα "cross-compile". Δηλαδή, η δυνατότητα δημιουργίας ενός εκτελέσιμου, όχι για το εγγενές του σύστημα (και τον επεξεργαστή), αλλά για το σύστημα-στόχο (τον μικροελεγκτή 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 ++ για τον cross-compiler. για ενσωματωμένους μικροελεγκτές ARM.

Βήμα 5: Το αρχείο Linker

Το αρχείο Linker
Το αρχείο Linker
Το αρχείο Linker
Το αρχείο Linker

Ας δημιουργήσουμε ένα σενάριο σύνδεσης.

Ένα βασικό μέρος ή μπλοκ σε αυτό το αρχείο θα ήταν η εντολή 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}

Πρέπει λοιπόν να καταλάβουμε πόσο FLASH (για το πρόγραμμα και τις σταθερές μας, κλπ) και πόση RAM (για χρήση από το πρόγραμμα, σωρός και στοίβα, κλπ) για τη συγκεκριμένη πλακέτα μας. Αυτό γίνεται λίγο ενδιαφέρον.

Η ωραία μικρή κάρτα που συνοδεύει το Nucleo λέει ότι έχει μνήμη flash 512 Kbytes και SRAM 80 Kbytes. Ωστόσο, συνδέοντάς το με USB, τοποθετείται ως σύστημα αρχείων με δύο αρχεία και τόσο ο διαχειριστής αρχείων όσο και το GParted υποδεικνύουν ότι έχει πάνω από 540+ Kbytes χώρο. (ΕΜΒΟΛΟ?).

ΑΛΛΑ, προσπαθώντας να διαγράψετε τα δύο αρχεία χρησιμοποιώντας τον διαχειριστή αρχείων, αποσυνδέοντας και επανασυνδέοντας τη συσκευή, εμφανίζει ακόμα τα δύο αρχεία. (και ο διαχειριστής αρχείων όντως αναγνώρισε κάτι επειδή υπάρχει ένα μικρό εικονίδιο "κλειδώματος" σε κάθε αρχείο.

Πάμε λοιπόν με τις φιγούρες στην κάρτα. Τώρα παίρνουμε το παραπάνω παράδειγμα και το μετατρέπουμε στον συγκεκριμένο πίνακα.

Μπορεί να θέλετε να χρησιμοποιήσετε κάτι σαν αυτόν τον μετατροπέα μνήμης στο διαδίκτυο, για να μεταβείτε από τη γενική KB σε συγκεκριμένο αριθμό byte.

Στη συνέχεια, μπορεί να θέλετε να χρησιμοποιήσετε έναν online μετατροπέα δεκαδικών σε εξάγωνο.

/ * Ορίστε το τέλος της μνήμης RAM και το όριο της μνήμης στοίβας */

/* (4KB SRAM στη γραμμή STM32F031x6, 4096 = 0x1000)* //* το παράδειγμα*/

/ * βήμα 1: (80KB SRAM στο STM32F303RE, 81920 = 0x14000) * // * ο πίνακας μας */

/* βήμα 2, προσθέστε το εξάγωνο μέγεθος στη δεκαεξαδική διεύθυνση έναρξης (παρακάτω). */

/ * (Η μνήμη RAM ξεκινά στη διεύθυνση 0x20000000) */

_estack = 0x20001000; /* το παράδειγμα */

_estack = 0x20014000; / * ο πίνακας μας */

ΜΝΗΜΗ {

ΦΛΑΣ (rx): ΠΡΟΕΛΕΥΣΗ = 0x08000000, ΜΗΚΟΣ = 512Κ

RAM (rxw): ΠΡΟΕΛΕΥΣΗ = 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

Χμμ.. Όχι ". Ευθυγράμμιση" Οδηγία

Ωστόσο, αυτό δεν είναι κρίσιμο. Περισσότερα για αυτό (ίσως) αργότερα.

.σύνταξη ενοποιημένη

.σύνταξη [ενοποιημένο | διαιρούμενο]

Αυτή η οδηγία ορίζει τη σύνταξη συνόλου οδηγιών όπως περιγράφεται στην ενότητα ARM-Instruction-set

9.4.2.1 Σύνταξη οδηγιών Σύνταξη Δύο ελαφρώς διαφορετικές συντάξεις υποστηρίζουν οδηγίες ARM και THUMB. Η προεπιλεγμένη, διαιρεμένη, χρησιμοποιεί το παλιό στυλ όπου οι οδηγίες ARM και THUMB είχαν τις δικές τους, ξεχωριστές συντάξεις. Η νέα, ενοποιημένη σύνταξη, η οποία μπορεί να επιλεγεί μέσω της οδηγίας.syntax.

.fpu vfpv4

Ο μεταγλωττιστής GCC μπορεί να παράγει δυαδικά αρχεία με διάφορες επιλογές σχετικά με το κυμαινόμενο σημείο: μαλακό - κατάλληλο για λειτουργία σε CPU χωρίς FPU - οι υπολογισμοί γίνονται στο λογισμικό από softfp που δημιουργείται από μεταγλωττιστή - κατάλληλο για λειτουργία σε CPU με ή χωρίς FPU - θα χρησιμοποιεί FPU εάν υπάρχει Το Για τη συγκεκριμένη περίπτωση (θα πρέπει να κάνετε τη δική σας έρευνα), το FPU του συγκεκριμένου πίνακα συμμορφώνεται με το vfpv4. Youσως χρειαστεί να παίξετε με αυτό. Or ακόμη και αφήστε το σε softfp.

. thumb (έναντι.arm)

Αυτοί οι μικροελεγκτές ARM έχουν στην πραγματικότητα ένα μείγμα σετ εντολών. Το ένα είναι ARM, το άλλο είναι THUMB. Μια διαφορά είναι οι οδηγίες 16-bit έναντι των οδηγιών 32-bit. Έτσι, αυτή η οδηγία λέει στον μεταγλωττιστή να αντιμετωπίσει τις επόμενες οδηγίες ως THUMB ή ARM.

Θα πάρουμε μόνο το υπόλοιπο του αρχείου ως έχει, καθώς αυτά τα Instructables δεν έχουν ακόμη εμβαθύνει στον προγραμματισμό συναρμολόγησης με διακοπή.

Βήμα 7: Η έκδοση συνέλευσης ενός προγράμματος «Hello World»

Τα παρακάτω μπορούν επίσης να μπουν στο αρχείο "core. S" που δημιουργήθηκε προηγουμένως. Αυτό, πάλι, προέρχεται από το παράδειγμα του άρθρου.

/ * * Ο χειριστής επαναφοράς. Καλείται κατά την επαναφορά. */.type reset_handler, %function reset_handler: // Ορίστε τον δείκτη στοίβας στο τέλος της στοίβας. // Η τιμή "_estack" ορίζεται στο σενάριο σύνδεσης. LDR r0, = _estack MOV sp, r0

// Ορίστε κάποιες ομοίωμα τιμών. Όταν βλέπουμε αυτές τις τιμές

// στο πρόγραμμα εντοπισμού σφαλμάτων, θα γνωρίζουμε ότι το πρόγραμμά μας // φορτώνεται στο τσιπ και λειτουργεί. LDR r7, = 0xDEADBEEF MOVS r0, #0 main_loop: // Προσθήκη 1 για εγγραφή 'r0'. ADDS r0, r0, #1 // Επιστροφή βρόχου. B main_loop.size reset_handler,.-Reset_handler

Έτσι, η ώθηση του παραπάνω προγράμματος είναι να φορτώσει ένα αναγνωρίσιμο μοτίβο σε έναν πυρήνα καταχωρητή MCU (στην περίπτωση αυτή R7), και μια αυξανόμενη τιμή που ξεκινά από το μηδέν σε έναν άλλο πυρήνα μητρώο MCU (στην περίπτωση αυτή R0). Αν περάσουμε τον κώδικα εκτέλεσης, θα πρέπει να δούμε την αύξηση των δεδομένων του R0.

Εάν ακολουθήσατε μαζί με το Instructables σχετικά με το MSP432 και το μάθημα/εργαστήρια TI-RSLK, τότε σχεδόν όλα τα παραπάνω προγράμματα θα πρέπει να σας είναι εξοικειωμένα.

Το καινούργιο πράγμα που μπορώ να δω είναι η χρήση του "=" κατά τη φόρτωση του "DEADBEEF" στο για εγγραφή R7. Δεν το είχαμε χρησιμοποιήσει.

Το αρχείο "core. S" που επισυνάπτεται εδώ περιέχει τώρα την πλήρη πηγή.

Βήμα 8: Συγκέντρωση του κώδικα

It'sρθε η ώρα να κάνετε κάποια πράγματα στη γραμμή εντολών. Κάτι αληθινό, επιτέλους.

Ωστόσο, δεν είμαστε αρκετά εκεί. Πρέπει και πάλι να τροποποιήσουμε την εντολή που δίνεται στο άρθρο και να την τροποποιήσουμε στη δική μας κατάσταση.

Ακολουθεί το παράδειγμα του κώδικα:

arm -none -eabi -gcc -x assembler -with -cpp -c -O0 -mcpu = cortex -m0 -mthumb -Πυρήνας τοίχου. S -o core.o

Αν πάμε στον ιστότοπο gnu.org για το GCC, (στην περίπτωση αυτή έκδοση 7.3),

Χ

Το -x είναι για να καθορίσετε τη γλώσσα. Διαφορετικά, αν όχι -x, τότε ο μεταγλωττιστής θα προσπαθήσει να μαντέψει χρησιμοποιώντας την επέκταση αρχείου. (στην περίπτωσή μας, *. S).

Το παραπάνω παράδειγμα από το άρθρο καθορίζει το assembler-with-cpp, αλλά θα μπορούσαμε απλά να κάνουμε assembler.

ντο

Το -c λέει μεταγλώττιση αλλά δεν συνδέεται.

Ο0

Το -O είναι για να ορίσετε το επίπεδο βελτιστοποίησης. Η χρήση του -O0 (oh -zero) λέει "μειώστε το χρόνο μεταγλώττισης και κάντε το σφάλμα να παράγει τα αναμενόμενα αποτελέσματα. Αυτή είναι η προεπιλογή".

mcpu = φλοιός-m0

Το -mcpu καθορίζει το όνομα του επεξεργαστή προορισμού. Στην περίπτωσή μας, θα ήταν φλοιός-m4.

mthumb

Το -mthumb καθορίζει την επιλογή μεταξύ δημιουργίας κώδικα που εκτελεί καταστάσεις ARM και THUMB.

Τείχος

Το -Wall είναι φυσικά πολύ συνηθισμένο και γνωστό. Ενεργοποιεί όλες τις προειδοποιητικές σημαίες.

Τέλος, στο τέλος της εντολής έχουμε το αρχείο εισόδου core. S και το αρχείο εξόδου core.o.

Εδώ είναι η νέα γραμμή εντολών που προκύπτει για να ταιριάζει στη συγκεκριμένη περίπτωσή μας.

arm -none -eabi -gcc -x assembler -c -O0 -mcpu = cortex -m4 -mthumb -Πυρήνας τοίχου. 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

Αυτό είναι λίγο δύσκολο να εξηγηθεί.

Έχει να κάνει με το "semihosting" και "retargeting", και έχει να κάνει με την είσοδο / έξοδο. Έχει επίσης να κάνει με κλήσεις συστήματος και βιβλιοθήκες.

Συνήθως, τα ενσωματωμένα συστήματα δεν παρέχουν τυπικές συσκευές εισόδου/εξόδου. Αυτό θα επηρεάσει τις κλήσεις συστήματος ή βιβλιοθήκης (παράδειγμα: printf ()).

Semihosting σημαίνει ότι ο εντοπισμός σφαλμάτων (βλ. Εικόνα Βήμα 11 με το τμήμα εντοπισμού σφαλμάτων κυκλωμένο με κόκκινο χρώμα) έχει ένα ειδικό κανάλι και χρησιμοποιεί το πρωτόκολλο ημιεπικοινωνίας και μπορείτε να δείτε την έξοδο του printf () στον κεντρικό υπολογιστή (μέσω του εντοπισμού σφαλμάτων).

Η επαναστοχοποίηση, από την άλλη πλευρά, σημαίνει ότι οι ίδιες κλήσεις συστήματος ή βιβλιοθήκης σημαίνουν κάτι άλλο. Κάνουν κάτι άλλο, που έχει νόημα για το ενσωματωμένο σύστημα. Κατά μία έννοια, ας πούμε για το printf (), υπάρχει μια νέα εφαρμογή, μια επανασχεδιασμένη εφαρμογή αυτής της συνάρτησης.

Έχοντας πει όλα αυτά, το --specs = nosys.specs σημαίνει ότι δεν θα κάνουμε ημιεπικοινωνία. Αυτό κανονικά σημαίνει ότι επανατοποθετούμε. Αυτό μας φέρνει στην επόμενη σημαία.

nostdlib

Η επιλογή σύνδεσης -nostdlib χρησιμοποιείται για τη σύνδεση ενός προγράμματος που προορίζεται να τρέξει αυτόνομα. -nostdlib συνεπάγεται τις μεμονωμένες επιλογές -nodefaultlibs και -nostartfiles. Παρακάτω συζητάμε ξεχωριστά τις δύο επιλογές, αλλά η πιο τυπική χρήση είναι απλώς το nostdlib για αγορές μιας στάσης. Κατά τη σύνδεση ενός φιλοξενούμενου προγράμματος, οι τυπικές βιβλιοθήκες συστήματος όπως το libc συνδέονται από προεπιλογή, παρέχοντας στο πρόγραμμα πρόσβαση σε όλες τις τυπικές λειτουργίες (printf, strlen και φίλοι). Η επιλογή σύνδεσης -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

Βεβαιωνόμαστε ότι το αρχείο δέσμης ενεργειών και το αρχείο 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

TestingConnection με το STM32 Nucleo-64
TestingConnection με το STM32 Nucleo-64
TestingConnection με το STM32 Nucleo-64
TestingConnection με το STM32 Nucleo-64

Η πρώτη σας αποστολή, αν επιλέξετε να το αποδεχτείτε, είναι να κάνετε το σύστημά σας να δει τον πίνακα ανάπτυξης.

Χρήση των Windows

Για Windows, αποφάσισα να εγκαταστήσω το TrueSTUDIO από την Atollic (δωρεάν έκδοση). Wasταν μια ανώδυνη εγκατάσταση και εγκατέστησε αυτόματα το πρόγραμμα οδήγησης, ώστε να μπορώ να χρησιμοποιήσω το 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-έρευνα

Και επέστρεψε:

Βρέθηκαν 1 stlink προγραμματιστές

Έτσι τώρα γνωρίζουμε ότι μπορούμε να μιλήσουμε/να ρωτήσουμε τον πίνακα ανάπτυξης.

Χρησιμοποιώντας Linux

Για το linux, δεν χρειάζεστε πραγματικά πρόγραμμα οδήγησης. Αλλά για το Debian, θα πρέπει να δημιουργήσετε τα εργαλεία st από την πηγή.

git clone

Βεβαιωθείτε ότι έχετε εγκαταστήσει το 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 install libusb-dev

Το σωστό devus libusb που λείπει μπορεί να προκαλέσει προβλήματα στο cmake.

Σφάλμα CMake: Οι ακόλουθες μεταβλητές χρησιμοποιούνται σε αυτό το έργο, αλλά έχουν οριστεί σε NOTFOUND. Παρακαλούμε ορίστε τις ή βεβαιωθείτε ότι έχουν οριστεί και δοκιμαστεί σωστά στα αρχεία CMake: LIBUSB_INCLUDE_DIR (ΠΡΟΤΕΡΑ)

Αλλαγή στον ριζικό κατάλογο του έργου (… blah /blah /stlink). Κάνε ένα "make release".

Μετά από αυτήν την κατασκευή, τα εργαλεία πρέπει να βρίσκονται στην ενότητα ".. /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 / x30 / x34 / x39 / x35 / x35 / x36 / x35 / x37 "flash: 524288 (μέγεθος σελίδας: 2048) sram: 65536 chipid: 0x0446 descr: F303 συσκευή υψηλής πυκνότητας devchu@chubox: ~/Development/stlink $./build/Release/st- info --probe Found 0 stlink προγραμματιστές devchu@chubox: ~/Development/stlink $

Βήμα 11: Ας χρησιμοποιήσουμε το GDB με Linux

Ας χρησιμοποιήσουμε το GDB με Linux
Ας χρησιμοποιήσουμε το GDB με Linux
Ας χρησιμοποιήσουμε το GDB με Linux
Ας χρησιμοποιήσουμε το GDB με Linux

Αν τα έχετε δοκιμάσει όλα αυτά και τα έχετε καταφέρει μέχρι εδώ - τέλεια! Εξοχος. Ας διασκεδάσουμε λίγο τώρα.

Όταν αγοράζετε αυτούς τους πίνακες ανάπτυξης ARM, είτε είναι το MSP432 Launchpad από το Texas Instruments, είτε αυτό που συζητάμε τώρα, το Nucleo-F303 (STM32 Nucleo-64), συνήθως φθάνουν ήδη αναβοσβήνουν με ένα πρόγραμμα λειτουργίας, συνήθως κάποιο πρόγραμμα που αναβοσβήνει που περιλαμβάνει επίσης το πάτημα ενός διακόπτη για να αλλάξετε τον ρυθμό με τον οποίο αναβοσβήνουν τα LED.

Πριν σπεύσουμε να γράψουμε υπερβολικά, ας δούμε τι υπάρχει και τι να κάνουμε.

Με το Linux, ανοίξτε ένα τερματικό, αλλάξτε κατάλογο το έργο stlink git που μόλις δημιουργήσαμε και βρείτε το εργαλείο st-util.

devchu@chubox: ~/Development/stlink $ find. -όνομα st-util

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

Εκτελέστε αυτό το εργαλείο. Δεδομένου ότι έχουμε δοκιμάσει ήδη τη σύνδεσή μας με το st-info --probe, θα πρέπει να λάβουμε κάποια έξοδο όπως αυτή:

devchu@chubox: ~/Development/stlink $./build/Release/src/gdbserver/st-util

st-util 1.4.0-50-g7fafee2 2018-10-20T18: 33: 23 ΠΛΗΡΟΦΟΡΙΕΣ common.c: Φόρτωση παραμέτρων συσκευής…. 2018-10-20T18: 33: 23 INFO common.c: Η συνδεδεμένη συσκευή είναι: F303 συσκευή υψηλής πυκνότητας, id 0x10036446 2018-10-20T18: 33: 23 INFO common.c: μέγεθος SRAM: 0x10000 bytes (64 KiB), Flash: 0x80000 bytes (512 KiB) σε σελίδες 2048 byte 2018-10-20T18: 33: 23 INFO gdb-server.c: Το αναγνωριστικό τσιπ είναι 00000446, το Core ID είναι 2ba01477. 2018-10-20T18: 33: 23 INFO gdb-server.c: Ακρόαση στο *: 4242…

Αυτός είναι ο διακομιστής GDB που τρέχει τώρα και βλέπει τον πίνακα ανάπτυξης και, το πιο σημαντικό, ακούει στη θύρα 4242 (η προεπιλεγμένη θύρα).

Τώρα είμαστε έτοιμοι να ενεργοποιήσουμε τον πελάτη GDB.

Στο Linux, ανοίξτε ένα άλλο τερματικό, εισαγάγετε αυτό:

arm-none-eabi-gdb -tui

Αυτό είναι ακριβώς το ίδιο με την εκτέλεση αυστηρά της γραμμής εντολών του gdb, ωστόσο παράγει ένα τερματικό βασισμένο σε κείμενο (η εικασία μου είναι ότι χρησιμοποιεί κατάρες).

Έχουμε τον πελάτη GDB και τον διακομιστή GDB σε λειτουργία. Ωστόσο, ο πελάτης δεν είναι συνδεδεμένος με το διακομιστή. Προς το παρόν δεν γνωρίζει τίποτα για το Nucleo μας (ή σανίδα της επιλογής σας). Πρέπει να το πούμε. Στο τερματικό, η ερώτησή σας θα πρέπει τώρα να είναι η "(gdb)". Εισαγω:

στόχος βοήθειας

Θα σας δώσει μια λίστα. Παρατηρήστε ότι αυτό που θέλουμε είναι στόχος εκτεταμένο -τηλεχειριστήριο - Χρησιμοποιήστε απομακρυσμένο υπολογιστή μέσω σειριακής γραμμής.

Αλλά πρέπει επίσης να του δώσουμε την τοποθεσία. Έτσι, στην προτροπή (gdb), πληκτρολογήστε:

(gdb) στόχος εκτεταμένο-απομακρυσμένο localhost: 4242

Θα πρέπει να λάβετε μια απάντηση κάπως έτσι:

(gdb) στόχος εκτεταμένο-απομακρυσμένο localhost: 4242

Απομακρυσμένη εντοπισμός σφαλμάτων χρησιμοποιώντας localhost: 4242 0x080028e4 σε ?? ()

Εν τω μεταξύ, στο τερματικό που εκτελεί το st-util gdbserver, πήραμε αυτό:

2018-10-20T18: 42: 30 INFO gdb-server.c: Βρέθηκαν 6 hw καταχωρητές breakpoint

2018-10-20T18: 42: 30 INFO gdb-server.c: συνδεδεμένο GDB.

Βήμα 12: Ας επαναλάβουμε, με Windows και Flash το πρόγραμμά μας

Ας επαναλάβουμε, με Windows και Flash το πρόγραμμά μας
Ας επαναλάβουμε, με Windows και Flash το πρόγραμμά μας
Ας επαναλάβουμε, με Windows και Flash το πρόγραμμά μας
Ας επαναλάβουμε, με Windows και Flash το πρόγραμμά μας
Ας επαναλάβουμε, με Windows και Flash το πρόγραμμά μας
Ας επαναλάβουμε, με Windows και Flash το πρόγραμμά μας

Τα βήματα για την εκτέλεση του st-util gdbserver και του προγράμματος-πελάτη arm-none-eabi-gdb είναι ουσιαστικά τα ίδια όπως κάναμε στο προηγούμενο βήμα. Ανοίγετε δύο τερματικά (cygwin, DOS cmd ή Windows Powershell), βρείτε τη θέση του st-util και εκτελέστε το. Στο άλλο τερματικό, εκτελέστε το πρόγραμμα-πελάτη arm-none-eabi-gdb. Η μόνη διαφορά είναι ότι η λειτουργία -tui (προβολή κειμένου βάσει τερματικού) πιθανότατα δεν υποστηρίζεται.

Εάν τα παραπάνω λειτουργούσαν στα Windows, τότε πιθανότατα θα πρέπει να σταματήσετε (μόνο ο πελάτης). Σε αυτό το σημείο, με κάποιο τρόπο θα χρειαστεί να εκτελέσετε το πρόγραμμα -πελάτη GDB όπου βρίσκεται το αρχείο δημιουργίας σας ("core.out") ή να προσθέσετε ολόκληρη τη διαδρομή σε αυτό το αρχείο ως όρισμα στο πρόγραμμα -πελάτη GDB.

Απλοποίησα τη ζωή μου χρησιμοποιώντας το cygwin και δημιουργώντας συνδέσμους από τον τοπικό μου κατάλογο $ HOME // bin στον οποίο βρίσκονται και τα δύο αυτά εργαλεία.

Εντάξει, έχουμε συγκεντρώσει και συνδέσει όπως πριν, και έχουμε το αρχείο main.elf έτοιμο να αναβοσβήνει.

Έχουμε το st-util που τρέχει σε ένα παράθυρο. Ξεκινάμε ξανά τον πελάτη GDB, αυτή τη φορά κάνουμε:

arm-none-eabi-gdb main.elf

Το αφήνουμε να ξεκινήσει, περιμένουμε την προτροπή (gdb), κάνουμε την ίδια εντολή σύνδεσης στον διακομιστή GDB (st-util) και είμαστε έτοιμοι να αναβοσβήσουμε το εκτελέσιμο. Είναι πολύ αντικλιματικό:

(gdb) φορτίο

Λειτουργώντας με τερματικά cygwin, υπάρχει ένα γνωστό πρόβλημα με τις εντολές της κονσόλας να μην εξάγονται. Έτσι, στην περίπτωσή μας, το παράθυρο που εκτελούσε τον διακομιστή ήταν εντελώς αθόρυβο. Αυτό που εκτελεί τον πελάτη, όπου εκτελέσαμε το φορτίο, εξάγει αυτό:

Ενότητα φόρτωσης.text, μέγεθος 0x1c lma 0x8000000 Διεύθυνση εκκίνησης 0x8000000, μέγεθος φόρτωσης 28 Ρυθμός μεταφοράς: 1 KB/sec, 28 bytes/εγγραφή.

Βήμα 13: Αναβοσβήνει με Linux - Περισσότερη ανταμοιβή: D

Αναβοσβήνει με Linux - Περισσότερη ανταμοιβή: D
Αναβοσβήνει με Linux - Περισσότερη ανταμοιβή: D

Βήμα 14: Ας βουτήξουμε λίγο πιο βαθιά

Αν φτάσατε εδώ, εξαιρετικό. Ας προχωρήσουμε.

Γιατί να μην κοιτάξετε μέσα στο αρχείο main.elf, το εκτελέσιμο; Εκτελέστε τα ακόλουθα:

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

Θα πρέπει να δείτε μια έξοδο σαν αυτήν:

main.elf: μορφή αρχείου elf32-littlearm

Αποσυναρμολόγηση τμήματος.text:

08000000:

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

08000008:

8000008: 4802 ldr r0, [τεμ, #8]; (8000014) 800000α: 4685 mov sp, r0 800000c: 4f02 ldr r7, [τεμ, #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.

Στη συνέχεια, παραπάνω, αλλά ένα μεταγενέστερο βήμα, όταν συζητούσαμε το τμήμα "Hello World", υπήρχε μια δήλωση όπου φορτώνουμε μια άμεση, σταθερή, κυριολεκτική τιμή ("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 0xfff00800000000000000000000000000000000000000000000000000000

Στη συνέχεια, στη γραμμή (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 rff 0x00 000000000000000000000000000000000000000000000000000000000 16777216

Τι συνέβη? Ακριβώς αυτό που θέλαμε. Το DEADBEEF φορτώθηκε στο R7 και το R0 αυξήθηκε (εξαιρετικά γρήγορα). Εάν επαναλάβετε, θα δείτε ξανά το R0 με άλλη τιμή.

Βήμα 16: Θέλαμε να δημιουργήσουμε έναν πίνακα μόνο για ανάγνωση στο Flash

Ένας τρόπος για να δημιουργήσετε το ισοδύναμο ενός πίνακα χρησιμοποιώντας τη συναρμολόγηση και τις οδηγίες, είναι ο εξής:

. τύπος myarray, %object // το όνομα ή η ετικέτα "myarray" ορίζεται ως τύπος αντικειμένου.

myarray: // αυτή είναι η αρχή της δήλωσης «myarray» // (από τι θα αποτελείται)..word 0x11111111 // το πρώτο μέλος ή τιμή που περιέχεται στο 'myarray'.. Λέξη 0x22222222 // η δεύτερη τιμή (συνεχόμενες διευθύνσεις)..word 0x33333333 // και ούτω καθεξής..syar myarray, Τώρα που το έχουμε ρυθμίσει στη μνήμη FLASH, μπορούμε να το χρησιμοποιήσουμε στο πρόγραμμα. Παρακάτω είναι ένα τμήμα:

LDR R1, myarray // αυτό φορτώνει τα δεδομένα που περιέχονται στην 1η θέση του "myarray". " // αυτό δεν είναι αυτό που θέλουμε.

LDR R1, = myarray // αυτό φορτώνει την ίδια την τιμή τοποθεσίας (η 1η διεύθυνση), // όχι τα δεδομένα.. // αυτό είναι αυτό που θέλουμε.

Το 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, ώστε να δείχνει σωστά το επόμενο

// διεύθυνση..

Β main_loop // Βρόχος πίσω.

Το βίντεο περνάει από όλα αυτά και υπάρχει ένα σφάλμα σε αυτό. Είναι καλό; δείχνει ότι είναι σημαντικός κώδικας εκτέλεσης και εντοπισμού σφαλμάτων. Δείχνει μια κλασική περίπτωση αποχώρησης από το τέλος ενός πίνακα.

Συνιστάται: