Halo semuanya.
Beberapa waktu yang lalu kami
menulis tentang bagaimana kami berhasil meluncurkan telepon SIP pada STM32F4-Discovery dengan 1 MB ROM dan 192 KB RAM) berdasarkan
Embox . Di sini saya harus mengatakan bahwa versi itu minimal dan menghubungkan dua telepon langsung tanpa server dan dengan transmisi suara hanya dalam satu arah. Oleh karena itu, kami memutuskan untuk meluncurkan ponsel yang lebih lengkap dengan panggilan melalui server, transmisi suara di kedua arah, tetapi pada saat yang sama tetap dalam ukuran memori sekecil mungkin.
Untuk telepon, diputuskan untuk memilih aplikasi
simple_pjsua sebagai bagian dari perpustakaan PJSIP. Ini adalah aplikasi minimal yang dapat mendaftar di server, menerima dan menjawab panggilan. Di bawah ini saya akan segera memberikan deskripsi tentang cara menjalankan ini pada STM32F7-Discovery.
Bagaimana cara menjalankannya
- Mengkonfigurasi Embox
make confload-platform/pjsip/stm32f7cube
- Dalam file conf / mods.config, atur akun SIP yang diinginkan.
include platform.pjsip.cmd.simple_pjsua_imported( sip_domain="server", sip_user="username", sip_passwd="password")
di mana server adalah server SIP (misalnya, sip.linphone.org), nama pengguna dan kata sandi adalah nama pengguna dan kata sandi akun.
- Bangun Embox dengan perintah make . Tentang firmware papan yang kami miliki di wiki dan di artikel .
- Jalankan perintah "simple_pjsua_imported" di konsol 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:alexk2222@sip.linphone.org: 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
- Akhirnya, tetap memasukkan speaker atau headphone ke output audio, dan berbicara ke dua mikrofon MEMS kecil di dekat layar. Kami memanggil dari Linux melalui aplikasi simple_pjsua, pjsua. Ya, atau Anda bisa menggunakan jenis linphone lainnya.
Semua ini dijelaskan di
wiki kami.
Bagaimana kita sampai pada ini?
Jadi, pada awalnya muncul pertanyaan tentang memilih platform perangkat keras. Karena jelas bahwa STM32F4-Discovery tidak muat di memori, STM32F7-Discovery dipilih. Ia memiliki 1 MB flash drive dan 256 KB RAM (+ 64 memori cepat khusus, yang juga akan kami gunakan). Juga tidak banyak untuk panggilan melalui server, tetapi memutuskan untuk mencoba masuk.
Secara konvensional, tugas itu dibagi menjadi beberapa tahap:
- Menjalankan PJSIP di QEMU. Itu nyaman untuk debugging, ditambah kami sudah memiliki dukungan codec AC97 di sana.
- Rekaman dan pemutaran suara pada QEMU dan STM32.
- Porting aplikasi simple_pjsua dari dalam PJSIP. Ini memungkinkan Anda untuk mendaftar di server SIP dan membuat panggilan.
- Menyebarkan server berbasis Asterisk Anda sendiri dan mengujinya, lalu coba yang eksternal seperti sip.linphone.org
Sound in Embox bekerja melalui Portaudio, yang juga digunakan di PISIP. Masalah pertama muncul pada QEMU - WAV bermain dengan baik pada 44100 Hz, tetapi ada sesuatu yang salah pada 8000. Ternyata itu masalah pengaturan frekuensi - secara default itu adalah 44100 dalam peralatan, dan ini tidak berubah secara programatik dengan kami.
Di sini, mungkin perlu dijelaskan sedikit bagaimana suara dimainkan secara umum. Kartu suara dapat mengatur beberapa penunjuk ke memori yang ingin Anda mainkan atau rekam pada frekuensi yang telah ditentukan. Setelah buffer berakhir, interupsi dihasilkan, dan eksekusi berlanjut dari buffer berikutnya. Faktanya adalah bahwa buffer ini harus diisi terlebih dahulu sebelum yang sebelumnya dimainkan. Masalah ini akan kita temui lebih lanjut pada STM32F7.
Selanjutnya, kami menyewa server dan menggunakan Asterisk di atasnya. Karena itu perlu banyak debug, tetapi tidak ingin banyak bicara ke mikrofon, itu perlu untuk melakukan pemutaran dan perekaman otomatis. Untuk melakukan ini, kami menambal simple_pjsua sehingga memungkinkan untuk menyelipkan file di tempat perangkat audio. Dalam PJSIP, ini dilakukan cukup sederhana, karena mereka memiliki konsep port, yang dapat berupa perangkat atau file. Dan port ini dapat dihubungkan secara fleksibel ke port lain. Anda dapat melihat kode di
repositori pjsip kami. Hasilnya, skemanya adalah sebagai berikut. Saya membuat dua akun di server Asterisk - untuk Linux dan untuk Embox. Selanjutnya, perintah
simple_pjsua_imported dieksekusi di Embox, Embox terdaftar di server, setelah itu kita memanggil Embox dari Linux. Pada saat koneksi, kami memeriksa pada server Asterisk bahwa seluruh koneksi dibuat, dan setelah beberapa waktu mereka akan mendengar suara dari Linux di Embox, dan di Linux kami menyimpan file yang dimainkan dari Embox.
Setelah berhasil pada QEMU, kami beralih ke porting ke STM32F7-Discovery. Masalah pertama - mereka tidak masuk ke ROM 1 MB tanpa optimasi kompilasi "-Os" yang disertakan dalam hal ukuran gambar. Oleh karena itu termasuk "-Os". Lebih lanjut, tambalan menonaktifkan dukungan C ++, jadi itu hanya diperlukan untuk pjsua, dan kami menggunakan simple_pjsua.
Setelah
memasang simple_pjsua , kami memutuskan bahwa sekarang ada peluang untuk meluncurkannya. Tetapi pertama-tama, Anda harus berurusan dengan perekaman dan pemutaran suara. Pertanyaan - di mana harus menulis? Kami memilih memori eksternal - SDRAM (128 MB). Anda bisa mencobanya sendiri:
Membuat WAV stereo dengan frekuensi 16000 Hz dan durasi 10 detik:
record -r 16000 -c 2 -d 10000 -m C0000000
Kami kehilangan:
play -m C0000000
Ada dua masalah. Yang pertama dengan codec adalah WM8994, dan memiliki konsep seperti slot, dan slot ini adalah 4. Jadi, secara default, jika ini tidak dikonfigurasi, maka ketika memutar audio, pemutaran terjadi di keempat slot. Oleh karena itu, pada frekuensi 16000 Hz, kami menerima 8000 Hz, tetapi untuk 8000 Hz pemutaran tidak berhasil. Ketika hanya slot 0 dan 2 yang dipilih, itu berfungsi sebagaimana mestinya. Masalah lain adalah antarmuka audio di STM32Cube, di mana output audio bekerja melalui SAI (Serial Audio Interface) secara serempak dengan input audio (tidak mengerti detailnya, tetapi ternyata mereka berbagi jam yang sama dan entah bagaimana audio terpasang padanya ketika menginisialisasi output audio) masukan). Artinya, mereka tidak dapat diluncurkan secara terpisah, sehingga mereka melakukan hal berikut - input audio dan output audio selalu berfungsi (termasuk interupsi yang dihasilkan). Tetapi ketika tidak ada yang hilang dalam sistem, maka kita cukup memasukkan buffer kosong ke output audio, dan ketika pemutaran dimulai, kita dengan jujur ββmulai mengisinya.
Selanjutnya, mereka menemukan fakta bahwa suara saat merekam suara sangat sunyi. Hal ini disebabkan oleh kenyataan bahwa mikrofon MEMS pada STM32F7-Discovery entah bagaimana tidak bekerja dengan baik pada frekuensi di bawah 16000 Hz. Oleh karena itu, kami menetapkan 16000 Hz, bahkan jika 8000 Hz datang. Untuk melakukan ini, kebenarannya adalah menambahkan konversi perangkat lunak dari satu frekuensi ke frekuensi lainnya.
Selanjutnya, saya harus menambah ukuran heap, yang terletak di RAM. Menurut perkiraan kami, pjsip membutuhkan sekitar 190 Kb, dan kami hanya memiliki sekitar 100 Kb. Di sini saya harus menggunakan sedikit memori eksternal - SDRAM (sekitar 128 Kb).
Setelah semua pengeditan ini, saya melihat paket pertama antara Linux dan Embox, dan saya mendengar suara! Tapi suaranya mengerikan, sama sekali tidak seperti pada QEMU, tidak ada yang bisa dibuat. Lalu kami berpikir tentang apa yang mungkin terjadi. Debugging menunjukkan bahwa Embox tidak punya waktu untuk mengisi / membongkar buffer audio. Sementara pjsip sedang memproses satu frame, 2 gangguan telah terjadi sebelum penyelesaian pemrosesan buffer, yang terlalu banyak. Pikiran pertama untuk mempercepat adalah mengoptimalkan kompiler, tetapi sudah termasuk dalam PJSIP. Yang kedua adalah titik apung perangkat keras, kami membicarakannya di
artikel . Namun seperti yang ditunjukkan oleh praktik, FPU tidak memberikan peningkatan kecepatan yang signifikan. Langkah selanjutnya adalah memprioritaskan utas. Embox memiliki strategi penjadwalan yang berbeda, dan saya memasukkan satu yang mendukung prioritas dan mengatur stream audio ke prioritas tertinggi. Itu juga tidak membantu.
Yang berikutnya adalah gagasan bahwa kami bekerja dengan memori eksternal dan akan menyenangkan untuk memindahkan struktur di sana, yang sangat sering diakses. Saya membuat analisis awal tentang kapan dan di bawah apa yang dialokasikan alokasi
simple_pjsua memori. Ternyata dari 190 Kb, 90 Kb pertama dialokasikan untuk kebutuhan internal PJSIP dan tidak terlalu sering diakses. Kemudian, selama panggilan masuk, fungsi pjsua_call_answer dipanggil, di mana buffer untuk bekerja dengan frame masuk dan keluar kemudian dialokasikan. Itu sekitar 100 kb. Dan di sini kita bertindak sebagai berikut. Sebelum panggilan, data ditempatkan di memori eksternal. Begitu panggilan - segera ganti tumpukan dengan yang lain - dalam RAM. Dengan demikian, semua data "panas" ditransfer ke memori yang lebih cepat dan lebih dapat diprediksi.
Akibatnya, semua ini bersama-sama diizinkan untuk memulai
simple_pjsua dan melakukan panggilan melalui servernya. Dan kemudian melalui server lain seperti sip.linphone.org.
Kesimpulan
Akibatnya, ternyata menjalankan
simple_pjsua dengan transmisi suara di kedua arah melalui server. Masalah dengan tambahan menghabiskan 128 Kb SDRAM dapat diselesaikan dengan menggunakan Cortex-M7 sedikit lebih kuat (misalnya, STM32F769NI dengan RAM 512 Kb), tetapi pada saat yang sama kami masih tidak memiliki harapan untuk masuk ke dalam 256 Kb :) Kami akan senang jika seseorang tertarik , dan bahkan lebih baik - coba. Semua sumber, seperti biasa, ada di
repositori kami.