โทรศัพท์ SIP บน STM32F7-Discovery

สวัสดีทุกคน

เมื่อสักครู่นี้เรา เขียน เกี่ยวกับวิธีที่เราจัดการเพื่อเปิดตัวโทรศัพท์ SIP บน STM32F4-Discovery ที่มี 1 MB ROM และ 192 KB RAM) ตาม เอ็มบ็อกซ์. ต้องบอกว่าเวอร์ชันนั้นมีน้อยและเชื่อมต่อโทรศัพท์สองเครื่องโดยตรงโดยไม่มีเซิร์ฟเวอร์และมีการส่งสัญญาณเสียงในทิศทางเดียว ดังนั้นเราจึงตัดสินใจที่จะเปิดตัวโทรศัพท์ที่สมบูรณ์ยิ่งขึ้นด้วยการโทรผ่านเซิร์ฟเวอร์ การส่งเสียงในทั้งสองทิศทาง แต่ในขณะเดียวกันก็รักษาขนาดหน่วยความจำให้เล็กที่สุดเท่าที่จะเป็นไปได้


สำหรับโทรศัพท์ก็ตัดสินใจเลือกแอปพลิเคชัน simple_pjsua เป็นส่วนหนึ่งของห้องสมุด PJSIP นี่เป็นแอปพลิเคชั่นขั้นต่ำที่สามารถลงทะเบียนบนเซิร์ฟเวอร์ รับและรับสาย ด้านล่างฉันจะให้คำอธิบายเกี่ยวกับวิธีเรียกใช้บน STM32F7-Discovery ทันที

วิธีการวิ่ง

  1. การกำหนดค่าเอ็มบ็อกซ์
    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 ขนาดเล็กสองตัวที่อยู่ถัดจากจอแสดงผล เราเรียกใช้จาก Linux ผ่านแอปพลิเคชัน simple_pjsua, pjsua หรือคุณจะใช้ linphone ประเภทอื่นก็ได้

ทั้งหมดนี้อธิบายไว้ในของเรา วิกิพีเดีย.

เราไปถึงที่นั่นได้อย่างไร

ในตอนแรกคำถามจึงเกิดขึ้นเกี่ยวกับการเลือกแพลตฟอร์มฮาร์ดแวร์ เนื่องจากเห็นได้ชัดว่า STM32F4-Discovery ไม่เหมาะกับหน่วยความจำ STM32F7-Discovery จึงถูกเลือก เธอมีแฟลชไดรฟ์ 1 MB และ RAM 256 KB (+ 64 หน่วยความจำเร็วพิเศษซึ่งเราจะใช้ด้วย) มีไม่มากสำหรับการโทรผ่านเซิร์ฟเวอร์ แต่เราตัดสินใจที่จะพยายามให้พอดี

เงื่อนไขสำหรับตัวเอง งานแบ่งออกเป็นหลายขั้นตอน:

  • ใช้ PJSIP บน QEMU มันสะดวกสำหรับการดีบั๊ก บวกกับเรารองรับตัวแปลงสัญญาณ AC97 ที่นั่นแล้ว
  • บันทึกเสียงและเล่นบน QEMU และบน STM32
  • พอร์ตแอปพลิเคชัน simple_pjsua จาก PJSIP อนุญาตให้คุณลงทะเบียนบนเซิร์ฟเวอร์ SIP และโทรออก
  • ปรับใช้เซิร์ฟเวอร์ที่ใช้เครื่องหมายดอกจันของคุณเองและทดสอบ จากนั้นลองใช้เซิร์ฟเวอร์ภายนอก เช่น sip.linphone.org

เสียงใน Embox ทำงานผ่าน Portaudio ซึ่งใช้ใน PISIP เช่นกัน ปัญหาแรกปรากฏขึ้นบน QEMU - WAV เล่นได้ดีที่ 44100 Hz แต่ที่ 8000 มีข้อผิดพลาดอย่างชัดเจน ปรากฎว่าเป็นเรื่องของการตั้งค่าความถี่ - โดยค่าเริ่มต้นอุปกรณ์คือ 44100 และสิ่งนี้ไม่ได้เปลี่ยนแปลงโดยทางโปรแกรม

บางทีนี่อาจเป็นเรื่องที่ควรค่าแก่การอธิบายถึงวิธีการเล่นเสียงโดยทั่วไป การ์ดเสียงสามารถตั้งค่าให้ตัวชี้ไปยังชิ้นส่วนของหน่วยความจำที่คุณต้องการเล่นหรือบันทึกด้วยความถี่ที่กำหนดไว้ล่วงหน้า หลังจากบัฟเฟอร์สิ้นสุด การขัดจังหวะจะถูกสร้างขึ้นและการดำเนินการจะดำเนินต่อไปในบัฟเฟอร์ถัดไป ความจริงก็คือต้องเติมบัฟเฟอร์เหล่านี้ล่วงหน้าในขณะที่กำลังเล่นบัฟเฟอร์ก่อนหน้า เราจะประสบปัญหานี้ต่อไปใน STM32F7

ต่อไป เราเช่าเซิร์ฟเวอร์และใช้งาน Asterisk บนเซิร์ฟเวอร์ เนื่องจากจำเป็นต้องดีบักมาก แต่ฉันไม่ต้องการพูดใส่ไมโครโฟนมากนัก จึงจำเป็นต้องเล่นและบันทึกอัตโนมัติ ในการทำเช่นนี้ เราได้แพตช์ simple_pjsua เพื่อให้คุณสามารถส่งไฟล์แทนอุปกรณ์เสียง ใน PJSIP สิ่งนี้ทำได้ค่อนข้างง่าย เนื่องจากมีแนวคิดของพอร์ต ซึ่งสามารถเป็นได้ทั้งอุปกรณ์หรือไฟล์ และพอร์ตเหล่านี้สามารถเชื่อมต่อกับพอร์ตอื่นได้อย่างยืดหยุ่น คุณสามารถดูรหัสได้ใน pjsip ของเรา ที่เก็บ. เป็นผลให้โครงการเป็นดังนี้ บนเซิร์ฟเวอร์ Asterisk ฉันเริ่มต้นสองบัญชี - สำหรับ Linux และสำหรับ Embox ถัดไป คำสั่งจะดำเนินการบน Embox simple_pjsua_imported, Embox ลงทะเบียนบนเซิร์ฟเวอร์ หลังจากนั้นเราเรียก Embox จาก Linux ในขณะที่ทำการเชื่อมต่อ เราตรวจสอบเซิร์ฟเวอร์ Asterisk ว่าสร้างการเชื่อมต่อแล้ว และหลังจากนั้นไม่นาน เราจะได้ยินเสียงจาก Linux ใน Embox และใน Linux เราจะบันทึกไฟล์ที่เล่นจาก Embox

หลังจากทำงานกับ QEMU แล้ว เราก็ย้ายไปที่ STM32F7-Discovery ปัญหาแรกคือมันไม่พอดีกับ 1 MB ของ ROM หากไม่ได้เปิดใช้งานการเพิ่มประสิทธิภาพคอมไพเลอร์ "-Os" สำหรับขนาดของรูปภาพ นั่นเป็นเหตุผลที่เรารวม "-Os" นอกจากนี้ แพทช์ปิดใช้งานการสนับสนุนสำหรับ C ++ ดังนั้นจึงจำเป็นสำหรับ pjsua เท่านั้น และเราใช้ simple_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 มีกลยุทธ์การจัดกำหนดการที่แตกต่างกัน และฉันได้รวมกลยุทธ์ที่รองรับลำดับความสำคัญและตั้งค่าการสตรีมเสียงเป็นลำดับความสำคัญสูงสุด สิ่งนี้ไม่ได้ช่วยเช่นกัน

แนวคิดต่อมาคือเรากำลังทำงานกับหน่วยความจำภายนอก และน่าจะดีหากย้ายโครงสร้างที่มีการเข้าถึงบ่อยมากไปที่นั่น ฉันได้วิเคราะห์เบื้องต้นว่าเมื่อใดและภายใต้อะไร simple_pjsua จัดสรรหน่วยความจำ ปรากฎว่าจาก 190 Kb 90 Kb แรกได้รับการจัดสรรสำหรับความต้องการภายในของ PJSIP และไม่ได้เข้าถึงบ่อยนัก นอกจากนี้ ระหว่างการโทรเข้า ฟังก์ชัน pjsua_call_answer จะถูกเรียกใช้ ซึ่งบัฟเฟอร์จะถูกจัดสรรสำหรับการทำงานกับเฟรมขาเข้าและขาออก มันยังคงประมาณ 100 Kb จากนั้นเราก็ทำสิ่งต่อไปนี้ เราวางข้อมูลไว้ในหน่วยความจำภายนอกจนกว่าจะถึงเวลาโทร ทันทีที่มีการโทรเราจะแทนที่ฮีปด้วย RAM อื่นทันที ดังนั้น ข้อมูล "ร้อน" ทั้งหมดจึงถูกถ่ายโอนไปยังหน่วยความจำที่เร็วขึ้นและคาดเดาได้มากขึ้น

เป็นผลให้ทั้งหมดนี้รวมกันทำให้สามารถเปิดตัวได้ simple_pjsua และโทรผ่านเซิร์ฟเวอร์ของคุณ แล้วผ่านเซิร์ฟเวอร์อื่นๆ เช่น sip.linphone.org

ผลการวิจัย

เป็นผลให้สามารถเปิดตัวได้ simple_pjsua ด้วยการส่งเสียงทั้งสองทิศทางผ่านเซิร์ฟเวอร์ ปัญหาเกี่ยวกับการใช้ SDRAM เพิ่มเติม 128 KB สามารถแก้ไขได้โดยใช้ Cortex-M7 ที่ทรงพลังกว่าเล็กน้อย (เช่น STM32F769NI พร้อม RAM 512 KB) แต่ในขณะเดียวกันเราก็ยังไม่เลิกหวังที่จะเข้าสู่ 256 KB 🙂 เรายินดีหากมีคนสนใจ หรือดีกว่านั้น ลองเลย แหล่งที่มาทั้งหมดอยู่ในของเราตามปกติ ที่เก็บ.

ที่มา: will.com

เพิ่มความคิดเห็น