Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | /* * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include "test_gpio.h" static struct drv_data data; static int cb_cnt; static void callback(const struct device *dev, struct gpio_callback *gpio_cb, uint32_t pins) { const struct drv_data *dd = CONTAINER_OF(gpio_cb, struct drv_data, gpio_cb); /*= checkpoint: pins should be marked with correct pin number bit =*/ zassert_equal(pins, BIT(PIN_IN), "unexpected pins %x", pins); ++cb_cnt; TC_PRINT("callback triggered: %d\n", cb_cnt); if ((cb_cnt == 1) && (dd->mode == GPIO_INT_EDGE_BOTH)) { gpio_pin_toggle(dev, PIN_OUT); } if (cb_cnt >= MAX_INT_CNT) { gpio_pin_set(dev, PIN_OUT, 0); gpio_pin_interrupt_configure(dev, PIN_IN, GPIO_INT_DISABLE); } } static int test_callback(int mode) { const struct device *dev = device_get_binding(DEV_NAME); struct drv_data *drv_data = &data; gpio_pin_interrupt_configure(dev, PIN_IN, GPIO_INT_DISABLE); gpio_pin_interrupt_configure(dev, PIN_OUT, GPIO_INT_DISABLE); /* 1. set PIN_OUT to logical initial state inactive */ uint32_t out_flags = GPIO_OUTPUT_LOW; if ((mode & GPIO_INT_LOW_0) != 0) { out_flags = GPIO_OUTPUT_HIGH | GPIO_ACTIVE_LOW; } int rc = gpio_pin_configure(dev, PIN_OUT, out_flags); if (rc != 0) { TC_ERROR("PIN_OUT config fail: %d", rc); return TC_FAIL; } /* 2. configure PIN_IN callback and trigger condition */ rc = gpio_pin_configure(dev, PIN_IN, GPIO_INPUT); if (rc != 0) { TC_ERROR("config PIN_IN fail: %d\n", rc); goto err_exit; } drv_data->mode = mode; gpio_init_callback(&drv_data->gpio_cb, callback, BIT(PIN_IN)); rc = gpio_add_callback(dev, &drv_data->gpio_cb); if (rc == -ENOTSUP) { TC_PRINT("interrupts not supported\n"); return TC_PASS; } else if (rc != 0) { TC_ERROR("set PIN_IN callback fail: %d\n", rc); return TC_FAIL; } /* 3. enable callback, trigger PIN_IN interrupt by operate PIN_OUT */ cb_cnt = 0; rc = gpio_pin_interrupt_configure(dev, PIN_IN, mode); if (rc == -ENOTSUP) { TC_PRINT("Mode %x not supported\n", mode); goto pass_exit; } else if (rc != 0) { TC_ERROR("config PIN_IN interrupt fail: %d\n", rc); goto err_exit; } k_sleep(K_MSEC(100)); gpio_pin_set(dev, PIN_OUT, 1); k_sleep(K_MSEC(1000)); (void)gpio_pin_interrupt_configure(dev, PIN_IN, GPIO_INT_DISABLE); /*= checkpoint: check callback is triggered =*/ TC_PRINT("OUT init %x, IN cfg %x, cnt %d\n", out_flags, mode, cb_cnt); if (mode == GPIO_INT_EDGE_BOTH) { if (cb_cnt != 2) { TC_ERROR("double edge not detected\n"); goto err_exit; } goto pass_exit; } if ((mode & GPIO_INT_EDGE) == GPIO_INT_EDGE) { if (cb_cnt != 1) { TC_ERROR("edge not trigger callback correctly\n"); goto err_exit; } goto pass_exit; } else { if (cb_cnt != MAX_INT_CNT) { TC_ERROR("level not trigger callback correctly\n"); goto err_exit; } } pass_exit: gpio_remove_callback(dev, &drv_data->gpio_cb); return TC_PASS; err_exit: gpio_remove_callback(dev, &drv_data->gpio_cb); return TC_FAIL; } /* export test cases */ void test_gpio_callback_variants(void) { zassert_equal(test_callback(GPIO_INT_EDGE_FALLING), TC_PASS, "falling edge failed"); zassert_equal(test_callback(GPIO_INT_EDGE_RISING), TC_PASS, "rising edge failed"); zassert_equal(test_callback(GPIO_INT_EDGE_TO_ACTIVE), TC_PASS, "edge active failed"); zassert_equal(test_callback(GPIO_INT_EDGE_TO_INACTIVE), TC_PASS, "edge inactive failed"); zassert_equal(test_callback(GPIO_INT_LEVEL_HIGH), TC_PASS, "level high failed"); zassert_equal(test_callback(GPIO_INT_LEVEL_LOW), TC_PASS, "level low failed"); zassert_equal(test_callback(GPIO_INT_LEVEL_ACTIVE), TC_PASS, "level active failed"); zassert_equal(test_callback(GPIO_INT_LEVEL_INACTIVE), TC_PASS, "level inactive failed"); zassert_equal(test_callback(GPIO_INT_EDGE_BOTH), TC_PASS, "edge both failed"); } |