1 /* --COPYRIGHT--,BSD 2 * Copyright (c) 2017, Texas Instruments Incorporated 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of Texas Instruments Incorporated nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * --/COPYRIGHT--*/ 32 /* Standard Includes */ 33 #include <stdint.h> 34 35 /* DriverLib Includes */ 36 #include <ti/devices/msp432p4xx/driverlib/debug.h> 37 #include <ti/devices/msp432p4xx/driverlib/cpu.h> 38 #include <ti/devices/msp432p4xx/driverlib/interrupt.h> 39 40 41 //***************************************************************************** 42 // 43 // This is a mapping between priority grouping encodings and the number of 44 // preemption priority bits. 45 // 46 //***************************************************************************** 47 static const uint32_t g_pulPriority[] = 48 { NVIC_APINT_PRIGROUP_0_8, NVIC_APINT_PRIGROUP_1_7, NVIC_APINT_PRIGROUP_2_6, 49 NVIC_APINT_PRIGROUP_3_5, NVIC_APINT_PRIGROUP_4_4, 50 NVIC_APINT_PRIGROUP_5_3, NVIC_APINT_PRIGROUP_6_2, 51 NVIC_APINT_PRIGROUP_7_1 }; 52 53 //***************************************************************************** 54 // 55 // This is a mapping between interrupt number and the register that contains 56 // the priority encoding for that interrupt. 57 // 58 //***************************************************************************** 59 static const uint32_t g_pulRegs[] = 60 { 0, NVIC_SYS_PRI1_R, NVIC_SYS_PRI2_R, NVIC_SYS_PRI3_R, NVIC_PRI0_R, 61 NVIC_PRI1_R, NVIC_PRI2_R, NVIC_PRI3_R, NVIC_PRI4_R, NVIC_PRI5_R, 62 NVIC_PRI6_R, NVIC_PRI7_R, NVIC_PRI8_R, NVIC_PRI9_R, NVIC_PRI10_R, 63 NVIC_PRI11_R, NVIC_PRI12_R, NVIC_PRI13_R, NVIC_PRI14_R, NVIC_PRI15_R }; 64 65 //***************************************************************************** 66 // 67 // This is a mapping between interrupt number (for the peripheral interrupts 68 // only) and the register that contains the interrupt enable for that 69 // interrupt. 70 // 71 //***************************************************************************** 72 static const uint32_t g_pulEnRegs[] = 73 { NVIC_EN0_R, NVIC_EN1_R }; 74 75 //***************************************************************************** 76 // 77 // This is a mapping between interrupt number (for the peripheral interrupts 78 // only) and the register that contains the interrupt disable for that 79 // interrupt. 80 // 81 //***************************************************************************** 82 static const uint32_t g_pulDisRegs[] = 83 { NVIC_DIS0_R, NVIC_DIS1_R }; 84 85 //***************************************************************************** 86 // 87 // This is a mapping between interrupt number (for the peripheral interrupts 88 // only) and the register that contains the interrupt pend for that interrupt. 89 // 90 //***************************************************************************** 91 static const uint32_t g_pulPendRegs[] = 92 { NVIC_PEND0_R, NVIC_PEND1_R }; 93 94 //***************************************************************************** 95 // 96 // This is a mapping between interrupt number (for the peripheral interrupts 97 // only) and the register that contains the interrupt unpend for that 98 // interrupt. 99 // 100 //***************************************************************************** 101 static const uint32_t g_pulUnpendRegs[] = 102 { NVIC_UNPEND0_R, NVIC_UNPEND1_R }; 103 104 //***************************************************************************** 105 // 106 //! \internal 107 //! The default interrupt handler. 108 //! 109 //! This is the default interrupt handler for all interrupts. It simply loops 110 //! forever so that the system state is preserved for observation by a 111 //! debugger. Since interrupts should be disabled before unregistering the 112 //! corresponding handler, this should never be called. 113 //! 114 //! \return None. 115 // 116 //***************************************************************************** 117 static void IntDefaultHandler(void) 118 { 119 // 120 // Go into an infinite loop. 121 // 122 while (1) 123 { 124 } 125 } 126 127 //***************************************************************************** 128 // 129 // The processor vector table. 130 // 131 // This contains a list of the handlers for the various interrupt sources in 132 // the system. The layout of this list is defined by the hardware; assertion 133 // of an interrupt causes the processor to start executing directly at the 134 // address given in the corresponding location in this list. 135 // 136 //***************************************************************************** 137 #if defined(__IAR_SYSTEMS_ICC__) 138 #pragma data_alignment=1024 139 static __no_init void (*g_pfnRAMVectors[NUM_INTERRUPTS+1])(void) @ "VTABLE"; 140 #elif defined(__TI_COMPILER_VERSION__) 141 #pragma DATA_ALIGN(g_pfnRAMVectors, 1024) 142 #pragma DATA_SECTION(g_pfnRAMVectors, ".vtable") 143 void (*g_pfnRAMVectors[NUM_INTERRUPTS + 1])(void); 144 #else 145 static __attribute__((section("vtable"))) 146 void (*g_pfnRAMVectors[NUM_INTERRUPTS+1])(void) __attribute__((aligned(1024))); 147 #endif 148 149 bool Interrupt_enableMaster(void) 150 { 151 // 152 // Enable processor interrupts. 153 // 154 return (CPU_cpsie()); 155 } 156 157 bool Interrupt_disableMaster(void) 158 { 159 // 160 // Disable processor interrupts. 161 // 162 return (CPU_cpsid()); 163 } 164 165 void Interrupt_registerInterrupt(uint32_t interruptNumber, 166 void (*intHandler)(void)) 167 { 168 uint32_t ulIdx, ulValue; 169 170 // 171 // Check the arguments. 172 // 173 ASSERT(interruptNumber < (NUM_INTERRUPTS+1)); 174 175 // 176 // Make sure that the RAM vector table is correctly aligned. 177 // 178 ASSERT(((uint32_t) g_pfnRAMVectors & 0x000000ff) == 0); 179 180 // 181 // See if the RAM vector table has been initialized. 182 // 183 if (SCB->VTOR != (uint32_t) g_pfnRAMVectors) 184 { 185 // 186 // Copy the vector table from the beginning of FLASH to the RAM vector 187 // table. 188 // 189 ulValue = SCB->VTOR; 190 for (ulIdx = 0; ulIdx < (NUM_INTERRUPTS + 1); ulIdx++) 191 { 192 g_pfnRAMVectors[ulIdx] = (void (*)(void)) HWREG32( 193 (ulIdx * 4) + ulValue); 194 } 195 196 // 197 // Point the NVIC at the RAM vector table. 198 // 199 SCB->VTOR = (uint32_t) g_pfnRAMVectors; 200 } 201 202 // 203 // Save the interrupt handler. 204 // 205 g_pfnRAMVectors[interruptNumber] = intHandler; 206 } 207 208 void Interrupt_unregisterInterrupt(uint32_t interruptNumber) 209 { 210 // 211 // Check the arguments. 212 // 213 ASSERT(interruptNumber < (NUM_INTERRUPTS+1)); 214 215 // 216 // Reset the interrupt handler. 217 // 218 g_pfnRAMVectors[interruptNumber] = IntDefaultHandler; 219 } 220 221 void Interrupt_setPriorityGrouping(uint32_t bits) 222 { 223 // 224 // Check the arguments. 225 // 226 ASSERT(bits < NUM_PRIORITY); 227 228 // 229 // Set the priority grouping. 230 // 231 uint32_t reg_value; 232 uint32_t PriorityGroupTmp = g_pulPriority[bits]; 233 reg_value = SCB->AIRCR; /* read old register configuration */ 234 reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ 235 reg_value = (reg_value | 236 ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | 237 (PriorityGroupTmp << 8U) ); /* Insert write key and priority group */ 238 SCB->AIRCR = reg_value; 239 } 240 241 uint32_t Interrupt_getPriorityGrouping(void) 242 { 243 uint32_t ulLoop, ulValue; 244 245 // 246 // Read the priority grouping. 247 // 248 ulValue = SCB->AIRCR & NVIC_APINT_PRIGROUP_M; 249 250 // 251 // Loop through the priority grouping values. 252 // 253 for (ulLoop = 0; ulLoop < NUM_PRIORITY; ulLoop++) 254 { 255 // 256 // Stop looping if this value matches. 257 // 258 if (ulValue == g_pulPriority[ulLoop]) 259 { 260 break; 261 } 262 } 263 264 // 265 // Return the number of priority bits. 266 // 267 return (ulLoop); 268 } 269 270 void Interrupt_setPriority(uint32_t interruptNumber, uint8_t priority) 271 { 272 uint32_t ulTemp; 273 274 // 275 // Check the arguments. 276 // 277 ASSERT((interruptNumber >= 4) && (interruptNumber < (NUM_INTERRUPTS+1))); 278 279 // 280 // Set the interrupt priority. 281 // 282 ulTemp = HWREG32(g_pulRegs[interruptNumber >> 2]); 283 ulTemp &= ~(0xFF << (8 * (interruptNumber & 3))); 284 ulTemp |= priority << (8 * (interruptNumber & 3)); 285 HWREG32 (g_pulRegs[interruptNumber >> 2]) = ulTemp; 286 } 287 288 uint8_t Interrupt_getPriority(uint32_t interruptNumber) 289 { 290 // 291 // Check the arguments. 292 // 293 ASSERT((interruptNumber >= 4) && (interruptNumber < (NUM_INTERRUPTS+1))); 294 295 // 296 // Return the interrupt priority. 297 // 298 return ((HWREG32(g_pulRegs[interruptNumber >> 2]) 299 >> (8 * (interruptNumber & 3))) & 0xFF); 300 } 301 302 void Interrupt_enableInterrupt(uint32_t interruptNumber) 303 { 304 // 305 // Check the arguments. 306 // 307 ASSERT(interruptNumber < (NUM_INTERRUPTS+1)); 308 309 // 310 // Determine the interrupt to enable. 311 // 312 if (interruptNumber == FAULT_MPU) 313 { 314 // 315 // Enable the MemManage interrupt. 316 // 317 SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; 318 } else if (interruptNumber == FAULT_BUS) 319 { 320 // 321 // Enable the bus fault interrupt. 322 // 323 SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA_Msk; 324 } else if (interruptNumber == FAULT_USAGE) 325 { 326 // 327 // Enable the usage fault interrupt. 328 // 329 SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk; 330 } else if (interruptNumber == FAULT_SYSTICK) 331 { 332 // 333 // Enable the System Tick interrupt. 334 // 335 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; 336 } else if (interruptNumber >= 16) 337 { 338 // 339 // Enable the general interrupt. 340 // 341 HWREG32 (g_pulEnRegs[(interruptNumber - 16) / 32]) = 1 342 << ((interruptNumber - 16) & 31); 343 } 344 } 345 346 void Interrupt_disableInterrupt(uint32_t interruptNumber) 347 { 348 // 349 // Check the arguments. 350 // 351 ASSERT(interruptNumber < (NUM_INTERRUPTS+1)); 352 353 // 354 // Determine the interrupt to disable. 355 // 356 if (interruptNumber == FAULT_MPU) 357 { 358 // 359 // Disable the MemManage interrupt. 360 // 361 SCB->SHCSR &= ~(SCB_SHCSR_MEMFAULTENA_Msk); 362 } else if (interruptNumber == FAULT_BUS) 363 { 364 // 365 // Disable the bus fault interrupt. 366 // 367 SCB->SHCSR &= ~(SCB_SHCSR_BUSFAULTENA_Msk); 368 } else if (interruptNumber == FAULT_USAGE) 369 { 370 // 371 // Disable the usage fault interrupt. 372 // 373 SCB->SHCSR &= ~(SCB_SHCSR_USGFAULTENA_Msk); 374 } else if (interruptNumber == FAULT_SYSTICK) 375 { 376 // 377 // Disable the System Tick interrupt. 378 // 379 SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk); 380 } else if (interruptNumber >= 16) 381 { 382 // 383 // Disable the general interrupt. 384 // 385 HWREG32 (g_pulDisRegs[(interruptNumber - 16) / 32]) = 1 386 << ((interruptNumber - 16) & 31); 387 } 388 } 389 390 bool Interrupt_isEnabled(uint32_t interruptNumber) 391 { 392 uint32_t ulRet; 393 394 // 395 // Check the arguments. 396 // 397 ASSERT(interruptNumber < (NUM_INTERRUPTS+1)); 398 399 // 400 // Initialize the return value. 401 // 402 ulRet = 0; 403 404 // 405 // Determine the interrupt to disable. 406 // 407 if (interruptNumber == FAULT_MPU) 408 { 409 // 410 // Check the MemManage interrupt. 411 // 412 ulRet = SCB->SHCSR & SCB_SHCSR_MEMFAULTENA_Msk; 413 } else if (interruptNumber == FAULT_BUS) 414 { 415 // 416 // Check the bus fault interrupt. 417 // 418 ulRet = SCB->SHCSR & SCB_SHCSR_BUSFAULTENA_Msk; 419 } else if (interruptNumber == FAULT_USAGE) 420 { 421 // 422 // Check the usage fault interrupt. 423 // 424 ulRet = SCB->SHCSR & SCB_SHCSR_USGFAULTENA_Msk; 425 } else if (interruptNumber == FAULT_SYSTICK) 426 { 427 // 428 // Check the System Tick interrupt. 429 // 430 ulRet = SysTick->CTRL & SysTick_CTRL_ENABLE_Msk; 431 } else if (interruptNumber >= 16) 432 { 433 // 434 // Check the general interrupt. 435 // 436 ulRet = HWREG32(g_pulEnRegs[(interruptNumber - 16) / 32]) 437 & (1 << ((interruptNumber - 16) & 31)); 438 } 439 return (ulRet); 440 } 441 442 void Interrupt_pendInterrupt(uint32_t interruptNumber) 443 { 444 // 445 // Check the arguments. 446 // 447 ASSERT(interruptNumber < (NUM_INTERRUPTS+1)); 448 449 // 450 // Determine the interrupt to pend. 451 // 452 if (interruptNumber == FAULT_NMI) 453 { 454 // 455 // Pend the NMI interrupt. 456 // 457 SCB->ICSR |= SCB_ICSR_NMIPENDSET_Msk; 458 } else if (interruptNumber == FAULT_PENDSV) 459 { 460 // 461 // Pend the PendSV interrupt. 462 // 463 SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; 464 } else if (interruptNumber == FAULT_SYSTICK) 465 { 466 // 467 // Pend the SysTick interrupt. 468 // 469 SCB->ICSR |= SCB_ICSR_PENDSTSET_Msk; 470 } else if (interruptNumber >= 16) 471 { 472 // 473 // Pend the general interrupt. 474 // 475 HWREG32 (g_pulPendRegs[(interruptNumber - 16) / 32]) = 1 476 << ((interruptNumber - 16) & 31); 477 } 478 } 479 480 void Interrupt_unpendInterrupt(uint32_t interruptNumber) 481 { 482 // 483 // Check the arguments. 484 // 485 ASSERT(interruptNumber < (NUM_INTERRUPTS+1)); 486 487 // 488 // Determine the interrupt to unpend. 489 // 490 if (interruptNumber == FAULT_PENDSV) 491 { 492 // 493 // Unpend the PendSV interrupt. 494 // 495 SCB->ICSR |= SCB_ICSR_PENDSVCLR_Msk; 496 } else if (interruptNumber == FAULT_SYSTICK) 497 { 498 // 499 // Unpend the SysTick interrupt. 500 // 501 SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk; 502 } else if (interruptNumber >= 16) 503 { 504 // 505 // Unpend the general interrupt. 506 // 507 HWREG32 (g_pulUnpendRegs[(interruptNumber - 16) / 32]) = 1 508 << ((interruptNumber - 16) & 31); 509 } 510 } 511 512 void Interrupt_setPriorityMask(uint8_t priorityMask) 513 { 514 CPU_basepriSet(priorityMask); 515 } 516 517 uint8_t Interrupt_getPriorityMask(void) 518 { 519 return (CPU_basepriGet()); 520 } 521 522 void Interrupt_setVectorTableAddress(uint32_t addr) 523 { 524 SCB->VTOR = addr; 525 } 526 527 uint32_t Interrupt_getVectorTableAddress(void) 528 { 529 return SCB->VTOR; 530 } 531 532 void Interrupt_enableSleepOnIsrExit(void) 533 { 534 SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk; 535 } 536 537 void Interrupt_disableSleepOnIsrExit(void) 538 { 539 SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk; 540 } 541