1 /*
2  * Copyright (C) 2017-2019 Alibaba Group Holding Limited
3  */
4 
5 
6 /******************************************************************************
7  * @file     core_rv64.h
8  * @brief    CSI RV32 Core Peripheral Access Layer Header File
9  * @version  V1.0
10  * @date     01. Sep 2018
11  ******************************************************************************/
12 
13 #ifndef __CORE_RV32_H_GENERIC
14 #define __CORE_RV32_H_GENERIC
15 
16 #include <stdint.h>
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 /*******************************************************************************
23  *                 CSI definitions
24  ******************************************************************************/
25 /**
26   \ingroup RV32
27   @{
28  */
29 
30 #ifndef __RV64
31 #define __RV64                (0x01U)
32 #endif
33 
34 /** __FPU_USED indicates whether an FPU is used or not.
35     This core does not support an FPU at all
36 */
37 #define __FPU_USED       0U
38 
39 #if defined ( __GNUC__ )
40 #if defined (__VFP_FP__) && !defined(__SOFTFP__)
41 #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
42 #endif
43 #endif
44 
45 #ifdef __cplusplus
46 }
47 #endif
48 
49 #endif /* __CORE_RV32_H_GENERIC */
50 
51 #ifndef __CSI_GENERIC
52 
53 #ifndef __CORE_RV32_H_DEPENDANT
54 #define __CORE_RV32_H_DEPENDANT
55 
56 #ifdef __cplusplus
57 extern "C" {
58 #endif
59 
60 /* check device defines and use defaults */
61 #ifndef __RV64_REV
62 #define __RV64_REV               0x0000U
63 #endif
64 
65 #ifndef __VIC_PRIO_BITS
66 #define __VIC_PRIO_BITS           2U
67 #endif
68 
69 #ifndef __Vendor_SysTickConfig
70 #define __Vendor_SysTickConfig    1U
71 #endif
72 
73 #ifndef __MPU_PRESENT
74 #define __MPU_PRESENT             1U
75 #endif
76 
77 #ifndef __ICACHE_PRESENT
78 #define __ICACHE_PRESENT          1U
79 #endif
80 
81 #ifndef __DCACHE_PRESENT
82 #define __DCACHE_PRESENT          1U
83 #endif
84 
85 
86 #ifndef __L2CACHE_PRESENT
87 #define __L2CACHE_PRESENT          1U
88 #endif
89 
90 #include <csi_rv64_gcc.h>
91 
92 /* IO definitions (access restrictions to peripheral registers) */
93 /**
94     \defgroup CSI_glob_defs CSI Global Defines
95 
96     <strong>IO Type Qualifiers</strong> are used
97     \li to specify the access to peripheral variables.
98     \li for automatic generation of peripheral register debug information.
99 */
100 #ifdef __cplusplus
101 #define     __I      volatile             /*!< Defines 'read only' permissions */
102 #else
103 #define     __I      volatile const       /*!< Defines 'read only' permissions */
104 #endif
105 #define     __O      volatile             /*!< Defines 'write only' permissions */
106 #define     __IO     volatile             /*!< Defines 'read / write' permissions */
107 
108 /* following defines should be used for structure members */
109 #define     __IM     volatile const       /*! Defines 'read only' structure member permissions */
110 #define     __OM     volatile             /*! Defines 'write only' structure member permissions */
111 #define     __IOM    volatile             /*! Defines 'read / write' structure member permissions */
112 
113 /*@} end of group C910 */
114 
115 /*******************************************************************************
116  *                 Register Abstraction
117   Core Register contain:
118   - Core Register
119   - Core CLINT Register
120  ******************************************************************************/
121 /**
122   \defgroup CSI_core_register Defines and Type Definitions
123   \brief Type definitions and defines for CK80X processor based devices.
124 */
125 
126 /**
127   \ingroup    CSI_core_register
128   \defgroup   CSI_CORE  Status and Control Registers
129   \brief      Core Register type definitions.
130   @{
131  */
132 
133 /**
134   \ingroup    CSI_core_register
135   \defgroup   CSI_CLINT Core-Local Interrupt Controller (CLINT)
136   \brief      Type definitions for the CLINT Registers
137   @{
138  */
139 
140 /**
141   \brief Access to the structure of a vector interrupt controller.
142  */
143 
144 typedef struct {
145     uint32_t RESERVED0;                 /*!< Offset: 0x000 (R/W)  CLINT configure register */
146     __IOM uint32_t PLIC_PRIO[1023];
147     __IOM uint32_t PLIC_IP[32];
148     uint32_t RESERVED1[3972/4 - 1];
149     __IOM uint32_t PLIC_H0_MIE[32];
150     __IOM uint32_t PLIC_H0_SIE[32];
151     __IOM uint32_t PLIC_H1_MIE[32];
152     __IOM uint32_t PLIC_H1_SIE[32];
153     __IOM uint32_t PLIC_H2_MIE[32];
154     __IOM uint32_t PLIC_H2_SIE[32];
155     __IOM uint32_t PLIC_H3_MIE[32];
156     __IOM uint32_t PLIC_H3_SIE[32];
157     uint32_t RESERVED2[(0x01FFFFC-0x00023FC)/4 - 1];
158     __IOM uint32_t PLIC_PER;
159     __IOM uint32_t PLIC_H0_MTH;
160     __IOM uint32_t PLIC_H0_MCLAIM;
161     uint32_t RESERVED3[0xFFC/4 - 1];
162     __IOM uint32_t PLIC_H0_STH;
163     __IOM uint32_t PLIC_H0_SCLAIM;
164     uint32_t RESERVED4[0xFFC/4 - 1];
165 
166     __IOM uint32_t PLIC_H1_MTH;
167     __IOM uint32_t PLIC_H1_MCLAIM;
168     uint32_t RESERVED5[0xFFC/4 - 1];
169     __IOM uint32_t PLIC_H1_STH;
170     __IOM uint32_t PLIC_H1_SCLAIM;
171     uint32_t RESERVED6[0xFFC/4 - 1];
172 
173     __IOM uint32_t PLIC_H2_MTH;
174     __IOM uint32_t PLIC_H2_MCLAIM;
175     uint32_t RESERVED7[0xFFC/4 - 1];
176     __IOM uint32_t PLIC_H2_STH;
177     __IOM uint32_t PLIC_H2_SCLAIM;
178     uint32_t RESERVED8[0xFFC/4 - 1];
179 
180     __IOM uint32_t PLIC_H3_MTH;
181     __IOM uint32_t PLIC_H3_MCLAIM;
182     uint32_t RESERVED9[0xFFC/4 - 1];
183     __IOM uint32_t PLIC_H3_STH;
184     __IOM uint32_t PLIC_H3_SCLAIM;
185     uint32_t RESERVED10[0xFFC/4 - 1];
186 } PLIC_Type;
187 
188 
189 /**
190   \ingroup    CSI_core_register
191   \defgroup   CSI_PMP Physical Memory Protection (PMP)
192   \brief      Type definitions for the PMP Registers
193   @{
194  */
195 
196 #define PMP_PMPCFG_R_Pos                       0U                                    /*!< PMP PMPCFG: R Position */
197 #define PMP_PMPCFG_R_Msk                       (0x1UL << PMP_PMPCFG_R_Pos)           /*!< PMP PMPCFG: R Mask */
198 
199 #define PMP_PMPCFG_W_Pos                       1U                                    /*!< PMP PMPCFG: W Position */
200 #define PMP_PMPCFG_W_Msk                       (0x1UL << PMP_PMPCFG_W_Pos)           /*!< PMP PMPCFG: W Mask */
201 
202 #define PMP_PMPCFG_X_Pos                       2U                                    /*!< PMP PMPCFG: X Position */
203 #define PMP_PMPCFG_X_Msk                       (0x1UL << PMP_PMPCFG_X_Pos)           /*!< PMP PMPCFG: X Mask */
204 
205 #define PMP_PMPCFG_A_Pos                       3U                                    /*!< PMP PMPCFG: A Position */
206 #define PMP_PMPCFG_A_Msk                       (0x3UL << PMP_PMPCFG_A_Pos)           /*!< PMP PMPCFG: A Mask */
207 
208 #define PMP_PMPCFG_L_Pos                       7U                                    /*!< PMP PMPCFG: L Position */
209 #define PMP_PMPCFG_L_Msk                       (0x1UL << PMP_PMPCFG_L_Pos)           /*!< PMP PMPCFG: L Mask */
210 
211 typedef enum {
212     REGION_SIZE_4B       = -1,
213     REGION_SIZE_8B       = 0,
214     REGION_SIZE_16B      = 1,
215     REGION_SIZE_32B      = 2,
216     REGION_SIZE_64B      = 3,
217     REGION_SIZE_128B     = 4,
218     REGION_SIZE_256B     = 5,
219     REGION_SIZE_512B     = 6,
220     REGION_SIZE_1KB      = 7,
221     REGION_SIZE_2KB      = 8,
222     REGION_SIZE_4KB      = 9,
223     REGION_SIZE_8KB      = 10,
224     REGION_SIZE_16KB     = 11,
225     REGION_SIZE_32KB     = 12,
226     REGION_SIZE_64KB     = 13,
227     REGION_SIZE_128KB    = 14,
228     REGION_SIZE_256KB    = 15,
229     REGION_SIZE_512KB    = 16,
230     REGION_SIZE_1MB      = 17,
231     REGION_SIZE_2MB      = 18,
232     REGION_SIZE_4MB      = 19,
233     REGION_SIZE_8MB      = 20,
234     REGION_SIZE_16MB     = 21,
235     REGION_SIZE_32MB     = 22,
236     REGION_SIZE_64MB     = 23,
237     REGION_SIZE_128MB    = 24,
238     REGION_SIZE_256MB    = 25,
239     REGION_SIZE_512MB    = 26,
240     REGION_SIZE_1GB      = 27,
241     REGION_SIZE_2GB      = 28,
242     REGION_SIZE_4GB      = 29,
243     REGION_SIZE_8GB      = 30,
244     REGION_SIZE_16GB     = 31
245 } region_size_e;
246 
247 typedef enum {
248     ADDRESS_MATCHING_TOR   = 1,
249     ADDRESS_MATCHING_NAPOT = 3
250 } address_matching_e;
251 
252 typedef struct {
253     uint32_t r: 1;           /* readable enable */
254     uint32_t w: 1;           /* writeable enable */
255     uint32_t x: 1;           /* execable enable */
256     address_matching_e a: 2; /* address matching mode */
257     uint32_t reserved: 2;    /* reserved */
258     uint32_t l: 1;           /* lock enable */
259 } mpu_region_attr_t;
260 
261 /*@} end of group CSI_PMP */
262 
263 /* CACHE Register Definitions */
264 #define CACHE_MHCR_WBR_Pos                     8U                                            /*!< CACHE MHCR: WBR Position */
265 #define CACHE_MHCR_WBR_Msk                     (0x1UL << CACHE_MHCR_WBR_Pos)                 /*!< CACHE MHCR: WBR Mask */
266 
267 #define CACHE_MHCR_IBPE_Pos                    7U                                            /*!< CACHE MHCR: IBPE Position */
268 #define CACHE_MHCR_IBPE_Msk                    (0x1UL << CACHE_MHCR_IBPE_Pos)                /*!< CACHE MHCR: IBPE Mask */
269 
270 #define CACHE_MHCR_L0BTB_Pos                   6U                                            /*!< CACHE MHCR: L0BTB Position */
271 #define CACHE_MHCR_L0BTB_Msk                   (0x1UL << CACHE_MHCR_L0BTB_Pos)               /*!< CACHE MHCR: BTB Mask */
272 
273 #define CACHE_MHCR_BPE_Pos                     5U                                            /*!< CACHE MHCR: BPE Position */
274 #define CACHE_MHCR_BPE_Msk                     (0x1UL << CACHE_MHCR_BPE_Pos)                 /*!< CACHE MHCR: BPE Mask */
275 
276 #define CACHE_MHCR_RS_Pos                      4U                                            /*!< CACHE MHCR: RS Position */
277 #define CACHE_MHCR_RS_Msk                      (0x1UL << CACHE_MHCR_RS_Pos)                  /*!< CACHE MHCR: RS Mask */
278 
279 #define CACHE_MHCR_WB_Pos                      3U                                            /*!< CACHE MHCR: WB Position */
280 #define CACHE_MHCR_WB_Msk                      (0x1UL << CACHE_MHCR_WB_Pos)                  /*!< CACHE MHCR: WB Mask */
281 
282 #define CACHE_MHCR_WA_Pos                      2U                                            /*!< CACHE MHCR: WA Position */
283 #define CACHE_MHCR_WA_Msk                      (0x1UL << CACHE_MHCR_WA_Pos)                  /*!< CACHE MHCR: WA Mask */
284 
285 #define CACHE_MHCR_DE_Pos                      1U                                            /*!< CACHE MHCR: DE Position */
286 #define CACHE_MHCR_DE_Msk                      (0x1UL << CACHE_MHCR_DE_Pos)                  /*!< CACHE MHCR: DE Mask */
287 
288 #define CACHE_MHCR_IE_Pos                      0U                                            /*!< CACHE MHCR: IE Position */
289 #define CACHE_MHCR_IE_Msk                      (0x1UL << CACHE_MHCR_IE_Pos)                  /*!< CACHE MHCR: IE Mask */
290 
291 #define CACHE_INV_ADDR_Pos                     5U
292 #define CACHE_INV_ADDR_Msk                     (0xFFFFFFFFUL << CACHE_INV_ADDR_Pos)
293 
294 /*@} end of group CSI_CACHE */
295 
296 
297 /**
298   \ingroup  CSI_core_register
299   \defgroup CSI_SysTick     System Tick Timer (CORET)
300   \brief    Type definitions for the System Timer Registers.
301   @{
302  */
303 
304 /**
305   \brief  The data structure of the access system timer.
306  */
307 typedef struct {
308 	__IOM uint32_t MSIP0;
309 	__IOM uint32_t MSIP1;
310 	__IOM uint32_t MSIP2;
311 	__IOM uint32_t MSIP3;
312 	uint32_t RESERVED0[(0x4004000-0x400000C)/4 - 1];
313 	__IOM uint32_t MTIMECMPL0;
314 	__IOM uint32_t MTIMECMPH0;
315 	__IOM uint32_t MTIMECMPL1;
316 	__IOM uint32_t MTIMECMPH1;
317 	__IOM uint32_t MTIMECMPL2;
318 	__IOM uint32_t MTIMECMPH2;
319 	__IOM uint32_t MTIMECMPL3;
320 	__IOM uint32_t MTIMECMPH3;
321 	uint32_t RESERVED1[(0x400C000-0x400401C)/4 - 1];
322 	__IOM uint32_t SSIP0;
323 	__IOM uint32_t SSIP1;
324 	__IOM uint32_t SSIP2;
325 	__IOM uint32_t SSIP3;
326 	uint32_t RESERVED2[(0x400D000-0x400C00C)/4 - 1];
327 	__IOM uint32_t STIMECMPL0;
328 	__IOM uint32_t STIMECMPH0;
329 	__IOM uint32_t STIMECMPL1;
330 	__IOM uint32_t STIMECMPH1;
331 	__IOM uint32_t STIMECMPL2;
332 	__IOM uint32_t STIMECMPH2;
333 	__IOM uint32_t STIMECMPL3;
334 	__IOM uint32_t STIMECMPH3;
335 } CORET_Type;
336 /*@} end of group CSI_SysTick */
337 
338 
339 /**
340   \ingroup    CSI_core_register
341   \defgroup   CSI_core_bitfield     Core register bit field macros
342   \brief      Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
343   @{
344  */
345 
346 /**
347   \brief   Mask and shift a bit field value for use in a register bit range.
348   \param[in] field  Name of the register bit field.
349   \param[in] value  Value of the bit field.
350   \return           Masked and shifted value.
351 */
352 #define _VAL2FLD(field, value)    ((value << field ## _Pos) & field ## _Msk)
353 
354 /**
355   \brief     Mask and shift a register value to extract a bit filed value.
356   \param[in] field  Name of the register bit field.
357   \param[in] value  Value of register.
358   \return           Masked and shifted bit field value.
359 */
360 #define _FLD2VAL(field, value)    ((value & field ## _Msk) >> field ## _Pos)
361 
362 /*@} end of group CSI_core_bitfield */
363 
364 /**
365   \ingroup    CSI_core_register
366   \defgroup   CSI_core_base     Core Definitions
367   \brief      Definitions for base addresses, unions, and structures.
368   @{
369  */
370 #define CORET_BASE          (PLIC_BASE + 0x4000000UL)                            /*!< CORET Base Address */
371 #define PLIC_BASE           (0x4000000000UL)                          /*!< PLIC Base Address */
372 
373 #define CORET               ((CORET_Type   *)     CORET_BASE  )       /*!< SysTick configuration struct */
374 #define CLINT               ((CLINT_Type    *)    CLINT_BASE   )       /*!< CLINT configuration struct */
375 #define PLIC                ((PLIC_Type    *)     PLIC_BASE   )       /*!< PLIC configuration struct */
376 
377 /*@} */
378 
379 /*******************************************************************************
380  *                Hardware Abstraction Layer
381   Core Function Interface contains:
382   - Core VIC Functions
383   - Core CORET Functions
384   - Core Register Access Functions
385  ******************************************************************************/
386 /**
387   \defgroup CSI_Core_FunctionInterface Functions and Instructions Reference
388 */
389 
390 /* ##########################   VIC functions  #################################### */
391 /**
392   \ingroup  CSI_Core_FunctionInterface
393   \defgroup CSI_Core_VICFunctions VIC Functions
394   \brief    Functions that manage interrupts and exceptions via the VIC.
395   @{
396  */
397 
398 /* The following MACROS handle generation of the register offset and byte masks */
399 #define _BIT_SHIFT(IRQn)         (  ((((uint32_t)(int32_t)(IRQn))         )      &  0x03UL) * 8UL)
400 #define _IP_IDX(IRQn)            (   (((uint32_t)(int32_t)(IRQn))                >>    5UL)      )
401 #define _IP2_IDX(IRQn)            (   (((uint32_t)(int32_t)(IRQn))                >>    2UL)      )
402 
403 /**
404   \brief   Enable External Interrupt
405   \details Enable a device-specific interrupt in the VIC interrupt controller.
406   \param [in]      IRQn  External interrupt number. Value cannot be negative.
407  */
csi_vic_enable_irq(int32_t IRQn)408 __STATIC_INLINE void csi_vic_enable_irq(int32_t IRQn)
409 {
410     PLIC->PLIC_H0_MIE[IRQn/32] = PLIC->PLIC_H0_MIE[IRQn/32] | (0x1 << (IRQn%32));
411 }
412 
413 /**
414   \brief   Disable External Interrupt
415   \details Disable a device-specific interrupt in the VIC interrupt controller.
416   \param [in]      IRQn  External interrupt number. Value cannot be negative.
417  */
csi_vic_disable_irq(int32_t IRQn)418 __STATIC_INLINE void csi_vic_disable_irq(int32_t IRQn)
419 {
420     PLIC->PLIC_H0_MIE[IRQn/32] = PLIC->PLIC_H0_MIE[IRQn/32] & (~(0x1 << (IRQn%32)));
421 }
422 
423 /**
424   \brief   Enable External Secure Interrupt
425   \details Enable a secure device-specific interrupt in the VIC interrupt controller.
426   \param [in]      IRQn  External interrupt number. Value cannot be negative.
427  */
csi_vic_enable_sirq(int32_t IRQn)428 __STATIC_INLINE void csi_vic_enable_sirq(int32_t IRQn)
429 {
430 	csi_vic_enable_irq(IRQn);
431 }
432 
433 /**
434   \brief   Disable External Secure Interrupt
435   \details Disable a secure device-specific interrupt in the VIC interrupt controller.
436   \param [in]      IRQn  External interrupt number. Value cannot be negative.
437  */
csi_vic_disable_sirq(int32_t IRQn)438 __STATIC_INLINE void csi_vic_disable_sirq(int32_t IRQn)
439 {
440     csi_vic_disable_irq(IRQn);
441 }
442 
443 /**
444   \brief   Check Interrupt is Enabled or not
445   \details Read the enabled register in the VIC and returns the pending bit for the specified interrupt.
446   \param [in]      IRQn  Interrupt number.
447   \return             0  Interrupt status is not enabled.
448   \return             1  Interrupt status is enabled.
449  */
csi_vic_get_enabled_irq(int32_t IRQn)450 __STATIC_INLINE uint32_t csi_vic_get_enabled_irq(int32_t IRQn)
451 {
452     return (uint32_t)((PLIC->PLIC_H0_MIE[IRQn/32] >> IRQn%32) & 0x1);
453 }
454 
455 /**
456   \brief   Check Interrupt is Pending or not
457   \details Read the pending register in the VIC and returns the pending bit for the specified interrupt.
458   \param [in]      IRQn  Interrupt number.
459   \return             0  Interrupt status is not pending.
460   \return             1  Interrupt status is pending.
461  */
csi_vic_get_pending_irq(int32_t IRQn)462 __STATIC_INLINE uint32_t csi_vic_get_pending_irq(int32_t IRQn)
463 {
464     return (uint32_t)((PLIC->PLIC_IP[IRQn/32] >> IRQn%32) & 0x1);
465 }
466 
467 /**
468   \brief   Set Pending Interrupt
469   \details Set the pending bit of an external interrupt.
470   \param [in]      IRQn  Interrupt number. Value cannot be negative.
471  */
csi_vic_set_pending_irq(int32_t IRQn)472 __STATIC_INLINE void csi_vic_set_pending_irq(int32_t IRQn)
473 {
474     PLIC->PLIC_IP[IRQn/32] = PLIC->PLIC_IP[IRQn/32] | (0x1 << (IRQn%32));
475 }
476 
477 /**
478   \brief   Clear Pending Interrupt
479   \details Clear the pending bit of an external interrupt.
480   \param [in]      IRQn  External interrupt number. Value cannot be negative.
481  */
csi_vic_clear_pending_irq(int32_t IRQn)482 __STATIC_INLINE void csi_vic_clear_pending_irq(int32_t IRQn)
483 {
484     PLIC->PLIC_H0_SCLAIM = IRQn;
485 }
486 
487 /**
488   \brief   Set Interrupt Priority
489   \details Set the priority of an interrupt.
490   \note    The priority cannot be set for every core interrupt.
491   \param [in]      IRQn  Interrupt number.
492   \param [in]  priority  Priority to set.
493  */
csi_vic_set_prio(int32_t IRQn,uint32_t priority)494 __STATIC_INLINE void csi_vic_set_prio(int32_t IRQn, uint32_t priority)
495 {
496     PLIC->PLIC_PRIO[IRQn] = priority;
497 }
498 
499 /**
500   \brief   Get Interrupt Priority
501   \details Read the priority of an interrupt.
502            The interrupt number can be positive to specify an external (device specific) interrupt,
503            or negative to specify an internal (core) interrupt.
504   \param [in]   IRQn  Interrupt number.
505   \return             Interrupt Priority.
506                       Value is aligned automatically to the implemented priority bits of the microcontroller.
507  */
csi_vic_get_prio(int32_t IRQn)508 __STATIC_INLINE uint32_t csi_vic_get_prio(int32_t IRQn)
509 {
510     uint32_t prio = PLIC->PLIC_PRIO[IRQn];
511     return prio;
512 }
513 
514 /**
515   \brief   Set interrupt handler
516   \details Set the interrupt handler according to the interrupt num, the handler will be filled in irq vectors.
517   \param [in]      IRQn  Interrupt number.
518   \param [in]   handler  Interrupt handler.
519  */
csi_vic_set_vector(int32_t IRQn,uint64_t handler)520 __STATIC_INLINE void csi_vic_set_vector(int32_t IRQn, uint64_t handler)
521 {
522     if (IRQn >= 0 && IRQn < 1024) {
523         uint64_t *vectors = (uint64_t *)__get_MTVT();
524         vectors[IRQn] = handler;
525     }
526 }
527 
528 /**
529   \brief   Get interrupt handler
530   \details Get the address of interrupt handler function.
531   \param [in]      IRQn  Interrupt number.
532  */
csi_vic_get_vector(int32_t IRQn)533 __STATIC_INLINE uint32_t csi_vic_get_vector(int32_t IRQn)
534 {
535     if (IRQn >= 0 && IRQn < 1024) {
536         uint64_t *vectors = (uint64_t *)__get_MTVT();
537         return (uint32_t)vectors[IRQn];
538     }
539 
540     return 0;
541 }
542 
543 /*@} end of CSI_Core_VICFunctions */
544 
545 /* ##########################   PMP functions  #################################### */
546 /**
547   \ingroup  CSI_Core_FunctionInterface
548   \defgroup CSI_Core_PMPFunctions PMP Functions
549   \brief    Functions that manage interrupts and exceptions via the VIC.
550   @{
551  */
552 
553 /**
554   \brief  configure memory protected region.
555   \details
556   \param [in]  idx        memory protected region (0, 1, 2, ..., 15).
557   \param [in]  base_addr  base address must be aligned with page size.
558   \param [in]  size       \ref region_size_e. memory protected region size.
559   \param [in]  attr       \ref region_size_t. memory protected region attribute.
560   \param [in]  enable     enable or disable memory protected region.
561   */
csi_mpu_config_region(uint32_t idx,uint32_t base_addr,region_size_e size,mpu_region_attr_t attr,uint32_t enable)562 __STATIC_INLINE void csi_mpu_config_region(uint32_t idx, uint32_t base_addr, region_size_e size,
563                                            mpu_region_attr_t attr, uint32_t enable)
564 {
565     uint8_t  pmpxcfg = 0;
566     uint32_t addr = 0;
567 
568     if (idx > 15) {
569         return;
570     }
571 
572     if (!enable) {
573         attr.a = 0;
574     }
575 
576     if (attr.a == ADDRESS_MATCHING_TOR) {
577         addr = base_addr >> 2;
578     } else {
579         if (size == REGION_SIZE_4B) {
580             addr = base_addr >> 2;
581             attr.a = 2;
582         } else {
583             addr = ((base_addr >> 2) & (0xFFFFFFFFU - ((1 << (size + 1)) - 1))) | ((1 << size) - 1);
584         }
585     }
586 
587     __set_PMPADDRx(idx, addr);
588 
589     pmpxcfg |= (attr.r << PMP_PMPCFG_R_Pos) | (attr.w << PMP_PMPCFG_W_Pos) |
590                (attr.x << PMP_PMPCFG_X_Pos) | (attr.a << PMP_PMPCFG_A_Pos) |
591                (attr.l << PMP_PMPCFG_L_Pos);
592 
593     __set_PMPxCFG(idx, pmpxcfg);
594 }
595 
596 /**
597   \brief  disable mpu region by idx.
598   \details
599   \param [in]  idx        memory protected region (0, 1, 2, ..., 15).
600   */
csi_mpu_disable_region(uint32_t idx)601 __STATIC_INLINE void csi_mpu_disable_region(uint32_t idx)
602 {
603     __set_PMPxCFG(idx, __get_PMPxCFG(idx) & (~PMP_PMPCFG_A_Msk));
604 }
605 
606 /*@} end of CSI_Core_PMPFunctions */
607 
608 /* ##################################    SysTick function  ############################################ */
609 /**
610   \ingroup  CSI_Core_FunctionInterface
611   \defgroup CSI_Core_SysTickFunctions SysTick Functions
612   \brief    Functions that configure the System.
613   @{
614  */
615 
616 
617 /**
618   \brief   CORE timer Configuration
619   \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
620            Counter is in free running mode to generate periodic interrupts.
621   \param [in]  ticks  Number of ticks between two interrupts.
622   \param [in]  IRQn   core timer Interrupt number.
623   \return          0  Function succeeded.
624   \return          1  Function failed.
625   \note    When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
626            function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
627            must contain a vendor-specific implementation of this function.
628  */
csi_coret_config(uint32_t ticks,int32_t IRQn)629 __STATIC_INLINE uint32_t csi_coret_config(uint32_t ticks, int32_t IRQn)
630 {
631     uint64_t value = (((uint64_t)CORET->MTIMECMPH0) << 32) + (uint64_t)CORET->MTIMECMPL0;
632 
633     value = value + (uint64_t)ticks;
634     CORET->MTIMECMPH0 = (uint32_t)(value >> 32);
635     CORET->MTIMECMPL0 = (uint32_t)value;
636     return (0UL);
637 }
638 
639 /**
640   \brief   get CORE timer reload value
641   \return          CORE timer counter value.
642  */
csi_coret_get_load(void)643 __STATIC_INLINE uint64_t csi_coret_get_load(void)
644 {
645     uint64_t value = (((uint64_t)CORET->MTIMECMPH0) << 32) + (uint64_t)CORET->MTIMECMPL0;
646     return value;
647 }
648 
649 /**
650   \brief   get CORE timer reload high value
651   \return          CORE timer counter value.
652  */
csi_coret_get_loadh(void)653 __STATIC_INLINE uint32_t csi_coret_get_loadh(void)
654 {
655     uint64_t value = (((uint64_t)CORET->MTIMECMPH0) << 32) + (uint64_t)CORET->MTIMECMPL0;
656     return (value >> 32) & 0xFFFFFFFF;
657 }
658 
659 /**
660   \brief   get CORE timer counter value
661   \return          CORE timer counter value.
662  */
csi_coret_get_value(void)663 __STATIC_INLINE uint64_t csi_coret_get_value(void)
664 {
665     uint64_t result;
666     __ASM volatile("csrr %0, 0xc01" : "=r"(result));
667     return result;
668 }
669 
670 /**
671   \brief   get CORE timer counter high value
672   \return          CORE timer counter value.
673  */
csi_coret_get_valueh(void)674 __STATIC_INLINE uint32_t csi_coret_get_valueh(void)
675 {
676     uint64_t result;
677     __ASM volatile("csrr %0, time" : "=r"(result));
678     return (result >> 32) & 0xFFFFFFFF;
679 }
680 
681 /*@} end of CSI_core_DebugFunctions */
682 
683 /* ##########################  Cache functions  #################################### */
684 /**
685   \ingroup  CSI_Core_FunctionInterface
686   \defgroup CSI_Core_CacheFunctions Cache Functions
687   \brief    Functions that configure Instruction and Data cache.
688   @{
689  */
690 
691 /**
692   \brief   Enable I-Cache
693   \details Turns on I-Cache
694   */
csi_icache_enable(void)695 __STATIC_INLINE void csi_icache_enable (void)
696 {
697 #if (__ICACHE_PRESENT == 1U)
698     uint32_t cache;
699     __DSB();
700     __ISB();
701     __ICACHE_IALL();
702     cache = __get_MHCR();
703     cache |= CACHE_MHCR_IE_Msk;
704     __set_MHCR(cache);
705     __DSB();
706     __ISB();
707 #endif
708 }
709 
710 
711 /**
712   \brief   Disable I-Cache
713   \details Turns off I-Cache
714   */
csi_icache_disable(void)715 __STATIC_INLINE void csi_icache_disable (void)
716 {
717 #if (__ICACHE_PRESENT == 1U)
718     uint32_t cache;
719     __DSB();
720     __ISB();
721     cache = __get_MHCR();
722     cache &= ~CACHE_MHCR_IE_Msk;            /* disable icache */
723     __set_MHCR(cache);
724     __ICACHE_IALL();                        /* invalidate all icache */
725     __DSB();
726     __ISB();
727 #endif
728 }
729 
730 
731 /**
732   \brief   Invalidate I-Cache
733   \details Invalidates I-Cache
734   */
csi_icache_invalid(void)735 __STATIC_INLINE void csi_icache_invalid (void)
736 {
737 #if (__ICACHE_PRESENT == 1U)
738     __DSB();
739     __ISB();
740     __ICACHE_IALL();                        /* invalidate all icache */
741     __DSB();
742     __ISB();
743 #endif
744 }
745 
746 
747 /**
748   \brief   Enable D-Cache
749   \details Turns on D-Cache
750   \note    I-Cache also turns on.
751   */
csi_dcache_enable(void)752 __STATIC_INLINE void csi_dcache_enable (void)
753 {
754 #if (__DCACHE_PRESENT == 1U)
755     uint32_t cache;
756     __DSB();
757     __ISB();
758     __DCACHE_IALL();                        /* invalidate all dcache */
759     cache = __get_MHCR();
760     cache |= (CACHE_MHCR_DE_Msk | CACHE_MHCR_WB_Msk | CACHE_MHCR_WA_Msk | CACHE_MHCR_RS_Msk | CACHE_MHCR_BPE_Msk | CACHE_MHCR_L0BTB_Msk | CACHE_MHCR_IBPE_Msk | CACHE_MHCR_WBR_Msk);      /* enable all Cache */
761     __set_MHCR(cache);
762 
763     __DSB();
764     __ISB();
765 #endif
766 }
767 
768 
769 /**
770   \brief   Disable D-Cache
771   \details Turns off D-Cache
772   \note    I-Cache also turns off.
773   */
csi_dcache_disable(void)774 __STATIC_INLINE void csi_dcache_disable (void)
775 {
776 #if (__DCACHE_PRESENT == 1U)
777     uint32_t cache;
778     __DSB();
779     __ISB();
780     cache = __get_MHCR();
781     cache &= ~(uint32_t)CACHE_MHCR_DE_Msk; /* disable all Cache */
782     __set_MHCR(cache);
783     __DCACHE_IALL();                             /* invalidate all Cache */
784     __DSB();
785     __ISB();
786 #endif
787 }
788 
789 /**
790   \brief   Invalidate D-Cache
791   \details Invalidates D-Cache
792   \note    I-Cache also invalid
793   */
csi_dcache_invalid(void)794 __STATIC_INLINE void csi_dcache_invalid (void)
795 {
796 #if (__DCACHE_PRESENT == 1U)
797     __DSB();
798     __ISB();
799     __DCACHE_IALL();                            /* invalidate all Cache */
800     __DSB();
801     __ISB();
802 #endif
803 }
804 
805 
806 /**
807   \brief   Clean D-Cache
808   \details Cleans D-Cache
809   \note    I-Cache also cleans
810   */
csi_dcache_clean(void)811 __STATIC_INLINE void csi_dcache_clean (void)
812 {
813 #if (__DCACHE_PRESENT == 1U)
814     __DSB();
815     __ISB();
816     __DCACHE_CALL();                                     /* clean all Cache */
817     __DSB();
818     __ISB();
819 #endif
820 }
821 
822 
823 /**
824   \brief   Clean & Invalidate D-Cache
825   \details Cleans and Invalidates D-Cache
826   \note    I-Cache also flush.
827   */
csi_dcache_clean_invalid(void)828 __STATIC_INLINE void csi_dcache_clean_invalid (void)
829 {
830 #if (__DCACHE_PRESENT == 1U)
831     __DSB();
832     __ISB();
833     __DCACHE_CIALL();                                   /* clean and inv all Cache */
834     __DSB();
835     __ISB();
836 #endif
837 }
838 
839 
840 /**
841   \brief   Invalidate L2-Cache
842   \details Invalidates L2-Cache
843   \note
844   */
csi_l2cache_invalid(void)845 __STATIC_INLINE void csi_l2cache_invalid (void)
846 {
847 #if (__L2CACHE_PRESENT == 1U)
848     __DSB();
849     __ISB();
850     __L2CACHE_IALL();                            /* invalidate l2 Cache */
851     __DSB();
852     __ISB();
853 #endif
854 }
855 
856 
857 /**
858   \brief   Clean L2-Cache
859   \details Cleans L2-Cache
860   \note
861   */
csi_l2cache_clean(void)862 __STATIC_INLINE void csi_l2cache_clean (void)
863 {
864 #if (__L2CACHE_PRESENT == 1U)
865     __DSB();
866     __ISB();
867     __L2CACHE_CALL();                                     /* clean l2 Cache */
868     __DSB();
869     __ISB();
870 #endif
871 }
872 
873 
874 /**
875   \brief   Clean & Invalidate L2-Cache
876   \details Cleans and Invalidates L2-Cache
877   \note
878   */
csi_l2cache_clean_invalid(void)879 __STATIC_INLINE void csi_l2cache_clean_invalid (void)
880 {
881 #if (__L2CACHE_PRESENT == 1U)
882     __DSB();
883     __ISB();
884     __L2CACHE_CIALL();                                   /* clean and inv l2 Cache */
885     __DSB();
886     __ISB();
887 #endif
888 }
889 
890 /**
891   \brief   D-Cache Invalidate by address
892   \details Invalidates D-Cache for the given address
893   \param[in]   addr    address (aligned to 32-byte boundary)
894   \param[in]   dsize   size of memory block (in number of bytes)
895 */
csi_dcache_invalid_range(uint64_t * addr,int64_t dsize)896 __STATIC_INLINE void csi_dcache_invalid_range (uint64_t *addr, int64_t dsize)
897 {
898 #if (__DCACHE_PRESENT == 1U)
899     int64_t op_size = dsize + (uint64_t)addr % 64;
900     uint64_t op_addr = (uint64_t)addr;
901     int64_t linesize = 64;
902 
903     __DSB();
904 
905     while (op_size > 0) {
906         __DCACHE_IPA(op_addr);
907         op_addr += linesize;
908         op_size -= linesize;
909     }
910 
911     __DSB();
912     __ISB();
913 #endif
914 }
915 
916 
917 /**
918   \brief   D-Cache Clean by address
919   \details Cleans D-Cache for the given address
920   \param[in]   addr    address (aligned to 32-byte boundary)
921   \param[in]   dsize   size of memory block (in number of bytes)
922 */
csi_dcache_clean_range(uint64_t * addr,int64_t dsize)923 __STATIC_INLINE void csi_dcache_clean_range (uint64_t *addr, int64_t dsize)
924 {
925 
926 #if (__DCACHE_PRESENT == 1)
927     int64_t op_size = dsize + (uint64_t)addr % 64;
928     uint64_t op_addr = (uint64_t) addr & CACHE_INV_ADDR_Msk;
929     int64_t linesize = 64;
930 
931     __DSB();
932 
933     while (op_size > 0) {
934         __DCACHE_CPA(op_addr);
935         op_addr += linesize;
936         op_size -= linesize;
937     }
938 
939     __DSB();
940     __ISB();
941 #endif
942 
943 }
944 
945 
946 /**
947   \brief   D-Cache Clean and Invalidate by address
948   \details Cleans and invalidates D_Cache for the given address
949   \param[in]   addr    address (aligned to 16-byte boundary)
950   \param[in]   dsize   size of memory block (aligned to 16-byte boundary)
951 */
csi_dcache_clean_invalid_range(uint64_t * addr,int64_t dsize)952 __STATIC_INLINE void csi_dcache_clean_invalid_range (uint64_t *addr, int64_t dsize)
953 {
954 #if (__DCACHE_PRESENT == 1U)
955     int64_t op_size = dsize + (uint64_t)addr % 64;
956     uint64_t op_addr = (uint64_t) addr;
957     int64_t linesize = 64;
958 
959     __DSB();
960 
961     while (op_size > 0) {
962         __DCACHE_CIPA(op_addr);
963         op_addr += linesize;
964         op_size -= linesize;
965     }
966 
967     __DSB();
968     __ISB();
969 #endif
970 }
971 
972 /**
973   \brief   setup cacheable range Cache
974   \details setup Cache range
975   */
csi_cache_set_range(uint64_t index,uint64_t baseAddr,uint64_t size,uint64_t enable)976 __STATIC_INLINE void csi_cache_set_range (uint64_t index, uint64_t baseAddr, uint64_t size, uint64_t enable)
977 {
978     ;
979 }
980 
981 /**
982   \brief   Enable cache profile
983   \details Turns on Cache profile
984   */
csi_cache_enable_profile(void)985 __STATIC_INLINE void csi_cache_enable_profile (void)
986 {
987     ;
988 }
989 
990 /**
991   \brief   Disable cache profile
992   \details Turns off Cache profile
993   */
csi_cache_disable_profile(void)994 __STATIC_INLINE void csi_cache_disable_profile (void)
995 {
996     ;
997 }
998 
999 /**
1000   \brief   Reset cache profile
1001   \details Reset Cache profile
1002   */
csi_cache_reset_profile(void)1003 __STATIC_INLINE void csi_cache_reset_profile (void)
1004 {
1005     ;
1006 }
1007 
1008 /**
1009   \brief   cache access times
1010   \details Cache access times
1011   \note    every 256 access add 1.
1012   \return          cache access times, actual times should be multiplied by 256
1013   */
csi_cache_get_access_time(void)1014 __STATIC_INLINE uint64_t csi_cache_get_access_time (void)
1015 {
1016     return 0;
1017 }
1018 
1019 /**
1020   \brief   cache miss times
1021   \details Cache miss times
1022   \note    every 256 miss add 1.
1023   \return          cache miss times, actual times should be multiplied by 256
1024   */
csi_cache_get_miss_time(void)1025 __STATIC_INLINE uint64_t csi_cache_get_miss_time (void)
1026 {
1027     return 0;
1028 }
1029 
1030 /*@} end of CSI_Core_CacheFunctions */
1031 
1032 /*@} end of CSI_core_DebugFunctions */
1033 
1034 /* ##################################    IRQ Functions  ############################################ */
1035 
1036 /**
1037   \brief   Save the Irq context
1038   \details save the psr result before disable irq.
1039  */
csi_irq_save(void)1040 __STATIC_INLINE uint64_t csi_irq_save(void)
1041 {
1042     uint64_t result;
1043     result = __get_MSTATUS();
1044     __disable_irq();
1045     return(result);
1046 }
1047 
1048 /**
1049   \brief   Restore the Irq context
1050   \details restore saved primask state.
1051   \param [in]      irq_state  psr irq state.
1052  */
csi_irq_restore(uint64_t irq_state)1053 __STATIC_INLINE void csi_irq_restore(uint64_t irq_state)
1054 {
1055     __set_MSTATUS(irq_state);
1056 }
1057 
1058 /*@} end of IRQ Functions */
1059 
1060 
1061 #ifdef __cplusplus
1062 }
1063 #endif
1064 
1065 #endif /* __CORE_RV32_H_DEPENDANT */
1066 
1067 #endif /* __CSI_GENERIC */
1068