สิ่งหนึ่งที่ฉันพบว่ามีประโยชน์กับหลาย ๆ เครื่องก็คือ stack switcher แบบง่าย ๆ ฉันยังไม่ได้เขียนหนึ่งสำหรับ PIC แต่ฉันคาดหวังว่าวิธีการนี้จะทำงานได้ดีบน PIC18 หากเธรดทั้งคู่ / ทั้งหมดใช้ระดับสแต็คทั้งหมด 31 หรือน้อยกว่า ใน 8051 รูทีนหลักคือ:
_taskswitch:
xch a, SP
xch a, _altSP
xch a, SP
เกษียณ
บน PIC ฉันลืมชื่อของตัวชี้สแต็ก แต่รูทีนจะเป็นดังนี้:
_taskswitch:
movlb _altSP >> 8
movf _altSP, w, b
movff _STKPTR, altSP
movwf _STKPTR, c
กลับ
เมื่อเริ่มต้นโปรแกรมให้เรียกรูทีน task2 () ซึ่งโหลด altSP พร้อมที่อยู่ของสแต็กสำรอง (16 อาจทำงานได้ดีสำหรับ PIC18Fxx) และรันลูป task2 กิจวัตรนี้จะต้องไม่กลับมามิฉะนั้นสิ่งอื่น ๆ จะตายอย่างเจ็บปวด แต่ควรเรียก _taskswitch ทุกครั้งที่ต้องการควบคุมการทำงานหลัก ภารกิจหลักควรเรียก _taskswitch ทุกครั้งที่ต้องการให้งานรอง บ่อยครั้งที่หนึ่งจะมีกิจวัตรน้อยน่ารักเช่น:
เป็นโมฆะ delay_t1 (สั้น val ที่ไม่ได้ลงชื่อ)
{
ทำ
taskswitch ();
ในขณะที่ ((สั้นไม่ได้ลงนาม) (millisecond_clock - val)> 0xFF00);
}
โปรดทราบว่าตัวสลับงานไม่มีวิธีการใด ๆ ในการทำ 'รอเงื่อนไข' สิ่งที่มันรองรับก็คือ spinwait ในทางกลับกันสวิตช์งานจะเร็วมากจนการพยายาม taskwitch () ในขณะที่ภารกิจอื่นกำลังรอให้ตัวจับเวลาหมดอายุจะสลับไปที่งานอื่นตรวจสอบตัวจับเวลาและสลับกลับเร็วกว่าตัวสลับงานทั่วไป จะกำหนดว่าไม่จำเป็นต้องสลับงาน
โปรดทราบว่าการทำงานมัลติทาสกิ้งแบบร่วมมือมีข้อ จำกัด บางประการ แต่ก็หลีกเลี่ยงความต้องการการล็อคและโค้ดที่เกี่ยวข้องกับ mutex จำนวนมากในกรณีที่ค่าคงที่ที่ถูกรบกวนชั่วคราวสามารถสร้างใหม่ได้อย่างรวดเร็ว
(แก้ไข): คำเตือนคู่เกี่ยวกับตัวแปรอัตโนมัติและเช่น:
- หากรูทีนที่ใช้การสลับงานถูกเรียกจากเธรดทั้งสองโดยทั่วไปจะจำเป็นต้องรวบรวมสำเนาสองชุดของรูทีน (อาจเป็นโดย #including ซอร์สไฟล์เดียวกันสองครั้งโดยมีคำสั่ง #define ต่างกัน) ไฟล์ต้นฉบับที่ให้มาจะมีโค้ดสำหรับเธรดเดียวเท่านั้นมิฉะนั้นจะมีโค้ดที่จะคอมไพล์สองครั้ง - หนึ่งครั้งสำหรับแต่ละเธรด - ดังนั้นฉันสามารถใช้มาโครเช่น "#define delay (x) delay_t1 (x)" หรือ #define delay (x) delay_tx (x) "ขึ้นอยู่กับว่าฉันใช้เธรดใดอยู่
- ฉันเชื่อว่าคอมไพเลอร์ PIC ที่ไม่สามารถ "เห็น" ฟังก์ชั่นที่เรียกว่าจะถือว่าฟังก์ชั่นดังกล่าวอาจทำให้ถังขยะใด ๆ และ CPU ทั้งหมดที่ลงทะเบียนดังนั้นหลีกเลี่ยงความจำเป็นในการบันทึกลงทะเบียนในรูทีน มัลติทาสกิ้งยึดเอาเสียก่อน] ทุกคนที่พิจารณาตัวสลับงานที่คล้ายกันสำหรับ CPU อื่น ๆ จำเป็นต้องทราบถึงระเบียบการลงทะเบียนที่ใช้งานอยู่ การกดรีจิสเตอร์ก่อนที่จะสลับงานและ popping หลังจากนั้นเป็นวิธีที่ง่ายในการดูแลสิ่งต่าง ๆ โดยสมมติว่ามีพื้นที่สแต็กเพียงพอ
มัลติทาสกิ้งแบบมีส่วนร่วมไม่อนุญาตให้ใครหลบหนีปัญหาการล็อคอย่างสมบูรณ์ แต่มันทำให้สิ่งต่าง ๆ ง่ายขึ้นอย่างมาก ใน RTOS ที่ยึดเอาเสียก่อนด้วยเครื่องเก็บขยะแบบย่อซึ่งจำเป็นต้องอนุญาตให้ตรึงวัตถุ เมื่อใช้ตัวสลับการทำงานร่วมกันคุณไม่จำเป็นต้องใช้รหัสที่สมมติว่ามีวัตถุ GC อาจย้ายเมื่อใดก็ได้ที่ taskwitch () ถูกเรียก ตัวบีบอัดแบบกระชับซึ่งไม่ต้องกังวลกับวัตถุที่ปักหมุดสามารถทำได้ง่ายกว่าที่ทำ