1 /*
2 * Copyright (c) 2016 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief Verify PWM can work well when configure through nsec,
10 * or cycle.
11 *
12 * @details
13 * - Test Steps
14 * -# Bind PWM_0 port 0.
15 * -# Set PWM period and pulse using pwm_set_cycles() or pwm_set().
16 * -# Use multimeter or other instruments to measure the output
17 * from PWM_OUT_0.
18 * - Expected Results
19 * -# The output of PWM_OUT_0 will differ according to the value
20 * of period and pulse.
21 * Always on -> Period : Pulse (1 : 1) -> 3.3V
22 * Half on -> Period : Pulse (2 : 1) -> 1.65V
23 * Always off -> Period : Pulse (1 : 0) -> 0V
24 */
25
26 #include <zephyr/device.h>
27 #include <inttypes.h>
28 #include <zephyr/drivers/pwm.h>
29 #include <zephyr/kernel.h>
30 #include <zephyr/ztest.h>
31
32 #if DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(pwm_0))
33 #define PWM_DEV_NODE DT_ALIAS(pwm_0)
34 #elif DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(pwm_1))
35 #define PWM_DEV_NODE DT_ALIAS(pwm_1)
36 #elif DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(pwm_2))
37 #define PWM_DEV_NODE DT_ALIAS(pwm_2)
38 #elif DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(pwm_3))
39 #define PWM_DEV_NODE DT_ALIAS(pwm_3)
40
41 #elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_pwm)
42 #define PWM_DEV_NODE DT_INST(0, nordic_nrf_pwm)
43
44 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_pwm)
45 #define PWM_DEV_NODE DT_INST(0, st_stm32_pwm)
46
47 #elif DT_HAS_COMPAT_STATUS_OKAY(xlnx_xps_timer_1_00_a_pwm)
48 #define PWM_DEV_NODE DT_INST(0, xlnx_xps_timer_1_00_a_pwm)
49
50 #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_ftm_pwm)
51 #define PWM_DEV_NODE DT_INST(0, nxp_ftm_pwm)
52
53 #elif DT_HAS_COMPAT_STATUS_OKAY(intel_blinky_pwm)
54 #define PWM_DEV_NODE DT_INST(0, intel_blinky_pwm)
55
56 #elif DT_HAS_COMPAT_STATUS_OKAY(renesas_ra_pwm)
57 #define PWM_DEV_NODE DT_INST(0, renesas_ra_pwm)
58
59 #elif DT_HAS_COMPAT_STATUS_OKAY(renesas_rz_gpt_pwm)
60 #define PWM_DEV_NODE DT_INST(0, renesas_rz_gpt_pwm)
61
62 #elif DT_HAS_COMPAT_STATUS_OKAY(renesas_rz_mtu_pwm)
63 #define PWM_DEV_NODE DT_INST(0, renesas_rz_mtu_pwm)
64
65 #else
66 #error "Define a PWM device"
67 #endif
68
69 #if defined(CONFIG_BOARD_COLIBRI_IMX7D_MCIMX7D_M4) || defined(CONFIG_SOC_MK64F12) || \
70 defined(CONFIG_SOC_MKW41Z4) || defined(CONFIG_SOC_SERIES_ESP32S2) || \
71 defined(CONFIG_SOC_SERIES_ESP32S3) || defined(CONFIG_SOC_SERIES_ESP32C3)
72 #define DEFAULT_PERIOD_CYCLE 1024
73 #define DEFAULT_PULSE_CYCLE 512
74 #define DEFAULT_PERIOD_NSEC 2000000
75 #define DEFAULT_PULSE_NSEC 500000
76 #elif DT_HAS_COMPAT_STATUS_OKAY(intel_blinky_pwm)
77 #define DEFAULT_PERIOD_CYCLE 32768
78 #define DEFAULT_PULSE_CYCLE 16384
79 #define DEFAULT_PERIOD_NSEC 2000000
80 #define DEFAULT_PULSE_NSEC 500000
81 #elif defined(CONFIG_SOC_FAMILY_MCXW)
82 #define DEFAULT_PERIOD_CYCLE 64000
83 #define DEFAULT_PULSE_CYCLE 32000
84 #define DEFAULT_PERIOD_NSEC 4000000
85 #define DEFAULT_PULSE_NSEC 2000000
86 #else
87 #define DEFAULT_PERIOD_CYCLE 64000
88 #define DEFAULT_PULSE_CYCLE 32000
89 #define DEFAULT_PERIOD_NSEC 2000000
90 #define DEFAULT_PULSE_NSEC 1000000
91 #endif
92
93 #if DT_HAS_COMPAT_STATUS_OKAY(zephyr_fake_pwm)
94 #include <zephyr/fff.h>
95 DEFINE_FFF_GLOBALS;
96 #endif
97
98 #if defined CONFIG_BOARD_SAM_E70_XPLAINED
99 #define DEFAULT_PWM_PORT 2 /* PWM on EXT2 connector, pin 8 */
100 #elif defined CONFIG_PWM_NRFX
101 #define DEFAULT_PWM_PORT 0
102 #define INVALID_PWM_PORT 9
103 #elif defined CONFIG_BOARD_ADAFRUIT_ITSYBITSY_M4_EXPRESS
104 #define DEFAULT_PWM_PORT 2 /* TCC1/WO[2] on PA18 (D7) */
105 #elif defined CONFIG_BOARD_MIMXRT685_EVK
106 #define DEFAULT_PWM_PORT 7 /* D3 on Arduino connector J27 */
107 #elif defined(CONFIG_BOARD_LPCXPRESSO55S69_LPC55S69_CPU0_NS) || \
108 defined(CONFIG_BOARD_LPCXPRESSO55S69_LPC55S69_CPU0)
109 #define DEFAULT_PWM_PORT 2 /* D2 on Arduino connector P18 */
110 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_pwm)
111 /* Default port should be adapted per board to fit the channel
112 * associated to the PWM pin. For intsance, for following device,
113 * pwm1: pwm {
114 * status = "okay";
115 * pinctrl-0 = <&tim1_ch3_pe13>;
116 * };
117 * the following should be used:
118 * #define DEFAULT_PWM_PORT 3
119 */
120 #define DEFAULT_PWM_PORT 1
121 #else
122 #define DEFAULT_PWM_PORT 0
123 #endif
124
125 #define UNIT_CYCLES 0
126 #define UNIT_NSECS 1
127
get_pwm_device(void)128 const struct device *get_pwm_device(void)
129 {
130 return DEVICE_DT_GET(PWM_DEV_NODE);
131 }
132
test_task(uint32_t port,uint32_t period,uint32_t pulse,uint8_t unit)133 static int test_task(uint32_t port, uint32_t period, uint32_t pulse, uint8_t unit)
134 {
135 TC_PRINT("[PWM]: %" PRIu8 ", [period]: %" PRIu32 ", [pulse]: %" PRIu32 "\n",
136 port, period, pulse);
137
138 const struct device *pwm_dev = get_pwm_device();
139
140 if (!device_is_ready(pwm_dev)) {
141 TC_PRINT("PWM device is not ready\n");
142 return TC_FAIL;
143 }
144
145 if (unit == UNIT_CYCLES) {
146 /* Verify pwm_set_cycles() */
147 if (pwm_set_cycles(pwm_dev, port, period, pulse, 0)) {
148 TC_PRINT("Fail to set the period and pulse width\n");
149 return TC_FAIL;
150 }
151 } else { /* unit == UNIT_NSECS */
152 /* Verify pwm_set() */
153 if (pwm_set(pwm_dev, port, period, pulse, 0)) {
154 TC_PRINT("Fail to set the period and pulse width\n");
155 return TC_FAIL;
156 }
157 }
158
159 return TC_PASS;
160 }
161
ZTEST_USER(pwm_basic,test_pwm_nsec)162 ZTEST_USER(pwm_basic, test_pwm_nsec)
163 {
164 /* Period : Pulse (2000000 : 1000000), unit (nsec). Voltage : 1.65V */
165 zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC,
166 DEFAULT_PULSE_NSEC, UNIT_NSECS) == TC_PASS);
167 k_sleep(K_MSEC(1000));
168
169 /* Period : Pulse (2000000 : 2000000), unit (nsec). Voltage : 3.3V */
170 zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC,
171 DEFAULT_PERIOD_NSEC, UNIT_NSECS) == TC_PASS);
172 k_sleep(K_MSEC(1000));
173
174 /* Period : Pulse (2000000 : 0), unit (nsec). Voltage : 0V */
175 zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC,
176 0, UNIT_NSECS) == TC_PASS);
177 k_sleep(K_MSEC(1000));
178 }
179
ZTEST_USER(pwm_basic,test_pwm_cycle)180 ZTEST_USER(pwm_basic, test_pwm_cycle)
181 {
182 /* Period : Pulse (64000 : 32000), unit (cycle). Voltage : 1.65V */
183 zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_CYCLE,
184 DEFAULT_PULSE_CYCLE, UNIT_CYCLES) == TC_PASS);
185 k_sleep(K_MSEC(1000));
186
187 /* Period : Pulse (64000 : 64000), unit (cycle). Voltage : 3.3V */
188 zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_CYCLE,
189 DEFAULT_PERIOD_CYCLE, UNIT_CYCLES) == TC_PASS);
190 k_sleep(K_MSEC(1000));
191
192 /* Period : Pulse (64000 : 0), unit (cycle). Voltage : 0V */
193 zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_CYCLE,
194 0, UNIT_CYCLES) == TC_PASS);
195 k_sleep(K_MSEC(1000));
196 }
197
198 #if defined INVALID_PWM_PORT
ZTEST_USER(pwm_basic,test_pwm_invalid_port)199 ZTEST_USER(pwm_basic, test_pwm_invalid_port)
200 {
201 const struct device *pwm_dev = get_pwm_device();
202
203 TC_PRINT("[PWM]: %" PRIu8 ", [period]: %" PRIu32 ", [pulse]: %" PRIu32 "\n",
204 INVALID_PWM_PORT, DEFAULT_PERIOD_CYCLE, DEFAULT_PULSE_CYCLE);
205
206 zassert_true(device_is_ready(pwm_dev), "PWM device is not ready");
207
208 zassert_equal(pwm_set_cycles(pwm_dev, INVALID_PWM_PORT, DEFAULT_PERIOD_CYCLE,
209 DEFAULT_PULSE_CYCLE, 0),
210 -EINVAL, "Invalid PWM port\n");
211
212 }
213 #endif
214