Newer
Older
mbed-os / hal / tests / TESTS / mbed_hal_fpga_ci_test_shield / gpio_irq / main.cpp
/*
 * Copyright (c) 2019, Arm Limited and affiliates.
 * 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.
 */

#if !DEVICE_INTERRUPTIN
#error [NOT_SUPPORTED] test not supported
#elif !COMPONENT_FPGA_CI_TEST_SHIELD
#error [NOT_SUPPORTED] FPGA CI Test Shield is needed to run this test
#elif !(defined(TARGET_FF_ARDUINO) || defined(TARGET_FF_ARDUINO_UNO)) && !defined(MBED_CONF_TARGET_DEFAULT_FORM_FACTOR)
#error [NOT_SUPPORTED] Test not supported for this form factor
#else

#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "mbed.h"
#include "MbedTester.h"
#include "pinmap.h"
#include "gpio_irq_fpga_test.h"

using namespace utest::v1;

#include "MbedTester.h"
#include "pinmap.h"
#include "test_utils.h"

MbedTester tester(DefaultFormFactor::pins(), DefaultFormFactor::restricted_pins());

static volatile uint32_t call_counter;
void test_gpio_irq_handler(uintptr_t context, gpio_irq_event event)
{
    call_counter++;
}

#define WAIT() wait_us(10)

void fpga_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;
    uintptr_t context = 123;
    TEST_ASSERT_EQUAL(0, gpio_irq_init(&gpio_irq, pin, test_gpio_irq_handler, context));

    gpio_irq_set(&gpio_irq, IRQ_RISE, true);
    gpio_irq_enable(&gpio_irq);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();

    // test irq on rising edge
    call_counter = 0;
    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(1, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(1, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(2, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(2, call_counter);

    gpio_irq_disable(&gpio_irq);

    call_counter = 0;
    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(0, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(0, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(0, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(0, call_counter);

    gpio_irq_enable(&gpio_irq);

    call_counter = 0;
    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(1, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(1, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(2, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(2, call_counter);

    // test irq on both rising and falling edge
    gpio_irq_set(&gpio_irq, IRQ_FALL, true);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();

    call_counter = 0;
    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(1, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(2, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(3, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(4, call_counter);

    gpio_irq_disable(&gpio_irq);

    call_counter = 0;
    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(0, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(0, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(0, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(0, call_counter);

    gpio_irq_enable(&gpio_irq);

    call_counter = 0;
    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(1, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(2, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(3, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(4, call_counter);

    // test irq on falling edge
    gpio_irq_set(&gpio_irq, IRQ_RISE, false);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();

    call_counter = 0;
    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(1, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(1, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(2, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(2, call_counter);

    gpio_irq_disable(&gpio_irq);

    call_counter = 0;
    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(0, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(0, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(0, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(0, call_counter);

    gpio_irq_enable(&gpio_irq);

    call_counter = 0;
    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(1, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(1, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 0, true);
    WAIT();
    TEST_ASSERT_EQUAL(2, call_counter);

    tester.gpio_write(MbedTester::LogicalPinGPIO0, 1, true);
    WAIT();
    TEST_ASSERT_EQUAL(2, call_counter);

    gpio_irq_free(&gpio_irq);
}

void fpga_gpio_irq_init_free_test(PinName pin)
{
    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("init/free", all_ports<GPIOIRQPort, DefaultFormFactor, fpga_gpio_irq_init_free_test>),
    Case("rising & falling edge", all_ports<GPIOIRQPort, DefaultFormFactor, fpga_gpio_irq_test>),
};

utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
    GREENTEA_SETUP(60, "default_auto");
    return greentea_test_setup_handler(number_of_cases);
}

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main()
{
    Harness::run(specification);
}

#endif /* !DEVICE_INTERRUPTIN */