void gptimer1_handler(int id) { uint32_t irq = reg32r(GPTIMER1_BASE, GPT_TISR); { static int blink = 0; if (blink & (1<<2)) { LEDS_OFF(LED0); LEDS_ON(LED1); } else { LEDS_ON(LED0); LEDS_OFF(LED1); } blink++; } // check for overflow int if (irq & OVF_IT_FLAG) { Remove(&thistask->Node); AddTail(&tasks, &thistask->Node); thistask = (struct task *)tasks.Head; irq_new_task(tcb_to_sp(&thistask->tcb)); } // clear ints reg32w(GPTIMER1_BASE, GPT_TISR, ~0); }
static RETURN_CODE writeSerial(Driver_t *self, void *message) { char *tmp = message; while (*tmp){ while ((reg32r(UART3_BASE,LSR_REG) & 0x20) == 0); reg32w(UART3_BASE,0,(*tmp++)); } return SUCCESS; }
void int_handler_function(void) { int irq = reg32r(GPTIMER1_BASE, GPT_TISR); if (irq & OVF_IT_FLAG) { // console_put_char('#'); tick_handler_function(); // console_put_char('@'); } reg32w(GPTIMER1_BASE, GPT_TISR, ~0); }
// DSS IRQ handler (irq 25) // Is also invoked for DSI interrupts void dispc_handler(int id) { uint32_t dssirq = reg32r(DSS_BASE, DSS_IRQSTATUS); { static int blink = 0; if (blink & (1<<6)) { LEDS_OFF(LED0); LEDS_ON(LED1); } else { LEDS_ON(LED0); LEDS_OFF(LED1); } blink++; } // see if we have any dispc interrupts if (dssirq & DSS_DISPC_IRQ) { uint32_t irqstatus = reg32r(DISPC_BASE, DISPC_IRQSTATUS); if (1 && (irqstatus & DISPC_VSYNC)) { // we do nothing special, just round-robin all tasks at every jiffy Remove(&thistask->Node); AddTail(&tasks, &thistask->Node); thistask = (struct task *)tasks.Head; irq_new_task(tcb_to_sp(&thistask->tcb)); } // we handle no other interrrupts, so clear all interrupt status bits if any set reg32w(DISPC_BASE, DISPC_IRQSTATUS, irqstatus); } // check for dsi ints (to clear them) if (dssirq & DSS_DSI_IRQ) { // not expecting this, just clear everything reg32w(DSI_BASE, DSI_IRQSTATUS, ~0); } }
static RETURN_CODE ioctlSerial(Driver_t *self, enum IOCTL_CMD cmd, void *data) { int baud_rate; switch(cmd) { case SERIAL_SET_BAUD_RATE: baud_rate = *((int *)data); reg32w(UART3_BASE, MDR1_REG, 0x07); reg32w(UART3_BASE, LCR_REG, 0x80|0x03); reg32w(UART3_BASE, DLL_REG, (baud_rate & 0xff)); reg32w(UART3_BASE, DLH_REF, (baud_rate >> 8) & 0xff); reg32w(UART3_BASE, LCR_REG, 0x03); reg32w(UART3_BASE, MCR_REG, 0x01 | 0x02 ); reg32w(UART3_BASE, FCR_REG, 0x01 | 0x02 | 0x04); reg32w(UART3_BASE, MDR1_REG, 0x0); return SUCCESS; default: return FAILURE; } }
static RETURN_CODE openSerial(Driver_t *self) { reg32w(UART3_BASE, MDR1_REG, 0x0); return SUCCESS; }
int main(int argc, char **argv) { local_exceptions_init(); // example is too fast/boring with caches on, so don't //mmu_simple_init(); video_init(1280, 1024); rp = graphics_init(FBADDR, WIDTH, HEIGHT, BM_RGB16); omap_attach_framebuffer(0, rp->drawable.bitmap); // also set it to the tv out (top-left corner of same data) omap_attach_framebuffer(VID_VID2 | VID_TVOUT, rp->drawable.bitmap); moveTo(rp, 0, 0); setColour(rp, 0x3e31a2); drawRect(rp, WIDTH, HEIGHT); // setup tasks to run int i; NewList(&tasks); dprintf("tasks %08x, Head=%08x Tail=%08x TailPred=%08x\n", &tasks, tasks.Head, tasks.Tail, tasks.TailPred); for (i=0;taskinit[i];i++ ){ struct task *t = taskinit[i]; // set initial pc and proc state t->tcb.pc = taskpc[i]; // runs in user mode t->tcb.spsr = 0x10; // initial argument 0 in reg 0 t->tcb.regs[0] = i; t->id = i; int j; for (j=1;j<10;j++) t->tcb.regs[j] = j; // initial stack - 4K each, before 32K of master stack t->tcb.regs[13] = 0x88000000 - 32768 - i*4096; AddTail((struct List *)&tasks, &t->Node); dprintf("adding task %d = %08x pc=%08x sp=%08x\n", i, t, t->tcb.pc, t->tcb.regs[13]); } dprintf("tasks %08x, Head=%08x Tail=%08x TailPred=%08x\n", &tasks, tasks.Head, tasks.Tail, tasks.TailPred); // set task 0 to `execute first' (it's actually us) thistask = &t1; fptask = 0; irq_new_task(tcb_to_sp(&thistask->tcb)); // add an irq handler for the vsync interrupt (lcd display?) irq_set_handler(INTC_DSS_IRQ, dispc_handler); irq_set_mask(INTC_DSS_IRQ, 1); // disable all but vsync reg32w(DISPC_BASE, DISPC_IRQENABLE, DISPC_VSYNC); reg32w(DISPC_BASE, DISPC_IRQSTATUS, ~0); // dss intterrupt can also receive DSI, so disable those too reg32w(DSI_BASE, DSI_IRQENABLE, 0); reg32w(DSI_BASE, DSI_IRQSTATUS, ~0); dprintf("enabling interrupts\n"); // data barrier for previous register writes asm volatile("dsb"); // turn on irq's, which enables task switching irq_enable(); // jump to user mode - we are now 'task 0' asm volatile("cps #0x10"); asm volatile("ldr sp,=0x88000000 - 32768"); task1(0); return 0; }
int main(int argc, char **argv) { local_exceptions_init(); // example is too fast/boring with caches on, so don't //mmu_simple_init(); video_init(1280, 1024); rp = graphics_init(FBADDR, WIDTH, HEIGHT, BM_RGB16); omap_attach_framebuffer(0, rp->drawable.bitmap); // also set it to the tv out (top-left corner of same data) omap_attach_framebuffer(VID_VID2 | VID_TVOUT, rp->drawable.bitmap); moveTo(rp, 0, 0); setColour(rp, 0x3e31a2); drawRect(rp, WIDTH, HEIGHT); // setup tasks to run int i; NewList(&tasks); dprintf("tasks %08x, Head=%08x Tail=%08x TailPred=%08x\n", &tasks, tasks.Head, tasks.Tail, tasks.TailPred); for (i=0;taskinit[i];i++ ){ struct task *t = taskinit[i]; // set initial pc and proc state t->tcb.pc = (uint32_t)task; // runs in user mode t->tcb.spsr = 0x10; // initial argument 0 in reg 0 t->tcb.regs[0] = i; t->id = i; int j; for (j=1;j<10;j++) t->tcb.regs[j] = j; // initial stack - 4K each, before 32K of master stack t->tcb.regs[13] = 0x88000000 - 32768 - i*4096; AddTail((struct List *)&tasks, &t->Node); dprintf("adding task %d = %08x pc=%08x sp=%08x\n", i, t, t->tcb.pc, t->tcb.regs[13]); } dprintf("tasks %08x, Head=%08x Tail=%08x TailPred=%08x\n", &tasks, tasks.Head, tasks.Tail, tasks.TailPred); // set task 0 to `execute first' (it's actually us) thistask = &t1; irq_new_task(tcb_to_sp(&thistask->tcb)); // // Setup timer interrupt via GPTIMER1 // // timer off reg32s(GPTIMER1_BASE, GPT_TCLR, 1, 0); // Sets true 1Khz rate w/ 32768Hz clock: S 16.2.4.3 TRM D reg32w(GPTIMER1_BASE, GPT_TPIR, 232000); reg32w(GPTIMER1_BASE, GPT_TNIR, -768000); reg32w(GPTIMER1_BASE, GPT_TLDR, 0xffffffe0); reg32w(GPTIMER1_BASE, GPT_TCRR, 0xffffffe0); // clear int status bits reg32w(GPTIMER1_BASE, GPT_TISR, ~0); // enable overflow int reg32w(GPTIMER1_BASE, GPT_TIER, OVF_IT_FLAG); // dividisor = 100 -> 10Hz so it's visible reg32w(GPTIMER1_BASE, GPT_TOCR, 0); reg32w(GPTIMER1_BASE, GPT_TOWR, 100); irq_set_handler(INTC_GPT1_IRQ, gptimer1_handler); irq_set_mask(INTC_GPT1_IRQ, 1); // force 32K clock reg32s(0x48004c00, 0x40, 1, 0); // turn timer back on reg32s(GPTIMER1_BASE, GPT_TCLR, 1|2|(2<<10), ~0); dprintf("enabling interrupts\n"); // data barrier for previous register writes asm volatile("dsb"); // turn on irq's, which enables task switching irq_enable(); // jump to user mode - we are now 'task 0' asm volatile("cps #0x10"); asm volatile("ldr sp,=0x88000000 - 32768"); task(0); return 0; }