SIP telefon na STM32F7-Discovery

Pozdrav.

Prije nekog vremena mi писали o tome kako smo uspjeli lansirati SIP telefon na STM32F4-Discovery s 1 MB ROM-a i 192 KB RAM-a) na temelju Embox. Ovdje treba reći da je ta verzija bila minimalna i povezivala je dva telefona direktno bez servera i sa prijenosom glasa u samo jednom smjeru. Stoga smo odlučili pokrenuti cjelovitiji telefon s pozivom preko servera, prijenosom glasa u oba smjera, ali u isto vrijeme zadržati unutar najmanje moguće veličine memorije.


Za telefon je odlučeno odabrati aplikaciju jednostavna_pjsua u sklopu knjižnice PJSIP. Ovo je minimalna aplikacija koja se može registrirati na poslužitelju, primati i odgovarati na pozive. U nastavku ću odmah dati opis kako ga pokrenuti na STM32F7-Discovery.

Kako trčati

  1. Konfiguriranje Emboxa
    make confload-platform/pjsip/stm32f7cube
  2. Postavite potreban SIP račun 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 poslužitelj (na primjer, sip.linphone.org), korisničko ime и lozinka - korisničko ime i lozinka računa.

  3. Sastavljanje Emboxa kao tim napraviti. O firmware-u ploče koji imamo wiki i č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, preostaje u audio izlaz ubaciti zvučnike ili slušalice, te govoriti u dva mala MEMS mikrofona pored displeja. Zovemo iz Linuxa preko aplikacije simple_pjsua, pjsua. Pa, ili možete koristiti bilo koju drugu vrstu telefonskog telefona.

Sve je to opisano na našem wiki.

Kako smo dospjeli 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 flash pogon od 1 MB i 256 KB RAM-a (+ 64 posebne brze memorije, koju ćemo također koristiti). Također nije puno za pozive preko poslužitelja, ali odlučili smo se pokušati uklopiti.

Uvjetno za sebe, zadatak je podijeljen u nekoliko faza:

  • Pokretanje PJSIP-a na QEMU. Bilo je zgodno za otklanjanje pogrešaka, plus što smo tamo već imali podršku za AC97 kodek.
  • Snimanje i reprodukcija glasa na QEMU i STM32.
  • Prijenos aplikacije jednostavna_pjsua iz PJSIP-a. Omogućuje vam registraciju na SIP poslužitelju i upućivanje poziva.
  • Implementirajte svoj vlastiti poslužitelj temeljen na Asterisk-u i isprobajte ga, a zatim isprobajte vanjski kao što je sip.linphone.org

Zvuk u Emboxu radi kroz Portaudio, 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 je očito nešto pošlo po zlu. Ispostavilo se da je u pitanju podešavanje frekvencije - standardno je u opremi bilo 44100, a to se programski nije mijenjalo.

Ovdje, možda, vrijedi malo objasniti kako se zvuk općenito reproducira. Zvučna kartica može se postaviti na neki pokazivač na dio memorije iz kojeg želite reproducirati ili snimati na unaprijed određenoj frekvenciji. Nakon što međuspremnik završi, generira se prekid i izvođenje se nastavlja sa sljedećim međuspremnikom. Činjenica je da se ovi međuspremnici moraju popuniti unaprijed dok se prethodni igra. Suočit ćemo se s ovim problemom dalje na STM32F7.

Zatim smo unajmili poslužitelj i na njemu postavili Asterisk. Budući da je bilo potrebno puno debugirati, ali nisam htio puno govoriti u mikrofon, bilo je potrebno napraviti automatsku reprodukciju i snimanje. Da bismo to učinili, zakrpali smo simple_pjsua tako da možete ubaciti datoteke umjesto audio uređaja. U PJSIP-u se to radi vrlo jednostavno, budući da imaju koncept porta, koji može biti ili uređaj ili datoteka. I ti se priključci mogu fleksibilno povezati s drugim priključcima. Kod možete vidjeti u našem pjsipu spremišta. Kao rezultat toga, shema je bila sljedeća. Na Asterisk serveru pokrenuo sam dva računa - za Linux i za Embox. Zatim se naredba izvršava na Emboxu jednostavna_pjsua_uvezena, Embox se prijavljuje na poslužitelj, nakon čega pozivamo Embox iz Linuxa. U trenutku povezivanja provjeravamo na Asterisk serveru je li veza uspostavljena i nakon nekog vremena trebali bismo čuti zvuk iz Linuxa u Emboxu, a u Linuxu spremamo datoteku koja se pusti iz Emboxa.

Nakon što je radio na QEMU, prešli smo na prijenos na STM32F7-Discovery. Prvi problem je što nisu stali u 1 MB ROM-a bez omogućene optimizacije prevoditelja "-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 jednostavna_pjsua, odlučio je da sada postoji prilika da ga pokrene. Ali prvo se trebalo pozabaviti snimanjem i reprodukcijom glasa. Pitanje je gdje napisati? Odabrali smo vanjsku memoriju - SDRAM (128 MB). Možete isprobati ovo sami:

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


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

Mi gubimo:


play -m C0000000

Ovdje postoje dva problema. Koristi se prvi s kodekom - WM8994 i ima nešto poput utora, a ima ih 4. Dakle, prema zadanim postavkama, ako ovo nije konfigurirano, prilikom reprodukcije zvuka, reprodukcija se odvija u sva četiri utora . Dakle, na frekvenciji od 16000 Hz dobili smo 8000 Hz, ali za 8000 Hz reprodukcija jednostavno nije radila. Kada su odabrani samo utori 0 i 2, radilo je kako treba. Drugi problem bilo je audio sučelje u STM32Cube, u kojem audio izlaz radi preko SAI (Serial Audio Interface) sinkrono s audio ulazom (nisam razumio detalje, ali pokazalo se da dijele zajednički sat i kada audio izlaz je inicijaliziran, audio je nekako priključen na njegov ulaz). Odnosno, ne možete ih pokrenuti odvojeno, pa smo učinili sljedeće - audio ulaz i audio izlaz uvijek rade (uključujući generiranje prekida). Ali kad se ništa ne reproducira u sustavu, onda jednostavno ubacimo prazan međuspremnik u audio izlaz, a kad krene reprodukcija, pošteno ga počnemo puniti.

Nadalje, naišli smo na činjenicu da je zvuk tijekom 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, 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 izračunima, pjsip je zahtijevao oko 190 KB, a nama je ostalo samo oko 100 KB. Ovdje sam morao koristiti nešto vanjske memorije - 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-u, nije se moglo ništa razabrati. Onda smo razmišljali što bi moglo biti u pitanju. Otklanjanje pogrešaka pokazalo je da Embox jednostavno nema vremena za popunjavanje/istovaranje audio međuspremnika. Dok je pjsip obrađivao jedan okvir, imala su se vremena dogoditi 2 prekida oko završetka obrade međuspremnika, što je previše. Prva pomisao na brzinu bila je optimizacija prevoditelja, ali ona je već bila uključena u PJSIP. Drugi je hardverski pokretni zarez, o njemu smo govorili u članak. Ali kao što je praksa pokazala, FPU nije dao značajno povećanje brzine. Sljedeći korak bilo je određivanje prioriteta niti. Embox ima različite strategije zakazivanja, a ja sam uključio onu koja podržava prioritete i postavlja audio streamove na najviši prioritet. Ni ovo nije pomoglo.

Sljedeća ideja je bila da radimo s vanjskom memorijom i da bi bilo lijepo tamo premjestiti strukture kojima se iznimno često pristupa. Napravio sam preliminarnu analizu kada i pod čime jednostavna_pjsua dodjeljuje memoriju. Pokazalo se da je od 190 Kb prvih 90 Kb namijenjeno internim potrebama PJSIP-a i njima se ne pristupa često. Nadalje, tijekom dolaznog poziva poziva se funkcija pjsua_call_answer u kojoj se zatim dodjeljuju međuspremnici za rad s dolaznim i odlaznim okvirima. I dalje je bilo oko 100 Kb. A onda smo učinili sljedeće. Do trenutka poziva podatke pohranjujemo u vanjsku memoriju. Čim poziv, odmah zamijenimo hrpu drugom - u RAM-u. Tako su svi “vrući” podaci prebačeni u bržu i predvidljiviju memoriju.

Kao rezultat, sve to zajedno omogućilo je pokretanje jednostavna_pjsua i poziv putem vašeg poslužitelja. A zatim i preko drugih poslužitelja kao što je sip.linphone.org.

Zaključci

Kao rezultat toga, bilo je moguće pokrenuti jednostavna_pjsua s prijenosom glasa u oba smjera preko poslužitelja. Problem s dodatno potrošenih 128 KB SDRAM-a može se riješiti korištenjem nešto jačeg Cortex-M7 (primjerice STM32F769NI s 512 KB RAM-a), no pritom još uvijek nismo izgubili nadu da ćemo ući u 256 KB 🙂 Bit će nam drago ako netko bude zainteresiran, ili još bolje, probajte. Svi su izvori, kao i obično, u našem spremišta.

Izvor: www.habr.com

Dodajte komentar