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 #else
60 #error "Define a PWM device"
61 #endif
62
63 #if defined(CONFIG_BOARD_COLIBRI_IMX7D_MCIMX7D_M4) || defined(CONFIG_SOC_MK64F12) || \
64 defined(CONFIG_SOC_MKW41Z4) || defined(CONFIG_SOC_SERIES_ESP32S2) || \
65 defined(CONFIG_SOC_SERIES_ESP32S3) || defined(CONFIG_SOC_SERIES_ESP32C3)
66 #define DEFAULT_PERIOD_CYCLE 1024
67 #define DEFAULT_PULSE_CYCLE 512
68 #define DEFAULT_PERIOD_NSEC 2000000
69 #define DEFAULT_PULSE_NSEC 500000
70 #elif DT_HAS_COMPAT_STATUS_OKAY(intel_blinky_pwm)
71 #define DEFAULT_PERIOD_CYCLE 32768
72 #define DEFAULT_PULSE_CYCLE 16384
73 #define DEFAULT_PERIOD_NSEC 2000000
74 #define DEFAULT_PULSE_NSEC 500000
75 #else
76 #define DEFAULT_PERIOD_CYCLE 64000
77 #define DEFAULT_PULSE_CYCLE 32000
78 #define DEFAULT_PERIOD_NSEC 2000000
79 #define DEFAULT_PULSE_NSEC 1000000
80 #endif
81
82 #if DT_HAS_COMPAT_STATUS_OKAY(zephyr_fake_pwm)
83 #include <zephyr/fff.h>
84 DEFINE_FFF_GLOBALS;
85 #endif
86
87 #if defined CONFIG_BOARD_SAM_E70_XPLAINED
88 #define DEFAULT_PWM_PORT 2 /* PWM on EXT2 connector, pin 8 */
89 #elif defined CONFIG_PWM_NRFX
90 #define DEFAULT_PWM_PORT 0
91 #define INVALID_PWM_PORT 9
92 #elif defined CONFIG_BOARD_ADAFRUIT_ITSYBITSY_M4_EXPRESS
93 #define DEFAULT_PWM_PORT 2 /* TCC1/WO[2] on PA18 (D7) */
94 #elif defined CONFIG_BOARD_MIMXRT685_EVK
95 #define DEFAULT_PWM_PORT 7 /* D3 on Arduino connector J27 */
96 #elif defined(CONFIG_BOARD_LPCXPRESSO55S69_LPC55S69_CPU0_NS) || \
97 defined(CONFIG_BOARD_LPCXPRESSO55S69_LPC55S69_CPU0)
98 #define DEFAULT_PWM_PORT 2 /* D2 on Arduino connector P18 */
99 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_pwm)
100 /* Default port should be adapted per board to fit the channel
101 * associated to the PWM pin. For intsance, for following device,
102 * pwm1: pwm {
103 * status = "okay";
104 * pinctrl-0 = <&tim1_ch3_pe13>;
105 * };
106 * the following should be used:
107 * #define DEFAULT_PWM_PORT 3
108 */
109 #define DEFAULT_PWM_PORT 1
110 #else
111 #define DEFAULT_PWM_PORT 0
112 #endif
113
114 #define UNIT_CYCLES 0
115 #define UNIT_NSECS 1
116
get_pwm_device(void)117 const struct device *get_pwm_device(void)
118 {
119 return DEVICE_DT_GET(PWM_DEV_NODE);
120 }
121
test_task(uint32_t port,uint32_t period,uint32_t pulse,uint8_t unit)122 static int test_task(uint32_t port, uint32_t period, uint32_t pulse, uint8_t unit)
123 {
124 TC_PRINT("[PWM]: %" PRIu8 ", [period]: %" PRIu32 ", [pulse]: %" PRIu32 "\n",
125 port, period, pulse);
126
127 const struct device *pwm_dev = get_pwm_device();
128
129 if (!device_is_ready(pwm_dev)) {
130 TC_PRINT("PWM device is not ready\n");
131 return TC_FAIL;
132 }
133
134 if (unit == UNIT_CYCLES) {
135 /* Verify pwm_set_cycles() */
136 if (pwm_set_cycles(pwm_dev, port, period, pulse, 0)) {
137 TC_PRINT("Fail to set the period and pulse width\n");
138 return TC_FAIL;
139 }
140 } else { /* unit == UNIT_NSECS */
141 /* Verify pwm_set() */
142 if (pwm_set(pwm_dev, port, period, pulse, 0)) {
143 TC_PRINT("Fail to set the period and pulse width\n");
144 return TC_FAIL;
145 }
146 }
147
148 return TC_PASS;
149 }
150
ZTEST_USER(pwm_basic,test_pwm_nsec)151 ZTEST_USER(pwm_basic, test_pwm_nsec)
152 {
153 /* Period : Pulse (2000000 : 1000000), unit (nsec). Voltage : 1.65V */
154 zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC,
155 DEFAULT_PULSE_NSEC, UNIT_NSECS) == TC_PASS, NULL);
156 k_sleep(K_MSEC(1000));
157
158 /* Period : Pulse (2000000 : 2000000), unit (nsec). Voltage : 3.3V */
159 zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC,
160 DEFAULT_PERIOD_NSEC, UNIT_NSECS) == TC_PASS, NULL);
161 k_sleep(K_MSEC(1000));
162
163 /* Period : Pulse (2000000 : 0), unit (nsec). Voltage : 0V */
164 zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC,
165 0, UNIT_NSECS) == TC_PASS, NULL);
166 k_sleep(K_MSEC(1000));
167 }
168
ZTEST_USER(pwm_basic,test_pwm_cycle)169 ZTEST_USER(pwm_basic, test_pwm_cycle)
170 {
171 /* Period : Pulse (64000 : 32000), unit (cycle). Voltage : 1.65V */
172 zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_CYCLE,
173 DEFAULT_PULSE_CYCLE, UNIT_CYCLES) == TC_PASS, NULL);
174 k_sleep(K_MSEC(1000));
175
176 /* Period : Pulse (64000 : 64000), unit (cycle). Voltage : 3.3V */
177 zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_CYCLE,
178 DEFAULT_PERIOD_CYCLE, UNIT_CYCLES) == TC_PASS, NULL);
179 k_sleep(K_MSEC(1000));
180
181 /* Period : Pulse (64000 : 0), unit (cycle). Voltage : 0V */
182 zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_CYCLE,
183 0, UNIT_CYCLES) == TC_PASS, NULL);
184 k_sleep(K_MSEC(1000));
185 }
186
187 #if defined INVALID_PWM_PORT
ZTEST_USER(pwm_basic,test_pwm_invalid_port)188 ZTEST_USER(pwm_basic, test_pwm_invalid_port)
189 {
190 const struct device *pwm_dev = get_pwm_device();
191
192 TC_PRINT("[PWM]: %" PRIu8 ", [period]: %" PRIu32 ", [pulse]: %" PRIu32 "\n",
193 INVALID_PWM_PORT, DEFAULT_PERIOD_CYCLE, DEFAULT_PULSE_CYCLE);
194
195 zassert_true(device_is_ready(pwm_dev), "PWM device is not ready");
196
197 zassert_equal(pwm_set_cycles(pwm_dev, INVALID_PWM_PORT, DEFAULT_PERIOD_CYCLE,
198 DEFAULT_PULSE_CYCLE, 0),
199 -EINVAL, "Invalid PWM port\n");
200
201 }
202 #endif
203