1 /*
2 * Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 
7 /***********************************************************************************************************************
8  * Includes   <System Includes> , "Project Includes"
9  **********************************************************************************************************************/
10 #include "bsp_api.h"
11 
12 /** ELC event definitions. */
13 
14 /***********************************************************************************************************************
15  * Macro definitions
16  **********************************************************************************************************************/
17 #define BSP_IRQ_UINT32_MAX       (0xFFFFFFFFU)
18 #define BSP_PRV_BITS_PER_WORD    (32)
19 
20 /***********************************************************************************************************************
21  * Typedef definitions
22  **********************************************************************************************************************/
23 
24 /***********************************************************************************************************************
25  * Exported global variables (to be accessed by other files)
26  **********************************************************************************************************************/
27 
28 /* This table is used to store the context in the ISR. */
29 void * gp_renesas_isr_context[BSP_ICU_VECTOR_MAX_ENTRIES];
30 
31 /***********************************************************************************************************************
32  * Private global variables and functions
33  **********************************************************************************************************************/
34 const bsp_interrupt_event_t g_interrupt_event_link_select[BSP_ICU_VECTOR_MAX_ENTRIES] BSP_WEAK_REFERENCE =
35 {
36     (bsp_interrupt_event_t) 0
37 };
38 
39 /*******************************************************************************************************************//**
40  * @addtogroup BSP_MCU
41  *
42  * @{
43  **********************************************************************************************************************/
44 #if 0 == BSP_CFG_INLINE_IRQ_FUNCTIONS
45  #if BSP_FEATURE_ICU_HAS_IELSR
46 
47 /*******************************************************************************************************************//**
48  * Clear the interrupt status flag (IR) for a given interrupt. When an interrupt is triggered the IR bit
49  * is set. If it is not cleared in the ISR then the interrupt will trigger again immediately.
50  *
51  * @param[in] irq            Interrupt for which to clear the IR bit. Note that the enums listed for IRQn_Type are
52  *                           only those for the Cortex Processor Exceptions Numbers.
53  *
54  * @warning Do not call this function for system exceptions where the IRQn_Type value is < 0.
55  **********************************************************************************************************************/
56 void R_BSP_IrqStatusClear (IRQn_Type irq)
57 {
58     /* Clear the IR bit in the selected IELSR register. */
59     R_ICU->IELSR_b[irq].IR = 0U;
60 
61     /* Read back the IELSR register to ensure that the IR bit is cleared.
62      * See section "13.5.1 Operations During an Interrupt" in the RA8M1 manual R01UH0994EJ0100. */
63     FSP_REGISTER_READ(R_ICU->IELSR[irq]);
64 }
65 
66  #endif
67 
68 /*******************************************************************************************************************//**
69  * Clear the interrupt status flag (IR) for a given interrupt and clear the NVIC pending interrupt.
70  *
71  * @param[in] irq            Interrupt for which to clear the IR bit. Note that the enums listed for IRQn_Type are
72  *                           only those for the Cortex Processor Exceptions Numbers.
73  *
74  * @warning Do not call this function for system exceptions where the IRQn_Type value is < 0.
75  **********************************************************************************************************************/
76 BSP_SECTION_FLASH_GAP void R_BSP_IrqClearPending (IRQn_Type irq)
77 {
78  #if BSP_FEATURE_ICU_HAS_IELSR
79 
80     /* Clear the IR bit in the selected IELSR register. */
81     R_BSP_IrqStatusClear(irq);
82 
83     /* Flush memory transactions to ensure that the IR bit is cleared before clearing the pending bit in the NVIC. */
84     __DMB();
85  #endif
86 
87     /* The following statement is used in place of NVIC_ClearPendingIRQ to avoid including a branch for system
88      * exceptions every time an interrupt is cleared in the NVIC. */
89     uint32_t _irq = (uint32_t) irq;
90     NVIC->ICPR[(((uint32_t) irq) >> 5UL)] = (uint32_t) (1UL << (_irq & 0x1FUL));
91 }
92 
93 /*******************************************************************************************************************//**
94  * Sets the interrupt priority and context.
95  *
96  * @param[in] irq            The IRQ to configure.
97  * @param[in] priority       NVIC priority of the interrupt
98  * @param[in] p_context      The interrupt context is a pointer to data required in the ISR.
99  *
100  * @warning Do not call this function for system exceptions where the IRQn_Type value is < 0.
101  **********************************************************************************************************************/
102 BSP_SECTION_FLASH_GAP void R_BSP_IrqCfg (IRQn_Type const irq, uint32_t priority, void * p_context)
103 {
104     /* The following statement is used in place of NVIC_SetPriority to avoid including a branch for system exceptions
105      * every time a priority is configured in the NVIC. */
106  #if (4U == __CORTEX_M)
107     NVIC->IP[((uint32_t) irq)] = (uint8_t) ((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t) UINT8_MAX);
108  #elif (33 == __CORTEX_M)
109     NVIC->IPR[((uint32_t) irq)] = (uint8_t) ((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t) UINT8_MAX);
110  #elif (23 == __CORTEX_M)
111     NVIC->IPR[_IP_IDX(irq)] = ((uint32_t) (NVIC->IPR[_IP_IDX(irq)] & ~((uint32_t) UINT8_MAX << _BIT_SHIFT(irq))) |
112                                (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t) UINT8_MAX) << _BIT_SHIFT(irq)));
113  #else
114     NVIC_SetPriority(irq, priority);
115  #endif
116 
117     /* Store the context. The context is recovered in the ISR. */
118     R_FSP_IsrContextSet(irq, p_context);
119 }
120 
121 /*******************************************************************************************************************//**
122  * Enable the IRQ in the NVIC (Without clearing the pending bit).
123  *
124  * @param[in] irq            The IRQ to enable. Note that the enums listed for IRQn_Type are only those for the Cortex
125  *                           Processor Exceptions Numbers.
126  *
127  * @warning Do not call this function for system exceptions where the IRQn_Type value is < 0.
128  **********************************************************************************************************************/
129 BSP_SECTION_FLASH_GAP void R_BSP_IrqEnableNoClear (IRQn_Type const irq)
130 {
131     /* The following statement is used in place of NVIC_EnableIRQ to avoid including a branch for system exceptions
132      * every time an interrupt is enabled in the NVIC. */
133     uint32_t _irq = (uint32_t) irq;
134 
135     __COMPILER_BARRIER();
136     NVIC->ISER[(_irq >> 5UL)] = (uint32_t) (1UL << (_irq & 0x1FUL));
137     __COMPILER_BARRIER();
138 }
139 
140 /*******************************************************************************************************************//**
141  * Clears pending interrupts in both ICU and NVIC, then enables the interrupt.
142  *
143  * @param[in] irq            Interrupt for which to clear the IR bit and enable in the NVIC. Note that the enums listed
144  *                           for IRQn_Type are only those for the Cortex Processor Exceptions Numbers.
145  *
146  * @warning Do not call this function for system exceptions where the IRQn_Type value is < 0.
147  **********************************************************************************************************************/
148 BSP_SECTION_FLASH_GAP void R_BSP_IrqEnable (IRQn_Type const irq)
149 {
150     /* Clear pending interrupts in the ICU and NVIC. */
151     R_BSP_IrqClearPending(irq);
152 
153     /* Enable the IRQ in the NVIC. */
154     R_BSP_IrqEnableNoClear(irq);
155 }
156 
157 /*******************************************************************************************************************//**
158  * Disables interrupts in the NVIC.
159  *
160  * @param[in] irq            The IRQ to disable in the NVIC. Note that the enums listed for IRQn_Type are
161  *                           only those for the Cortex Processor Exceptions Numbers.
162  *
163  * @warning Do not call this function for system exceptions where the IRQn_Type value is < 0.
164  **********************************************************************************************************************/
165 BSP_SECTION_FLASH_GAP void R_BSP_IrqDisable (IRQn_Type const irq)
166 {
167     /* The following statements is used in place of NVIC_DisableIRQ to avoid including a branch for system
168      * exceptions every time an interrupt is cleared in the NVIC. */
169     uint32_t _irq = (uint32_t) irq;
170     NVIC->ICER[(((uint32_t) irq) >> 5UL)] = (uint32_t) (1UL << (_irq & 0x1FUL));
171 
172     __DSB();
173     __ISB();
174 }
175 
176 /*******************************************************************************************************************//**
177  * Sets the interrupt priority and context, clears pending interrupts, then enables the interrupt.
178  *
179  * @param[in] irq            Interrupt number.
180  * @param[in] priority       NVIC priority of the interrupt
181  * @param[in] p_context      The interrupt context is a pointer to data required in the ISR.
182  *
183  * @warning Do not call this function for system exceptions where the IRQn_Type value is < 0.
184  **********************************************************************************************************************/
185 BSP_SECTION_FLASH_GAP void R_BSP_IrqCfgEnable (IRQn_Type const irq, uint32_t priority, void * p_context)
186 {
187     R_BSP_IrqCfg(irq, priority, p_context);
188     R_BSP_IrqEnable(irq);
189 }
190 
191 #endif                                 // 0 == BSP_CFG_INLINE_IRQ_FUNCTIONS
192 
193 /** @} (end addtogroup BSP_MCU) */
194 
195 /*******************************************************************************************************************//**
196  *        Using the vector table information section that has been built by the linker and placed into ROM in the
197  * .vector_info. section, this function will initialize the ICU so that configured ELC events will trigger interrupts
198  * in the NVIC.
199  *
200  **********************************************************************************************************************/
bsp_irq_cfg(void)201 BSP_SECTION_FLASH_GAP void bsp_irq_cfg (void)
202 {
203 #if FSP_PRIV_TZ_USE_SECURE_REGS
204  #if (BSP_FEATURE_TZ_VERSION == 2 && BSP_TZ_SECURE_BUILD == 0)
205 
206     /* On MCUs with this implementation of TrustZone, IRQ security attribution is set to secure by default.
207      * This means that flat projects do not need to set security attribution to secure. */
208  #else
209 
210     /* Unprotect security registers. */
211     R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_SAR);
212 
213   #if !BSP_TZ_SECURE_BUILD
214 
215     /* Set the DMAC channels to secure access. */
216    #ifdef BSP_TZ_CFG_ICUSARC
217     R_CPSCU->ICUSARC = ~R_CPSCU_ICUSARC_SADMACn_Msk;
218    #endif
219   #endif
220 
221     /* Place all vectors in non-secure state unless they are used in the secure project. */
222     uint32_t interrupt_security_state[BSP_ICU_VECTOR_MAX_ENTRIES / BSP_PRV_BITS_PER_WORD];
223     memset(&interrupt_security_state, UINT8_MAX, sizeof(interrupt_security_state));
224 
225     for (uint32_t i = 0U; i < BSP_ICU_VECTOR_MAX_ENTRIES; i++)
226     {
227         if (0U != g_interrupt_event_link_select[i])
228         {
229             /* This is a secure vector. Clear the associated bit. */
230             uint32_t index = i / BSP_PRV_BITS_PER_WORD;
231             uint32_t bit   = i % BSP_PRV_BITS_PER_WORD;
232             interrupt_security_state[index] &= ~(1U << bit);
233         }
234     }
235 
236     /* The Secure Attribute managed within the ARM CPU NVIC must match the security attribution of IELSEn
237      * (Reference section 13.2.9 in the RA6M4 manual R01UH0890EJ0050). */
238     uint32_t volatile * p_icusarg = &R_CPSCU->ICUSARG;
239     for (uint32_t i = 0U; i < BSP_ICU_VECTOR_MAX_ENTRIES / BSP_PRV_BITS_PER_WORD; i++)
240     {
241         p_icusarg[i]  = interrupt_security_state[i];
242         NVIC->ITNS[i] = interrupt_security_state[i];
243     }
244 
245     /* Protect security registers. */
246     R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_SAR);
247  #endif
248 #endif
249 
250 #if BSP_FEATURE_ICU_HAS_IELSR
251     for (uint32_t i = 0U; i < (BSP_ICU_VECTOR_MAX_ENTRIES - BSP_FEATURE_ICU_FIXED_IELSR_COUNT); i++)
252     {
253         if (0U != g_interrupt_event_link_select[i])
254         {
255             R_ICU->IELSR[i] = (uint32_t) g_interrupt_event_link_select[i];
256         }
257     }
258 #endif
259 }
260