تلفن SIP در STM32F7-Discovery

سلام بر همه

چندی پیش ما писали در مورد اینکه چگونه توانستیم یک تلفن SIP در STM32F4-Discovery با 1 مگابایت رام و 192 کیلوبایت رم راه اندازی کنیم) بر اساس صندوق پستی. در اینجا باید گفت که آن نسخه حداقل بود و دو گوشی را مستقیماً بدون سرور و با انتقال صدا تنها در یک جهت متصل می کرد. بنابراین، تصمیم گرفتیم یک تلفن کاملتر با تماس از طریق سرور، انتقال صدا در هر دو جهت، اما در عین حال در کمترین اندازه حافظه ممکن راه اندازی کنیم.


برای تلفن، تصمیم گرفته شد که یک برنامه را انتخاب کنید simple_pjsua به عنوان بخشی از کتابخانه PJSIP. این یک برنامه حداقلی است که می تواند روی سرور ثبت نام کند، تماس ها را دریافت و پاسخ دهد. در زیر فوراً توضیحی در مورد نحوه اجرای آن در STM32F7-Discovery خواهم داد.

نحوه اجرا

  1. پیکربندی Embox
    make confload-platform/pjsip/stm32f7cube
  2. حساب SIP مورد نیاز را در فایل conf/mods.config تنظیم کنید.
    
    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 در کنار نمایشگر صحبت کنید. ما از لینوکس از طریق اپلیکیشن simple_pjsua، pjsua تماس می گیریم. خوب، یا می توانید از هر نوع لینفون دیگری استفاده کنید.

همه اینها در ما توضیح داده شده است ویکی.

چگونه به آنجا رسیدیم

بنابراین، در ابتدا این سوال در مورد انتخاب یک پلت فرم سخت افزاری مطرح شد. از آنجایی که مشخص بود STM32F4-Discovery از حافظه جا نمی گیرد، STM32F7-Discovery انتخاب شد. او یک درایو فلش 1 مگابایتی و 256 کیلوبایت رم دارد (+ 64 حافظه سریع ویژه که ما نیز از آن استفاده خواهیم کرد). همچنین برای تماس از طریق سرور زیاد نیست، اما ما تصمیم گرفتیم سعی کنیم با آن هماهنگ شویم.

به طور مشروط برای خود، این کار به چند مرحله تقسیم شد:

  • اجرای PJSIP در QEMU. برای اشکال زدایی راحت بود، به علاوه ما قبلاً از کدک AC97 پشتیبانی می کردیم.
  • ضبط و پخش صدا در QEMU و STM32.
  • انتقال یک برنامه simple_pjsua از PJSIP این به شما امکان می دهد در سرور SIP ثبت نام کنید و تماس برقرار کنید.
  • سرور مبتنی بر ستاره خود را مستقر کرده و روی آن تست کنید، سپس سرورهای خارجی مانند sip.linphone.org را امتحان کنید.

صدا در Embox از طریق Portaudio کار می کند که در PISIP نیز استفاده می شود. اولین مشکلات در QEMU ظاهر شد - WAV در 44100 هرتز به خوبی پخش شد، اما در 8000 به وضوح مشکلی پیش آمد. معلوم شد که موضوع تنظیم فرکانس است - به طور پیش فرض در تجهیزات 44100 بود و این از نظر برنامه ای تغییر نکرد.

در اینجا شاید لازم باشد کمی توضیح دهیم که چگونه صدا به طور کلی پخش می شود. کارت صدا را می توان روی یک نشانگر به یک قطعه حافظه که می خواهید از آن با فرکانس از پیش تعیین شده پخش یا ضبط کنید، تنظیم کنید. پس از پایان بافر، یک وقفه ایجاد می شود و اجرا با بافر بعدی ادامه می یابد. واقعیت این است که این بافرها باید از قبل در حین پخش قبلی پر شوند. در STM32F7 بیشتر با این مشکل مواجه خواهیم شد.

بعد، ما یک سرور اجاره کردیم و استریسک را روی آن مستقر کردیم. از آنجایی که نیاز به اشکال زدایی زیاد بود، اما نمی خواستم زیاد با میکروفون صحبت کنم، لازم بود پخش و ضبط خودکار انجام شود. برای این کار، simple_pjsua را وصله کردیم تا بتوانید به جای دستگاه های صوتی، فایل ها را لغزش کنید. در PJSIP، این کار به سادگی انجام می شود، زیرا آنها مفهوم پورت را دارند که می تواند یک دستگاه یا یک فایل باشد. و این پورت ها را می توان به صورت انعطاف پذیر به پورت های دیگر متصل کرد. شما می توانید کد را در pjsip ما ببینید مخازن. در نتیجه، طرح به شرح زیر بود. در سرور استریسک، من دو حساب را راه اندازی کردم - برای لینوکس و برای Embox. سپس دستور در Embox اجرا می شود simple_pjsua_imported، Embox روی سرور ثبت می شود و پس از آن Embox را از لینوکس فراخوانی می کنیم. در لحظه اتصال روی سرور استریسک چک می کنیم که اتصال برقرار است و پس از مدتی باید در Embox صدا را از لینوکس بشنویم و در لینوکس فایلی که از Embox پخش می شود را ذخیره می کنیم.

بعد از اینکه روی QEMU کار کرد، به سمت انتقال به STM32F7-Discovery رفتیم. اولین مشکل این است که آنها بدون بهینه سازی کامپایلر فعال "-Os" برای اندازه تصویر در 1 مگابایت رام قرار نمی گیرند. به همین دلیل ما "-Os" را قرار دادیم. علاوه بر این، پچ پشتیبانی از C ++ را غیرفعال کرد، بنابراین فقط برای pjsua مورد نیاز است و ما از simple_pjsua استفاده می کنیم.

پس از قرار گرفتن simple_pjsua، تصمیم گرفت که اکنون فرصتی برای راه اندازی آن وجود دارد. اما ابتدا باید به ضبط و پخش صدا پرداخت. سوال اینجاست که کجا بنویسیم؟ ما حافظه خارجی را انتخاب کردیم - SDRAM (128 مگابایت). شما می توانید این را خودتان امتحان کنید:

یک WAV استریو با فرکانس 16000 هرتز و مدت زمان 10 ثانیه ایجاد می کند:


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

باختیم:


play -m C0000000

اینجا دوتا مشکل داریم. اولی با کدک - WM8994 استفاده می شود و چیزی به نام اسلات دارد و 4 تا از این اسلات وجود دارد بنابراین به طور پیش فرض اگر این پیکربندی نشده باشد در هنگام پخش صدا پخش در هر چهار اسلات انجام می شود. . بنابراین، در فرکانس 16000 هرتز، ما 8000 هرتز دریافت کردیم، اما برای 8000 هرتز، پخش به سادگی کار نمی کرد. وقتی فقط اسلات 0 و 2 انتخاب شدند، همانطور که باید کار می کرد. مشکل دیگر رابط صوتی در STM32Cube بود که در آن خروجی صدا از طریق SAI (رابط صوتی سریال) به طور همزمان با ورودی صدا کار می کند (من جزئیات را متوجه نشدم، اما معلوم شد که آنها یک ساعت مشترک دارند و زمانی که خروجی صدا مقدار دهی اولیه می شود، صدا به نحوی به ورودی آن متصل می شود). یعنی نمی‌توانید آنها را جداگانه اجرا کنید، بنابراین ما کارهای زیر را انجام دادیم - ورودی صدا و خروجی صدا همیشه کار می‌کنند (از جمله وقفه‌ها ایجاد می‌شوند). اما زمانی که هیچ چیزی در سیستم پخش نمی شود، به سادگی یک بافر خالی را در خروجی صدا قرار می دهیم و وقتی پخش شروع می شود، صادقانه شروع به پر کردن آن می کنیم.

علاوه بر این، ما با این واقعیت مواجه شدیم که صدا در هنگام ضبط صدا بسیار آرام بود. این به دلیل این واقعیت است که میکروفون های MEMS در STM32F7-Discovery به نحوی در فرکانس های زیر 16000 هرتز به خوبی کار نمی کنند. بنابراین 16000 هرتز را تنظیم می کنیم حتی اگر 8000 هرتز بیاید. برای انجام این کار، لازم بود یک نرم افزار تبدیل یک فرکانس به فرکانس دیگر اضافه شود.

بعد، مجبور شدم اندازه هیپ را که در RAM قرار دارد، افزایش دهم. طبق محاسبات ما، pjsip حدود 190 کیلوبایت نیاز داشت و فقط حدود 100 کیلوبایت باقی مانده است. در اینجا مجبور شدم از حافظه خارجی استفاده کنم - SDRAM (حدود 128 کیلوبایت).

بعد از این همه ویرایش، اولین بسته های بین لینوکس و ایمباکس را دیدم و صدا را شنیدم! اما صدا وحشتناک بود، اصلا شبیه QEMU نبود، تشخیص چیزی غیرممکن بود. سپس به این فکر کردیم که چه چیزی می تواند باشد. اشکال زدایی نشان داد که Embox به سادگی زمان برای پر کردن / تخلیه بافرهای صوتی ندارد. در حالی که pjsip در حال پردازش یک فریم بود، 2 وقفه در مورد تکمیل پردازش بافر زمان داشت که خیلی زیاد است. اولین فکر برای افزایش سرعت بهینه سازی کامپایلر بود، اما قبلاً در PJSIP گنجانده شده بود. دومی یک نقطه شناور سخت افزاری است، ما در مورد آن صحبت کردیم مقاله. اما همانطور که تمرین نشان داده است، FPU افزایش قابل توجهی در سرعت نداد. مرحله بعدی اولویت بندی موضوعات بود. Embox استراتژی‌های زمان‌بندی مختلفی دارد، و من یکی را اضافه کرده‌ام که از اولویت‌ها پشتیبانی می‌کند و جریان‌های صوتی را روی بالاترین اولویت قرار می‌دهد. این هم کمکی نکرد

ایده بعدی این بود که ما با حافظه خارجی کار می کنیم و خوب است که ساختارهایی را به آنجا منتقل کنیم که بسیار زیاد به آنها دسترسی پیدا می کنند. من یک تحلیل اولیه از زمان و تحت چه زمانی انجام دادم simple_pjsua حافظه را اختصاص می دهد. مشخص شد که از 190 کیلوبایت، 90 کیلوبایت اول برای نیازهای داخلی PJSIP تخصیص داده شده است و اغلب به آنها دسترسی پیدا نمی شود. علاوه بر این، در طول یک تماس ورودی، تابع pjsua_call_answer فراخوانی می شود، که در آن بافرها برای کار با فریم های ورودی و خروجی تخصیص داده می شوند. هنوز حدود 100 کیلوبایت بود. و سپس موارد زیر را انجام دادیم. تا لحظه تماس، داده ها را در حافظه خارجی قرار می دهیم. به محض تماس، بلافاصله پشته را با یکی دیگر - در RAM جایگزین می کنیم. بنابراین، تمام داده های "گرم" به حافظه سریعتر و قابل پیش بینی تر منتقل شدند.

در نتیجه همه اینها با هم امکان راه اندازی را فراهم کرد simple_pjsua و از طریق سرور خود تماس بگیرید. و سپس از طریق سرورهای دیگر مانند sip.linphone.org.

یافته ها

در نتیجه امکان راه اندازی وجود داشت simple_pjsua با انتقال صدا در هر دو جهت از طریق سرور. مشکل 128 کیلوبایت SDRAM اضافی را می توان با استفاده از Cortex-M7 کمی قدرتمندتر حل کرد (به عنوان مثال STM32F769NI با 512 کیلوبایت رم)، اما در عین حال، ما هنوز امید خود را برای ورود به 256 از دست نداده ایم. KB 🙂 خوشحال خواهیم شد اگر کسی علاقه مند باشد، یا بهتر است آن را امتحان کند. همه منابع، طبق معمول، در ما هستند مخازن.

منبع: www.habr.com

اضافه کردن نظر