Hallo allemaal.
Een tijd geleden hebben we hoe we erin zijn geslaagd om een SIP-telefonie op STM32F4-Discovery met 1 MB ROM en 192 KB RAM op te zetten, gebaseerd op . Hierbij moet gezegd worden dat die versie minimaal was en twee telefoons rechtstreeks met elkaar verbond zonder server, met spraakoverdracht slechts in ƩƩn richting. Daarom besloten we een meer volledige telefoon te lanceren met een oproep via de server, spraakoverdracht in beide richtingen, maar met zo min mogelijk geheugengrootte.

Voor de telefoon hebben we besloten om de applicatie simple_pjsua uit de PJSIP-bibliotheek te kiezen. Dit is een minimale applicatie die kan registreren op de server, oproepen kan aannemen en beantwoorden. Hieronder zal ik meteen beschrijven hoe je dit kunt uitvoeren op STM32F7-Discovery.
Hoe te starten
- Configureren van Embox
make confload-platform/pjsip/stm32f7cube - In het bestand conf/mods.config definiƫren we het benodigde SIP-account.
include platform.pjsip.cmd.simple_pjsua_imported( sip_domain="server", sip_user="username", sip_passwd="password")waar server ā dit is de SIP-server (bijvoorbeeld, sip.linphone.org), username en password ā de gebruikersnaam en het wachtwoord voor het account.
- We bouwen Embox met het commando make. We hebben informatie over het flashen van de kaart op onze en in .
- Voer in de console van Embox het commando āsimple_pjsua_importedā uit
00:00:12.870 pjsua_acc.c ....SIP outbound status voor acc 0 is niet actief 00:00:12.884 pjsua_acc.c ....sip:alexk2222@sip.linphone.org: registratie succesvol, status=200 (Registratie succesvol) 00:00:12.911 pjsua_acc.c ....Keep-alive timer gestart voor acc 0, bestemming:91.121.209.194:5060, interval:15s - Ten slotte, het enige wat we nog moesten doen was de luidsprekers of koptelefoon aansluiten op de audio-uitgang, en praten in twee kleine MEMS-microfoons naast het scherm. We bellen vanaf Linux met de applicatie simple_pjsua, pjsua. Of we kunnen ook een andere zoals linphone gebruiken.
Dit is allemaal beschreven op onze .
Hoe we hier kwamen
Dus, in eerste instantie stonden we voor de keuze van de hardwareplatform. Aangezien het duidelijk was dat de STM32F4-Discovery niet geschikt was qua geheugen, werd de STM32F7-Discovery gekozen. Het heeft 1 MB flash en 256 KB RAM (+ 64 KB speciale snelle geheugen die we ook gaan gebruiken). Ook niet veel voor bellen via de server, maar we besloten het te proberen.
We hebben de taak voor onszelf in verschillende fasen verdeeld:
- PJSIP draaien op QEMU. Dit was handig voor debugging, plus we hadden daar al ondersteuning voor de AC97-codec.
- Opnames en afspelen van geluid op QEMU en op STM32.
- Porteren van de applicatie simple_pjsua uit de PJSIP-bibliotheek. Het stelt je in staat om je te registreren op een SIP-server en te bellen.
- Stel je eigen server op basis van Asterisk in en test het daarop, daarna kun je externe zoals sip.linphone.org proberen.
Geluid in Embox werkt via Portaudio, dat ook in PISIP wordt gebruikt. Bij QEMU kwamen de eerste problemen naar voren: WAV-bestanden op 44100 Hz speelden goed af, maar op 8000 Hz ging er duidelijk iets mis. Het bleek dat de probleem bij de frequentie-instelling lag ā standaard was deze op 44100 ingesteld in de hardware, en wij veranderden dat programmatisch niet.
Hier moet misschien een korte uitleg komen over hoe het afspelen van geluid eigenlijk werkt. Aan de geluidskaart kan een aanwijzer worden ingesteld naar een stuk geheugen waaruit moet worden afgespeeld of opgenomen op een vooraf ingestelde frequentie. Zodra de buffer op is, wordt er een onderbreking gecreƫerd en gaat de uitvoering verder met de volgende buffer. Het probleem is dat deze buffers op tijd moeten worden gevuld terwijl de vorige wordt afgespeeld. Dit probleem zullen we later ook tegenkomen op de STM32F7.
Vervolgens huurden we een server en zetten Asterisk daarop op. Aangezien we veel moesten debuggen en niet veel in de microfoon wilden praten, moest er automatische afspeling en opname gemaakt worden. Hiervoor hebben we simple_pjsua gepatcht zodat we bestanden in plaats van audiokapaciteiten konden gebruiken. In PJSIP is dit vrij eenvoudig, omdat ze een poortconcept hebben, dat zowel een apparaat als een bestand kan zijn. En deze poorten kunnen flexibel aan andere poorten worden gekoppeld. Je kunt de code bekijken in onze pjsip. Uiteindelijk was het schema als volgt. Op de Asterisk-server heb ik twee accounts aangemaakt ā voor Linux en voor Embox. Daarna wordt het commando uitgevoerd op Embox. simple_pjsua_imported, Embox registreert zich op de server, waarna we vanaf Linux naar Embox bellen. Op het moment van verbinding controleren we op de Asterisk-server of de verbinding is opgezet, en na enige tijd zouden we geluid uit Linux in Embox moeten horen, terwijl we het bestand dat uit Embox wordt afgespeeld op Linux opslaan.
Nadat dit werkte op QEMU, gingen we over op de porting naar STM32F7-Discovery. Het eerste probleem was dat we niet in 1 MB ROM pasten zonder de compiler-optimalisatie ā-Osā voor de afbeeldingsgrootte in te schakelen. Daarom zetten we ā-Osā aan. Vervolgens hebben we met een patch de ondersteuning voor C++ uitgeschakeld, aangezien deze alleen nodig is voor pjsua en wij simple_pjsua gebruiken.
Nadat we erin passen simple_pjsua, concludeerden we dat de kansen om dit nu te starten er zijn. Maar eerst moesten we met de opname en afspelen van spraak aan de slag. De vraag was: waar moeten we opnemen? We kozen voor extern geheugen ā SDRAM (128 MB). Je kunt het zelf proberen:
Genereert stereo WAV met een frequentie van 16000 Hz en een duur van 10 seconden:
record -r 16000 -c 2 -d 10000 -m C0000000
Afspelen:
play -m C0000000
Hier waren twee problemen. Het eerste had te maken met de codec - WM8994 werd gebruikt, en daarin bestaat een concept genaamd slot, met in totaal 4 slots. Standaard, als dit niet wordt ingesteld, vindt audio-afspelen plaats in alle vier de slots. Bij 16000 Hz kregen we dus 8000 Hz, en voor 8000 Hz werkte het afspelen gewoon niet. Toen we alleen slots 0 en 2 selecteerden, werkte het zoals het hoort. Een ander probleem was de audio-interface in STM32Cube, waarin de audio-uitgang werkt via SAI (Serial Audio Interface) synchroon met de audio-ingang (ik heb me niet in de details verdiept, maar het lijkt erop dat ze een gezamenlijke klok delen en bij de initialisatie van de audio-uitgang op de een of andere manier de audio-ingang aan deze klok wordt gekoppeld). Dit betekent dat ze niet afzonderlijk kunnen worden gestart, dus we deden het volgende - zowel de audio-ingang als de audio-uitgang zijn altijd actief (inclusief het genereren van interrupts). Maar wanneer er niets in het systeem wordt afgespeeld, geven we de audio-uitgang gewoon een lege buffer, en wanneer afspelen begint, beginnen we deze op een eerlijke manier te vullen.
Daarna werden we geconfronteerd met het probleem dat het geluid bij het opnemen van de stem erg stil was. Dit gebeurt omdat MEMS-microfoons op de STM32F7-Discovery slecht werken bij frequenties onder de 16000 Hz. Daarom stellen we 16000 Hz in, zelfs als er 8000 Hz binnenkomt. Hiervoor moest echter wel een softwarematige conversie van de ene frequentie naar de andere worden toegevoegd.
Vervolgens moesten we de grootte van de heap in het RAM verhogen. Volgens onze berekeningen had pjsip ongeveer 190 Kb nodig, terwijl we nog maar ongeveer 100 Kb overhad. We moesten een beetje externe geheugen gebruiken - SDRAM (ongeveer 128 Kb).
Na al deze aanpassingen zag ik de eerste pakketten tussen Linux en Embox en hoorde ik geluid! Maar het geluid was vreselijk, helemaal niet zoals op QEMU; niets was te begrijpen. Toen vroegen we ons af wat er aan de hand kon zijn. De debugging toonde aan dat Embox simpelweg niet in staat was om audio-buffers op tijd te vullen/uit te voeren. Terwijl pjsip ƩƩn frame verwerkte, vonden er 2 interrupts plaats over het voltooien van de buffer-verwerking, wat te veel was. Onze eerste gedachte om te versnellen was compilatie-optimalisatie, maar deze was al ingeschakeld in PJSIP. Het tweede punt - de hardware floating point, waarover we hebben gesproken in . Maar zoals de praktijk heeft aangetoond, heeft de FPU geen significante snelheidstoename gegeven. De volgende stap was het stellen van prioriteiten voor de flows. In Embox zijn er verschillende planningsstrategieƫn, en ik heb diegene ingeschakeld die prioriteiten ondersteunt, en de maximale prioriteit toegewezen aan de audiostreams. Dit hielp ook niet.
De volgende gedachte was dat we met extern geheugen werken en het zou goed zijn om de structuren daarheen te verplaatsen, aangezien ze extreem vaak worden aangesproken. Ik heb een voorlopige analyse uitgevoerd van wanneer en waarvoor simple_pjsua geheugen wordt toegewezen. Het bleek dat van de 190 Kb de eerste 90 Kb werd toegewezen voor interne behoeften van PJSIP en hier werd niet zo vaak een beroep op gedaan. Vervolgens, tijdens een binnenkomende oproep, wordt de functie pjsua_call_answer aangeroepen, waarin dan de buffers voor het werken met inkomende en uitgaande frames worden toegewezen. Dit was nog eens ongeveer 100 Kb. We hebben het als volgt aangepakt. Voor het moment van de oproep plaatsen we de gegevens in extern geheugen. Zodra de oproep binnenkomt, vervangen we de heap onmiddellijk door een andere - in RAM. Op deze manier zijn alle 'hete' gegevens verplaatst naar sneller en voorspelbaarder geheugen.
Uiteindelijk heeft dit alles samen het mogelijk gemaakt om simple_pjsua te bellen via onze server. En daarna ook via andere servers zoals sip.linphone.org.
Conclusies
Uiteindelijk is het gelukt om simple_pjsua stemverkeer in beide richtingen via de server te verzenden. Het probleem met de extra 128 Kb SDRAM kan worden opgelost door gebruik te maken van een iets krachtiger Cortex-M7 (bijvoorbeeld de STM32F769NI met 512 Kb RAM), maar tegelijkertijd hebben we de hoop nog niet opgegeven om binnen de 256 Kb te blijven š We verwelkomen iedereen die geĆÆnteresseerd is en des te beter ā het zelf probeert. Alle bronnen, zoals gewoonlijk, zijn beschikbaar in onze .
Bron: habr.com
