/* * Copyright (c) 2016 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief Verify PWM can work well when configure through nsec, * or cycle. * * @details * - Test Steps * -# Bind PWM_0 port 0. * -# Set PWM period and pulse using pwm_set_cycles() or pwm_set(). * -# Use multimeter or other instruments to measure the output * from PWM_OUT_0. * - Expected Results * -# The output of PWM_OUT_0 will differ according to the value * of period and pulse. * Always on -> Period : Pulse (1 : 1) -> 3.3V * Half on -> Period : Pulse (2 : 1) -> 1.65V * Always off -> Period : Pulse (1 : 0) -> 0V */ #include #include #include #include #include #if DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(pwm_0)) #define PWM_DEV_NODE DT_ALIAS(pwm_0) #elif DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(pwm_1)) #define PWM_DEV_NODE DT_ALIAS(pwm_1) #elif DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(pwm_2)) #define PWM_DEV_NODE DT_ALIAS(pwm_2) #elif DT_NODE_HAS_STATUS_OKAY(DT_ALIAS(pwm_3)) #define PWM_DEV_NODE DT_ALIAS(pwm_3) #elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_pwm) #define PWM_DEV_NODE DT_INST(0, nordic_nrf_pwm) #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_pwm) #define PWM_DEV_NODE DT_INST(0, st_stm32_pwm) #elif DT_HAS_COMPAT_STATUS_OKAY(xlnx_xps_timer_1_00_a_pwm) #define PWM_DEV_NODE DT_INST(0, xlnx_xps_timer_1_00_a_pwm) #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_ftm_pwm) #define PWM_DEV_NODE DT_INST(0, nxp_ftm_pwm) #elif DT_HAS_COMPAT_STATUS_OKAY(intel_blinky_pwm) #define PWM_DEV_NODE DT_INST(0, intel_blinky_pwm) #elif DT_HAS_COMPAT_STATUS_OKAY(renesas_ra_pwm) #define PWM_DEV_NODE DT_INST(0, renesas_ra_pwm) #else #error "Define a PWM device" #endif #if defined(CONFIG_BOARD_COLIBRI_IMX7D_MCIMX7D_M4) || defined(CONFIG_SOC_MK64F12) || \ defined(CONFIG_SOC_MKW41Z4) || defined(CONFIG_SOC_SERIES_ESP32S2) || \ defined(CONFIG_SOC_SERIES_ESP32S3) || defined(CONFIG_SOC_SERIES_ESP32C3) #define DEFAULT_PERIOD_CYCLE 1024 #define DEFAULT_PULSE_CYCLE 512 #define DEFAULT_PERIOD_NSEC 2000000 #define DEFAULT_PULSE_NSEC 500000 #elif DT_HAS_COMPAT_STATUS_OKAY(intel_blinky_pwm) #define DEFAULT_PERIOD_CYCLE 32768 #define DEFAULT_PULSE_CYCLE 16384 #define DEFAULT_PERIOD_NSEC 2000000 #define DEFAULT_PULSE_NSEC 500000 #else #define DEFAULT_PERIOD_CYCLE 64000 #define DEFAULT_PULSE_CYCLE 32000 #define DEFAULT_PERIOD_NSEC 2000000 #define DEFAULT_PULSE_NSEC 1000000 #endif #if DT_HAS_COMPAT_STATUS_OKAY(zephyr_fake_pwm) #include DEFINE_FFF_GLOBALS; #endif #if defined CONFIG_BOARD_SAM_E70_XPLAINED #define DEFAULT_PWM_PORT 2 /* PWM on EXT2 connector, pin 8 */ #elif defined CONFIG_PWM_NRFX #define DEFAULT_PWM_PORT 0 #define INVALID_PWM_PORT 9 #elif defined CONFIG_BOARD_ADAFRUIT_ITSYBITSY_M4_EXPRESS #define DEFAULT_PWM_PORT 2 /* TCC1/WO[2] on PA18 (D7) */ #elif defined CONFIG_BOARD_MIMXRT685_EVK #define DEFAULT_PWM_PORT 7 /* D3 on Arduino connector J27 */ #elif defined(CONFIG_BOARD_LPCXPRESSO55S69_LPC55S69_CPU0_NS) || \ defined(CONFIG_BOARD_LPCXPRESSO55S69_LPC55S69_CPU0) #define DEFAULT_PWM_PORT 2 /* D2 on Arduino connector P18 */ #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_pwm) /* Default port should be adapted per board to fit the channel * associated to the PWM pin. For intsance, for following device, * pwm1: pwm { * status = "okay"; * pinctrl-0 = <&tim1_ch3_pe13>; * }; * the following should be used: * #define DEFAULT_PWM_PORT 3 */ #define DEFAULT_PWM_PORT 1 #else #define DEFAULT_PWM_PORT 0 #endif #define UNIT_CYCLES 0 #define UNIT_NSECS 1 const struct device *get_pwm_device(void) { return DEVICE_DT_GET(PWM_DEV_NODE); } static int test_task(uint32_t port, uint32_t period, uint32_t pulse, uint8_t unit) { TC_PRINT("[PWM]: %" PRIu8 ", [period]: %" PRIu32 ", [pulse]: %" PRIu32 "\n", port, period, pulse); const struct device *pwm_dev = get_pwm_device(); if (!device_is_ready(pwm_dev)) { TC_PRINT("PWM device is not ready\n"); return TC_FAIL; } if (unit == UNIT_CYCLES) { /* Verify pwm_set_cycles() */ if (pwm_set_cycles(pwm_dev, port, period, pulse, 0)) { TC_PRINT("Fail to set the period and pulse width\n"); return TC_FAIL; } } else { /* unit == UNIT_NSECS */ /* Verify pwm_set() */ if (pwm_set(pwm_dev, port, period, pulse, 0)) { TC_PRINT("Fail to set the period and pulse width\n"); return TC_FAIL; } } return TC_PASS; } ZTEST_USER(pwm_basic, test_pwm_nsec) { /* Period : Pulse (2000000 : 1000000), unit (nsec). Voltage : 1.65V */ zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC, DEFAULT_PULSE_NSEC, UNIT_NSECS) == TC_PASS, NULL); k_sleep(K_MSEC(1000)); /* Period : Pulse (2000000 : 2000000), unit (nsec). Voltage : 3.3V */ zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC, DEFAULT_PERIOD_NSEC, UNIT_NSECS) == TC_PASS, NULL); k_sleep(K_MSEC(1000)); /* Period : Pulse (2000000 : 0), unit (nsec). Voltage : 0V */ zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC, 0, UNIT_NSECS) == TC_PASS, NULL); k_sleep(K_MSEC(1000)); } ZTEST_USER(pwm_basic, test_pwm_cycle) { /* Period : Pulse (64000 : 32000), unit (cycle). Voltage : 1.65V */ zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_CYCLE, DEFAULT_PULSE_CYCLE, UNIT_CYCLES) == TC_PASS, NULL); k_sleep(K_MSEC(1000)); /* Period : Pulse (64000 : 64000), unit (cycle). Voltage : 3.3V */ zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_CYCLE, DEFAULT_PERIOD_CYCLE, UNIT_CYCLES) == TC_PASS, NULL); k_sleep(K_MSEC(1000)); /* Period : Pulse (64000 : 0), unit (cycle). Voltage : 0V */ zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_CYCLE, 0, UNIT_CYCLES) == TC_PASS, NULL); k_sleep(K_MSEC(1000)); } #if defined INVALID_PWM_PORT ZTEST_USER(pwm_basic, test_pwm_invalid_port) { const struct device *pwm_dev = get_pwm_device(); TC_PRINT("[PWM]: %" PRIu8 ", [period]: %" PRIu32 ", [pulse]: %" PRIu32 "\n", INVALID_PWM_PORT, DEFAULT_PERIOD_CYCLE, DEFAULT_PULSE_CYCLE); zassert_true(device_is_ready(pwm_dev), "PWM device is not ready"); zassert_equal(pwm_set_cycles(pwm_dev, INVALID_PWM_PORT, DEFAULT_PERIOD_CYCLE, DEFAULT_PULSE_CYCLE, 0), -EINVAL, "Invalid PWM port\n"); } #endif