ไมโครคอนโทรลเลอร์ Raspberry Pi RP2350 เพิ่มอินเทอร์เฟส HSTX (High-Speed Serial Transmit) ซึ่งเป็นอินเตอร์เฟสการส่งข้อมูลความเร็วสูง พร้อมกับการนำเสนอ PIO (Programmable IO) ของ Raspberry Pi RP2040 เมื่อสามปีก่อน ปัจจุบันไมโครคอนโทรลเลอร์ RP2350 ใหม่มี PIO จำนวนสามบล็อกและอินเทอร์เฟส HSTX หนึ่งบล็อกที่สามารถใช้งานได้ผ่าน 8x GPIOs ดังนั้นเรามาทำความเข้าใจว่า HSTX คืออะไร ใช้ทำอะไร และมันแตกต่างจาก PIOs อย่างไร รวมถึงดูตัวอย่างการเขียนโปรแกรมใน C และ MicroPython กัน
อินเทอร์เฟส High-Speed Serial Transmit (HSTX) มีรายละเอียดอยู่ในข้อมูล datasheet ของ RP2350 เริ่มตั้งแต่หน้า 1118 ซึ่งระบุว่า “อินเทอร์เฟส High-Speed Serial Transmit (HSTX) จะทำการสตรีมข้อมูลจากโดเมนสัญญาณนาฬิกาของระบบไปยัง GPIO ได้สูงสุด 8 ขาในอัตราที่ไม่ขึ้นกับความเร็วของสัญญาณนาฬิกาของระบบ” เมื่ออ่านต่อไป เราจะเห็นว่ามันทำงานที่ความถี่ 150 MHz ซึ่งทำให้สามารถส่งข้อมูลได้ที่อัตรา 300 Mbps ต่อขา GPIO โดยใช้การทำงานในโหมด DDR หรือรวมเป็น 2,400 Mbps ผ่าน 8 ขา GPIO
มีคือคำอธิบายเพิ่มจากข้อมูล Datasheet
The HSTX is asynchronous from the rest of the system. A 32-bit-wide FIFO provides high-bandwidth access from the system DMA. The command expander performs simple manipulation of the datastream, and the output shift register portions the 32-bit data out over successive HSTX clock cycles, swizzled by the bit crossbar. The outputs are double-data-rate: up to two bits per pin per clock cycle.
HSTX drives data through GPIOs using DDR output registers to transfer up to two bits per clock cycle per pin. The HSTX balances all delays to GPIO outputs within 300 picoseconds, minimizing common-mode components when using neighboring GPIOs as a pseudo-differential driver. This also helps maintain destination setup and hold time when a clock is driven alongside the output data.
The maximum frequency for the HSTX clock is 150MHz, the same as the system clock. With DDR output operation, this is a maximum data rate of 300Mb/s per pin. There are no limits on the frequency ratio of the system and HSTX clocks, however, each clock must be individually fast enough to maintain your required throughput. Very low system clock frequencies coupled with very high HSTX frequencies may encounter system DMA bandwidth limitations since the DMA is capped at one HSTX FIFO write per system clock cycle.
บน Raspberry Pi RP2350, GPIOs 12 ถึง 19 สามารถใช้สำหรับฟังก์ชัน High-Speed Serial Transmit (HSTX) ได้ แต่ต้องทราบว่า HSTX เป็นฟังก์ชันที่ใช้สำหรับการส่งออกข้อมูลเท่านั้น (output-only) ดังนั้นจึงไม่ยืดหยุ่นเท่ากับ PIOs ที่อนุญาตให้ผู้ใช้สร้างอินเทอร์เฟส high-speed (หรือไม่) ได้หลากหลาย เราได้ทำการแก้ไขไดอะแกรมพินเอาต์ของ Raspberry Pi Pico 2 เพื่อเน้น GPIOs ที่รองรับ HSTX
HSTX ใช้กับอะไรได้บ้าง?
HSTX สสามารถใช้สำหรับการส่งข้อมูลความเร็วสูง แต่สามารถทำได้เพียงการส่งข้อมูลเท่านั้น ไม่สามารถรับข้อมูลได้ ดังนั้นมันจึงเหมาะอย่างยิ่งสำหรับการใช้งานที่ต้องการการส่งข้อมูลอย่างรวดเร็ว เช่น การเชื่อมต่อวิดีโอหรือการแสดงผล อย่างไรก็ตาม HSTX จะไม่เหมาะสำหรับการส่งข้อมูลในทิศทางสองทาง (bidirectional transfers) เช่น การจำลองการเชื่อมต่อ Ethernet เพราะมันไม่สามารถรับข้อมูลได้
PIO ของ Raspberry Pi RP2040 ถูกใช้ในการสร้างการเชื่อมต่อวิดีโอ DVI, VGA, และ composite video, แต่ในบอร์ดที่ใช้ไมโครคอนโทรลเลอร์ RP2350, I/O blocks ที่สามารถโปรแกรมได้อาจถูกปล่อยให้ว่างและใช้ฟังก์ชัน HSTX แทน ถ้าคุณต้องการทดลองใช้งานฟังก์ชัน HSTX บน Raspberry Pi Pico 2 คุณจะต้องทำการบัดกรีพินเพิ่ม แต่วิธีที่สะดวกกว่าคือการใช้บอร์ดที่ออกแบบมาเพื่อการนี้โดยเฉพาะ เช่น RP2xxx Stamp Carrier XL กับโมดูล R2350 Stamp เนื่องจากบอร์ดนี้จะเปิดเผยอินเทอร์เฟส HSTX ผ่านพอร์ต micro HDMI ทำให้การเริ่มต้นใช้งานสะดวกและง่ายขึ้น
ภาพด้านบนที่แสดงให้เห็นบอร์ด Stamp Carrier XL RP2xxx ที่เชื่อมต่อกับคีย์บอร์ดและจอแสดงผลที่แสดงอินเทอร์เฟส CircuitPython REPL และ Artur Pacholec จากการโพสต์บน X ยืนยันว่ากำลังใช้งาน HSTX สามารถค้นหา CircuitPython รองรับ HSTX ได้ที่ https://github.com/adafruit/circuitpython/blob/main/ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c ]
คาดว่าจะมีบอร์ดอื่นๆ จาก Adafruit, Pimoroni, และผู้ผลิตรายอื่นๆ กำลังจะมาถึงในเร็วๆ นี้ ซึ่งมีการรองรับเอาท์พุตวิดีโอและ/หรือจอแสดงผลที่รองรับ HSTX
ตัวอย่างโค้ด HSTX สำหรับ RP2350 ใน C
Raspberry Pi มีตัวอย่างโค้ด HSTX ใน Raspberry Pi Pico C/C++ SDK ดังนี้ :
- dvi_out_hstx_encoder – ตัวอย่างนี้ใช้ HSTX เพื่อสร้างเอาต์พุต DVI โดยใช้ command expander และ TMDS encoder ใน HSTX ความละเอียดของ frame buffer ตั้งค่าไว้ที่ 640×480 ตัวอย่างนี้ต้องการการเชื่อมต่อวิดีโอดิจิทัลภายนอกที่เชื่อมต่อกับ GPIOs 12 ถึง 19 พร้อมด้วยตัวต้านทานจำกัดกระแสที่เหมาะสม เช่น 270 โอห์ม ตัวอย่างนี้สามารถใช้กับ บอร์ด Pico DVI Sock ซึ่งสามารถบัดกรีลงบน Raspberry Pi Pico 2 ได้
- spi_lcd – ตัวอย่างนี้ใช้ HSTX ขับเคลื่อน LCD ST7789 SPI โดยอัตราการส่งสัญญาณ SPI จะไม่ขึ้นกับ (และสามารถเร็วกว่า) สัญญาณนาฬิกาของระบบ โดยมีการทดสอบที่ความละเอียด 240×240 ใช้กับโมดูล WaveShare ST7789 ขนาด 1.3 นิ้ว
เนื่องจากตัวอย่างทั้งสองยาวเกินกว่าที่จะใส่ไว้ในบทความนี้ ดังนั้นเราจะแสดงโค้ดที่เกี่ยวข้องกับ HSTX จากตัวอย่าง SPI LCD:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#include "hardware/structs/hstx_ctrl.h" #include "hardware/structs/hstx_fifo.h" // These can be any permutation of HSTX-capable pins: #define PIN_DIN 12 #define PIN_SCK 13 #define PIN_CS 14 #define PIN_DC 15 // These can be any pin: #define PIN_RESET 16 #define PIN_BL 17 #define FIRST_HSTX_PIN 12 #if PIN_DIN < FIRST_HSTX_PIN || PIN_DIN >= FIRST_HSTX_PIN + 8 #error "Must be an HSTX-capable pin: DIN" #elif PIN_SCK < FIRST_HSTX_PIN || PIN_SCK >= FIRST_HSTX_PIN + 8 #error "Must be an HSTX-capable pin: SCK" #elif PIN_CS < FIRST_HSTX_PIN || PIN_CS >= FIRST_HSTX_PIN + 8 #error "Must be an HSTX-capable pin: CS" #elif PIN_DC < FIRST_HSTX_PIN || PIN_DC >= FIRST_HSTX_PIN + 8 #error "Must be an HSTX-capable pin: DC" #endif static inline void hstx_put_word(uint32_t data) { while (hstx_fifo_hw->stat & HSTX_FIFO_STAT_FULL_BITS) ; hstx_fifo_hw->fifo = data; } static inline void lcd_put_dc_cs_data(bool dc, bool csn, uint8_t data) { hstx_put_word( (uint32_t)data | (csn ? 0x0ff00000u : 0x00000000u) | // Note DC gets inverted inside of HSTX: (dc ? 0x00000000u : 0x0003fc00u) ); } |
ต้องใช้ไฟล์ include สองไฟล์ พิน 12 ถึง 17 ถูจะถูกกำหนดให้กับสัญญาณเฉพาะสำหรับหน้าจอ นอกจากนี้ยังมีบางแมโครเพื่อตรวจสอบว่าพิน SPI ที่เลือกนั้นสามารถใช้งาน HSTX ได้จริง ฟังก์ชันแรกในบรรทัด (inline function) จะทำการโหลดข้อมูล 32 บิตไปยัง FIFO buffer เมื่อมีพื้นที่ว่างหรือเมื่อ buffer ว่าง และฟังก์ชันที่สองจะทำการส่งข้อมูลไปยัง SPI LCD
ในฟังก์ชันหลัก (main function) ยังมีโค้ดที่เกี่ยวข้องกับ HSTX ดังนี้:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
int main() { stdio_init_all(); // Switch HSTX to USB PLL (presumably 48 MHz) because clk_sys is probably // running a bit too fast for this example -- 48 MHz means 48 Mbps on // PIN_DIN. Need to reset around clock mux change, as the AUX mux can // introduce short clock pulses: reset_block(RESETS_RESET_HSTX_BITS); hw_write_masked( &clocks_hw->clk[clk_hstx].ctrl, CLOCKS_CLK_HSTX_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB << CLOCKS_CLK_HSTX_CTRL_AUXSRC_LSB, CLOCKS_CLK_HSTX_CTRL_AUXSRC_BITS ); unreset_block_wait(RESETS_RESET_HSTX_BITS); gpio_init(PIN_RESET); gpio_init(PIN_BL); gpio_set_dir(PIN_RESET, GPIO_OUT); gpio_set_dir(PIN_BL, GPIO_OUT); gpio_put(PIN_RESET, 1); gpio_put(PIN_BL, 1); hstx_ctrl_hw->bit[PIN_SCK - FIRST_HSTX_PIN] = HSTX_CTRL_BIT0_CLK_BITS; hstx_ctrl_hw->bit[PIN_DIN - FIRST_HSTX_PIN] = (7u << HSTX_CTRL_BIT0_SEL_P_LSB) | (7u << HSTX_CTRL_BIT0_SEL_N_LSB); hstx_ctrl_hw->bit[PIN_CS - FIRST_HSTX_PIN] = (27u << HSTX_CTRL_BIT0_SEL_P_LSB) | (27u << HSTX_CTRL_BIT0_SEL_N_LSB); hstx_ctrl_hw->bit[PIN_DC - FIRST_HSTX_PIN] = (17u << HSTX_CTRL_BIT0_SEL_P_LSB) | (17u << HSTX_CTRL_BIT0_SEL_N_LSB) | (HSTX_CTRL_BIT0_INV_BITS); // We have packed 8-bit fields, so shift left 1 bit/cycle, 8 times. hstx_ctrl_hw->csr = HSTX_CTRL_CSR_EN_BITS | (31u << HSTX_CTRL_CSR_SHIFT_LSB) | (8u << HSTX_CTRL_CSR_N_SHIFTS_LSB) | (1u << HSTX_CTRL_CSR_CLKDIV_LSB); gpio_set_function(PIN_SCK, 0/*GPIO_FUNC_HSTX*/); gpio_set_function(PIN_DIN, 0/*GPIO_FUNC_HSTX*/); gpio_set_function(PIN_CS, 0/*GPIO_FUNC_HSTX*/); gpio_set_function(PIN_DC, 0/*GPIO_FUNC_HSTX*/); |
การใช้ HSTX ที่ความเร็ว 150 MHz อาจเร็วเกินไปสำหรับ LCD ดังนั้นจึงใช้สัญญาณนาฬิกา USB ความเร็ว 48 MHz แทน สำหรับการอ้างอิง การสาธิตเอาต์พุต DVI จะใช้สัญญาณนาฬิกาเริ่มต้นที่ 125 MHz ซึ่งเพียงพอสำหรับความละเอียด 640×480 ที่ 60 เฟรมต่อวินาที (FPS)
บางส่วนของโค้ดทำการเปลี่ยนแปลงการตั้งค่าลงทะเบียนการกำหนดค่า Bit crossbar ซึ่งควบคุมว่าบิตไหนของ output shift register จะปรากฏบน GPIO ใดในช่วงครึ่งแรกและครึ่งหลังของแต่ละรอบนาฬิกา HSTX โดยมีพารามิเตอร์ดังนี้:
- BITx.SEL_P เลือกบิตของ shift register (0 ถึง 31) ที่จะออกในช่วงครึ่งแรกของแต่ละรอบนาฬิกา HSTX
- BITx.SEL_N ลือกบิตของ shift register (0 ถึง 31) ที่จะออกในช่วงครึ่งหลังของแต่ละรอบนาฬิกา HSTX
- BITx.INV ทำการกลับขั้วสัญญาณ (logical NOT)
- BITx.CLK ระบุว่าพินนี้ควรเชื่อมต่อกับตัวสร้างสัญญาณนาฬิกาแทนที่จะเป็น output shift register
ในโค้ดที่กล่าวถึงจะทำการปิดการทำงานแบบ DDR โดยการตั้งค่า SEL_N ให้เท่ากับ SEL_P สำหรับพินสามพิน และเชื่อมต่อสัญญาณ CLK กับตัวสร้างสัญญาณนาฬิกา พิน DC ยังมีการกลับขั้วสัญญาณด้วย
SDK ของ MicroPython ได้รับการอัปเดตสำหรับ RP2350 แต่เอกสารล่าสุดยังไม่มีการรองรับ HSTX, แต่ CircuitPython (Alpha) image สำหรับ Raspberry Pi Pico 2 และบอร์ด RP2350 อื่นๆ สามารถจัดการ HSTX เพื่อสร้างสัญญาณเอาต์พุตความถี่สูง เช่น เอาต์พุตจอแสดงผล DVI ได้แล้ว, โปรดทราบว่า HSTX ถูกนำไปใช้ใน CircuitPython 9.2.0 ซึ่งยังอยู่ในเวอร์ชัน Alpha
แปลจากบทความภาษาอังกฤษ : A closer look at Raspberry Pi RP2350’s HSTX high-speed serial transmit interface
บรรณาธิการข่าวและบทความภาษาไทย CNX Software ได้มีความสนใจในด้านเทคโนโลยี โดยเฉพาะ Smart Home และ IoT