Line 66... |
Line 66... |
|
|
void kwrite_audio(TASKP tsk, int dev, int *dst, int len);
|
void kwrite_audio(TASKP tsk, int dev, int *dst, int len);
|
void kwrite_txuart(TASKP tsk, int dev, int *dst, int len);
|
void kwrite_txuart(TASKP tsk, int dev, int *dst, int len);
|
int kpost(TASKP *task, unsigned events, int milliseconds);
|
int kpost(TASKP *task, unsigned events, int milliseconds);
|
TASKP kschedule(int LAST_TASK, TASKP *tasklist, TASKP last);
|
TASKP kschedule(int LAST_TASK, TASKP *tasklist, TASKP last);
|
|
extern TASKP *ksetup(void);
|
|
|
int LAST_TASK;
|
int LAST_TASK;
|
|
|
|
extern int nwritten, nread, nstarts;
|
|
|
void kernel_entry(void) {
|
void kernel_entry(void) {
|
int nheartbeats= 0, tickcount = 0, milliseconds=0, ticks = 0;
|
int nheartbeats= 0, tickcount = 0, milliseconds=0, ticks = 0;
|
int audiostate = 0;
|
int audiostate = 0, buttonstate = 0;
|
TASKP *tasklist, current;
|
TASKP *tasklist, current;
|
int *last_context;
|
int *last_context;
|
IOSPACE *sys = (IOSPACE *)IOADDR;
|
IOSPACE *sys = (IOSPACE *)IOADDR;
|
sys->io_spio = 0x0f0;
|
|
sys->io_timb = 0; // Turn off the watchdog timer
|
|
LAST_TASK = kntasks();
|
|
heap = _top_of_heap;
|
|
|
|
pipedev = sys_malloc(sizeof(KDEVICE));
|
|
pipedev->write = (RWFDFUN)kwrite_syspipe;
|
|
pipedev->read = (RWFDFUN)kread_syspipe;
|
|
pipedev->close = NULL;
|
|
|
|
/*
|
|
txdev = sys_malloc(sizeof(KDEVICE));
|
|
txdev->write = (RWFDFUN)kwrite_txuart;
|
|
txdev->read = (RWFDFUN)kread_syspipe;
|
|
txdev->close = NULL;
|
|
|
|
pwmdev = sys_malloc(sizeof(KDEVICE));
|
|
pwmdev->write = (RWFDFUN)kwrite_audio;
|
|
pwmdev->read = (RWFDFUN)kread_syspipe;
|
|
pwmdev->close = NULL;
|
|
*/
|
|
|
|
txdev = pwmdev = pipedev;
|
|
|
|
rxpipe = new_syspipe(16); //rxpipe->m_wrtask=INTERRUPT_WRITE_TASK;
|
|
txpipe = new_syspipe(16); txpipe->m_rdtask = INTERRUPT_READ_TASK;
|
|
keypipe = new_syspipe(16);
|
|
lcdpipe = new_syspipe(16);
|
|
pwmpipe = new_syspipe(256); pwmpipe->m_rdtask= INTERRUPT_READ_TASK;
|
|
cmdpipe = new_syspipe(16);
|
|
|
|
tasklist = sys_malloc(sizeof(TASKP)*(1+LAST_TASK));
|
|
kinit(tasklist);
|
|
tasklist[LAST_TASK] = new_task(2, idle_task);
|
|
|
|
|
tasklist = ksetup();
|
|
|
// current = tasklist[0];
|
current = tasklist[0];
|
current = tasklist[LAST_TASK];
|
|
restore_context(current->context);
|
restore_context(current->context);
|
last_context = current->context;
|
last_context = current->context;
|
|
|
// Turn all interrupts off, acknowledge all at the same time
|
|
sys->io_pic = 0x7fff7fff;
|
|
unsigned enableset =
|
unsigned enableset =
|
INT_ENABLEV(INT_BUTTON)
|
INT_ENABLEV(INT_BUTTON)
|
|INT_ENABLEV(INT_TIMA)
|
|INT_ENABLEV(INT_TIMA)
|
// |INT_ENABLEV(INT_UARTRX)
|
// |INT_ENABLEV(INT_UARTRX)
|
// |INT_ENABLEV(INT_UARTTX) // Needs to be turned on by driver
|
// |INT_ENABLEV(INT_UARTTX) // Needs to be turned on by driver
|
// |INT_ENABLEV(INT_AUDIO // Needs to be turned on by driver)
|
// |INT_ENABLEV(INT_AUDIO // Needs to be turned on by driver)
|
// |INT_ENABLEV(INT_GPIO)
|
// |INT_ENABLEV(INT_GPIO)
|
// |INT_ENABLEV(INT_TIMB);
|
// |INT_ENABLEV(INT_TIMB);
|
;
|
;
|
// Then selectively turn some of them back on
|
// Then selectively turn some of them back on
|
sys->io_pic = INT_ENABLE | enableset;
|
sys->io_pic = INT_ENABLE | enableset | 0x07fff;
|
|
|
sys->io_tima = CONTEXT_LENGTH | TM_REPEAT;
|
|
|
|
sys->io_spio = 0x0f1;
|
|
if (1) {
|
|
// Reset our wishbone scope for debug later
|
|
SCOPE *scope = (SCOPE *)SCOPEADDR;
|
|
scope->s_control = 12;
|
|
}
|
|
|
|
if (0) {
|
|
// Wait on a button press before starting
|
|
while((sys->io_spio & 0x0f0)==0)
|
|
;
|
|
sys->io_spio = 0xf3;
|
|
for(int i=0; i<0x40000; i++)
|
|
sys->io_spio = ((i>>14)&2)|0x20;
|
|
sys->io_spio = 0xf7;
|
|
}
|
|
sys->io_pic = 0x7fff|INT_ENABLE;
|
|
|
|
do {
|
do {
|
int need_resched = 0, context_has_been_saved, pic;
|
int need_resched = 0, context_has_been_saved, pic;
|
nheartbeats++;
|
nheartbeats++;
|
|
|
if (0) {
|
|
int v = 0xe4, p = sys->io_pic;
|
|
if (p < 0) // LED 4 if interrupts enabled
|
|
v &= ~4;
|
|
if(p & 0x8000) // LED 8 if any already active
|
|
v |= 8;
|
|
sys->io_spio = v;
|
|
}
|
|
|
|
// if (sys->io_timb == 0)
|
|
// sys->io_timb = 1600000000; // CONTEXT_LENGTH;
|
|
// sys->io_timb = (sys->io_tima & 0x7fffffff) + 350;
|
|
// sys->io_spio = 0x0e0;
|
|
zip_rtu();
|
zip_rtu();
|
// sys->io_spio = 0xe2;
|
|
// sys->io_timb = CONTEXT_LENGTH;
|
|
|
|
last_context = current->context;
|
last_context = current->context;
|
context_has_been_saved = 0;
|
context_has_been_saved = 0;
|
pic = sys->io_pic;
|
pic = sys->io_pic;
|
|
|
Line 197... |
Line 129... |
tickcount++;
|
tickcount++;
|
ticks = 0;
|
ticks = 0;
|
sys->io_spio = ((sys->io_spio&1)^1)|0x010;
|
sys->io_spio = ((sys->io_spio&1)^1)|0x010;
|
pic |= SWINT_CLOCK;
|
pic |= SWINT_CLOCK;
|
}
|
}
|
|
if (buttonstate)
|
|
buttonstate--;
|
|
else
|
|
enableset |= INT_ENABLEV(INT_BUTTON);
|
}
|
}
|
//
|
//
|
if (pic&INT_BUTTON) {
|
if (pic&INT_BUTTON) {
|
// Need to turn the button interrupt off
|
// Need to turn the button interrupt off
|
enableset &= ~(INT_ENABLEV(INT_BUTTON));
|
enableset &= ~(INT_ENABLEV(INT_BUTTON));
|
if ((sys->io_spio&0x0f0)==0x030)
|
if ((sys->io_spio&0x0f0)==0x030)
|
kpanic();
|
kpanic();
|
} else // We can turn it back on when the button
|
buttonstate = 3;
|
// is released
|
}
|
enableset |= INT_ENABLEV(INT_BUTTON);
|
|
if (pic & INT_UARTRX) {
|
if (pic & INT_UARTRX) {
|
int v = sys->io_uart;
|
int v = sys->io_uart;
|
|
|
if ((v & (~0x7f))==0) {
|
if ((v & (~0x7f))==0) {
|
kpush_syspipe(rxpipe, v);
|
kpush_syspipe(rxpipe, v);
|
|
|
// Local Echo
|
// Local Echo
|
if (pic & INT_UARTTX)
|
if (pic & INT_UARTTX) {
|
sys->io_uart = v;
|
sys->io_uart = v;
|
|
sys->io_pic = INT_UARTTX;
|
|
pic &= ~INT_UARTTX;
|
|
}
|
}
|
}
|
} if (pic & INT_UARTTX) {
|
} if (pic & INT_UARTTX) {
|
if (kpop_syspipe(txpipe, (int *)&sys->io_uart)==0) {
|
int v;
|
|
if (kpop_syspipe(txpipe, &v)==0) {
|
enableset |= (INT_ENABLEV(INT_UARTTX));
|
enableset |= (INT_ENABLEV(INT_UARTTX));
|
|
sys->io_uart= v;
|
sys->io_pic = INT_UARTTX;
|
sys->io_pic = INT_UARTTX;
|
} else {
|
// if (v == 'W')
|
if (txpipe->m_wrtask)
|
// sys->io_timb = 5;
|
txpipe->m_wrtask->state = SCHED_READY;
|
// 75k was writing the 'e'
|
|
} else
|
enableset &= ~(INT_ENABLEV(INT_UARTTX));
|
enableset &= ~(INT_ENABLEV(INT_UARTTX));
|
}
|
|
} if (audiostate) {
|
} if (audiostate) {
|
if (pic & INT_AUDIO) {
|
if (pic & INT_AUDIO) {
|
int v;
|
int v;
|
// States:
|
// States:
|
// 0 -- not in use
|
// 0 -- not in use
|
Line 241... |
Line 181... |
sys->io_pwm_audio = (audiostate>>2)&0x0ffff;
|
sys->io_pwm_audio = (audiostate>>2)&0x0ffff;
|
audiostate = 1;
|
audiostate = 1;
|
} else if (kpop_syspipe(pwmpipe, &v)==0) {
|
} else if (kpop_syspipe(pwmpipe, &v)==0) {
|
audiostate = (2|(v<<2))&0x03ffff;
|
audiostate = (2|(v<<2))&0x03ffff;
|
sys->io_pwm_audio = (v>>16)&0x0ffff;
|
sys->io_pwm_audio = (v>>16)&0x0ffff;
|
|
nread++;
|
} else {
|
} else {
|
audiostate = 0;
|
audiostate = 0;
|
// Turn the device off
|
// Turn the device off
|
sys->io_pwm_audio = 0x10000;
|
sys->io_pwm_audio = 0x10000;
|
// Turn the interrupts off
|
// Turn the interrupts off
|
Line 253... |
Line 194... |
}
|
}
|
|
|
// This particular interrupt cannot be cleared
|
// This particular interrupt cannot be cleared
|
// until the port has been written to. Hence,
|
// until the port has been written to. Hence,
|
// now that we've written to the port, we clear
|
// now that we've written to the port, we clear
|
// it now.
|
// it now. If it needs retriggering, the port
|
|
// will retrigger itself -- despite being
|
|
// cleared here.
|
sys->io_pic = INT_AUDIO;
|
sys->io_pic = INT_AUDIO;
|
}} else { // if (audiostate == 0)
|
}} else { // if (audiostate == 0)
|
int v;
|
int sample;
|
if (kpop_syspipe(pwmpipe, &v)==0) {
|
if (kpop_syspipe(pwmpipe, &sample)==0) {
|
audiostate = (2|(v<<2))&0x03ffff;
|
nstarts++;
|
sys->io_pwm_audio = 0x310000 | ((v>>16)&0x0ffff);
|
nread++;
|
|
audiostate = (2|(sample<<2))&0x03ffff;
|
|
sys->io_pwm_audio = 0x310000 | ((sample>>16)&0x0ffff);
|
enableset |= (INT_ENABLEV(INT_AUDIO));
|
enableset |= (INT_ENABLEV(INT_AUDIO));
|
sys->io_spio = 0x022;
|
sys->io_spio = 0x022;
|
sys->io_pic = INT_AUDIO;
|
sys->io_pic = INT_AUDIO;
|
} // else sys->io_spio = 0x020;
|
} // else sys->io_spio = 0x020;
|
} milliseconds = kpost(tasklist, pic, milliseconds);
|
} milliseconds = kpost(tasklist, pic, milliseconds);
|
Line 271... |
Line 216... |
// Restart interrupts
|
// Restart interrupts
|
enableset &= (~0x0ffff); // Keep the bottom bits off
|
enableset &= (~0x0ffff); // Keep the bottom bits off
|
sys->io_pic = INT_ENABLE|enableset;
|
sys->io_pic = INT_ENABLE|enableset;
|
} else {
|
} else {
|
sys->io_pic = INT_ENABLE; // Make sure interrupts are on
|
sys->io_pic = INT_ENABLE; // Make sure interrupts are on
|
int v;
|
int sample;
|
|
|
// Check for the beginning of an audio pipe. If the
|
// Check for the beginning of an audio pipe. If the
|
// interrupt is not enabled, we still might need to
|
// interrupt is not enabled, we still might need to
|
// enable it.
|
// enable it.
|
if ((audiostate==0)&&(kpop_syspipe(pwmpipe, &v)==0)) {
|
if ((audiostate==0)&&(kpop_syspipe(pwmpipe, &sample)==0)) {
|
audiostate = (2|(v<<2))&0x03ffff;
|
audiostate = (2|(sample<<2))&0x03ffff;
|
sys->io_pwm_audio = 0x310000 | ((v>>16)&0x0ffff);
|
sys->io_pwm_audio = 0x310000 | ((sample>>16)&0x0ffff);
|
|
sys->io_pic = INT_AUDIO;
|
enableset |= (INT_ENABLEV(INT_AUDIO));
|
enableset |= (INT_ENABLEV(INT_AUDIO));
|
sys->io_spio = 0x022;
|
sys->io_spio = 0x022;
|
|
nstarts++;
|
|
nread++;
|
} // else sys->io_spio = 0x020;
|
} // else sys->io_spio = 0x020;
|
|
|
// Or the beginning of a transmit pipe.
|
// Or the beginning of a transmit pipe.
|
if (pic & INT_UARTTX) {
|
if (pic & INT_UARTTX) {
|
if (kpop_syspipe(txpipe, (int *)&sys->io_uart)==0) {
|
int v;
|
|
if (kpop_syspipe(txpipe, &v)==0) {
|
enableset |= (INT_ENABLEV(INT_UARTTX));
|
enableset |= (INT_ENABLEV(INT_UARTTX));
|
|
sys->io_uart = v;
|
sys->io_pic = INT_UARTTX;
|
sys->io_pic = INT_UARTTX;
|
} else {
|
// if (v == 'W')
|
if (txpipe->m_wrtask)
|
// sys->io_timb = 5;
|
txpipe->m_wrtask = SCHED_READY;
|
} else
|
enableset &= ~(INT_ENABLEV(INT_UARTTX));
|
enableset &= ~(INT_ENABLEV(INT_UARTTX));
|
}
|
}
|
}
|
|
|
|
// What if the interrupt bit for the buttons is off?
|
|
if ((sys->io_spio & 0x0f0)==0)
|
|
enableset |= INT_ENABLEV(INT_BUTTON);
|
|
|
|
// What if someone left interrupts off?
|
// What if someone left interrupts off?
|
// This might happen as part of a wait trap call, such
|
// This might happen as part of a wait trap call, such
|
// as syspipe() accomplishes within uwrite_syspipe()
|
// as syspipe() accomplishes within uwrite_syspipe()
|
// (We also might've just turned them off ... ooops)
|
// (We also might've just turned them off ... ooops)
|
Line 501... |
Line 446... |
tasklist[i]->waitsig = 0;
|
tasklist[i]->waitsig = 0;
|
}
|
}
|
} return milliseconds;
|
} return milliseconds;
|
}
|
}
|
|
|
void kuserexit(int a) {
|
|
syscall(TRAPID_EXIT, a, 0, 0);
|
|
}
|
|
|
|
void *sys_malloc(int sz) {
|
|
{
|
|
SCOPE *s = (SCOPE *)SCOPEADDR;
|
|
s->s_control = TRIGGER_SCOPE_NOW | (s->s_control & 0x0ffff);
|
|
}
|
|
|
|
void *res = heap;
|
|
heap += sz;
|
|
if ((int)heap > ((int)&res)-32) {
|
|
IOSPACE *sys = (IOSPACE *)IOADDR;
|
|
sys->io_spio = 0xf3;
|
|
asm("break 0");
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
// This won't work. Once we apply an rtu(), there will be an immediate
|
|
// interrupt before the task has had a chance to fill in a first value. By
|
|
// instead waiting until the task comes back from it's first task swap, perhaps
|
|
// having stalled it's pipe, then we can get our interrupt up and running.
|
|
// Not only that, but at that time we'll have plenty of info to stuff into the
|
|
// interrupt as well.
|
|
void kwrite_audio(TASKP tsk, int dev, int *dst, int len) {
|
|
kwrite_syspipe(tsk,dev,dst,len);
|
|
if (tsk->context[15] == (int)uwrite_syspipe) {
|
|
IOSPACE *io = (IOSPACE *)IOADDR;
|
|
// Turn our audio interrupt on.
|
|
io->pic = INT_ENABLEV(INT_AUDIO);
|
|
}
|
|
}
|
|
|
|
void kwrite_txuart(TASKP tsk, int dev, int *dst, int len) {
|
|
kwrite_syspipe(tsk,dev,dst,len);
|
|
if (tsk->context[15] == (int)uwrite_syspipe) {
|
|
IOSPACE *io = (IOSPACE *)IOADDR;
|
|
// Turn our UART transmit interrupt on.
|
|
io->pic = INT_ENABLEV(INT_UARTTX);
|
|
}
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|