1 /**
2 *********************************************************************************
3 *
4 * @file ald_utils.c
5 * @brief This file contains the Utilities functions/types for the driver.
6 *
7 * @version V1.0
8 * @date 8 Feb. 2023
9 * @author AE Team
10 * @note
11 * Change Logs:
12 * Date Author Notes
13 * 8 Feb. 2023 Lisq The first version
14 *
15 * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 *
19 * Licensed under the Apache License, Version 2.0 (the License); you may
20 * not use this file except in compliance with the License.
21 * You may obtain a copy of the License at
22 *
23 * www.apache.org/licenses/LICENSE-2.0
24 *
25 * Unless required by applicable law or agreed to in writing, software
26 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
27 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28 * See the License for the specific language governing permissions and
29 * limitations under the License.
30 **********************************************************************************
31 */
32
33 #include <string.h>
34 #include "ald_conf.h"
35
36 /** @defgroup EASTSOFT ES32VF2264 ALD
37 * @brief Shanghai Eastsoft Microelectronics E902 Chip Abstraction Layer Driver(ALD)
38 * @{
39 */
40
41 /** @defgroup UTILS Utils
42 * @brief Utils module driver
43 * @{
44 */
45
46 /** @defgroup ALD_Private_Constants Private Constants
47 * @brief ALD Private Constants
48 * @{
49 */
50
51 /**
52 * @brief ALD version number
53 */
54 #define __ALD_VERSION_MAIN (0x01) /**< [31:24] main version */
55 #define __ALD_VERSION_SUB1 (0x00) /**< [23:16] sub1 version */
56 #define __ALD_VERSION_SUB2 (0x00) /**< [15:8] sub2 version */
57 #define __ALD_VERSION_RC (0x00) /**< [7:0] release candidate */
58 #define __ALD_VERSION ((__ALD_VERSION_MAIN << 24) | \
59 (__ALD_VERSION_SUB1 << 16) | \
60 (__ALD_VERSION_SUB2 << 8 ) | \
61 (__ALD_VERSION_RC))
62 /**
63 * @}
64 */
65
66 /** @defgroup ALD_Private_Variables Private Variables
67 * @{
68 */
69 /** @brief lib_tick: Increase by one millisecond
70 */
71 __IO uint32_t lib_tick;
72 uint32_t __systick_interval = ALD_SYSTICK_INTERVAL_1MS;
73 /**
74 * @}
75 */
76
77
78 /** @defgroup ALD_Public_Functions Public Functions
79 * @{
80 */
81
82 /** @defgroup ALD_Public_Functions_Group1 Initialization Function
83 * @brief Initialization functions
84 *
85 * @verbatim
86 ===============================================================================
87 ##### Initialization functions #####
88 ===============================================================================
89 [..] This section provides functions allowing to:
90 (+) Initializes interface, the NVIC allocation and initial clock
91 configuration. It initializes the source of time base also when timeout
92 is needed and the backup domain when enabled.
93 (+) Configure The time base source to have 1ms time base with a dedicated
94 Tick interrupt priority.
95 (++) Systick timer is used by default as source of time base, but user
96 can eventually implement his proper time base source (a general purpose
97 timer for example or other time source), keeping in mind that Time base
98 duration should be kept 1ms.
99 (++) Time base configuration function (ald_tick_init()) is called automatically
100 at the beginning of the program after reset by ald_cmu_init() or at
101 any time when clock is configured.
102 (++) Source of time base is configured to generate interrupts at regular
103 time intervals. Care must be taken if ald_delay_ms() is called from a
104 peripheral ISR process, the Tick interrupt line must have higher priority
105 (numerically lower) than the peripheral interrupt. Otherwise the caller
106 ISR process will be blocked.
107 (++) functions affecting time base configurations are declared as __weak
108 to make override possible in case of other implementations in user file.
109 (+) Configure the interval of Systick interrupt.
110
111 @endverbatim
112 * @{
113 */
114
115 /**
116 * @brief This function Configures time base source, CLINT and DMA.
117 * @note This function is called at the beginning of program after reset and before
118 * the clock configuration.
119 * @note The time base configuration is based on MSI clock when exiting from Reset.
120 * Once done, time base tick start incrementing.
121 * In the default implementation, Systick is used as source of time base.
122 * The tick variable is incremented each 1ms in its ISR.
123 * @retval None
124 */
ald_cmu_init(void)125 void ald_cmu_init(void)
126 {
127 ald_cmu_clock_config_default();
128 ald_tick_init(TICK_INT_PRIORITY);
129 #ifdef ALD_DMA
130 ald_cmu_perh_clock_config(ALD_CMU_PERH_DMA, ENABLE);
131 ald_dma_init();
132 #endif
133 return;
134 }
135
136 /**
137 * @brief This function configures the source of the time base.
138 * The time source is configured to have 1ms time base with a dedicated
139 * Tick interrupt priority.
140 * @note In the default implementation, SysTick timer is the source of time base.
141 * It is used to generate interrupts at regular time intervals.
142 * Care must be taken if ald_delay_ms() is called from a peripheral ISR process,
143 * The SysTick interrupt must have higher priority (numerically lower)
144 * than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
145 * The function is declared as __weak to be overwritten in case of other
146 * implementation in user file.
147 * @param prio: Tick interrupt priority.
148 * @retval None
149 */
ald_tick_init(uint32_t prio)150 __weak void ald_tick_init(uint32_t prio)
151 {
152 /* Configure the SysTick IRQ */
153 csi_coret_config(ald_cmu_get_sys_clock() / ALD_SYSTICK_INTERVAL_1MS, CLINT_IRQn);
154 csi_vic_set_prio(CLINT_IRQn, prio);
155 csi_vic_enable_sirq(CLINT_IRQn);
156
157 return;
158 }
159
160 /**
161 * @brief Selects the interval of systick interrupt.
162 * @param value: The value of interval:
163 * @arg @ref SYSTICK_INTERVAL_1MS 1 millisecond
164 * @arg @ref SYSTICK_INTERVAL_10MS 10 milliseconds
165 * @arg @ref SYSTICK_INTERVAL_100MS 100 milliseconds
166 * @arg @ref SYSTICK_INTERVAL_1000MS 1 second
167 * @retval None
168 */
ald_systick_interval_select(ald_systick_interval_t value)169 void ald_systick_interval_select(ald_systick_interval_t value)
170 {
171 assert_param(IS_SYSTICK_INTERVAL(value));
172
173 if (value == 0)
174 return;
175
176 csi_coret_config(ald_cmu_get_sys_clock() / value, CLINT_IRQn);
177 __systick_interval = value;
178
179 if (TICK_INT_PRIORITY != 15)
180 csi_vic_set_prio(CLINT_IRQn, TICK_INT_PRIORITY);
181
182 return;
183 }
184 /**
185 * @}
186 */
187
188 /** @defgroup ALD_Public_Functions_Group2 Control functions
189 * @brief Control functions
190 *
191 * @verbatim
192 ===============================================================================
193 ##### Control functions #####
194 ===============================================================================
195 [..] This section provides functions allowing to:
196 (+) Provide a tick value in millisecond
197 (+) Provide a blocking delay in millisecond
198 (+) Suspend the time base source interrupt
199 (+) Resume the time base source interrupt
200 (+) Get the ALD version
201 (+) Waiting for flag
202 (+) Configure the interrupt
203 (+) Provide system tick value
204 (+) Initialize core timestamp
205 (+) Get core timestamp
206 (+) Get CPU ID
207 (+) Get UID
208 (+) Get CHIPID
209
210 @endverbatim
211 * @{
212 */
213
214 /**
215 * @brief This function invoked by Systick ISR.
216 * @note This function is declared as __weak to be overwritten in case of
217 * other implementations in user file.
218 * @retval None
219 */
ald_systick_irq_cbk(void)220 __weak void ald_systick_irq_cbk(void)
221 {
222 /* do nothing */
223 return;
224 }
225
226 /**
227 * @brief This function is called to increment a global variable "lib_tick"
228 * used as application time base.
229 * @note In the default implementation, this variable is incremented each 1ms
230 * in Systick ISR.
231 * @note This function is declared as __weak to be overwritten in case of other
232 * implementations in user file.
233 * @retval None
234 */
ald_inc_tick(void)235 __weak void ald_inc_tick(void)
236 {
237 ++lib_tick;
238 ald_systick_irq_cbk();
239 }
240
241 /**
242 * @brief Provides a tick value in millisecond.
243 * @note This function is declared as __weak to be overwritten in case of other
244 * implementations in user file.
245 * @retval tick value
246 */
ald_get_tick(void)247 __weak uint32_t ald_get_tick(void)
248 {
249 return lib_tick;
250 }
251
252 /**
253 * @brief This function provides accurate delay (in milliseconds) based
254 * on variable incremented.
255 * @note In the default implementation, SysTick timer is the source of time base.
256 * It is used to generate interrupts at regular time intervals where lib_tick
257 * is incremented.
258 * @note This function is declared as __weak to be overwritten in case of other
259 * implementations in user file.
260 * @param delay: specifies the delay time length, in milliseconds.
261 * @retval None
262 */
ald_delay_1ms(__IO uint32_t delay)263 __weak void ald_delay_1ms(__IO uint32_t delay)
264 {
265 uint32_t tick, __delay;
266
267 switch (__systick_interval) {
268 case ALD_SYSTICK_INTERVAL_1MS:
269 __delay = delay;
270 break;
271
272 case ALD_SYSTICK_INTERVAL_10MS:
273 __delay = delay / 10;
274 break;
275
276 case ALD_SYSTICK_INTERVAL_100MS:
277 __delay = delay / 100;
278 break;
279
280 case ALD_SYSTICK_INTERVAL_1000MS:
281 __delay = delay / 1000;
282 break;
283
284 default:
285 __delay = delay;
286 break;
287 }
288
289 tick = ald_get_tick();
290 __delay = __delay == 0 ? 1 : __delay;
291
292 while ((ald_get_tick() - tick) < __delay)
293 ;
294 }
295
296 /**
297 * @brief This function provides accurate delay (in microseconds) based
298 * on variable incremented.
299 * @note In the default implementation, SysTick timer is the source of time base.
300 * It is used to generate interrupts at regular time intervals where lib_tick
301 * is incremented.
302 * @note This function is declared as __weak to be overwritten in case of other
303 * implementations in user file.
304 * @param delay: specifies the delay time length, in microseconds(us).
305 * @retval None
306 */
ald_delay_1us(__IO uint32_t delay)307 __weak void ald_delay_1us(__IO uint32_t delay)
308 {
309 uint32_t start, now, delta, us_tick;
310 start = CORET->MTIME;
311 us_tick = ald_cmu_get_sys_clock() / 1000000UL;
312 do
313 {
314 now = CORET->MTIME;
315 delta = now - start;
316 }
317 while (delta < (us_tick * delay));
318 }
319
320 /**
321 * @brief This method returns the ALD revision
322 * @retval version: 0xXYZR (8bits for each decimal, R for RC)
323 */
ald_get_ald_version(void)324 uint32_t ald_get_ald_version(void)
325 {
326 return __ALD_VERSION;
327 }
328
329 /**
330 * @brief Configure the flash wait period.
331 * @param cycle: The period.
332 * @retval None
333 */
ald_flash_wait_config(uint8_t cycle)334 void ald_flash_wait_config(uint8_t cycle)
335 {
336 uint32_t tmp;
337
338 tmp = MSC->MEMWAIT;
339 MODIFY_REG(tmp, MSC_MEMWAIT_FLASH_W_MSK, (0x30U | cycle) << MSC_MEMWAIT_FLASH_W_POSS);
340 MSC->MEMWAIT = tmp;
341
342 return;
343 }
344
345 /**
346 * @brief Waiting the specified bit in the register change to SET/RESET.
347 * @param reg: The register address.
348 * @param bit: The specified bit.
349 * @param status: The status for waiting.
350 * @param timeout: Timeout duration.
351 * @retval Status, see @ref ald_status_t.
352 */
ald_wait_flag(uint32_t * reg,uint32_t bit,flag_status_t status,uint32_t timeout)353 ald_status_t ald_wait_flag(uint32_t *reg, uint32_t bit, flag_status_t status, uint32_t timeout)
354 {
355 uint32_t tick = ald_get_tick();
356
357 assert_param(timeout > 0);
358
359 if (status == SET) {
360 while (!(IS_BIT_SET(*reg, bit))) {
361 if (((ald_get_tick()) - tick) > timeout)
362 return ALD_TIMEOUT;
363 }
364 }
365 else {
366 while ((IS_BIT_SET(*reg, bit))) {
367 if (((ald_get_tick()) - tick) > timeout)
368 return ALD_TIMEOUT;
369 }
370 }
371
372 return ALD_OK;
373 }
374
375 /**
376 * @brief Configure interrupt.
377 * @param irq: Interrunpt type.
378 * @param prio: preempt priority(0-7). The larger the prio value, the higher the priority.
379 * @param status: Status.
380 * @arg ENABLE
381 * @arg DISABLE
382 * @retval None
383 */
ald_mcu_irq_config(IRQn_Type irq,uint8_t prio,type_func_t status)384 void ald_mcu_irq_config(IRQn_Type irq, uint8_t prio, type_func_t status)
385 {
386 assert_param(IS_FUNC_STATE(status));
387
388 if (status == ENABLE)
389 {
390 csi_vic_set_prio(irq, prio);
391 csi_vic_enable_sirq(irq);
392 }
393 else
394 {
395 csi_vic_disable_sirq(irq);
396 }
397
398 return;
399 }
400 /**
401 * @}
402 */
403
404 /**
405 * @}
406 */
407
408 /**
409 * @}
410 */
411
412 /**
413 * @}
414 */
415