1 /* 2 * PIC32 microcontroller interrupt handling code. 3 * 4 * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "mips.h" 21 #include "pic32.h" 22 #include "cpu.h" 23 24 .globl enable_interrupts 25 .globl handle_error_level 26 .globl init_interrupts 27 .extern exception_handler 28 .extern interrupt_handler 29 30 /* Put general routines in the text section. */ 31 32 .text 33 34 /* 35 Clear the error and exception status flags, making interrupts and exceptions 36 possible. 37 */ 38 39 handle_error_level: 40 mfc0 $t3, CP0_STATUS 41 42 /* Clear error level and exception level. */ 43 44 li $t4, ~(STATUS_ERL | STATUS_EXL) 45 and $t3, $t3, $t4 46 mtc0 $t3, CP0_STATUS 47 48 jr $ra 49 nop 50 51 /* Enable interrupts and direct interrupt requests to non-bootloader vectors. */ 52 53 enable_interrupts: 54 mfc0 $t3, CP0_STATUS 55 56 /* Clear interrupt priority bits. */ 57 58 li $t4, ~STATUS_IRQ 59 and $t3, $t3, $t4 60 61 /* Set interrupt priority. */ 62 63 ori $t3, $t3, (CPU_INT_PRIORITY << STATUS_IRQ_SHIFT) 64 65 /* CP0_STATUS &= ~STATUS_BEV (use non-bootloader vectors) */ 66 67 li $t4, ~STATUS_BEV 68 and $t3, $t3, $t4 69 70 /* Enable interrupts. */ 71 72 ori $t3, $t3, STATUS_IE 73 mtc0 $t3, CP0_STATUS 74 75 jr $ra 76 nop 77 78 /* Initialise the interrupt system parameters. */ 79 80 init_interrupts: 81 /* Clear debug mode. */ 82 83 mfc0 $t3, CP0_DEBUG 84 li $t4, ~DEBUG_DM 85 and $t3, $t3, $t4 86 mtc0 $t3, CP0_DEBUG 87 88 /* Update the exception base. */ 89 90 mfc0 $t3, CP0_STATUS 91 li $t4, STATUS_BEV /* BEV = 1 or EBASE cannot be set */ 92 or $t3, $t3, $t4 93 mtc0 $t3, CP0_STATUS 94 95 la $t3, ebase 96 mtc0 $t3, CP0_EBASE 97 98 /* Set vector spacing. */ 99 100 li $t3, 0x20 /* Must be non-zero or the CPU gets upset */ 101 mtc0 $t3, CP0_INTCTL 102 103 li $t3, CAUSE_IV /* IV = 1 (use EBASE+0x200 for interrupts) */ 104 mtc0 $t3, CP0_CAUSE 105 106 jr $ra 107 nop 108 109 110 111 /* Exception servicing, positioned at EBASE at the start of program memory. */ 112 113 .section .vectors, "a" 114 115 /* TLB error servicing. */ 116 117 ebase: 118 tlb_handler: 119 j exception_handler 120 nop 121 122 123 124 /* General exception servicing. */ 125 126 .org 0x180 127 128 exc_handler: 129 j exception_handler 130 nop 131 132 133 134 /* Interrupt servicing. */ 135 136 .org 0x200 137 .set noat 138 139 #define IRQ_STACK_LIMIT (KSEG0_BASE + 256) 140 #define IRQ_STACK_TOP (IRQ_STACK_LIMIT - 32 * 4) 141 142 int_handler: 143 144 /* Store affected registers from IRQ_STACK_LIMIT - 4 downwards. */ 145 146 li $k0, IRQ_STACK_LIMIT 147 148 .irp reg, \ 149 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 \ 150 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \ 151 28, 29, 30, 31 152 sw $\reg, -(\reg * 4)($k0) 153 .endr 154 155 /* Switch to the IRQ stack. */ 156 157 li $sp, IRQ_STACK_TOP 158 159 jal interrupt_handler 160 nop 161 162 /* Restore affected registers. */ 163 164 .irp reg, \ 165 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 \ 166 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \ 167 28, 29, 30, 31 168 lw $\reg, -(\reg * 4)($k0) 169 .endr 170 171 eret 172 nop