SIP-Telefon auf STM32F7-Discovery

Hej alle.

For et stykke tid siden skrevet om hvordan vi formÄede at kÞre 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 kun forbandt to telefoner direkte uden server og med stemmeoverfÞrsel kun i én retning. Derfor besluttede vi at lancere en mere fuldgyldig telefon med opkald via server, stemmeoverfÞrsel i begge retninger, men samtidig holde os inden for sÄ lille hukommelsesstÞrrelse som muligt.

Afspil video

Til telefonen besluttede vi at vÊlge applikationen simple_pjsua som en del af PJSIP-biblioteket. Dette er en minimal applikation, som kan registrere sig pÄ serveren, modtage og besvare opkald. Nedenfor vil jeg straks give en beskrivelse af, hvordan man starter det op pÄ STM32F7-Discovery.

SÄdan starter du

  1. Konfigurerer Embox
    make confload-platform/pjsip/stm32f7cube
  2. I filen conf/mods.config angiver vi den Ăžnskede SIP-konto.
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server",
        sip_user="username",
        sip_passwd="password")
    

    hvor server — dette er SIP-serveren (for eksempel sip.linphone.org), brugernavn og adgangskode — brugernavn og adgangskode til kontoen.

  3. Saml Embox med kommandoen make. Vi har information om flashen af kortet pÄ wiki og i artikel.
  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:alexk2222@sip.linphone.org: registration success, status=200 (Registration success
    00:00:12.911    pjsua_acc.c  ....Keep-alive timer started for acc 0, destination:91.121.209.194:5060, interval:15s
    

  5. Endelig er det tilbage at tilslutte hÞjttalere eller hovedtelefoner til lydudgangen og tale ind i to smÄ MEMS-mikrofoner tÊt pÄ skÊrmen. Vi ringer fra Linux via applikationen simple_pjsua, pjsua. Eller man kan bruge en hvilken som helst anden som linphone.

Alt dette er beskrevet pÄ vores wiki.

Hvordan vi kom hertil

SÄ i starten opstod spÞrgsmÄlet om valg af hardwareplatform. Da det blev klart, at STM32F4-Discovery ikke ville vÊre tilstrÊkkelig med hensyn til hukommelse, blev STM32F7-Discovery valgt. Den har 1 MB flash og 256 KB RAM (+ 64 KB speciel hurtig hukommelse, som vi ogsÄ vil bruge). Det er heller ikke meget til opkald gennem serveren, men vi besluttede at prÞve at presse det ind.

For os selv delte vi opgaven op i flere faser:

  • KĂžrsel af PJSIP pĂ„ QEMU. Det var praktisk til debugging, plus vi havde allerede support for AC97 codec der.
  • Optagelse og afspilning af lyd pĂ„ QEMU og pĂ„ STM32.
  • Portering af applikationen simple_pjsua fra PJSIP-biblioteket. Den gĂžr det muligt at registrere sig pĂ„ SIP-serveren og ringe.
  • OpsĂŠtning af vores egen server baseret pĂ„ Asterisk og teste pĂ„ den, hvorefter vi vil prĂžve eksterne, sĂ„som sip.linphone.org

Lyden i Embox fungerer gennem Portaudio, som ogsĂ„ anvendes i PISIP. PĂ„ QEMU opstod de fĂžrste problemer – WAV-filer ved 44100 Hz blev afspillet fint, men ved 8000 Hz gik noget tydeligvis galt. Det viste sig, at problemet lĂ„ i indstillingen af frekvensen – standarden i hardwaren var 44100, og det blev ikke ĂŠndret programmĂŠssigt.

Her er det mÄske vÊrd at forklare lidt om, hvordan lyden faktisk afspilles. Der kan sÊttes en indikator pÄ lydkortet til et hukommelsesomrÄde, hvorfra der skal afspilles eller optages ved en forudbestemt frekvens. NÄr bufferen er brugt op, genereres der et afbrydelse, og udfÞrelsen fortsÊtter fra den nÊste buffer. Problemet er, at disse buffere skal fyldes i forvejen, mens den tidligere afspilles. Denne udfordring vil vi ogsÄ stÞde pÄ senere med STM32F7.

Derefter lejede vi en server og installerede Asterisk pĂ„ den. Da vi mĂ„tte debugge meget, og det ikke var sjovt at tale ind i mikrofonen, besluttede vi at lave automatisk afspilning og optagelse. For at gĂžre dette patchede vi simple_pjsua, sĂ„ vi kunne indsĂŠtte filer i stedet for lydudstyr. I PJSIP er dette meget enkelt, da de har et begreb om port, som kan vĂŠre bĂ„de en enhed og en fil. Og disse porte kan fleksibelt tilsluttes til andre porte. Koden kan ses i vores pjsip. repositorySammenfattende var diagrammet som fĂžlger. PĂ„ Asterisk-serveren oprettede jeg to konti – en til Linux og en til Embox. DernĂŠst udfĂžres kommandoen pĂ„ Embox. simple_pjsua_imported, Embox registrerer sig pĂ„ serveren, hvorefter vi fra Linux ringer til Embox. I forbindelse med forbindelsen kontrollerer vi pĂ„ Asterisk-serveren, at forbindelsen er oprettet, og efter nogen tid skal vi hĂžre lyden fra Linux i Embox, og i Linux gemmer vi den fil, der bliver afspillet fra Embox.

Efter at dette fungerede pĂ„ QEMU, gik vi videre til porteringen til STM32F7-Discovery. Det fĂžrste problem var, at vi ikke kunne fĂ„ plads i 1 MB ROM uden at aktivere compilationsoptimeringen “-Os” for billedstĂžrrelsen. Derfor aktiverede vi “-Os”. DernĂŠst, med et patch, deaktiverede vi C++-support, da det kun er nĂždvendigt for pjsua, og vi bruger simple_pjsua.

Efter at vi fik plads simple_pjsua, besluttede vi, at der nu var chancer for at starte det. Men fĂžrst skulle vi finde ud af optagelse og afspilning af stemmen. SpĂžrgsmĂ„let var – hvor skulle vi optage? Vi valgte ekstern hukommelse – SDRAM (128 MB). Du kan prĂžve dette selv:

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


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

Afspiller:


play -m C0000000

Her opstod der to problemer. Det fĂžrste med codec'en — WM8994 bruges, og der er noget, der hedder slot, og der er 4 slotter. Som standard, hvis man ikke konfigurerer det, sĂ„ afspilles lyd i alle fire slotter. Derfor fik vi ved 16000 Hz 8000 Hz, og for 8000 Hz fungerede afspilningen bare ikke. Da vi valgte kun slottene 0 og 2, sĂ„ fungerede det som det skulle. Et andet problem var lydinterfacet i STM32Cube, hvor lydudgangen fungerer via SAI (Serial Audio Interface) synkront med lydindgangen (jeg har ikke undersĂžgt detaljerne, men det ser ud til, at de deler fĂŠlles clock, og ved initialisering af lydudgangen binds lydindgangen eller lignende). Det vil sige, at man ikke kan starte dem separat, derfor gjorde vi fĂžlgende — bĂ„de lydindgang og lydudgang fungerer altid (herunder genereres afbrydelser). Men nĂ„r der ikke afspilles noget i systemet, indsĂŠtter vi bare en tom buffer til lydudgangen, og nĂ„r afspilningen starter, sĂ„ begynder vi ĂŠrligt at fylde den.

Derefter stÞdte vi pÄ, at lyden ved optagelse af stemmen var meget lav. Dette skyldes, at MEMS mikrofonerne pÄ STM32F7-Discovery fungerer dÄrligt ved frekvenser under 16000 Hz. Derfor indstiller vi 16000 Hz, selv hvis der kommer 8000 Hz. Faktisk var det nÞdvendigt at tilfÞje en softwarekonvertering af en frekvens til en anden.

DernĂŠst var vi nĂždt til at Ăžge stĂžrrelsen pĂ„ bunken, der ligger i RAM. IfĂžlge vores beregninger krĂŠvede pjsip omkring 190 KB, men vi havde kun omkring 100 KB tilbage. Her mĂ„tte vi bruge lidt ekstern hukommelse — SDRAM (omkring 128 KB).

Efter alle disse ĂŠndringer sĂ„ jeg de fĂžrste pakker mellem Linux og Embox og hĂžrte lyd! Men lyden var forfĂŠrdelig, slet ikke som pĂ„ QEMU, intet kunne forstĂ„s. SĂ„ begyndte vi at undre os over, hvad der kunne vĂŠre galt. Debugging viste, at Embox simpelthen ikke kunne nĂ„ at fylde/udlevere lydbufferne. Mens pjsip behandlede en ramme, skete der to afbrydelser om afslutningen af bufferbehandlingen, hvilket var for meget. Den fĂžrste tanke til at fremskynde var compileroptimering, men det var allerede aktiveret i PJSIP. Det andet — hardware flydende punkt, om det fortalte vi i artikel. Men som praksis har vist, gav FPU ikke en betydelig stigning i hastighed. NĂŠste skridt var at prioritere trĂ„de. I Embox er der forskellige planlĂŠgningsstrategier, og jeg aktiverede den, der understĂžtter prioriteter, og gav lyden den hĂžjeste prioritet. Dette hjalp heller ikke.

NÊste idé var, at vi arbejder med ekstern hukommelse, og det ville vÊre godt at flytte strukturer derhen, som der er meget hyppig adgang til. Jeg udfÞrte en forudgÄende analyse af, hvornÄr og til hvad simple_pjsua hukommelse bliver tildelt. Det viste sig, at ud af 190 Kb blev de fÞrste 90 Kb tildelt til interne behov i PJSIP, og adgangen til dem sker ikke sÊrlig ofte. Derefter, under et indgÄende opkald, kaldes funktionen pjsua_call_answer, hvor der derefter tildeles buffere til behandling af indgÄende og udgÄende rammer. Det var omkring 100 Kb mere. Og her gjorde vi det pÄ fÞlgende mÄde. Indtil opkaldet placerer vi data i den eksterne hukommelse. SÄ snart opkaldet er modtaget - sÄ skifter vi hurtigt til en anden stak - i RAM. PÄ denne mÄde blev alle "hot" data flyttet til hurtigere og mere forudsigelig hukommelse.

Samlet set gjorde alt dette det muligt at starte simple_pjsua og ringe gennem vores server. Og derefter ogsÄ gennem andre servere som sip.linphone.org.

Konklusioner

Resultatet blev, at vi fik startet simple_pjsua med stemmeoverfĂžrsel i begge retninger gennem serveren. Problemet med de ekstra brugte 128 Kb SDRAM kan lĂžses ved at bruge en lidt mere kraftfuld Cortex-M7 (for eksempel STM32F769NI med 512 Kb RAM), men vi har stadig ikke mistet hĂ„bet om at fĂ„ det til at passe ind i 256 Kb 🙂 Vi vil vĂŠre glade, hvis nogen er interesseret, og endnu bedre - prĂžver det. Alle kildekoder er, som sĂŠdvanligt, tilgĂŠngelige i vores repository.

Kilde: habr.com

KĂžb pĂ„lidelig webhosting med DDoS-beskyttelse, VPS VDS-servere đŸ”„ KĂžb pĂ„lidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster