Telèfon SIP a STM32F7-Discovery

Hola a tots

Fa un temps nosaltres писали sobre com vam aconseguir llançar un telèfon SIP a STM32F4-Discovery amb 1 MB de ROM i 192 KB de RAM) basat en Embox. Aquí cal dir que aquella versió era mínima i connectava dos telèfons directament sense servidor i amb transmissió de veu en un sol sentit. Per això, vam decidir llançar un telèfon més complet amb una trucada a través del servidor, transmissió de veu en ambdues direccions, però alhora mantenir dins de la mida de memòria més petita possible.


Per al telèfon, es va decidir triar una aplicació simple_pjsua com a part de la biblioteca PJSIP. Aquesta és una aplicació mínima que pot registrar-se al servidor, rebre i respondre trucades. A continuació, donaré immediatament una descripció de com executar-lo a STM32F7-Discovery.

Com córrer

  1. Configuració d'Embox
    make confload-platform/pjsip/stm32f7cube
  2. Establiu el compte SIP necessari al fitxer conf/mods.config.
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server", 
        sip_user="username",
        sip_passwd="password")
    

    on servidor és un servidor SIP (per exemple, sip.linphone.org), nom d'usuari и contrasenya - Nom d'usuari i contrasenya del compte.

  3. Muntatge d'Embox com a equip fer. Sobre el firmware de la placa que tenim wiki i article.
  4. Executeu l'ordre "simple_pjsua_imported" a la consola d'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. Finalment, queda inserir altaveus o auriculars a la sortida d'àudio i parlar en dos petits micròfons MEMS al costat de la pantalla. Truquem des de Linux mitjançant l'aplicació simple_pjsua, pjsua. Bé, o podeu utilitzar qualsevol altre tipus de telèfon.

Tot això està descrit al nostre wiki.

Com hi hem arribat

Així doncs, inicialment va sorgir la pregunta sobre l'elecció d'una plataforma de maquinari. Com que estava clar que STM32F4-Discovery no encaixaria de la memòria, es va triar STM32F7-Discovery. Té una unitat flash d'1 MB i 256 KB de RAM (+ 64 de memòria ràpida especial, que també utilitzarem). Tampoc hi ha moltes trucades a través del servidor, però vam decidir intentar encaixar-hi.

Condicionalment per ells mateixos, la tasca es va dividir en diverses etapes:

  • Executant PJSIP a QEMU. Era convenient per a la depuració, a més a més ja teníem suport per al còdec AC97 allà.
  • Gravació i reproducció de veu a QEMU i a STM32.
  • Portar una aplicació simple_pjsua de PJSIP. Et permet registrar-te al servidor SIP i fer trucades.
  • Desplegueu el vostre propi servidor basat en Asterisk i proveu-lo i, a continuació, proveu-ne de externs com sip.linphone.org

El so a Embox funciona a través de Portaudio, que també s'utilitza en PISIP. Els primers problemes van aparèixer a QEMU: WAV va tocar bé a 44100 Hz, però a 8000 alguna cosa clarament va sortir malament. Va resultar que es tractava d'establir la freqüència: per defecte era 44100 a l'equip, i això no va canviar programàticament.

Aquí, potser, val la pena explicar una mica com es reprodueix el so en general. La targeta de so es pot configurar a un punter a una peça de memòria des de la qual voleu reproduir o gravar a una freqüència predeterminada. Un cop finalitza el buffer, es genera una interrupció i l'execució continua amb el següent buffer. El cas és que aquests buffers s'han d'omplir amb antelació mentre es juga l'anterior. Ens enfrontarem a aquest problema més a STM32F7.

A continuació, vam llogar un servidor i hi vam desplegar Asterisk. Com que calia depurar molt, però no volia parlar gaire pel micròfon, calia fer una reproducció i gravació automàtica. Per fer-ho, hem pegat simple_pjsua perquè pugueu lliscar fitxers en lloc dels dispositius d'àudio. A PJSIP, això es fa de manera senzilla, ja que tenen el concepte de port, que pot ser un dispositiu o un fitxer. I aquests ports es poden connectar de manera flexible a altres ports. Podeu veure el codi al nostre pjsip repositoris. Com a resultat, l'esquema era el següent. Al servidor Asterisk, vaig iniciar dos comptes: per a Linux i per a Embox. A continuació, l'ordre s'executa a Embox simple_pjsua_imported, Embox es registra al servidor, després de la qual cosa anomenem Embox des de Linux. En el moment de la connexió, comprovem al servidor Asterisk que la connexió està establerta, i al cap d'una estona hauríem d'escoltar so de Linux a Embox, i a Linux desem el fitxer que es reprodueix des d'Embox.

Després que funcionés a QEMU, vam passar a la portabilitat a STM32F7-Discovery. El primer problema és que no encaixaven en 1 MB de ROM sense l'optimització del compilador activada "-Os" per a la mida de la imatge. Per això hem inclòs "-Os". A més, el pedaç va desactivar el suport per a C ++, de manera que només es necessita per a pjsua, i fem servir simple_pjsua.

Després de ser col·locat simple_pjsua, va decidir que ara hi ha l'oportunitat de llançar-lo. Però primer calia ocupar-se de l'enregistrament i reproducció de la veu. La pregunta és on escriure? Hem escollit memòria externa - SDRAM (128 MB). Podeu provar això vosaltres mateixos:

Crea un WAV estèreo amb una freqüència de 16000 Hz i una durada de 10 segons:


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

Hem perdut:


play -m C0000000

Aquí hi ha dos problemes. S'utilitza el primer amb el còdec: WM8994, i té una ranura, i n'hi ha 4. Per tant, de manera predeterminada, si no està configurat, quan es reprodueix l'àudio, la reproducció es produeix a les quatre ranures. . Per tant, a una freqüència de 16000 Hz, vam rebre 8000 Hz, però per a 8000 Hz, la reproducció simplement no va funcionar. Quan només es van seleccionar les ranures 0 i 2, funcionava com calia. Un altre problema va ser la interfície d'àudio de l'STM32Cube, en la qual la sortida d'àudio funciona mitjançant SAI (Serial Audio Interface) de manera sincrònica amb l'entrada d'àudio (no vaig entendre els detalls, però resulta que comparteixen un rellotge comú i quan el La sortida d'àudio està inicialitzada, l'àudio s'adjunta d'alguna manera a l'entrada). És a dir, no els podeu executar per separat, així que vam fer el següent: l'entrada d'àudio i la sortida d'àudio sempre funcionen (incloses les interrupcions que es generen). Però quan no es reprodueix res al sistema, simplement introduïm un buffer buit a la sortida d'àudio i, quan comença la reproducció, comencem a omplir-lo sincerament.

A més, ens vam trobar amb el fet que el so durant l'enregistrament de veu era molt silenciós. Això es deu al fet que els micròfons MEMS de l'STM32F7-Discovery d'alguna manera no funcionen bé a freqüències inferiors a 16000 Hz. Per tant, establim 16000 Hz, encara que arribin 8000 Hz. Per fer-ho, però, calia afegir una conversió de programari d'una freqüència a una altra.

A continuació, vaig haver d'augmentar la mida del munt, que es troba a la memòria RAM. Segons els nostres càlculs, pjsip necessitava uns 190 KB i només ens queden uns 100 KB. Aquí vaig haver d'utilitzar una mica de memòria externa: SDRAM (uns 128 KB).

Després de totes aquestes edicions, vaig veure els primers paquets entre Linux i Embox, i vaig sentir el so! Però el so era terrible, no era gens igual que a QEMU, era impossible distingir res. Llavors vam pensar què podria passar. La depuració va demostrar que Embox simplement no té temps per omplir/descarregar els buffers d'àudio. Mentre pjsip processava un fotograma, s'han produït 2 interrupcions sobre la finalització del processament de la memòria intermèdia, que és massa. El primer pensament per a la velocitat va ser l'optimització del compilador, però ja estava inclòs a PJSIP. El segon és un punt flotant de maquinari, en vam parlar article. Però, com ha demostrat la pràctica, FPU no va donar un augment significatiu de la velocitat. El següent pas va ser prioritzar els fils. Embox té diferents estratègies de programació i n'he inclòs una que admet les prioritats i estableix els fluxos d'àudio a la prioritat més alta. Això tampoc va ajudar.

La següent idea era que estem treballant amb memòria externa i seria bo moure-hi estructures a les quals s'accedeix molt sovint. Vaig fer una anàlisi preliminar de quan i sota què simple_pjsua assigna memòria. Va resultar que de 190 Kb, els primers 90 Kb estan destinats a necessitats internes de PJSIP i no s'hi accedeix molt sovint. A més, durant una trucada entrant, es crida a la funció pjsua_call_answer, en la qual s'assignen buffers per treballar amb trames entrants i sortints. Encara eren uns 100 Kb. I després vam fer el següent. Fins al moment de la trucada, col·loquem les dades a la memòria externa. Tan aviat com la trucada, substituïm immediatament el munt per un altre - a la memòria RAM. Així, totes les dades "calentes" es van transferir a una memòria més ràpida i previsible.

Com a resultat, tot plegat va fer possible el llançament simple_pjsua i truca a través del teu servidor. I després a través d'altres servidors com sip.linphone.org.

Troballes

Com a resultat, es va poder llançar simple_pjsua amb transmissió de veu en ambdues direccions a través del servidor. El problema amb 128 KB de SDRAM gastat addicionalment es pot resoldre utilitzant un Cortex-M7 una mica més potent (per exemple, STM32F769NI amb 512 KB de RAM), però al mateix temps, encara no hem perdut l'esperança d'entrar a 256. KB 🙂 Estarem encantats si algú està interessat, o millor encara, prova-ho. Totes les fonts, com és habitual, estan al nostre repositoris.

Font: www.habr.com

Afegeix comentari