diff --git a/TESTS/mbed_hal/pinmap/main.cpp b/TESTS/mbed_hal/pinmap/main.cpp index 103902be4a..79c600c3b7 100644 --- a/TESTS/mbed_hal/pinmap/main.cpp +++ b/TESTS/mbed_hal/pinmap/main.cpp @@ -21,6 +21,7 @@ using namespace utest::v1; #include "gpio_api.h" +#include "gpio_irq_api.h" #include "analogin_api.h" #include "analogout_api.h" #include "can_api.h" @@ -40,6 +41,9 @@ typedef struct { const pinmap_info_t pinmap_functions[] = { PINMAP_TEST_ENTRY(gpio_pinmap), +#if DEVICE_INTERRUPTIN + PINMAP_TEST_ENTRY(gpio_irq_pinmap), +#endif #if DEVICE_ANALOGIN PINMAP_TEST_ENTRY(analogin_pinmap), #endif diff --git a/TESTS/mbed_hal_fpga_ci_test_shield/gpio_irq/main.cpp b/TESTS/mbed_hal_fpga_ci_test_shield/gpio_irq/main.cpp index 7f9b6da15b..c1b2464fc9 100644 --- a/TESTS/mbed_hal_fpga_ci_test_shield/gpio_irq/main.cpp +++ b/TESTS/mbed_hal_fpga_ci_test_shield/gpio_irq/main.cpp @@ -30,32 +30,38 @@ using namespace utest::v1; -#include "mbed.h" #include "MbedTester.h" #include "pinmap.h" +#include "test_utils.h" -static uint32_t call_counter; +MbedTester tester(DefaultFormFactor::pins(), DefaultFormFactor::restricted_pins()); + +static volatile uint32_t call_counter; void test_gpio_irq_handler(uint32_t id, gpio_irq_event event) { call_counter++; } -const PinList *form_factor = pinmap_ff_default_pins(); -const PinList *restricted = pinmap_restricted_pins(); -MbedTester tester(form_factor, restricted); - #define WAIT() wait_us(10) - void gpio_irq_test(PinName pin) { + // Reset everything and set all tester pins to hi-Z. + tester.reset(); + + // Map pins for test. + tester.pin_map_set(pin, MbedTester::LogicalPinGPIO0); + + // Select GPIO0. + tester.select_peripheral(MbedTester::PeripheralGPIO); + gpio_t gpio; // configure pin as input gpio_init_in(&gpio, pin); gpio_irq_t gpio_irq; uint32_t id = 123; - gpio_irq_init(&gpio_irq, pin, test_gpio_irq_handler, id); + TEST_ASSERT_EQUAL(0, gpio_irq_init(&gpio_irq, pin, test_gpio_irq_handler, id)); gpio_irq_set(&gpio_irq, IRQ_RISE, true); gpio_irq_enable(&gpio_irq); @@ -241,51 +247,26 @@ void gpio_irq_test(PinName pin) WAIT(); TEST_ASSERT_EQUAL(2, call_counter); - gpio_irq_free(&gpio_irq); } - -void gpio_irq_test() +void init_free_test(PinName pin) { - for (uint32_t i = 0; i < form_factor->count; i++) { - const PinName test_pin = form_factor->pins[i]; - if (test_pin == NC) { - continue; - } - if (pinmap_list_has_pin(restricted, test_pin)) { - printf("Skipping gpio pin %s (%i)\r\n", pinmap_ff_default_pin_to_string(test_pin), test_pin); - continue; - } - tester.pin_map_reset(); - tester.pin_map_set(test_pin, MbedTester::LogicalPinGPIO0); - - printf("GPIO irq test on pin %3s (%3i)\r\n", pinmap_ff_default_pin_to_string(test_pin), test_pin); - gpio_irq_test(test_pin); - } -} - -utest::v1::status_t setup(const Case *const source, const size_t index_of_case) -{ - tester.reset(); - tester.select_peripheral(MbedTester::PeripheralGPIO); - - return greentea_case_setup_handler(source, index_of_case); -} - -utest::v1::status_t teardown(const Case *const source, const size_t passed, const size_t failed, - const failure_t reason) -{ - return greentea_case_teardown_handler(source, passed, failed, reason); + gpio_t gpio; + gpio_irq_t gpio_irq; + gpio_init_in(&gpio, pin); + TEST_ASSERT_EQUAL(0, gpio_irq_init(&gpio_irq, pin, test_gpio_irq_handler, 123)); + gpio_irq_free(&gpio_irq); } Case cases[] = { - Case("GPIO - irq test", setup, gpio_irq_test, teardown) + Case("init/free", all_ports), + Case("rising & falling edge", all_ports), }; utest::v1::status_t greentea_test_setup(const size_t number_of_cases) { - GREENTEA_SETUP(10, "default_auto"); + GREENTEA_SETUP(60, "default_auto"); return greentea_test_setup_handler(number_of_cases); } diff --git a/components/testing/COMPONENT_FPGA_CI_TEST_SHIELD/test_utils.h b/components/testing/COMPONENT_FPGA_CI_TEST_SHIELD/test_utils.h index ebcad147fc..5deeaeb430 100644 --- a/components/testing/COMPONENT_FPGA_CI_TEST_SHIELD/test_utils.h +++ b/components/testing/COMPONENT_FPGA_CI_TEST_SHIELD/test_utils.h @@ -440,6 +440,19 @@ const char *const GPIOMaps::pin_type_names[] = { "IO" }; const char *const GPIOMaps::name = "GPIO"; typedef Port<1, GPIOMaps, DefaultFormFactor, TF1> GPIOPort; +#if DEVICE_INTERRUPTIN +#include "gpio_irq_api.h" +struct GPIOIRQMaps { + static const PinMap *maps[]; + static const char *const pin_type_names[]; + static const char *const name; +}; +const PinMap *GPIOIRQMaps::maps[] = { gpio_irq_pinmap() }; +const char *const GPIOIRQMaps::pin_type_names[] = { "IRQ_IN" }; +const char *const GPIOIRQMaps::name = "GPIO_IRQ"; +typedef Port<1, GPIOIRQMaps, DefaultFormFactor, TF1> GPIOIRQPort; +#endif + #if DEVICE_SPI #include "spi_api.h" struct SPIMaps { diff --git a/hal/gpio_irq_api.h b/hal/gpio_irq_api.h index 6ca858f600..931c800164 100644 --- a/hal/gpio_irq_api.h +++ b/hal/gpio_irq_api.h @@ -21,6 +21,7 @@ #define MBED_GPIO_IRQ_API_H #include "device.h" +#include "pinmap.h" #if DEVICE_INTERRUPTIN @@ -85,6 +86,18 @@ void gpio_irq_enable(gpio_irq_t *obj); */ void gpio_irq_disable(gpio_irq_t *obj); +/** Get the pins that support all GPIO IRQ tests + * + * Return a PinMap array of pins that support GPIO IRQ. + * The array is terminated with {NC, NC, 0}. + * + * Targets should override the weak implementation of this + * function to provide the actual pinmap for GPIO IRQ testing. + * + * @return PinMap array + */ +const PinMap *gpio_irq_pinmap(void); + /**@}*/ #ifdef __cplusplus diff --git a/hal/mbed_gpio_irq.c b/hal/mbed_gpio_irq.c new file mode 100644 index 0000000000..b8c6e86d56 --- /dev/null +++ b/hal/mbed_gpio_irq.c @@ -0,0 +1,31 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "hal/gpio_irq_api.h" + +#if DEVICE_INTERRUPTIN + +#include "platform/mbed_toolchain.h" +#include "hal/gpio_api.h" + +MBED_WEAK const PinMap *gpio_irq_pinmap() +{ + // Targets should override this weak implementation to provide correct data. + // By default, this is exactly the same as GPIO PinMap. + return gpio_pinmap(); +} + +#endif diff --git a/targets/TARGET_Cypress/TARGET_PSOC6_FUTURE/gpio_irq_api.c b/targets/TARGET_Cypress/TARGET_PSOC6_FUTURE/gpio_irq_api.c index 54baf3e18c..8ed9bc6b8e 100644 --- a/targets/TARGET_Cypress/TARGET_PSOC6_FUTURE/gpio_irq_api.c +++ b/targets/TARGET_Cypress/TARGET_PSOC6_FUTURE/gpio_irq_api.c @@ -49,7 +49,7 @@ static void gpio_irq_dispatcher(uint32_t port_id) MBED_ASSERT(obj); Cy_GPIO_ClearInterrupt(port, pin); event = (obj->mode == IRQ_FALL)? IRQ_FALL : IRQ_RISE; - obj->handler(obj->id_arg, event); + ((gpio_irq_handler) obj->handler)(obj->id_arg, event); } } } @@ -202,7 +202,7 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32 MBED_ASSERT("Invalid pin ID!"); return (-1); } - obj->handler = handler; + obj->handler = (uint32_t) handler; obj->id_arg = id; return gpio_irq_setup_channel(obj); } else { diff --git a/targets/TARGET_Cypress/TARGET_PSOC6_FUTURE/objects.h b/targets/TARGET_Cypress/TARGET_PSOC6_FUTURE/objects.h index 43daa3e7a9..094ffd6aec 100644 --- a/targets/TARGET_Cypress/TARGET_PSOC6_FUTURE/objects.h +++ b/targets/TARGET_Cypress/TARGET_PSOC6_FUTURE/objects.h @@ -23,7 +23,6 @@ #include "PinNames.h" #include "PortNames.h" -#include "gpio_irq_api.h" #include "gpio_object.h" #include "cy_sysclk.h" #include "cy_syspm.h" @@ -37,8 +36,8 @@ struct gpio_irq_s { GPIO_PRT_Type* port; uint32_t port_id; uint32_t pin; - gpio_irq_event mode; - gpio_irq_handler handler; + uint32_t mode; + uint32_t handler; uint32_t id_arg; #if defined (TARGET_MCU_PSOC6_M0) cy_en_intr_t cm0p_irq_src;