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 + IRQ_STACK_SIZE) 140 #define IRQ_STACK_TOP (IRQ_STACK_LIMIT - 34 * 4) 141 142 int_handler: 143 144 /* Store affected registers from IRQ_STACK_LIMIT - 4 downwards. */ 145 146 lui $k0, %hi(IRQ_STACK_LIMIT) 147 ori $k0, $k0, %lo(IRQ_STACK_LIMIT) 148 149 .irp reg, \ 150 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 \ 151 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \ 152 28, 29, 30, 31 153 sw $\reg, -(\reg * 4)($k0) 154 .endr 155 156 mflo $k1 157 sw $k1, -(32 * 4)($k0) 158 mfhi $k1 159 sw $k1, -(33 * 4)($k0) 160 161 /* Switch to the IRQ stack. */ 162 163 lui $sp, %hi(IRQ_STACK_TOP) 164 ori $sp, $sp, %lo(IRQ_STACK_TOP) 165 166 jal interrupt_handler 167 nop 168 169 /* Restore affected registers. */ 170 171 lw $k1, -(32 * 4)($k0) 172 mtlo $k1 173 lw $k1, -(33 * 4)($k0) 174 mthi $k1 175 176 .irp reg, \ 177 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 \ 178 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \ 179 28, 29, 30, 31 180 lw $\reg, -(\reg * 4)($k0) 181 .endr 182 183 eret 184 nop