NMSIS-Core  Version 1.2.0
NMSIS-Core support for Nuclei processor-based devices
core_feature_timer.h
1 /*
2  * Copyright (c) 2019 Nuclei Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the License); you may
7  * not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 #ifndef __CORE_FEATURE_TIMER_H__
19 #define __CORE_FEATURE_TIMER_H__
20 
24 /*
25  * System Timer Feature Configuration Macro:
26  * 1. __SYSTIMER_PRESENT: Must, Define whether Private System Timer is present or not.
27  * * 0: Not present
28  * * 1: Present
29  * 2. __SYSTIMER_BASEADDR: Must, Define the base address of the System Timer.
30  * 3. __SYSTIMER_HARTID: Optional, Define the system timer hart index of the cpu, important for case when cpu hartid and cpu hart index are different, only set it if your cpu is single core.
31  */
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 #include "core_feature_base.h"
37 
38 #if defined(__SYSTIMER_PRESENT) && (__SYSTIMER_PRESENT == 1)
39 
55 typedef struct {
56  __IOM uint64_t MTIMER;
57  __IOM uint64_t MTIMERCMP;
58  __IOM uint32_t RESERVED0[0x3F8];
59  __IOM uint32_t MSFTRST;
60  __IOM uint32_t RESERVED1;
61  __IOM uint32_t MTIMECTL;
62  __IOM uint32_t MSIP;
64 
65 /* Timer Control / Status Register Definitions */
66 #define SysTimer_MTIMECTL_TIMESTOP_Pos 0U
67 #define SysTimer_MTIMECTL_TIMESTOP_Msk (1UL << SysTimer_MTIMECTL_TIMESTOP_Pos)
68 #define SysTimer_MTIMECTL_CMPCLREN_Pos 1U
69 #define SysTimer_MTIMECTL_CMPCLREN_Msk (1UL << SysTimer_MTIMECTL_CMPCLREN_Pos)
70 #define SysTimer_MTIMECTL_CLKSRC_Pos 2U
71 #define SysTimer_MTIMECTL_CLKSRC_Msk (1UL << SysTimer_MTIMECTL_CLKSRC_Pos)
73 #define SysTimer_MSIP_MSIP_Pos 0U
74 #define SysTimer_MSIP_MSIP_Msk (1UL << SysTimer_MSIP_MSIP_Pos)
76 #define SysTimer_MTIMER_Msk (0xFFFFFFFFFFFFFFFFULL)
77 #define SysTimer_MTIMERCMP_Msk (0xFFFFFFFFFFFFFFFFULL)
78 #define SysTimer_MTIMECTL_Msk (0xFFFFFFFFUL)
79 #define SysTimer_MSIP_Msk (0xFFFFFFFFUL)
80 #define SysTimer_MSFTRST_Msk (0xFFFFFFFFUL)
82 #define SysTimer_MSFRST_KEY (0x80000A5FUL)
84 #define SysTimer_CLINT_MSIP_OFS (0x1000UL)
85 #define SysTimer_CLINT_MTIMECMP_OFS (0x5000UL)
86 #define SysTimer_CLINT_MTIME_OFS (0xCFF8UL)
88 #ifndef __SYSTIMER_BASEADDR
89 /* Base address of SYSTIMER(__SYSTIMER_BASEADDR) should be defined in <Device.h> */
90 #error "__SYSTIMER_BASEADDR is not defined, please check!"
91 #endif
92 /* System Timer Memory mapping of Device */
93 #define SysTimer_BASE __SYSTIMER_BASEADDR
94 #define SysTimer ((SysTimer_Type *) SysTimer_BASE)
96 /* System Timer Clint register base */
97 #define SysTimer_CLINT_MSIP_BASE(hartid) (unsigned long)((SysTimer_BASE) + (SysTimer_CLINT_MSIP_OFS) + ((hartid) << 2))
98 #define SysTimer_CLINT_MTIMECMP_BASE(hartid) (unsigned long)((SysTimer_BASE) + (SysTimer_CLINT_MTIMECMP_OFS) + ((hartid) << 3))
99 #define SysTimer_CLINT_MTIME_BASE (unsigned long)((SysTimer_BASE) + (SysTimer_CLINT_MTIME_OFS))
100  /* end of group NMSIS_Core_SysTimer_Registers */
102 
103 /* ################################## SysTimer function ############################################ */
117 #ifndef __SYSTIMER_HARTID
118 #define SysTimer_GetHartID() (__get_hart_index())
119 #else
120 #define SysTimer_GetHartID() (__SYSTIMER_HARTID)
121 #endif
122 
133 {
134 #if __RISCV_XLEN == 32
135  uint8_t *addr;
136  addr = (uint8_t *)(&(SysTimer->MTIMER));
137  __SW(addr, 0); // prevent carry
138  __SW(addr + 4, (uint32_t)(value >> 32));
139  __SW(addr, (uint32_t)(value));
140 #else
141  SysTimer->MTIMER = value;
142 #endif
143 }
144 
155 {
156 #if __RISCV_XLEN == 32
157  volatile uint32_t high0, low, high;
158  uint64_t full;
159  uint8_t *addr;
160 
161  addr = (uint8_t *)(&(SysTimer->MTIMER));
162 
163  high0 = __LW(addr + 4);
164  low = __LW(addr);
165  high = __LW(addr + 4);
166  if (high0 != high) {
167  low = __LW(addr);
168  }
169  full = (((uint64_t)high) << 32) | low;
170  return full;
171 #else
172  return SysTimer->MTIMER;
173 #endif
174 }
175 
189 __STATIC_FORCEINLINE void SysTimer_SetHartCompareValue(uint64_t value, unsigned long hartid)
190 {
191  if (hartid == 0) {
192 #if __RISCV_XLEN == 32
193  uint8_t *addr;
194  addr = (uint8_t *)(&(SysTimer->MTIMERCMP));
195  __SW(addr, -1U); // prevent load > timecmp
196  __SW(addr + 4, (uint32_t)(value >> 32));
197  __SW(addr, (uint32_t)(value));
198 #else
199  SysTimer->MTIMERCMP = value;
200 #endif
201  } else {
202  uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MTIMECMP_BASE(hartid));
203 #if __RISCV_XLEN == 32
204  __SW(addr, -1U); // prevent load > timecmp
205  __SW(addr + 4, (uint32_t)(value >> 32));
206  __SW(addr, (uint32_t)value);
207 #else
208  __SD(addr, value);
209 #endif
210  }
211 }
212 
226 {
227  unsigned long hartid = SysTimer_GetHartID();
228  SysTimer_SetHartCompareValue(value, hartid);
229 }
230 
243 {
244  if (hartid == 0) {
245  return SysTimer->MTIMERCMP;
246  } else {
247  uint64_t full;
248  uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MTIMECMP_BASE(hartid));
249 #if __RISCV_XLEN == 32
250  // MTIMECMP didn't increase
251  uint32_t high, low;
252 
253  high = __LW(addr + 4);
254  low = __LW(addr);
255  full = (((uint64_t)high) << 32) | low;
256 #else
257  full = __LD(addr);
258 #endif
259  return full;
260  }
261 }
262 
273 {
274  unsigned long hartid = SysTimer_GetHartID();
275  return SysTimer_GetHartCompareValue(hartid);
276 }
277 
285 {
287 }
288 
296 {
298 }
299 
315 {
316  SysTimer->MTIMECTL = (mctl & SysTimer_MTIMECTL_Msk);
317 }
318 
328 {
329  return (SysTimer->MTIMECTL & SysTimer_MTIMECTL_Msk);
330 }
331 
343 __STATIC_FORCEINLINE void SysTimer_SetHartSWIRQ(unsigned long hartid)
344 {
345  if (hartid == 0) {
347  } else {
348  uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
350  }
351 }
352 
363 {
364  unsigned long hartid = SysTimer_GetHartID();
365  SysTimer_SetHartSWIRQ(hartid);
366 }
367 
380 {
381  if (hartid == 0) {
383  } else {
384  uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
385  __SW(addr, 0);
386  }
387 }
388 
399 {
400  unsigned long hartid = SysTimer_GetHartID();
401  SysTimer_ClearHartSWIRQ(hartid);
402 }
403 
418 __STATIC_FORCEINLINE uint32_t SysTimer_GetHartMsipValue(unsigned long hartid)
419 {
420  if (hartid == 0) {
421  return (uint32_t)(SysTimer->MSIP & SysTimer_MSIP_Msk);
422  } else {
423  uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
424  return __LW(addr);
425  }
426 }
427 
441 {
442  unsigned long hartid = SysTimer_GetHartID();
443  return SysTimer_GetHartMsipValue(hartid);
444 }
445 
456 __STATIC_FORCEINLINE void SysTimer_SetHartMsipValue(uint32_t msip, unsigned long hartid)
457 {
458  if (hartid == 0) {
459  SysTimer->MSIP = (msip & SysTimer_MSIP_Msk);
460  } else {
461  uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
462  __SW(addr, msip);
463  }
464 }
465 
474 {
475  unsigned long hartid = SysTimer_GetHartID();
476  SysTimer_SetHartMsipValue(msip, hartid);
477 }
478 
490 {
491  SysTimer->MSFTRST = SysTimer_MSFRST_KEY;
492  // will reset cpu, never return
493  while (1);
494 }
495 
502 __STATIC_FORCEINLINE void SysTimer_SendIPI(unsigned long hartid)
503 {
504  uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
505  __SW(addr, 1);
506 }
507 
514 __STATIC_FORCEINLINE void SysTimer_ClearIPI(unsigned long hartid)
515 {
516  uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
517  __SW(addr, 0);
518 }
519 
520 #if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) && defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
521 
545 __STATIC_INLINE uint32_t SysTick_Config(uint64_t ticks)
546 {
547  uint64_t loadticks = SysTimer_GetLoadValue();
548  SysTimer_SetCompareValue(ticks + loadticks);
552  return (0UL);
553 }
554 
581 __STATIC_INLINE uint32_t SysTick_HartConfig(uint64_t ticks, unsigned long hartid)
582 {
583  uint64_t loadticks = SysTimer_GetLoadValue();
584  SysTimer_SetHartCompareValue(ticks + loadticks, hartid);
588  return (0UL);
589 }
590 
614 __STATIC_FORCEINLINE uint32_t SysTick_Reload(uint64_t ticks)
615 {
616  uint64_t cur_ticks = SysTimer_GetLoadValue();
617  uint64_t reload_ticks = ticks + cur_ticks;
618 
619  if (__USUALLY(reload_ticks > cur_ticks)) {
620  SysTimer_SetCompareValue(reload_ticks);
621  } else {
622  /* When added the ticks value, then the MTIMERCMP < TIMER,
623  * which means the MTIMERCMP is overflowed,
624  * so we need to reset the counter to zero */
627  }
628 
629  return (0UL);
630 }
631 
657 __STATIC_FORCEINLINE uint32_t SysTick_HartReload(uint64_t ticks, unsigned long hartid)
658 {
659  uint64_t cur_ticks = SysTimer_GetLoadValue();
660  uint64_t reload_ticks = ticks + cur_ticks;
661 
662  if (__USUALLY(reload_ticks > cur_ticks)) {
663  SysTimer_SetHartCompareValue(reload_ticks, hartid);
664  } else {
665  /* When added the ticks value, then the MTIMERCMP < TIMER,
666  * which means the MTIMERCMP is overflowed,
667  * so we need to reset the counter to zero */
669  SysTimer_SetHartCompareValue(ticks, hartid);
670  }
671 
672  return (0UL);
673 }
674 
675 #endif /* defined(__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) */
676  /* End of Doxygen Group NMSIS_Core_SysTimer */
677 
678 #endif /* defined(__SYSTIMER_PRESENT) && (__SYSTIMER_PRESENT == 1) */
679 
680 #ifdef __cplusplus
681 }
682 #endif
683 #endif /* __CORE_FEATURE_TIMER_H__ */
SysTimer_IRQn
@ SysTimer_IRQn
System Timer Interrupt.
Definition: core_feature_eclic.h:212
SysTimer_CLINT_MSIP_BASE
#define SysTimer_CLINT_MSIP_BASE(hartid)
Definition: core_feature_timer.h:97
SysTimer_GetHartID
#define SysTimer_GetHartID()
SysTimer_GetHartID() is used to get timer hartid which might not be the same as cpu hart id,...
Definition: core_feature_timer.h:118
SysTimer_SetMsipValue
__STATIC_FORCEINLINE void SysTimer_SetMsipValue(uint32_t msip)
Set system timer MSIP register value in machine mode.
Definition: core_feature_timer.h:473
SysTimer_GetLoadValue
__STATIC_FORCEINLINE uint64_t SysTimer_GetLoadValue(void)
Get system timer load value.
Definition: core_feature_timer.h:154
SysTimer_MSIP_MSIP_Msk
#define SysTimer_MSIP_MSIP_Msk
SysTick Timer MSIP: MSIP Mask.
Definition: core_feature_timer.h:74
SysTimer_Type::MSFTRST
__IOM uint32_t MSFTRST
Offset: 0xFF0 (R/W) System Timer Software Core Reset Register.
Definition: core_feature_timer.h:59
ECLIC_EnableIRQ
#define ECLIC_EnableIRQ
Definition: core_feature_eclic.h:249
SysTimer_MSIP_Msk
#define SysTimer_MSIP_Msk
SysTick Timer MSIP value Mask.
Definition: core_feature_timer.h:79
ECLIC_SetLevelIRQ
#define ECLIC_SetLevelIRQ
Definition: core_feature_eclic.h:261
SysTimer_Type::MTIMER
__IOM uint64_t MTIMER
Offset: 0x000 (R/W) System Timer current value 64bits Register.
Definition: core_feature_timer.h:56
SysTimer_SetHartCompareValue
__STATIC_FORCEINLINE void SysTimer_SetHartCompareValue(uint64_t value, unsigned long hartid)
Set system timer compare value by hartid.
Definition: core_feature_timer.h:189
SysTimer_GetHartCompareValue
__STATIC_FORCEINLINE uint64_t SysTimer_GetHartCompareValue(unsigned long hartid)
Get system timer compare value by hartid.
Definition: core_feature_timer.h:242
SysTimer_ClearSWIRQ
__STATIC_FORCEINLINE void SysTimer_ClearSWIRQ(void)
Clear system timer software interrupt pending request in machine mode.
Definition: core_feature_timer.h:398
SysTimer_Start
__STATIC_FORCEINLINE void SysTimer_Start(void)
Enable system timer counter running.
Definition: core_feature_timer.h:284
SysTimer_SetLoadValue
__STATIC_FORCEINLINE void SysTimer_SetLoadValue(uint64_t value)
Set system timer load value.
Definition: core_feature_timer.h:132
ECLIC_NON_VECTOR_INTERRUPT
#define ECLIC_NON_VECTOR_INTERRUPT
Non-Vector Interrupt Mode of ECLIC.
Definition: core_feature_eclic.h:152
__IOM
#define __IOM
Defines 'read/write' structure member permissions.
Definition: nmsis_compiler.h:69
SysTick_Reload
__STATIC_FORCEINLINE uint32_t SysTick_Reload(uint64_t ticks)
System Tick Reload.
Definition: core_feature_timer.h:614
__LW
__STATIC_FORCEINLINE uint32_t __LW(volatile void *addr)
Load 32bit value from address (32 bit)
Definition: core_feature_base.h:1537
SysTimer_ClearIPI
__STATIC_FORCEINLINE void SysTimer_ClearIPI(unsigned long hartid)
clear ipi to target hart using Systimer Clint
Definition: core_feature_timer.h:514
SysTimer_GetHartMsipValue
__STATIC_FORCEINLINE uint32_t SysTimer_GetHartMsipValue(unsigned long hartid)
Get system timer MSIP register value by hartid.
Definition: core_feature_timer.h:418
SysTimer_SetHartMsipValue
__STATIC_FORCEINLINE void SysTimer_SetHartMsipValue(uint32_t msip, unsigned long hartid)
Set system timer MSIP register value by hartid.
Definition: core_feature_timer.h:456
SysTimer_SendIPI
__STATIC_FORCEINLINE void SysTimer_SendIPI(unsigned long hartid)
send ipi to target hart using Systimer Clint
Definition: core_feature_timer.h:502
__STATIC_INLINE
#define __STATIC_INLINE
Define a static function that may be inlined by the compiler.
Definition: nmsis_gcc.h:65
SysTimer_CLINT_MTIMECMP_BASE
#define SysTimer_CLINT_MTIMECMP_BASE(hartid)
Definition: core_feature_timer.h:98
SysTimer_ClearHartSWIRQ
__STATIC_FORCEINLINE void SysTimer_ClearHartSWIRQ(unsigned long hartid)
Clear system timer software interrupt pending request by hartid.
Definition: core_feature_timer.h:379
SysTimer_MSFRST_KEY
#define SysTimer_MSFRST_KEY
SysTick Timer Software Reset Request Key.
Definition: core_feature_timer.h:82
SysTimer_SetSWIRQ
__STATIC_FORCEINLINE void SysTimer_SetSWIRQ(void)
Trigger or set software interrupt via system timer in machine mode.
Definition: core_feature_timer.h:362
SysTimer_Type::RESERVED1
__IOM uint32_t RESERVED1
Offset: 0xFF4 Reserved.
Definition: core_feature_timer.h:60
SysTimer_SetHartSWIRQ
__STATIC_FORCEINLINE void SysTimer_SetHartSWIRQ(unsigned long hartid)
Trigger or set software interrupt via system timer by hartid.
Definition: core_feature_timer.h:343
SysTimer_Type::MTIMECTL
__IOM uint32_t MTIMECTL
Offset: 0xFF8 (R/W) System Timer Control Register, previously MSTOP register.
Definition: core_feature_timer.h:61
SysTimer_GetMsipValue
__STATIC_FORCEINLINE uint32_t SysTimer_GetMsipValue(void)
Get system timer MSIP register value in machine mode.
Definition: core_feature_timer.h:440
SysTimer_GetControlValue
__STATIC_FORCEINLINE uint32_t SysTimer_GetControlValue(void)
Get system timer control value.
Definition: core_feature_timer.h:327
__STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE
Define a static function that should be always inlined by the compiler.
Definition: nmsis_gcc.h:70
SysTimer_SetCompareValue
__STATIC_FORCEINLINE void SysTimer_SetCompareValue(uint64_t value)
Set system timer compare value in machine mode.
Definition: core_feature_timer.h:225
SysTimer_SetControlValue
__STATIC_FORCEINLINE void SysTimer_SetControlValue(uint32_t mctl)
Set system timer control value.
Definition: core_feature_timer.h:314
SysTick_HartReload
__STATIC_FORCEINLINE uint32_t SysTick_HartReload(uint64_t ticks, unsigned long hartid)
System Tick Reload.
Definition: core_feature_timer.h:657
__USUALLY
#define __USUALLY(exp)
provide the compiler with branch prediction information, the branch is usually true
Definition: nmsis_gcc.h:177
SysTimer_MTIMECTL_TIMESTOP_Msk
#define SysTimer_MTIMECTL_TIMESTOP_Msk
SysTick Timer MTIMECTL: TIMESTOP Mask.
Definition: core_feature_timer.h:67
SysTimer_GetCompareValue
__STATIC_FORCEINLINE uint64_t SysTimer_GetCompareValue(void)
Get system timer compare value in machine mode.
Definition: core_feature_timer.h:272
SysTimer_Type::MSIP
__IOM uint32_t MSIP
Offset: 0xFFC (R/W) System Timer SW interrupt Register.
Definition: core_feature_timer.h:62
SysTimer_SoftwareReset
__STATIC_FORCEINLINE void SysTimer_SoftwareReset(void)
Do software reset request.
Definition: core_feature_timer.h:489
SysTimer_Stop
__STATIC_FORCEINLINE void SysTimer_Stop(void)
Stop system timer counter running.
Definition: core_feature_timer.h:295
__SW
__STATIC_FORCEINLINE void __SW(volatile void *addr, uint32_t val)
Write 32bit value to address (32 bit)
Definition: core_feature_base.h:1589
SysTimer_Type::MTIMERCMP
__IOM uint64_t MTIMERCMP
Offset: 0x008 (R/W) System Timer compare Value 64bits Register.
Definition: core_feature_timer.h:57
SysTimer_Type
Structure type to access the System Timer (SysTimer).
Definition: core_feature_timer.h:55
SysTick_HartConfig
__STATIC_INLINE uint32_t SysTick_HartConfig(uint64_t ticks, unsigned long hartid)
System Tick Configuration By hartid.
Definition: core_feature_timer.h:581
SysTimer
#define SysTimer
SysTick configuration struct.
Definition: core_feature_timer.h:94
SysTick_Config
__STATIC_INLINE uint32_t SysTick_Config(uint64_t ticks)
System Tick Configuration.
Definition: core_feature_timer.h:545
SysTimer_MTIMECTL_Msk
#define SysTimer_MTIMECTL_Msk
SysTick Timer MTIMECTL/MSTOP value Mask.
Definition: core_feature_timer.h:78
ECLIC_SetShvIRQ
#define ECLIC_SetShvIRQ
Definition: core_feature_eclic.h:257