URL
https://opencores.org/ocsvn/eco32/eco32/trunk
Subversion Repositories eco32
Compare Revisions
- This comparison shows the changes necessary to convert path
/eco32/tags/eco32-0.23/stdalone/twotasks-1/os
- from Rev 101 to Rev 157
- ↔ Reverse comparison
Rev 101 → Rev 157
/Makefile
0,0 → 1,27
BUILD = ../../../build |
|
SRC = start.s main.c end.s |
BIN = twotasks-1.bin |
MAP = twotasks-1.map |
EXO = twotasks-1.exo |
|
all: $(BIN) $(EXO) |
|
run: $(BIN) |
$(BUILD)/bin/sim -i -t 1 -l $(BIN) -a 0x10000 |
|
$(EXO): $(BIN) |
$(BUILD)/bin/bin2exo -S2 0x10000 $(BIN) $(EXO) |
|
$(BIN): $(SRC) task1.dump task2.dump |
$(BUILD)/bin/lcc -A -Wo-kernel \ |
-Wl-m -Wl$(MAP) -o $(BIN) $(SRC) |
|
task1.dump: |
../dump/dump ../task1/task1 task1.dump |
|
task2.dump: |
../dump/dump ../task2/task2 task2.dump |
|
clean: |
rm -f *~ task1.dump task2.dump $(BIN) $(MAP) $(EXO) |
/start.s
0,0 → 1,283
; |
; start.s -- startup code |
; |
|
.import main |
.import task0StkTop |
.import currentStkTop |
.import _ecode |
.import _edata |
.import _ebss |
|
.export _bcode |
.export _bdata |
.export _bbss |
|
.export enable |
.export disable |
.export orMask |
.export andMask |
.export getISR |
.export setISR |
.export startTask |
.export setTLB |
|
.code |
_bcode: |
|
.data |
_bdata: |
|
.bss |
_bbss: |
|
.code |
|
; reset arrives here |
reset: |
j start |
|
; interrupts arrive here |
intrpt: |
j isr |
|
; user TLB misses arrive here |
userMiss: |
j isr |
|
isr: |
add $26,$29,$0 ; sp -> $26 |
add $27,$1,$0 ; $1 -> $27 |
ldw $29,$0,currentStkTop ; setup kernel mode stack |
sub $29,$29,128 ; save registers |
stw $2,$29,8 |
stw $3,$29,12 |
stw $4,$29,16 |
stw $5,$29,20 |
stw $6,$29,24 |
stw $7,$29,28 |
stw $8,$29,32 |
stw $9,$29,36 |
stw $10,$29,40 |
stw $11,$29,44 |
stw $12,$29,48 |
stw $13,$29,52 |
stw $14,$29,56 |
stw $15,$29,60 |
stw $16,$29,64 |
stw $17,$29,68 |
stw $18,$29,72 |
stw $19,$29,76 |
stw $20,$29,80 |
stw $21,$29,84 |
stw $22,$29,88 |
stw $23,$29,92 |
stw $24,$29,96 |
stw $25,$29,100 |
stw $26,$29,116 ; this is the task's sp |
stw $27,$29,4 ; this is the task's $1 |
stw $30,$29,120 ; this is the task's resumption addr |
stw $31,$29,124 |
add $5,$29,$0 ; $5 = pointer to register array |
mvfs $4,0 ; $4 = IRQ number |
slr $4,$4,16 |
and $4,$4,0x1F |
sll $26,$4,2 ; $26 = 4 * IRQ number |
ldw $26,$26,irqsrv ; get addr of service routine |
jalr $26 ; call service routine |
j resume ; resume task if ISR returns |
|
; resume a task |
resume: |
ldw $29,$0,currentStkTop ; setup kernel mode stack |
sub $29,$29,128 ; restore registers |
ldw $2,$29,8 |
ldw $3,$29,12 |
ldw $4,$29,16 |
ldw $5,$29,20 |
ldw $6,$29,24 |
ldw $7,$29,28 |
ldw $8,$29,32 |
ldw $9,$29,36 |
ldw $10,$29,40 |
ldw $11,$29,44 |
ldw $12,$29,48 |
ldw $13,$29,52 |
ldw $14,$29,56 |
ldw $15,$29,60 |
ldw $16,$29,64 |
ldw $17,$29,68 |
ldw $18,$29,72 |
ldw $19,$29,76 |
ldw $20,$29,80 |
ldw $21,$29,84 |
ldw $22,$29,88 |
ldw $23,$29,92 |
ldw $24,$29,96 |
ldw $25,$29,100 |
ldw $26,$29,116 ; this is the task's sp |
ldw $27,$29,4 ; this is the task's $1 |
ldw $30,$29,120 ; this is the task's resumption addr |
ldw $31,$29,124 |
add $1,$27,$0 ; $27 -> $1 |
add $29,$26,$0 ; $26 -> sp |
rfx ; return from exception |
|
start: |
add $8,$0,0xA8003FFF |
add $9,$0,0xC0000000 |
stw $8,$9,0 ; 0xC0000000: j 0xC0010000 |
stw $8,$9,4 ; 0xC0000004: j 0xC0010004 |
stw $8,$9,8 ; 0xC0000008: j 0xC0010008 |
mvfs $8,0 |
or $8,$8,1 << 27 ; let vector point to RAM |
mvts $8,0 |
add $10,$0,_bdata ; copy data segment |
add $8,$0,_edata |
sub $9,$8,$10 |
add $9,$9,_ecode |
j cpytest |
cpyloop: |
ldw $11,$9,0 |
stw $11,$8,0 |
cpytest: |
sub $8,$8,4 |
sub $9,$9,4 |
bgeu $8,$10,cpyloop |
add $8,$0,_bbss ; clear bss |
add $9,$0,_ebss |
j clrtest |
clrloop: |
stw $0,$8,0 |
add $8,$8,4 |
clrtest: |
bltu $8,$9,clrloop |
ldw $29,$0,task0StkTop ; setup kernel mode stack for task 0 |
jal main ; call 'main' |
start1: |
j start1 ; loop |
|
enable: |
mvfs $8,0 |
or $8,$8,1 << 23 |
mvts $8,0 |
jr $31 |
|
disable: |
mvfs $8,0 |
and $8,$8,~(1 << 23) |
mvts $8,0 |
jr $31 |
|
orMask: |
mvfs $8,0 |
and $4,$4,0x0000FFFF ; use lower 16 bits only |
or $8,$8,$4 |
mvts $8,0 |
jr $31 |
|
andMask: |
mvfs $8,0 |
or $4,$4,0xFFFF0000 ; use lower 16 bits only |
and $8,$8,$4 |
mvts $8,0 |
jr $31 |
|
getISR: |
sll $4,$4,2 |
ldw $2,$4,irqsrv |
jr $31 |
|
setISR: |
sll $4,$4,2 |
stw $5,$4,irqsrv |
jr $31 |
|
startTask: |
ldw $29,$0,currentStkTop ; setup kernel mode stack |
sub $29,$29,128 |
stw $0,$29,0 ; preset registers |
stw $0,$29,4 |
stw $0,$29,8 |
stw $0,$29,12 |
stw $0,$29,16 |
stw $0,$29,20 |
stw $0,$29,24 |
stw $0,$29,28 |
stw $0,$29,32 |
stw $0,$29,36 |
stw $0,$29,40 |
stw $0,$29,44 |
stw $0,$29,48 |
stw $0,$29,52 |
stw $0,$29,56 |
stw $0,$29,60 |
stw $0,$29,64 |
stw $0,$29,68 |
stw $0,$29,72 |
stw $0,$29,76 |
stw $0,$29,80 |
stw $0,$29,84 |
stw $0,$29,88 |
stw $0,$29,92 |
stw $0,$29,96 |
stw $0,$29,100 |
stw $0,$29,104 |
stw $0,$29,108 |
stw $0,$29,112 |
add $8,$0,0x80000000 |
stw $8,$29,116 ; sp |
stw $0,$29,120 ; task starts at virtual addr 0 |
stw $0,$29,124 |
mvfs $8,0 |
or $8,$8,1 << 25 ; set previous mode to 'user' |
or $8,$8,1 << 22 ; and enable interrupts |
mvts $8,0 |
j resume |
|
setTLB: |
mvts $4,1 ; set index |
mvts $5,2 ; set entryHi |
mvts $6,3 ; set entryLo |
tbwi ; write TLB entry at index |
jr $31 |
|
.data |
|
; interrupt service routine table |
|
.align 4 |
|
irqsrv: |
.word 0 ; 00: terminal 0 transmitter interrupt |
.word 0 ; 01: terminal 0 receiver interrupt |
.word 0 ; 02: terminal 1 transmitter interrupt |
.word 0 ; 03: terminal 1 receiver interrupt |
.word 0 ; 04: keyboard interrupt |
.word 0 ; 05: unused |
.word 0 ; 06: unused |
.word 0 ; 07: unused |
.word 0 ; 08: disk interrupt |
.word 0 ; 09: unused |
.word 0 ; 10: unused |
.word 0 ; 11: unused |
.word 0 ; 12: unused |
.word 0 ; 13: unused |
.word 0 ; 14: timer 0 interrupt |
.word 0 ; 15: timer 1 interrupt |
.word 0 ; 16: bus timeout exception |
.word 0 ; 17: illegal instruction exception |
.word 0 ; 18: privileged instruction exception |
.word 0 ; 19: divide instruction exception |
.word 0 ; 20: trap instruction exception |
.word 0 ; 21: TLB miss exception |
.word 0 ; 22: TLB write exception |
.word 0 ; 23: TLB invalid exception |
.word 0 ; 24: illegal address exception |
.word 0 ; 25: privileged address exception |
.word 0 ; 26: unused |
.word 0 ; 27: unused |
.word 0 ; 28: unused |
.word 0 ; 29: unused |
.word 0 ; 30: unused |
.word 0 ; 31: unused |
/main.c
0,0 → 1,345
/* |
* main.c -- start the ball rolling |
*/ |
|
|
#include "stdarg.h" |
#include "start.h" |
|
|
/**************************************************************/ |
|
|
int currentTask; |
unsigned int *currentStkTop; |
|
|
/**************************************************************/ |
|
|
unsigned int task0Stack[256]; |
unsigned int *task0StkTop = task0Stack + 256; |
|
|
unsigned char task1Code[] = { |
#include "task1.dump" |
}; |
|
unsigned int task1Stack[256]; |
unsigned int *task1StkTop = task1Stack + 256; |
|
|
unsigned char task2Code[] = { |
#include "task2.dump" |
}; |
|
unsigned int task2Stack[256]; |
unsigned int *task2StkTop = task2Stack + 256; |
|
|
/**************************************************************/ |
|
|
void putchar(char c) { |
unsigned int *base; |
|
if (c == '\n') { |
putchar('\r'); |
} |
base = (unsigned int *) 0xF0300000; |
while ((*(base + 2) & 1) == 0) ; |
*(base + 3) = c; |
} |
|
|
void puts(char *s) { |
char c; |
|
while ((c = *s++) != '\0') { |
putchar(c); |
} |
} |
|
|
void printn(int n) { |
int a; |
|
if (n < 0) { |
putchar('-'); |
n = -n; |
} |
a = n / 10; |
if (a != 0) { |
printn(a); |
} |
putchar(n % 10 + '0'); |
} |
|
|
void printu(unsigned int n, unsigned int b) { |
unsigned int a; |
|
a = n / b; |
if (a != 0) { |
printu(a, b); |
} |
putchar("0123456789ABCDEF"[n % b]); |
} |
|
|
void printf(char *fmt, ...) { |
va_list ap; |
char c; |
int n; |
unsigned int u; |
char *s; |
|
va_start(ap, fmt); |
while (1) { |
while ((c = *fmt++) != '%') { |
if (c == '\0') { |
va_end(ap); |
return; |
} |
putchar(c); |
} |
c = *fmt++; |
if (c == 'd') { |
n = va_arg(ap, int); |
printn(n); |
} else |
if (c == 'u' || c == 'o' || c == 'x') { |
u = va_arg(ap, int); |
printu(u, c == 'o' ? 8 : (c == 'x' ? 16 : 10)); |
} else |
if (c == 's') { |
s = va_arg(ap, char *); |
puts(s); |
} else { |
putchar(c); |
} |
} |
} |
|
|
/**************************************************************/ |
|
|
static char *exceptionCause[32] = { |
/* 00 */ "terminal 0 transmitter interrupt", |
/* 01 */ "terminal 0 receiver interrupt", |
/* 02 */ "terminal 1 transmitter interrupt", |
/* 03 */ "terminal 1 receiver interrupt", |
/* 04 */ "keyboard interrupt", |
/* 05 */ "unknown interrupt", |
/* 06 */ "unknown interrupt", |
/* 07 */ "unknown interrupt", |
/* 08 */ "disk interrupt", |
/* 09 */ "unknown interrupt", |
/* 10 */ "unknown interrupt", |
/* 11 */ "unknown interrupt", |
/* 12 */ "unknown interrupt", |
/* 13 */ "unknown interrupt", |
/* 14 */ "timer 0 interrupt", |
/* 15 */ "timer 1 interrupt", |
/* 16 */ "bus timeout exception", |
/* 17 */ "illegal instruction exception", |
/* 18 */ "privileged instruction exception", |
/* 19 */ "divide instruction exception", |
/* 20 */ "trap instruction exception", |
/* 21 */ "TLB miss exception", |
/* 22 */ "TLB write exception", |
/* 23 */ "TLB invalid exception", |
/* 24 */ "illegal address exception", |
/* 25 */ "privileged address exception", |
/* 26 */ "unknown exception", |
/* 27 */ "unknown exception", |
/* 28 */ "unknown exception", |
/* 29 */ "unknown exception", |
/* 30 */ "unknown exception", |
/* 31 */ "unknown exception" |
}; |
|
|
void defaultISR(int irq, unsigned int *registers) { |
printf("\n%s\n", exceptionCause[irq]); |
} |
|
|
void initInterrupts(void) { |
int i; |
|
for (i = 0; i < 32; i++) { |
setISR(i, defaultISR); |
} |
} |
|
|
/**************************************************************/ |
|
|
unsigned int getNumber(unsigned char *p) { |
return (unsigned int) *(p + 0) << 24 | |
(unsigned int) *(p + 1) << 16 | |
(unsigned int) *(p + 2) << 8 | |
(unsigned int) *(p + 3) << 0; |
} |
|
|
void loadTask(unsigned char *code, |
unsigned int physCodeAddr, |
unsigned int physDataAddr) { |
unsigned int magic; |
unsigned int csize; |
unsigned int dsize; |
unsigned int bsize; |
unsigned char *virtLoadAddr; |
int i; |
|
magic = getNumber(code); |
code += sizeof(unsigned int); |
csize = getNumber(code); |
code += sizeof(unsigned int); |
dsize = getNumber(code); |
code += sizeof(unsigned int); |
bsize = getNumber(code); |
code += sizeof(unsigned int); |
if (magic != 0x1AA09232) { |
printf("Error: Load module is not executable!\n"); |
while (1) ; |
} |
code += 4 * sizeof(unsigned int); |
printf("(csize = 0x%x, dsize = 0x%x, bsize = 0x%x)\n", |
csize, dsize, bsize); |
virtLoadAddr = (unsigned char *) (0xC0000000 | physCodeAddr); |
for (i = 0; i < csize; i++) { |
*virtLoadAddr++ = *code++; |
} |
virtLoadAddr = (unsigned char *) (0xC0000000 | physDataAddr); |
for (i = 0; i < dsize; i++) { |
*virtLoadAddr++ = *code++; |
} |
for (i = 0; i < bsize; i++) { |
*virtLoadAddr++ = '\0'; |
} |
} |
|
|
/**************************************************************/ |
|
|
void trapISR(int irq, unsigned int *registers) { |
/* 'putchar' is the only system call yet */ |
putchar(registers[4]); |
/* skip the trap instruction */ |
registers[30] += 4; |
} |
|
|
/**************************************************************/ |
|
|
void missISR(int irq, unsigned int *registers) { |
if (currentTask == 1) { |
setTLB(5, 0x00000000, 64 << 12 | 0x01); /* code at 256 k */ |
setTLB(27, 0x00001000, 68 << 12 | 0x03); /* data at 272 k */ |
setTLB(22, 0x7FFFF000, 80 << 12 | 0x03); /* user-mode stack at 320 k */ |
} else if (currentTask == 2) { |
setTLB(5, 0x00000000, 96 << 12 | 0x01); /* code at 384 k */ |
setTLB(27, 0x00001000, 100 << 12 | 0x03); /* data at 400 k */ |
setTLB(22, 0x7FFFF000, 112 << 12 | 0x03); /* user-mode stack at 448 k */ |
} |
} |
|
|
void flushTLB(void) { |
unsigned int invalPage; |
int i; |
|
invalPage = 0xC0000000; |
for (i = 0; i < 32; i++) { |
setTLB(i, invalPage, 0); |
invalPage += (1 << 12); |
} |
} |
|
|
/**************************************************************/ |
|
|
void initTimer(void) { |
unsigned int *timerBase; |
|
timerBase = (unsigned int *) 0xF0000000; |
*(timerBase + 1) = 50000000; |
*timerBase = 2; |
orMask(1 << 14); |
} |
|
|
int task1Started = 0; |
int task2Started = 0; |
|
|
void timerISR(int irq, unsigned int *registers) { |
unsigned int *timerBase; |
|
timerBase = (unsigned int *) 0xF0000000; |
*timerBase = 2; |
printf(">|<"); |
if (currentTask == 0) { |
if (!task1Started) { |
/* load & start task1 */ |
printf("\nOS: loading task1\n"); |
loadTask(task1Code, 64 << 12, 68 << 12); |
printf("OS: starting task1\n"); |
task1Started = 1; |
currentTask = 1; |
currentStkTop = task1StkTop; |
flushTLB(); |
startTask(); |
} |
} else if (currentTask == 1) { |
if (!task2Started) { |
/* load & start task2 */ |
printf("\nOS: loading task2\n"); |
loadTask(task2Code, 96 << 12, 100 << 12); |
printf("OS: starting task2\n"); |
task2Started = 1; |
currentTask = 2; |
currentStkTop = task2StkTop; |
flushTLB(); |
startTask(); |
} else { |
/* switch tasks */ |
currentTask = 2; |
currentStkTop = task2StkTop; |
flushTLB(); |
} |
} else if (currentTask == 2) { |
/* switch tasks */ |
currentTask = 1; |
currentStkTop = task1StkTop; |
flushTLB(); |
} |
} |
|
|
/**************************************************************/ |
|
|
void main(void) { |
currentTask = 0; |
currentStkTop = task0StkTop; |
printf("\n"); |
printf("OS: initializing interrupts\n"); |
initInterrupts(); |
setISR(20, trapISR); |
setISR(21, missISR); |
setISR(14, timerISR); |
printf("OS: initializing timer\n"); |
initTimer(); |
printf("OS: waiting for interrupt...\n"); |
enable(); |
while (1) ; |
} |
/start.h
0,0 → 1,23
/* |
* start.h -- startup code |
*/ |
|
|
#ifndef _START_H_ |
#define _START_H_ |
|
|
typedef void (*ISR)(int irq, unsigned int *registers); |
|
|
void enable(void); |
void disable(void); |
void orMask(unsigned int mask); |
void andMask(unsigned int mask); |
ISR getISR(int irq); |
void setISR(int irq, ISR isr); |
void startTask(void); |
void setTLB(int index, unsigned int entryHi, unsigned int entryLo); |
|
|
#endif /* _START_H_ */ |
/end.s
0,0 → 1,19
; |
; end.s -- end-of-segment labels |
; |
|
.export _ecode |
.export _edata |
.export _ebss |
|
.code |
.align 4 |
_ecode: |
|
.data |
.align 4 |
_edata: |
|
.bss |
.align 4 |
_ebss: |
/stdarg.h
0,0 → 1,41
/* |
* stdarg.h -- variable argument lists |
*/ |
|
|
#ifndef _STDARG_H_ |
#define _STDARG_H_ |
|
|
typedef char *va_list; |
|
|
static float __va_arg_tmp; |
|
|
#define va_start(list, start) \ |
((void)((list) = (sizeof(start)<4 ? \ |
(char *)((int *)&(start)+1) : (char *)(&(start)+1)))) |
|
#define __va_arg(list, mode, n) \ |
(__typecode(mode)==1 && sizeof(mode)==4 ? \ |
(__va_arg_tmp = *(double *)(&(list += \ |
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \ |
*(mode *)&__va_arg_tmp) : \ |
*(mode *)(&(list += \ |
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)])) |
|
#define _bigendian_va_arg(list, mode, n) \ |
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \ |
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \ |
__va_arg(list, mode, n)) |
|
#define va_end(list) ((void)0) |
|
#define va_arg(list, mode) \ |
(sizeof(mode)==8 ? \ |
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \ |
_bigendian_va_arg(list, mode, 3U)) |
|
|
#endif /* _STDARG_H_ */ |