基于proteus的ARM7TDMI-RTOS

很久前的代码(初学代码较乱),希望对阅读本文的读者理解RTOS有所帮助。

main.c

#include<stdio.h>
#include <stdarg.h>
#include <stdlib.h>  

#include"ARM7.h"
#define P3 *((volatile unsigned *)0x80000090)
#define P2 *((volatile unsigned *)0x80000088)
#define P1 *((volatile unsigned *)0x80000084)
#define P0 *((volatile unsigned *)0x80000080)

#define tasknumsize	4
#define semMaxNum 3 
volatile unsigned char cnt=0,IntNestNum=0;
volatile unsigned int clk=0,wait[tasknumsize];
volatile unsigned long taskrdy=0,nxttask=0,curtask=0,pcurtask,phightask,taskstkptr[tasknumsize];

void delay(unsigned int z);
void putS(char *s);
void CNTinterrupt(void);
void USARTinterrupt(void);
extern void start(void);
extern void run(void);
void clkTick(void);
void Sched(void);
void EnterInt(void);
void IntExitSw(void);


void CNTinterrupt(void)
{
	if(CNT>=0x3)
	{	
		CNT=0x0;
	//	BUF='A';
		clkTick();
	}
    CNTINT=0x0;//清零计数器中断
    INTFLG=0x03;//清零中断标志位
}

void USARTinterrupt(void)
{
	char tmp;
	tmp=BUF;			//通过读取BUF,清除LSR(0)位
	INTFLG=0x02;		//清零中断标志位,bit0->CNT,bit1->USART
	INTMSK=0x03;
}

void DisInt(void)
{
	INTMSK=0x00;
}

void EnInt(void)
{
	INTMSK=0x01;	//使能定时器中断
}

void delay(unsigned int z)
{
	unsigned int x,y;
	for(x=z;x>0;x--)
		for(y=110;y>0;y--);
}

void put_char(char ch)
{
	BUF = ch;
	while(!(LSR&0x40));
}

void putS(char *s)
{
	while(*s!='\0')
	{
		BUF = *s;
		while(!(LSR&0x40));
		s++;
	}
}

#define stksize	512
unsigned int task0stk[stksize];
unsigned int task1stk[stksize];
unsigned int task2stk[stksize];
unsigned int idlestk[stksize];
void task0(void);
void task1(void);
void task2(void);
void idle(void);
#define NOINT       (0xC0)
#define Mode_SVC    (0x13)

void create(void (*fun)(void),unsigned int *pstk,unsigned char num)
{
	*(pstk)=(unsigned int)fun;
	*(--pstk) = (unsigned int)13;           		/* lr */ 
    *(--pstk) = (unsigned int)12;                   /* r12*/ 
    *(--pstk) = (unsigned int)11;                   /* r11*/ 
    *(--pstk) = (unsigned int)10;                   /* r10*/ 
    *(--pstk) = (unsigned int)9;                    /* r9 */ 
    *(--pstk) = (unsigned int)8;                    /* r8 */ 
    *(--pstk) = (unsigned int)7;                    /* r7 */ 
    *(--pstk) = (unsigned int)6;                    /* r6 */ 
    *(--pstk) = (unsigned int)5;                    /* r5 */ 
    *(--pstk) = (unsigned int)4;                    /* r4 */ 
    *(--pstk) = (unsigned int)3;                    /* r3 */ 
    *(--pstk) = (unsigned int)2;                    /* r2 */ 
    *(--pstk) = (unsigned int)1;                    /* r1 */ 
    *(--pstk) = (unsigned int)0;                    /* r0 */ 
    *(--pstk) = (unsigned int)(Mode_SVC);       	/* spsr 保存在任务栈中*/
    taskstkptr[num]=(unsigned int)pstk;
    wait[num]=0;
    taskrdy |= (0x1<<num);  //是任务进入就绪态
}

struct sem{
	unsigned int semCnt;
	unsigned int semPend;

}sem_t[semMaxNum];

void semCreate(unsigned char idx,unsigned int semN)
{
	if(idx < semMaxNum)
	{
		sem_t[idx].semCnt = semN;
		sem_t[idx].semPend = 0;
	}
}

void semPending(unsigned char idx)
{
	
	if(idx < semMaxNum)
	{
		if(sem_t[idx].semCnt==0)
		{
		
			sem_t[idx].semPend |= (0x1<<curtask);
			taskrdy &= ~(0x1<<curtask);  //挂起任务
				
			Sched();	
			
		}
		if(sem_t[idx].semCnt>0)
		{
			sem_t[idx].semCnt--;
		}
		
	}

}

void semPost(unsigned char idx)
{
	unsigned char i;
	DisInt();

	if(sem_t[idx].semCnt < 0xffff)
		sem_t[idx].semCnt++;
	for(i=0;((i<tasknumsize)&&!(sem_t[idx].semPend&(0x01<<i)));i++);
	EnInt();
	if(i<tasknumsize)
	{
		sem_t[idx].semPend &= ~(0x1<<i);
		taskrdy |= (0x1<<i);  //就绪任务	
		
		Sched();
		
	}	
}


void EnterInt(void)
{
	if(IntNestNum<255)
		IntNestNum++;
}

void IntExitSw(void)
{
	if(IntNestNum>0)
		IntNestNum--; 
	if(IntNestNum==0)
		Sched();
}

void Sched(void)
{
	DisInt();
	for(nxttask=0;nxttask<tasknumsize;nxttask++)
	{
		if((taskrdy&(0x1<<nxttask))!=0)//只要寻找到更高优先级的任务就退出
		{
			if(nxttask!=curtask)
			{
				phightask=taskstkptr[nxttask];
				run();
			}
			goto exit;  //当任务切换回自己的任务时,Sched中for循环还没有结束,导致还没执行自己的任务又跳到其他的任务。
		}
	}
exit:
	EnInt();
}

void waitdly(unsigned int dly)
{
	DisInt();
	if(dly!=0)
	{
		taskrdy &= ~(0x1<<curtask);  //挂起任务
		wait[curtask]=dly;
		Sched();
	}
	EnInt();
}

void clkTick(void)
{
	unsigned char t;
	for(t=0;t<tasknumsize;t++)
	{
		if(wait[t]>0)
		{
			wait[t]--;
			if(wait[t]==0)
				taskrdy |= (0x1<<t);  //是任务进入就绪态
		}
	}	
}

void idle(void)
{
	unsigned char i;
	while(1)
	{
		i++;
		delay(100);
		P0 = i;
	}
}

void initBD(void)
{
	LCR=0x83;
	DLM=0x0;
	DLL=0x01;
	LCR=0x03;
	
	IER=0x1;		//使能接收中断
	
	INTMSK=0x00;	//失能中断,bit0->CNT,bit1->USART
}

void TimeOn(void)
{
	INTMSK=0x01;
}

void startTask(void)
{
	create(idle,&idlestk[stksize-1],3);
	phightask=taskstkptr[nxttask];
	start();	
}

int main()
{

	initBD();
	
	pISR_CNT=(unsigned)CNTinterrupt;
	pISR_USART=(unsigned)USARTinterrupt;
	putS("\r\nMy rtos test!!!\n\r");
	putS("Build...\n\rDate: " __DATE__ "\n\rTime:" __TIME__ "\n\r");
	
	semCreate(0,1);
	semCreate(1,1);
	semCreate(2,1);
	
	create(task0,&task0stk[stksize-1],0);
	create(task1,&task1stk[stksize-1],1);
	create(task2,&task2stk[stksize-1],2);
	
	P0=0xaa;P1=0x0a;P2=0x0f;P3=0xf0;

	TimeOn();
	startTask();

	return 0;
}

#define EnableSem 1

void task0(void)
{
	unsigned char a = 0;
	while(1)
	{
		#if EnableSem
		semPending(0);
		semPending(1);
		semPending(2);
		#endif
		putS("task0........................................................\n\r");
		delay(100);
		putS("task0............................................................\n\r");
		delay(100);
		putS("task0................................................................\n\r\n\r");
		#if EnableSem
		semPost(1);
		#endif
		waitdly(8);
		P1 = a++;
	}
}

void task1(void)
{
	unsigned char b = 0;
	while(1)
	{
		#if EnableSem
		semPending(1);
		#endif
		putS("task1........................................................\n\r");
		delay(100);
		putS("task1............................................................\n\r");
		delay(100);
		putS("task1................................................................\n\r\n\r");
		#if EnableSem
		semPost(2);
		#endif
		waitdly(28);
		P2 = b++;
		
	}
}
void task2(void)
{
	unsigned char c = 0;
	while(1)
	{
		#if EnableSem
		semPending(2);
		#endif
		putS("task2........................................................\n\r");
		delay(100);
		putS("task2............................................................\n\r");
		delay(100);
		putS("task2................................................................\n\r\n\r");
		#if EnableSem
		semPost(0);
		semPost(1);
		semPost(2);
		#endif
		delay(800);
		P3 = c++;
		waitdly(10);
	}
}
init.s

_ISR_STARTADDRESS   EQU   0xc03ffff0

INTFLG		EQU 0x80000008
INTMSK		EQU 0x8000000c

CNTINT		EQU 0x80000004

IRQMODE	    EQU	0x12
SVCMODE	    EQU	0x13
MODEMASK    EQU	0x1f
NOINT	    EQU	0xc0

			EXPORT run
			EXPORT start
			IMPORT phightask
			IMPORT taskstkptr
			IMPORT curtask
			IMPORT nxttask
			IMPORT IntNestNum
			IMPORT IntExitSw
			IMPORT EnterInt
			
			IMPORT	|Image$$RO$$Limit|  	; End of ROM code (=start of ROM data)
		    IMPORT	|Image$$RW$$Base|   	; Base of RAM to initialise
		    IMPORT	|Image$$ZI$$Base|   	; Base and limit of area
		    IMPORT	|Image$$ZI$$Limit|  	; to zero initialise

			IMPORT main	
			EXPORT  __ENTRY	
			AREA	Example,CODE,READONLY	; 声明代码段Example 
			ENTRY				; 标识程序入口
			CODE32				; 声明32位ARM指令
__ENTRY			
	    b ResetHandler  ;for debug
	    b HandlerUndef  ;handlerUndef
	    b HandlerSWI    ;SWI interrupt handler
	    b HandlerPabort ;handlerPAbort
	    b HandlerDabort ;handlerDAbort
	    b .		    	;handlerReserved
	    ldr pc,=HandlerIRQ	;这段代码是不能在rom低地址的被执行的
	    b HandlerFIQ

HandlerIRQ
		stmfd   sp!,{r1-r3}
		mov		r1,sp
		add		sp,sp,#3*4
		sub		r2, lr, #4
		mrs		r3,spsr
		msr     cpsr_c, #SVCMODE|NOINT   ;Change to SVC mode
		
		stmfd	sp!,{r2}
		stmfd	sp!,{r4-r12,lr}
		ldmfd	r1,{r4-r6}
		stmfd	sp!,{r4-r6}
		stmfd	sp!,{r0}
		stmfd	sp!,{r3}
		
	    bl 		EnterInt  

		ldr	    r0,=INTMSK
		ldr	    r1,=0x00  ;//关闭中断,防止中断嵌套
		str	    r1,[r0]
		
		msr    cpsr_c,#IRQMODE|NOINT 
		
		ldr	    r9,=INTFLG
		ldr	    r9,[r9]
		mov	    r8,#0x0
0
		movs    r9,r9,lsr #1
		bcs	    %F1
		add	    r8,r8,#4
		b	    %B0
1
		ldr	    r9,=HandleCNT
		add	    r9,r9,r8
		ldr	    r9,[r9]
		cmp		r9, #0
		movne	lr, pc
		movne	pc, r9
		
		msr     cpsr_c,#SVCMODE|NOINT
		
		bl 		IntExitSw
		
2
		ldr	    r0,=INTMSK
		ldr	    r1,=0x01  ;cntr interrupt anable
		str	    r1,[r0]
 					
		ldmfd	sp!, {r0}		;从IRQ返回
		msr		spsr_cxsf, r0
		ldmfd	sp!, {r0-r12,lr,pc}^

ResetHandler
HandlerUndef
HandlerSWI
HandlerPabort
HandlerDabort
HandlerFIQ

		ldr	    r0,=INTMSK
		ldr	    r1,=0x00  ;all interrupt disable
		str	    r1,[r0]

		ldr	    r0,=INTFLG
		ldr	    r1,=0x00  ;clean all interrupt Flag
		str	    r1,[r0]
		
		mrs	    r0,cpsr
    	bic	    r0,r0,#MODEMASK
		orr	    r1,r0,#IRQMODE|NOINT
		msr	    cpsr_cxsf,r1 	    	;IRQMode
		ldr	    sp,=IRQStack

		bic	    r0,r0,#MODEMASK|NOINT
		orr	    r1,r0,#SVCMODE
		msr	    cpsr_cxsf,r1 	    	;SVCMode
		ldr	    sp,=SVCStack

	    LDR	    r0, =0xc0f00000			;必须复制到ram中才能正常执行,不然就会使得RW段与ZI段不正常
	    LDR		r1, =0x0		
	    LDR	    r2, =|Image$$ZI$$Limit|	;注意,此时的Image$$ZI$$Limit为设置的ro_base后的地址值
	    sub		r2,r2,r0				
3
		ldmia	r1!,{r3-r7}
		stmia	r0!,{R3-R7}
		cmp		r1,r2
		bcc		%b3

		ldr		pc,=ram_code
ram_code	
	    LDR	    r0, =|Image$$RO$$Limit|	; Get pointer to ROM data
	    LDR	    r1, =|Image$$RW$$Base|	; and RAM copy
	    LDR	    r3, =|Image$$ZI$$Base|	
	    
;Zero init base => top of initialised data
				
	    CMP	    r0, r1	    			; Check that they are different
	    BEQ	    %F5
4		
	    CMP	    r1, r3	    			; Copy init data
	    LDRCC   r2, [r0], #4    		; --> LDRCC r2, [r0] + ADD r0, r0, #4		 
	    STRCC   r2, [r1], #4    		; --> STRCC r2, [r1] + ADD r1, r1, #4
	    BCC	    %B4
5		
	    LDR	    r1, =|Image$$ZI$$Limit| ; Top of zero init segment
	    MOV	    r2, #0
6		
	    CMP	    r3, r1	    			; Zero init
	    STRCC   r2, [r3], #4
	    BCC	    %B6

		bl main
		b .
start
		ldr		r2,nxttask
		ldr		r1,=curtask
		str		r2,[r1]

		ldr	    r0,=INTMSK
		ldr	    r1,=0x01  ;cntr interrupt enable
		str	    r1,[r0]

		ldr 	sp,phightask
		ldmfd	sp!,{r1}
		msr	    spsr_c,r1	;SVCMode
		ldmfd	sp!, {r0-r12,lr,pc}^
		
run
		stmfd	sp!,{lr}		;pc
		stmfd   sp!,{r0-r12,lr}
		mrs		r0, spsr       	;Push SPSR
		stmfd	sp!,{r0}
		
		mov		r0,sp
		ldr		r1,=taskstkptr
		ldr		r2,curtask
		mov		r2,r2,lsl #2	;r2=curtask*4,taskstkptr一个成员变量占用4字节内存
		add		r1,r1,r2
		str		r0,[r1]
		
		ldr		r2,nxttask
		ldr		r1,=curtask
		str		r2,[r1]
			
		ldr	    r0,=INTMSK
		ldr	    r1,=0x01  ;cntr interrupt enable
		str	    r1,[r0]
		
		ldr 	sp,phightask	;把任务切换前的堆栈指针给sp,让该任务按切换前的函数返回进行原路返回。
		ldmfd	sp!,{r1}
		msr	    spsr_c,r1		;SVCMode		
		ldmfd	sp!, {r0-r12,lr,pc}^
		
	ALIGN

	AREA RamData,DATA,READWRITE

	^	(_ISR_STARTADDRESS-1024*4)
	
SVCStack	#	1024*2				
IRQStack	#	1024*2

	^	_ISR_STARTADDRESS
HandleCNT	#	4
HandleUSART	#	4			
			
			END

效果:


源码下载地址:点击打开链接

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值