SIP-telefon på STM32F7-Discovery

Hej alle sammen.

For et stykke tid siden vi skrev om hvordan det lykkedes at lancere en SIP-telefon på STM32F4-Discovery med 1 MB ROM og 192 KB RAM) baseret på Embox. Her skal det siges, at den version var minimal og forbundet to telefoner direkte uden server og med stemmetransmission i kun én retning. Derfor besluttede vi at lancere en mere komplet telefon med et opkald gennem serveren, stemmetransmission i begge retninger, men samtidig holde sig inden for den mindst mulige hukommelsesstørrelse.


Til telefonen blev det besluttet at vælge en applikation simple_pjsua som en del af PJSIP-biblioteket. Dette er en minimal applikation, der kan registrere sig på serveren, modtage og besvare opkald. Nedenfor vil jeg straks give en beskrivelse af, hvordan man kører det på STM32F7-Discovery.

Hvordan man løber

  1. Konfiguration af Embox
    make confload-platform/pjsip/stm32f7cube
  2. Indstil den nødvendige SIP-konto i filen conf/mods.config.
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server", 
        sip_user="username",
        sip_passwd="password")
    

    где server er en SIP-server (for eksempel sip.linphone.org), brugernavn и adgangskode - kontobrugernavn og adgangskode.

  3. Samling af Embox som et team lave. Om bestyrelsens firmware, vi har på wiki og artiklen.
  4. Kør kommandoen "simple_pjsua_imported" i Embox-konsollen
    
    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. Til sidst er det tilbage at indsætte højttalere eller hovedtelefoner i lydudgangen og tale i to små MEMS-mikrofoner ved siden af ​​skærmen. Vi ringer fra Linux gennem applikationen simple_pjsua, pjsua. Nå, eller du kan bruge enhver anden type linphone.

Alt dette er beskrevet på vores wiki.

Hvordan kom vi dertil

Så i første omgang opstod spørgsmålet om valg af hardwareplatform. Da det var klart, at STM32F4-Discovery ikke ville passe ind fra hukommelsen, blev STM32F7-Discovery valgt. Hun har et 1 MB flashdrev og 256 KB RAM (+ 64 speciel hurtig hukommelse, som vi også vil bruge). Også ikke meget for opkald gennem serveren, men vi besluttede at prøve at passe ind.

Betinget for sig selv var opgaven opdelt i flere faser:

  • Kører PJSIP på QEMU. Det var praktisk til debugging, plus vi havde allerede support til AC97 codec der.
  • Stemmeoptagelse og afspilning på QEMU og på STM32.
  • Portering af en applikation simple_pjsua fra PJSIP. Det giver dig mulighed for at registrere dig på SIP-serveren og foretage opkald.
  • Implementer din egen Asterisk-baserede server og test på den, og prøv derefter eksterne som f.eks. sip.linphone.org

Lyd i Embox fungerer gennem Portaudio, som også bruges i PISIP. De første problemer dukkede op på QEMU - WAV spillede godt ved 44100 Hz, men ved 8000 gik noget tydeligvis galt. Det viste sig, at det var et spørgsmål om at indstille frekvensen – som standard var den 44100 i udstyret, og dette ændrede sig ikke programmæssigt.

Her er det måske værd at forklare lidt, hvordan lyden spilles generelt. Lydkortet kan indstilles til at pege på et stykke hukommelse, hvorfra du vil afspille eller optage ved en forudbestemt frekvens. Når bufferen slutter, genereres et interrupt, og eksekveringen fortsætter med den næste buffer. Faktum er, at disse buffere skal udfyldes på forhånd, mens den forrige spilles. Vi vil møde dette problem yderligere på STM32F7.

Dernæst lejede vi en server og installerede Asterisk på den. Da det var nødvendigt at debugge meget, men jeg ikke ville tale meget ind i mikrofonen, var det nødvendigt at lave automatisk afspilning og optagelse. For at gøre dette har vi patchet simple_pjsua, så du kan smide filer i stedet for lydenheder. I PJSIP gøres dette ganske enkelt, da de har konceptet med en port, som enten kan være en enhed eller en fil. Og disse porte kan fleksibelt forbindes med andre porte. Du kan se koden i vores pjsip depoter. Som følge heraf var ordningen som følger. På Asterisk-serveren startede jeg to konti - til Linux og til Embox. Dernæst udføres kommandoen på Embox simple_pjsua_imported, registrerer Embox på serveren, hvorefter vi kalder Embox fra Linux. I forbindelse med forbindelsen tjekker vi på Asterisk-serveren, at forbindelsen er etableret, og efter et stykke tid skulle vi høre lyd fra Linux i Embox, og i Linux gemmer vi filen, der afspilles fra Embox.

Efter at det fungerede på QEMU, gik vi videre til portering til STM32F7-Discovery. Det første problem er, at de ikke passede ind i 1 MB ROM uden den aktiverede compiler optimering "-Os" for størrelsen af ​​billedet. Derfor har vi inkluderet "-Os". Yderligere deaktiverede patchen understøttelse af C++, så det er kun nødvendigt for pjsua, og vi bruger simple_pjsua.

Efter at være blevet placeret simple_pjsua, besluttede, at nu er der en chance for at lancere den. Men først var det nødvendigt at beskæftige sig med optagelsen og afspilningen af ​​stemmen. Spørgsmålet er, hvor skal man skrive? Vi valgte ekstern hukommelse - SDRAM (128 MB). Du kan selv prøve dette:

Opretter en stereo WAV med en frekvens på 16000 Hz og en varighed på 10 sekunder:


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

Vi taber:


play -m C0000000

Der er to problemer her. Den første med codec - WM8994 bruges, og den har sådan en ting som en slot, og der er 4 af disse slots. Så hvis dette ikke er konfigureret som standard, sker afspilning i alle fire slots, når der afspilles lyd. . Derfor modtog vi ved en frekvens på 16000 Hz 8000 Hz, men for 8000 Hz virkede afspilningen simpelthen ikke. Når kun plads 0 og 2 blev valgt, fungerede det, som det skulle. Et andet problem var lydgrænsefladen i STM32Cube, hvor lydudgangen fungerer via SAI (Serial Audio Interface) synkront med lydindgangen (jeg forstod ikke detaljerne, men det viser sig, at de deler et fælles ur, og når lydoutput initialiseres, lyd er på en eller anden måde knyttet til indgangen). Det vil sige, at du ikke kan køre dem separat, så vi gjorde følgende - lydindgangen og lydudgangen fungerer altid (inklusive interrupts genereres). Men når der ikke afspilles noget i systemet, så smutter vi simpelthen en tom buffer ind i lydudgangen, og når afspilningen starter, begynder vi ærligt talt at fylde den.

Yderligere stødte vi på det faktum, at lyden under stemmeoptagelse var meget stille. Dette skyldes, at MEMS-mikrofoner på STM32F7-Discovery på en eller anden måde ikke fungerer godt ved frekvenser under 16000 Hz. Derfor sætter vi 16000 Hz, selvom der kommer 8000 Hz. For at gøre dette var det dog nødvendigt at tilføje en softwarekonvertering af en frekvens til en anden.

Dernæst måtte jeg øge størrelsen på heapen, som er placeret i RAM. Ifølge vores beregninger krævede pjsip omkring 190 KB, og vi har kun omkring 100 KB tilbage. Her skulle jeg bruge noget ekstern hukommelse - SDRAM (ca. 128 KB).

Efter alle disse redigeringer så jeg de første pakker mellem Linux og Embox, og jeg hørte lyden! Men lyden var forfærdelig, slet ikke den samme som på QEMU, det var umuligt at se noget. Så tænkte vi på, hvad der kunne være i vejen. Fejlretning viste, at Embox simpelthen ikke har tid til at fylde/aflæse lydbuffere. Mens pjsip behandlede en frame, havde 2 interrupts tid til at opstå om afslutningen af ​​bufferbehandling, hvilket er for meget. Den første tanke for hastighed var compiler optimering, men den var allerede inkluderet i PJSIP. Det andet er et hardware flydende punkt, vi talte om det i artiklen. Men som praksis har vist, gav FPU ikke en væsentlig stigning i hastigheden. Næste skridt var at prioritere tråde. Embox har forskellige planlægningsstrategier, og jeg har inkluderet en, der understøtter prioriteter og indstiller lydstreams til højeste prioritet. Dette hjalp heller ikke.

Den næste idé var, at vi arbejder med ekstern hukommelse, og det ville være rart at flytte strukturer dertil, som man bruger ekstremt ofte. Jeg lavede en foreløbig analyse af hvornår og under hvad simple_pjsua tildeler hukommelse. Det viste sig, at ud af 190 Kb er de første 90 Kb allokeret til interne behov i PJSIP, og de er ikke tilgået særlig ofte. Yderligere, under et indgående opkald, kaldes pjsua_call_answer-funktionen, hvor buffere derefter allokeres til at arbejde med indgående og udgående rammer. Det var stadig omkring 100 Kb. Og så gjorde vi følgende. Indtil tidspunktet for opkaldet placerer vi dataene i ekstern hukommelse. Så snart opkaldet udskifter vi straks dyngen med en anden - i RAM. Således blev alle "varme" data overført til hurtigere og mere forudsigelig hukommelse.

Som et resultat gjorde alt dette tilsammen det muligt at lancere simple_pjsua og ring gennem din server. Og så gennem andre servere såsom sip.linphone.org.

Fund

Som et resultat var det muligt at lancere simple_pjsua med stemmetransmission i begge retninger gennem serveren. Problemet med yderligere brugt 128 KB SDRAM kan løses ved at bruge en lidt kraftigere Cortex-M7 (for eksempel STM32F769NI med 512 KB RAM), men samtidig har vi stadig ikke opgivet håbet om at komme ind i 256 KB 🙂 Vi vil blive glade, hvis nogen er interesseret, eller endnu bedre, prøv det. Alle kilder er som sædvanlig i vores depoter.

Kilde: www.habr.com

Tilføj en kommentar