/* * Copyright (c) 2022 Google Inc * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include static struct gpio_dt_spec irq_pin = GPIO_DT_SPEC_GET(DT_INST(0, test_gpio_enable_disable_interrupt), irq_gpios); static struct gpio_callback cb_data; static bool cb_called; static void callback(const struct device *dev, struct gpio_callback *gpio_cb, uint32_t pins) { cb_called = true; } struct gpio_enable_disable_interrupt_fixture { const struct gpio_dt_spec *irq_spec; }; static void *gpio_enable_disable_interrupt_setup(void) { static struct gpio_enable_disable_interrupt_fixture fixture; fixture.irq_spec = &irq_pin; return &fixture; } static void gpio_enable_disable_interrupt_before(void *arg) { struct gpio_enable_disable_interrupt_fixture *fixture = (struct gpio_enable_disable_interrupt_fixture *)arg; zassert_true(gpio_is_ready_dt(fixture->irq_spec), "GPIO device is not ready"); zassert_ok(gpio_pin_configure_dt(fixture->irq_spec, GPIO_INPUT)); zassert_ok(gpio_emul_input_set(fixture->irq_spec->port, fixture->irq_spec->pin, 0), "failed to set value on input pin"); cb_called = false; zassert_ok(gpio_pin_interrupt_configure_dt(fixture->irq_spec, GPIO_INT_DISABLE)); gpio_init_callback(&cb_data, callback, BIT(fixture->irq_spec->pin)); zassert_ok(gpio_add_callback(fixture->irq_spec->port, &cb_data), "failed to add callback"); } static void gpio_enable_disable_interrupt_after(void *arg) { struct gpio_enable_disable_interrupt_fixture *fixture = (struct gpio_enable_disable_interrupt_fixture *)arg; zassert_ok(gpio_remove_callback(fixture->irq_spec->port, &cb_data), "failed to remove callback"); } static void enable_interrupt(const struct gpio_dt_spec *irq_spec) { zassert_ok(gpio_pin_interrupt_configure_dt(irq_spec, GPIO_INT_MODE_ENABLE_ONLY), "failed to only enable interrupt"); } static void disable_interrupt(const struct gpio_dt_spec *irq_spec) { zassert_ok(gpio_pin_interrupt_configure_dt(irq_spec, GPIO_INT_MODE_DISABLE_ONLY), " failed to only disable interrupt"); } static void trigger_callback(const struct gpio_dt_spec *irq_spec) { zassert_ok(gpio_emul_input_set(irq_spec->port, irq_spec->pin, 1), "failed to set value on input pin"); k_sleep(K_MSEC(100)); } ZTEST_F(gpio_enable_disable_interrupt, test_not_configured_as_interrupt) { enable_interrupt(fixture->irq_spec); trigger_callback(fixture->irq_spec); zassert_false(cb_called, "callback should not be executed before configuring the interrupt"); } ZTEST_F(gpio_enable_disable_interrupt, test_initial_enable_then_disable) { zassert_ok(gpio_pin_interrupt_configure_dt(fixture->irq_spec, GPIO_INT_EDGE_RISING), "failed to set interrupt with edge rising"); disable_interrupt(fixture->irq_spec); trigger_callback(fixture->irq_spec); zassert_false(cb_called, "callback should not be executed after disabling the interrupt"); } ZTEST_F(gpio_enable_disable_interrupt, test_disable_then_enable) { zassert_ok(gpio_pin_interrupt_configure_dt(fixture->irq_spec, GPIO_INT_EDGE_RISING), "failed to set interrupt with edge rising"); disable_interrupt(fixture->irq_spec); trigger_callback(fixture->irq_spec); enable_interrupt(fixture->irq_spec); zassert_true(cb_called, "callback should be executed after enabling the interrupt"); } ZTEST_SUITE(gpio_enable_disable_interrupt, NULL, gpio_enable_disable_interrupt_setup, gpio_enable_disable_interrupt_before, gpio_enable_disable_interrupt_after, NULL);