1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/portability/cmsis_os2.h>
9 #include <zephyr/portability/cmsis_types.h>
10 
11 #define ONESHOT_TIME_TICKS 100
12 #define PERIOD_TICKS       MAX(50, k_ms_to_ticks_ceil32(10))
13 #define NUM_PERIODS        5
14 
15 uint32_t num_oneshots_executed;
16 uint32_t num_periods_executed;
17 
18 const osTimerAttr_t timer_attr = {"myTimer", 0, NULL, 0U};
19 
Timer1_Callback(void * arg)20 static void Timer1_Callback(void *arg)
21 {
22 	uint32_t Tmr = *(uint32_t *)arg;
23 
24 	num_oneshots_executed++;
25 	TC_PRINT("oneshot_callback (Timer %d) = %d\n", Tmr, num_oneshots_executed);
26 }
27 
Timer2_Callback(void * arg)28 static void Timer2_Callback(void *arg)
29 {
30 	uint32_t Tmr = *(uint32_t *)arg;
31 
32 	num_periods_executed++;
33 	TC_PRINT("periodic_callback (Timer %d) = %d\n", Tmr, num_periods_executed);
34 }
35 
ZTEST(cmsis_timer,test_timer)36 ZTEST(cmsis_timer, test_timer)
37 {
38 	osTimerId_t id1;
39 	osTimerId_t id2;
40 	uint32_t exec1;
41 	uint32_t exec2;
42 	osStatus_t status;
43 	uint32_t timerDelay;
44 	const char *name;
45 
46 	/* Create one-shot timer */
47 	exec1 = 1U;
48 	id1 = osTimerNew(Timer1_Callback, osTimerOnce, &exec1, &timer_attr);
49 	zassert_true(id1 != NULL, "error creating one-shot timer");
50 
51 	name = osTimerGetName(id1);
52 	zassert_str_equal(timer_attr.name, name, "Error getting Timer name");
53 
54 	/* Stop the timer before start */
55 	status = osTimerStop(id1);
56 	zassert_true(status == osErrorResource, "error while stopping non-active timer");
57 
58 	timerDelay = ONESHOT_TIME_TICKS;
59 	status = osTimerStart(id1, timerDelay);
60 	zassert_true(status == osOK, "error starting one-shot timer");
61 
62 	zassert_equal(osTimerIsRunning(id1), 1, "Error: Timer not running");
63 
64 	/* Timer should fire only once if setup in one shot
65 	 * mode. Wait for 3 times the one-shot time to see
66 	 * if it fires more than once.
67 	 */
68 	osDelay(timerDelay * 3U + 10);
69 	zassert_true(num_oneshots_executed == 1U, "error setting up one-shot timer");
70 
71 	status = osTimerStop(id1);
72 	zassert_true(status == osOK, "error stopping one-shot timer");
73 
74 	status = osTimerDelete(id1);
75 	zassert_true(status == osOK, "error deleting one-shot timer");
76 
77 	/* Create periodic timer */
78 	exec2 = 2U;
79 	id2 = osTimerNew(Timer2_Callback, osTimerPeriodic, &exec2, NULL);
80 	zassert_true(id2 != NULL, "error creating periodic timer");
81 
82 	zassert_equal(osTimerIsRunning(id2), 0, "Error: Timer is running");
83 
84 	timerDelay = PERIOD_TICKS;
85 	status = osTimerStart(id2, timerDelay);
86 	zassert_true(status == osOK, "error starting periodic timer");
87 
88 	/* Timer should fire periodically if setup in periodic
89 	 * mode. Wait for NUM_PERIODS periods to see if it is
90 	 * fired NUM_PERIODS times.
91 	 */
92 	osDelay(timerDelay * NUM_PERIODS + 10);
93 
94 	zassert_true(num_periods_executed == NUM_PERIODS, "error setting up periodic timer");
95 
96 	/* Delete the timer before stop */
97 	status = osTimerDelete(id2);
98 	zassert_true(status == osOK, "error deleting periodic timer");
99 }
100 
101 static struct cmsis_rtos_timer_cb timer_cb3;
102 static const osTimerAttr_t timer_attr3 = {
103 	.name = "Timer3",
104 	.cb_mem = &timer_cb3,
105 	.cb_size = sizeof(timer_cb3),
106 };
Timer3_Callback(void * arg)107 static void Timer3_Callback(void *arg)
108 {
109 	printf("Timer3 callback ran\n");
110 }
ZTEST(cmsis_timer,test_timer_static_allocation)111 ZTEST(cmsis_timer, test_timer_static_allocation)
112 {
113 	osTimerId_t id;
114 	osStatus_t status;
115 
116 	id = osTimerNew(Timer3_Callback, osTimerOnce, NULL, &timer_attr3);
117 	zassert_true(id != NULL, "error creating timer with static cb");
118 	status = osTimerDelete(id);
119 	zassert_true(status == osOK, "error timer with static cb");
120 }
121 ZTEST_SUITE(cmsis_timer, NULL, NULL, NULL, NULL, NULL);
122