日韩在线不卡免费视频一区,日韩欧美精品一区二区三区经典,日产精品码2码三码四码区,人妻无码一区二区三区免费,日本feerbbwdh少妇丰满

  • 回復(fù)
  • 收藏
  • 點(diǎn)贊
  • 分享
  • 發(fā)新帖

談?wù)勱P(guān)于復(fù)雜性多任務(wù)程序的原理和設(shè)計(jì)程序

當(dāng)你看到操作系統(tǒng)的多任務(wù)并行的時(shí)候,你是否覺的很神奇呢?你是否想過那些任務(wù)的時(shí)間片輪轉(zhuǎn)是怎么實(shí)現(xiàn)的呢?這個時(shí)間片輪轉(zhuǎn)的秘密是什么呢?相信很多單片機(jī)初學(xué)者都會對這個問題感興趣。

當(dāng)你查看單片機(jī)的匯編指令的時(shí)候,你是否留意過中斷返回指令的操作過程?如果你留意過這個操作過程的話,你一定會發(fā)現(xiàn)它通過堆棧復(fù)原PC指針的過程。也就是說:當(dāng)單片機(jī)產(chǎn)生中斷的時(shí)候,它會把當(dāng)前程序正在運(yùn)行的PC指針保存在堆棧當(dāng)中;然后當(dāng)中斷程序運(yùn)行完畢的時(shí)候,程序執(zhí)行中斷返回指令,把堆棧中保存的PC指針再返回出來。

這個是單片機(jī)運(yùn)行的正常情況,但是如果在單片機(jī)的中斷中修改了堆棧中的PC指針值,那么是不是中斷就返不回來原來的程序地址?如果還是這個地址是我故意設(shè)定的值那么他是不是執(zhí)行完這個中斷就跳到我的設(shè)定的這個地址上去了?

如果這個地址又是另外一個任務(wù)的地址的時(shí)候不是正好實(shí)現(xiàn)了從一個任務(wù)的死循環(huán)中跳到了另外一個任務(wù)的死循環(huán)中去了?對了!沒錯!多任務(wù)并行運(yùn)行、時(shí)間片輪轉(zhuǎn)的秘密就是:在定時(shí)中斷中修改堆棧,使保存在中斷中PC指針按照預(yù)定的方式改變從而讓PC指針在幾個任務(wù)地址中不停的跳轉(zhuǎn)。

如果你有空去看UCOS的移植代碼的時(shí)候,你會發(fā)現(xiàn)切換任務(wù)的asm函數(shù)就是在修改堆棧的內(nèi)容。當(dāng)然了,真正的任務(wù)的切換過程不僅僅是修改PC指針的堆棧內(nèi)容,同時(shí)也修改了單片機(jī)所用到的所有可能被用到的寄存器的內(nèi)容。

全部回復(fù)(15)
正序查看
倒序查看
001a
LV.3
2
2014-02-11 16:30

分享的是我寫的一個雙任務(wù)并行的程序。一個任務(wù)是“main”函數(shù)的死循環(huán),另外一個任務(wù)是函數(shù)“task1”中的死循環(huán)。任務(wù)操作很簡單,就是兩個io口不停在切換電平,但是由于兩個任務(wù)中的時(shí)間延時(shí)不一樣而是切換電平的頻率不一樣。單片機(jī)用的是瑞薩k0s系列的單片機(jī)(應(yīng)為這個是我工作中常用的型號,我現(xiàn)在對這個比較熟,而51單片機(jī)很久沒有用過了,所以用的是這個型號,什么時(shí)候有空了我再寫個51單片機(jī)的程序)。有這個系列單片機(jī)開發(fā)板的可以單步運(yùn)行看看任務(wù)切換過程中“偷換”堆棧內(nèi)容的過程。(后面將分享我在這個平臺下寫的一個簡單的時(shí)間片輪轉(zhuǎn)的小操作系統(tǒng))修改堆棧內(nèi)容的中斷函數(shù):

__interrupt void MD_INTTM80( void )

{

/* TODO */

#asm

push ax

push bc

push de

push hl

movw ax,sp

movw bc,ax

mov a,#0ffh

sub a, c

inc a

mov c,a ;the sp_long

;/*********************;load the sp_long*****************************/

mov a,c

mov !0fec0h,a ;load the sp_long

;/**************************************************/

mov b,a ;load the data

movw de,#0feffh

movw hl,#0fec1h

?L_mov1: mov a,[de]

mov [hl],a

decw de

dec b

incw hl

mov a,b

cmp a,#0h

bnz $?L_mov1

;/************************load the data to sp**************************/

mov a,!0fea0h ;load the data to sp

mov b,a

movw de,#0fea1h

movw hl,#0feffh

?L_mov2: mov a,[de]

mov [hl],a

incw de

dec b

decw hl

mov a,b

cmp a,#0h

bnz $?L_mov2

;/*************************get the new sp_point*************************/

mov a,#0ffh ;get the new sp_point

sub a,!0fea0h

inc a

mov !0fe90h,a

mov a,#0feh

mov !0fe91h,a

;/************************save the sp_data**************************/

mov a,!0fec0h ;save the sp_data

mov !0fea0h,a

mov b,a

movw de,#0fec1h

movw hl,#0fea1h

?L_mov_sp: mov a,[de]

mov [hl],a

incw de

dec b

incw hl

mov a,b

cmp a,#0h

bnz $?L_mov_sp

#endasm

/**************************************************/

#asm

mov a,!0fe90h

mov x,a

mov a,!0fe91h

movw sp,ax

pop hl

pop de

pop bc

pop ax

#endasm

}

 

附上原理圖,之后咱們再談?wù)勅绾卧O(shè)計(jì)復(fù)雜的多任務(wù)程序

程序和原理圖:

AVR-多任務(wù)模擬系統(tǒng)設(shè)計(jì)(程序 原理圖).rar

 

0
回復(fù)
matou
LV.3
3
2014-02-22 20:08
@001a
分享的是我寫的一個雙任務(wù)并行的程序。一個任務(wù)是“main”函數(shù)的死循環(huán),另外一個任務(wù)是函數(shù)“task1”中的死循環(huán)。任務(wù)操作很簡單,就是兩個io口不停在切換電平,但是由于兩個任務(wù)中的時(shí)間延時(shí)不一樣而是切換電平的頻率不一樣。單片機(jī)用的是瑞薩k0s系列的單片機(jī)(應(yīng)為這個是我工作中常用的型號,我現(xiàn)在對這個比較熟,而51單片機(jī)很久沒有用過了,所以用的是這個型號,什么時(shí)候有空了我再寫個51單片機(jī)的程序)。有這個系列單片機(jī)開發(fā)板的可以單步運(yùn)行看看任務(wù)切換過程中“偷換”堆棧內(nèi)容的過程。(后面將分享我在這個平臺下寫的一個簡單的時(shí)間片輪轉(zhuǎn)的小操作系統(tǒng))修改堆棧內(nèi)容的中斷函數(shù):__interruptvoidMD_INTTM80(void){/*TODO*/#asmpushaxpushbcpushdepushhlmovwax,spmovwbc,axmova,#0ffhsuba,cincamovc,a;thesp_long;/*********************;loadthesp_long*****************************/mova,cmov!0fec0h,a;loadthesp_long;/**************************************************/movb,a;loadthedatamovwde,#0feffhmovwhl,#0fec1h?L_mov1:mova,[de]mov[hl],adecwdedecbincwhlmova,bcmpa,#0hbnz$?L_mov1;/************************loadthedatatosp**************************/mova,!0fea0h;loadthedatatospmovb,amovwde,#0fea1hmovwhl,#0feffh?L_mov2:mova,[de]mov[hl],aincwdedecbdecwhlmova,bcmpa,#0hbnz$?L_mov2;/*************************getthenewsp_point*************************/mova,#0ffh;getthenewsp_pointsuba,!0fea0hincamov!0fe90h,amova,#0fehmov!0fe91h,a;/************************savethesp_data**************************/mova,!0fec0h;savethesp_datamov!0fea0h,amovb,amovwde,#0fec1hmovwhl,#0fea1h?L_mov_sp:mova,[de]mov[hl],aincwdedecbincwhlmova,bcmpa,#0hbnz$?L_mov_sp#endasm/**************************************************/#asmmova,!0fe90hmovx,amova,!0fe91hmovwsp,axpophlpopdepopbcpopax#endasm} 附上原理圖,之后咱們再談?wù)勅绾卧O(shè)計(jì)復(fù)雜的多任務(wù)程序[圖片]程序和原理圖:AVR-多任務(wù)模擬系統(tǒng)設(shè)計(jì)(程序原理圖).rar 
這個想法不錯,實(shí)現(xiàn)起來不知道難不難,能不能用c語言實(shí)現(xiàn)
0
回復(fù)
daylight
LV.4
4
2014-02-22 20:09
@001a
分享的是我寫的一個雙任務(wù)并行的程序。一個任務(wù)是“main”函數(shù)的死循環(huán),另外一個任務(wù)是函數(shù)“task1”中的死循環(huán)。任務(wù)操作很簡單,就是兩個io口不停在切換電平,但是由于兩個任務(wù)中的時(shí)間延時(shí)不一樣而是切換電平的頻率不一樣。單片機(jī)用的是瑞薩k0s系列的單片機(jī)(應(yīng)為這個是我工作中常用的型號,我現(xiàn)在對這個比較熟,而51單片機(jī)很久沒有用過了,所以用的是這個型號,什么時(shí)候有空了我再寫個51單片機(jī)的程序)。有這個系列單片機(jī)開發(fā)板的可以單步運(yùn)行看看任務(wù)切換過程中“偷換”堆棧內(nèi)容的過程。(后面將分享我在這個平臺下寫的一個簡單的時(shí)間片輪轉(zhuǎn)的小操作系統(tǒng))修改堆棧內(nèi)容的中斷函數(shù):__interruptvoidMD_INTTM80(void){/*TODO*/#asmpushaxpushbcpushdepushhlmovwax,spmovwbc,axmova,#0ffhsuba,cincamovc,a;thesp_long;/*********************;loadthesp_long*****************************/mova,cmov!0fec0h,a;loadthesp_long;/**************************************************/movb,a;loadthedatamovwde,#0feffhmovwhl,#0fec1h?L_mov1:mova,[de]mov[hl],adecwdedecbincwhlmova,bcmpa,#0hbnz$?L_mov1;/************************loadthedatatosp**************************/mova,!0fea0h;loadthedatatospmovb,amovwde,#0fea1hmovwhl,#0feffh?L_mov2:mova,[de]mov[hl],aincwdedecbdecwhlmova,bcmpa,#0hbnz$?L_mov2;/*************************getthenewsp_point*************************/mova,#0ffh;getthenewsp_pointsuba,!0fea0hincamov!0fe90h,amova,#0fehmov!0fe91h,a;/************************savethesp_data**************************/mova,!0fec0h;savethesp_datamov!0fea0h,amovb,amovwde,#0fec1hmovwhl,#0fea1h?L_mov_sp:mova,[de]mov[hl],aincwdedecbincwhlmova,bcmpa,#0hbnz$?L_mov_sp#endasm/**************************************************/#asmmova,!0fe90hmovx,amova,!0fe91hmovwsp,axpophlpopdepopbcpopax#endasm} 附上原理圖,之后咱們再談?wù)勅绾卧O(shè)計(jì)復(fù)雜的多任務(wù)程序[圖片]程序和原理圖:AVR-多任務(wù)模擬系統(tǒng)設(shè)計(jì)(程序原理圖).rar 
單片機(jī)小型操作系統(tǒng)多任務(wù)并行的原理,不錯
0
回復(fù)
001a
LV.3
5
2014-02-22 20:11
@001a
分享的是我寫的一個雙任務(wù)并行的程序。一個任務(wù)是“main”函數(shù)的死循環(huán),另外一個任務(wù)是函數(shù)“task1”中的死循環(huán)。任務(wù)操作很簡單,就是兩個io口不停在切換電平,但是由于兩個任務(wù)中的時(shí)間延時(shí)不一樣而是切換電平的頻率不一樣。單片機(jī)用的是瑞薩k0s系列的單片機(jī)(應(yīng)為這個是我工作中常用的型號,我現(xiàn)在對這個比較熟,而51單片機(jī)很久沒有用過了,所以用的是這個型號,什么時(shí)候有空了我再寫個51單片機(jī)的程序)。有這個系列單片機(jī)開發(fā)板的可以單步運(yùn)行看看任務(wù)切換過程中“偷換”堆棧內(nèi)容的過程。(后面將分享我在這個平臺下寫的一個簡單的時(shí)間片輪轉(zhuǎn)的小操作系統(tǒng))修改堆棧內(nèi)容的中斷函數(shù):__interruptvoidMD_INTTM80(void){/*TODO*/#asmpushaxpushbcpushdepushhlmovwax,spmovwbc,axmova,#0ffhsuba,cincamovc,a;thesp_long;/*********************;loadthesp_long*****************************/mova,cmov!0fec0h,a;loadthesp_long;/**************************************************/movb,a;loadthedatamovwde,#0feffhmovwhl,#0fec1h?L_mov1:mova,[de]mov[hl],adecwdedecbincwhlmova,bcmpa,#0hbnz$?L_mov1;/************************loadthedatatosp**************************/mova,!0fea0h;loadthedatatospmovb,amovwde,#0fea1hmovwhl,#0feffh?L_mov2:mova,[de]mov[hl],aincwdedecbdecwhlmova,bcmpa,#0hbnz$?L_mov2;/*************************getthenewsp_point*************************/mova,#0ffh;getthenewsp_pointsuba,!0fea0hincamov!0fe90h,amova,#0fehmov!0fe91h,a;/************************savethesp_data**************************/mova,!0fec0h;savethesp_datamov!0fea0h,amovb,amovwde,#0fec1hmovwhl,#0fea1h?L_mov_sp:mova,[de]mov[hl],aincwdedecbincwhlmova,bcmpa,#0hbnz$?L_mov_sp#endasm/**************************************************/#asmmova,!0fe90hmovx,amova,!0fe91hmovwsp,axpophlpopdepopbcpopax#endasm} 附上原理圖,之后咱們再談?wù)勅绾卧O(shè)計(jì)復(fù)雜的多任務(wù)程序[圖片]程序和原理圖:AVR-多任務(wù)模擬系統(tǒng)設(shè)計(jì)(程序原理圖).rar 

寫自己的小型單片機(jī)操作系統(tǒng)代碼解析三:__interrupt void MD_INTTM80( void ) 解析:這用的C語言中嵌入?yún)R編語言的方式寫的匯編語言。實(shí)現(xiàn)的功能是我放第一貼講的任務(wù)切換的匯編語言是一樣的。簡單說一下這里匯編實(shí)現(xiàn)的功能:

1、調(diào)用函數(shù) stick_chang_task(void)獲取當(dāng)前任務(wù)堆棧的初始地址和下個任務(wù)堆棧的初始地址。

2、保存此時(shí)單片機(jī)中的堆棧內(nèi)容到當(dāng)前運(yùn)行的任務(wù)的中的任務(wù)堆棧

3、把下一個任務(wù)中的任務(wù)堆棧數(shù)組的內(nèi)容覆蓋到單片機(jī)的堆棧中

4、根據(jù)下一個任務(wù)堆棧數(shù)組中的內(nèi)容恢復(fù)SP的值

0
回復(fù)
001a
LV.3
6
2014-02-22 20:11
@001a
寫自己的小型單片機(jī)操作系統(tǒng)代碼解析三:__interruptvoidMD_INTTM80(void)解析:這用的C語言中嵌入?yún)R編語言的方式寫的匯編語言。實(shí)現(xiàn)的功能是我放第一貼講的任務(wù)切換的匯編語言是一樣的。簡單說一下這里匯編實(shí)現(xiàn)的功能:1、調(diào)用函數(shù)stick_chang_task(void)獲取當(dāng)前任務(wù)堆棧的初始地址和下個任務(wù)堆棧的初始地址。2、保存此時(shí)單片機(jī)中的堆棧內(nèi)容到當(dāng)前運(yùn)行的任務(wù)的中的任務(wù)堆棧3、把下一個任務(wù)中的任務(wù)堆棧數(shù)組的內(nèi)容覆蓋到單片機(jī)的堆棧中4、根據(jù)下一個任務(wù)堆棧數(shù)組中的內(nèi)容恢復(fù)SP的值

自己的小型單片機(jī)操作系統(tǒng)代碼解析二:

void cread_task(void(*task)(void),unsigned char *stack_) 解析

這個函數(shù)的作用是:建立死循環(huán)的任務(wù)。

參數(shù):

task

任務(wù)函數(shù)。建立死循環(huán)任務(wù)的時(shí)候,任務(wù)的函數(shù)名,用來獲取任務(wù)的函數(shù)名。

stack_

任務(wù)堆棧的數(shù)組指針。

os_sub_tasknum++;// 任務(wù)總數(shù)加1

ostask_stask_adress[(os_sub_tasknum-1)]=(unsigned int)stack_;//把當(dāng)前任務(wù) 用的任務(wù)堆棧地址首地址,賦值到這個數(shù)組給任務(wù)調(diào)度分配的時(shí)候用,也就是當(dāng)前時(shí)間片運(yùn)行完后,決定運(yùn)行那一個任務(wù)的時(shí)候就靠他了。

int_task(task,stack_);//初始化任務(wù)堆棧

void stick_chang_task(void) 解析

這個函數(shù)在 “時(shí)間中斷函數(shù)”__interrupt void MD_INTTM80( void ) 中調(diào)用。用來實(shí)現(xiàn)任務(wù)調(diào)度的功能。在里,任務(wù)可以按照時(shí)間片一個個進(jìn)行循環(huán)運(yùn)行就是靠這個函數(shù)實(shí)現(xiàn)的。

old_task=ostask_stask_adress[os_cur_tasknum];//當(dāng)前運(yùn)行的任務(wù)堆棧首地址賦值給全局變量old_task

os_cur_tasknum++;//當(dāng)前第幾個任務(wù)

if(os_cur_tasknum>=os_sub_tasknum)

{

os_cur_tasknum=0;

}

new_task=ostask_stask_adress[os_cur_tasknum];//下一個要運(yùn)行的任務(wù)堆棧首地址賦值給全局變量new_task

//判斷是否是第一次任務(wù)切換時(shí)候用到。第一次任務(wù)切換的時(shí)候是從main中切換出來的,不需要保存當(dāng)前的的堆棧內(nèi)容,所以設(shè)這個值給“時(shí)間中斷函數(shù)”__interrupt void MD_INTTM80( void ) 切換任務(wù)的時(shí)候進(jìn)行判斷

os_1st_time++;

if(os_1st_time>1)

{

os_1st_time=2;

}

0
回復(fù)
001a
LV.3
7
2014-02-22 20:13
@001a
自己的小型單片機(jī)操作系統(tǒng)代碼解析二:voidcread_task(void(*task)(void),unsignedchar*stack_)解析這個函數(shù)的作用是:建立死循環(huán)的任務(wù)。參數(shù):task任務(wù)函數(shù)。建立死循環(huán)任務(wù)的時(shí)候,任務(wù)的函數(shù)名,用來獲取任務(wù)的函數(shù)名。stack_任務(wù)堆棧的數(shù)組指針。os_sub_tasknum++;//任務(wù)總數(shù)加1ostask_stask_adress[(os_sub_tasknum-1)]=(unsignedint)stack_;//把當(dāng)前任務(wù)用的任務(wù)堆棧地址首地址,賦值到這個數(shù)組給任務(wù)調(diào)度分配的時(shí)候用,也就是當(dāng)前時(shí)間片運(yùn)行完后,決定運(yùn)行那一個任務(wù)的時(shí)候就靠他了。int_task(task,stack_);//初始化任務(wù)堆棧voidstick_chang_task(void)解析這個函數(shù)在“時(shí)間中斷函數(shù)”__interruptvoidMD_INTTM80(void)中調(diào)用。用來實(shí)現(xiàn)任務(wù)調(diào)度的功能。在里,任務(wù)可以按照時(shí)間片一個個進(jìn)行循環(huán)運(yùn)行就是靠這個函數(shù)實(shí)現(xiàn)的。old_task=ostask_stask_adress[os_cur_tasknum];//當(dāng)前運(yùn)行的任務(wù)堆棧首地址賦值給全局變量old_taskos_cur_tasknum++;//當(dāng)前第幾個任務(wù)if(os_cur_tasknum>=os_sub_tasknum){os_cur_tasknum=0;}new_task=ostask_stask_adress[os_cur_tasknum];//下一個要運(yùn)行的任務(wù)堆棧首地址賦值給全局變量new_task//判斷是否是第一次任務(wù)切換時(shí)候用到。第一次任務(wù)切換的時(shí)候是從main中切換出來的,不需要保存當(dāng)前的的堆棧內(nèi)容,所以設(shè)這個值給“時(shí)間中斷函數(shù)”__interruptvoidMD_INTTM80(void)切換任務(wù)的時(shí)候進(jìn)行判斷os_1st_time++;if(os_1st_time>1){os_1st_time=2;}

寫自己的小型單片機(jī)操作系統(tǒng)代碼解析一

:我寫的這個小型操作系統(tǒng)核心代碼在工程的“mini_os”目錄下。從今天開始將陸續(xù)對mini_os.c文件的函數(shù)進(jìn)行解析。里面總共4個函數(shù),分別是:

void cread_task(void(*task)(void),unsigned char *stack_);

void int_task(void(*task)(void),unsigned char *stack_);

void stick_chang_task(void);

__interrupt void MD_INTTM80( void );

他們分別實(shí)現(xiàn)的功能是:建立任務(wù)API函數(shù);初始化任務(wù)函數(shù),在建立任務(wù)函數(shù)中掉用;實(shí)現(xiàn)任務(wù)調(diào)度順序的函數(shù);實(shí)現(xiàn)任務(wù)切換的核心代碼,是匯編語言寫的。void int_task(void(*task)(void),unsigned char *stack_);

解析:可能很多人看著個函數(shù)都覺的很奇怪,為啥全是賦值?操作系統(tǒng)說白是用代碼虛擬一個CPU出來,那么你想想,一個CPU要想運(yùn)行是不是需要自己的基本數(shù)據(jù)空間呢?那就對了。這個作為一個任務(wù)的初始化函數(shù),那肯定得給一個任務(wù)虛擬一段這任務(wù)的數(shù)據(jù)空間了。這一段數(shù)據(jù)通常被稱為任務(wù)堆棧。所以任務(wù)建立的時(shí)候每一個任務(wù)都要建立自己的一個數(shù)組所為任務(wù)堆棧,不同的任務(wù)是不能共用同一個數(shù)組作為任務(wù)堆棧的。這個數(shù)據(jù)結(jié)構(gòu)包括:數(shù)據(jù)的長度(兩個字節(jié))、PSW、任務(wù)函數(shù)的地址、通用寄存器的。這個結(jié)構(gòu)的順序并不是固定的,但是要和任務(wù)切換函數(shù)里寫的要一致。

0
回復(fù)
close3
LV.5
8
2014-02-22 20:15
混合編程,多謝分享
0
回復(fù)
001a
LV.3
9
2014-02-22 20:17
@001a
分享的是我寫的一個雙任務(wù)并行的程序。一個任務(wù)是“main”函數(shù)的死循環(huán),另外一個任務(wù)是函數(shù)“task1”中的死循環(huán)。任務(wù)操作很簡單,就是兩個io口不停在切換電平,但是由于兩個任務(wù)中的時(shí)間延時(shí)不一樣而是切換電平的頻率不一樣。單片機(jī)用的是瑞薩k0s系列的單片機(jī)(應(yīng)為這個是我工作中常用的型號,我現(xiàn)在對這個比較熟,而51單片機(jī)很久沒有用過了,所以用的是這個型號,什么時(shí)候有空了我再寫個51單片機(jī)的程序)。有這個系列單片機(jī)開發(fā)板的可以單步運(yùn)行看看任務(wù)切換過程中“偷換”堆棧內(nèi)容的過程。(后面將分享我在這個平臺下寫的一個簡單的時(shí)間片輪轉(zhuǎn)的小操作系統(tǒng))修改堆棧內(nèi)容的中斷函數(shù):__interruptvoidMD_INTTM80(void){/*TODO*/#asmpushaxpushbcpushdepushhlmovwax,spmovwbc,axmova,#0ffhsuba,cincamovc,a;thesp_long;/*********************;loadthesp_long*****************************/mova,cmov!0fec0h,a;loadthesp_long;/**************************************************/movb,a;loadthedatamovwde,#0feffhmovwhl,#0fec1h?L_mov1:mova,[de]mov[hl],adecwdedecbincwhlmova,bcmpa,#0hbnz$?L_mov1;/************************loadthedatatosp**************************/mova,!0fea0h;loadthedatatospmovb,amovwde,#0fea1hmovwhl,#0feffh?L_mov2:mova,[de]mov[hl],aincwdedecbdecwhlmova,bcmpa,#0hbnz$?L_mov2;/*************************getthenewsp_point*************************/mova,#0ffh;getthenewsp_pointsuba,!0fea0hincamov!0fe90h,amova,#0fehmov!0fe91h,a;/************************savethesp_data**************************/mova,!0fec0h;savethesp_datamov!0fea0h,amovb,amovwde,#0fec1hmovwhl,#0fea1h?L_mov_sp:mova,[de]mov[hl],aincwdedecbincwhlmova,bcmpa,#0hbnz$?L_mov_sp#endasm/**************************************************/#asmmova,!0fe90hmovx,amova,!0fe91hmovwsp,axpophlpopdepopbcpopax#endasm} 附上原理圖,之后咱們再談?wù)勅绾卧O(shè)計(jì)復(fù)雜的多任務(wù)程序[圖片]程序和原理圖:AVR-多任務(wù)模擬系統(tǒng)設(shè)計(jì)(程序原理圖).rar 
補(bǔ)充下,任務(wù)切換是不分優(yōu)先級的
0
回復(fù)
001a
LV.3
10
2014-02-22 20:20

今天公開我的之前寫的仿UCOS(只有多任務(wù)切換的功能,是我發(fā)的第一個貼的程序的升級版),任務(wù)建立的多少跟ram的空間大小有關(guān),平臺MCU:NEC 公司的(現(xiàn)在為瑞薩公司)k0s系列9234,開發(fā)環(huán)境PM+。

任務(wù)調(diào)用程序一覽:

void task1(void);//任務(wù)1函數(shù)聲明

void task2(void);/任務(wù)2函數(shù)聲明

void task3(void);/任務(wù)3函數(shù)聲明

unsigned char task1_stask[30],task2_stask[30],task3_stask[30];//任務(wù)堆棧用到的數(shù)據(jù)空間

void delay(unsigned int i)

{

while(i--);

}

unsigned int ii1,ii2;

unsigned char a1;

int j;

void main( void )

{

/* TODO. add user code */

static unsigned int j,i;

ii1=0;

ii2=0;

PM3.3=0;

PM3.2=0;

PM4.2=0;

//inti_task_sp();

#asm

mov a,#0feh

mov x,#0ffh

movw sp,ax

#endasm

//初始化SP指針

cread_task(task1, task1_stask);

cread_task(task2, task2_stask);

cread_task(task3, task3_stask);

//建立三個任務(wù)

TM80_Start();

//開始任務(wù)調(diào)度

while(1);

}

void task1(void)//任務(wù)1內(nèi)容

{

static unsigned int i;

i=1;

stask_:

while(1)

{

//ii2++;

//i=50000;

P3.2=~P3.2;

delay(20000);

//while(i--);

}

ii2++;

ii2++;

ii2++;

goto stask_;

}

void task2(void)//任務(wù)2內(nèi)容

{

main_:

while(1){

//ii1++;

//j=300;

P3.3=~P3.3;

delay(1000);

//while(j--);

//j=10000;

//while(j--);

//i=10000;

//while(i--);

//i=10000;

//while(i--);

}

//ii1++;

//ii1++;

//ii1++;

goto main_;

}

void task3(void)//任務(wù)3內(nèi)容

{

main_:

while(1){

//ii1++;

//j=300;

P4.2=~P4.2;

delay(4000);

//while(j--);

//j=10000;

//while(j--);

//i=10000;

//while(i--);

//i=10000;

//while(i--);

}

//ii1++;

//ii1++;

//ii1++;

goto main_;

}

caozuoxintong_v3.1.zip

0
回復(fù)
for_real
LV.3
11
2014-02-22 20:22
@001a
今天公開我的之前寫的仿UCOS(只有多任務(wù)切換的功能,是我發(fā)的第一個貼的程序的升級版),任務(wù)建立的多少跟ram的空間大小有關(guān),平臺MCU:NEC公司的(現(xiàn)在為瑞薩公司)k0s系列9234,開發(fā)環(huán)境PM+。任務(wù)調(diào)用程序一覽:voidtask1(void);//任務(wù)1函數(shù)聲明voidtask2(void);/任務(wù)2函數(shù)聲明voidtask3(void);/任務(wù)3函數(shù)聲明unsignedchartask1_stask[30],task2_stask[30],task3_stask[30];//任務(wù)堆棧用到的數(shù)據(jù)空間voiddelay(unsignedinti){while(i--);}unsignedintii1,ii2;unsignedchara1;intj;voidmain(void){/*TODO.addusercode*/staticunsignedintj,i;ii1=0;ii2=0;PM3.3=0;PM3.2=0;PM4.2=0;//inti_task_sp();#asmmova,#0fehmovx,#0ffhmovwsp,ax#endasm//初始化SP指針cread_task(task1,task1_stask);cread_task(task2,task2_stask);cread_task(task3,task3_stask);//建立三個任務(wù)TM80_Start();//開始任務(wù)調(diào)度while(1);}voidtask1(void)//任務(wù)1內(nèi)容{staticunsignedinti;i=1;stask_:while(1){//ii2++;//i=50000;P3.2=~P3.2;delay(20000);//while(i--);}ii2++;ii2++;ii2++;gotostask_;}voidtask2(void)//任務(wù)2內(nèi)容{main_:while(1){//ii1++;//j=300;P3.3=~P3.3;delay(1000);//while(j--);//j=10000;//while(j--);//i=10000;//while(i--);//i=10000;//while(i--);}//ii1++;//ii1++;//ii1++;gotomain_;}voidtask3(void)//任務(wù)3內(nèi)容{main_:while(1){//ii1++;//j=300;P4.2=~P4.2;delay(4000);//while(j--);//j=10000;//while(j--);//i=10000;//while(i--);//i=10000;//while(i--);}//ii1++;//ii1++;//ii1++;gotomain_;}caozuoxintong_v3.1.zip
看匯編,就象看天書啊
0
回復(fù)
soap泡泡
LV.4
12
2014-02-22 20:23
C語言也有時(shí)間片輪轉(zhuǎn)啊。網(wǎng)上一搜大把的。
0
回復(fù)
elio
LV.2
13
2014-02-22 20:24
加上調(diào)度機(jī)制,這其實(shí)就是就是所有操作系統(tǒng)最基礎(chǔ)的東西。
0
回復(fù)
vidas
LV.2
14
2014-02-22 20:25
@for_real
看匯編,就象看天書啊
看不懂匯編,但是好多的底層必須用匯編,真糾結(jié)呀,,,好比對SP,PC的更改,對堆棧的更改
0
回復(fù)
candyman
LV.2
15
2014-02-22 20:27
有C語言的嗎?
0
回復(fù)
001a
LV.3
16
2014-02-22 20:28
@candyman
有C語言的嗎?

木有啊。。。C語言不能獲取堆棧SP當(dāng)前的值,這樣獲取不了堆棧長度(當(dāng)前堆棧長度=當(dāng)前堆棧的值和原來設(shè)的堆棧底之差的絕對值)。       

上面匯編的內(nèi)容是:先保護(hù)常用寄存器 ax bc de hl(如果是51單片那么對應(yīng)的應(yīng)該是r0 r1 r2 r3 ...) ;然后計(jì)算堆棧長度;再把堆棧數(shù)據(jù)全部復(fù)制到一段數(shù)據(jù)“1”區(qū)內(nèi)(這個是數(shù)據(jù)去起中間緩存的作用),并且保存這段數(shù)據(jù)的長度;再把數(shù)據(jù)“2”區(qū)內(nèi)的數(shù)據(jù)覆蓋回原來的堆棧(數(shù)據(jù)“2”區(qū)就是上一個任務(wù)的堆棧數(shù)據(jù));再根據(jù)數(shù)據(jù)“2”去的數(shù)據(jù)長度回復(fù)SP值;再把數(shù)據(jù)“1”區(qū)的數(shù)據(jù)覆蓋數(shù)據(jù)“2”去的數(shù)據(jù)(下個中斷來的時(shí)候再把這個數(shù)據(jù)“2”區(qū)的書覆蓋堆棧);最后還原常用寄存器 ax bc de hl 數(shù)據(jù),退出中斷(因?yàn)槲覍懙膮R編是嵌在C語言中的,所以不用這個匯編指令)。

0
回復(fù)
發(fā)