micropython --- การเข้าถึงและควบคุมภายใน MicroPython¶
Functions¶
- micropython.const(expr: int) int¶
ใช้เพื่อประกาศว่า expression เป็นค่าคงที่ เพื่อให้ compiler สามารถปรับให้เหมาะสมได้ การใช้งานฟังก์ชันนี้ควรเป็นดังนี้:
from micropython import const CONST_X = const(123) CONST_Y = const(2 * CONST_X + 1)
ค่าคงที่ที่ประกาศด้วยวิธีนี้ยังสามารถเข้าถึงได้เป็นตัวแปร global จากภายนอกโมดูลที่ประกาศ ในทางกลับกัน หากค่าคงที่เริ่มต้นด้วยขีดล่าง จะถูกซ่อน ไม่สามารถใช้เป็นตัวแปร global และไม่ใช้หน่วยความจำระหว่างการทำงาน
ฟังก์ชัน
constนี้ได้รับการรู้จักโดยตรงจาก MicroPython parser และมีให้เป็นส่วนหนึ่งของโมดูลmicropythonเพื่อให้สามารถเขียนสคริปต์ที่ทำงานได้ทั้งบน CPython และ MicroPython โดยใช้รูปแบบข้างต้น
- micropython.opt_level(level: int | None = None) int | None¶
หากกำหนด level ฟังก์ชันนี้จะตั้งค่าระดับการปรับให้เหมาะสมสำหรับการคอมไพล์สคริปต์ต่อไป และคืนค่า
Noneมิฉะนั้นจะคืนค่าระดับการปรับให้เหมาะสมปัจจุบันระดับการปรับให้เหมาะสมควบคุมลักษณะการคอมไพล์ดังต่อไปนี้:
Assertions: ที่ระดับ 0 คำสั่ง assertion จะเปิดใช้งานและถูกคอมไพล์ลงใน bytecode; ที่ระดับ 1 ขึ้นไป assertion จะไม่ถูกคอมไพล์
ตัวแปรในตัว
__debug__: ที่ระดับ 0 ตัวแปรนี้มีค่าเป็นTrue; ที่ระดับ 1 ขึ้นไปมีค่าเป็นFalseหมายเลขบรรทัดในซอร์สโค้ด: ที่ระดับ 0, 1 และ 2 หมายเลขบรรทัดในซอร์สโค้ดจะถูกเก็บพร้อมกับ bytecode เพื่อให้ exception รายงานหมายเลขบรรทัดที่เกิดขึ้นได้; ที่ระดับ 3 ขึ้นไปหมายเลขบรรทัดจะไม่ถูกเก็บ
ระดับการปรับให้เหมาะสมเริ่มต้นมักจะเป็นระดับ 0
- micropython.alloc_emergency_exception_buf(size: int) None¶
จัดสรร size bytes ของ RAM สำหรับ emergency exception buffer (ขนาดที่เหมาะสมคือประมาณ 100 bytes) บัฟเฟอร์นี้ใช้เพื่อสร้าง exception ในกรณีที่การจัดสรร RAM ปกติล้มเหลว (เช่น ภายใน interrupt handler) และด้วยเหตุนี้จึงให้ข้อมูล traceback ที่มีประโยชน์ในสถานการณ์เหล่านั้น
วิธีที่ดีในการใช้ฟังก์ชันนี้คือวางไว้ที่จุดเริ่มต้นของสคริปต์หลัก (เช่น
boot.pyหรือmain.py) จากนั้น emergency exception buffer จะทำงานสำหรับโค้ดทั้งหมดที่ตามมา
- micropython.mem_info(verbose: Any | None = None) None¶
พิมพ์ข้อมูลเกี่ยวกับหน่วยความจำที่ใช้อยู่ในปัจจุบัน หากกำหนดอาร์กิวเมนต์ verbose จะพิมพ์ข้อมูลเพิ่มเติม
ข้อมูลที่พิมพ์ขึ้นอยู่กับการใช้งาน แต่ปัจจุบันรวมถึงปริมาณ stack และ heap ที่ใช้ ในโหมด verbose จะพิมพ์ heap ทั้งหมดโดยระบุว่าบล็อกใดถูกใช้งานและบล็อกใดว่างอยู่
- micropython.qstr_info(verbose: Any | None = None) None¶
พิมพ์ข้อมูลเกี่ยวกับสตริงที่ถูก intern ในปัจจุบัน หากกำหนดอาร์กิวเมนต์ verbose จะพิมพ์ข้อมูลเพิ่มเติม
ข้อมูลที่พิมพ์ขึ้นอยู่กับการใช้งาน แต่ปัจจุบันรวมถึงจำนวนสตริงที่ถูก intern และปริมาณ RAM ที่ใช้ ในโหมด verbose จะพิมพ์ชื่อสตริง RAM-interned ทั้งหมด
- micropython.stack_use() int¶
คืนค่าจำนวนเต็มที่แทนปริมาณ stack ที่ใช้งานอยู่ในปัจจุบัน ค่าสัมบูรณ์ไม่มีประโยชน์มากนัก แต่ควรใช้เพื่อคำนวณความแตกต่างของการใช้งาน stack ณ จุดต่าง ๆ
- micropython.heap_lock() None¶
ล็อค heap ขณะที่ล็อค การจัดสรรหน่วยความจำไม่สามารถเกิดขึ้นได้ และ
MemoryErrorจะถูก raise หากมีการพยายามจัดสรร heap ใด ๆการล็อคสามารถซ้อนกันได้: การเรียก
heap_lock()หลายครั้งจะเพิ่มความลึกของการล็อค heap จะยังคงล็อคอยู่จนกว่าheap_unlock()จะถูกเรียกในจำนวนครั้งเท่ากันหาก REPL ทำงานขณะที่ heap ถูกล็อค จะถูกปลดล็อคโดยบังคับ
- micropython.heap_unlock() int¶
ลดความลึกของการล็อค heap ลงหนึ่งและคืนค่าความลึกใหม่เป็นจำนวนเต็มที่ไม่เป็นลบ ค่าที่คืนเป็น
0หมายความว่า heap ไม่ได้ถูกล็อคอีกต่อไปและอนุญาตให้จัดสรรได้อีกครั้ง
- micropython.heap_locked() int¶
คืนค่าความลึกของการล็อค heap ปัจจุบันเป็นจำนวนเต็มที่ไม่เป็นลบ;
0หมายความว่า heap ไม่ได้ถูกล็อคหมายเหตุ: ฟังก์ชันนี้ไม่สามารถใช้งานได้บน OpenMV Cam
- micropython.kbd_intr(chr: int) None¶
ตั้งค่าตัวอักษรที่จะ raise
KeyboardInterruptexception โดยค่าเริ่มต้นจะถูกตั้งเป็น 3 ระหว่างการรันสคริปต์ ซึ่งตรงกับ Ctrl-C การส่ง -1 ไปยังฟังก์ชันนี้จะปิดการจับ Ctrl-C และการส่ง 3 จะคืนค่ากลับฟังก์ชันนี้สามารถใช้เพื่อป้องกันการจับ Ctrl-C บน stream ของอักขระที่เข้ามาซึ่งโดยปกติใช้สำหรับ REPL ในกรณีที่ stream นั้นถูกใช้เพื่อจุดประสงค์อื่น
- micropython.schedule(func: Callable[[Any], Any], arg: Any) None¶
จัดกำหนดการให้ฟังก์ชัน func ทำงาน "เร็ว ๆ นี้" ฟังก์ชันจะรับค่า arg เป็นอาร์กิวเมนต์เดียว "เร็ว ๆ นี้" หมายความว่า MicroPython runtime จะพยายามทำให้ฟังก์ชันทำงานเร็วที่สุดเท่าที่เป็นไปได้ โดยคำนึงถึงประสิทธิภาพด้วย และมีเงื่อนไขดังต่อไปนี้:
ฟังก์ชันที่ถูกจัดกำหนดการจะไม่แย่งการทำงานของฟังก์ชันที่ถูกจัดกำหนดการอื่น
ฟังก์ชันที่ถูกจัดกำหนดการจะทำงาน "ระหว่าง opcode" เสมอ ซึ่งหมายความว่าการดำเนินการ Python พื้นฐานทั้งหมด (เช่น การ append ไปยัง list) รับประกันว่าเป็น atomic
port บางตัวอาจกำหนด "critical regions" ซึ่งฟังก์ชันที่ถูกจัดกำหนดการจะไม่ทำงานเด็ดขาด ฟังก์ชันอาจถูกจัดกำหนดการภายใน critical region แต่จะไม่ทำงานจนกว่า region นั้นจะสิ้นสุด ตัวอย่างของ critical region คือ preempting interrupt handler (IRQ)
ภายในฟังก์ชัน native code ฟังก์ชันที่ถูกจัดกำหนดการจะไม่ถูกเรียก เว้นแต่ native code จะเรียกฟังก์ชันที่ทำเช่นนั้นโดยเฉพาะ
ฟังก์ชันบางตัวรวมถึง
poll.poll,poll.ipoll,time.sleepและtime.sleep_ms(รวมถึงการ sleep ระยะเวลาเป็นศูนย์) จะเรียกฟังก์ชันที่ถูกจัดกำหนดการ
การใช้งานฟังก์ชันนี้คือการจัดกำหนดการ callback จาก preempting IRQ IRQ ดังกล่าวมีข้อจำกัดสำหรับโค้ดที่ทำงานใน IRQ (เช่น heap อาจถูกล็อค) และการจัดกำหนดการฟังก์ชันให้ทำงานภายหลังจะยกเลิกข้อจำกัดเหล่านั้น
บน port แบบ multi-thread พฤติกรรมของฟังก์ชันที่ถูกจัดกำหนดการขึ้นอยู่กับว่า Global Interpreter Lock (GIL) เปิดใช้งานสำหรับ port นั้น ๆ หรือไม่:
หาก GIL เปิดใช้งาน ฟังก์ชันสามารถแย่งการทำงานของ thread ใด ๆ และทำงานใน context ของ thread นั้น
หาก GIL ปิดใช้งาน ฟังก์ชันจะแย่งการทำงานได้เฉพาะ main thread และทำงานใน context ของ thread นั้น
หมายเหตุ: หาก
schedule()ถูกเรียกจาก preempting IRQ เมื่อการจัดสรรหน่วยความจำไม่ได้รับอนุญาต และ callback ที่จะส่งไปยังschedule()เป็น bound method การส่ง bound method โดยตรงจะล้มเหลว เนื่องจากการสร้าง reference ไปยัง bound method ทำให้เกิดการจัดสรรหน่วยความจำ วิธีแก้คือสร้าง reference ไปยัง method ใน class constructor และส่ง reference นั้นไปยังschedule()รายละเอียดอยู่ที่ เอกสารอ้างอิง ใต้หัวข้อ "Creation of Python objects"มี queue ขนาดจำกัดสำหรับเก็บฟังก์ชันที่ถูกจัดกำหนดการ และ
schedule()จะ raiseRuntimeErrorหาก queue เต็ม
Classes¶
- class micropython.RingIO(size: int)¶
- class micropython.RingIO(buffer: bytes | bytearray | memoryview)
ให้ ringbuffer ขนาดคงที่สำหรับ bytes พร้อม stream interface ถือได้ว่าเป็น FIFO-queue variant ของ
io.BytesIOรูปแบบ constructor สองแบบต่างกันเฉพาะวิธีการจัดหา backing buffer:RingIO(size)จัดสรร backing buffer ภายใน อัลกอริทึม ringbuffer แบบคลาสสิกสำรอง 1 byte สำหรับการติดตาม ดังนั้น buffer ที่จัดสรรจะมีขนาดใหญ่กว่าsizeหนึ่ง byte และ instance สามารถเก็บข้อมูลได้sizebytes เต็มจำนวน ตัวอย่างเช่นRingIO(16)จัดสรร buffer 17 bytes และเก็บข้อมูลได้ 16 bytesRingIO(buffer)ใช้bufferที่ให้มาแทนที่จะจัดสรรใหม่ เนื่องจากสำรอง 1 byte ไว้สำหรับการติดตาม instance จึงสามารถเก็บข้อมูลได้len(buffer) - 1bytes ตัวอย่างเช่นRingIO(bytearray(16))เก็บข้อมูลได้ 15 bytes
instance ของ RingIO ปลอดภัยสำหรับ IRQ/thread เมื่อใช้เพื่อส่งข้อมูลในทิศทางเดียว (เช่น เขียนจาก IRQ และอ่านจากฟังก์ชัน non-IRQ หรือในทางกลับกัน) สิ่งนี้ไม่เป็นความจริงหาก instance เดียวถูกเขียนจากทั้ง context IRQ และ non-IRQ ซึ่งมักทำให้ข้อมูลเสียหาย
- read(nbytes: int | None = None) bytes¶
อ่านอักขระที่มีอยู่ เป็นฟังก์ชันแบบไม่บล็อก หากกำหนด
nbytesจะอ่านได้สูงสุดจำนวนนั้น bytes มิฉะนั้นจะอ่านข้อมูลให้มากที่สุดเท่าที่เป็นไปได้ค่าที่คืน: ออบเจกต์ bytes ที่มี bytes ที่อ่านได้ จะเป็นออบเจกต์ bytes ที่มีความยาวเป็นศูนย์หากไม่มีข้อมูล
- readline(nbytes: int | None = None) bytes¶
อ่านบรรทัดหนึ่ง โดยสิ้นสุดที่อักขระขึ้นบรรทัดใหม่หรือคืนค่าหากมีอยู่ใน buffer มิฉะนั้นคืนค่า bytes ที่มีอยู่ใน buffer หากกำหนด
nbytesจะอ่านได้สูงสุดจำนวนนั้น bytesค่าที่คืน: ออบเจกต์ bytes ที่มีบรรทัดที่อ่านได้
- readinto(buf: bytearray | memoryview, nbytes: int | None = None) int¶
อ่าน bytes ที่มีอยู่ลงใน
bufที่กำหนด หากกำหนดnbytesจะอ่านได้สูงสุดจำนวนนั้น bytes มิฉะนั้นอ่านได้สูงสุดlen(buf)bytesค่าที่คืน: จำนวนเต็มนับจำนวน bytes ที่อ่านลงใน
buf
- write(buf: bytes | bytearray | memoryview) int¶
เขียน bytes จาก
bufลงใน ringbuffer แบบไม่บล็อก จำกัดโดยพื้นที่ว่างใน ringbufferค่าที่คืน: จำนวนเต็มนับจำนวน bytes ที่เขียน