Điện thoại SIP trên STM32F7-Discovery

Xin chào tất cả mọi người.

Cách đây một thời gian chúng tôi писали về cách chúng tôi quản lý để khởi chạy điện thoại SIP trên STM32F4-Discovery với 1 MB ROM và 192 KB RAM) dựa trên Hộp thư. Ở đây phải nói rằng phiên bản đó là tối thiểu và được kết nối trực tiếp với hai điện thoại mà không cần máy chủ và chỉ truyền giọng nói theo một hướng. Do đó, chúng tôi quyết định ra mắt một chiếc điện thoại hoàn thiện hơn với cuộc gọi qua máy chủ, truyền giọng nói theo cả hai hướng nhưng đồng thời giữ trong kích thước bộ nhớ nhỏ nhất có thể.


Đối với điện thoại, nó đã được quyết định chọn một ứng dụng đơn giản_pjsua như một phần của thư viện PJSIP. Đây là một ứng dụng tối thiểu có thể đăng ký trên máy chủ, nhận và trả lời cuộc gọi. Dưới đây tôi sẽ ngay lập tức đưa ra mô tả về cách chạy nó trên STM32F7-Discovery.

Làm thế nào để chạy

  1. Định cấu hình hộp thư đến
    make confload-platform/pjsip/stm32f7cube
  2. Đặt tài khoản SIP được yêu cầu trong tệp conf/mods.config.
    
    include platform.pjsip.cmd.simple_pjsua_imported(
        sip_domain="server", 
        sip_user="username",
        sip_passwd="password")
    

    đâu máy chủ là máy chủ SIP (ví dụ: sip.linphone.org), tên truy nhập и mật khẩu - tên tài khoản và mật khẩu.

  3. Lắp ráp Embox thành một nhóm làm cho. Về phần sụn bảng chúng tôi có trên wikiBài viết.
  4. Chạy lệnh “simple_pjsua_imported” trong bảng điều khiển 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. Cuối cùng, vẫn còn cắm loa hoặc tai nghe vào đầu ra âm thanh và nói vào hai micrô MEMS nhỏ bên cạnh màn hình. Chúng tôi gọi từ Linux thông qua ứng dụng simple_pjsua, pjsua. Chà, hoặc bạn có thể sử dụng bất kỳ loại linphone nào khác.

Tất cả điều này được mô tả trên của chúng tôi wiki.

Làm thế nào mà chúng tôi đến đó

Vì vậy, ban đầu nảy sinh câu hỏi về việc chọn nền tảng phần cứng. Vì rõ ràng là STM32F4-Discovery sẽ không vừa với bộ nhớ nên STM32F7-Discovery đã được chọn. Cô ấy có ổ đĩa flash 1 MB và RAM 256 KB (+ 64 bộ nhớ nhanh đặc biệt mà chúng tôi cũng sẽ sử dụng). Cũng không có nhiều cuộc gọi qua máy chủ, nhưng chúng tôi quyết định cố gắng hòa nhập.

Có điều kiện cho bản thân, nhiệm vụ được chia thành nhiều giai đoạn:

  • Chạy PJSIP trên QEMU. Nó thuận tiện cho việc gỡ lỗi, cộng với việc chúng tôi đã hỗ trợ codec AC97 ở đó.
  • Ghi âm và phát lại giọng nói trên QEMU và trên STM32.
  • Chuyển một ứng dụng đơn giản_pjsua từ PJSIP. Nó cho phép bạn đăng ký trên máy chủ SIP và thực hiện cuộc gọi.
  • Triển khai máy chủ dựa trên Asterisk của riêng bạn và thử nghiệm trên đó, sau đó thử các máy chủ bên ngoài, chẳng hạn như sip.linphone.org

Âm thanh trong Embox hoạt động thông qua Portaudio, cũng được sử dụng trong PISIP. Các vấn đề đầu tiên xuất hiện trên QEMU - WAV phát tốt ở 44100 Hz, nhưng ở 8000 rõ ràng đã xảy ra sự cố. Hóa ra đó là vấn đề cài đặt tần số - theo mặc định, nó là 44100 trong thiết bị và điều này không thay đổi theo chương trình.

Ở đây, có lẽ, đáng để giải thích một chút về cách âm thanh được phát nói chung. Thẻ âm thanh có thể được đặt thành một số con trỏ tới một phần bộ nhớ mà bạn muốn phát hoặc ghi ở tần số định trước. Sau khi bộ đệm kết thúc, một ngắt được tạo ra và quá trình thực thi tiếp tục với bộ đệm tiếp theo. Thực tế là những bộ đệm này cần được lấp đầy trước trong khi bộ đệm trước đó đang được phát. Chúng tôi sẽ đối mặt với vấn đề này hơn nữa trên STM32F7.

Tiếp theo, chúng tôi thuê một máy chủ và triển khai Asterisk trên đó. Vì cần phải gỡ lỗi nhiều nhưng tôi không muốn nói nhiều vào micrô nên cần phải thực hiện phát lại và ghi âm tự động. Để thực hiện việc này, chúng tôi đã vá lỗi simple_pjsua để bạn có thể trượt tệp thay vì thiết bị âm thanh. Trong PJSIP, điều này được thực hiện khá đơn giản, vì chúng có khái niệm về cổng, cổng này có thể là thiết bị hoặc tệp. Và các cổng này có thể kết nối linh hoạt với các cổng khác. Bạn có thể xem mã trong pjsip của chúng tôi kho lưu trữ. Kết quả là, sơ đồ như sau. Trên máy chủ Asterisk, tôi đã tạo hai tài khoản - cho Linux và cho Embox. Tiếp theo, lệnh được thực thi trên Embox đơn giản_pjsua_imported, Embox đăng ký trên máy chủ, sau đó chúng tôi gọi Embox từ Linux. Tại thời điểm kết nối, chúng tôi kiểm tra trên máy chủ Asterisk xem kết nối đã được thiết lập chưa và sau một lúc, chúng tôi sẽ nghe thấy âm thanh từ Linux trong Embox và trong Linux, chúng tôi lưu tệp được phát từ Embox.

Sau khi nó hoạt động trên QEMU, chúng tôi chuyển sang chuyển sang STM32F7-Discovery. Vấn đề đầu tiên là chúng không vừa với 1 MB ROM mà không có trình tối ưu hóa trình biên dịch được kích hoạt “-Os” cho kích thước của hình ảnh. Đó là lý do tại sao chúng tôi bao gồm "-Os". Hơn nữa, bản vá đã vô hiệu hóa hỗ trợ cho C ++, vì vậy nó chỉ cần thiết cho pjsua và chúng tôi sử dụng simple_pjsua.

Sau khi được đặt đơn giản_pjsua, quyết định rằng bây giờ có cơ hội để khởi chạy nó. Nhưng trước tiên, cần phải xử lý việc ghi và phát lại giọng nói. Vấn đề là viết ở đâu? Chúng tôi đã chọn bộ nhớ ngoài - SDRAM (128 MB). Bạn có thể tự mình thử điều này:

Tạo WAV âm thanh nổi với tần số 16000 Hz và thời lượng 10 giây:


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

Chúng tôi thua:


play -m C0000000

Có hai vấn đề ở đây. Đầu tiên với codec - WM8994 được sử dụng và nó có một thứ như một khe cắm và có 4 trong số các khe cắm này. . Do đó, ở tần số 16000 Hz, chúng tôi nhận được 8000 Hz, nhưng đối với 8000 Hz, việc phát lại đơn giản là không hoạt động. Khi chỉ các vị trí 0 và 2 được chọn, nó sẽ hoạt động như bình thường. Một vấn đề khác là giao diện âm thanh trong STM32Cube, trong đó đầu ra âm thanh hoạt động đồng bộ qua SAI (Giao diện âm thanh nối tiếp) với đầu vào âm thanh (tôi không hiểu chi tiết, nhưng hóa ra chúng có chung một đồng hồ và khi đầu ra âm thanh được khởi tạo, âm thanh bằng cách nào đó được gắn vào đầu vào). Nghĩa là, bạn không thể chạy chúng một cách riêng biệt, vì vậy chúng tôi đã làm như sau - đầu vào âm thanh và đầu ra âm thanh luôn hoạt động (bao gồm cả các ngắt được tạo ra). Nhưng khi không có gì đang được phát trong hệ thống, thì chúng tôi chỉ cần trượt một bộ đệm trống vào đầu ra âm thanh và khi quá trình phát lại bắt đầu, chúng tôi sẽ bắt đầu lấp đầy nó một cách trung thực.

Hơn nữa, chúng tôi nhận thấy rằng âm thanh trong quá trình ghi âm giọng nói rất nhỏ. Điều này là do micrô MEMS trên STM32F7-Discovery bằng cách nào đó không hoạt động tốt ở tần số dưới 16000 Hz. Do đó, chúng tôi đặt 16000 Hz, ngay cả khi 8000 Hz xuất hiện. Tuy nhiên, để làm được điều này, cần phải thêm phần mềm chuyển đổi tần số này sang tần số khác.

Tiếp theo, tôi phải tăng kích thước của heap nằm trong RAM. Theo tính toán của chúng tôi, pjsip cần khoảng 190 KB và chúng tôi chỉ còn khoảng 100 KB. Ở đây tôi phải sử dụng một số bộ nhớ ngoài - SDRAM (khoảng 128 KB).

Sau tất cả những chỉnh sửa này, tôi đã thấy các gói đầu tiên giữa Linux và Embox và tôi đã nghe thấy âm thanh! Nhưng âm thanh rất tệ, không giống như trên QEMU, không thể phát hiện ra điều gì. Sau đó, chúng tôi nghĩ về những gì có thể là vấn đề. Gỡ lỗi cho thấy rằng Embox đơn giản là không có thời gian để lấp đầy/dỡ bỏ bộ đệm âm thanh. Trong khi pjsip đang xử lý một khung, 2 ngắt có thời gian xảy ra khi hoàn thành xử lý bộ đệm, điều này là quá nhiều. Suy nghĩ đầu tiên về tốc độ là tối ưu hóa trình biên dịch, nhưng nó đã được đưa vào PJSIP. Thứ hai là một điểm nổi phần cứng, chúng tôi đã nói về nó trong Bài viết. Nhưng như thực tế đã chỉ ra, FPU không tăng tốc độ đáng kể. Bước tiếp theo là ưu tiên các chủ đề. Embox có các chiến lược lập lịch trình khác nhau và tôi đã bao gồm một chiến lược hỗ trợ mức độ ưu tiên và đặt luồng âm thanh ở mức độ ưu tiên cao nhất. Điều này cũng không giúp được gì.

Ý tưởng tiếp theo là chúng ta đang làm việc với bộ nhớ ngoài và sẽ rất tuyệt nếu di chuyển các cấu trúc được truy cập cực kỳ thường xuyên vào đó. Tôi đã làm một phân tích sơ bộ về thời gian và dưới những gì đơn giản_pjsua cấp phát bộ nhớ. Hóa ra là trong số 190 Kb, 90 Kb đầu tiên được phân bổ cho các nhu cầu nội bộ của PJSIP và chúng không được truy cập thường xuyên. Hơn nữa, trong một cuộc gọi đến, hàm pjsua_call_answer được gọi, trong đó các bộ đệm sau đó được phân bổ để làm việc với các khung đến và đi. Nó vẫn còn khoảng 100 Kb. Và sau đó chúng tôi đã làm như sau. Cho đến thời điểm thực hiện cuộc gọi, chúng tôi đặt dữ liệu vào bộ nhớ ngoài. Ngay sau cuộc gọi, chúng tôi ngay lập tức thay thế đống này bằng một đống khác - trong RAM. Do đó, tất cả dữ liệu “nóng” đã được chuyển sang bộ nhớ nhanh hơn và dễ đoán hơn.

Kết quả là, tất cả điều này cùng nhau làm cho nó có thể khởi chạy đơn giản_pjsua và gọi qua máy chủ của bạn. Và sau đó thông qua các máy chủ khác, chẳng hạn như sip.linphone.org.

Những phát hiện

Kết quả là, nó đã có thể khởi chạy đơn giản_pjsua với việc truyền giọng nói theo cả hai hướng thông qua máy chủ. Vấn đề với việc sử dụng thêm 128 KB SDRAM có thể được giải quyết bằng cách sử dụng Cortex-M7 mạnh hơn một chút (ví dụ: STM32F769NI với 512 KB RAM), nhưng đồng thời, chúng tôi vẫn không từ bỏ hy vọng đạt được 256 KB 🙂 Chúng tôi sẽ rất vui nếu ai đó quan tâm, Hoặc tốt hơn nữa, hãy thử nó. Tất cả các nguồn, như thường lệ, là trong của chúng tôi kho lưu trữ.

Nguồn: www.habr.com

Thêm một lời nhận xét