SIP-telefon pÄ STM32F7-Discovery

Hei alle sammen.

For en tid siden skrevet om hvordan vi klarte Ä kjÞre en SIP-telefon pÄ STM32F4-Discovery med 1 MB ROM og 192 KB RAM basert pÄ Embox. Det mÄ nevnes at den versjonen var minimal og koblet to telefoner direkte uten server og med stemmebÄndet bare i én retning. Derfor bestemte vi oss for Ä kjÞre en mer fullverdig telefon med samtale via server, stemmeoverfÞring i begge retninger, men samtidig holde oss innenfor sÄ liten minnestÞrrelse som mulig.

Spill video

For telefonen ble det besluttet Ä velge applikasjonen simple_pjsua som en del av PJSIP-biblioteket. Dette er en minimal applikasjon som kan registrere seg pÄ serveren, motta og besvare samtaler. Nedenfor gir jeg umiddelbart en beskrivelse av hvordan dette kan startes pÄ STM32F7-Discovery.

Hvordan starte

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

    der server — dette er SIP-serveren (for eksempel sip.linphone.org), username og password — brukernavnet og passordet for kontoen.

  3. Vi bygger Embox med kommandoen lag. Vi har informasjon om hvordan vi skal blinke brettet pÄ wiki og i artikkelen.
  4. Vi starter Embox-konsollen med kommandoen “simple_pjsua_imported”
    
    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. Til slutt er det bare Ä sette inn hÞyttalere eller hodetelefoner i lydutgangen og snakke inn i to smÄ MEMS-mikrofoner nÊr skjermen. Vi ringer fra Linux via applikasjonen simple_pjsua, pjsua. Eller vi kan bruke hvilken som helst annen som linphone.

Alt dette er beskrevet pÄ vÄr wiki.

Hvordan vi kom dit

SÄ, i utgangspunktet oppstod spÞrsmÄlet om valg av maskinvareplattform. Da det var klart at STM32F4-Discovery ikke ville vÊre tilstrekkelig med hensyn til minne, ble STM32F7-Discovery valgt. Den har 1 MB flashminne og 256 KB RAM (+ 64 KB spesialhurtigminne, som vi ogsÄ vil bruke). Det er ikke mye for samtaler gjennom serveren, men vi bestemte oss for Ä prÞve Ä klare det.

Vi delte oppgaven vÄre i flere faser:

  • KjĂžre PJSIP pĂ„ QEMU. Dette var praktisk for feilsĂžking, og vi hadde allerede stĂžtte for AC97-kodeken der.
  • Opptak av stemme og reproduksjon pĂ„ QEMU og STM32.
  • Portering av applikasjonen simple_pjsua fra PJSIP-biblioteket. Det lar deg registrere deg pĂ„ en SIP-server og ringe.
  • Sette opp din egen server basert pĂ„ Asterisk og teste pĂ„ den, etterpĂ„ prĂžve eksterne som sip.linphone.org

Lyd i Embox fungerer via Portaudio, som ogsĂ„ brukes i PISIP. I QEMU dukket de fĂžrste problemene opp — WAV-filer ble godt spilt av pĂ„ 44100 Hz, men pĂ„ 8000 var det tydelig noe som ikke stemte. Det viste seg at det handlet om frekvensinnstillingen — som standard var den 44100 i maskinvaren, og dette ble ikke endret programmatisk.

Her er det kanskje verdt Ä forklare litt om hvordan avspilling av lyd faktisk fungerer. Lydkortet kan bli satt opp med en pekere til et minneomrÄde som det skal spille av fra, eller ta opp med en forhÄndsbestemt frekvens. NÄr bufferen er tom, genereres et avbrudd, og kjÞringen fortsetter med neste buffer. Tingen er at disse bufferne mÄ fylles opp i tide, mens den forrige fortsatt spilles av. Denne utfordringen vil vi komme tilbake til senere pÄ STM32F7.

Deretter leide vi en server og satte opp Asterisk pĂ„ den. Ettersom det var mye som mĂ„tte feilsĂžkes, og vi ikke Ăžnsket Ă„ snakke mye i mikrofonen, mĂ„tte vi lage automatisk avspilling og opptak. For dette patchet vi simple_pjsua slik at vi kunne gi filer i stedet for lyd-enheter. I PJSIP gjĂžres dette ganske enkelt, da de har et konsept om porter som kan vĂŠre bĂ„de en enhet eller en fil. Og disse portene kan kobles fleksibelt til andre porter. Du kan se koden vĂ„r i pjsip. depotetSĂ„, oppsettet var som fĂžlger. PĂ„ Asterisk-serveren opprettet jeg to kontoer — for Linux og for Embox. Deretter pĂ„ Embox kjĂžrte vi kommandoen simple_pjsua_imported, Embox registrerer seg pĂ„ serveren, hvoretter vi ringer fra Linux til Embox. I det Ăžyeblikket forbindelsen etableres, sjekker vi pĂ„ Asterisk-serveren at forbindelsen er satt opp, og etter en stund skal vi hĂžre lyd fra Linux i Embox, mens vi pĂ„ Linux lagrer filen som spilles av fra Embox.

Etter at dette fungerte pĂ„ QEMU, gikk vi videre til portering til STM32F7-Discovery. Det fĂžrste problemet var at vi ikke fikk plass i 1 MB ROM uten Ă„ aktivere kompilatoren '−Os' for bilde-stĂžrrelsen. Derfor aktiverte vi '−Os'. Videre, via et patch, deaktiverte vi stĂžtte for C++, da det kun er nĂždvendig for pjsua og vi bruker simple_pjsua.

Etter Ă„ ha fĂ„tt plass simple_pjsua, mente vi at sjansene for Ă„ kjĂžre dette nĂ„ var til stede. Men fĂžrst mĂ„tte vi finne ut av opptak og avspilling av stemme. SpĂžrsmĂ„let var — hvor skulle vi lagre? Vi valgte ekstern minne — SDRAM (128 MB). Du kan prĂžve dette selv:

Vil lage stereo WAV med en frekvens pÄ 16000 Hz og varighet pÄ 10 sekunder:


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

Spiller av:


play -m C0000000

Her oppstod to problemer. Det fĂžrste med kodeken – WM8994 brukes, og det finnes et konsept som kalles slot, og det finnes fire slike slots. Vel, som standard, hvis dette ikke er konfigurert, sĂ„ skjer avspillingen av lyd i alle fire slots. Derfor fikk vi ved 16000 Hz 8000 Hz, og ved 8000 Hz fungerte ikke avspillingen i det hele tatt. Da vi valgte kun slots 0 og 2, fungerte det som det skulle. Det andre problemet var lydgrensesnittet i STM32Cube, der lydutgangen fungerer via SAI (Serial Audio Interface) synkront med lydinngangen (jeg har ikke sett pĂ„ detaljene, men det er som om de deler en felles klokke, og ved initiering av lydutgangen blir lydinngangen knyttet pĂ„ en eller annen mĂ„te). Det vil si at de ikke kan kjĂžres separat, sĂ„ vi gjorde fĂžlgende – lydinngangen og lydutgangen er alltid operative (inkludert generering av avbrudd). Men nĂ„r det ikke spilles av noe i systemet, sĂ„ gir vi bare et tomt buffer til lydutgangen, og nĂ„r avspillingen starter, begynner vi for alvor Ă„ fylle den.

Deretter stÞtte vi pÄ det faktum at lyden under opptak av stemmen var veldig svak. Dette skjer fordi MEMS mikrofoner pÄ STM32F7-Discovery fungerer dÄrlig pÄ frekvenser under 16000 Hz. Derfor stiller vi inn 16000 Hz, selv om vi fÄr 8000 Hz. For dette trengte vi faktisk Ä legge til en programvarekonvertering fra én frekvens til en annen.

Videre mĂ„tte vi Ăžke stĂžrrelsen pĂ„ heapen, som er plassert i RAM. IfĂžlge vĂ„re beregninger krevde pjsip omtrent 190 Kb, og vi hadde bare omtrent 100 Kb igjen. Her mĂ„tte vi bruke litt ekstern minne – SDRAM (omtrent 128 Kb).

Etter alle disse rettingene sĂ„ jeg de fĂžrste pakkene mellom Linux og Embox, og hĂžrte lyden! Men lyden var forferdelig, helt annerledes enn i QEMU, ingenting kunne bli forstĂ„tt. Da begynte vi Ă„ tenke pĂ„ hva som kan vĂŠre problemet. FeilsĂžkingen viste at Embox bare ikke klarte Ă„ fylle/tĂžmme lydbufferne raskt nok. Mens pjsip behandler Ă©n ramme, klarte det Ă„ skje to avbrudd om fullfĂžringen av bufferbehandlingen, noe som var for mye. Den fĂžrste tanken for Ă„ Ăžke hastigheten var optimaliseringen av kompilatoren, men den var allerede inkludert i PJSIP. Den andre – maskinvareflyttalls, om den hadde vi snakket i artikkelen. Men som praksisen har vist, ga ikke FPU noen betydelig Ăžkning i hastighet. Neste skritt var Ă„ sette prioriteringer for flytene. I Embox finnes det ulike planleggingsstrategier, og jeg aktivert den som stĂžtter prioriteringer, og satte den hĂžyeste prioriteten for lydstrĂžmmer. Dette hjalp heller ikke.

Den neste ideen var at vi jobber med ekstern minne, og det ville vĂŠre bra Ă„ flytte strukturer dit som det er ekstremt hyppig tilgang pĂ„. Jeg gjennomfĂžrte en forelĂžpig analyse av nĂ„r og under hva simple_pjsua minnet blir tildelt. Det viste seg at av 190 Kb ble de fĂžrste 90 Kb tildelt til interne behov for PJSIP, og tilgangen til dem skjer ikke sĂ„ ofte. Deretter under et inngĂ„ende anrop blir funksjonen pjsua_call_answer kalt, hvor buffere blir tildelt for Ă„ jobbe med inngĂ„ende og utgĂ„ende rammer. Dette var omtrent 100 Kb til. Og her gjorde vi det fĂžlgende. FĂžr anropet plasserer vi dataene i ekstern minne. SĂ„ snart anropet skjer — bytter vi umiddelbart haugen til en annen — i RAM. Dermed ble alle “varme” data flyttet til raskere og mer forutsigbar minne.

Til slutt gjorde alt dette det mulig Ä starte simple_pjsua og ringe gjennom sin egen server. Og deretter ogsÄ gjennom andre servere som sip.linphone.org.

Konklusjoner

Til slutt klarte vi Ă„ starte simple_pjsua med overfĂžring av stemme i begge retninger gjennom serveren. Problemet med de ekstra brukte 128 Kb SDRAM kan lĂžses ved Ă„ bruke en litt kraftigere Cortex-M7 (for eksempel STM32F769NI med 512 Kb RAM), men samtidig har vi fortsatt ikke mistet hĂ„pet om Ă„ passe inn i 256 Kb 🙂 Vi vil gjerne ha noen som er interessert, og enda bedre — prĂžver det. Alle kilder, som vanlig, er tilgjengelige i vĂ„r depotet.

Kilde: habr.com

KjĂžp pĂ„litelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere đŸ”„ KjĂžp pĂ„litelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere | ProHoster