復(fù)習(xí)到操作系統(tǒng)這本書,在看到進(jìn)程管理的時(shí)候,想起以前費(fèi)了相當(dāng)大的時(shí)間去做一個(gè)屬于自己的操作系統(tǒng),結(jié)果什么都沒(méi)弄出來(lái)。
趁著看到這個(gè)章節(jié),又一次地萌生了這個(gè)想法,于是網(wǎng)上各種尋找資料。發(fā)現(xiàn)現(xiàn)在的大多數(shù)操作系統(tǒng)都已經(jīng)比較完善,換而言之,就是太龐大。無(wú)法去理解,無(wú)法自己照搬原文去弄一個(gè)屬于自己的操作系統(tǒng)出來(lái)。
機(jī)緣偶得之下,發(fā)現(xiàn)了一篇關(guān)于在單片機(jī)下面實(shí)現(xiàn)一個(gè)實(shí)時(shí)操作系統(tǒng)的文章, 即《建立一個(gè)屬于自己的AVR的RTOS》,這篇文章比起講什么操作系統(tǒng)原理、unix內(nèi)核分析、linux內(nèi)核分析、xx內(nèi)核分析等等來(lái)說(shuō),簡(jiǎn)單明了了很多(有興趣的同學(xué)們可以去研究一下這篇文章)。在參考這篇文章以及在51單片機(jī)下面使用匯編語(yǔ)言編程,以及眾多網(wǎng)上資料之后。總結(jié)地寫出了一個(gè)"在51單片機(jī)下具有延時(shí)功能占先式內(nèi)核的操作系統(tǒng)“,并仿真成功,加深了我對(duì)操作系統(tǒng)這個(gè)東西的小小理解。下面附上程序代碼以及實(shí)現(xiàn)。
如果網(wǎng)頁(yè)復(fù)制代碼有錯(cuò)誤,操作系統(tǒng)的完整代碼請(qǐng)從這里下載:http://www.torrancerestoration.com/f/12545.rar
以下是部分代碼:
#include <regx52.h> #define MAX_TASKS 5 typedef struct os_task_control_table { unsigned char os_task_wait_tick; unsigned char os_task_stack_top; }TCB; volatile unsigned char int_count; volatile unsigned char os_en_cr_count; #define enter_int() EA=0;int_count++; #define os_enter_critical() EA=0;os_en_cr_count++; #define os_exit_critical() if(os_en_cr_count>=1){os_en_cr_count--;if(os_en_cr_count==0)EA=1;} unsigned char code os_map_tbl[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; volatile unsigned char os_task_int_tbl; idata volatile TCB os_tcb[MAX_TASKS]; volatile unsigned char os_task_running_id; volatile unsigned char os_task_rdy_tbl; unsigned char idata os_task_stack[MAX_TASKS][20]; void os_init(void); void os_task_create(unsigned char task_id ,unsigned int task_point,unsigned char stack_point); void os_delay(unsigned char ticks); void os_start(void); void os_task_switch(void); void exit_int(void); void os_init(void) { EA = 0; ET2 = 1; T2CON = 0X00; T2MOD = 0X00; RCAP2H = 0x0D8; RCAP2L = 0x0F0; os_task_rdy_tbl = 0; os_task_int_tbl = 0xff; int_count = 0; os_en_cr_count = 0; } void os_task_create(unsigned char task_id ,unsigned int task_point,unsigned char stack_point) { os_enter_critical(); ((unsigned char idata *)stack_point)[0] = task_point; ((unsigned char idata *)stack_point)[1] = task_point>>8; os_tcb[task_id].os_task_stack_top = stack_point+14; os_task_rdy_tbl |= os_map_tbl[task_id]; os_tcb[task_id].os_task_wait_tick = 0; os_exit_critical(); } void os_delay(unsigned char ticks) { os_enter_critical(); os_tcb[os_task_running_id].os_task_wait_tick = ticks; os_task_rdy_tbl &= ~os_map_tbl[os_task_running_id]; os_exit_critical(); os_task_switch(); } void os_start(void) { os_task_running_id = 0; os_tcb[os_task_running_id].os_task_stack_top -= 13; EA = 1; SP = os_tcb[os_task_running_id].os_task_stack_top; TR2 = 1; } void os_task_switch(void) { unsigned char i; EA = 0; os_tcb[os_task_running_id].os_task_stack_top = SP; os_task_int_tbl &= ~os_map_tbl[os_task_running_id]; for(i=0; i<MAX_TASKS; i++) { if(os_task_rdy_tbl&os_map_tbl[i]) { break; } } os_task_running_id = i; SP = os_tcb[os_task_running_id].os_task_stack_top; if(os_task_int_tbl&os_map_tbl[os_task_running_id]) { __asm POP 7 __asm POP 6 //恢復(fù)任務(wù)寄存器 __asm POP 5 __asm POP 4 __asm POP 3 __asm POP 2 __asm POP 1 __asm POP 0 __asm POP PSW __asm POP DPL __asm POP DPH __asm POP B __asm POP ACC } EA = 1; __asm RETI } void exit_int(void) { unsigned char i; SP -= 2; if(--int_count == 0) { os_tcb[os_task_running_id].os_task_stack_top = SP; os_task_int_tbl |= os_map_tbl[os_task_running_id]; for(i=0; i<MAX_TASKS; i++) { if(os_task_rdy_tbl&os_map_tbl[i]) { break; } } os_task_running_id = i; SP = os_tcb[os_task_running_id].os_task_stack_top; if(os_task_int_tbl&os_map_tbl[os_task_running_id]) { __asm POP 7 __asm POP 6 //恢復(fù)任務(wù)寄存器 __asm POP 5 __asm POP 4 __asm POP 3 __asm POP 2 __asm POP 1 __asm POP 0 __asm POP PSW __asm POP DPL __asm POP DPH __asm POP B __asm POP ACC } EA = 1; __asm RETI } __asm POP 7 __asm POP 6 //恢復(fù)任務(wù)寄存器 __asm POP 5 __asm POP 4 __asm POP 3 __asm POP 2 __asm POP 1 __asm POP 0 __asm POP PSW __asm POP DPL __asm POP DPH __asm POP B __asm POP ACC EA=1; __asm RETI } void timer2_isr(void) interrupt 5 { unsigned char i; TF2=0; enter_int(); for(i=0; i<MAX_TASKS; i++) { if(os_tcb[i].os_task_wait_tick) { os_tcb[i].os_task_wait_tick--; if(os_tcb[i].os_task_wait_tick == 0) { os_task_rdy_tbl |= os_map_tbl[i]; } } } exit_int(); } void task_0(void) { while(1) { } } sbit seg2 = P2^5; sbit seg3 = P2^6; sbit seg4 = P2^7; void delay_ms(unsigned int xms){ unsigned int x,y; for(x=xms; x>0; x--) for(y=248; y>0; y--); } unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0}; void task_1(void) { unsigned char gw,sw,bw; while(1) { bw = os_tcb[2].os_task_wait_tick/100; sw = os_tcb[2].os_task_wait_tick%100/10; gw = os_tcb[2].os_task_wait_tick%10; P0 = table[bw]; seg2=0; delay_ms(3); seg2=1; P0 = table[sw]; seg3=0; delay_ms(3); seg3=1; P0 = table[gw]; seg4=0; delay_ms(3); seg4=1; } } void task_2(void) { unsigned char i; while(1) { i++; P3 = 0x01<<(i%8); os_delay(200); } } void task_3(void) { unsigned char i; while(1) { i++; //P2 = 0x01<<(i%8); os_delay(7); } } void task_4(void) { unsigned char i; while(1) { i++; P1 = 0x01<<(i%8); os_delay(10); } } void main(void) { os_init(); os_task_create(4,(unsigned int)&task_0,(unsigned char)os_task_stack[4]); os_task_create(3,(unsigned int)&task_1,(unsigned char)os_task_stack[3]); os_task_create(2,(unsigned int)&task_2,(unsigned char)os_task_stack[2]); os_task_create(1,(unsigned int)&task_3,(unsigned char)os_task_stack[1]); os_task_create(0,(unsigned int)&task_4,(unsigned char)os_task_stack[0]); os_start(); }
實(shí)現(xiàn)的圖片:
講解一下實(shí)現(xiàn)的內(nèi)容:
task_0是個(gè)空循環(huán)
task_1的作用是提取task_2的等待時(shí)間,顯示在數(shù)碼管上
task_2是在P3口上的跑馬燈(2秒跑一個(gè)燈)
task_3是單純地調(diào)用任務(wù)延時(shí)
task_4在P1口上的跑馬燈(100ms跑一個(gè)燈)
程序使用定時(shí)器2計(jì)數(shù)器產(chǎn)生的中斷作為時(shí)鐘源,時(shí)鐘的節(jié)拍是10ms一次。
當(dāng)然這個(gè)渺小的操作系統(tǒng)只實(shí)現(xiàn)了一些相當(dāng)基本的功能:多任務(wù)和系統(tǒng)延時(shí)以及搶占優(yōu)先級(jí)。還有信號(hào)量、內(nèi)存管理、事件、郵箱等等機(jī)制尚未實(shí)現(xiàn),但是懂了這個(gè)基礎(chǔ)內(nèi)容之后,其它的東西,都是在上面做擴(kuò)充的。
記得在一篇資料里面聽(tīng)到過(guò)這個(gè):會(huì)寫狀態(tài)機(jī)的程序員,肯定會(huì)寫操作系統(tǒng)。這句話到現(xiàn)在覺(jué)得相當(dāng)正確。操作系統(tǒng)就是一個(gè)另類的狀態(tài)機(jī),人為地干預(yù)了子程序調(diào)用和返回的過(guò)程。慶幸當(dāng)年的匯編沒(méi)白學(xué),操作系統(tǒng)需要懂得一些基本的硬件結(jié)構(gòu),匯編,C語(yǔ)言,當(dāng)懂得這些之后,再去網(wǎng)上多搜索點(diǎn)相關(guān)的資料,并且自己去用代碼一行行實(shí)現(xiàn),加以時(shí)日,操作系統(tǒng)便能輕松地玩轉(zhuǎn)與手.
在此,感謝黃健昌在網(wǎng)上的發(fā)表的《 建立一個(gè)屬于自己的AVR的RTOS》,這篇文章讓我對(duì)RTOS有了一個(gè)淺顯的了解
風(fēng)城少主發(fā)表的《建立一個(gè)屬于自己的51實(shí)時(shí)操作系統(tǒng)》,指導(dǎo)我在熟悉的51單片機(jī)上實(shí)現(xiàn)這個(gè)操作系統(tǒng)。
芯源老師的《芯源的單片機(jī)教程》為我提供了51單片機(jī)匯編及其硬件架構(gòu)的深入了解。
感謝http://www.torrancerestoration.com/mcu/1111.html 這個(gè)作者的激勵(lì)與鼓勵(lì)
真誠(chéng)地感謝上面提及的人,讓我能夠入門操作系統(tǒng),進(jìn)而了解到什么是嵌入式操作系統(tǒng),怎么去具體實(shí)現(xiàn)。