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