1 /*
2 // Copyright (C) 2022 Beken Corporation
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef __PORTMACRO_H__
17 #define __PORTMACRO_H__
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22
23
24 #include <stdint.h>
25 #include <os/os.h>
26
27 /* Type definitions. */
28 #if __riscv_xlen == 64
29 #define portSTACK_TYPE uint64_t
30 #define portBASE_TYPE int64_t
31 #define portUBASE_TYPE uint64_t
32 #define portMAX_DELAY ( TickType_t ) 0xffffffffffffffffUL
33 #define portPOINTER_SIZE_TYPE uint64_t
34 #elif __riscv_xlen == 32
35 #define portSTACK_TYPE uint32_t
36 #define portBASE_TYPE int32_t
37 #define portUBASE_TYPE uint32_t
38 #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
39 #else
40 #error Assembler did not define __riscv_xlen
41 #endif
42
43 typedef portSTACK_TYPE StackType_t;
44 typedef portBASE_TYPE BaseType_t;
45 typedef portUBASE_TYPE UBaseType_t;
46 typedef portUBASE_TYPE TickType_t;
47
48
49 /* Macros to access high and low part of 64-bit mtime registers in RV32 */
50 #if __riscv_xlen == 32
51 #define portREG64_HI(reg_addr) ( ( (volatile uint32_t *)reg_addr )[1] )
52 #define portREG64_LO(reg_addr) ( ( (volatile uint32_t *)reg_addr )[0] )
53 #endif
54
55 extern volatile uint64_t *mtime;
56 extern volatile uint64_t *mtimecmp;
57
58 extern unsigned int port_disable_mie_flag(void);
59 extern void port_enable_mie_flag(uint32_t val);
60
61 __attribute__((always_inline))
prvMieSave()62 static inline UBaseType_t prvMieSave()
63 {
64 UBaseType_t uxSavedStatusValue;
65
66 __asm volatile( "csrrc %0, mstatus, 0x8":"=r"( uxSavedStatusValue ) );
67 return uxSavedStatusValue;
68 }
69 /*-----------------------------------------------------------*/
70
71 __attribute__((always_inline))
prvMieRestore(UBaseType_t uxSavedStatusValue)72 static inline void prvMieRestore( UBaseType_t uxSavedStatusValue )
73 {
74 __asm volatile( "csrw mstatus, %0"::"r"( uxSavedStatusValue ) );
75 }
76 /*-----------------------------------------------------------*/
77
78 /* prvReadMtime(): Read machine timer register.
79 Note: Always use this API to access mtime */
80 __attribute__((always_inline))
prvReadMtime(void)81 inline uint64_t prvReadMtime( void )
82 {
83 uint32_t ulTimeHigh, ulTimeLow;
84
85 #if __riscv_xlen == 32
86 do
87 {
88 ulTimeHigh = portREG64_HI( mtime );
89 ulTimeLow = portREG64_LO( mtime );
90
91 if( ulTimeHigh == portREG64_HI( mtime ) )
92 return ( ((uint64_t)ulTimeHigh) << 32 ) | ulTimeLow;
93 } while( 1 );
94 #else
95 return *mtime;
96 #endif
97 }
98 /*-----------------------------------------------------------*/
99
100 /* prvWriteMtimeCmp(ullNewMtimeCmp): Write machine timer compare register.
101 Note: Use this API to access register if timer interrupt is enabled. */
102 __attribute__((always_inline))
prvWriteMtimeCmp(uint64_t ullNewMtimeCmp)103 static inline void prvWriteMtimeCmp( uint64_t ullNewMtimeCmp )
104 {
105 #if __riscv_xlen == 32
106 /* To avoid triggering spurious interrupts when writting to mtimecmp,
107 keeping the high part to the maximum value in the writing progress.
108
109 We assume mtime overflow doesn't occur, because 64-bit mtime overflow
110 period is longer than 500 years for the CPUs whose clock rate is lower
111 than 1GHz. */
112
113 portREG64_HI( mtimecmp ) = UINT32_MAX;
114 portREG64_LO( mtimecmp ) = ullNewMtimeCmp & 0xFFFFFFFF;
115 portREG64_HI( mtimecmp ) = ( ullNewMtimeCmp >> 32 ) & 0xFFFFFFFF;
116 #else
117 *mtimecmp = ullNewMtimeCmp;
118 #endif
119 }
120
121
122 void vPortSetupTimerInterrupt(void);
123 void vPortSetupMEXTInterrupt(void);
124
port_disable_interrupts_flag(void)125 __inline static int port_disable_interrupts_flag(void)
126 {
127 uint32_t uxSavedStatusValue;
128
129 __asm volatile( "csrrc %0, mstatus, 0x8":"=r"( uxSavedStatusValue ) );
130 return uxSavedStatusValue;
131 }
132
133 /*
134 * Enable Interrupts
135 */
port_enable_interrupts_flag(int val)136 __inline static void port_enable_interrupts_flag(int val)
137 {
138 __asm volatile( "csrw mstatus, %0"::"r"( val ) );
139 }
140
port_set_interrupt_mask_from_isr(void)141 __inline static unsigned int port_set_interrupt_mask_from_isr(void)
142 {
143 unsigned int val;
144
145 __asm volatile( "csrrc %0, mstatus, 0x8":"=r"( val ) );
146
147 return val;
148 }
149
port_clear_interrupt_mask_from_isr(int val)150 __inline static void port_clear_interrupt_mask_from_isr(int val)
151 {
152 __asm volatile( "csrw mstatus, %0"::"r"( val ) );
153 }
154
155
156 #define portDISABLE_INTERRUPTS() __asm volatile( "csrc mstatus, 8" )
157 #define portENABLE_INTERRUPTS() __asm volatile( "csrs mstatus, 8" )
158 #define portENTER_CRITICAL()
159 #define portEXIT_CRITICAL()
160
161
162 #define portNOP() __asm volatile ( " nop " )
163
164
165 extern uint32_t platform_is_in_interrupt_context( void );
166
167
168
169 #ifdef __cplusplus
170 }
171 #endif
172
173 #endif /* _PORTMACRO_H_ */
174