1 /*
2  * Copyright (c) 2009-2020 Arm Limited. All rights reserved.
3  *
4  * Portions Copyright (C) 2022-2024 Analog Devices, Inc.
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  *
8  * Licensed under the Apache License, Version 2.0 (the License); you may
9  * not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
16  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef LIBRARIES_CMSIS_INCLUDE_CORE_RV32_H_
22 #define LIBRARIES_CMSIS_INCLUDE_CORE_RV32_H_
23 
24 #if defined(__ICCARM__)
25 #pragma system_include /* treat file as system include file for MISRA check */
26 #endif
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 #ifndef __CORE_CM4_H_GENERIC
33 #define __CORE_CM4_H_GENERIC
34 
35 /** \page CMSIS_MISRA_Exceptions  MISRA-C:2004 Compliance Exceptions
36   CMSIS violates the following MISRA-C:2004 rules:
37 
38    \li Required Rule 8.5, object/function definition in header file.<br>
39      Function definitions in header files are used to allow 'inlining'.
40 
41    \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.<br>
42      Unions are used for effective representation of core registers.
43 
44    \li Advisory Rule 19.7, Function-like macro defined.<br>
45      Function-like macros are used to allow more efficient code.
46  */
47 
48 /*******************************************************************************
49  *                 CMSIS definitions
50  ******************************************************************************/
51 /** \ingroup Cortex_M4
52   @{
53  */
54 
55 #if defined(__CC_ARM)
56 // #define __ASM            __asm                                      /*!< asm keyword for ARM Compiler          */
57 // #define __INLINE         __inline                                   /*!< inline keyword for ARM Compiler       */
58 #define __STATIC_INLINE static __inline
59 
60 #elif defined(__ICCARM__)
61 // #define __ASM            __asm                                      /*!< asm keyword for IAR Compiler          */
62 // #define __INLINE         inline                                     /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
63 #define __STATIC_INLINE static inline
64 
65 #elif defined(__TMS470__)
66 // #define __ASM            __asm                                      /*!< asm keyword for TI CCS Compiler       */
67 #define __STATIC_INLINE static inline
68 
69 #elif defined(__GNUC__)
70 // #define __ASM            __asm                                      /*!< asm keyword for GNU Compiler          */
71 // #define __INLINE         inline                                     /*!< inline keyword for GNU Compiler       */
72 #define __STATIC_INLINE static inline
73 
74 #elif defined(__TASKING__)
75 // #define __ASM            __asm                                      /*!< asm keyword for TASKING Compiler      */
76 // #define __INLINE         inline                                     /*!< inline keyword for TASKING Compiler   */
77 #define __STATIC_INLINE static inline
78 
79 #endif
80 
81 /** __FPU_USED indicates whether an FPU is used or not. For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions.
82 */
83 #if defined(__CC_ARM)
84 #if defined __TARGET_FPU_VFP
85 #if (__FPU_PRESENT == 1)
86 #define __FPU_USED 1
87 #else
88 #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
89 #define __FPU_USED 0
90 #endif
91 #else
92 #define __FPU_USED 0
93 #endif
94 
95 #elif defined(__ICCARM__)
96 #if defined __ARMVFP__
97 #if (__FPU_PRESENT == 1)
98 #define __FPU_USED 1
99 #else
100 #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
101 #define __FPU_USED 0
102 #endif
103 #else
104 #define __FPU_USED 0
105 #endif
106 
107 #elif defined(__TMS470__)
108 #if defined __TI_VFP_SUPPORT__
109 #if (__FPU_PRESENT == 1)
110 #define __FPU_USED 1
111 #else
112 #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
113 #define __FPU_USED 0
114 #endif
115 #else
116 #define __FPU_USED 0
117 #endif
118 
119 #elif defined(__GNUC__)
120 #if defined(__VFP_FP__) && !defined(__SOFTFP__)
121 #if (__FPU_PRESENT == 1)
122 #define __FPU_USED 1
123 #else
124 #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
125 #define __FPU_USED 0
126 #endif
127 #else
128 #define __FPU_USED 0
129 #endif
130 
131 #elif defined(__TASKING__)
132 #if defined __FPU_VFP__
133 #if (__FPU_PRESENT == 1)
134 #define __FPU_USED 1
135 #else
136 #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
137 #define __FPU_USED 0
138 #endif
139 #else
140 #define __FPU_USED 0
141 #endif
142 #endif
143 
144 #include <stdint.h> /* standard types definitions                      */
145 //#include <core_cmInstr.h>                /* Core Instruction Access                         */
146 //#include <core_cmFunc.h>                 /* Core Function Access                            */
147 //#include <core_cm4_simd.h>               /* Compiler specific SIMD Intrinsics               */
148 
149 #endif /* __CORE_CM4_H_GENERIC */
150 
151 #ifndef __CMSIS_GENERIC
152 
153 #ifndef __CORE_CM4_H_DEPENDENT
154 #define __CORE_CM4_H_DEPENDENT
155 
156 /* check device defines and use defaults */
157 #if defined __CHECK_DEVICE_DEFINES
158 #ifndef __CM4_REV
159 #define __CM4_REV 0x0000
160 #warning "__CM4_REV not defined in device header file; using default!"
161 #endif
162 
163 #ifndef __FPU_PRESENT
164 #define __FPU_PRESENT 0
165 #warning "__FPU_PRESENT not defined in device header file; using default!"
166 #endif
167 
168 #ifndef __MPU_PRESENT
169 #define __MPU_PRESENT 0
170 #warning "__MPU_PRESENT not defined in device header file; using default!"
171 #endif
172 
173 #ifndef __NVIC_PRIO_BITS
174 #define __NVIC_PRIO_BITS 4
175 #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
176 #endif
177 
178 #ifndef __Vendor_SysTickConfig
179 #define __Vendor_SysTickConfig 0
180 #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
181 #endif
182 #endif
183 
184 /* IO definitions (access restrictions to peripheral registers) */
185 /**
186     \defgroup CMSIS_glob_defs CMSIS Global Defines
187 
188     <strong>IO Type Qualifiers</strong> are used
189     \li to specify the access to peripheral variables.
190     \li for automatic generation of peripheral register debug information.
191 */
192 #ifdef __cplusplus
193 #define __I volatile /*!< Defines 'read only' permissions                 */
194 #else
195 #define __I volatile const /*!< Defines 'read only' permissions                 */
196 #endif
197 #define __O volatile /*!< Defines 'write only' permissions                */
198 #define __IO volatile /*!< Defines 'read / write' permissions              */
199 
200 /*@} end of group Cortex_M4 */
201 
get_mstatus(void)202 __attribute__((always_inline)) __STATIC_INLINE uint32_t get_mstatus(void)
203 {
204     uint32_t retval;
205     __asm volatile("csrr %0, mstatus" : "=r"(retval));
206     return retval;
207 }
208 
get_mtvec(void)209 __attribute__((always_inline)) __STATIC_INLINE uint32_t get_mtvec(void)
210 {
211     uint32_t retval;
212     __asm volatile("csrr %0, mtvec" : "=r"(retval));
213     return retval;
214 }
215 
get_mepc(void)216 __attribute__((always_inline)) __STATIC_INLINE uint32_t get_mepc(void)
217 {
218     uint32_t retval;
219     __asm volatile("csrr %0, mepc" : "=r"(retval));
220     return retval;
221 }
222 
get_mcause(void)223 __attribute__((always_inline)) __STATIC_INLINE uint32_t get_mcause(void)
224 {
225     uint32_t retval;
226     __asm volatile("csrr %0, mcause" : "=r"(retval));
227     return retval;
228 }
229 
get_uepc(void)230 __attribute__((always_inline)) __STATIC_INLINE uint32_t get_uepc(void)
231 {
232     uint32_t retval;
233     __asm volatile("csrr %0, uepc" : "=r"(retval));
234     return retval;
235 }
236 
237 /** \brief  No Operation
238 
239     No Operation does nothing. This instruction can be used for code alignment purposes.
240  */
__NOP(void)241 __attribute__((always_inline)) __STATIC_INLINE void __NOP(void)
242 {
243     __asm volatile("nop");
244 }
245 
246 /** \brief  Wait For Interrupt
247 
248     Wait For Interrupt is a hint instruction that suspends execution
249     until one of a number of events occurs.
250  */
__WFI(void)251 __attribute__((always_inline)) __STATIC_INLINE void __WFI(void)
252 {
253     __asm volatile("wfi");
254 }
255 
256 /*******************************************************************************
257  *                 Register Abstraction
258   Core Register contain:
259   - Core NVIC Register
260 
261   // MLB - These have been purged from RISC V
262   - Core Register
263   - Core SCB Register
264   - Core SysTick Register
265   - Core Debug Register
266   - Core MPU Register
267   - Core FPU Register
268  ******************************************************************************/
269 
270 /** \ingroup    CMSIS_core_register
271     \defgroup   CMSIS_NVIC  Nested Vectored Interrupt Controller (NVIC)
272     \brief      Type definitions for the NVIC Registers
273   @{
274  */
275 
276 /**
277  * @brief Structure type to access the GCR Registers.
278  */
279 typedef struct {
280     __IO uint32_t irq0_enable; /**< <tt>\b 0x00:<\tt> */
281     __IO uint32_t irq0_pending; /**< <tt>\b 0x04:<\tt>  */
282     __IO uint32_t irq0_set_pending; /**< <tt>\b 0x08:<\tt>  */
283     __IO uint32_t irq0_clear_pending; /**< <tt>\b 0x0c:<\tt>  */
284     __IO uint32_t irq1_enable; /**< <tt>\b 0x10:<\tt> */
285     __IO uint32_t irq1_pending; /**< <tt>\b 0x14:<\tt>  */
286     __IO uint32_t irq1_set_pending; /**< <tt>\b 0x18:<\tt>  */
287     __IO uint32_t irq1_clear_pending; /**< <tt>\b 0x1c:<\tt>  */
288 } mxc_intr_regs_t;
289 
290 typedef struct {
291     __IO uint32_t event0_enable; /**< <tt>\b 0x20:<\tt>*/
292     __IO uint32_t event0_pending; /**< <tt>\b 0x24:<\tt> */
293     __IO uint32_t event0_set_pending; /**< <tt>\b 0x28:<\tt> */
294     __IO uint32_t event0_clear_pending; /**< <tt>\b 0x2C:<\tt> */
295     __IO uint32_t event1_enable; /**< <tt>\b 0x30:<\tt>*/
296     __IO uint32_t event1_pending; /**< <tt>\b 0x34:<\tt> */
297     __IO uint32_t event1_set_pending; /**< <tt>\b 0x38:<\tt> */
298     __IO uint32_t event1_clear_pending; /**< <tt>\b 0x3C:<\tt> */
299 } mxc_event_regs_t;
300 
301 typedef struct {
302     __IO uint32_t sleep_ctrl; /**< <tt>\b 0x40:<\tt>  */
303     __IO uint32_t sleep_status; /**< <tt>\b 0x44:<\tt>  */
304 } mxc_sleep_regs_t;
305 
306 /* Software Triggered Interrupt Register Definitions */
307 #define NVIC_STIR_INTID_Pos 0 /*!< STIR: INTLINESNUM Position */
308 #define NVIC_STIR_INTID_Msk (0x1FFUL << NVIC_STIR_INTID_Pos) /*!< STIR: INTLINESNUM Mask */
309 
310 /*@} end of group CMSIS_NVIC */
311 
312 /* For MCUs with extra RISCV core (RISCV1) */
313 #ifdef __riscv1
314 #define MXC_BASE_INTR ((uint32_t)0xE5170000UL)
315 #define MXC_BASE_EVENT ((uint32_t)0xE5170020UL)
316 #define MXC_BASE_SLEEP ((uint32_t)0xE5170040UL)
317 #else
318 #define MXC_BASE_INTR ((uint32_t)0xE5070000UL)
319 #define MXC_BASE_EVENT ((uint32_t)0xE5070020UL)
320 #define MXC_BASE_SLEEP ((uint32_t)0xE5070040UL)
321 #endif
322 
323 #define MXC_INTR ((mxc_intr_regs_t *)MXC_BASE_INTR)
324 #define MXC_EVENT ((mxc_event_regs_t *)MXC_BASE_EVENT)
325 #define MXC_SLEEP ((mxc_sleep_regs_t *)MXC_BASE_SLEEP)
326 
327 /*******************************************************************************
328  *                Hardware Abstraction Layer
329   Core Function Interface contains:
330   - Core NVIC Functions
331 
332   // MLB - These have been purged in RISC V
333   - Core SysTick Functions
334   - Core Debug Functions
335   - Core Register Access Functions
336  ******************************************************************************/
337 /** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
338 */
339 
340 /* ##########################   NVIC functions  #################################### */
341 /** \ingroup  CMSIS_Core_FunctionInterface
342     \defgroup CMSIS_Core_NVICFunctions NVIC Functions
343     \brief      Functions that manage interrupts and exceptions via the NVIC.
344     @{
345  */
346 // IRQn < 32
347 #define CLEAR_PENDING0(IRQn) MXC_INTR->irq0_clear_pending |= 1 << IRQn
348 // IRQ >= 32
349 #define CLEAR_PENDING1(IRQn) MXC_INTR->irq1_clear_pending |= 1 << (IRQn - 32)
350 
351 /** \brief  Enable External Interrupt
352 
353     The function enables a device-specific interrupt in the NVIC interrupt controller.
354 
355     \param [in]      IRQn  External interrupt number. Value cannot be negative.
356  */
NVIC_EnableIRQ(IRQn_Type IRQn)357 __STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
358 {
359     // MLB - Moved global enable into __enable_irq
360     // handled event specific enable here
361     if (IRQn < 32) {
362         MXC_INTR->irq0_enable |= (1 << IRQn);
363         MXC_EVENT->event0_enable |= (1 << IRQn);
364     } else {
365         MXC_INTR->irq1_enable |= (1 << (IRQn - 32));
366         MXC_EVENT->event1_enable |= (1 << (IRQn - 32));
367     }
368 }
369 
370 /** \brief  Disable External Interrupt
371 
372     The function disables a device-specific interrupt in the NVIC interrupt controller.
373 
374     \param [in]      IRQn  External interrupt number. Value cannot be negative.
375  */
NVIC_DisableIRQ(IRQn_Type IRQn)376 __STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
377 {
378     // MLB - Moved Global Disable into __disable_irq
379     // handled event specific interrupt here
380     if (IRQn < 32) {
381         MXC_INTR->irq0_enable &= ~(1 << IRQn);
382         MXC_EVENT->event0_enable &= ~(1 << IRQn);
383     } else {
384         MXC_INTR->irq1_enable &= ~(1 << (IRQn - 32));
385         MXC_EVENT->event1_enable &= ~(1 << (IRQn - 32));
386     }
387 }
388 
NVIC_EnableEVENT(IRQn_Type EVENT)389 __STATIC_INLINE void NVIC_EnableEVENT(IRQn_Type EVENT)
390 {
391     if (EVENT < 32)
392         MXC_EVENT->event0_enable |= (1 << EVENT);
393     else
394         MXC_EVENT->event1_enable |= (1 << (EVENT - 32));
395 }
396 
NVIC_DisableEVENT(IRQn_Type EVENT)397 __STATIC_INLINE void NVIC_DisableEVENT(IRQn_Type EVENT)
398 {
399     if (EVENT < 32)
400         MXC_EVENT->event0_enable &= ~(1 << EVENT);
401     else
402         MXC_EVENT->event1_enable &= ~(1 << (EVENT - 32));
403 }
404 
NVIC_ClearPendingEVENT(IRQn_Type EVENT)405 __STATIC_INLINE void NVIC_ClearPendingEVENT(IRQn_Type EVENT)
406 {
407     if (EVENT < 32)
408         MXC_EVENT->event0_clear_pending |= (1 << EVENT);
409     else
410         MXC_EVENT->event1_clear_pending |= (1 << (EVENT - 32));
411 }
412 
413 // Implemented in system_riscv_*.c
414 void __enable_irq(void);
415 
__disable_irq(void)416 __STATIC_INLINE void __disable_irq(void)
417 {
418     // Atomic disable
419     __asm volatile("csrw mstatus, 0x0");
420 
421     // Set the MPIE bit
422     int mstatus = 0x80;
423     __asm volatile("csrw mstatus, %0" : /* no output */ : "r"(mstatus));
424 }
425 
426 /** \brief  Get Pending Interrupt
427 
428     The function reads the pending register in the NVIC and returns the pending bit
429     for the specified interrupt.
430 
431     \param [in]      IRQn  Interrupt number.
432 
433     \return             0  Interrupt status is not pending.
434     \return             1  Interrupt status is pending.
435  */
NVIC_GetPendingIRQ(IRQn_Type IRQn)436 __STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
437 {
438     if (IRQn < 32)
439         return (MXC_INTR->irq0_pending & (1 << IRQn));
440     else
441         return (MXC_INTR->irq1_pending & (1 << (IRQn - 32)));
442 }
443 
444 /** \brief  Set Pending Interrupt
445 
446     The function sets the pending bit of an external interrupt.
447 
448     \param [in]      IRQn  Interrupt number. Value cannot be negative.
449  */
NVIC_SetPendingIRQ(IRQn_Type IRQn)450 __STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
451 {
452     //NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */
453 }
454 
455 /** \brief  Clear Pending Interrupt
456 
457     The function clears the pending bit of an external interrupt.
458 
459     \param [in]      IRQn  External interrupt number. Value cannot be negative.
460  */
NVIC_ClearPendingIRQ(IRQn_Type IRQn)461 __STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
462 {
463     //NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */
464     if (IRQn < 32) {
465         MXC_INTR->irq0_clear_pending |= (1 << IRQn);
466         MXC_EVENT->event0_clear_pending |= (1 << IRQn);
467     } else {
468         MXC_INTR->irq1_clear_pending |= (1 << (IRQn - 32));
469         MXC_EVENT->event1_clear_pending |= (1 << (IRQn - 32));
470     }
471 }
472 
473 /** \brief  Get Active Interrupt
474 
475     The function reads the active register in NVIC and returns the active bit.
476 
477     \param [in]      IRQn  Interrupt number.
478 
479     \return             0  Interrupt status is not active.
480     \return             1  Interrupt status is active.
481  */
NVIC_GetActive(IRQn_Type IRQn)482 __STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn)
483 {
484     return (
485         0); //((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */
486 }
487 
488 /** \brief  System Reset
489 
490     The function initiates a system reset request to reset the MCU.
491  */
NVIC_SystemReset(void)492 __STATIC_INLINE void NVIC_SystemReset(void)
493 {
494     //__DSB();                                                     /* Ensure all outstanding memory accesses included
495     //                                                                buffered write are completed before reset */
496     // SCB->AIRCR  = ((0x5FA << SCB_AIRCR_VECTKEY_Pos)      |
497     //               (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
498     //                SCB_AIRCR_SYSRESETREQ_Msk);                   /* Keep priority group unchanged */
499     //__DSB();                                                     /* Ensure completion of memory access */
500     while (1) {} /* wait until reset */
501 }
502 
503 /**
504   This function returns the content of the Performance Counter Mode Register (PCMR).
505  */
CSR_GetPCMR(void)506 __STATIC_INLINE uint32_t CSR_GetPCMR(void)
507 {
508     uint32_t reg;
509     __asm volatile("csrr %0, 0x7A1" : "=r"(reg));
510     return reg;
511 }
512 
513 /**
514   This function sets the content of the Performance Counter Mode Register (PCMR).
515  */
CSR_SetPCMR(uint32_t reg)516 __STATIC_INLINE void CSR_SetPCMR(uint32_t reg)
517 {
518     __asm volatile("csrw 0x7A1, %0" : /* no output */ : "r"(reg));
519 }
520 
521 /**
522   This function returns the content of the Performance Counter Event Register (PCER).
523  */
CSR_GetPCER(void)524 __STATIC_INLINE uint32_t CSR_GetPCER(void)
525 {
526     uint32_t reg;
527     __asm volatile("csrr %0, 0x7A0" : "=r"(reg));
528     return reg;
529 }
530 
531 /**
532   This function sets the content of the Performance Counter Event Register (PCER).
533  */
CSR_SetPCER(uint32_t reg)534 __STATIC_INLINE void CSR_SetPCER(uint32_t reg)
535 {
536     __asm volatile("csrw 0x7A0, %0" : /* no output */ : "r"(reg));
537 }
538 
539 /**
540   This function returns the content of the Performance Counter Counter Register (PCCR).
541  */
CSR_GetPCCR(void)542 __STATIC_INLINE uint32_t CSR_GetPCCR(void)
543 {
544     uint32_t reg;
545     __asm volatile("csrr %0, 0x780" : "=r"(reg));
546     return reg;
547 }
548 
549 /**
550   This function sets the content of the Performance Counter Counter Register (PCCR).
551  */
CSR_SetPCCR(uint32_t reg)552 __STATIC_INLINE void CSR_SetPCCR(uint32_t reg)
553 {
554     __asm volatile("csrw 0x780, %0" : /* no output */ : "r"(reg));
555 }
556 
557 /*@} end of CMSIS_Core_NVICFunctions */
558 
559 /*@} end of CMSIS_core_DebugFunctions */
560 
561 #endif /* __CORE_CM4_H_DEPENDENT */
562 
563 #endif /* __CMSIS_GENERIC */
564 
565 #ifdef __cplusplus
566 }
567 #endif
568 
569 #endif // LIBRARIES_CMSIS_INCLUDE_CORE_RV32_H_
570