Téléphone SIP sur STM32F7-Discovery

Bonjour.

Il y a quelque temps nous écrit sur la façon dont nous avons réussi à lancer un téléphone SIP sur STM32F4-Discovery avec 1 Mo de ROM et 192 Ko de RAM) basé sur Embox. Ici, il faut dire que cette version était minimale et connectait directement deux téléphones sans serveur et avec une transmission vocale dans un seul sens. Par conséquent, nous avons décidé de lancer un téléphone plus complet avec un appel via le serveur, une transmission vocale dans les deux sens, tout en respectant la plus petite taille de mémoire possible.


Pour le téléphone, il a été décidé de choisir une application simple_pjsua dans le cadre de la bibliothèque PJSIP. Il s'agit d'une application minimale qui peut s'enregistrer sur le serveur, recevoir et répondre aux appels. Ci-dessous, je vais immédiatement donner une description de la façon de l'exécuter sur STM32F7-Discovery.

Comment lancer

  1. Configuration d'Embox
    make confload-platform/pjsip/stm32f7cube
  2. Définissez le compte SIP requis dans le fichier conf/mods.config.
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server", 
        sip_user="username",
        sip_passwd="password")
    

    serveur est un serveur SIP (par exemple, sip.linphone.org), Nom d'utilisateur и Mot de passe - nom d'utilisateur et mot de passe du compte.

  3. Assembler Embox en équipe faire. À propos du micrologiciel de la carte que nous avons sur wiki et article.
  4. Exécutez la commande "simple_pjsua_imported" dans la console 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. Enfin, il reste à insérer des haut-parleurs ou des écouteurs dans la sortie audio et à parler dans deux petits microphones MEMS à côté de l'écran. Nous appelons depuis Linux via l'application simple_pjsua, pjsua. Eh bien, ou vous pouvez utiliser n'importe quel autre type de linphone.

Tout cela est décrit sur notre wiki.

Comment en sommes-nous arrivés là

Ainsi, au départ, la question s'est posée de choisir une plate-forme matérielle. Puisqu'il était clair que STM32F4-Discovery ne rentrerait pas dans la mémoire, STM32F7-Discovery a été choisi. Elle dispose d'un lecteur flash de 1 Mo et de 256 Ko de RAM (+ 64 mémoires rapides spéciales, que nous utiliserons également). Pas beaucoup non plus pour les appels via le serveur, mais nous avons décidé d'essayer de nous intégrer.

Conditionnellement pour eux-mêmes, la tâche a été divisée en plusieurs étapes:

  • Exécution de PJSIP sur QEMU. C'était pratique pour le débogage, et nous avions déjà la prise en charge du codec AC97.
  • Enregistrement et lecture de la voix sur QEMU et sur STM32.
  • Portage d'une application simple_pjsua du PJSIP. Il vous permet de vous inscrire sur le serveur SIP et de passer des appels.
  • Déployez votre propre serveur basé sur Asterisk et testez-le, puis essayez des serveurs externes tels que sip.linphone.org

Le son dans Embox fonctionne via Portaudio, qui est également utilisé dans PISIP. Les premiers problèmes sont apparus sur QEMU - WAV jouait bien à 44100 Hz, mais à 8000 quelque chose s'est clairement mal passé. Il s'est avéré qu'il s'agissait de régler la fréquence - par défaut, c'était 44100 dans l'équipement, et cela n'a pas changé par programme.

Ici, peut-être vaut-il la peine d'expliquer un peu comment le son est joué en général. La carte son peut être réglée sur un pointeur vers un morceau de mémoire à partir duquel vous voulez jouer ou enregistrer à une fréquence prédéterminée. Une fois le tampon terminé, une interruption est générée et l'exécution se poursuit avec le tampon suivant. Le fait est que ces tampons doivent être remplis à l'avance pendant que le précédent est en cours de lecture. Nous reviendrons sur ce problème plus loin sur STM32F7.

Ensuite, nous avons loué un serveur et déployé Asterisk dessus. Comme il fallait beaucoup déboguer, mais que je ne voulais pas trop parler dans le micro, il fallait faire une lecture et un enregistrement automatiques. Pour ce faire, nous avons patché simple_pjsua afin que vous puissiez glisser 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 soit un périphérique, soit un fichier. Et ces ports peuvent être connectés de manière flexible à d'autres ports. Vous pouvez voir le code dans notre pjsip référentiels. En conséquence, le schéma était le suivant. Sur le serveur Asterisk, j'ai ouvert deux comptes - pour Linux et pour Embox. Ensuite, la commande est exécutée sur Embox simple_pjsua_imported, Embox est enregistré sur le serveur, après quoi nous appelons Embox depuis Linux. Au moment de la connexion, nous vérifions sur le serveur Asterisk que la connexion est établie, et après un certain temps, nous devrions entendre le son de Linux dans Embox, et sous Linux, nous enregistrons le fichier qui est lu depuis Embox.

Après avoir travaillé sur QEMU, nous sommes passés au portage sur STM32F7-Discovery. Le premier problème est qu'ils ne rentrent pas dans 1 Mo de ROM sans l'optimisation du compilateur activée "-Os" pour la taille de l'image. C'est pourquoi nous avons inclus "-Os". De plus, le patch a désactivé la prise en charge de C ++, il n'est donc nécessaire que pour pjsua, et nous utilisons simple_pjsua.

Après avoir été placé simple_pjsua, a décidé qu'il y avait maintenant une chance de le lancer. Mais il fallait d'abord s'occuper de l'enregistrement et de la lecture de la voix. La question est où écrire ? Nous avons choisi la mémoire externe - SDRAM (128 Mo). Vous pouvez essayer ceci vous-même :

Crée un WAV stéréo avec une fréquence de 16000 Hz et une durée de 10 secondes :


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

Nous perdons:


play -m C0000000

Ici, nous avons deux problèmes. Le premier avec le codec - WM8994 est utilisé, et il a une chose comme un emplacement, et il y en a 4. Donc, par défaut, si cela n'est pas configuré, alors lors de la lecture audio, la lecture se produit dans les quatre emplacements . Par conséquent, à une fréquence de 16000 Hz, nous avons reçu 8000 Hz, mais pour 8000 Hz, la lecture ne fonctionnait tout simplement pas. Lorsque seuls les emplacements 0 et 2 étaient sélectionnés, cela fonctionnait comme il se doit. Un autre problème était l'interface audio du STM32Cube, dans laquelle la sortie audio fonctionne via SAI (Serial Audio Interface) de manière synchrone avec l'entrée audio (je n'ai pas compris les détails, mais il s'avère qu'ils partagent une horloge commune et lorsque le la sortie audio est initialisée, l'audio est en quelque sorte attaché à son entrée). Autrement dit, vous ne pouvez pas les exécuter séparément, nous avons donc fait ce qui suit - l'entrée audio et la sortie audio fonctionnent toujours (y compris les interruptions sont générées). Mais lorsque rien n'est joué dans le système, nous glissons simplement un tampon vide dans la sortie audio, et lorsque la lecture commence, nous commençons honnêtement à le remplir.

De plus, nous avons rencontré le fait que le son lors de l'enregistrement vocal était très silencieux. Cela est dû au fait que les microphones MEMS du STM32F7-Discovery ne fonctionnent pas bien à des fréquences inférieures à 16000 16000 Hz. Par conséquent, nous fixons 8000 Hz, même si XNUMX Hz vient. Pour ce faire, cependant, il a fallu ajouter un logiciel de conversion d'une fréquence à une autre.

Ensuite, j'ai dû augmenter la taille du tas, qui se trouve dans la RAM. Selon nos calculs, pjsip nécessitait environ 190 Ko, et il ne nous reste qu'environ 100 Ko. Ici, j'ai dû utiliser de la mémoire externe - SDRAM (environ 128 Ko).

Après tous ces montages, j'ai vu les premiers packages entre Linux et Embox, et j'ai entendu le son ! Mais le son était terrible, pas du tout le même que sur QEMU, impossible de distinguer quoi que ce soit. Ensuite, nous avons pensé à ce qui pourrait être le problème. Le débogage a montré qu'Embox n'a tout simplement pas le temps de remplir/décharger les tampons audio. Alors que pjsip traitait une image, 2 interruptions ont eu le temps de se produire à propos de l'achèvement du traitement du tampon, ce qui est trop. La première pensée pour la vitesse était l'optimisation du compilateur, mais elle était déjà incluse dans PJSIP. La seconde est une virgule flottante matérielle, nous en avons parlé dans article. Mais comme l'a montré la pratique, le FPU n'a pas donné une augmentation significative de la vitesse. L'étape suivante consistait à hiérarchiser les threads. Embox a différentes stratégies de planification, et j'en ai inclus une qui prend en charge les priorités et définit les flux audio sur la priorité la plus élevée. Cela n'a pas aidé non plus.

L'idée suivante était que nous travaillions avec de la mémoire externe et qu'il serait bien d'y déplacer des structures auxquelles on accède extrêmement souvent. J'ai fait une analyse préliminaire de quand et sous quoi simple_pjsua alloue de la mémoire. Il s'est avéré que sur 190 Ko, les 90 premiers Ko sont alloués aux besoins internes de PJSIP et ils ne sont pas très souvent consultés. De plus, lors d'un appel entrant, la fonction pjsua_call_answer est appelée, dans laquelle des tampons sont ensuite alloués pour travailler avec les trames entrantes et sortantes. C'était encore environ 100 Ko. Et puis nous avons fait ce qui suit. Jusqu'au moment de l'appel, nous plaçons les données dans la mémoire externe. Dès l'appel, 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.

En conséquence, tout cela ensemble a permis de lancer simple_pjsua et appeler via votre serveur. Et ensuite via d'autres serveurs tels que sip.linphone.org.

résultats

Il a ainsi été possible de lancer simple_pjsua avec transmission vocale dans les deux sens via le serveur. Le problème avec 128 Ko de SDRAM dépensés en plus peut être résolu en utilisant un Cortex-M7 légèrement plus puissant (par exemple, STM32F769NI avec 512 Ko de RAM), mais en même temps, nous n'avons toujours pas abandonné l'espoir d'entrer dans 256 KB 🙂 Nous serons heureux si quelqu'un est intéressé, Ou mieux encore, essayez-le. Toutes les sources, comme d'habitude, sont dans notre référentiels.

Source: habr.com

Ajouter un commentaire