################################################################################# # File : reset.s # Author : Alain Greiner # Date : 20/11/2009 ################################################################################# # This boot code creates four tasks running on the same processor, # and executing four different programs: main0, main1, main2, main3. # Each Task has his own terminal, and his own stack. # - It initializes the interrupt vector with 7 ISR addresses # ( timer, tty0, tty1, tty2, tty3, io, dma ) # - It initializes the _current_task_array & _task_number_array variables # - It initializes contexts for tasks T1,T2,T3 : EPC, SR, SP, RA # - It initializes registers for task T0 : EPC, SR, SP # - It initializes the Timer & ICU components. # - It jumps to main in user mode. ################################################################################# .section .reset,"ax",@progbits .extern seg_stack_base .extern seg_timer_base .extern seg_icu_base .extern _task_context .extern _current_task_array # running task index .extern _task_number_array # number of tasks .extern main0 .extern main1 .extern main2 .extern main3 .extern _interrupt_vector .extern _isr_tty_get_task0 .extern _isr_tty_get_task1 .extern _isr_tty_get_task2 .extern _isr_tty_get_task3 .extern _isr_ioc .extern _isr_dma .extern _isr_switch .globl reset # makes reset an external symbol .ent reset .align 2 reset: .set noreorder # initializes interrupt vector la $27, _interrupt_vector # $27 <= interrupt vector address la $26, _isr_switch # sw $26, 0($27) # interrupt_vector[0] <= _isr_switch la $26, _isr_tty_get_task0 # sw $26, 4($27) # interrupt_vector[1] <= _isr_tty_get_task0 la $26, _isr_tty_get_task1 # sw $26, 8($27) # interrupt_vector[2] <= _isr_tty_get_task1 la $26, _isr_tty_get_task2 # sw $26, 12($27) # interrupt_vector[3] <= _isr_tty_get_task2 la $26, _isr_tty_get_task3 # sw $26, 16($27) # interrupt_vector[4] <= _isr_tty_get_task3 la $26, _isr_ioc # sw $26, 20($27) # interrupt_vector[5] <= _isr_ioc la $26, _isr_dma # sw $26, 24($27) # interrupt_vector[6] <= _isr_dma # initializes task index & task number la $27, _current_task_array sw $0, 0($27) # task_index <= 0 la $27, _task_number_array li $26, 4 sw $26, 0($27) # task_number <= 4 # initializes stack pointers for tasks 1,2,3 (each stack is 64 KB) la $27, _task_context_array # $27 <= &ctx[] la $26, seg_stack_base li $10, 0x00020000 # 128 K add $10, $26, $10 sw $10, 4*(64+29)($27) # SP for task 1 li $10, 0x00030000 # 192 K add $10, $26, $10 sw $10, 4*(128+29)($27) # SP for task 2 li $10, 0x00040000 # 256 K add $10, $26, $10 sw $10, 4*(192+29)($27) # SP for task 3 # initializes EPC for tasks 1,2,3 (main1, main2, main3) la $26, main1 sw $26, 4*(64+32)($27) # EPC for task 1 la $26, main2 sw $26, 4*(128+32)($27) # EPC for task 2 la $26, main3 sw $26, 4*(192+32)($27) # EPC for task 3 # initializes RA for tasks 1,2,3 (to execute the eret instruction) la $26, to_user sw $26, 4*(64+31)($27) # $31 for task 1 sw $26, 4*(128+31)($27) # $31 for task 2 sw $26, 4*(192+31)($27) # $31 for task 3 # initializes SR sor tasks 1,2,3 (set UM, EXL, IE) li $26, 0x0000FF13 sw $26, 4*64($27) # SR for task 1 sw $26, 4*128($27) # SR for task 2 sw $26, 4*192($27) # SR for task 3 # ICU Configuration: 7 IRQs enabled : TIMER, IO, DMA la $27, seg_icu_base li $26, 0x7F sw $26, 8($27) # ICU mask <= 0111 1111 # TIMER Configuration: period = 10000 cycles la $27, seg_timer_base li $26, 10000 sw $26, 8($27) # period <= 10000 li $26, 0x3 sw $26, 4($27) # TIMER start # initializes Registers for T0 (size = 64K) la $26, seg_stack_base li $27, 0x10000 add $29, $26, $27 # SP for task 0 la $26, main0 mtc0 $26, $14 # EPC for task 0 li $26, 0x0000FF13 mtc0 $26, $12 # SR for task 0 # jump to address contained in EPC (in user mode) to_user: eret .end reset .set reorder