1 /**
2 * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 ******************************************************************************
6 * @file drv_cache.c
7 * @version V0.1
8 * @brief cpu cache interface
9 *
10 * Change Logs:
11 * Date Author Notes
12 * 2019-04-01 Cliff.Chen first implementation
13 *
14 ******************************************************************************
15 */
16
17 /** @addtogroup RKBSP_Driver_Reference
18 * @{
19 */
20
21 /** @addtogroup Cache
22 * @{
23 */
24
25 /** @defgroup Cache_How_To_Use How To Use
26 * @{
27
28 The Cache driver use to keeping data coherent between cpu and device, it can be used in the following three scenarios:
29
30 - **The cpu want to read the latest data that has been modified by device**:
31 - The device modify the data;
32 - The cpu invalidate the data by rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE,
33 addr, size);
34 - The cpu read the latest data;
35
36 - **The device want to read the latest data that was modified by cpu**:
37 - The cpu modify the data;
38 - The device flush the data by rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, addr, size);
39 - The device read the latest data;
40
41 - **The cpu want to execute two code section on the same memory**:
42 - Loading the code A in the memory from start address of ADDR;
43 - Executing the code A;
44 - Loading the code B in the memory from start address of ADDR;
45 - Invalidating by rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, ADDR, size);
46 - Executing the code B
47
48 @} */
49
50 #include <rthw.h>
51 #include "drv_cache.h"
52 #include "hal_base.h"
53
54 #if defined(ARCH_ARM_CORTEX_M)
55
56 #ifdef RT_USING_CMBACKTRACE
57 #include "cm_backtrace.h"
58 #endif
59
60 /********************* Private MACRO Definition ******************************/
61 /** @defgroup CACHE_Private_Macro Private Macro
62 * @{
63 */
64
65 /** @} */ // CACHE_Private_Macro
66
67 /********************* Private Structure Definition **************************/
68 /** @defgroup CACHE_Private_Structure Private Structure
69 * @{
70 */
71
72 /** @} */ // CACHE_Private_Structure
73
74 /********************* Private Variable Definition ***************************/
75 /** @defgroup CACHE_Private_Variable Private Variable
76 * @{
77 */
78
79 /** @} */ // CACHE_Private_Variable
80
81 /********************* Private Function Definition ***************************/
82 /** @defgroup CACHE_Private_Function Private Function
83 * @{
84 */
85
86 /** @} */ // CACHE_Private_Function
87
88 /********************* Public Function Definition ****************************/
89
90 /** @defgroup CACHE_Public_Functions Public Functions
91 * @{
92 */
93
94 /**
95 * @brief Enable the icache of cpu.
96 * @attention The cache will be enabled when board initialization, do not dynamically switch cache
97 * unless specifically required.
98 */
rt_hw_cpu_icache_enable(void)99 void rt_hw_cpu_icache_enable(void)
100 {
101 HAL_ICACHE_Enable();
102 }
103
104 /**
105 * @brief Disable the icache of cpu.
106 * @attention The cache will be enabled when board initialization, do not dynamically switch cache
107 * unless specifically required.
108 */
rt_hw_cpu_icache_disable(void)109 void rt_hw_cpu_icache_disable(void)
110 {
111 HAL_ICACHE_Disable();
112 }
113
114 /**
115 * @brief Get icache status.
116 * @return 0
117 * @attention Not yet implemnted.
118 */
rt_hw_cpu_icache_status(void)119 rt_base_t rt_hw_cpu_icache_status(void)
120 {
121 return 0;
122 }
123
124 /**
125 * @brief Icache maintain operation.
126 * @param ops: RT_HW_CACHE_INVALIDATE for cache invalidate.
127 * @param addr: The start address of memory you want maintain.
128 * @param size: The length of memory you want maintain.
129 */
rt_hw_cpu_icache_ops(int ops,void * addr,int size)130 void rt_hw_cpu_icache_ops(int ops, void *addr, int size)
131 {
132 if (ops & RT_HW_CACHE_INVALIDATE)
133 {
134 HAL_ICACHE_InvalidateByRange((uint32_t)addr, size);
135 }
136 }
137
138 /**
139 * @brief Enable the dcache of cpu.
140 * @attention The cache will be enabled when board initialization, do not dynamically switch cache
141 * unless specifically required.
142 */
rt_hw_cpu_dcache_enable(void)143 void rt_hw_cpu_dcache_enable(void)
144 {
145 HAL_DCACHE_Enable();
146 }
147
148 /**
149 * @brief Disable the dcache of cpu.
150 * @attention The cache will be enabled when board initialization, do not dynamically switch cache
151 * unless specifically required.
152 */
rt_hw_cpu_dcache_disable(void)153 void rt_hw_cpu_dcache_disable(void)
154 {
155 HAL_DCACHE_Disable();
156 }
157
158 /**
159 * @brief Get dcache status.
160 * @return 0
161 * @attention Not yet implemnted.
162 */
rt_hw_cpu_dcache_status(void)163 rt_base_t rt_hw_cpu_dcache_status(void)
164 {
165 return 0;
166 }
167
168 /**
169 * @brief Dcache maintain operation.
170 * @param ops: RT_HW_CACHE_INVALIDATE for cache invalidate,
171 * RT_HW_CACHE_FLUSH for cache clean.
172 * @param addr: The start address of memory you want maintain.
173 * @param size: The length of memory you want maintain.
174 */
rt_hw_cpu_dcache_ops(int ops,void * addr,int size)175 void rt_hw_cpu_dcache_ops(int ops, void *addr, int size)
176 {
177 if ((ops & RT_HW_CACHE_FLUSH) && (ops & RT_HW_CACHE_INVALIDATE))
178 {
179 HAL_DCACHE_CleanInvalidateByRange((uint32_t)addr, size);
180 }
181 else if (ops & RT_HW_CACHE_FLUSH)
182 {
183 HAL_DCACHE_CleanByRange((uint32_t)addr, size);
184 }
185 else if (ops & RT_HW_CACHE_INVALIDATE)
186 {
187 HAL_DCACHE_InvalidateByRange((uint32_t)addr, size);
188 }
189 else
190 {
191 RT_ASSERT(0);
192 }
193 }
194
195 /**
196 * @brief Dump ahb error occur in icache & dcache, it called by cache interrupt.
197 * @param fault_handler_lr: The value of LR register.
198 * @param fault_handler_sp: The value of SP register.
199 */
cache_dump_ahb_error(uint32_t fault_handler_lr,uint32_t fault_handler_sp)200 void cache_dump_ahb_error(uint32_t fault_handler_lr, uint32_t fault_handler_sp)
201 {
202 uint32_t addr;
203
204 if (HAL_ICACHE_GetInt())
205 {
206 addr = HAL_ICACHE_GetErrAddr();
207 rt_kprintf("a ahb bus error occur in icache, addr=%p\n", (void *)addr);
208 HAL_ICACHE_ClearInt();
209 }
210
211 if (HAL_DCACHE_GetInt())
212 {
213 addr = HAL_DCACHE_GetErrAddr();
214 rt_kprintf("a ahb bus error occur in dcache, addr=%p\n", (void *)addr);
215 HAL_DCACHE_ClearInt();
216 }
217
218 #ifdef RT_USING_CMBACKTRACE
219 cm_backtrace_fault(fault_handler_lr, fault_handler_sp);
220 #endif
221 }
222
223 extern void CACHE_IRQHandler(void);
224
225 /**
226 * @brief Enable cache interrupt and register the handler, it called by board initialization.
227 * @return RT_EOK
228 */
rt_hw_cpu_cache_init(void)229 int rt_hw_cpu_cache_init(void)
230 {
231 #if defined(ICACHE) || defined(DCACHE)
232 HAL_ICACHE_EnableInt();
233 HAL_DCACHE_EnableInt();
234 #if defined(RKMCU_PISCES) || defined(RKMCU_RK2108)
235 rt_hw_interrupt_install(CACHE_IRQn, (rt_isr_handler_t)CACHE_IRQHandler, RT_NULL, RT_NULL);
236 rt_hw_interrupt_umask(CACHE_IRQn);
237 #elif defined(RKMCU_RK2206)
238 rt_hw_interrupt_install(CACHE0_I_IRQn, (rt_isr_handler_t)CACHE_IRQHandler, RT_NULL, RT_NULL);
239 rt_hw_interrupt_install(CACHE0_D_IRQn, (rt_isr_handler_t)CACHE_IRQHandler, RT_NULL, RT_NULL);
240 rt_hw_interrupt_umask(CACHE0_I_IRQn);
241 rt_hw_interrupt_umask(CACHE0_D_IRQn);
242 #endif
243 #endif
244 return RT_EOK;
245 }
246
247 /** @} */ // CACHE_Public_Functions
248
249 #else
250
rt_hw_cpu_icache_enable(void)251 rt_weak void rt_hw_cpu_icache_enable(void)
252 {
253 }
254
rt_hw_cpu_icache_disable(void)255 rt_weak void rt_hw_cpu_icache_disable(void)
256 {
257 }
258
rt_hw_cpu_icache_status(void)259 rt_weak rt_base_t rt_hw_cpu_icache_status(void)
260 {
261 return 0;
262 }
263
rt_hw_cpu_icache_ops(int ops,void * addr,int size)264 rt_weak void rt_hw_cpu_icache_ops(int ops, void *addr, int size)
265 {
266 }
267
rt_hw_cpu_dcache_enable(void)268 rt_weak void rt_hw_cpu_dcache_enable(void)
269 {
270 }
271
rt_hw_cpu_dcache_disable(void)272 rt_weak void rt_hw_cpu_dcache_disable(void)
273 {
274 }
275
rt_hw_cpu_dcache_status(void)276 rt_weak rt_base_t rt_hw_cpu_dcache_status(void)
277 {
278 return 0;
279 }
280
rt_hw_cpu_dcache_ops(int ops,void * addr,int size)281 rt_weak void rt_hw_cpu_dcache_ops(int ops, void *addr, int size)
282 {
283 }
284
285 #endif
286
287 /** @} */ // Cache
288
289 /** @} */ // RKBSP_Driver_Reference
290