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