Το σύστημα IoT περιλαμβάνει μικροελεγκτής με ARM Cortex-M, RISC-V, AVR, και ιδιόκτητες αρχιτεκτονικές, ο καθένας με μοναδικούς χάρτες μνήμης, περιφερειακά μητρώα και ιδιοτροπίες μεταγλωττιστών. Χωρίς σκόπιμο σχεδιασμό για τη φορητότητα, ο κώδικας που λειτουργεί σε έναν άλλο συχνά σπάει, οδηγώντας σε δαπανηρές διορθώσεις και εφιάλτες συντήρησης. Αυτό το άρθρο παρέχει έναν διευρυμένο οδηγό για την επίτευξη πραγματικής φορητότητας σε ενσωματωμένα C, καλύπτοντας τόσο στρατηγικές προσεγγίσεις όσο και πρακτικές τακτικές.

Κατανόηση της φορητότητας στην ανάπτυξη του IoT

Η φορητότητα σημαίνει ότι ο πηγαίος κώδικας μπορεί να συνταχθεί και να λειτουργήσει σε διαφορετικές αρχιτεκτονικές υλικού με μικρή ή καμία τροποποίηση. Στον κόσμο IoT, η φορητότητα δεν είναι απλά μια ευκολία ⁇ είναι μια επιχειρηματική απαίτηση. Οι κύκλοι ζωής των προϊόντων είναι μεγάλες, οι αλυσίδες εφοδιασμού μετατοπίζονται, και το νέο πυρίτιο εμφανίζεται συνεχώς. Μια φορητή βάση κώδικα σας επιτρέπει να επαναχρησιμοποιήσετε το υπάρχον firmware στις γενιές των προϊόντων, γρήγορα να ανατρέχετε σε εναλλακτικά συστατικά κατά τη διάρκεια των ελλείψεων, και να μειώσετε το χρόνο ⁇ σε ⁇ αγορά για παράγωγα προϊόντα.

Στο ένα άκρο, ο κώδικας που είναι εντελώς ανεξάρτητος από την πλατφόρμα (π.χ. αλγόριθμοι γενικής διαλογής) μεταγλωττίζει οπουδήποτε. Στο άλλο άκρο, ο κώδικας που χειρίζεται άμεσα τα μητρώα υλικού είναι εγγενώς μη ⁇ φορητός. Ο στόχος του φορητού C για το IoT είναι να απομονώσει μη ⁇ φορέσιμες λεπτομέρειες πίσω από τα στρώματα αφαίρεσης, έτσι ώστε η βασική επιχειρηματική λογική και ο κώδικας αλγορίθμου να παραμείνει επαναχρησιμοποιήσιμος.

Κοινές προκλήσεις για τη φορητότητα κώδικα

Αρκετές διαφορές χαμηλού επιπέδου πλήττουν την ενσωματωμένη φορητότητα C:

  • Η Ενδικότητα. ARM Cortex ⁇ M και AVR είναι μικρές ⁇ endian· κάποιες παλαιότερες αρχιτεκτονικές (π.χ., Freescale HC12) είναι μεγάλες ⁇ endian. Απευθείας χυτά δείκτες ή σωματεία σε byte εντολές οδηγούν σε σιωπηλή φθορά δεδομένων.
  • Σχεδόν και ορισμοί τύπων λέξεων. Ένα μπορεί να είναι 16 bits σε AVR 8 ⁇ bit, 32 bits σε Cortex ⁇ M0, και 64 bits σε επεξεργαστή RISC ⁇ V 64 ⁇ bit. Ο κώδικας που υποθέτει είναι ακριβώς 32 bits θα σπάσει.
  • Εγγραφή διαφορές χάρτη. Ακόμη και δύο MCU από τον ίδιο πωλητή συχνά έχουν διαφορετικές περιφερειακές διευθύνσεις βάσης, πεδία bit, και ακολουθίες ρυθμίσεων.
  • Επεκτάσεις και πραγματάκια compiler. GCC, IAR, ARM Compiler 6, και Keil κάθε μία έχουν τις δικές τους συντακτικές και inline διαλέκτους συναρμολόγησης.
  • Αναμνηστική διάταξη και ευθυγράμμιση. Ορισμένες πλατφόρμες απαιτούν αυστηρή ευθυγράμμιση για πρόσβαση 32-bit· άλλες χειρίζονται λανθασμένη πρόσβαση με χειριστή ελαττωμάτων.
  • Διακοπή χειρισμού και στοίβας χρήση. Διακόπτες διανυσματικών διανυσματικών φορέων, μοντέλα προτεραιότητας και συμπεριφορά φωλιάσματος ποικίλουν ευρέως.

Βασικές στρατηγικές για τη συγγραφή Φορητό κώδικα Γ

Στρώσεις αφαίρεσης υλικού (HAL)

Το πιο ισχυρό εργαλείο στο φορητό-κωδικό οπλοστάσιο είναι ένα Hardware abstraction layer]. Ένα καλά σχεδιασμένο HAL εκθέτει ένα ομοιόμορφο API για κοινά περιφερειακά (GPIO, UART, I2C, SPI, χρονοδιακόπτες) ενώ κρύβει το υποκείμενο μητρώο ⁇ bashing. Η διεπαφή πρέπει να ορίζεται σε μια κεφαλίδα (π.χ., ) που δηλώνει λειτουργίες όπως και . Χωριστά αρχεία πηγής εφαρμόζουν αυτές τις λειτουργίες για κάθε πλατφόρμα-στόχο. Ο κωδικός εφαρμογής δεν περιλαμβάνει ποτέ ] περιλαμβάνει μια κεφαλή-ειδική κεφαλίδα μητρώου άμεσα ⁇ αυτό περιλαμβάνει μόνο τη διεπαφή HAL.

Ένα τυπικό πρότυπο εφαρμογής HAL μοιάζει με αυτό:

// hal_gpio.h (common)
typedef uint8_t gpio_pin_t;
typedef uint8_t gpio_port_t;
void hal_gpio_set_output(gpio_port_t port, gpio_pin_t pin);
void hal_gpio_set_high(gpio_port_t port, gpio_pin_t pin);
void hal_gpio_set_low(gpio_port_t port, gpio_pin_t pin);

Τα ειδικά αρχεία πλατφόρμας (π.χ., ) περιέχουν το πραγματικό μητρώο γράφει. Όταν μετακινούνται σε ένα νέο MCU, μόνο οι πηγές HAL χαμηλού επιπέδου χρειάζονται επαναγραφή, ενώ όλα τα υψηλότερα στρώματα παραμένουν ανέγγιχτα.

Υιοθετώντας τις Τυπικές Βιβλιοθήκες

Λειτουργίες όπως [[LFT:8]], [[LFT:9]], οι επιχειρήσεις εγχόρδων και οι λειτουργίες μαθηματικών είναι διαθέσιμες σε κάθε μεταγλωττιστή C που συμμορφώνεται. Αποφυγή υποθέσεων για εσωτερικά βιβλιοθήκη είναι κρίσιμη - ποτέ δεν ξαναγράψει [[LFT:10]] για την απόδοση, εκτός αν έχετε επιβεβαιώσει ότι η υλοποίηση του μεταγλωττιστή σας είναι ανεπαρκής.

Για συστήματα IoT με περιορισμένη μνήμη, σκεφτείτε να χρησιμοποιήσετε ένα υποσύνολο της τυποποιημένης βιβλιοθήκης (όπως [[LFT:0]]] newlib ⁇ nano[[LFT:1]] στο οικοσύστημα του GCC) αντί να κυλήσετε τις δικές σας σειρές ⁇ τίνες. Παρομοίως, η [[LFT:11]] μακροεντολή και [[LFT:12]] είναι παγκοσμίως διαθέσιμες. Σύνδεσμος: Η [[LFT:2]]GNU C Βιβλιοθήκη τεκμηρίωση[[[LPT:3]] είναι μια εξαιρετική αναφορά για την κατανόηση του τι είναι εγγυημένο φορητό.

Χρήση τύπων δεδομένων σταθερού πλάτους

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

Όταν πρέπει να σειριαστείτε τα δεδομένα σε byte ⁇ προσανατολισμένες μεταφορές, συνδυάστε τους τύπους σταθερού πλάτους με τις ⁇ ητές λειτουργίες μετατροπής byte ⁇ order ([[[LFT:24]]], [[LFT:25]]], ή τα φορητά ισοδύναμα τους). Ποτέ απλά δεν ρίχνετε ένα [[LFT:26]] σε ένα [[LFT:27]]] και το στέλνετε μέσω ενός δικτύου ⁇ ηendianness θα σας δαγκώσει.

Σύνταξη υπό όρους

Οι οδηγίες προεπεξεργαστών αποτελούν νόμιμο εργαλείο για τον κώδικα πλατφόρμας ⁇ ειδικό, αλλά πρέπει να χρησιμοποιούνται συνετή. Καθορίστε ένα μικρό σύνολο μακροεντολών διαμόρφωσης σε μια ενιαία κεντρική κεφαλίδα (π.χ., ) αντί να διασκορπίζετε [[LFT:29]] μέσω κάθε αρχείου. Παράδειγμα:

// platform_config.h
#if defined(STM32L4)
 #define PLATFORM_STM32L4
#elif defined(EFM32GG)
 #define PLATFORM_EFM32GG
#else
 #error "Unsupported platform"
#endif

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

Ελαχιστοποίηση των εξωτερικών εξαρτήσεων

Κάθε βιβλιοθήκη τρίτου μέρους που περιλαμβάνει είναι ένας πιθανός κίνδυνος φορητότητας. Πριν προσθέσετε μια εξάρτηση, επαληθεύστε ότι υποστηρίζει όλες τις αρχιτεκτονικές σας στόχο και ότι δεν τραβά σε μη -φορτή παραδοχές. Οι βιβλιοθήκες που είναι γραμμένα εξ ολοκλήρου σε φορητή C (π.χ., FatFS] ή [FreeRTOS]) είναι ασφαλέστερες από αυτές που βασίζονται σε inline συναρμολόγηση ή μεταγλωττιστή ⁇ ειδικά pragmas. Ακόμα και τότε, σκεφτείτε να τυλίξετε τη βιβλιοθήκη με τη δική σας λεπτή αφαίρεση ώστε να μπορείτε να την ανταλλάξετε αργότερα χωρίς να αγγίξετε τον κώδικα εφαρμογής.

Link: Το άρθρο Embededed.com για τον πραγματικό ⁇ κόσμο φορητό κώδικα C προσφέρει πρόσθετη προοπτική για τη διαχείριση εξαρτήσεων.

Πρακτικές Συμβουλές για την Ενίσχυση της Φορησιμότητας

Εγγραφή τροποποιητικού κώδικα

Διαλύστε το λογισμικό σας σε ανεξάρτητες ενότητες με καλά καθορισμένες διεπαφές. Κάθε μονάδα θα πρέπει να εκθέσει τη λειτουργικότητα του μέσω ενός αρχείου κεφαλίδας και να κρύψει τις εσωτερικές λεπτομέρειες του. Αυτός ο διαχωρισμός των ανησυχιών καθιστά εύκολη την αντικατάσταση μιας μονάδας με μια φορητή έκδοση κατά τη μεταφορά σε μια νέα πλατφόρμα. Για παράδειγμα, μια μονάδα ελέγχου κινητήρα θα πρέπει να μιλήσει σε ένα HAL για την έξοδο PWM, όχι άμεσα σε ένα περιφερειακό αρχείο χρονόμετρο.

Εξαρτήσεις υλικού εγγράφου

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

Χρήση εργαλείων κατασκευής σταυρών ⁇ πλατφόρμων

Κατασκευή συστημάτων όπως [[LFT:0]]CMake ή [[LFT:2]]Η Meson[ μπορεί να διαχειριστεί πολλαπλές ρυθμίσεις στόχων από μια δομή έργου. CMake, για παράδειγμα, σας επιτρέπει να καθορίσετε αρχεία αλυσίδας εργαλείων για κάθε πλατφόρμα και να ορίσετε ορισμούς μεταγλώττισης με βάση τον στόχο. Αυτό εξαλείφει την ανάγκη για χειροκίνητη διατήρηση χωριστών αρχείων έργου για IAR, Keil, και GCC. Σύνδεσμος: Η [[LFT:4]CMake τεκμηρίωση[[LFT:5]]] παρέχει εκτεταμένα παραδείγματα δημιουργίας διασταυρούμενων ⁇ υπολογιστικών αρχείων.

Χρήση φορητών τεχνικών διαχείρισης bit

Κατά τη ρύθμιση ή εκκαθάριση bits σε μητρώα, αποφύγετε τη γραφή απόλυτη μάσκες που αναλαμβάνουν θέσεις bit ⁇ field. Αντ 'αυτού, χρησιμοποιήστε συμβολικές σταθερές που ορίζονται στο HAL, και να χρησιμοποιήσετε μακροεντολές ή λειτουργίες inline για ασφαλείς λειτουργίες bit:

#define BIT_SET(reg, bit) ((reg) |= (1u << (bit)))
#define BIT_CLEAR(reg, bit) ((reg) &= ~(1u << (bit)))

Καθορίστε ως αφηρημένη παράμετρο και όχι ως κυριολεκτικό ακέραιο. Με αυτόν τον τρόπο, αν η θέση bit αλλάζει σε διαφορετικό MCU, μόνο ο σταθερός ορισμός πρέπει να αλλάξει, όχι η χρήση σε όλη τη βάση κώδικα.

Δοκιμή και επικύρωση σε όλες τις πλατφόρμες

Για τις λειτουργικές δοκιμές, βάλτε εξομοιωτές (π.χ., QEMU για ARM ή Renode για RISC ⁇ V) για να προσομοιώσετε την εκτέλεση χωρίς υλικό. Όταν το υλικό είναι διαθέσιμο, διατηρεί μια μικρή «φάρμακα hardware» αντιπροσωπευτικών συσκευών για τακτικές δοκιμές καπνού.

Οι δοκιμές οπισθοδρόμησης θα πρέπει να ασκούν όλα τα API HAL σε κάθε πλατφόρμα για να πιάσει ασυμβατότητες νωρίς. Μια δοκιμή όπως “γράψτε ένα byte σε ένα UART, διαβάστε το πίσω σε ένα loopback” θα εκθέσουν το χρονοδιάγραμμα ή τις διαφορές διαμόρφωσης μεταξύ των υλοποιήσεων UART.

Συμπέρασμα

Η εγγραφή φορητών C κώδικα για συσκευές IoT δεν είναι μια μετασκέψη ⁇ είναι μια πειθαρχία που πρέπει να ψηθεί στην αρχιτεκτονική από την πρώτη ημέρα. Με την επένδυση σε ένα στρώμα αφαίρεσης υλικού, προσκολλώνται σε τυπικούς τύπους και βιβλιοθήκες, χρησιμοποιώντας υπό όρους συλλογή φειδωλή, και δοκιμές αυστηρά σε όλους τους στόχους, δημιουργεί firmware που μπορεί να επιβιώσει από τις αναπόφευκτες αλλαγές στο τοπίο υλικού. Η προκαταβολική προσπάθεια πληρώνει μερίσματα στη μειωμένη συντήρηση, ταχύτερη μεταφορά στο νέο πυρίτιο, και μεγαλύτερη ανθεκτικότητα στην παροχή ⁇ αλυσιδωτές διαταραχές. Αρχίστε την εφαρμογή αυτών των στρατηγικών σήμερα για να το μέλλον ⁇ απόδειξη ενσωματωμένα έργα C σας.