SIP telefon na STM32F7-Discovery

Pozdrav svima.

Nedavno smo pisali o tome kako smo uspjeli pokrenuti SIP telefon na STM32F4-Discovery s 1 MB ROM-a i 192 KB RAM-a na osnovi Embox. Treba reći da je ta verzija bila minimalna i povezivala je dva telefona izravno bez poslužitelja, a prijenos glasa je bio samo u jednom smjeru. Zato smo odlučili pokrenuti funkcionalniji telefon s pozivom kroz poslužitelj, prijenosom glasa u oba smjera, ali uz što manju potrošnju memorije.

Pogledajte video

Za telefon je odlučeno da se izabere aplikacija simple_pjsua iz biblioteke PJSIP. To je minimalna aplikacija koja može registrirati se na poslužitelju, primati i odgovarati na pozive. U nastavku ću odmah navesti opis kako to pokrenuti na STM32F7-Discovery.

Kako pokrenuti

  1. Konfiguriramo Embox
    make confload-platform/pjsip/stm32f7cube
  2. U datoteci conf/mods.config postavljamo potrebni SIP račun.
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server",
        sip_user="username",
        sip_passwd="password")
    

    gdje Poslužitelj — to je SIP poslužitelj (na primjer, sip.linphone.org), korisničko_ime i lozinka — korisničko ime i lozinka za račun.

  3. Sakupljamo Embox naredbom make. O firmware-u ploče imamo na wiki i u članku.
  4. Pokrećemo u konzoli Embox naredbu “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. Na kraju, treba povezati zvučnike ili slušalice u audio izlaz i govoriti u dva mala MEMS mikrofona blizu ekrana. Zovemo s Linux-a koristeći aplikaciju simple_pjsua, pjsua. Ili se može koristiti bilo koja druga, poput linphone.

Sve to je opisano na našem wiki.

Kako smo došli do toga

Dakle, prvotno se postavilo pitanje odabira hardverske platforme. Kako je bilo očito da STM32F4-Discovery neće biti dovoljno zbog memorije, izabrali smo STM32F7-Discovery. Ima 1 MB flash memorije i 256 KB RAM-a (+ 64 MB brze specijalne memorije koju ćemo također koristiti). To nije mnogo za pozive kroz poslužitelj, ali odlučili smo pokušati.

Uslovno smo zadatak podijelili na nekoliko faza:

  • Pokretanje PJSIP-a na QEMU. To je bilo zgodno za debagiranje, plus smo već imali podršku za AC97 kodek.
  • Snima glas i reproducira na QEMU i na STM32.
  • Portiranje aplikacije simple_pjsua iz PJSIP paketa. Omogućuje registraciju na SIP poslužitelju i pozivanje.
  • Postaviti vlastiti poslužitelj na bazi Asteriska i testirati na njemu, a zatim pokušati vanjske, kao što je sip.linphone.org

Zvuk u Emboxu radi putem Portaudio, koji se koristi i u PISIP-u. Na QEMU su se pojavili prvi problemi — WAV datoteke su se dobro reproducirale na 44100 Hz, dok nešto nije bilo u redu na 8000. Ispostavilo se da je problem u postavkama frekvencije — prema zadanim postavkama bio je 44100, a to nismo mogli programatski promijeniti.

Ovdje je možda potrebno malo pojasniti kako uopće dolazi do reprodukcije zvuka. Zvukovnoj kartici može se postaviti pokazivač na dio memorije iz kojeg se treba reproducirati ili snimati na unaprijed postavljenoj frekvenciji. Nakon što se bafer završi, generira se prekid, a izvršavanje se nastavlja s sljedećim baferom. Stvar je u tome da se ti baferi moraju pravovremeno puniti dok se reproducira prethodni. S ovim problemom ćemo se još susresti dalje na STM32F7.

Nakon toga, iznajmili smo server i postavili Asterisk na njega. Budući da je bilo potrebno puno raditi na debuggiranju, a nije se željelo previše govoriti u mikrofon, trebalo je izraditi automatsku reprodukciju i snimanje. Za to smo modificirali simple_pjsua da bi mogli koristiti datoteke umjesto audio uređaja. U PJSIP-u se to radi prilično lako, jer imaju koncept porta koji može biti i uređaj i datoteka. A ti portovi se mogu fleksibilno povezivati s drugim portovima. Pogledajte kod u našem pjsipu. repozitorijuNa serveru Asterisk stvorio sam dva računa — za Linux i za Embox. Nakon toga na Emboxu izvršava se naredba simple_pjsua_imported, Embox se registrira na serveru, a potom s Linuxa zovemo Embox. Tijekom spajanja provjeravamo na serveru Asterisk da li je sve povezano, i nakon izvjesnog vremena trebali bismo čuti zvuk iz Linuksa u Emboxu, a u Linuxu čuvamo onaj datoteku koja se reproducira iz Emboxa.

Nakon što je to proradilo na QEMU-u, prešli smo na portiranje na STM32F7-Discovery. Prvi problem — nismo stizali u 1 MB ROM bez uključene optimizacije kompajlera "-Os" po veličini slike. Stoga smo uključili "-Os". Nadalje, patch-om smo isključili podršku za C++, jer je ona potrebna samo za pjsua, a mi koristimo simple_pjsua.

Nakon što smo stisnuli simple_pjsua, odlučili smo da sada imamo šanse da to pokrenemo. No prvo smo morali razjasniti snimanje i reprodukciju glasa. Pitanje — gdje snimati? Odabrali smo vanjsku memoriju — SDRAM (128 MB). Možete to isprobati sami:

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


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

Sviramo:


play -m C0000000

Ovdje su nastala dva problema. Prvi je bio s kodekom — koristi se WM8994, i u njemu postoji pojam kao slot, a slotova ima 4. Tako, prema zadanim postavkama, ako to ne prilagodite, pri reprodukciji zvuka, reprodukcija se odvija u svih četiri slota. Stoga, na frekvenciji od 16000 Hz dobivali smo 8000 Hz, a za 8000 Hz reprodukcija jednostavno nije radila. Kada smo odabrali samo slotove 0 i 2, sve je počelo raditi kako treba. Drugi problem bio je audio sučelje u STM32Cube, u kojem se audio izlaz radi putem SAI (Serial Audio Interface) sinkrono s audio ulazom (nisam se previše bavio detaljima, ali ispada da dijele zajednički sat i prilikom inicijalizacije audio izlaza, audio ulaz se na neki način povezuje s njim). To znači da ih ne možete pokrenuti odvojeno, pa smo učinili sljedeće — audio ulaz i audio izlaz uvijek rade (uključujući generiranje prekida). No kada se u sustavu ništa ne reproducira, jednostavno pružamo prazni buferski izlaz, a kada započne reprodukcija, pošteno počinjemo puniti taj buffer.

Nakon toga suočili smo se s problemom da je zvuk prilikom snimanja glasa bio vrlo tih. To se događa zbog toga što MEMS mikrofoni na STM32F7-Discovery nekako loše rade na frekvencijama ispod 16000 Hz. Zbog toga smo odabrali 16000 Hz, čak i ako dolazi 8000 Hz. Za to je, doduše, bilo potrebno dodati softversku pretvorbu jedne frekvencije u drugu.

Nakon toga morali smo povećati veličinu hrpe koja se nalazi u RAM-u. Prema našim proračunima, pjsip je zahtijevao oko 190 KB, a nama je ostalo samo oko 100 KB. Ovdje smo morali uključiti malo vanjske memorije — SDRAM (oko 128 KB).

Nakon svih ovih ispravki vidio sam prve pakete između Linuxa i Emboxa, i čuo zvuk! Ali zvuk je bio grozan, ništa nije bilo poput onog na QEMU-u, ništa se nije moglo razabrati. Tada smo se zapitali što bi moglo biti u pitanju. Debagiranje je pokazalo da Embox jednostavno ne uspijeva popuniti/isprazniti audio buffere. Dok pjsip obrađuje jedan frame, već su se dogodila 2 prekida o završetku obrade buffera, što je previše. Prva misao za ubrzavanje bila je optimizacija kompajlera, ali ona je već bila uključena u PJSIP. Drugo — hardverska plava točka, o kojoj smo pričali u članku. No, kao što pokazuje praksa, FPU nije donio značajan porast brzine. Sljedeći korak bio je postavljanje prioriteta tokova. U Embox-u postoje različite strategije planiranja, i uključio sam onu koja podržava prioritete, dajući audio tokovima najviši prioritet. To također nije pomoglo.

Sljedeća ideja bila je da radimo s vanjskom memorijom i bilo bi dobro premjestiti strukture u nju, do kojih se izuzetno često pristupa. Proveo sam preliminarnu analizu kada i za što simple_pjsua se dodjeljuje memorija. Ispostavilo se da od 190 Kb, prvih 90 Kb se dodjeljuje za unutarnje potrebe PJSIP-a i njihovo korištenje nije baš učestalo. Zatim, tijekom dolaznog poziva, poziva se funkcija pjsua_call_answer, u kojoj se tada dodjeljuju baferi za rad s dolaznim i izlaznim okvirima. To je bilo još oko 100 Kb. I tada smo postupili ovako. Do trenutka poziva, podatke smještamo u vanjsku memoriju. Čim poziv započne — odmah zamjenjujemo hrpu s drugom — u RAM-u. Tako su svi „vrući“ podaci preneseni u bržu i predvidljiviju memoriju.

Na kraju, sve ovo zajedno omogućilo je pokretanje simple_pjsua i pozivanje putem vlastitog servera. A zatim i putem drugih servera poput sip.linphone.org.

Zaključci

Na kraju je uspjelo pokrenuti simple_pjsua s prijenosom glasa u oba smjera preko servera. Problem s dodatno potrošenih 128 Kb SDRAM-a može se riješiti korištenjem malo moćnijeg Cortex-M7 (na primjer, STM32F769NI s 512 Kb RAM-a), ali još uvijek se nadamo da ćemo stati i u 256 Kb 🙂 Bit ćemo sretni ako se netko zainteresira, a još bolje — isproba. Svi izvori, kao i obično, dostupni su na našem repozitoriju.

Izvor: habr.com

Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere 🔥 Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere | ProHoster