Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Trying to design a RTOS kernel on 8051 µC

Status
Not open for further replies.

opentdoors

Newbie level 6
Joined
Jan 15, 2005
Messages
12
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
Viet Nam
Activity points
233
8051 kernel

Hello everyones !

I'm a new member on this forum. I come from Vietnam as a electronics engineer.
I've tried to design a RTOS kernels on 89c52 with 8KB ext RAM. It just the way to learn Real-time Linux.

My evalution board consist a 89c52 with 8K RAM (6264) at 0x8000. There are 16 task in my design, each task has a 256 bytes external memory. Example:

-Task 0 with ext mem from 0x8000 to 0x80FF
-Task 1 ---------------------- 0x8100 to 0x81FF
...
-Task 15----------------------0x8F00 to 0x8FFF

So that DPH= task_id OR 80, DPL=0x00 to 0xFF.

Each task has a byte counter. When a Timer interrupt occured, counter of task is decremented one, and if counter of task reach to zero then this task is ready state.
Counter array is placed in internal RAM, ponted by R0. When a task is in running, it will call a Ondelay to reset its counter.

There are two other arrays in internal RAM, semaphore (just binary semaphore) array and event array. When a task is in wait state a semaphore, 8051 CPU also in idle mode until a timer interrupt occured. And when a task is in a wait state a event, it's alway switched to sheduler routine.

Sheduler is a routine based on counter array to change task's id in two variable: running_id and blocke_id, then it call context_switching to save internal stack of blocked task to external memory of that task, and restore stack content for next task. New task will be in running state after "reti ".

Sorry, in next time I'm going to post some source codes written in 8051 asm.

Thanks
 

8051 copy stack

All tasks was defined in program memory like this:

tasktable:

dw task0
dw task1
...
dw task15

With 256 bytes external RAM for each task, I used address from 0x00 for save context.

stack equ 5FH
page equ 80H
xsp equ 0FDH
_createTask: /* acc=task id; R0=task priority */

mov b,a
mov dptr,#tasktable
rl a
inc a
movc a,@a+dptr
push acc
mov a,b
rl a
movc a,@a+dptr
push acc
push psw
push 0
push 1
..
push 7
push acc
push b
push DPH
push DPL

mov a,#page
orl a,b; task_id OR 0x80
mov DPH,a
clr a
mov DPL,a
create_xsp: /*save stack to RAM*/
pop acc
movx @dptr,a
inc dptr
mov a,sp
cjne a,#stack,create_xsp
/*Create TCB */

push DPL; save ext stack
mov a,#xsp
mov DPL,a
pop acc
movx @dptr,a
inc dptr
mov a,R0: task's priority
movx @dptr,a
inc dptr
mov a,DPH
movx @dptr,a
ret

Added after 22 minutes:

Skeleton of tasks can be defined:

task0:
/*Body of task*/
mov a,#counter0
lcall _timeDelay
ajmp task0

task1:
/*Body of task*/
mov a,#counter1
lcall _timeDelay
ajmp task1

....
task15:
/*Body of task*/
mov a,#counter15
lcall _timeDelay
ajmp task15

The _timeDelay function will reset counter of each task. Counter of each task decremented by timer interrupt routine. When counter of task come to zero, this task will be in ready state, if there are two or three .. tasks was in ready state, then task has priority higher come to running state.

If Timer ISR occured every 2ms, then task's counter = #counter_n * 2ms, task will be run every (#counter_n * 2ms). Counter of each task is a WORD variable.
 

c code rtos 8051

xTimeDelay equ 0FBH

_timeDelay:
/*a=counter high byte, R1=counter low byte*/
clr EA; disable interrupts
push DPH
push DPL
push 0
push b

mov b,a
mov a,running_id;running_id is a global variable in internal RAM
mov DPH,a

anl a,#0FH
add a,#taskcounters; taskcounters is address of counter array
mov R0,a; R0 point to address of counter of task running
mov a,#xTimeDelay;address of WORD variable in external RAM
mov DPL,a
mov a,R1
movx @dptr,a
inc dptr
mov a,b
movx @dptr,a

mov @R0,a
pop b
pop 0
pop DPL
pop DPH
setb EA
setb IDL; PCON.0 go to idle mode
ret

Added after 24 minutes:

This is sheduler function, it check counter array to detect which task'counter come to zero to change content in two variable: running_id and suspend_id. Then switching context routine based on these variable to switch.

_sheduler:

clr EA
push psw
push 0
...
push 7
push acc
push b
push DPH
push DPL

mov R2,#0FFh; initial task priority
mov R0,#taskcounters
mov DPH,#page; DPH=0x80
mov R1,#0Fh
mov suspend_id,running_id

_loop:

mov a,@R0
jnz _next
mov a,#priority
mov DPL,a
movx a,@dptr; get task's priority
mov b,a
subb a,R2 ; if a>R2
jnc _next ;
mov R2,b ; els if a<R2 then R2=a
mov a,#task_id
mov DPL,a
movx a,@dptr; get task's id (task_id=id OR 0x80)
mov resume_id,a
_next:
inc R0
inc DPH
djnz R1,_loop

mov running_id,resume_id

/**/

Added after 2 hours:

This context switching routine. This routine copy internal stack ponted by sp register of current task (identified by DPH) to external RAM, and then save content of DPL register to location xsp of 256 byte external RAM.

_contextSwitching:

mov a,suspend_id
mov DPH,a
clr a
mov DPL,a
save_context:
pop acc
movx @dptr,a
inc dptr
mov a,sp
cjne a,#stack,save_context
push DPL
mov a,#xsp
mov DPL,a
pop acc
movx @dptr,a

mov a,resume_id
mov DPH,a
movx a,@dptr; DPL=[xsp]
mov DPL,a
restore_context:
dec dptr
movx a,@dptr
push acc
mov a,DPL
jnz restore_context
pop DPL
pop DPH
pop b
pop acc
pop 7
...
pop 0
pop psw
reti

Added after 22 minutes:

This _timer routine called by TimerISR. When it called, this routine decrement the counters of task by one.

_timer:
push <0,1,dptr,acc,b>
mov R0,#taskcounters
mov R1,#0Fh; loop index
_tloop:
mov a,@R0
jz _tcheck
dec @R0
k1:
inc R0
djnz R1,_tloop
ret
_tcheck:
mov a,R0
subb a,#taskcounters; get id
orl a,#page; task_id=id OR 0x80
mov DPH,a
mov a,#xtimeDelay
mov DPL,a
movx a,@dptr; get high byte
jz k1
dec a
movx @dptr,a
inc dptr
movx a,@dptr; get low byte
mov @R0,a
sjmp k1
 

8051 task

Is there anyone can give me some advise about my design?

I think,that's better development a RTOS on RICS-like µC as AVR or PIC. I'd seen some RTOS for µC 8 bits like Salvo, uCOS-ii, TinyRTX Keil....

Added after 39 minutes:

Here is semaphore processing routines. I create a binary semaphore array called "mutex_buf" in internal RAM pointed by R0 (or R1).

mutex_buf is boolean: zero or non-zero. Each element of mutex_buf assigned a resource like port, memory..
ex:

PORT_sem equ 1H
mov a,#PORT_sem; here semaphore id is PORT_sem, id=0÷15


_semCreate:
/*acc= semaphore's id,R1=initial semaphore value(zero)*/

push 0
mov R0,#mutex_buf
add a,R0
mov R0,a ; R0 point to [mutex_buf +i]
;mov a,R1; may be "clr a"
mov @R0,a; *(mutex_buf)=R1
pop 0

ret

When a task access a shared resource, it'd to wait semphore assigned this resource to take a access- right.
void semWait(UCHAR semaphore_id)
{
while(semaphore_id);
semaphore_id=1;
}

In asm:
_semWait:
/*a=semaphore id*/
clr EA
push 0
mov R0,#mutex_buf
add a,R0
mov a,@R0
jnz _semWaiting
mov @R0,#1
pop 0
setb EA
ret

_semWaiting:
pop 0
setb EA
setb IDL; goto idle mode
sjmp _semWait

_semSignal:
/*a=semaphore id*/
clr EA
push 0
mov R0,#mutex_buf
add a,R0
mov R0,a
mov @R0,#0H
pop 0
setb EA
ret

Thus a task can be written like this, with semaphore created by _semCreate routine above:

_task:
.......
mov a,PORT_sem
lcall _semWait
....processing PORT
lcall _semSignal
.....
mov a,#counter
lcall _timeDelay
ajmp _task
 

difference task and event in rtos

Hi all,

I am G kannan ,here i am designing a scheduler for 8051 (priority based preemption ).

i need one help.i want the design flow of the scheduler and how the context switching occured. Look forward to hear from u.

pls mail me kannan_emb@yahoo.com

Thanks and Regards
kannan
 

how create a rtos

I'm sorry. In previous time, I said that sheduler called when a task in waiting a event state.

But algorithm of my RTOS is round-robin. So that CPU come to idle state when a task waiting a event untill timer interrupt occurred.

Event flag is a byte which its value present 255 difference events. The task which in waiting a event state could be written:

_task:
mov a,#_eventType
lcall _eventWait
/*Processing */
ajmp _task

_eventWait in pseu-do code:
void _eventWait()
{
taskcounters[running_id]=255;
IF (event==_eventType) THEN
event=0;
ELSE goto IDLE_MODE;
}

The content of event variable was set by a other task.
 

when to add wait states for microcontroller?

why not post the flowchart instead of the asm code?
 

    opentdoors

    Points: 2
    Helpful Answer Positive Rating
context switching 8051

thinkey said:
why not post the flowchart instead of the asm code?

Oh, I'm sorry. I'd not enough time to explain by flowchat. I'm quite lazy.

Which part in my code you want me to explain? May be scheduler?

In my system, each task has 2 priority, one of them is the counter of task, play as dynamic priority.
 

scheduling 8051

I think few body will be attracted in asm code
 

design and rtos

I like asm,c ,c++.
and i'm writing a rtos of 52, many thanks to your post.
 

interrupt rtos flow chart

May be asm code difficult to understand than C code. But by writting a kernel by asm code, kernel could trace the value of program counter to control the tasks.

Writting a application in C, using the system call from kernel depend on compiler.
 

movx 8051

you could have posted all of the code in a single file.
whats the need for posting in many post?
hock
 

89s52 rtos

i want to make a RTOS by C language. Its precision is as the program is written by asm language?
 

writing a rtos

elchula said:
i want to make a RTOS by C language. Its precision is as the program is written by asm language?

May be difficult, and size of code getting large for 8051.
 

architecture 8051 kernel

That would be better to understand, for a person like me who is not so good at Assembly, only C makes it all......

Good luck
 

rtos for 8051

I'm tring to design an RTOS i have any problem with interpretation of the asm code in the code over described the task is fissed in a precise number? o can to be modified second the requirements?
 

rtos kernel calls

Jack// ani said:
That would be better to understand, for a person like me who is not so good at Assembly, only C makes it all......

Good luck
Why I used assembler, because 8051 is difference from PIC, AVR... When a task using a system call in C like: createTask ( (void*)*func(void*),priority,*mem...), then memory space for each task in 8051 not same as in AVR/PIC. Thus, writting createTask in 8051-assembler is for 8051 architecture.

All task could use every system calls of kernel like : semaphore, event, interrupt... is the same regardless platform.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top