SIP telefon na STM32F7-Discovery

Pozdrav svima.

Malopre smo mi napisao je o tome kako smo uspjeli da lansiramo SIP telefon na STM32F4-Discovery sa 1 MB ROM-a i 192 KB RAM-a) na osnovu Embox. Ovdje se mora reći da je ta verzija bila minimalna i povezivala dva telefona direktno bez servera i sa prijenosom glasa samo u jednom smjeru. Stoga smo odlučili da lansiramo kompletniji telefon sa pozivom preko servera, prenosom glasa u oba smjera, ali u isto vrijeme da zadržimo najmanju moguću veličinu memorije.


Za telefon je odlučeno da se izabere aplikacija simple_pjsua kao dio biblioteke PJSIP. Ovo je minimalna aplikacija koja se može registrovati na serveru, primati i odgovarati na pozive. U nastavku ću odmah dati opis kako ga pokrenuti na STM32F7-Discovery.

Kako trčati

  1. Konfigurisanje Embox-a
    make confload-platform/pjsip/stm32f7cube
  2. Postavite traženi SIP nalog u datoteci conf/mods.config.
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server", 
        sip_user="username",
        sip_passwd="password")
    

    gdje server je SIP server (na primjer, sip.linphone.org), korisničko ime и lozinka - korisničko ime i lozinka naloga.

  3. Sastavljanje Embox-a kao tim napraviti. O firmveru ploče koji imamo wiki i unutra članak.
  4. Pokrenite naredbu “simple_pjsua_imported” u Embox konzoli
    
    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. Na kraju, ostaje da u audio izlaz ubacite zvučnike ili slušalice, i govorite u dva mala MEMS mikrofona pored ekrana. Pozivamo iz Linuxa preko aplikacije simple_pjsua, pjsua. Pa, ili možete koristiti bilo koju drugu vrstu linfona.

Sve ovo je opisano na našem wiki.

Kako smo stigli tamo

Dakle, u početku se postavilo pitanje o odabiru hardverske platforme. Budući da je bilo jasno da STM32F4-Discovery neće stati iz memorije, odabran je STM32F7-Discovery. Ima fleš disk od 1 MB i 256 KB RAM-a (+ 64 specijalne brze memorije, koju ćemo takođe koristiti). Takođe nije puno za pozive preko servera, ali smo odlučili da pokušamo da se uklopimo.

Uvjetno za sebe, zadatak je podijeljen u nekoliko faza:

  • Pokretanje PJSIP-a na QEMU. Bilo je zgodno za otklanjanje grešaka, plus tu smo već imali podršku za AC97 kodek.
  • Snimanje i reprodukcija glasa na QEMU i na STM32.
  • Portiranje aplikacije simple_pjsua iz PJSIP-a. Omogućava vam da se registrujete na SIP serveru i upućujete pozive.
  • Postavite svoj vlastiti server baziran na Asterisk i testirajte na njemu, a zatim isprobajte eksterne kao što je sip.linphone.org

Zvuk u Emboxu radi preko Portaudio-a, koji se također koristi u PISIP-u. Prvi problemi su se pojavili na QEMU - WAV je dobro svirao na 44100 Hz, ali na 8000 nešto je očito krenulo po zlu. Ispostavilo se da je u pitanju podešavanje frekvencije - standardno je u opremi bila 44100, a to se nije programski mijenjalo.

Ovdje, možda, vrijedi malo objasniti kako se zvuk uopće reproducira. Zvučna kartica se može postaviti na neki pokazivač na dio memorije iz kojeg želite reproducirati ili snimati na unaprijed određenoj frekvenciji. Nakon što se bafer završi, generira se prekid i izvršenje se nastavlja sa sljedećim baferom. Činjenica je da ove bafere treba unaprijed popuniti dok se igra prethodni. Sa ovim problemom ćemo se suočiti dalje na STM32F7.

Zatim smo iznajmili server i na njemu postavili Asterisk. Pošto je bilo potrebno dosta debagovati, ali nisam želeo mnogo da pričam u mikrofon, bilo je potrebno napraviti automatsku reprodukciju i snimanje. Da bismo to učinili, zakrpili smo simple_pjsua tako da možete ubaciti datoteke umjesto audio uređaja. U PJSIP-u se to radi prilično jednostavno, jer imaju koncept porta, koji može biti ili uređaj ili datoteka. I ovi portovi se mogu fleksibilno povezati s drugim portovima. Kod možete vidjeti u našem pjsip-u spremišta. Kao rezultat toga, shema je bila sljedeća. Na Asterisk serveru sam pokrenuo dva naloga - za Linux i za Embox. Zatim se naredba izvršava na Emboxu simple_pjsua_imported, Embox se registruje na serveru, nakon čega pozivamo Embox iz Linuxa. U trenutku povezivanja na Asterisk serveru provjeravamo da je veza uspostavljena i nakon nekog vremena u Emboxu bi trebalo da čujemo zvuk iz Linuxa, au Linuxu snimamo fajl koji se reproducira iz Emboxa.

Nakon što je proradio na QEMU, prešli smo na portiranje na STM32F7-Discovery. Prvi problem je što nisu stali u 1 MB ROM-a bez omogućene optimizacije kompajlera “-Os” za veličinu slike. Zato smo uključili "-Os". Nadalje, zakrpa je onemogućila podršku za C ++, tako da je potrebna samo za pjsua, a mi koristimo simple_pjsua.

Nakon postavljanja simple_pjsua, odlučio da sada postoji šansa da ga pokrene. Ali prvo je bilo potrebno pozabaviti se snimanjem i reprodukcijom glasa. Pitanje je gde pisati? Izabrali smo eksternu memoriju - SDRAM (128 MB). Ovo možete isprobati i sami:

Stvara stereo WAV sa frekvencijom od 16000 Hz i trajanjem od 10 sekundi:


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

gubimo:


play -m C0000000

Ovdje postoje dva problema. Koristi se prvi sa kodekom - WM8994, i ima tako nešto kao slot, a ova slota ima 4. Dakle, prema zadanim postavkama, ako ovo nije konfigurisano, tada se prilikom reprodukcije zvuka, reprodukcija odvija u sva četiri slota . Stoga smo na frekvenciji od 16000 Hz dobili 8000 Hz, ali za 8000 Hz reprodukcija jednostavno nije funkcionirala. Kada su odabrani samo slotovi 0 i 2, radilo je kako treba. Drugi problem je bio audio interfejs u STM32Cube, u kojem audio izlaz radi preko SAI (Serial Audio Interface) sinhrono sa audio ulazom (nisam razumio detalje, ali ispostavilo se da dijele zajednički sat i kada audio izlaz je inicijaliziran, zvuk je nekako vezan za njegov ulaz). Odnosno, ne možete ih pokrenuti odvojeno, pa smo uradili sljedeće - audio ulaz i audio izlaz uvijek rade (uključujući i generiranje prekida). Ali kada se ništa ne reproducira u sistemu, onda jednostavno ubacimo prazan bafer u audio izlaz, a kada reprodukcija počne, iskreno počinjemo da ga popunjavamo.

Nadalje, naišli smo na činjenicu da je zvuk tokom snimanja glasa bio vrlo tih. To je zbog činjenice da MEMS mikrofoni na STM32F7-Discovery nekako ne rade dobro na frekvencijama ispod 16000 Hz. Stoga postavljamo 16000 Hz, čak i ako dođe 8000 Hz. Da bi se to postiglo, međutim, bilo je potrebno dodati softversku konverziju jedne frekvencije u drugu.

Zatim sam morao povećati veličinu hrpe koja se nalazi u RAM-u. Prema našim proračunima, pjsip je zahtijevao oko 190 KB, a ostalo nam je samo oko 100 KB. Ovdje sam morao koristiti neku eksternu memoriju - SDRAM (oko 128 KB).

Nakon svih ovih izmjena, vidio sam prve pakete između Linuxa i Emboxa, i čuo sam zvuk! Ali zvuk je bio užasan, nimalo isti kao na QEMU, nemoguće je bilo šta razaznati. Onda smo razmišljali šta bi moglo biti u pitanju. Otklanjanje grešaka pokazalo je da Embox jednostavno nema vremena da popuni/isprazni audio bafere. Dok je pjsip obrađivao jedan okvir, 2 prekida su imala vremena da se dese oko završetka obrade bafera, što je previše. Prva pomisao na brzinu bila je optimizacija kompajlera, ali je već bila uključena u PJSIP. Drugi je hardverski pokretni zarez, o tome smo razgovarali članak. Ali kao što je praksa pokazala, FPU nije dao značajno povećanje brzine. Sljedeći korak je bio određivanje prioriteta niti. Embox ima različite strategije planiranja, a ja sam uključio onu koja podržava prioritete i postavlja audio tokove na najviši prioritet. Ni ovo nije pomoglo.

Sljedeća ideja je bila da radimo sa eksternom memorijom i bilo bi lijepo tamo premjestiti strukture kojima se pristupa izuzetno često. Uradio sam preliminarnu analizu kada i pod čime simple_pjsua dodeljuje memoriju. Pokazalo se da je od 190 Kb prvih 90 Kb izdvojeno za interne potrebe PJSIP-a i da im se ne pristupa često. Dalje, tokom dolaznog poziva, poziva se funkcija pjsua_call_answer, u kojoj se zatim dodjeljuju baferi za rad sa dolaznim i odlaznim okvirima. I dalje je bilo oko 100 Kb. A onda smo uradili sledeće. Do trenutka poziva podatke stavljamo u eksternu memoriju. Čim poziv, odmah zamjenjujemo hrpu drugom - u RAM-u. Tako su svi „vrući“ podaci prebačeni u bržu i predvidljiviju memoriju.

Kao rezultat, sve ovo zajedno omogućilo je lansiranje simple_pjsua i pozovite preko vašeg servera. A zatim preko drugih servera kao što je sip.linphone.org.

nalazi

Kao rezultat toga, bilo je moguće lansiranje simple_pjsua sa prijenosom glasa u oba smjera preko servera. Problem sa dodatno potrošenim 128 KB SDRAM-a može se riješiti korištenjem nešto snažnijeg Cortex-M7 (npr. STM32F769NI sa 512 KB RAM-a), ali u isto vrijeme još uvijek nismo odustali od nade da ćemo ući u 256 KB 🙂 Biće nam drago ako neko bude zainteresovan, ili još bolje, probajte. Svi izvori, kao i obično, nalaze se u našem spremišta.

izvor: www.habr.com

Dodajte komentar