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