diff --git a/TESTS/mbed_hal/critical_section/critical_section_test.h b/TESTS/mbed_hal/critical_section/critical_section_test.h new file mode 100644 index 0000000000..3a85684d98 --- /dev/null +++ b/TESTS/mbed_hal/critical_section/critical_section_test.h @@ -0,0 +1,51 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * 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. + */ + +/** \addtogroup hal_critical_tests + * @{ + */ + +#ifndef MBED_CRITICAL_SECTION_TEST_H +#define MBED_CRITICAL_SECTION_TEST_H + +/** Template for HAL critical section tests + * + * Test critical section + * Given a critical section HAL mechanism + * When before critical section + * Then interrupts are enabled + * When inside critical section + * Then interrupts are disabled + * When after critical section + * Then interrupts are enabled again + * + * Test critical section - nested lock + * Given a critical section HAL mechanism + * When before critical section + * Then interrupts are enabled + * When inside nested critical section + * Then interrupts are disabled + * When after nested critical section + * Then interrupts are enabled again + * + */ +template +void test_critical_section(); + + +/**@}*/ + +#endif // MBED_CRITICAL_SECTION_TEST_H diff --git a/TESTS/mbed_hal/critical_section/main.cpp b/TESTS/mbed_hal/critical_section/main.cpp new file mode 100644 index 0000000000..faa0039fc8 --- /dev/null +++ b/TESTS/mbed_hal/critical_section/main.cpp @@ -0,0 +1,84 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * 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 "critical_section_test.h" +#include "hal/critical_section_api.h" +#include "utest/utest.h" +#include "unity/unity.h" +#include "greentea-client/test_env.h" +#include "mbed.h" +#include "cmsis.h" +#ifdef TARGET_NRF5 // for all NRF5x targets +#include "nrf_nvic.h" // for __NRF_NVIC_APP_IRQS_0 / __NRF_NVIC_APP_IRQS_1 +#endif + +using utest::v1::Case; + +bool test_are_interrupts_enabled(void) +{ + // NRF5x targets don't disable interrupts when in critical section, instead they mask application interrupts this is due to BLE stack + // (BLE to be operational requires some interrupts to be always enabled) +#ifdef TARGET_NRF52_DK + // check if APP interrupts are masked for NRF52_DK board + return (((NVIC->ISER[0] & __NRF_NVIC_APP_IRQS_0) != 0) || ((NVIC->ISER[1] & __NRF_NVIC_APP_IRQS_1) != 0)); +#elif TARGET_NRF5 + // check if APP interrupts are masked for other NRF5 boards + return ((NVIC->ISER[0] & __NRF_NVIC_APP_IRQS_0) != 0); +#else +#if defined(__CORTEX_A9) + return ((__get_CPSR() & 0x80) == 0); +#else + return ((__get_PRIMASK() & 0x1) == 0); +#endif +#endif +} + + +template +void test_critical_section() +{ + TEST_ASSERT_FALSE(hal_in_critical_section()); + TEST_ASSERT_TRUE(test_are_interrupts_enabled()); + + for (int i = 0; i < N; i++) { + hal_critical_section_enter(); + TEST_ASSERT_TRUE(hal_in_critical_section()); + TEST_ASSERT_FALSE(test_are_interrupts_enabled()); + } + + // assumed to be called once (according API) + hal_critical_section_exit(); + + TEST_ASSERT_FALSE(hal_in_critical_section()); + TEST_ASSERT_TRUE(test_are_interrupts_enabled()); +} + +Case cases[] = { + Case("Test critical section single lock", test_critical_section<1>), + Case("Test critical section nested lock", test_critical_section<10>) +}; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(10, "timing_drift_auto"); + return utest::v1::greentea_test_setup_handler(number_of_cases); +} + +utest::v1::Specification specification(greentea_test_setup, cases); + +int main() +{ + return !utest::v1::Harness::run(specification); +}