CommonPIC32

lib/cpu.S

152:3cad7f8a1679
2020-05-01 Paul Boddie Fixed markup.
     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 #define IRQ_STACK_LIMIT	(KSEG0_BASE + IRQ_STACK_SIZE)    25 #define IRQ_STACK_TOP	(IRQ_STACK_LIMIT - 34 * 4)    26     27 .globl enable_interrupts    28 .globl handle_error_level    29 .globl init_interrupts    30 .extern exception_handler    31 .extern interrupt_handler    32     33 /* Put general routines in the text section. */    34     35 .text    36     37 /*    38 Clear the error and exception status flags, making interrupts and exceptions    39 possible.    40 */    41     42 handle_error_level:    43         mfc0 $t3, CP0_STATUS    44     45 	/* Clear error level and exception level. */    46     47         li $t4, ~(STATUS_ERL | STATUS_EXL)    48         and $t3, $t3, $t4    49         mtc0 $t3, CP0_STATUS    50     51         jr $ra    52         nop    53     54 /* Enable interrupts and direct interrupt requests to non-bootloader vectors. */    55     56 enable_interrupts:    57         mfc0 $t3, CP0_STATUS    58     59 	/* Clear interrupt priority bits. */    60     61         li $t4, ~STATUS_IRQ    62         and $t3, $t3, $t4    63     64 	/* Set interrupt priority. */    65     66 	ori $t3, $t3, (CPU_INT_PRIORITY << STATUS_IRQ_SHIFT)    67     68 	/* CP0_STATUS &= ~STATUS_BEV (use non-bootloader vectors) */    69     70         li $t4, ~STATUS_BEV    71         and $t3, $t3, $t4    72     73 	/* Enable interrupts. */    74     75         ori $t3, $t3, STATUS_IE    76         mtc0 $t3, CP0_STATUS    77     78         jr $ra    79         nop    80     81 /* Initialise the interrupt system parameters. */    82     83 init_interrupts:    84 	/* Clear debug mode. */    85     86         mfc0 $t3, CP0_DEBUG    87         li $t4, ~DEBUG_DM    88         and $t3, $t3, $t4    89         mtc0 $t3, CP0_DEBUG    90     91 	/* Update the exception base. */    92     93         mfc0 $t3, CP0_STATUS    94         li $t4, STATUS_BEV      /* BEV = 1 or EBASE cannot be set */    95         or $t3, $t3, $t4    96         mtc0 $t3, CP0_STATUS    97     98         la $t3, ebase    99         mtc0 $t3, CP0_EBASE   100    101 	/* Set vector spacing. */   102    103         li $t3, 0x20            /* Must be non-zero or the CPU gets upset */   104         mtc0 $t3, CP0_INTCTL   105    106         li $t3, CAUSE_IV        /* IV = 1 (use EBASE+0x200 for interrupts) */   107         mtc0 $t3, CP0_CAUSE   108    109         jr $ra   110         nop   111    112    113    114 /* Exception servicing, positioned at EBASE at the start of program memory. */   115    116 .section .vectors, "a"   117    118 /* TLB error servicing. */   119    120 ebase:   121 tlb_handler:   122         j exception_handler   123         nop   124    125    126    127 /* General exception servicing. */   128    129 .org 0x180   130    131 exc_handler:   132 	move $k0, $sp   133 	move $k1, $t9   134    135 	/* Switch to the IRQ stack. */   136    137 	lui $sp, %hi(IRQ_STACK_TOP)   138 	ori $sp, $sp, %lo(IRQ_STACK_TOP)   139    140 	/* Obtain the address directly to avoid initialising $gp here. */   141    142 	lui $t9, %hi(exception_handler)   143 	ori $t9, $t9, %lo(exception_handler)   144 	jr $t9   145         nop   146    147    148    149 /* Interrupt servicing. */   150    151 .org 0x200   152 .set noat   153    154 int_handler:   155    156         /* Store affected registers from IRQ_STACK_LIMIT - 4 downwards. */   157    158         lui $k0, %hi(IRQ_STACK_LIMIT)   159         ori $k0, $k0, %lo(IRQ_STACK_LIMIT)   160    161 	.irp reg, \   162 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 \   163 		16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \   164 		28, 29, 30, 31   165 		sw $\reg, -(\reg * 4)($k0)   166 	.endr   167    168 	mflo $k1   169 	sw $k1, -(32 * 4)($k0)   170 	mfhi $k1   171 	sw $k1, -(33 * 4)($k0)   172    173 	/* Switch to the IRQ stack. */   174    175         lui $sp, %hi(IRQ_STACK_TOP)   176         ori $sp, $sp, %lo(IRQ_STACK_TOP)   177    178 	/* Obtain the address directly to avoid initialising $gp here. */   179    180 	lui $t9, %hi(interrupt_handler)   181 	ori $t9, $t9, %lo(interrupt_handler)   182 	jalr $t9   183 	nop   184    185         /* Restore affected registers. */   186    187 	lw $k1, -(32 * 4)($k0)   188 	mtlo $k1   189 	lw $k1, -(33 * 4)($k0)   190 	mthi $k1   191    192 	.irp reg, \   193 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 \   194 		16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \   195 		28, 29, 30, 31   196 		lw $\reg, -(\reg * 4)($k0)   197 	.endr   198    199         eret   200         nop