Téléphone SIP sur STM32F7-Discovery

Bonjour Ă  tous.

Il y a quelque temps, nous ont écrit avons réussi à faire fonctionner un téléphone SIP sur STM32F4-Discovery avec 1 Mo de ROM et 192 Ko de RAM) basé sur Embox. Il faut dire que cette version était minimale et connectait deux téléphones directement sans serveur, et le transfert de voix n'était qu'unidirectionnel. Nous avons donc décidé de lancer un téléphone plus complet, capable de passer des appels via un serveur, avec une transmission de voix dans les deux sens, tout en optimisant l'utilisation de la mémoire.

Lire la vidéo

Pour le téléphone, nous avons choisi l'application simple_pjsua faisant partie de la bibliothÚque PJSIP. C'est une application minimale qui peut s'enregistrer sur un serveur, recevoir et répondre à des appels. Ci-dessous, je vais tout de suite décrire comment la lancer sur STM32F7-Discovery.

Comment démarrer

  1. Configurer Embox
    make confload-platform/pjsip/stm32f7cube
  2. Dans le fichier conf/mods.config, définissez le compte SIP nécessaire.
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server", 
        sip_user="username",
        sip_passwd="password")
    

    oĂč serveur — c'est le serveur SIP (par exemple, sip.linphone.org), username et password — le nom d'utilisateur et le mot de passe du compte.

  3. Nous construisons Embox avec la commande make. Nous avons des informations sur le flashage de la carte sur wiki et dans article.
  4. Lancez la commande Embox “simple_pjsua_imported” dans la console
    
    00:00:12.870    pjsua_acc.c  ....Le statut sortant SIP pour acc 0 n'est pas actif
    00:00:12.884    pjsua_acc.c  ....sip:alexk2222@sip.linphone.org: enregistrement réussi, statut=200 (Enregistrement réussi
    00:00:12.911    pjsua_acc.c  ....Le minuteur de maintien actif a été démarré pour acc 0, destination:91.121.209.194:5060, intervalle:15s
    

  5. Enfin, il reste à brancher des haut-parleurs ou des écouteurs à la sortie audio, et à parler dans deux petits microphones MEMS prÚs de l'écran. Appelons depuis Linux via l'application simple_pjsua, pjsua. Ou nous pourrions utiliser n'importe quelle autre application comme linphone.

Tout cela est décrit sur notre wiki.

Comment nous y sommes arrivés

Alors, la question initiale Ă©tait de choisir une plateforme matĂ©rielle. Étant donnĂ© que nous savions que le STM32F4-Discovery ne convenait pas en termes de mĂ©moire, nous avons optĂ© pour le STM32F7-Discovery. Celui-ci dispose de 1 Mo de flash et de 256 Ko de RAM (+ 64 Ko de mĂ©moire rapide spĂ©ciale, que nous allons Ă©galement utiliser). Ce n'est pas beaucoup pour des appels via un serveur, mais nous avons dĂ©cidĂ© de tenter le coup.

Nous avons conditionnellement divisé la tùche en plusieurs étapes :

  • DĂ©marrer PJSIP sur QEMU. Cela Ă©tait pratique pour le dĂ©bogage, plus nous avions dĂ©jĂ  un support pour le codec AC97.
  • Enregistrement de la voix et reproduction sur QEMU et sur STM32.
  • Portage de l'application simple_pjsua de la bibliothĂšque PJSIP. Elle permet de s'enregistrer sur un serveur SIP et de passer des appels.
  • DĂ©ployer votre propre serveur basĂ© sur Asterisk et tester dessus, avant d'essayer des externes, comme sip.linphone.org.

Le son dans Embox fonctionne via Portaudio, qui est Ă©galement utilisĂ© dans PISIP. Quelques problĂšmes sont apparus sur QEMU — les fichiers WAV Ă  44100 Hz se sont bien jouĂ©s, mais Ă  8000, quelque chose ne fonctionnait clairement pas. Il s'est avĂ©rĂ© que le problĂšme venait de la configuration de la frĂ©quence — par dĂ©faut, dans le matĂ©riel, elle Ă©tait Ă  44100, et cela n'a pas Ă©tĂ© changĂ© par logiciel.

Il convient peut-ĂȘtre d'expliquer un peu comment se dĂ©roule la lecture du son. Une carte audio peut se voir attribuer un pointeur vers une zone mĂ©moire, Ă  partir de laquelle il faut lire ou enregistrer Ă  une frĂ©quence préétablie. Une fois que le tampon est Ă©puisĂ©, une interruption est gĂ©nĂ©rĂ©e, et l'exĂ©cution reprend avec le tampon suivant. Le fait est qu'il faut remplir ces tampons Ă  l'avance, tant que le prĂ©cĂ©dent est en cours de lecture. Nous allons rencontrer ce problĂšme plus tard sur STM32F7.

Ensuite, nous avons louĂ© un serveur et dĂ©ployĂ© Asterisk dessus. Comme il fallait dĂ©boguer beaucoup et que nous ne souhaitions pas parler dans le microphone, nous devions mettre en place une lecture et un enregistrement automatiques. Pour cela, nous avons patchĂ© simple_pjsua afin de pouvoir insĂ©rer des fichiers Ă  la place des pĂ©riphĂ©riques audio. Dans PJSIP, cela se fait assez simplement, car ils ont le concept de port, qui peut ĂȘtre Ă  la fois un pĂ©riphĂ©rique et un fichier. Et ces ports peuvent ĂȘtre connectĂ©s de maniĂšre flexible Ă  d'autres ports. Vous pouvez consulter le code dans notre pjsip. dĂ©pĂŽts. En fin de compte, le schĂ©ma Ă©tait le suivant. Sur le serveur Asterisk, j'ai créé deux comptes — un pour Linux et un pour Embox. Ensuite, sur Embox, la commande est exĂ©cutĂ©e simple_pjsua_imported, Embox s'enregistre sur le serveur, puis nous appelons Embox depuis Linux. Au moment de la connexion, nous vĂ©rifions sur le serveur Asterisk que toute la connexion est Ă©tablie, et aprĂšs un certain temps, nous devrions entendre le son provenant de Linux dans Embox, et sur Linux, nous sauvegardons le fichier qui est jouĂ© depuis Embox.

Une fois que cela a fonctionnĂ© sur QEMU, nous sommes passĂ©s Ă  la portabilitĂ© sur STM32F7-Discovery. Le premier problĂšme — nous ne tenions pas dans 1 Mo de ROM sans activer l'optimisation du compilateur “-Os” pour rĂ©duire la taille de l'image. Donc, nous avons activĂ© “-Os”. Ensuite, nous avons dĂ©sactivĂ© le support de C++ par patch, car cela n'est nĂ©cessaire que pour pjsua, et nous utilisons simple_pjsua.

Une fois que nous avons rĂ©ussi Ă  intĂ©grer simple_pjsua, nous avons dĂ©cidĂ© que les chances de le lancer Ă©taient dĂ©sormais rĂ©elles. Mais d'abord, il fallait se pencher sur l'enregistrement et la lecture de la voix. La question se posait — oĂč enregistrer ? Nous avons choisi la mĂ©moire externe — SDRAM (128 Mo). Vous pouvez essayer vous-mĂȘme :

Créera un WAV stéréo à 16000 Hz et d'une durée de 10 secondes :


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

Lecture :


play -m C0000000

Il y avait deux problĂšmes. Le premier concernait le codec — le WM8994, qui a un concept de slot, et il y a quatre slots. Par dĂ©faut, si ce n'est pas configurĂ©, lors de la lecture audio, cela se produit dans les quatre slots. Donc, Ă  16000 Hz, nous obtenions 8000 Hz, et pour 8000 Hz, la lecture ne fonctionnait tout simplement pas. Quand nous avons choisi uniquement les slots 0 et 2, cela a bien fonctionnĂ©. Un autre problĂšme Ă©tait l'interface audio dans STM32Cube, oĂč la sortie audio fonctionne via SAI (Serial Audio Interface) synchronisĂ©e avec l'entrĂ©e audio (je n'ai pas approfondi les dĂ©tails, mais il semble qu'ils partagent un horloge commune et lors de l'initialisation de la sortie audio, l'entrĂ©e audio s'y attache d'une certaine maniĂšre). Donc, ils ne peuvent pas ĂȘtre lancĂ©s sĂ©parĂ©ment, c'est pourquoi nous avons fait ce qui suit — l'entrĂ©e audio et la sortie audio fonctionnent toujours (y compris la gĂ©nĂ©ration d'interruptions). Mais quand rien n'est jouĂ© dans le systĂšme, nous fournissons simplement un tampon vide Ă  la sortie audio, et quand la lecture dĂ©marre, nous commençons Ă  le remplir correctement.

Ensuite, nous avons rencontrĂ© le problĂšme que le son lors de l'enregistrement de la voix Ă©tait trĂšs faible. Cela se produit parce que les microphones MEMS sur l'STM32F7-Discovery fonctionnent mal Ă  des frĂ©quences infĂ©rieures Ă  16000 Hz. Nous rĂ©glons donc Ă  16000 Hz, mĂȘme s'il arrive Ă  8000 Hz. Pour cela, il a fallu ajouter une conversion logicielle d'une frĂ©quence Ă  une autre.

Nous avons ensuite dĂ» augmenter la taille du tas, qui se trouve dans la RAM. Selon nos calculs, pjsip nĂ©cessitait environ 190 Ko, tandis que nous n'avions plus qu'environ 100 Ko disponibles. Nous avons donc dĂ» utiliser un peu de mĂ©moire externe — SDRAM (environ 128 Ko).

AprĂšs toutes ces modifications, j'ai vu les premiers paquets entre Linux et Embox, et j'ai entendu du son ! Mais le son Ă©tait horrible, rien Ă  voir avec QEMU, et rien n'Ă©tait comprĂ©hensible. Nous nous sommes donc demandĂ© quelle pouvait ĂȘtre la cause. Le dĂ©bogage a montrĂ© qu'Embox avait simplement du mal Ă  remplir/vider les tampons audio. Pendant que pjsip traitait un cadre, deux interruptions de fin de traitement des buffers se produisaient, ce qui Ă©tait trop. La premiĂšre idĂ©e pour accĂ©lĂ©rer le processus Ă©tait l'optimisation du compilateur, mais elle Ă©tait dĂ©jĂ  activĂ©e dans PJSIP. DeuxiĂšmement — le point flottant matĂ©riel, dont nous avons parlĂ© dans article. Mais comme l'expĂ©rience l'a montrĂ©, le FPU n'a pas apportĂ© de gain de vitesse significatif. La prochaine Ă©tape a Ă©tĂ© de dĂ©finir les prioritĂ©s des flux. Dans Embox, il existe diffĂ©rentes stratĂ©gies de planification, et j'ai activĂ© celle qui prend en charge les prioritĂ©s, attribuant la prioritĂ© la plus Ă©levĂ©e aux flux audio. Cela n'a pas non plus aidĂ©.

L'idĂ©e suivante Ă©tait que nous travaillons avec de la mĂ©moire externe et qu'il serait donc judicieux d'y dĂ©placer les structures auxquelles nous accĂ©dons trĂšs frĂ©quemment. J'ai rĂ©alisĂ© une analyse prĂ©liminaire sur le moment et le pourquoi simple_pjsua de l'allocation mĂ©moire. Il s'est avĂ©rĂ© que sur 190 Ko, les 90 premiers Ko sont allouĂ©s pour les besoins internes de PJSIP et sont accĂ©dĂ©s assez rarement. Ensuite, lors d'un appel entrant, la fonction pjsua_call_answer est appelĂ©e, oĂč des tampons sont ensuite allouĂ©s pour travailler avec les trames entrantes et sortantes. Cela reprĂ©sentait encore environ 100 Ko. Et lĂ , nous avons agi de la maniĂšre suivante. Avant l'appel, nous plaçons les donnĂ©es en mĂ©moire externe. DĂšs que l'appel commence, nous remplaçons immĂ©diatement le tas par un autre – en RAM. Ainsi, toutes les donnĂ©es « chaudes » ont Ă©tĂ© transfĂ©rĂ©es vers une mĂ©moire plus rapide et plus prĂ©visible.

Au final, tout cela a permis de lancer simple_pjsua et d'appeler via son propre serveur. Puis, nous avons également pu le faire via d'autres serveurs comme sip.linphone.org.

Conclusions

En fin de compte, nous avons rĂ©ussi Ă  lancer simple_pjsua avec transmission vocale bidirectionnelle via le serveur. Le problĂšme des 128 Ko de SDRAM supplĂ©mentaires peut ĂȘtre rĂ©solu en utilisant un Cortex-M7 un peu plus puissant (par exemple, STM32F769NI avec 512 Ko de RAM), mais pour l'instant, nous n'avons pas encore abandonnĂ© l'espoir d'entrer aussi dans 256 Ko 🙂 Nous serions ravis si quelqu'un s'intĂ©resse, et encore mieux – essaie. Tous les sources, comme d'habitude, sont Ă  notre disposition. dĂ©pĂŽts.

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster