# HG changeset patch # User Paul Boddie # Date 1511048397 -3600 # Node ID f83509c62e120a18859590a80b5b5ed54e1faf9d # Parent a297782bef19fe2df936cb86cceca01c2fcc24f6# Parent 2bc674143b083a0ae234ab562f2e9d41bd837200 Merged changes from a parallel development branch. diff -r a297782bef19 -r f83509c62e12 mips.h --- a/mips.h Tue Nov 07 14:38:33 2017 +0100 +++ b/mips.h Sun Nov 19 00:39:57 2017 +0100 @@ -10,6 +10,7 @@ #define CP0_CONTEXT $4 #define CP0_PAGEMASK $5 #define CP0_WIRED $6 +#define CP0_BADVADDR $8 #define CP0_COUNT $9 #define CP0_ENTRYHI $10 #define CP0_COMPARE $11 diff -r a297782bef19 -r f83509c62e12 pic32.h --- a/pic32.h Tue Nov 07 14:38:33 2017 +0100 +++ b/pic32.h Sun Nov 19 00:39:57 2017 +0100 @@ -28,6 +28,12 @@ #define TMR3 0xBF800A10 #define PR3 0xBF800A20 +#define U1MODE 0xBF806000 +#define U1STA 0xBF806010 +#define U1TXREG 0xBF806020 +#define U1RXREG 0xBF806030 +#define U1BRG 0xBF806040 + #define PMCON 0xBF807000 #define PMMODE 0xBF807010 #define PMADDR 0xBF807020 @@ -42,6 +48,8 @@ #define CFGCON 0xBF80F200 #define SYSKEY 0xBF80F230 +#define U1RXR 0xBF80FA50 + #define RPA0R 0xBF80FB00 #define RPA1R 0xBF80FB04 #define RPA2R 0xBF80FB08 @@ -54,6 +62,7 @@ #define RPB4R 0xBF80FB3C #define RPB5R 0xBF80FB40 #define RPB10R 0xBF80FB54 +#define RPB15R 0xBF80FB68 #define INTCON 0xBF881000 #define IFS0 0xBF881030 diff -r a297782bef19 -r f83509c62e12 vga.S --- a/vga.S Tue Nov 07 14:38:33 2017 +0100 +++ b/vga.S Sun Nov 19 00:39:57 2017 +0100 @@ -57,9 +57,51 @@ .extern init_framebuffer .extern init_framebuffer_with_pattern .extern screendata -.extern fontdata .extern blit_string -.extern message +.extern message0 +.extern message1 + +.macro load_affected + lw $v0, -4($k0) + lw $v1, -8($k0) + lw $s0, -12($k0) + lw $s1, -16($k0) + lw $s2, -20($k0) + lw $s3, -24($k0) + lw $t8, -28($k0) + lw $ra, -32($k0) + lw $sp, -36($k0) + lw $gp, -40($k0) +.endm + +.macro load_state + lw $s0, -44($k0) + lw $s1, -48($k0) + lw $s2, -52($k0) + lw $s3, -56($k0) + lw $gp, -60($k0) +.endm + +.macro save_affected + sw $v0, -4($k0) + sw $v1, -8($k0) + sw $s0, -12($k0) + sw $s1, -16($k0) + sw $s2, -20($k0) + sw $s3, -24($k0) + sw $t8, -28($k0) + sw $ra, -32($k0) + sw $sp, -36($k0) + sw $gp, -40($k0) +.endm + +.macro save_state + sw $s0, -44($k0) + sw $s1, -48($k0) + sw $s2, -52($k0) + sw $s3, -56($k0) + sw $gp, -60($k0) +.endm _start: /* @@ -115,7 +157,7 @@ li $t1, (1 << 3) /* PORTA<3> = RA3 */ sw $t1, CLR($t0) - jal init_oc_pins + jal init_io_pins nop /* Initialise the status register. */ @@ -146,6 +188,11 @@ jal init_oc nop + /* Initialise UART for debugging. */ + + jal init_uart + nop + /* Initialise the display state. */ li $s0, 0 /* line counter */ @@ -156,10 +203,7 @@ /* Save the state for retrieval in the interrupt handler. */ li $k0, IRQ_STACK_LIMIT - sw $s0, -44($k0) - sw $s1, -48($k0) - sw $s2, -52($k0) - sw $s3, -56($k0) + save_state /* Enable interrupts and loop. */ @@ -186,6 +230,10 @@ li $t1, (1 << 3) /* PORTA<3> = RA3 */ sw $t1, INV($t0) + la $v0, U1TXREG + li $v1, '.' + sw $v1, 0($v0) + bnez $a1, loop /* until counter == 0 */ nop @@ -393,7 +441,7 @@ jr $ra nop -init_oc_pins: +init_io_pins: /* Unlock the configuration register bits. */ la $v0, SYSKEY @@ -420,6 +468,12 @@ li $v1, 0b0101 /* RPA1R<3:0> = 0101 (OC2) */ sw $v1, 0($v0) + /* Map U1TX to RPB15. */ + + la $v0, RPB15R + li $v1, 0b0001 /* RPB15R<3:0> = 0001 (U1TX) */ + sw $v1, 0($v0) + la $v0, CFGCON sw $t8, 0($v0) @@ -661,6 +715,34 @@ +/* UART initialisation. */ + +init_uart: + /* Initialise UART. */ + + la $v0, U1BRG + li $v1, 12 /* U1BRG<15:0> = BRG = (FPB / (16 * baudrate)) - 1 = (24000000 / (16 * 115200)) - 1 = 12 */ + sw $v1, 0($v0) + + la $v0, U1MODE + li $v1, (1 << 15) /* U1MODE<15> = ON = 0 */ + sw $v1, CLR($v0) + + /* Start UART. */ + + la $v0, U1STA + li $v1, (1 << 10) /* U1STA<10> = UTXEN = 1 */ + sw $v1, SET($v0) + + la $v0, U1MODE + li $v1, (1 << 15) /* U1MODE<15> = ON = 1 */ + sw $v1, SET($v0) + + jr $ra + nop + + + /* Utilities. */ handle_error_level: @@ -736,62 +818,39 @@ interrupt_handler: - /* Store affected registers. */ + /* + Save affected registers, restoring IRQ state and switching to the IRQ + stack. + */ li $k0, IRQ_STACK_LIMIT - sw $v0, -4($k0) - sw $v1, -8($k0) - sw $s0, -12($k0) - sw $s1, -16($k0) - sw $s2, -20($k0) - sw $s3, -24($k0) - sw $t8, -28($k0) - sw $ra, -32($k0) - sw $sp, -36($k0) + save_affected + load_state + li $sp, IRQ_STACK_TOP + + /* + The timer interrupt will only occur outside the visible region, but the + interrupt condition will still occur as the timer wraps around. - /* Load state. */ + Here, we deliberately ignore the timer condition during the visible/ + active region. - lw $s0, -44($k0) - lw $s1, -48($k0) - lw $s2, -52($k0) - lw $s3, -56($k0) + The DMA interrupt should only be active within the visible region. + */ - li $sp, IRQ_STACK_TOP + la $t8, visible_active + beq $s1, $t8, irq_dma + nop /* Check for a timer interrupt condition. */ la $v0, IFS0 lw $v1, 0($v0) andi $v1, $v1, (1 << 9) /* T2IF */ - beqz $v1, irq_dma + beqz $v1, irq_exit nop - /* Clear the timer interrupt condition. */ - - sw $v1, CLR($v0) - - /* - The timer interrupt will only occur outside the visible region, but the - interrupt condition will still occur as the timer wraps around. - Therefore, the handling of other interrupts may find the timer interrupt - condition set. - - For the visible region, the event handler is invoked when handling the - DMA interrupt. Otherwise, the event handler is invoked in response to - the timer interrupt. - */ - - la $t8, visible_active - beq $s1, $t8, irq_dma - nop - - /* Increment the line counter (only outside the visible region). */ - - addiu $s0, $s0, 1 - - /* Jump to the event handler (only outside the visible region). */ - - jalr $s1 + j irq_handle nop irq_dma: @@ -816,98 +875,35 @@ beqz $v1, irq_exit nop - /* Clear the block transfer completion interrupt flag. */ +irq_handle: + /* Clear the interrupt condition. */ sw $v1, CLR($v0) - /* - The DMA interrupt should only be active within the visible region. - The event handler is invoked here instead of in response to a timer - interrupt within that region. - */ - - /* Increment the line counter (only within the visible region). */ + /* Increment the line counter. */ addiu $s0, $s0, 1 - /* Jump to the event handler (only within the visible region). */ + /* Jump to the event handler. */ jalr $s1 nop - /* Jump to the DMA update routine. */ - - j visible_update_address - nop - irq_exit: - /* Save state. */ + /* + Save IRQ state and restore the affected registers, switching back to the + original stack. + */ li $k0, IRQ_STACK_LIMIT - sw $s0, -44($k0) - sw $s1, -48($k0) - sw $s2, -52($k0) - sw $s3, -56($k0) - - /* Restore affected registers. */ - - lw $v0, -4($k0) - lw $v1, -8($k0) - lw $s0, -12($k0) - lw $s1, -16($k0) - lw $s2, -20($k0) - lw $s3, -24($k0) - lw $t8, -28($k0) - lw $ra, -32($k0) - lw $sp, -36($k0) + save_state + load_affected eret nop -exc_handler: - li $t9, 0x80000000 - mfc0 $t6, CP0_ERROREPC - nop -exc_loop: - and $t7, $t9, $t6 - beqz $t7, exc_errorepc_zero - nop -exc_errorepc_one: - la $v0, PORTA - li $v1, (1 << 2) /* PORTA<2> = RA2 */ - sw $v1, SET($v0) - j exc_loop_wait - nop -exc_errorepc_zero: - la $v0, PORTA - li $v1, (1 << 3) /* PORTA<3> = RA3 */ - sw $v1, SET($v0) -exc_loop_wait: - li $t8, 5000000 -exc_loop_delay: - addiu $t8, $t8, -1 - bnez $t8, exc_loop_delay - nop - la $v0, PORTA - li $v1, (3 << 2) /* PORTA<3:2> = RA3, RA2 */ - sw $v1, CLR($v0) -exc_loop_wait_again: - li $t8, 2500000 -exc_loop_delay_again: - addiu $t8, $t8, -1 - bnez $t8, exc_loop_delay_again - nop -exc_errorepc_next: - srl $t9, $t9, 1 - bnez $t9, exc_loop - nop - j exc_handler - nop - - - /* Event routines. */ /* The vertical back porch. */ @@ -937,19 +933,12 @@ The condition still occurs, however. */ - la $v0, IEC0 - li $v1, (1 << 9) - sw $v1, CLR($v0) /* T2IE = 0 */ - la $v0, IPC2 - li $v1, 0b11111 - sw $v1, CLR($v0) /* T2IP, T2IS = 0 */ - li $v1, 0b00111 - sw $v1, SET($v0) /* T2IP = 1; T2IS = 3 */ - - la $v0, IEC0 - li $v1, (1 << 9) - sw $v1, SET($v0) /* T2IE = 0 */ + lw $v1, 0($v0) + li $t8, ~0b11111 + and $v1, $v1, $t8 /* T2IP = 0; T2IS = 0 */ + ori $v1, $v1, 0b00111 /* T2IP = 1; T2IS = 3 */ + sw $v1, 0($v0) /* Enable the line channel for timer event transfer initiation. */ @@ -969,7 +958,7 @@ /* Test for front porch. */ sltiu $v0, $s0, VFP_START - bnez $v0, _visible_active_ret + bnez $v0, visible_update_address nop /* Start the front porch region. */ @@ -978,19 +967,18 @@ /* Restore delivery of the timer interrupt after the visible period. */ - la $v0, IEC0 - li $v1, (1 << 9) - sw $v1, CLR($v0) /* T2IE = 0 */ + la $v0, IPC2 + lw $v1, 0($v0) + li $t8, ~0b11111 + and $v1, $v1, $t8 /* T2IP = 0; T2IS = 0 */ + ori $v1, $v1, 0b11111 /* T2IP = 7; T2IS = 3 */ + sw $v1, 0($v0) - la $v0, IPC2 - li $v1, 0b11111 - sw $v1, CLR($v0) /* T2IP, T2IS = 0 */ - li $v1, 0b11111 - sw $v1, SET($v0) /* T2IP = 7; T2IS = 3 */ + /* Disable the line channel. */ - la $v0, IEC0 - li $v1, (1 << 9) - sw $v1, SET($v0) /* T2IE = 1 */ + la $v0, DCH0ECON + li $v1, (1 << 4) /* DCH0ECON<4> = SIRQEN = 0 */ + sw $v1, CLR($v0) _visible_active_ret: jr $ra @@ -1002,23 +990,6 @@ visible_update_address: - /* Test for the last visible line. */ - - la $v0, vfp_active - bne $s1, $v0, _visible_update_address - nop - - /* Disable the line channel. */ - - la $v0, DCH0ECON - li $v1, (1 << 4) /* DCH0ECON<4> = SIRQEN = 0 */ - sw $v1, CLR($v0) - - j _visible_update_ret - nop - -_visible_update_address: - /* Update the line data address if the line counter (referring to the next line) is even. @@ -1051,7 +1022,7 @@ sw $s2, 0($v0) _visible_update_ret: - j irq_exit + jr $ra nop @@ -1104,3 +1075,39 @@ _vsync_active_ret: jr $ra nop + + + +/* Exception handler. */ + +exc_handler: + mfc0 $t7, CP0_ERROREPC + nop + +exc_write_word: + li $t8, 32 + la $v0, U1TXREG +exc_loop: + addiu $t8, $t8, -4 + srlv $v1, $t7, $t8 /* $v1 = $t7 >> $t8 */ + andi $v1, $v1, 0xF + addiu $t9, $v1, -10 /* $t9 >= 10? */ + bgez $t9, exc_alpha + nop +exc_digit: + addiu $v1, $v1, 48 /* convert to digit: '0' */ + j exc_write + nop +exc_alpha: + addiu $v1, $v1, 55 /* convert to alpha: 'A' - 10 */ +exc_write: + sw $v1, 0($v0) + bnez $t8, exc_loop + nop +exc_loop_end: + li $v1, '\n' + sw $v1, 0($v0) + +exc_handler_end: + j exc_handler_end + nop diff -r a297782bef19 -r f83509c62e12 vga.h --- a/vga.h Tue Nov 07 14:38:33 2017 +0100 +++ b/vga.h Sun Nov 19 00:39:57 2017 +0100 @@ -22,6 +22,6 @@ #define SCREEN_LIMIT_KSEG0 (KSEG0_BASE + SCREEN_LIMIT) #define IRQ_STACK_LIMIT SCREEN_BASE_KSEG0 -#define IRQ_STACK_TOP (IRQ_STACK_LIMIT - 56) +#define IRQ_STACK_TOP (IRQ_STACK_LIMIT - 64) #endif /* __VGA_H__ */