1.1 --- a/stage2/irq.c Fri Feb 26 00:23:58 2016 +0100
1.2 +++ b/stage2/irq.c Fri Feb 26 00:44:01 2016 +0100
1.3 @@ -45,6 +45,12 @@
1.4
1.5 /* Task management. */
1.6
1.7 +enum { max_tasks = 3 };
1.8 +static u32 stack_pointers[max_tasks];
1.9 +u8 current_task = 0;
1.10 +u32 current_stack_pointer;
1.11 +extern u32 _got_copy_start;
1.12 +
1.13 const u32 stack_start = 0x00080000;
1.14 const u32 stack_size = 0x00002000;
1.15 const u32 pagesize = 4 * 1024;
1.16 @@ -81,9 +87,9 @@
1.17
1.18 if (REG_INTC_IPR & (1 << TIMER_CHAN_IRQ)) {
1.19
1.20 - /* Update the pixel type. */
1.21 + /* Switch task. */
1.22
1.23 - /* pixel_type = __gpio_get_pin(GPIO_POWER); */
1.24 + /* switch_task(); */
1.25
1.26 /* Clear interrupt status. */
1.27
1.28 @@ -100,12 +106,6 @@
1.29 }
1.30 }
1.31
1.32 -void start_task()
1.33 -{
1.34 - /* enter_user_mode(); */
1.35 - plot_pattern(1, 0, 0);
1.36 -}
1.37 -
1.38 void tlb_handle()
1.39 {
1.40 u32 asid, virtual, physical, bottom, top;
1.41 @@ -137,6 +137,51 @@
1.42 Request a physical region mapping two 4KB pages.
1.43 Pages employ C=3, dirty, valid, with the task number as the ASID.
1.44 */
1.45 -
1.46 +
1.47 map_page(virtual, physical, pagesize, 0x1e, asid);
1.48 +}
1.49 +
1.50 +void start_task(unsigned short task)
1.51 +{
1.52 + u32 args[] = {1, 0, (task - 1) * 120};
1.53 +
1.54 + /*
1.55 + Each task employs a stack at a multiple of the given start address in
1.56 + physical memory, but at the same address in virtual memory.
1.57 + */
1.58 +
1.59 + map_page(stack_start + stack_size * task - stack_size, stack_start + stack_size * task - stack_size, pagesize, 0x1e, 0);
1.60 +
1.61 + /*
1.62 + Set the stack for the new task, initialising the global pointer and
1.63 + return address.
1.64 + */
1.65 +
1.66 + init_stack(stack_start + stack_size * task, _got_copy_start, (void (*)()) plot_pattern, args, 3);
1.67 +
1.68 + /* Advance the stack pointer so that the adopted frame will be found. */
1.69 +
1.70 + stack_pointers[task] = stack_start - framesize;
1.71 }
1.72 +
1.73 +void switch_task()
1.74 +{
1.75 + /*
1.76 + Get the current stack pointer. This is obtained just after saving the
1.77 + task's state.
1.78 + */
1.79 +
1.80 + stack_pointers[current_task] = current_stack_pointer;
1.81 +
1.82 + /* Switch the current task. */
1.83 +
1.84 + current_task++;
1.85 + if (current_task == max_tasks) current_task = 1;
1.86 +
1.87 + /*
1.88 + Set the current stack pointer. This is actually set just before
1.89 + restoring the task's state.
1.90 + */
1.91 +
1.92 + current_stack_pointer = stack_pointers[current_task];
1.93 +}