Hi!
Now, it is possible to have concurrent rt-tasks with seperated stacks
in uClinux.
In rt_init_app() you just have to call rt_init_task() (and starting
the timer as usual), and within every rt-task, you can call rt_sleep()
to wait until the next timer period occurs.
As the stuff is rather simple, i added the whole
../linux/arch/m68knommu/platform/68328/rt_application.c
so those, who are interressted can have a look at it.
The next step is a full priority scheduler :-)
(but even then, there are still many things missing: FIFOs and
convenient shared memory mechanisms)
BTW: Jeff will supply me with a uCsimm, so that i can play with real
hardware :-)
/* ../linux/arch/m68knommu/platform/68328/rt_application.c , bkuhn/GPL */
#include <asm/system.h>
#include <asm/MC68328.h>
extern int rt_request_irq(unsigned int irq, void (*handler)(void));
extern void rt_free_irq(unsigned int irq);
extern void rt_starttimer(int period);
unsigned long fb_data[160][5];
/* ------------ the following should part of the core ------------ */
#define STACKSIZE 4000
struct rttc {
int stackpointer;
int stack[STACKSIZE];
};
struct rttc rtlinuxtask;
struct rttc *current_task=&rtlinuxtask;
void rt_switch_to_task(struct rttc *new_task) {
__asm__ __volatile__ (
"movem.l %%d0-%%d7/%%a0-%%a6,-(%%sp)\n\t"
"move.l %#1f,-(%%sp)\n\t"
"move.l (%0),%%a1\n\t"
"move.l %%sp,(%%a1)\n\t"
"move.l %1,(%0)\n\t"
"move.l %1,%%a1\n\t"
"move.l (%%a1),%%sp\n\t"
"rts\n\t"
"1: movem.l (%%sp)+,%%d0-%%d7/%%a0-%%a6\n\t"
: : "a" (¤t_task) , "d" (new_task) : "%a1", "memory");
};
#define MAX_TASKS 16
struct rttc *tasklist[MAX_TASKS];
int tasks=0;
void rt_init_task(struct rttc *task,void (*code)(void)) {
task->stack[STACKSIZE-16]=(int) code;
task->stackpointer=(int) &(task->stack[STACKSIZE-16]);
tasklist[tasks++]=task;
};
void rt_wakeup_tasks() {
int i;
for(i=0;i<tasks;i++) {
rt_switch_to_task(tasklist[i]);
};
};
void rt_sleep() {
rt_switch_to_task(&rtlinuxtask);
};
/* ------- the demo begins here --------- */
struct rttc task1,task2,task3;
void task1_code(void) {
while(1) {
fb_data[10][0]--;
rt_sleep();
};
};
void task2_code(void) {
while(1) {
fb_data[10][2]++;
rt_sleep();
};
};
void task3_code(void) {
while(1) {
fb_data[10][4]-=5;
rt_sleep();
};
};
/* rt-handler for timer1 */
void rt_timer_demo(void) {
/* start the concurrent tasks */
rt_wakeup_tasks();
/* don't forget to reset the pending interrupt! */
TSTAT1 &= 0;
};
/* rt-handler for pen */
void rt_pen_demo(void) {
/* just do something */
fb_data[20][2]--;
/* pen-irq doesn't seem to be resetable ? */
};
void rt_init_app(void) {
/* set LCD-Display output area */
LSSA = fb_data;
/* init the concurrent tasks */
rt_init_task(&task1,task1_code);
rt_init_task(&task2,task2_code);
rt_init_task(&task3,task3_code);
/* start timer1 and request handler */
rt_starttimer(10000);
rt_request_irq(TMR1_IRQ_NUM,rt_timer_demo);
/* request handler for pen-interrupt */
rt_request_irq(PEN_IRQ_NUM,rt_pen_demo);
};
--- [rtl] ---
To unsubscribe:
echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
----
For more information on Real-Time Linux see:
http://www.rtlinux.org/~rtlinux/