SIP телефон на STM32F7-Discovery

Здраво на сите

Пред некое време ние пишува за тоа како успеавме да лансираме SIP телефон на STM32F4-Discovery со 1 MB ROM и 192 KB RAM) врз основа на Ембокс. Овде мора да се каже дека таа верзија беше минимална и поврзуваше два телефони директно без сервер и со пренос на глас само во еден правец. Затоа, решивме да лансираме покомплетен телефон со повик преку сервер, пренос на глас во двете насоки, но во исто време да се вклопи во најмала можна големина на меморијата.


Беше одлучено да се избере апликација за телефонот просто_пјсуа како дел од библиотеката на ПЈСИП. Ова е минимална апликација која може да се регистрира на серверот, да прима и одговара на повици. Подолу веднаш ќе дадам опис како да се изврши ова на STM32F7-Discovery.

Како да започнете

  1. Конфигурирање на Embox
    make confload-platform/pjsip/stm32f7cube
  2. Во датотеката conf/mods.config ја поставивме потребната SIP сметка.
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server", 
        sip_user="username",
        sip_passwd="password")
    

    каде што сервер е SIP сервер (на пример, sip.linphone.org), корисничко име и лозинка — корисничко име и лозинка за сметката.

  3. Со тим го составуваме Embox направи. Имаме информации за фирмверот на плочата на вики и Член.
  4. Извршете ја командата „simple_pjsua_imported“ во конзолата Embox
    
    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. Конечно, останува само да се вметнат звучници или слушалки во аудио излезот и да се зборува во два мали MEMS микрофони до екранот. Повикуваме од Linux користејќи ја апликацијата simple_pjsua, pjsua. Па, или можете да користите било кој друг тип на телефон за телефон.

Сето ова е опишано на нашата вики.

Како стигнавме овде

Значи, првично се појави прашањето за избор на хардверска платформа. Бидејќи беше јасно дека STM32F4-Discovery нема да биде соодветен за меморија, беше избран STM32F7-Discovery. Таа има 1 MB флеш диск и 256 KB RAM (+ 64 специјална брза меморија, која исто така ќе ја користиме). Исто така, не е многу за повици преку серверот, но решивме да се обидеме да влеземе.

Конвенционално, задачата беше поделена во неколку фази:

  • Водење на PJSIP на QEMU. Беше погодно за дебагирање, плус веќе имавме поддршка за кодекот AC97 таму.
  • Гласовно снимање и репродукција на QEMU и STM32.
  • Пренесување на апликацијата просто_пјсуа од ПЈСИП. Ви овозможува да се регистрирате на SIP сервер и да остварувате повици.
  • Распоредете сопствен сервер базиран на ѕвездичка и тестирајте на него, а потоа пробајте ги надворешните, како што е sip.linphone.org

Звукот во Embox работи преку Portaudio, кој исто така се користи во PISIP. Првите проблеми се појавија на QEMU - WAV-овите се играа добро на 44100 Hz, но на 8000 нешто очигледно тргна наопаку. Се испостави дека проблемот е во поставувањето на фреквенцијата - стандардно во опремата беше 44100, а ние не го сменивме ова во софтверот.

Овде, веројатно вреди да се објасни малку за тоа како се репродуцира звукот воопшто. Звучната картичка може да постави одреден покажувач на парче меморија од која треба да се репродуцира или да се снима на однапред одредена фреквенција. Откако ќе истече баферот, се генерира прекин и извршувањето продолжува од следниот тампон. Поентата е дека овие бафери треба да се пополнат однапред додека се репродуцира претходниот. Овој проблем ќе го сретнеме понатаму на STM32F7.

Следно, изнајмивме сервер и распоредивме Asterisk на него. Бидејќи имаше многу дебагирање што требаше да се направи и не сакав многу да зборувам во микрофонот, неопходно беше да се направи автоматска репродукција и снимање. За да го направите ова, го закрпивме simple_pjsua за да можеме да вметнуваме датотеки наместо аудио уреди. Во PJSIP ова се прави многу едноставно, бидејќи тие го имаат концептот на порта, која може да биде или уред или датотека. И овие порти можат флексибилно да се поврзат со други порти. Можете да го видите кодот во нашиот pjsip складишта. Како резултат на тоа, шемата беше како што следува. Направив две сметки на серверот Asterisk - за Linux и за Embox. Следно, командата се извршува на Embox едноставна_пјсуа_увезена, Embox се регистрира на серверот, по што го повикуваме Embox од Linux. Во моментот на поврзување проверуваме на серверот Asterisk дали е воспоставена целата конекција и по некое време треба да слушнеме звук од Linux во Embox, а во Linux ја зачувуваме датотеката што се репродуцира од Embox.

Откако ова функционираше на QEMU, продолживме да го пренесуваме во STM32F7-Discovery. Првиот проблем беше што не можевме да се вклопиме во 1 MB ROM без вклучена оптимизација на компајлерот „-Os“ за големината на сликата. Затоа, вклучивме „-Os“. Следно, закрпата ја оневозможи поддршката за C++, така што е потребна само за pjsua, а ние користиме simple_pjsua.

По поставувањето просто_пјсуа, одлучи дека сега има шанса да го лансира. Но, прво требаше да откриеме како да снимаме и репродуцираме гласови. Прашање: каде да пишувам? Избравме надворешна меморија - SDRAM (128 MB). Можете да го пробате ова сами:

Ќе создаде стерео WAV со фреквенција од 16000 Hz и времетраење од 10 секунди:


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

Ние губиме:


play -m C0000000

Тука имаше два проблеми. Првиот е со кодекот - се користи WM8994 и има такво нешто како слот и има 4 од овие слотови четири слотови. Затоа, на фреквенција од 16000 Hz добивме 8000 Hz, но за репродукција од 8000 Hz едноставно не функционираше. Кога избравме само слотови 0 и 2, работеше како што се очекуваше. Друг проблем беше аудио интерфејсот во STM32Cube, во кој аудио излезот работи преку SAI (Serial Audio Interface) синхроно со аудио влезот (не ги разбрав деталите, но излегува дека делат заеднички часовник и при иницијализирање аудио излезот, звукот е некако врзан за влезот). Тоа е, невозможно е да ги извршите одделно, па го направивме следново - аудио влезот и аудио излезот секогаш работат (вклучувајќи ги и прекините се генерираат). Но, кога ништо не се репродуцира во системот, едноставно внесуваме празен тампон во аудио излезот, а кога ќе започне репродукцијата, искрено почнуваме да го пополнуваме.

Тогаш наидовме на фактот дека звукот при снимањето на гласот беше многу тивок. Ова се должи на фактот дека микрофоните MEMS на STM32F7-Discovery некако не работат добро на фреквенции под 16000 Hz. Затоа, го поставивме на 16000 Hz, дури и ако пристигне 8000 Hz. За да го направите ова, сепак, беше неопходно да се додаде софтверска конверзија на една фреквенција во друга.

Следно, моравме да ја зголемиме големината на купот, кој се наоѓа во RAM меморијата. Според нашите пресметки, pjsip бараше околу 190 KB, а ни останаа само околу 100 KB. Тука моравме да користиме малку надворешна меморија - SDRAM (околу 128 KB).

После сите овие уредувања, ги видов првите пакети помеѓу Linux и Embox и го слушнав звукот! Но звукот беше страшен, воопшто не како на QEMU, ништо не се слушаше. Потоа се запрашавме што може да биде работата. Дебагирањето покажа дека Embox едноставно нема време да ги пополни/расточи аудио баферите. Додека pjsip обработува една рамка, се случија 2 прекини за завршување на обработката на баферот, што е премногу. Мојата прва мисла за забрзување беше оптимизација на компајлерот, но тоа веќе беше вклучено во PJSIP. Вториот е хардверска подвижна запирка, разговаравме за тоа Член. Но, како што покажа практиката, FPU не обезбеди значително зголемување на брзината. Следниот чекор беше да се постават приоритети на конецот. Embox има различни стратегии за закажување, а јас ја овозможив онаа што поддржува приоритети и им дадов најголем приоритет на аудио преносите. Ниту ова не помогна.

Следната идеја беше дека работиме со надворешна меморија и би било добро таму да се преместуваат структури до кои се пристапува исклучително често. Спроведов прелиминарна анализа за тоа кога и под што просто_пјсуа доделува меморија. Се покажа дека од 190 KB, првите 90 KB се распределени за внатрешните потреби на ПЈСИП и до нив не се пристапува многу често. Следно, за време на дојдовен повик, се повикува функцијата pjsua_call_answer, во која потоа се доделуваат бафери за работа со дојдовни и појдовни рамки. Сè уште беше околу 100 KB. И тогаш го направивме следново. Сè додека не се оствари повикот, податоците се чуваат во надворешна меморија. Штом ѕвони повикот, веднаш го заменуваме купот со друг во RAM меморијата. Така, сите „жешки“ податоци беа префрлени во побрза и попредвидлива меморија.

Како резултат на тоа, сето ова заедно ни овозможи да лансираме просто_пјсуа и јавете се преку вашиот сервер. А потоа преку други сервери како sip.linphone.org.

Наоди

На крајот беше можно да се лансира просто_пјсуа со пренос на глас во двете насоки преку серверот. Проблемот со дополнителни 128 KB SDRAM може да се реши со користење на малку помоќен Cortex-M7 (на пример, STM32F769NI со 512 KB RAM), но сè уште не сме се откажале од надежта дека ќе се вклопиме во 256 KB :) Ќе биди мило ако некој е заинтересиран, или уште подобро, пробај. Сите извори, како и обично, се во нашите складишта.

Извор: www.habr.com

Додадете коментар