Τηλέφωνο SIP στο STM32F7-Discovery

Γεια σε όλους.

Πριν από λίγο καιρό εμείς писали για το πώς καταφέραμε να κυκλοφορήσουμε ένα τηλέφωνο SIP στο STM32F4-Discovery με 1 MB ROM και 192 KB RAM) με βάση Embox. Εδώ πρέπει να πούμε ότι αυτή η έκδοση ήταν ελάχιστη και συνέδεε δύο τηλέφωνα απευθείας χωρίς διακομιστή και με μετάδοση φωνής μόνο προς μία κατεύθυνση. Ως εκ τούτου, αποφασίσαμε να λανσάρουμε ένα πιο ολοκληρωμένο τηλέφωνο με κλήση μέσω διακομιστή, μετάδοση φωνής και προς τις δύο κατευθύνσεις, αλλά ταυτόχρονα να διατηρείται στο μικρότερο δυνατό μέγεθος μνήμης.


Για το τηλέφωνο, αποφασίστηκε να επιλεγεί μια εφαρμογή simple_pjsua ως μέρος της βιβλιοθήκης PJSIP. Πρόκειται για μια ελάχιστη εφαρμογή που μπορεί να εγγραφεί στον διακομιστή, να λαμβάνει και να απαντά σε κλήσεις. Παρακάτω θα δώσω αμέσως μια περιγραφή του τρόπου εκτέλεσης του στο STM32F7-Discovery.

Πώς να τρέξετε

  1. Διαμόρφωση Embox
    make confload-platform/pjsip/stm32f7cube
  2. Ορίστε τον απαιτούμενο λογαριασμό SIP στο αρχείο conf/mods.config.
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server", 
        sip_user="username",
        sip_passwd="password")
    

    όπου διακομιστής είναι ένας διακομιστής SIP (για παράδειγμα, sip.linphone.org), όνομα χρήστη и κωδικό πρόσβασης - όνομα χρήστη και κωδικός πρόσβασης λογαριασμού.

  3. Συναρμολόγηση του Embox ως ομάδα κάνω. Σχετικά με το υλικολογισμικό της πλακέτας που έχουμε wiki και άρθρο.
  4. Εκτελέστε την εντολή "simple_pjsua_imported" στην κονσόλα Embox
    
    00:00:12.870    pjsua_acc.c  ....SIP outbound status for acc 0 is not active
    00:00:12.884    pjsua_acc.c  ....sip:[email protected]: registration success, status=200 (Registration succes
    00:00:12.911    pjsua_acc.c  ....Keep-alive timer started for acc 0, destination:91.121.209.194:5060, interval:15s
    

  5. Τέλος, μένει να τοποθετήσετε ηχεία ή ακουστικά στην έξοδο ήχου και να μιλήσετε σε δύο μικρά μικρόφωνα MEMS δίπλα στην οθόνη. Καλούμε από Linux μέσω της εφαρμογής simple_pjsua, pjsua. Λοιπόν, ή μπορείτε να χρησιμοποιήσετε οποιοδήποτε άλλο είδος τηλεφώνου.

Όλα αυτά περιγράφονται στο δικό μας wiki.

Πώς φτάσαμε εκεί

Έτσι, αρχικά προέκυψε το ερώτημα σχετικά με την επιλογή μιας πλατφόρμας υλικού. Επειδή ήταν σαφές ότι το STM32F4-Discovery δεν χωρούσε από τη μνήμη, επιλέχθηκε το STM32F7-Discovery. Διαθέτει μονάδα flash 1 MB και μνήμη RAM 256 KB (+ 64 ειδική γρήγορη μνήμη, την οποία θα χρησιμοποιήσουμε επίσης). Επίσης, δεν υπάρχουν πολλές κλήσεις μέσω του διακομιστή, αλλά αποφασίσαμε να προσπαθήσουμε να ταιριάξουμε.

Υπό όρους για τον εαυτό τους, η εργασία χωρίστηκε σε διάφορα στάδια:

  • Εκτέλεση PJSIP σε QEMU. Ήταν βολικό για τον εντοπισμό σφαλμάτων, καθώς είχαμε ήδη υποστήριξη για τον κωδικοποιητή AC97 εκεί.
  • Εγγραφή και αναπαραγωγή φωνής στο QEMU και στο STM32.
  • Μεταφορά μιας εφαρμογής simple_pjsua από το PJSIP. Σας επιτρέπει να εγγραφείτε στον διακομιστή SIP και να πραγματοποιήσετε κλήσεις.
  • Αναπτύξτε τον δικό σας διακομιστή που βασίζεται σε αστερίσκο και δοκιμάστε τον και, στη συνέχεια, δοκιμάστε εξωτερικούς, όπως το sip.linphone.org

Ο ήχος στο Embox λειτουργεί μέσω του Portaudio, το οποίο χρησιμοποιείται επίσης στο PISIP. Τα πρώτα προβλήματα εμφανίστηκαν στο QEMU - Το WAV έπαιζε καλά στα 44100 Hz, αλλά στα 8000 κάτι πήγε στραβά. Αποδείχθηκε ότι ήταν θέμα ρύθμισης της συχνότητας - από προεπιλογή ήταν 44100 στον εξοπλισμό και αυτό δεν άλλαξε προγραμματικά.

Εδώ, ίσως, αξίζει να εξηγήσουμε λίγο πώς παίζεται γενικά ο ήχος. Η κάρτα ήχου μπορεί να ρυθμιστεί σε κάποιον δείκτη σε ένα κομμάτι μνήμης από το οποίο θέλετε να παίξετε ή να ηχογραφήσετε σε μια προκαθορισμένη συχνότητα. Μετά το τέλος του buffer, δημιουργείται μια διακοπή και η εκτέλεση συνεχίζεται με την επόμενη buffer. Το γεγονός είναι ότι αυτά τα buffer πρέπει να συμπληρωθούν εκ των προτέρων κατά την αναπαραγωγή του προηγούμενου. Θα αντιμετωπίσουμε αυτό το πρόβλημα περαιτέρω στο STM32F7.

Στη συνέχεια, νοικιάσαμε έναν διακομιστή και αναπτύξαμε το Asterisk σε αυτόν. Δεδομένου ότι χρειαζόταν πολύς εντοπισμός σφαλμάτων, αλλά δεν ήθελα να μιλήσω πολύ στο μικρόφωνο, ήταν απαραίτητο να κάνω αυτόματη αναπαραγωγή και εγγραφή. Για να γίνει αυτό, επιδιορθώσαμε το simple_pjsua, ώστε να μπορείτε να γλιστρήσετε αρχεία αντί για συσκευές ήχου. Στο PJSIP, αυτό γίνεται πολύ απλά, αφού έχουν την έννοια της θύρας, η οποία μπορεί να είναι είτε συσκευή είτε αρχείο. Και αυτές οι θύρες μπορούν να συνδεθούν ευέλικτα με άλλες θύρες. Μπορείτε να δείτε τον κώδικα στο pjsip μας αποθετήρια. Ως αποτέλεσμα, το σχέδιο ήταν το εξής. Στον διακομιστή Asterisk, ξεκίνησα δύο λογαριασμούς - για Linux και για Embox. Στη συνέχεια, η εντολή εκτελείται στο Embox simple_pjsua_imported, το Embox είναι καταχωρημένο στον διακομιστή, μετά από αυτό καλούμε το Embox από το Linux. Τη στιγμή της σύνδεσης ελέγχουμε στον διακομιστή Asterisk ότι έχει δημιουργηθεί η σύνδεση και μετά από λίγο θα ακούμε ήχο από Linux στο Embox και στο Linux αποθηκεύουμε το αρχείο που παίζεται από το Embox.

Αφού δούλεψε στο QEMU, προχωρήσαμε στη μεταφορά στο STM32F7-Discovery. Το πρώτο πρόβλημα είναι ότι δεν χωρούσαν σε 1 MB ROM χωρίς την ενεργοποιημένη βελτιστοποίηση μεταγλωττιστή "-Os" για το μέγεθος της εικόνας. Γι' αυτό συμπεριλάβαμε το "-Os". Επιπλέον, η ενημέρωση κώδικα απενεργοποίησε την υποστήριξη για C ++, επομένως χρειάζεται μόνο για το pjsua και χρησιμοποιούμε simple_pjsua.

Αφού τοποθετηθεί simple_pjsua, αποφάσισε ότι τώρα υπάρχει η ευκαιρία να το λανσάρει. Πρώτα όμως ήταν απαραίτητο να ασχοληθούμε με την ηχογράφηση και την αναπαραγωγή της φωνής. Το ερώτημα είναι πού να γράψω; Επιλέξαμε εξωτερική μνήμη - SDRAM (128 MB). Μπορείτε να δοκιμάσετε αυτό μόνοι σας:

Δημιουργεί ένα στερεοφωνικό WAV με συχνότητα 16000 Hz και διάρκεια 10 δευτερολέπτων:


record -r 16000 -c 2 -d 10000 -m C0000000

Χάνουμε:


play -m C0000000

Εδώ υπάρχουν δύο προβλήματα. Χρησιμοποιείται το πρώτο με τον κωδικοποιητή - WM8994 και έχει μια υποδοχή, και υπάρχουν 4 από αυτές τις υποδοχές. Έτσι, από προεπιλογή, εάν αυτό δεν έχει ρυθμιστεί, τότε κατά την αναπαραγωγή ήχου, η αναπαραγωγή γίνεται και στις τέσσερις υποδοχές . Επομένως, σε συχνότητα 16000 Hz, λάβαμε 8000 Hz, αλλά για 8000 Hz, η αναπαραγωγή απλά δεν λειτούργησε. Όταν επιλέχθηκαν μόνο οι υποδοχές 0 και 2, λειτούργησε όπως θα έπρεπε. Ένα άλλο πρόβλημα ήταν η διεπαφή ήχου στο STM32Cube, στην οποία η έξοδος ήχου λειτουργεί μέσω SAI (Serial Audio Interface) ταυτόχρονα με την είσοδο ήχου (δεν κατάλαβα τις λεπτομέρειες, αλλά αποδεικνύεται ότι μοιράζονται ένα κοινό ρολόι και όταν Η έξοδος ήχου έχει αρχικοποιηθεί, ο ήχος συνδέεται με κάποιο τρόπο στην είσοδο του). Δηλαδή, δεν μπορείτε να τα εκτελέσετε ξεχωριστά, επομένως κάναμε τα εξής - η είσοδος ήχου και η έξοδος ήχου λειτουργούν πάντα (συμπεριλαμβανομένων των διακοπών που δημιουργούνται). Αλλά όταν δεν αναπαράγεται τίποτα στο σύστημα, τότε απλώς εισάγουμε ένα κενό buffer στην έξοδο ήχου και όταν ξεκινά η αναπαραγωγή, αρχίζουμε ειλικρινά να το γεμίζουμε.

Επιπλέον, συναντήσαμε το γεγονός ότι ο ήχος κατά την εγγραφή φωνής ήταν πολύ ήσυχος. Αυτό οφείλεται στο γεγονός ότι τα μικρόφωνα MEMS στο STM32F7-Discovery κατά κάποιο τρόπο δεν λειτουργούν καλά σε συχνότητες κάτω από 16000 Hz. Επομένως, ορίζουμε 16000 Hz, ακόμα κι αν έρθουν 8000 Hz. Για να γίνει αυτό, όμως, ήταν απαραίτητο να προστεθεί μια μετατροπή λογισμικού μιας συχνότητας σε μια άλλη.

Στη συνέχεια, έπρεπε να αυξήσω το μέγεθος του σωρού, το οποίο βρίσκεται στη μνήμη RAM. Σύμφωνα με τους υπολογισμούς μας, το pjsip απαιτούσε περίπου 190 KB και μας απομένουν μόνο περίπου 100 KB. Εδώ έπρεπε να χρησιμοποιήσω κάποια εξωτερική μνήμη - SDRAM (περίπου 128 KB).

Μετά από όλες αυτές τις επεξεργασίες, είδα τα πρώτα πακέτα μεταξύ Linux και Embox και άκουσα τον ήχο! Αλλά ο ήχος ήταν τρομερός, καθόλου ο ίδιος όπως στο QEMU, ήταν αδύνατο να διακρίνει κανείς τίποτα. Μετά σκεφτήκαμε τι μπορεί να φταίει. Ο εντοπισμός σφαλμάτων έδειξε ότι το Embox απλά δεν έχει χρόνο να γεμίσει / ξεφορτώσει τα buffer ήχου. Ενώ το pjsip επεξεργαζόταν ένα πλαίσιο, είχαν χρόνο να εμφανιστούν 2 διακοπές σχετικά με την ολοκλήρωση της επεξεργασίας του buffer, κάτι που είναι πάρα πολύ. Η πρώτη σκέψη για την ταχύτητα ήταν η βελτιστοποίηση μεταγλωττιστή, αλλά είχε ήδη συμπεριληφθεί στο PJSIP. Το δεύτερο είναι ένα υλικό κινητής υποδιαστολής, το συζητήσαμε άρθρο. Αλλά όπως έδειξε η πρακτική, το FPU δεν έδωσε σημαντική αύξηση στην ταχύτητα. Το επόμενο βήμα ήταν να δοθεί προτεραιότητα στα νήματα. Το Embox έχει διαφορετικές στρατηγικές προγραμματισμού και έχω συμπεριλάβει μία που υποστηρίζει προτεραιότητες και ορίζει τις ροές ήχου στην υψηλότερη προτεραιότητα. Ούτε αυτό βοήθησε.

Η επόμενη ιδέα ήταν ότι εργαζόμαστε με εξωτερική μνήμη και θα ήταν ωραίο να μεταφέρουμε δομές εκεί που έχουν εξαιρετικά συχνά πρόσβαση. Έκανα μια προκαταρκτική ανάλυση για το πότε και κάτω από τι simple_pjsua εκχωρεί μνήμη. Αποδείχθηκε ότι από τα 190 Kb, τα πρώτα 90 Kb διατίθενται για εσωτερικές ανάγκες του PJSIP και δεν είναι πολύ συχνά προσβάσιμα. Επιπλέον, κατά τη διάρκεια μιας εισερχόμενης κλήσης, καλείται η συνάρτηση pjsua_call_answer, στην οποία στη συνέχεια εκχωρούνται buffer για εργασία με εισερχόμενα και εξερχόμενα πλαίσια. Ήταν ακόμα περίπου 100 Kb. Και μετά κάναμε το εξής. Μέχρι τη στιγμή της κλήσης τοποθετούμε τα δεδομένα στην εξωτερική μνήμη. Μόλις γίνει η κλήση, αντικαθιστούμε αμέσως το σωρό με ένα άλλο - σε RAM. Έτσι, όλα τα «καυτά» δεδομένα μεταφέρθηκαν σε ταχύτερη και πιο προβλέψιμη μνήμη.

Ως αποτέλεσμα, όλα αυτά μαζί κατέστησαν δυνατή την εκτόξευση simple_pjsua και καλέστε μέσω του διακομιστή σας. Και μετά μέσω άλλων διακομιστών όπως ο sip.linphone.org.

Ευρήματα

Ως αποτέλεσμα, ήταν δυνατή η εκτόξευση simple_pjsua με μετάδοση φωνής και προς τις δύο κατευθύνσεις μέσω του διακομιστή. Το πρόβλημα με επιπλέον δαπανημένα 128 KB SDRAM μπορεί να λυθεί χρησιμοποιώντας ένα ελαφρώς πιο ισχυρό Cortex-M7 (για παράδειγμα, STM32F769NI με 512 KB μνήμης RAM), αλλά ταυτόχρονα, δεν έχουμε χάσει την ελπίδα μας να μπούμε στο 256 KB 🙂 Θα χαρούμε αν κάποιος ενδιαφέρεται, ή καλύτερα, δοκιμάστε το. Όλες οι πηγές, ως συνήθως, βρίσκονται στο δικό μας αποθετήρια.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο