ความนิยมของบอร์ด Raspberry Pico ที่ขับเคลื่อนด้วย ไมโครคอนโทรลเลอร์ RP2040 ทำให้ผู้อ่านทุกคนต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับบอร์ดและชิป ดังนั้นวันนี้เราจะมาพูดถึง วงจรภายใน Programmable I/O ของ RP2040 ซึ่งเป็นคุณสมบัติที่ทำให้แตกต่างจากบอร์ดไมโครคอนโทรลเลอร์อื่น ๆ ส่วนใหญ่
PIO จำนวน 2 บล็อก (PIO0 & PIO1) หรือจะเรียกว่าอินเทอร์เฟซฮาร์ดแวร์ใน RP2040 มีวงจร Programmable State Machines อย่างละ 4 ชุด บล็อกPIO ทั้งสองนี้สามารถรันโปรแกรมพร้อมกันเพื่อจัดการ GPIO และถ่ายโอนข้อมูลดิบ ตอนนี้ State machine เหล่านี้ทำอะไร? PIO State machine ดำเนินการโปรแกรมที่ดึงมาจากแหล่งต่างๆ บางครั้งโปรแกรมจะถูกนำมาจากไลบรารี PIO (UART, SPI หรือ I2C) หรือซอฟต์แวร์สำหรับผู้ใช้
ทำไม Programmable I/O?
บอร์ดทั้งหมดมักจะมาพร้อมกับการสนับสนุนฮาร์ดแวร์สำหรับโปรโตคอลการสื่อสารดิจิทัลเช่น I2C, SPI และ UART อย่างไรก็ตามหากคุณวางแผนที่จะใช้อินเทอร์เฟซเหล่านี้มากกว่าที่มีอยู่บนบอร์ด คุณสามารถใช้ Programmable I/O ได้ที่มีให้ในไมโครคอนโทรลเลอร์ RP2040
มีสิ่งที่ดีกว่าที่คิด สมมติว่าคุณต้องการเอาต์พุตวิดีโอ DPI หรือ “สื่อสารกับอุปกรณ์อนุกรมที่พบใน AliExpress” ก็สามารถทำได้ด้วย Programmable I/O ได้ ตามชื่อที่ระบุไว้ Programmable I/O ทำให้ชัดเจนว่าสามารถตั้งโปรแกรมได้โดยตรงเพื่อรองรับอินเทอร์เฟซต่างๆรวมถึงอินเทอร์เฟซการ์ด SD, เอาต์พุต VGA และการถ่ายโอนข้อมูลความเร็วสูง รอก่อน! เรามีส่วนที่น่าตื่นเต้นที่สุดของบทความที่กำลังจะมาถึงนั่นคือ Programmable I/O เพื่อให้งานของคุณง่ายขึ้น
เราจะเริ่มต้นกับการเขียนโปรแกรม Programmable I/O ของ RP2040 ได้อย่างไร
Pico SDK (Software Development Kit) ให้ส่วนหัวไลบรารีและระบบสร้างที่จำเป็นในการเขียนโปรแกรมสำหรับอุปกรณ์ที่ใช้ RP2040 เช่น Raspberry Pi Pico ในภาษา C, C++ หรือ Arm assembly
หากคุณวางแผนที่จะใช้ Python ในการเขียนโค้ดคุณต้องใช้ตัวแก้ไขที่เหมาะสมเท่านั้น (สมมติว่า Thonny) และ MicroPython ที่ติดตั้งบนบอร์ดพัฒนา แต่ในกรณีของ ภาษา C/C++ คุณต้องใช้ไฟล์ CMake ที่บอก Pico SDK ว่าจะเปลี่ยนไฟล์ C ให้เป็นแอปพลิเคชั่นไบนารีสำหรับบอร์ดไมโครคอนโทรลเลอร์ที่ใช้ RP2040 ตามที่อธิบายไว้ในบทเรียนแนะนำ MicroPython และ ภาษา C สำหรับ Raspberry Pi Pico ล่าสุด
PIO Assembler จะแยกวิเคราะห์ไฟล์ต้นฉบับ PIO และเอาต์พุตเวอร์ชันที่ประกอบพร้อมสำหรับการรวมในแอปพลิเคชัน RP2040 ซึ่งรวมถึงแอปพลิเคชัน C และ C++ ที่สร้างขึ้นจาก Pico SDK และโปรแกรม Python ที่ทำงานบนพอร์ต RP2040 MicroPython
ในการเริ่มต้นด้วยการเขียนโปรแกรม State machine สำหรับแอปพลิเคชัน PIO ของคุณมีส่วนประกอบ 3 อย่าง สำหรับโปรแกรมที่ใช้ภาษา C/C++
-
- A PIO โปรแกรม
- C-language ซอฟต์แวร์ที่ใช้ภาษา C รันเพื่อแสดง
- A CMake ไฟล์ที่อธิบายถึงวิธีการรวมทั้งสองนี้เป็นอิมเมจโปรแกรมเพื่อโหลดลงในบอร์ดพัฒนาที่ใช้ RP2040
คำสั่งในการเขียนโปรแกรมสำหรับ PIO
ตอนนี้เมื่อพูดถึงการเขียนโปรแกรมอินเทอร์เฟซ I/O จะใช้ภาษาAssembly มีเและพียง 9 คำสั่ง “JMP, WAIT, IN, OUT, PUSH, PULL, MOV, IRQ และ SET” แม้ว่าคนส่วนใหญ่อาจสนใจในการเขียนโปรแกรมอินเทอร์เฟซ PIO ด้วยภาษา C / C++ หรือ Python แต่ให้เราดูคำสั่งภาษาAssembly บางส่วนที่ใช้สำหรับอินเทอร์เฟซ I/O
-
- JMP: คำสั่ง “jump” นี้อาจเป็นคำสั่งที่มีเงื่อนไขหรือไม่ใช่เงื่อนไขก็ได้ ในการนี้จะถ่ายโอนขั้นตอนการดำเนินการโดยการเปลี่ยนการลงทะเบียนตัวชี้คำสั่ง กล่าวง่ายๆคือด้วยคำสั่ง “jmp” ขั้นตอนการดำเนินการจะไปยังส่วนอื่นของโค้ด
- WAIT: คำสั่งนี้จะหยุดการทำงานของโค้ด แต่ละคำสั่งใช้เวลาหนึ่งรอบเว้นแต่จะหยุดทำงาน (โดยใช้คำสั่ง WAIT)
- OUT: คำสั่งนี้จะเปลี่ยนข้อมูลจากการลงทะเบียนกับเอาต์พุตไปยังปลายทางอื่น ๆ ครั้งละ 1 … 32 บิต
- PULL: คำสั่งนี้จะแสดงคำ 32 บิตจาก TX FIFO ลงในรีจิสเตอร์กะเอาต์พุต
- IN: คำสั่งนี้จะเปลี่ยน 1 …ครั้งละ 32 บิตในรีจิสเตอร์
- PUSH: คำสั่งนี้เพื่อเขียนเนื้อหา ISR ไปยัง RX FIFO
ข้อมูลเพิ่มเติมเกี่ยวกับคำสั่งภาษาแอสเซมบลีมีอยู่ใน แผ่นข้อมูลRP2040
ตัวอย่างการใช้ภาษา C/C++ และ MicroPython ในการเขียนโปรแกรม Programmable I/O ของ RP2040
ทำให้ง่ายขึ้นเราจะตรวจสอบโปรแกรมของ hello_world ที่กะพริบ LED ออนบอร์ดโดย Programmable I/O และนำข้อมูลข้อมูล ขนาด 32 บิตไปใส่หรืออ่านข้อมูลจาก FIFO (คำสั่ง PULL)
โปรแกรมใน C/C ++ มีลักษณะดังนี้:
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 |
#include "pico/stdlib.h" #include "hardware/pio.h" // Our assembled program: #include "hello.pio.h" int main() { // Choose which PIO instance to use (there are two instances) PIO pio = pio0; // Our assembled program needs to be loaded into this PIO's instruction // memory. This SDK function will find a location (offset) in the // instruction memory where there is enough space for our program. We need // to remember this location! uint offset = pio_add_program(pio, &hello_program); // Find a free state machine on our chosen PIO (erroring if there are // none). Configure it to run our program, and start it, using the // helper function we included in our .pio file. uint sm = pio_claim_unused_sm(pio, true); hello_program_init(pio, sm, offset, PICO_DEFAULT_LED_PIN); // The state machine is now running. Any value we push to its TX FIFO will // appear on the LED pin. while (true) { // Blink pio_sm_put_blocking(pio, sm, 1); sleep_ms(500); // Blonk pio_sm_put_blocking(pio, sm, 0); sleep_ms(500); } } |
รหัส C/C++ ด้านบนจะกะพริบ LED หนึ่งรอบครบ 1 วินาที LED ถูกตั้งโปรแกรมในลักษณะที่จะเปิดเป็นเวลา 500 มิลลิวินาทีตามด้วยปิดเป็นเวลา 500 มิลลิวินาที แต่ก่อนstate machine จะรันโปรแกรมได้เราจำเป็นต้องโหลดโปรแกรมลงในหน่วยความจำคำสั่งนี้ “ ฟังก์ชัน pio_add_program () ค้นหาพื้นที่ว่างสำหรับโปรแกรมของเราในหน่วยความจำคำสั่งของ PIO ที่กำหนดและโหลดขึ้นมา” ด้วยเหตุนี้เราจึงกำหนดค่าstate machine ให้ส่งออกข้อมูลไปยัง LED ออนบอร์ด
รหัสแอสเซมบลีสำหรับไฟล์. pio ที่แสดงด้านล่างมีฟังก์ชันตัวช่วย C ทั้งหมดเพื่อตั้งรหัส C/C++
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 |
.program hello loop: pull out pins, 1 jmp loop % c-sdk { static inline void hello_program_init(PIO pio, uint sm, uint offset, uint pin) { pio_sm_config c = hello_program_get_default_config(offset); // Map the state machine's OUT pin group to one pin, namely the `pin` // parameter to this function. sm_config_set_out_pins(&c, pin, 1); // Set this pin's GPIO function (connect PIO to the pad) pio_gpio_init(pio, pin); // Set the pin direction to output at the PIO pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); // Load our configuration, and jump to the start of the program pio_sm_init(pio, sm, offset, &c); // Set the state machine running pio_sm_set_enabled(pio, sm, true); } %} |
นอกเหนือจากนี้คุณยังต้องการไฟล์ CMake ที่อธิบายถึงวิธีการสร้างไฟล์ .pio และ .c ในไบนารีที่เหมาะสำหรับการโหลดลงในบอร์ดพัฒนา Raspberry Pi Pico ของคุณ
ไม่มีตัวอย่างเทียบเท่าที่เขียนด้วย MicroPython แต่เราสามารถเห็นรหัส PIO MicroPython ที่ง่ายกว่าที่ใช้ในการกะพริบ LED ออนบอร์ด
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 |
import time from rp2 import PIO, asm_pio from machine import Pin # Define the blink program. It has one GPIO to bind to on the set instruction, which is an output pin. # Use lots of delays to make the blinking visible by eye. @asm_pio(set_init=rp2.PIO.OUT_LOW) def blink(): wrap_target() set(pins, 1) [31] nop() [31] nop() [31] nop() [31] nop() [31] set(pins, 0) [31] nop() [31] nop() [31] nop() [31] nop() [31] wrap() # Instantiate a state machine with the blink program, at 1000Hz, with set bound to Pin(25) (LED on the rp2 board) sm = rp2.StateMachine(0, blink, freq=1000, set_base=Pin(25)) # Run the state machine for 3 seconds. The LED should blink. sm.active(1) time.sleep(3) sm.active(0) |
ในกรณีนี้ไม่มีไฟล์ .pio แยกต่างหากและทั้ง MicroPython และรหัสแอสเซมบลีจะถูกวางไว้ในไฟล์ .py
แม้ว่า PIO จะสามารถตั้งโปรแกรมด้วย MicroPython ได้ แต่เอกสาร Python SDKระบุว่าขณะนี้ไม่เสถียร/กำลังดำเนินการอยู่ ดังนั้นจึงแนะนำให้ใช้ภาษา C/C++
สามารถแก้ไขโค้ดได้หลายแบบโดยการเพิ่มสีที่คุณต้องการแสดงด้วยความช่วยเหลือของรูปแบบฐานสิบหกใน RGB อย่างไรก็ตามมีตัวอย่างมากมาย เช่น PWM, UART หรือแม้แต่การเชื่อมต่อ NeoPixels สำหรับผู้ที่สนใจคุณสามารถค้นหาตัวอย่างการเขียนโปรแกรม PIO มากมายในที่เก็บ GitHub สำหรับตัวอย่าง ภาษา C และ MicroPython
สรุป
Programmable I/O ของ RP2040 มีความสามารถในการรันโปรแกรมพร้อมกัน เพื่อรองรับอินเทอร์เฟซต์ เช่น เอาต์พุต VGA และการถ่ายโอนข้อมูลความเร็วสูงขึ้น คุณสามารถตรวจสอบในเอกสาร Rraspberry pi pico C/C++SDK สำหรับ C/C++ และ Python เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับ RP2040 Programmable I/O
แปลจากบทความภาษาอังกฤษ A closer look at Raspberry Pi RP2040 Programmable IOs (PIO)
บรรณาธิการข่าวและบทความภาษาไทย CNX Software ได้มีความสนใจในด้านเทคโนโลยี โดยเฉพาะ Smart Home และ IoT