Birkaç makinede faydalı bulduğum tek şey basit bir yığın değiştirici. Aslında PIC için bir tane yazmadım, ancak her iki / tüm iş parçacığı toplam 31 ya da daha az yığın seviyesi kullanıyorsa, yaklaşımın PIC18 üzerinde iyi çalışacağını umuyorum. 8051'de, ana rutin:
_taskswitch:
xch a, SP
xch a, _altSP
xch a, SP
çürümek
PIC'de yığın göstergesinin adını unuttum, ancak rutin şöyle bir şey olurdu:
_taskswitch:
movlb _altSP >> 8
movf _altSP, w, b
movff _STKPTR, altSP
movwf _STKPTR, c
dönüş
Programınızın başlangıcında, altSP'yi alternatif yığının adresiyle yükleyen bir görev2 () yordamını çağırın (16 muhtemelen bir PIC18Fxx için iyi sonuç verir) ve task2 döngüsünü çalıştırır; Bu rutin asla geri dönmemelidir, aksi halde işler acı verici bir ölümle ölür. Bunun yerine, birincil görevin kontrolünü vermek istediğinde _taskswitch'i çağırmalıdır; Birincil görev daha sonra ikincil göreve ulaşmak istediğinde _taskswitch'i çağırmalıdır. Genellikle, biri gibi sevimli küçük rutinleri olacak:
void delay_t1 (işaretsiz kısa val)
{
yap
taskswitch ();
while ((imzasız kısa) (millisecond_clock - val)> 0xFF00);
}
Görev değiştiricinin herhangi bir 'koşulu bekle' yapmanın bir yolu olmadığını unutmayın; Tüm desteklediği bir ıspanak. Öte yandan, görev anahtarı o kadar hızlıdır ki, diğer görev bir zamanlayıcının sona ermesini beklerken bir görev anahtarı () denemek diğer göreve geçer, zamanlayıcıyı kontrol eder ve tipik bir görev değiştiriciden daha hızlı geri döner Görevlerin yerine getirilmesine gerek olmadığını belirlerdi.
Kooperatif çoklu görevinin bazı sınırlamaları olduğunu unutmayın, ancak geçici olarak rahatsız edilen değişmezlerin hızlı bir şekilde yeniden kurulabildiği durumlarda çok sayıda kilitleme ve diğer muteks ile ilgili kod gereksinimlerini önler.
(Düzenleme): Otomatik değişkenlerle ilgili birkaç uyarı;
- Görev değiştirme kullanan bir rutin her iki diziden de çağrılıyorsa, genellikle rutinin iki kopyasını derlemek gerekir (büyük olasılıkla #define ifadeleriyle aynı kaynak dosyasını iki kez ekleyerek). Herhangi bir kaynak dosya yalnızca bir iş parçacığı için kod veya başka iki kez derlenecek kod içerecektir - her iş parçacığı için bir kez - böylece "#define delay (x) delay_t1 (x)" gibi makrolar kullanabilirim veya #define delay (x) delay_tx (x) "kullandığım konuya bağlı.
- Çağrılan bir işlevi "göremeyen" PIC derleyicilerinin, böyle bir işlevin tüm CPU kayıtlarına zarar verebileceğini varsaydığı ve böylece görev değiştirme yordamındaki herhangi bir kaydı kaydetme ihtiyacını ortadan kaldıracağına inanıyorum. önleyici çoklu görev]. Başka bir CPU için benzer bir görev değiştiriciyi düşünen herkes, kullanımdaki kayıt kurallarından haberdar olmalıdır. Bir görev değiştirmeden önce kayıtları itmek ve sonra bunları açmak, yeterli yığın alanı bulunduğunu varsayarak, işleri halletmenin kolay bir yoludur.
İşbirlikçi çoklu görev, bir kişinin kilitleme ve benzeri konulardan tamamen kaçmasına izin vermez, ama gerçekten işleri kolaylaştırır. Sıkıştırılmış bir çöp toplayıcılı önleyici bir RTOS'ta, örneğin, nesnelerin sabitlenmesine izin vermek gerekir. Bir işbirlikçi anahtarlayıcı kullanırken, bu, GC nesnelerinin görevler () çağrıldığında herhangi bir zamanda hareket edebileceğini varsayması şartıyla gerekli değildir. İğnelenmiş nesneler için endişelenmek zorunda kalmayan bir sıkıştırma toplayıcı, olduğundan daha basit olabilir.