OpenCores
URL https://opencores.org/ocsvn/s6soc/s6soc/trunk

Subversion Repositories s6soc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /s6soc/trunk/sw/zipos
    from Rev 27 to Rev 29
    Reverse comparison

Rev 27 → Rev 29

/cmodram.ld
58,7 → 58,7
obj-zip/keypad.o(.text)
obj-zip/display.o(.text)
obj-zip/rtcsim.o(.text)
*(.rodata) *(.strings)
*(.rodata*) *(.strings)
load_image_start = . ;
} > flash
.ramcode : {
/doorbell.c
4,7 → 4,16
//
// Project: CMod S6 System on a Chip, ZipCPU demonstration project
//
// Purpose:
// Purpose: This is the user program, or perhaps more appropriately
// user program(s), associated with running the ZipOS on the
// CMod-S6. To run within the ZipOS, a user program must implement
// two functions: kntasks() and kinit(TASKP *). The first one is simple.
// it simply returns the number of tasks the kernel needs to allocate
// space for. The second routine needs to allocate space for each task,
// set up any file descriptors associated with (each) task, and identify
// the entry point of each task. These are the only two routines
// associated with user tasks called from kernel space. Examples of each
// are found within here.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
47,6 → 56,7
 
#include "../dev/display.h"
#include "../dev/rtcsim.h"
#include "../dev/keypad.h"
 
/* Our system will need some pipes to handle ... life. How about these:
*
58,9 → 68,8
* lcdpipe - write()s to this pipe write to the LCD display SPI port
* pwmpipe - write()s to this pipe will send values to the audio port
* Interrupt consumed
* cmdpipe - written to by the user command task, read by the display task
* used to communicate menu status
*
* These pipes are allocated within the kernel setup function, ksetup().
*/
 
/* We'll need some tasks as well:
108,6 → 117,15
*/
// #define KEYPAD_TASK keypad_task_id
/*
* Read from the keypad, and set up a series of menu screens on the Display,
* so that we can:
*
* 1. Set time
* 2. Set dawn
* 3. Set dusk
*/
#define MENU_TASK menu_task_id
/*
* Maintain a realtime clock
*/
#define RTCCLOCK_TASK rtccclock_task_id
122,12 → 140,6
*/
#define DOORBELL_TASK doorbell_task_id
 
/*
* Interract with any user commands, such as setting the clock, setting
* nighttime (when the lights turn on) or setting daytime when only the
* doorbell rings.
*/
// #define COMMAND_TASK command_task_id
#define LAST_TASK last_task_id
 
typedef enum {
139,8 → 151,11
DOORBELL_TASK, DISPLAY_TASK,
#endif
#endif
#ifdef KEYPAD_TASK
KEYPAD_TASK,
//#ifdef KEYPAD_TASK
//KEYPAD_TASK,
//#endif
#ifdef MENU_TASK
MENU_TASK,
#endif
#ifdef COMMAND_TASK
COMMAND_TASK,
153,7 → 168,7
doorbell_task(void),
display_task(void),
keypad_task(void),
command_task(void);
menu_task(void);
// idle_task ... is accomplished within the kernel
extern void restore_context(int *), save_context(int *);
extern SYSPIPE *rxpipe, *txpipe, *pwmpipe, *lcdpipe;
171,43 → 186,42
#ifdef DOORBELL_TASK
#ifdef DISPLAY_TASK
// 13 + 10 +9(uwrite)+4(uarthex)+2(uartstr)+2(uartchr)
tasklist[DOORBELL_TASK] = new_task(64, doorbell_task);
tasklist[DOORBELL_TASK]->fd[FILENO_STDOUT] = sys_malloc(sizeof(KFILDES));
tasklist[DOORBELL_TASK]->fd[FILENO_STDOUT]->id = (int)lcdpipe;
tasklist[DOORBELL_TASK]->fd[FILENO_STDOUT]->dev= pipedev;
tasklist[DOORBELL_TASK]->fd[FILENO_STDERR] = sys_malloc(sizeof(KFILDES));
tasklist[DOORBELL_TASK]->fd[FILENO_STDERR]->id = (int)txpipe;
tasklist[DOORBELL_TASK]->fd[FILENO_STDERR]->dev= pipedev;
tasklist[DOORBELL_TASK]->fd[FILENO_AUX] = sys_malloc(sizeof(KFILDES));
tasklist[DOORBELL_TASK]->fd[FILENO_AUX]->id = (int)pwmpipe;
tasklist[DOORBELL_TASK]->fd[FILENO_AUX]->dev= pipedev;
tasklist[DOORBELL_TASK] = new_task(96, doorbell_task);
// tasklist[DOORBELL_TASK]->fd[FILENO_STDOUT]= kopen((int)lcdpipe,pipedev);
tasklist[DOORBELL_TASK]->fd[FILENO_STDERR]= kopen((int)txpipe, pipedev);
tasklist[DOORBELL_TASK]->fd[FILENO_AUX] = kopen((int)pwmpipe, pipedev);
 
//
tasklist[DISPLAY_TASK] = new_task(32, display_task);
tasklist[DISPLAY_TASK]->fd[FILENO_STDIN] = sys_malloc(sizeof(KFILDES));
tasklist[DISPLAY_TASK]->fd[FILENO_STDIN]->id = (int)lcdpipe;
tasklist[DISPLAY_TASK]->fd[FILENO_STDIN]->dev= pipedev;
tasklist[DISPLAY_TASK]->fd[FILENO_STDIN] = kopen((int)lcdpipe,pipedev);
#endif
#endif
 
 
#ifdef KEYPAD_TASK
tasklist[KEYPAD_TASK] = new_task(16, keypad_task);
tasklist[KEYPAD_TASK]->fd[FILENO_STDOUT] = sys_malloc(sizeof(KFILDES));
tasklist[NMEA_TASK]->fd[FILENO_STDOUT]->id = (int)keypipe;
tasklist[NMEA_TASK]->fd[FILENO_STDOUT]->dev= pipedev;
// Stack = 7 + 9(uwrite) + 2*4
tasklist[KEYPAD_TASK] = new_task(32, keypad_task);
tasklist[KEYPAD_TASK]->fd[FILENO_STDOUT] = kopen((int)keypipe,pipedev);
#endif
#ifdef MENU_TASK
// Stack = 18 + 10(showbell/shownow) + 9(uwrite) + 2(menu_readkey)
// + 18 (time_menu/dawn_menu/dusk_menu)
tasklist[MENU_TASK] = new_task(72, menu_task);
// tasklist[MENU_TASK]->fd[FILENO_STDIN] = kopen((int)keypipe,pipedev);
tasklist[MENU_TASK]->fd[FILENO_STDOUT]= kopen((int)lcdpipe,pipedev);
tasklist[MENU_TASK]->fd[FILENO_STDERR]= kopen((int)txpipe, pipedev);
#endif
}
 
#ifdef DOORBELL_TASK
// #define HALF_HOUR_S 1800 // Seconds per half hour
// #define HALF_HOUR_S 180 // Seconds per three minutes--for test
#define HALF_HOUR_S 30 // 3 Mins is to long, here's 3 seconds
 
#include "../dev/samples.c"
 
#ifdef MENU_TASK
unsigned dawn = 0x060000, dusk = 0x180000;
#else
const unsigned dawn = 0x060000, dusk = 0x180000;
int nwritten = 0, nread = 0, nstarts = 0;
#endif
 
void shownow(unsigned now) { // Uses 10 stack slots + 8 for write()
char dmsg[9];
252,14 → 266,6
write(FILENO_STDOUT, dmsg, 9);
}
 
void belllight(unsigned now) {
IOSPACE *sys = (IOSPACE *)IOADDR;
if ((now < dawn)||(now > dusk))
sys->io_spio = 0x088; // Turn our light on
else
sys->io_spio = 0x80; // Turn light off
}
 
void uartchr(char v) {
if (write(FILENO_STDERR, &v, 1) != 1)
write(FILENO_STDERR, "APPLE-PANIC", 11);
282,9 → 288,20
else
ch += '0';
uartchr(ch);
} uartstr("\r\n\0");
} uartstr("\r\n");
}
 
#ifdef DOORBELL_TASK
#include "../dev/samples.c"
 
void belllight(unsigned now) {
IOSPACE *sys = (IOSPACE *)IOADDR;
if ((now < dawn)||(now > dusk))
sys->io_spio = 0x088; // Turn our light on
else
sys->io_spio = 0x80; // Turn light off
}
 
void doorbell_task(void) {
// Controls LED 0x08
 
293,21 → 310,25
// write(KFD_STDOUT, disp_build_gtlogo, sizeof(disp_build_gtlogo));
// write(KFD_STDOUT, disp_reset_data, sizeof(disp_reset_data));
// write(KFD_STDOUT, disp_gtech_data, sizeof(disp_gtech_data));
 
IOSPACE *sys = (IOSPACE *)IOADDR;
 
while(1) {
nread = nwritten = 0;
int event;
// Initial state: doorbell is not ringing. In this state, we
// can wait forever for an event
sys->io_spio = 0x080; // Turn our light off
event = wait(INT_BUTTON|SWINT_PPS,-1);
 
#ifndef MENU_TASK
unsigned when = rtcclock;
if (event & INT_BUTTON)
showbell(when);
else if (event & SWINT_PPS)
shownow(when);
#else
if (event & INT_BUTTON)
post(SWINT_DOORBELL);
#endif
 
while(event & INT_BUTTON) {
// Next state, the button has been pressed, the
326,17 → 347,9
if (len > 256)
len = 256;
 
/*
while(len > 64) {
write(FILENO_AUX, sptr, 64);
sptr += 64;
len -= 64;
}*/
 
// We will stall here, if the audio FIFO is full
write(FILENO_AUX, sptr, len);
sptr += len;
nwritten += len;
 
// If the user presses the button more than
// once, we start the sound over as well as
343,21 → 356,25
// our light counter.
event = wait(INT_BUTTON|SWINT_PPS, 0);
if (event&INT_BUTTON) {
if (sptr > &sound_data[2048]) {
if (sptr > &sound_data[1024]) {
sptr = sound_data;
seconds = 0;
#ifndef MENU_TASK
when = (volatile unsigned)rtcclock;
showbell(when);
#else
post(SWINT_DOORBELL);
#endif
}
} else if (event&SWINT_PPS) {
seconds++;
belllight(rtcclock);
#ifndef MENU_TASK
showbell(when);
#endif
}
}
 
uartchr('D');
// Next state: the doorbell is no longer ringing, but
// we have yet to return to normal--the light is still
// on.
365,32 → 382,279
(((event=wait(INT_BUTTON|SWINT_PPS,-1))&INT_BUTTON)==0)) {
seconds++;
belllight(rtcclock);
#ifndef MENU_TASK
showbell(when);
#endif
}
if (event&INT_BUTTON) {
#ifndef MENU_TASK
when = (volatile unsigned)rtcclock;
showbell(when);
uartchr('B');
#endif
}
}
 
// uartstr("\r\n");
uartstr("\r\nNWritten: "); uarthex(nwritten);
uartstr("NRead : "); uarthex(nread);
uartstr("NStarts : "); uarthex(nstarts);
nwritten = nread = nstarts = 0;
}
}
#endif
 
#ifdef MENU_TASK
void entered_menu_str(char *str, unsigned now,int pos) {
//
// Set current time
// xx:xx:xx
//
str[0] = PACK(0x1b, '[', '1',';');
str[1] = PACK('0','H',' ',' ');
str[2] = PACK(' ','x','x',':');
str[3] = PACK('x','x',' ',' ');
//str[3]=PACK('x','x',':','x');
str[4] = PACK(' ','\0','\0','\0');
 
if (pos>0) {
int ch = ((now >> 20)&0x0f)+'0';
str[2] &= ~0x0ff0000;
str[2] |= (ch<<16);
 
/*
if (pos > 1) {
int ch = ((now >> 16)&0x0f)+'0';
str[2] &= ~0x0ff00;
str[2] |= (ch<<8);
 
if (pos > 2) {
int ch = ((now >> 12)&0x0f)+'0';
str[3] &= ~0xff000000;
str[3] |= (ch<<24);
 
NWritten: 000018E7
NRead : 000018E7
NStarts : 00000001
if (pos > 3) {
int ch = ((now >> 8)&0x0f)+'0';
str[3] &= ~0x0ff0000;
str[3] |= (ch<<16);
 
if (pos > 4) {
int ch = ((now >> 4)&0x0f)+'0';
str[3] &= ~0x0ff00;
str[3] |= ':'<<8;
str[3] &= ~0x0ff;
str[3] |= (ch);
 
*/
if (pos > 5)
ch = (now&0x0f)+'0';
else
ch = 'x';
str[4] &= ~0x0ff000000;
str[4] |= (ch<<24);
}}}}}
}
 
void show_time_menu(unsigned when, int posn) {
char dmsg[10];
dmsg[0] = PACK(0x1b,'[','j','S');
dmsg[1] = PACK('e','t',' ','c');
dmsg[2] = PACK('u','r','r','e');
dmsg[3] = PACK('n','t',' ','t');
dmsg[4] = PACK('i','m','e',':');
entered_menu_str(&dmsg[5], when, posn);
write(FILENO_STDOUT, dmsg, 9);
}
 
void show_dawn_menu(unsigned when, int posn) {
char dmsg[10];
dmsg[0] = PACK(0x1b,'[','j','S');
dmsg[1] = PACK('e','t',' ','s');
dmsg[2] = PACK('u','n','r','i');
dmsg[3] = PACK('s','e',':','\0');
entered_menu_str(&dmsg[4], when, posn);
write(FILENO_STDOUT, dmsg, 8);
}
 
void show_dusk_menu(unsigned when, int posn) {
char dmsg[10];
dmsg[0] = PACK(0x1b,'[','j','S');
dmsg[1] = PACK('e','t',' ','s');
dmsg[2] = PACK('u','n','s','e');
dmsg[3] = PACK('t',':','\0','\0');
entered_menu_str(&dmsg[4], when, posn);
write(FILENO_STDOUT, dmsg, 8);
}
 
int menu_readkey(void) {
int key;
wait(0,3);
key = keypadread();
keypad_wait_for_release();
clear(INT_KEYPAD);
return key;
}
 
void time_menu(void) {
int timeout = 60;
unsigned newclock = 0;
for(int p=0; p<6; p++) {
int key, event;
show_time_menu(newclock, p);
do {
event = wait(SWINT_PPS|INT_KEYPAD,-1);
if (event&SWINT_PPS) {
timeout--;
if (timeout == 0)
return;
} if (event&INT_KEYPAD) {
timeout = 60;
key = menu_readkey();
if ((key >= 0)&&(key < 10)) {
int sh;
sh = (5-p)*4;
newclock &= ~(0x0f<<sh);
newclock |= (key<<sh);
} else if (key == 12) {
if (p>=0)
p--;
} else {
if (p > 4)
break;
else
return;
}
}
} while(0==(event&INT_KEYPAD));
}
 
clear(SWINT_PPS);
rtcclock = newclock;
if (wait(SWINT_PPS, 1))
rtcclock = newclock;
}
 
void dawn_menu(void) {
int timeout = 60;
unsigned newdawn = 0;
for(int p=0; p<6; p++) {
int key, event;
show_dawn_menu(newdawn, p);
do {
event = wait(SWINT_PPS|INT_KEYPAD,-1);
if (event&SWINT_PPS) {
timeout--;
if (timeout == 0)
return;
} if (event&INT_KEYPAD) {
timeout = 60;
key = menu_readkey();
if ((key >= 0)&&(key < 10)) {
int sh = (5-p)*4;
newdawn &= ~(0x0f<<sh);
newdawn |= key<<sh;
} else if (key == 12) {
if (p>=0)
p--;
} else {
if (p > 4)
break;
else
return;
}
}
} while(0 == (event&INT_KEYPAD));
} dawn = newdawn;
}
 
void dusk_menu(void) {
int timeout = 60;
unsigned newdusk = 0;
for(int p=0; p<6; p++) {
int key, event;
show_dusk_menu(newdusk, p);
do {
event = wait(SWINT_PPS|INT_KEYPAD,-1);
if (event&SWINT_PPS) {
timeout--;
if (timeout == 0)
return;
} if (event&INT_KEYPAD) {
key = menu_readkey();
if ((key >= 0)&&(key < 10)) {
int sh = (5-p)*4;
newdusk &= ~(0x0f<<sh);
newdusk |= key<<sh;
} else if (key == 12) {
if (p>=0)
p--;
} else {
if (p > 4)
break;
else
return;
}
}
} while(0 == (event&INT_KEYPAD));
} dusk = newdusk;
}
 
void unknown_menu(void) {
// 0123456789ABCDEF
// Unknown Cmd Key
// A/Tm B/Dwn C/Dsk
char dmsg[11];
dmsg[0] = PACK(0x1b,'[','j','U');
dmsg[1] = PACK('n','k','n','o');
dmsg[2] = PACK('w','n',' ','C');
dmsg[3] = PACK('m','d',' ','K');
dmsg[4] = PACK('e','y','\0','\0');
dmsg[5] = PACK(0x1b,'[','1',';');
dmsg[6] = PACK('0','H','A','/');
dmsg[7] = PACK('T','m',' ','B');
dmsg[8] = PACK('/','D','w','n');
dmsg[9] = PACK(' ','C','/','D');
dmsg[10] = PACK('s','k',0,0);
write(FILENO_STDOUT, dmsg, 11);
}
void menu_task(void) {
// Controls LED 0x08
 
// Start by initializing the display to GT Gisselquist\nTechnology
// write(KFD_STDOUT, disp_build_backslash,sizeof(disp_build_backslash));
// write(KFD_STDOUT, disp_build_gtlogo, sizeof(disp_build_gtlogo));
// write(KFD_STDOUT, disp_reset_data, sizeof(disp_reset_data));
// write(KFD_STDOUT, disp_gtech_data, sizeof(disp_gtech_data));
IOSPACE *sys = (IOSPACE *)IOADDR;
unsigned belltime = 0, when;
 
 
when = rtcclock;
while(1) {
int event;
// Initial state: doorbell is not ringing. In this state, we
// can wait forever for an event
sys->io_spio = 0x080; // Turn our light off
event = wait(SWINT_DOORBELL|SWINT_PPS|INT_KEYPAD,-1);
if (event & SWINT_DOORBELL) {
showbell(when);
belltime = time();
} else if (event & SWINT_PPS) {
unsigned now = time();
if ((now-belltime)<HALF_HOUR_S)
showbell(when);
else {
when = rtcclock;
shownow(when);
}
}
 
if (event & INT_KEYPAD) {
int key;
key = menu_readkey();
switch(key) {
case 10: time_menu();
when = rtcclock;
break;
case 11: dawn_menu(); break;
case 12: dusk_menu(); break;
default:
unknown_menu();
wait(0,3000);
} clear(INT_KEYPAD);
}
}
}
#endif
 
/swint.h
50,5 → 50,6
#define SWINT_PPD 0x020000
#define SWINT_ALARM 0x040000
#define SWINT_CLOCK 0x080000
#define SWINT_DOORBELL 0x100000
 
#endif
/ksetup.c
6,7 → 6,7
//
// Purpose: These are the routines from kernel.c that didn't need to be
// in RAM memory. They are specifically the pre-run setup
// routines.
// routines that are executed from FLASH memory.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
58,6 → 58,7
 
int LAST_TASK;
 
__attribute__((cold))
TASKP *ksetup(void) {
TASKP *tasklist;
IOSPACE *sys = (IOSPACE *)IOADDR;
78,7 → 79,7
txpipe = new_syspipe(8); txpipe->m_rdtask = INTERRUPT_READ_TASK;
keypipe = new_syspipe(16);
lcdpipe = new_syspipe(16);
pwmpipe = new_syspipe(256); pwmpipe->m_rdtask= INTERRUPT_READ_TASK;
pwmpipe = new_syspipe(128); pwmpipe->m_rdtask= INTERRUPT_READ_TASK;
cmdpipe = new_syspipe(16);
 
tasklist = sys_malloc(sizeof(TASKP)*(1+LAST_TASK));
112,12 → 113,14
sys->io_spio = 0x0f7;
}
 
// __attribute__((noreturn))
void kuserexit(int a) {
syscall(TRAPID_EXIT, a, 0, 0);
}
 
__attribute__((malloc))
void *sys_malloc(int sz) {
{
if (0) {
SCOPE *s = (SCOPE *)SCOPEADDR;
s->s_control = TRIGGER_SCOPE_NOW | (s->s_control & 0x0ffff);
}
132,3 → 135,9
return res;
}
 
KFILDES *kopen(int id, KDEVICE *dev) {
KFILDES *fd = (KFILDES *)sys_malloc(sizeof(KFILDES));
fd->id = (int)id;
fd->dev= dev;
return fd;
}
/kernel.c
72,8 → 72,6
 
int LAST_TASK;
 
extern int nwritten, nread, nstarts;
 
void kernel_entry(void) {
int nheartbeats= 0, tickcount = 0, milliseconds=0, ticks = 0;
int audiostate = 0, buttonstate = 0;
183,7 → 181,6
} else if (kpop_syspipe(pwmpipe, &v)==0) {
audiostate = (2|(v<<2))&0x03ffff;
sys->io_pwm_audio = (v>>16)&0x0ffff;
nread++;
} else {
audiostate = 0;
// Turn the device off
203,8 → 200,6
}} else { // if (audiostate == 0)
int sample;
if (kpop_syspipe(pwmpipe, &sample)==0) {
nstarts++;
nread++;
audiostate = (2|(sample<<2))&0x03ffff;
sys->io_pwm_audio = 0x310000 | ((sample>>16)&0x0ffff);
enableset |= (INT_ENABLEV(INT_AUDIO));
211,7 → 206,8
sys->io_spio = 0x022;
sys->io_pic = INT_AUDIO;
} // else sys->io_spio = 0x020;
} milliseconds = kpost(tasklist, pic, milliseconds);
}
milliseconds = kpost(tasklist, pic, milliseconds);
 
// Restart interrupts
enableset &= (~0x0ffff); // Keep the bottom bits off
229,8 → 225,6
sys->io_pic = INT_AUDIO;
enableset |= (INT_ENABLEV(INT_AUDIO));
sys->io_spio = 0x022;
nstarts++;
nread++;
} // else sys->io_spio = 0x020;
 
// Or the beginning of a transmit pipe.
326,10 → 320,11
else { kpanic(); zip_halt(); }
if ((!fd)||(!fd->dev))
last_context[1] = -EBADF;
else
else {
fd->dev->write(current, fd->id,
(void *)last_context[3], last_context[4]);
} break;
}}
break;
case TRAPID_TIME:
last_context[1] = tickcount;
break;
392,11 → 387,12
}
 
// Now let's see if we can find the next ready task to run
for(; nxtid<LAST_TASK; nxtid++)
for(; nxtid<LAST_TASK; nxtid++) {
if (tasklist[nxtid]->state == SCHED_READY) {
current=tasklist[nxtid];
break;
}
}
// The last task (the idle task) doesn't count
if (nxtid >= LAST_TASK) {
nxtid = 0; // Don't automatically run idle task
406,8 → 402,7
}
// Now we stop at the idle task, if nothing else is ready
current = tasklist[nxtid];
}
return current;
} return current;
}
 
int kpost(TASKP *tasklist, unsigned events, int milliseconds) {
/kfildes.h
68,4 → 68,6
#define NULL (void *)0
#endif
 
KFILDES *kopen(int id, KDEVICE *dev);
 
#endif
/Makefile
73,6 → 73,9
$(OBJDIR)/%.s: %.c
$(CC) -S $(CFLAGS) -c $< -o $@
 
$(OBJDIR)/%.s: ../dev/%.c
$(CC) -S $(CFLAGS) -c $< -o $@
 
$(OBJDIR)/resetdump.o: resetdump.s
$(AS) $^ -o $@
 

powered by: WebSVN 2.1.0

© copyright 1999-2023 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.