

เมื่ออุปกรณ์ส่งสัญญาณเข้ามาที่ขาของบอร์ด การใช้ interrupt ช่วยให้โปรแกรมรู้ว่ามีเหตุการณ์เกิดขึ้นได้โดยไม่ต้องคอยอ่านขาอยู่ตลอด แต่พอมีฟังก์ชันให้เขียนตอนเหตุการณ์มาถึง ก็ชวนให้เอางานทั้งหมดไปใส่ไว้ตรงนั้น ทั้งอ่านเซนเซอร์ แปลงข้อมูลและส่งข้อความออกเครือข่าย
สิ่งที่ต้องระวังคือ ISR หรือ interrupt service routine ทำงานในบริบทต่างจาก task ปกติ งานที่เรียกได้สบายใน loop ไม่จำเป็นต้องเหมาะกับบริบทนี้ โดยเฉพาะสิ่งที่รอทรัพยากรหรือใช้เวลาที่คาดเดาไม่ได้
แทนการถามเพียงว่า ISR ต้องสั้นกี่บรรทัด ควรแยกว่าอะไรจำเป็นต้องรับไว้ทันที และอะไรส่งต่อไปทำภายหลังได้ครับ จำนวนบรรทัดไม่ได้บอกเวลาหรือเงื่อนไขของฟังก์ชันที่ซ่อนอยู่ข้างใน
สมมติว่าเซนเซอร์มีขาแจ้งว่าข้อมูลพร้อม สิ่งที่ ISR อาจต้องทำคือรับสถานะที่จำเป็นตาม driver แล้วส่งสัญญาณให้ task ไปอ่านข้อมูลต่อ ไม่จำเป็นต้องเรียกเครือข่ายในจุดเดียวกับที่รับเหตุการณ์ทางไฟฟ้า
แต่ต้องรู้ด้วยว่าอุปกรณ์เก็บข้อมูลค้างไว้ให้ได้นานแค่ไหน และเหตุการณ์แต่ละครั้งมีข้อมูลใหม่หรือเพียงแจ้งว่ามีงานรอ หากตัวอุปกรณ์ไม่เก็บประวัติให้ การส่งแค่ธงว่าพร้อมอาจรวมหลายเหตุการณ์จนแยกไม่ได้ การเลือกสิ่งที่ส่งต่อจึงต้องอิงสัญญาของอุปกรณ์ด้วย
สำหรับพัลส์ที่ต้องนับครบ อาจเหมาะกับ peripheral นับสัญญาณหรือ buffer ที่ออกแบบมารับอัตรานั้น มากกว่าการหวังให้ task ตื่นมาทันทุก edge การใช้ interrupt เป็นจุดเริ่มไม่ได้รับรองว่าจะเก็บข้อมูลครบโดยไม่ดูความสามารถของเส้นทางทั้งหมด

FreeRTOS มี API กลุ่ม FromISR สำหรับงานบางชนิด เช่น การส่งข้อมูลเข้าคิว ซึ่งต่างจากฟังก์ชันที่ task ปกติเรียกใช้ เอกสารระบุว่าฟังก์ชันส่งคิวแบบปกติไม่ควรถูกเรียกจาก ISR จึงไม่ควรเปลี่ยน context แล้วใช้คำสั่งเดิมทั้งหมดโดยไม่ตรวจ
การมีชื่อ FromISR ก็ยังต้องใช้ตามข้อกำหนดของ port และระดับ interrupt ที่อนุญาต รวมถึงวิธีแจ้งว่ามี task ที่ควรได้ทำงานต่อ ไม่คัดลอกชื่อฟังก์ชันจากอีกชิปแล้วถือว่าเงื่อนไขเหมือนกันทุกสถาปัตยกรรม
ส่วน library ระดับแอป เช่น การอ่านบัสหรือส่ง MQTT อาจมี mutex การจัดสรรหน่วยความจำและการรออยู่ภายใน การที่ฟังก์ชันเรียกแล้วดูเหมือนทำงานในตัวอย่างเล็กไม่ได้พิสูจน์ว่าใช้จาก ISR ได้ ควรย้ายไปบริบทที่เอกสารรองรับก่อน
คิวของ FreeRTOS คัดลอกข้อมูลตามขนาด item ที่กำหนดไว้ หาก item เป็นโครงสร้างเล็กที่มีค่าพร้อมใช้ ผู้รับก็ได้สำเนาตามนั้น แต่ถ้า item เป็น pointer สิ่งที่คัดลอกคือค่าที่อยู่ ไม่ได้ทำให้หน่วยความจำที่ชี้อยู่ถูกเก็บต่อให้อัตโนมัติ
จึงต้องรู้ว่าใครเป็นเจ้าของ buffer และผู้รับจะอ่านเมื่อใด ไม่ส่ง pointer ไปยังข้อมูลชั่วคราวที่หมดอายุหลังออกจากฟังก์ชัน หรือ buffer ที่ผู้ส่งนำกลับมาเขียนทับก่อน task ผู้รับทำงาน การส่งคิวสำเร็จไม่ได้ยืนยันอายุของข้อมูลที่อยู่นอก item
หากไม่ต้องขนข้อมูลครบชิ้น อาจใช้กลไกแจ้ง task ตามความหมายที่ต้องการ แต่ต้องแยกว่าต้องการเพียงรู้ว่ามีงานอย่างน้อยหนึ่งชิ้น หรือต้องรักษาจำนวนเหตุการณ์และลำดับไว้ วิธีที่รวมเหตุการณ์เข้าด้วยกันอาจถูกสำหรับงานแบบหนึ่งและทำข้อมูลหายสำหรับอีกแบบ

การส่งจาก ISR ไม่ควรรอให้ช่องว่างเกิดขึ้นเหมือนงานปกติที่ยอมรอได้ จึงต้องตรวจผลส่งและกำหนดว่าจะทำอย่างไรเมื่อไม่มีพื้นที่ ไม่เรียกซ้ำวนรอใน ISR จนงานที่ต้องช่วยระบายคิวไม่มีโอกาสทำงาน
ทางเลือกขึ้นกับสิ่งที่ข้อมูลแทน เช่น เก็บตัวนับเหตุการณ์ที่รับไม่ทัน แจ้งสถานะ overflow หรือใช้พื้นที่ที่ออกแบบสำหรับข้อมูลชุดนั้น แต่การเพิ่มคิวเพียงอย่างเดียวช่วยได้แค่บางช่วง หากอัตรางานเข้ามามากกว่าอัตราที่ทำออกได้ต่อเนื่อง สุดท้ายก็ต้องแก้ที่ภาระและขีดความสามารถ
ข้อมูลที่ task กับ ISR ใช้ร่วมกันยังต้องมีกลไกประสานตามระบบจริง โดยเฉพาะบน ESP32 ที่มีหลายแกน การทำเครื่องหมาย volatile อย่างเดียวไม่ได้สร้างการป้องกันการแก้พร้อมกันหรือทำให้หลายขั้นตอนเป็นงานอะตอมมิก ควรใช้วิธีที่ SDK รองรับและรักษาช่วงป้องกันให้สั้นตามหน้าที่
บน ESP32 การเขียนหรือลบ SPI flash อาจมีช่วงที่ cache ใช้งานไม่ได้ เอกสารจึงแยก handler ที่เข้าถึงเฉพาะ code กับ data ในหน่วยความจำภายใน ออกจาก handler ที่ยังพึ่งข้อมูลหรือคำสั่งใน flash
การวางฟังก์ชันหลักไว้ใน IRAM เพียงตัวเดียวไม่เพียงพอ หากมันเรียกฟังก์ชันอื่นหรืออ่านค่าที่อยู่ใน flash อีกทอด การเลือก flag ว่าเป็น IRAM-safe จึงต้องตรวจเส้นทาง code และ data ที่เข้าถึงทั้งหมดตามเงื่อนไข ไม่ใช่เติม attribute เพื่อให้ compiler ผ่านแล้วถือว่าปลอดข้อจำกัด
ไม่ได้หมายความว่า interrupt ทุกตัวต้องตั้งรูปแบบเดียวกัน งานที่ยอมเลื่อนระหว่าง flash operation ได้อาจมีทางเลือกต่างออกไป ต้องเลือกจากความต้องการเวลาและข้อกำหนดของ driver ไม่เพิ่ม flag โดยไม่มีเหตุผลรองรับ
ในชุดทดลองควรตรวจทั้งจำนวนเหตุการณ์ที่รับ จำนวนที่ส่งต่อได้ และสถานะเมื่อปลายทางช้าหรือมี flash operation ตามงานที่ต้องรองรับ จะได้เห็นว่าปัญหาอยู่ที่รับไม่ทัน ข้อมูลถูกเขียนทับ หรือ task ระบายไม่ทัน
บทนี้ไม่ได้รัน firmware หรือวัด latency ของบอร์ดจริง จึงไม่มีจำนวน interrupt ต่อวินาทีที่รับรองให้ใช้ได้กับทุกงาน ภาพประกอบอธิบายการแบ่งความรับผิดชอบ ไม่ใช่ผลทดสอบความเร็วของ ISR
ISR ควรรับสิ่งที่จำเป็นในเวลาที่ต้องการ แล้วส่งงานไปยังบริบทที่เหมาะสม โดยตรวจ API อายุข้อมูลและความจุของทางส่งต่อร่วมกัน เมื่อคิวเต็มหรือข้อมูลมาถี่กว่าที่ทำทันต้องมีสถานะที่ตามได้ ส่วนเงื่อนไขอย่าง IRAM-safe ก็ต้องตรวจทั้งเส้นทาง เพื่อให้การย้ายงานออกจาก ISR ช่วยรักษาความถูกต้องของข้อมูลไปพร้อมกับจังหวะของระบบ