IntcInterrupts_p0.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /**
  2. * FILE: IntcInterrupts_p1.c
  3. *
  4. * COPYRIGHT (c) 2002-2012 Freescale Semiconductor, Inc. All rights reserved.
  5. *
  6. * DESCRIPTION: Contains the implementations of the generic interrupt
  7. * controller handling routines for the e200z4 MCU . The __INTCInterruptHandler__
  8. * is located at no specific address and is branched by the PowerPC Zen core
  9. * to that location if the __initExternalInterrupts function has been called
  10. * to setup the core to do so.
  11. *
  12. *
  13. * Note: We use "_p0" suffix on functions and section names to reference the
  14. * Core_0, "_p1" for functions and section names using the Core_1.
  15. *
  16. * The following code setup the INTC module for Software Vector Mode.
  17. * To enable the Hardware Vector Mode please consult the Qorivva cookbook AN2865.
  18. *
  19. * VERSION: 1.2
  20. */
  21. #ifdef __cplusplus
  22. extern "C" {
  23. #endif
  24. /*---------------------------------------------------------------------------*/
  25. /* By default we do not use nested interrupts, interrupts are handled in C. */
  26. /* In case you want to use nested interrupts, set INTC_NESTED_INTERRUPT. */
  27. /* In this case make sure all the needed registers are saved in the prolog */
  28. /* and epilog of asm void INTC_INTCInterruptHandler(void) */
  29. /*---------------------------------------------------------------------------*/
  30. #ifndef INTC_NESTED_INTERRUPT
  31. #define INTC_NESTED_INTERRUPT 0
  32. #endif
  33. /*---------------------------------------------------------------------------*/
  34. /* Includes */
  35. /*---------------------------------------------------------------------------*/
  36. #include "MPC5646C.h" /* MPC55xx platform development header */
  37. #include "IntcInterrupts.h" /* Implement functions from this file */
  38. /*---------------------------------------------------------------------------*/
  39. /* Inline Assembler Defines */
  40. /*---------------------------------------------------------------------------*/
  41. /* This macro allows to use C defined address with the inline assembler */
  42. #define MAKE_HLI_ADDRESS(hli_name, c_expr) /*lint -e753 */enum { hli_name=/*lint -e30*/((int)(c_expr)) /*lint -esym(749, hli_name) */ };
  43. /* Address of the IACKR Interrupt Controller register. */
  44. MAKE_HLI_ADDRESS(INTC_IACKR, &INTC.IACKR_PRC0.R)
  45. /* Address of the EOIR End-of-Interrupt Register register. */
  46. MAKE_HLI_ADDRESS(INTC_EOIR, &INTC.EOIR_PRC0.R)
  47. /* INTC.MCR -- caution, VTES and HVEN for both cores are in this register */
  48. MAKE_HLI_ADDRESS(INTC_MCR, &INTC.MCR.R)
  49. /*----------------------------------------------------------------------------*/
  50. /* Function Implementations */
  51. /*----------------------------------------------------------------------------*/
  52. /* This is the interrupt service routine table used in software mode.
  53. The INTC supports 4 bytes or 8 byte entries, we will use 4 byte entries.
  54. The 4/8 bytes mode is configured in INTC_InitINTCInterrupts.
  55. */
  56. #define INTC_INTERRUPTS_REQUEST_VECTOR_TABLE_SIZE (278 * 4)
  57. #pragma push /* Save the current state */
  58. #pragma section data_type ".__initialized_intc_handlertable" ".__uninitialized_intc_handlertable"
  59. /* The INTC vector table will be placed in RAM.
  60. We will use the ".__uninitialized_intc_handlertable" name to do the
  61. placement in the Linker Command File (.lcf) to avoid the initialization at
  62. startup time. This will decrease the code size, but the table won't be
  63. initialized to zero.
  64. */
  65. INTCInterruptFn INTCInterruptsHandlerTable[INTC_INTERRUPTS_REQUEST_VECTOR_TABLE_SIZE];
  66. #pragma pop
  67. #pragma push /* save the current state */
  68. #pragma force_active on /* make sure this function remains */
  69. #pragma function_align 16 /* We use 16 bytes alignment for Exception handlers */
  70. /** Handle the interrupt source by jumping to the ISR branch table (IACKR) */
  71. #if INTC_NESTED_INTERRUPT == 0
  72. __declspec(section ".__exception_handlers_p0")
  73. __declspec(interrupt)
  74. void INTC_INTCInterruptHandler(void)
  75. {
  76. INTCInterruptFn handlerFn;
  77. handlerFn = INTCInterruptsHandlerTable[INTC.IACKR_PRC0.R/4];
  78. (**handlerFn)();
  79. INTC.EOIR_PRC0.R = 0;
  80. }
  81. #else
  82. __declspec(interrupt)
  83. __declspec(section ".__exception_handlers_p0")
  84. __asm void INTC_INTCInterruptHandler(void)
  85. {
  86. nofralloc
  87. prolog:
  88. stwu r1, -0x50 (r1) /* Create stack frame */
  89. stw r0, 0x24 (r1) /* Store r0 working register */
  90. /* Save SRR0 and SRR1 */
  91. mfsrr1 r0 /* Store SRR1 (before enabling EE) */
  92. stw r0, 0x10 (r1)
  93. mfsrr0 r0 /* Store SRR0 (before enabling EE) */
  94. stw r0, 0x0C (r1)
  95. /* Clear request to processor; r3 contains the address of the ISR */
  96. stw r3, 0x28 (r1) /* Store r3 to work with */
  97. lis r3, INTC_IACKR@ha /* Read pointer into ISR Vector Table */
  98. lwz r3, INTC_IACKR@l(r3) /* Load INTC_IACKR, which clears request to processor */
  99. lwz r3, 0x0(r3) /* Read ISR address from ISR Vector Table using pointer */
  100. // lwz r3, 0x400088c6
  101. /* Enable processor recognition of interrupts */
  102. wrteei 1 /* Set MSR[EE]=1 */
  103. /* Save rest of context required by EABI */
  104. stw r12, 0x4C (r1) /* Store r12 */
  105. stw r11, 0x48 (r1) /* Store r11 */
  106. stw r10, 0x44 (r1) /* Store r10 */
  107. stw r9, 0x40 (r1) /* Store r9 */
  108. stw r8, 0x3C (r1) /* Store r8 */
  109. stw r7, 0x38 (r1) /* Store r7 */
  110. stw r6, 0x34 (r1) /* Store r6 */
  111. stw r5, 0x30 (r1) /* Store r5 */
  112. stw r4, 0x2C (r1) /* Store r4 */
  113. mfcr r0 /* Store CR */
  114. stw r0, 0x20 (r1)
  115. mfxer r0 /* Store XER */
  116. stw r0, 0x1C (r1)
  117. mfctr r0 /* Store CTR */
  118. stw r0, 0x18 (r1)
  119. mflr r0 /* Store LR */
  120. stw r0, 0x14 (r1)
  121. /* Branch to ISR handler address from SW vector table */
  122. mtlr r3 /* Store ISR address to LR */
  123. blrl /* Branch to ISR, but return here */
  124. epilog:
  125. /* Restore context required by EABI (except working registers) */
  126. lwz r0, 0x14 (r1) /* Restore LR */
  127. mtlr r0
  128. lwz r0, 0x18 (r1) /* Restore CTR */
  129. mtctr r0
  130. lwz r0, 0x1C (r1) /* Restore XER */
  131. mtxer r0
  132. lwz r0, 0x20 (r1) /* Restore CR */
  133. mtcrf 0xff, r0
  134. lwz r5, 0x30 (r1) /* Restore r5 */
  135. lwz r6, 0x34 (r1) /* Restore r6 */
  136. lwz r7, 0x38 (r1) /* Restore r7 */
  137. lwz r8, 0x3C (r1) /* Restore r8 */
  138. lwz r9, 0x40 (r1) /* Restore r9 */
  139. lwz r10, 0x44 (r1) /* Restore r10 */
  140. lwz r11, 0x48 (r1) /* Restore r11 */
  141. lwz r12, 0x4C (r1) /* Restore r12 */
  142. /* Disable processor recognition of interrupts */
  143. wrteei 0
  144. /* Ensure interrupt flag has finished clearing */
  145. mbar 0
  146. /* Write 0 to INTC_EOIR, informing INTC to lower priority */
  147. li r3, 0
  148. lis r4, INTC_EOIR@ha /* Load upper half of INTC_EOIR address */
  149. stw r3, INTC_EOIR@l(r4) /* Write 0 to INTC_EOIR */
  150. /* Restore Working Registers */
  151. lwz r3, 0x28 (r1) /* Restore r3 */
  152. lwz r4, 0x2C (r1) /* Restore r4 */
  153. /* Retrieve SRR0 and SRR1 */
  154. lwz r0, 0x0C (r1) /* Restore SRR0 */
  155. mtsrr0 r0
  156. lwz r0, 0x10 (r1) /* Restore SRR1 */
  157. mtsrr1 r0
  158. /* Restore Other Working Registers */
  159. lwz r0, 0x24 (r1) /* Restore r0 */
  160. /* Restore space on stack */
  161. addi r1, r1, 0x50
  162. /* End of Interrupt */
  163. rfi
  164. }
  165. #endif
  166. #pragma force_active off
  167. #pragma pop
  168. /**
  169. * This function can be used to install an interrupt handler for a given
  170. * interrupt vector. It will also set the Priority Status Register for the
  171. * source to the one given
  172. */
  173. void INTC_InstallINTCInterruptHandler(INTCInterruptFn handlerFn, unsigned short vectorNum,
  174. unsigned char psrPriority)
  175. {
  176. /* Set the function pointer in the ISR Handler table */
  177. INTCInterruptsHandlerTable[vectorNum] = handlerFn;
  178. /* Set the PSR Priority */
  179. INTC.PSR[vectorNum].B.PRI = psrPriority;
  180. }
  181. /**
  182. * This function will setup INTC for Software Vector Mode and
  183. * the Vector Table Base Address to INTCInterruptsHandlerTable_p1.
  184. * This function can be used from user_init() (no stack frame, no memory access).
  185. *
  186. * Note the MCR is common to both cores so we just clear the flags for core 1.
  187. */
  188. __asm void INTC_InitINTCInterrupts( void )
  189. {
  190. nofralloc
  191. /* Set the location of the ISR Handler Table in INTC IACKR Register */
  192. lis r0, INTCInterruptsHandlerTable@ha
  193. ori r0, r0, INTCInterruptsHandlerTable@l
  194. lis r3,INTC_IACKR@ha
  195. stw r0, INTC_IACKR@l(r3)
  196. /* Set INTC.MCR.B.HVEN_PRC0 = 0 for SW vector mode */
  197. /* and INTC.MCR.B.VTES_PRC0 = 0 for 4-byte branch table entries. */
  198. lis r3, INTC_MCR@ha
  199. lwz r0, INTC_MCR@l(r3)
  200. /* clear VTES and HVEN flags for core 0*/
  201. andi. r0, r0, 0xFF00
  202. stw r0, INTC_MCR@l(r3)
  203. /* Enable external interrupts by setting MSR[EE] = 1. */
  204. wrteei 0
  205. blr
  206. }
  207. #ifdef __cplusplus
  208. }
  209. #endif