diff --git a/TESTS/events/queue/main.cpp b/TESTS/events/queue/main.cpp index 75d724f9ed..7a7253346d 100644 --- a/TESTS/events/queue/main.cpp +++ b/TESTS/events/queue/main.cpp @@ -20,8 +20,15 @@ #include "unity.h" #include "utest.h" +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif + using namespace utest::v1; +// Assume that tolerance is 5% of measured time. +#define DELTA(ms) (ms / 20) + // TEST_EQUEUE_SIZE was reduced below 1024B to fit this test to devices with small RAM (RAM <= 16kB) // additionally TEST_EQUEUE_SIZE was expressed in EVENTS_EVENT_SIZE to increase readability // (for more details about EVENTS_EVENT_SIZE see EventQueue constructor) @@ -89,7 +96,7 @@ SIMPLE_POSTS_TEST(0) void time_func(Timer *t, int ms) { - TEST_ASSERT_INT_WITHIN(5, ms, t->read_ms()); + TEST_ASSERT_INT_WITHIN(DELTA(ms), ms, t->read_ms()); t->reset(); } diff --git a/TESTS/events/timing/main.cpp b/TESTS/events/timing/main.cpp index 74ec8f949f..e93c75cfb0 100644 --- a/TESTS/events/timing/main.cpp +++ b/TESTS/events/timing/main.cpp @@ -24,6 +24,9 @@ using namespace utest::v1; +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif // Test delay #ifndef TEST_EVENTS_TIMING_TIME diff --git a/TESTS/host_tests/rtc_reset.py b/TESTS/host_tests/rtc_reset.py new file mode 100644 index 0000000000..abe1afd9c6 --- /dev/null +++ b/TESTS/host_tests/rtc_reset.py @@ -0,0 +1,144 @@ +""" +mbed SDK +Copyright (c) 2017-2017 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. +""" +from __future__ import print_function + +from mbed_host_tests import BaseHostTest +from time import sleep + + +class RtcResetTest(BaseHostTest): + """This test checks that a device's RTC keeps count through a reset + + It does this by setting the RTC's time, triggering a reset, + delaying and then reading the RTC's time again to ensure + that the RTC is still counting. + """ + + """Start of the RTC""" + START_TIME = 50000 + START_TIME_TOLERANCE = 10 + """Time to delay after sending reset""" + DELAY_TIME = 5.0 + DELAY_TOLERANCE = 1.0 + VALUE_PLACEHOLDER = "0" + + def setup(self): + """Register callbacks required for the test""" + self._error = False + generator = self.rtc_reset_test() + generator.next() + + def run_gen(key, value, time): + """Run the generator, and fail testing if the iterator stops""" + if self._error: + return + try: + generator.send((key, value, time)) + except StopIteration: + self._error = True + + for resp in ("start", "read", "ack"): + self.register_callback(resp, run_gen) + + def teardown(self): + """No work to do here""" + pass + + def rtc_reset_test(self): + """Generator for running the reset test + + This function calls yield to wait for the next event from + the device. If the device gives the wrong response, then the + generator terminates by returing which raises a StopIteration + exception and fails the test. + """ + + # Wait for start token + key, value, time = yield + if key != "start": + return + + # Initialize, and set the time + self.send_kv("init", self.VALUE_PLACEHOLDER) + + # Wait for ack from the device + key, value, time = yield + if key != "ack": + return + + self.send_kv("write", str(self.START_TIME)) + + # Wait for ack from the device + key, value, time = yield + if key != "ack": + return + + self.send_kv("read", self.VALUE_PLACEHOLDER) + key, value, time = yield + if key != "read": + return + dev_time_start = int(value) + + # Unitialize, and reset + self.send_kv("free", self.VALUE_PLACEHOLDER) + + # Wait for ack from the device + key, value, time = yield + if key != "ack": + return + + self.send_kv("reset", self.VALUE_PLACEHOLDER) + + # No ack after reset + sleep(self.DELAY_TIME) + + # Restart the test, and send the sync token + self.send_kv("__sync", "00000000-0000-000000000-000000000000") + key, value, time = yield + if key != "start": + return + + # Initialize, and read the time + self.send_kv("init", self.VALUE_PLACEHOLDER) + + # Wait for ack from the device + key, value, time = yield + if key != "ack": + return + + self.send_kv("read", self.VALUE_PLACEHOLDER) + key, value, time = yield + if key != "read": + return + dev_time_end = int(value) + + # Check result + elapsed = dev_time_end - dev_time_start + start_time_valid = (self.START_TIME <= dev_time_start < + self.START_TIME + self.START_TIME_TOLERANCE) + elapsed_time_valid = elapsed >= self.DELAY_TIME - self.DELAY_TOLERANCE + passed = start_time_valid and elapsed_time_valid + if not start_time_valid: + self.log("FAIL: Expected start time of %i got %i" % + (self.START_TIME, dev_time_start)) + elif not passed: + self.log("FAIL: Delayed for %fs but device " + "reported elapsed time of %fs" % + (self.DELAY_TIME, elapsed)) + self.send_kv("exit", "pass" if passed else "fail") + yield # No more events expected + diff --git a/TESTS/mbed_drivers/lp_ticker/main.cpp b/TESTS/mbed_drivers/lp_ticker/main.cpp index aeb36765f1..ada1f7ead8 100644 --- a/TESTS/mbed_drivers/lp_ticker/main.cpp +++ b/TESTS/mbed_drivers/lp_ticker/main.cpp @@ -19,7 +19,7 @@ #include "unity/unity.h" -#if !DEVICE_LOWPOWERTIMER +#if !DEVICE_LPTICKER #error [NOT_SUPPORTED] Low power ticker not supported for this target #endif @@ -33,8 +33,9 @@ static const int test_timeout = 10; /* Due to poor accuracy of LowPowerTicker on many platforms there is no sense to tune tolerance value as it was in Ticker tests. - Tolerance value is set to 2000us to cover this diversity */ -#define TOLERANCE_US 2000 + Tolerance value is set to 600us for measurement inaccuracy + 5% tolerance + for LowPowerTicker. */ +#define TOLERANCE_US(DELAY) (600 + DELAY / 20) volatile uint32_t ticker_callback_flag; @@ -117,7 +118,7 @@ void test_multi_call_time(void) while(!ticker_callback_flag); time_diff = gtimer.read_us(); - TEST_ASSERT_UINT32_WITHIN(TOLERANCE_US, MULTI_TICKER_TIME_MS * 1000, time_diff); + TEST_ASSERT_UINT32_WITHIN(TOLERANCE_US(MULTI_TICKER_TIME_MS * 1000), MULTI_TICKER_TIME_MS * 1000, time_diff); } } @@ -167,7 +168,7 @@ void test_attach_time(void) ticker.detach(); const int time_diff = gtimer.read_us(); - TEST_ASSERT_UINT64_WITHIN(TOLERANCE_US, DELAY_US, time_diff); + TEST_ASSERT_UINT64_WITHIN(TOLERANCE_US(DELAY_US), DELAY_US, time_diff); } /** Test single callback time via attach_us @@ -189,7 +190,7 @@ void test_attach_us_time(void) ticker.detach(); const int time_diff = gtimer.read_us(); - TEST_ASSERT_UINT64_WITHIN(TOLERANCE_US, DELAY_US, time_diff); + TEST_ASSERT_UINT64_WITHIN(TOLERANCE_US(DELAY_US), DELAY_US, time_diff); } // Test cases diff --git a/TESTS/mbed_drivers/lp_timeout/main.cpp b/TESTS/mbed_drivers/lp_timeout/main.cpp index eaccab90c9..b3cbe7de0a 100644 --- a/TESTS/mbed_drivers/lp_timeout/main.cpp +++ b/TESTS/mbed_drivers/lp_timeout/main.cpp @@ -14,8 +14,8 @@ * limitations under the License. */ -#if !DEVICE_LOWPOWERTIMER -#error [NOT_SUPPORTED] Low power timer not supported for this target +#if !DEVICE_LPTICKER + #error [NOT_SUPPORTED] Low power timer not supported for this target #endif #include "mbed.h" diff --git a/TESTS/mbed_drivers/lp_timer/main.cpp b/TESTS/mbed_drivers/lp_timer/main.cpp index a7232149a3..cadf3f41c7 100644 --- a/TESTS/mbed_drivers/lp_timer/main.cpp +++ b/TESTS/mbed_drivers/lp_timer/main.cpp @@ -22,7 +22,7 @@ #include "rtos.h" #include "hal/us_ticker_api.h" -#if !DEVICE_LOWPOWERTIMER +#if !DEVICE_LPTICKER #error [NOT_SUPPORTED] test not supported #endif @@ -35,39 +35,25 @@ extern uint32_t SystemCoreClock; * timer we need to adjust delta. */ -/* Macro to define delta based on CPU clock frequency. + /* + * Define tolerance as follows: + * tolerance = 500 us + 5% of measured time * - * Note that some extra time is counted by the timer. - * Additional time is caused by the function calls and - * additional operations performed by wait and - * stop functions before in fact timer is stopped. This may - * add additional time to the counted result. + * e.g. + * 1 ms delay: tolerance = 550 us + * 10 ms delay: tolerance = 1000 us + * 100 ms delay: tolerance = 5500 us + * 1000 ms delay: tolerance = 50500 us * - * To take in to account this extra time we introduce DELTA - * value based on CPU clock (speed): - * DELTA = TOLERANCE_FACTOR / SystemCoreClock * US_FACTOR - * - * e.g. - * For K64F DELTA = (80000 / 120000000) * 1000000 = 666[us] - * For NUCLEO_F070RB DELTA = (80000 / 48000000) * 1000000 = 1666[us] - * For NRF51_DK DELTA = (80000 / 16000000) * 1000000 = 5000[us] - * - * As low power timer cannot be too much accurate, this DELTA should not be more precise than 500us, - * which corresponds to a maximum CPU clock around 130MHz - */ + * */ + #define US_PER_SEC 1000000 #define US_PER_MSEC 1000 -#define TOLERANCE_FACTOR 80000.0f -#define US_FACTOR 1000000.0f -#define CLOCK_MAX 130000000 +#define MSEC_PER_SEC 1000 -static const int delta_sys_clk_us = (SystemCoreClock < CLOCK_MAX? ((int) (TOLERANCE_FACTOR / (float) SystemCoreClock * US_FACTOR)):((int) (TOLERANCE_FACTOR / (float) CLOCK_MAX * US_FACTOR))); - -/* When test performs time measurement using Timer in sequence, then measurement error accumulates - * in the successive attempts. */ - #define DELTA_US(i) (delta_sys_clk_us * i) - #define DELTA_S(i) ((float)delta_sys_clk_us * i / US_PER_SEC) - #define DELTA_MS(i) (1 + ( (i * delta_sys_clk_us) / US_PER_MSEC)) +#define DELTA_US(delay_ms) (500 + (delay_ms) * US_PER_MSEC / 20) +#define DELTA_MS(delay_ms) (1 + ((delay_ms) * US_PER_MSEC / 20 / US_PER_MSEC)) +#define DELTA_S(delay_ms) (0.000500f + (((float)(delay_ms)) / MSEC_PER_SEC / 20)) /* This test verifies if low power timer is stopped after * creation. @@ -122,10 +108,10 @@ void test_lptimer_time_accumulation() lp_timer.stop(); /* Check results - totally 10 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.010f, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), 10, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(1), 10000, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), 10000, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(10), 0.010f, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(10), 10, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(10), 10000, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(10), 10000, lp_timer.read_high_resolution_us()); /* Wait 50 ms - this is done to show that time elapsed when * the timer is stopped does not have influence on the @@ -144,10 +130,10 @@ void test_lptimer_time_accumulation() lp_timer.stop(); /* Check results - totally 30 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(2), 0.030f, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(2), 30, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(2), 30000, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(2), 30000, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(30), 0.030f, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(30), 30, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(30), 30000, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(30), 30000, lp_timer.read_high_resolution_us()); /* Wait 50 ms - this is done to show that time elapsed when * the timer is stopped does not have influence on the @@ -165,10 +151,10 @@ void test_lptimer_time_accumulation() lp_timer.stop(); /* Check results - totally 60 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(3), 0.060f, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(3), 60, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(3), 60000, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(3), 60000, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(60), 0.060f, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(60), 60, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(60), 60000, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(60), 60000, lp_timer.read_high_resolution_us()); /* Wait 50 ms - this is done to show that time elapsed when * the timer is stopped does not have influence on the @@ -187,10 +173,10 @@ void test_lptimer_time_accumulation() lp_timer.stop(); /* Check results - totally 1060 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(4), 1.060f, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(4), 1060, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(4), 1060000, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(4), 1060000, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1060), 1.060f, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(1060), 1060, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(1060), 1060000, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(1060), 1060000, lp_timer.read_high_resolution_us()); } /* This test verifies if reset() function resets the @@ -216,10 +202,10 @@ void test_lptimer_reset() lp_timer.stop(); /* Check results - totally 10 ms elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.010f, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), 10, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(1), 10000, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), 10000, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(10), 0.010f, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(10), 10, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(10), 10000, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(10), 10000, lp_timer.read_high_resolution_us()); /* Reset the timer - previous measured time should be lost now. */ lp_timer.reset(); @@ -234,10 +220,10 @@ void test_lptimer_reset() lp_timer.stop(); /* Check results - 20 ms elapsed since the reset. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.020f, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), 20, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(1), 20000, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), 20000, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(20), 0.020f, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(20), 20, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(20), 20000, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(20), 20000, lp_timer.read_high_resolution_us()); } /* This test verifies if calling start() for already @@ -267,10 +253,10 @@ void test_lptimer_start_started_timer() lp_timer.stop(); /* Check results - 30 ms have elapsed since the first start. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(2), 0.030f, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(2), 30, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(2), 30000, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(2), 30000, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(30), 0.030f, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(30), 30, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(30), 30000, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(30), 30000, lp_timer.read_high_resolution_us()); } /* This test verifies low power timer float operator. @@ -294,7 +280,7 @@ void test_lptimer_float_operator() lp_timer.stop(); /* Check result - 10 ms elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.010f, (float )(lp_timer)); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(10), 0.010f, (float )(lp_timer)); } /* This test verifies if time counted by the low power timer is @@ -310,6 +296,8 @@ void test_lptimer_time_measurement() { LowPowerTimer lp_timer; + const int delta_ms = (wait_val_us / US_PER_MSEC); + /* Start the timer. */ lp_timer.start(); @@ -320,10 +308,10 @@ void test_lptimer_time_measurement() lp_timer.stop(); /* Check results - wait_val_us us have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), (float )wait_val_us / 1000000, lp_timer.read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), wait_val_us / 1000, lp_timer.read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(1), wait_val_us, lp_timer.read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), wait_val_us, lp_timer.read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(delta_ms), (float )wait_val_us / 1000000, lp_timer.read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(delta_ms), wait_val_us / 1000, lp_timer.read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(delta_ms), wait_val_us, lp_timer.read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(delta_ms), wait_val_us, lp_timer.read_high_resolution_us()); } utest::v1::status_t test_setup(const size_t number_of_cases) diff --git a/TESTS/mbed_drivers/race_test/main.cpp b/TESTS/mbed_drivers/race_test/main.cpp index 48ce06a6f7..d1fb39f1d5 100644 --- a/TESTS/mbed_drivers/race_test/main.cpp +++ b/TESTS/mbed_drivers/race_test/main.cpp @@ -26,6 +26,10 @@ #error [NOT_SUPPORTED] test not supported for single threaded enviroment #endif +#if !DEVICE_USTICKER +#error [NOT_SUPPORTED] test not supported +#endif + using namespace utest::v1; #define TEST_STACK_SIZE 512 diff --git a/TESTS/mbed_drivers/rtc/main.cpp b/TESTS/mbed_drivers/rtc/main.cpp index 315818b7f2..d0ebba2c72 100644 --- a/TESTS/mbed_drivers/rtc/main.cpp +++ b/TESTS/mbed_drivers/rtc/main.cpp @@ -21,7 +21,7 @@ #include "rtos.h" #include "rtc_api.h" -#if !DEVICE_RTC +#if !DEVICE_RTC || !DEVICE_USTICKER #error [NOT_SUPPORTED] test not supported #endif diff --git a/TESTS/mbed_drivers/ticker/main.cpp b/TESTS/mbed_drivers/ticker/main.cpp index bab9c2bf54..6be70a7178 100644 --- a/TESTS/mbed_drivers/ticker/main.cpp +++ b/TESTS/mbed_drivers/ticker/main.cpp @@ -18,6 +18,9 @@ #include "utest/utest.h" #include "unity/unity.h" +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif using utest::v1::Case; diff --git a/TESTS/mbed_drivers/timeout/main.cpp b/TESTS/mbed_drivers/timeout/main.cpp index acab4fda5c..8670a7300d 100644 --- a/TESTS/mbed_drivers/timeout/main.cpp +++ b/TESTS/mbed_drivers/timeout/main.cpp @@ -19,6 +19,10 @@ #include "unity/unity.h" #include "timeout_tests.h" +#if !DEVICE_USTICKER +#error [NOT_SUPPORTED] usticker not supported for this target. +#endif + using namespace utest::v1; utest::v1::status_t greentea_failure_handler(const Case * const source, const failure_t reason) diff --git a/TESTS/mbed_drivers/timeout/timeout_tests.h b/TESTS/mbed_drivers/timeout/timeout_tests.h index 2920e8c243..8c2ccb45b3 100644 --- a/TESTS/mbed_drivers/timeout/timeout_tests.h +++ b/TESTS/mbed_drivers/timeout/timeout_tests.h @@ -276,7 +276,7 @@ void test_sleep(void) timeout.detach(); } -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER /** Template for tests: timeout during deepsleep * * Test timeout during deepsleep diff --git a/TESTS/mbed_drivers/timer/main.cpp b/TESTS/mbed_drivers/timer/main.cpp index dfc16fdf3f..76f2842256 100644 --- a/TESTS/mbed_drivers/timer/main.cpp +++ b/TESTS/mbed_drivers/timer/main.cpp @@ -22,39 +22,32 @@ #include "rtos.h" #include "hal/us_ticker_api.h" +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif + using namespace utest::v1; extern uint32_t SystemCoreClock; -/* Macro to define delta based on CPU clock frequency. - * - * Note that some extra time is counted by the timer. - * Additional time is caused by the function calls and - * additional operations performed by wait and - * stop functions before in fact timer is stopped. This may - * add additional time to the counted result. - * - * To take in to account this extra time we introduce DELTA - * value based on CPU clock (speed): - * DELTA = TOLERANCE_FACTOR / SystemCoreClock * US_FACTOR - * - * e.g. - * For K64F DELTA = (30000 / 120000000) * 1000000 = 250[us] - * For NUCLEO_F070RB DELTA = (30000 / 48000000) * 1000000 = 625[us] - * For NRF51_DK DELTA = (30000 / 16000000) * 1000000 = 1875[us] - */ #define US_PER_SEC 1000000 #define US_PER_MSEC 1000 -#define TOLERANCE_FACTOR 30000.0f -#define US_FACTOR 1000000.0f +#define MSEC_PER_SEC 1000 -static const int delta_sys_clk_us = ((int) (TOLERANCE_FACTOR / (float)SystemCoreClock * US_FACTOR)); - -/* When test performs time measurement using Timer in sequence, then measurement error accumulates - * in the successive attempts. */ - #define DELTA_US(i) (delta_sys_clk_us * i) - #define DELTA_S(i) ((float)delta_sys_clk_us * i / US_PER_SEC) - #define DELTA_MS(i) (1 + ( (i * delta_sys_clk_us) / US_PER_MSEC)) + /* + * Define tolerance as follows: + * tolerance = 500 us + 2% of measured time + * + * e.g. + * 1 ms delay: tolerance = 520 us + * 10 ms delay: tolerance = 700 us + * 100 ms delay: tolerance = 2500 us + * 1000 ms delay: tolerance = 20500 us + * + * */ +#define DELTA_US(delay_ms) (500 + (delay_ms) * US_PER_MSEC / 50) +#define DELTA_MS(delay_ms) (1 + ((delay_ms) * US_PER_MSEC / 50 / US_PER_MSEC)) +#define DELTA_S(delay_ms) (0.000500f + (((float)(delay_ms)) / MSEC_PER_SEC / 50)) #define TICKER_FREQ_1MHZ 1000000 #define TICKER_BITS 32 @@ -413,10 +406,10 @@ void test_timer_time_accumulation_os_ticker() p_timer->stop(); /* Check results - totally 10 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.010f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), 10, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(1), 10000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), 10000, p_timer->read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(10), 0.010f, p_timer->read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(10), 10, p_timer->read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(10), 10000, p_timer->read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(10), 10000, p_timer->read_high_resolution_us()); /* Wait 50 ms - this is done to show that time elapsed when * the timer is stopped does not have influence on the @@ -435,10 +428,10 @@ void test_timer_time_accumulation_os_ticker() p_timer->stop(); /* Check results - totally 30 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(2), 0.030f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(2), 30, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(2), 30000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(2), 30000, p_timer->read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(30), 0.030f, p_timer->read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(30), 30, p_timer->read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(30), 30000, p_timer->read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(30), 30000, p_timer->read_high_resolution_us()); /* Wait 50 ms - this is done to show that time elapsed when * the timer is stopped does not have influence on the @@ -456,10 +449,10 @@ void test_timer_time_accumulation_os_ticker() p_timer->stop(); /* Check results - totally 60 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(3), 0.060f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(3), 60, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(3), 60000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(3), 60000, p_timer->read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(60), 0.060f, p_timer->read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(60), 60, p_timer->read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(60), 60000, p_timer->read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(60), 60000, p_timer->read_high_resolution_us()); /* Wait 50 ms - this is done to show that time elapsed when * the timer is stopped does not have influence on the @@ -478,10 +471,10 @@ void test_timer_time_accumulation_os_ticker() p_timer->stop(); /* Check results - totally 1060 ms have elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(4), 1.060f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(4), 1060, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(4), 1060000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(4), 1060000, p_timer->read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1060), 1.060f, p_timer->read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(1060), 1060, p_timer->read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(1060), 1060000, p_timer->read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(1060), 1060000, p_timer->read_high_resolution_us()); } /* This test verifies if reset() function resets the timer @@ -507,10 +500,10 @@ void test_timer_reset_os_ticker() p_timer->stop(); /* Check results - totally 10 ms elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.010f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), 10, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(1), 10000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), 10000, p_timer->read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(10), 0.010f, p_timer->read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(10), 10, p_timer->read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(10), 10000, p_timer->read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(10), 10000, p_timer->read_high_resolution_us()); /* Reset the timer - previous measured time should be lost now. */ p_timer->reset(); @@ -525,10 +518,10 @@ void test_timer_reset_os_ticker() p_timer->stop(); /* Check results - 20 ms elapsed since the reset. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.020f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), 20, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(1), 20000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), 20000, p_timer->read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(20), 0.020f, p_timer->read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(20), 20, p_timer->read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(20), 20000, p_timer->read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(20), 20000, p_timer->read_high_resolution_us()); } /* This test verifies if reset() function resets the timer @@ -609,10 +602,10 @@ void test_timer_start_started_timer_os_ticker() p_timer->stop(); /* Check results - 30 ms have elapsed since the first start. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(2), 0.030f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(2), 30, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(2), 30000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(2), 30000, p_timer->read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(30), 0.030f, p_timer->read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(30), 30, p_timer->read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(30), 30000, p_timer->read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(30), 30000, p_timer->read_high_resolution_us()); } /* This test verifies if calling start() for already @@ -646,10 +639,10 @@ void test_timer_start_started_timer_user_ticker() p_timer->stop(); /* Check results - 30 ms have elapsed since the first start. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(2), 0.030f, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(2), 30, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(2), 30000, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(2), 30000, p_timer->read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(30), 0.030f, p_timer->read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(30), 30, p_timer->read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(30), 30000, p_timer->read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(30), 30000, p_timer->read_high_resolution_us()); } /* This test verifies Timer float operator. @@ -673,7 +666,7 @@ void test_timer_float_operator_os_ticker() p_timer->stop(); /* Check result - 10 ms elapsed. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.010f, (float)(*p_timer)); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(10), 0.010f, (float)(*p_timer)); } /* This test verifies Timer float operator. @@ -728,10 +721,10 @@ void test_timer_time_measurement() p_timer->stop(); /* Check results. */ - TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), (float)wait_val_us / 1000000, p_timer->read()); - TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), wait_val_us / 1000, p_timer->read_ms()); - TEST_ASSERT_INT32_WITHIN(DELTA_US(1), wait_val_us, p_timer->read_us()); - TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), wait_val_us, p_timer->read_high_resolution_us()); + TEST_ASSERT_FLOAT_WITHIN(DELTA_S(wait_val_us / US_PER_MSEC), (float)wait_val_us / US_PER_SEC, p_timer->read()); + TEST_ASSERT_INT32_WITHIN(DELTA_MS(wait_val_us / US_PER_MSEC), wait_val_us / US_PER_MSEC, p_timer->read_ms()); + TEST_ASSERT_INT32_WITHIN(DELTA_US(wait_val_us / US_PER_MSEC), wait_val_us, p_timer->read_us()); + TEST_ASSERT_UINT64_WITHIN(DELTA_US(wait_val_us / US_PER_MSEC), wait_val_us, p_timer->read_high_resolution_us()); } utest::v1::status_t test_setup(const size_t number_of_cases) { diff --git a/TESTS/mbed_drivers/timerevent/main.cpp b/TESTS/mbed_drivers/timerevent/main.cpp index 5dee578645..817a8606a6 100644 --- a/TESTS/mbed_drivers/timerevent/main.cpp +++ b/TESTS/mbed_drivers/timerevent/main.cpp @@ -13,6 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#if !DEVICE_USTICKER +#error [NOT_SUPPORTED] usticker not supported for this target. +#endif + #include "mbed.h" #include "greentea-client/test_env.h" #include "unity.h" @@ -23,7 +27,12 @@ using namespace utest::v1; +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif + #define TEST_DELAY_US 50000ULL +#define DELTA 2 class TestTimerEvent: public TimerEvent { private: @@ -35,6 +44,8 @@ private: public: TestTimerEvent() : TimerEvent(), sem(0, 1) { + + sleep_manager_lock_deep_sleep(); } TestTimerEvent(const ticker_data_t *data) : @@ -42,6 +53,7 @@ public: } virtual ~TestTimerEvent() { + sleep_manager_unlock_deep_sleep(); } // Make these methods publicly accessible @@ -118,7 +130,7 @@ void test_insert(void) { int32_t sem_slots = tte.sem_wait(0); TEST_ASSERT_EQUAL(0, sem_slots); - sem_slots = tte.sem_wait(TEST_DELAY_US / 1000 + 1); + sem_slots = tte.sem_wait(TEST_DELAY_US / 1000 + DELTA); TEST_ASSERT_EQUAL(1, sem_slots); tte.remove(); @@ -147,7 +159,7 @@ void test_remove(void) { TEST_ASSERT_EQUAL(0, sem_slots); tte.remove(); - sem_slots = tte.sem_wait(TEST_DELAY_US * 2 / 1000 + 1); + sem_slots = tte.sem_wait(TEST_DELAY_US * 2 / 1000 + DELTA); TEST_ASSERT_EQUAL(0, sem_slots); } diff --git a/TESTS/mbed_hal/common_tickers/main.cpp b/TESTS/mbed_hal/common_tickers/main.cpp new file mode 100644 index 0000000000..007f74de04 --- /dev/null +++ b/TESTS/mbed_hal/common_tickers/main.cpp @@ -0,0 +1,537 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "ticker_api_tests.h" +#include "hal/us_ticker_api.h" +#include "hal/lp_ticker_api.h" + +#if !DEVICE_USTICKER +#error [NOT_SUPPORTED] test not supported +#endif + +#define FORCE_OVERFLOW_TEST (false) +#define TICKER_INT_VAL 500 +#define TICKER_DELTA 10 + +#define LP_TICKER_OVERFLOW_DELTA 0 // this will allow to detect that ticker counter rollovers to 0 +#define US_TICKER_OVERFLOW_DELTA 50 + +#define TICKER_100_TICKS 100 + +#define MAX_FUNC_EXEC_TIME_US 20 +#define DELTA_FUNC_EXEC_TIME_US 5 +#define NUM_OF_CALLS 1000 + +#define NUM_OF_CYCLES 100000 + +#define US_TICKER_OV_LIMIT 35000 +#define LP_TICKER_OV_LIMIT 4000 + +using namespace utest::v1; + +volatile int intFlag = 0; +const ticker_interface_t* intf; +ticker_irq_handler_type prev_irq_handler; +unsigned int ticker_overflow_delta; + +/* Auxiliary function to count ticker ticks elapsed during execution of N cycles of empty while loop. + * Parameter is used to disable compiler optimisation. */ +uint32_t count_ticks(uint32_t cycles, uint32_t step) +{ + register uint32_t reg_cycles = cycles; + + const ticker_info_t* p_ticker_info = intf->get_info(); + const uint32_t max_count = ((1 << p_ticker_info->bits) - 1); + + core_util_critical_section_enter(); + + const uint32_t start = intf->read(); + + while (reg_cycles -= step) { + /* Just wait. */ + } + + const uint32_t stop = intf->read(); + + core_util_critical_section_exit(); + + /* Handle overflow - overflow protection may not work in this case. */ + uint32_t diff = (start <= stop) ? (stop - start) : (uint32_t)(max_count - start + stop + 1); + + return (diff); +} + +/* Since according to the ticker requirements min acceptable counter size is + * - 12 bits for low power timer - max count = 4095, + * - 16 bits for high frequency timer - max count = 65535 + * then all test cases must be executed in this time windows. + * HAL ticker layer handles counter overflow and it is not handled in the target + * ticker drivers. Ensure we have enough time to execute test case without overflow. + */ +void overflow_protect() +{ + uint32_t time_window; + + if (intf == get_us_ticker_data()->interface) { + time_window = US_TICKER_OV_LIMIT; + } else { + time_window = LP_TICKER_OV_LIMIT; + } + + const uint32_t ticks_now = intf->read(); + const ticker_info_t* p_ticker_info = intf->get_info(); + + const uint32_t max_count = ((1 << p_ticker_info->bits) - 1); + + if ((max_count - ticks_now) > time_window) { + return; + } + + while (intf->read() > ticks_now); +} + +void ticker_event_handler_stub(const ticker_data_t * const ticker) +{ + if (ticker == get_us_ticker_data()) { + us_ticker_clear_interrupt(); + } else { +#if DEVICE_LPTICKER + lp_ticker_clear_interrupt(); +#endif + } + + /* Indicate that ISR has been executed in interrupt context. */ + if (IsIrqMode()) { + intFlag++; + } +} + +void wait_cycles(volatile unsigned int cycles) +{ + while (cycles--); +} + +/* Test that ticker_init can be called multiple times and + * ticker_init allows the ticker to keep counting and disables the ticker interrupt. + */ +void ticker_init_test() +{ + overflow_protect(); + + intFlag = 0; + + intf->init(); + + /* Wait a while - let the ticker to count. */ + wait_cycles(10000); + + const uint32_t ticks_start = intf->read(); + + intf->set_interrupt(ticks_start + TICKER_INT_VAL); + + /* Re-initialise the ticker. */ + intf->init(); + + const uint32_t ticks_after_reinit = intf->read(); + + /* Wait long enough to fire ticker interrupt (should not be fired). */ + while (intf->read() < (ticks_start + 2 * TICKER_INT_VAL)) { + /* Just wait. */ + } + + TEST_ASSERT(intf->read() >= (ticks_start + 2 * TICKER_INT_VAL)); + TEST_ASSERT(ticks_start <= ticks_after_reinit); + TEST_ASSERT_EQUAL(0, intFlag); +} + +/* Test that ticker frequency is non-zero and counter is at least 8 bits */ +void ticker_info_test(void) +{ + const ticker_info_t* p_ticker_info = intf->get_info(); + + TEST_ASSERT(p_ticker_info->frequency != 0); + TEST_ASSERT(p_ticker_info->bits >= 8); +} + +/* Test that ticker interrupt fires only when the ticker counter increments to the value set by ticker_set_interrupt. */ +void ticker_interrupt_test(void) +{ + uint32_t ticker_timeout[] = { 100, 200, 300, 500 }; + + overflow_protect(); + + for (uint32_t i = 0; i < (sizeof(ticker_timeout) / sizeof(uint32_t)); i++) { + intFlag = 0; + const uint32_t tick_count = intf->read(); + + /* Set interrupt. Interrupt should be fired when tick count is equal to: + * tick_count + ticker_timeout[i]. */ + intf->set_interrupt(tick_count + ticker_timeout[i]); + + /* Wait until ticker count reach value: tick_count + ticker_timeout[i] - TICKER_DELTA. + * Interrupt should not be fired. */ + while (intf->read() < (tick_count + ticker_timeout[i] - TICKER_DELTA)) { + /* Indicate failure if interrupt has fired earlier. */ + TEST_ASSERT_EQUAL_INT_MESSAGE(0, intFlag, "Interrupt fired too early"); + } + + /* Wait until ticker count reach value: tick_count + ticker_timeout[i] + TICKER_DELTA. + * Interrupt should be fired after this time. */ + while (intf->read() < (tick_count + ticker_timeout[i] + TICKER_DELTA)) { + /* Just wait. */ + } + + TEST_ASSERT_EQUAL(1, intFlag); + + /* Wait until ticker count reach value: tick_count + 2 * ticker_timeout[i] + TICKER_DELTA. + * Interrupt should not be triggered again. */ + while (intf->read() < (tick_count + 2 * ticker_timeout[i] + TICKER_DELTA)) { + /* Just wait. */ + } + + TEST_ASSERT_EQUAL(1, intFlag); + } +} + +/* Test that ticker interrupt is not triggered when ticker_set_interrupt */ +void ticker_past_test(void) +{ + intFlag = 0; + + const uint32_t tick_count = intf->read(); + + /* Set interrupt tick count to value in the past. + * Interrupt should not be fired. */ + intf->set_interrupt(tick_count - TICKER_DELTA); + + wait_cycles(1000); + + TEST_ASSERT_EQUAL(0, intFlag); +} + +/* Test that ticker can be rescheduled repeatedly before the handler has been called. */ +void ticker_repeat_reschedule_test(void) +{ + overflow_protect(); + + intFlag = 0; + + const uint32_t tick_count = intf->read(); + + /* Set interrupt. Interrupt should be fired when tick count is equal to: + * tick_count + TICKER_INT_VAL. */ + intf->set_interrupt(tick_count + TICKER_INT_VAL); + + /* Reschedule interrupt - it should not be fired yet. + * Re-schedule interrupt. */ + intf->set_interrupt(tick_count + (2 * TICKER_INT_VAL)); + intf->set_interrupt(tick_count + (3 * TICKER_INT_VAL)); + + /* Wait until ticker count reach value: tick_count + 3*TICKER_INT_VAL - TICKER_DELTA. + * Interrupt should not be fired. */ + while (intf->read() < (tick_count + 3 * TICKER_INT_VAL - TICKER_DELTA)) { + /* Indicate failure if interrupt has fired earlier. */ + TEST_ASSERT_EQUAL_INT_MESSAGE(0, intFlag, "Interrupt fired too early"); + } + + /* Wait until ticker count reach value: tick_count + 3*TICKER_INT_VAL + TICKER_DELTA. + * Interrupt should be fired after this time. */ + while (intf->read() < (tick_count + 3 * TICKER_INT_VAL + TICKER_DELTA)) { + /* Just wait. */ + } + + TEST_ASSERT_EQUAL(1, intFlag); +} + +/* Test that ticker_fire_interrupt causes and interrupt to get fired immediately. */ +void ticker_fire_now_test(void) +{ + intFlag = 0; + + intf->fire_interrupt(); + + /* On some platforms set_interrupt function sets interrupt in the nearest feature. */ + wait_cycles(1000); + + TEST_ASSERT_EQUAL(1, intFlag); +} + +/* Test that the ticker correctly handles overflow. */ +void ticker_overflow_test(void) +{ + const ticker_info_t* p_ticker_info = intf->get_info(); + + /* We need to check how long it will take to overflow. + * We will perform this test only if this time is no longer than 30 sec. + */ + const uint32_t max_count = (1 << p_ticker_info->bits) - 1; + const uint32_t required_time_sec = (max_count / p_ticker_info->frequency); + + if (required_time_sec > 30 && !FORCE_OVERFLOW_TEST) { + TEST_ASSERT_TRUE(true); + printf("Test has been skipped.\n"); + return; + } + + intFlag = 0; + + /* Wait for max count. */ + while (intf->read() != (max_count - ticker_overflow_delta)) { + /* Just wait. */ + } + + /* Now we are near/at the overflow point. Detect rollover. */ + while (intf->read() > ticker_overflow_delta); + + const uint32_t after_overflow = intf->read(); + + /* Now we are just after overflow. Wait a while assuming that ticker still counts. */ + while (intf->read() < TICKER_100_TICKS) { + /* Just wait. */ + } + + const uint32_t next_after_overflow = intf->read(); + + /* Check that after the overflow ticker continue count. */ + TEST_ASSERT(after_overflow <= ticker_overflow_delta); + TEST_ASSERT(next_after_overflow >= TICKER_100_TICKS); + TEST_ASSERT_EQUAL(0, intFlag); + + const uint32_t tick_count = intf->read(); + + /* Check if interrupt scheduling still works. */ + intf->set_interrupt(tick_count + TICKER_INT_VAL); + + /* Wait for the interrupt. */ + while (intf->read() < (tick_count + TICKER_INT_VAL + TICKER_DELTA)) { + /* Just wait. */ + } + + TEST_ASSERT_EQUAL(1, intFlag); +} + +/* Test that the ticker increments by one on each tick. */ +void ticker_increment_test(void) +{ + const ticker_info_t* p_ticker_info = intf->get_info(); + + /* Perform test based on ticker speed. */ + if (p_ticker_info->frequency <= 250000) { // low frequency tickers + const uint32_t base_tick_count = intf->read(); + uint32_t next_tick_count = base_tick_count; + + while (next_tick_count == base_tick_count) { + next_tick_count = intf->read(); + } + + TEST_ASSERT_UINT32_WITHIN(1, next_tick_count, base_tick_count); + } else { // high frequency tickers + + uint32_t num_of_cycles = NUM_OF_CYCLES; + + uint32_t base_tick_count = count_ticks(num_of_cycles, 1); + uint32_t next_tick_count = base_tick_count; + uint32_t inc_val = 0; + + while (inc_val < 100) { + + next_tick_count = count_ticks(num_of_cycles + inc_val, 1); + + if (next_tick_count == base_tick_count) { + + /* Same tick count, so increase num of cycles. */ + inc_val++; + } else { + + /* It is possible that the difference between base and next + * tick count on some platforms is greater that 1, in this case we need + * to repeat counting with the reduced number of cycles (for slower boards). + * In cases if difference is exactly 1 we can exit the loop. + */ + num_of_cycles /= 2; + inc_val = 0; + base_tick_count = count_ticks(num_of_cycles, 1); + + if (next_tick_count - base_tick_count == 1 || + base_tick_count - next_tick_count == 1) { + break; + } + } + } + + /* Since we are here we know that next_tick_count != base_tick_count. + * The accuracy of our measurement method is +/- 1 tick, so it is possible that + * next_tick_count == base_tick_count - 1. This is also valid result. + */ + TEST_ASSERT_UINT32_WITHIN(1, next_tick_count, base_tick_count); + } +} + +/* Test that common ticker functions complete with the required amount of time. */ +void ticker_speed_test(void) +{ + Timer timer; + int counter = NUM_OF_CALLS; + + /* ---- Test ticker_read function. ---- */ + timer.reset(); + timer.start(); + while (counter--) { + intf->read(); + } + timer.stop(); + + TEST_ASSERT(timer.read_us() < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US))); + + /* ---- Test ticker_clear_interrupt function. ---- */ + counter = NUM_OF_CALLS; + timer.reset(); + timer.start(); + while (counter--) { + intf->clear_interrupt(); + } + timer.stop(); + + TEST_ASSERT(timer.read_us() < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US))); + + /* ---- Test ticker_set_interrupt function. ---- */ + counter = NUM_OF_CALLS; + timer.reset(); + timer.start(); + while (counter--) { + intf->set_interrupt(0); + } + timer.stop(); + + TEST_ASSERT(timer.read_us() < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US))); + + /* ---- Test fire_interrupt function. ---- */ + counter = NUM_OF_CALLS; + timer.reset(); + timer.start(); + while (counter--) { + intf->fire_interrupt(); + } + timer.stop(); + + TEST_ASSERT(timer.read_us() < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US))); + + /* ---- Test disable_interrupt function. ---- */ + counter = NUM_OF_CALLS; + timer.reset(); + timer.start(); + while (counter--) { + intf->disable_interrupt(); + } + timer.stop(); + + TEST_ASSERT(timer.read_us() < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US))); +} + +utest::v1::status_t us_ticker_setup(const Case *const source, const size_t index_of_case) +{ + intf = get_us_ticker_data()->interface; + + OS_Tick_Disable(); + + intf->init(); + + prev_irq_handler = set_us_ticker_irq_handler(ticker_event_handler_stub); + + ticker_overflow_delta = US_TICKER_OVERFLOW_DELTA; + + return greentea_case_setup_handler(source, index_of_case); +} + +utest::v1::status_t us_ticker_teardown(const Case * const source, const size_t passed, const size_t failed, + const failure_t reason) +{ + set_us_ticker_irq_handler(prev_irq_handler); + + prev_irq_handler = NULL; + + OS_Tick_Enable(); + + return greentea_case_teardown_handler(source, passed, failed, reason); +} + +#if DEVICE_LPTICKER +utest::v1::status_t lp_ticker_setup(const Case *const source, const size_t index_of_case) +{ + intf = get_lp_ticker_data()->interface; + + OS_Tick_Disable(); + + intf->init(); + + prev_irq_handler = set_lp_ticker_irq_handler(ticker_event_handler_stub); + + ticker_overflow_delta = LP_TICKER_OVERFLOW_DELTA; + + return greentea_case_setup_handler(source, index_of_case); +} + +utest::v1::status_t lp_ticker_teardown(const Case * const source, const size_t passed, const size_t failed, + const failure_t reason) +{ + set_lp_ticker_irq_handler(prev_irq_handler); + + prev_irq_handler = NULL; + + OS_Tick_Enable(); + + return greentea_case_teardown_handler(source, passed, failed, reason); +} +#endif + +utest::v1::status_t test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(30, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Microsecond ticker init is safe to call repeatedly", us_ticker_setup, ticker_init_test, us_ticker_teardown), + Case("Microsecond ticker info test", us_ticker_setup, ticker_info_test, us_ticker_teardown), + Case("Microsecond ticker interrupt test", us_ticker_setup, ticker_interrupt_test, us_ticker_teardown), + Case("Microsecond ticker past interrupt test", us_ticker_setup, ticker_past_test, us_ticker_teardown), + Case("Microsecond ticker reschedule test", us_ticker_setup, ticker_repeat_reschedule_test, us_ticker_teardown), + Case("Microsecond ticker fire interrupt", us_ticker_setup, ticker_fire_now_test, us_ticker_teardown), + Case("Microsecond ticker overflow test", us_ticker_setup, ticker_overflow_test, us_ticker_teardown), + Case("Microsecond ticker increment test", us_ticker_setup, ticker_increment_test, us_ticker_teardown), + Case("Microsecond ticker speed test", us_ticker_setup, ticker_speed_test, us_ticker_teardown), +#if DEVICE_LPTICKER + Case("lp ticker init is safe to call repeatedly", lp_ticker_setup, ticker_init_test, lp_ticker_teardown), + Case("lp ticker info test", lp_ticker_setup, ticker_info_test, lp_ticker_teardown), + Case("lp ticker interrupt test", lp_ticker_setup, ticker_interrupt_test, lp_ticker_teardown), + Case("lp ticker past interrupt test", lp_ticker_setup, ticker_past_test, lp_ticker_teardown), + Case("lp ticker reschedule test", lp_ticker_setup, ticker_repeat_reschedule_test, lp_ticker_teardown), + Case("lp ticker fire interrupt", lp_ticker_setup, ticker_fire_now_test, lp_ticker_teardown), + Case("lp ticker overflow test", lp_ticker_setup, ticker_overflow_test, lp_ticker_teardown), + Case("lp ticker increment test", lp_ticker_setup, ticker_increment_test, lp_ticker_teardown), + Case("lp ticker speed test", lp_ticker_setup, ticker_speed_test, lp_ticker_teardown), +#endif +}; + +Specification specification(test_setup, cases); + +int main() +{ + return !Harness::run(specification); +} diff --git a/TESTS/mbed_hal/common_tickers/ticker_api_tests.h b/TESTS/mbed_hal/common_tickers/ticker_api_tests.h new file mode 100644 index 0000000000..84b064de45 --- /dev/null +++ b/TESTS/mbed_hal/common_tickers/ticker_api_tests.h @@ -0,0 +1,129 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 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_ticker_tests */ +/** @{*/ + +#ifndef TICKER_API_TESTS_H +#define TICKER_API_TESTS_H + +#include "device.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/** Test that ticker_init can be called multiple times and + * ticker_init resets the internal count and disables the ticker interrupt. + * + * Given ticker is initialised and interrupt is set. + * When ticker is re-initialised. + * Then ticker keeps counting and disables the ticker interrupt. + */ +void ticker_init_test(void); + +/** Test that ticker frequency is non-zero and counter is at least 8 bits + * + * Given ticker is available. + * When ticker information data is obtained. + * Then ticker information indicate that frequency is non-zero and counter is at least 8 bits. + */ +void ticker_info_test(void); + +/** Test that the ticker increments by one on each tick. + * + * We have the following assumption for the timer clock frequency: + * + * NOTE: + * high freq ticker: 250 KHz (1 tick per 4 us) - 8 Mhz (1 tick per 1/8 us) + * low power ticker: 8 KHz (1 tick per 125 us) - 64 KHz (1 tick per ~15.6 us) + * + * Lowest CPU speed is 16 MHz (1 tick per 1/16 us). + * + * For the boards with ticker clock freq less than or equal to 250 KHz we will try to prove that ticker is incremented by one + * straightforward by reading ticker count value in the loop in order to detect a single ticker value update (hopefully by one). + * For faster tickers we need to prove this indirectly using additional count_ticks() function which returns number of + * ticks needed to perform N cycles of the empty while loop. For the same number of cycles function result should be the same with + * accuracy +/- 1 tick. After the first test we will call count_ticks again with number of cycles equal N, N+1, N+2, ... + * until we get other ticks result. + * + * Given ticker is available. + * When ticker is initialised. + * Then ticker counter is incremented by one. + */ +void ticker_increment_test(void); + +/** Test that ticker interrupt fires only when the ticker counter increments to the value set by ticker_set_interrupt. + * + * Given ticker is available, initialised. + * When ticker interrupt is set. + * Then ticker interrupt fires at the valid time. + */ +void ticker_interrupt_test(void); + +/** Test that ticker interrupt is not triggered when ticker_set_interrupt is called with a time from the past + * + * Given ticker is available, initialised. + * When ticker interrupt is set to the time in the past. + * Then ticker interrupt is not triggered. + */ +void ticker_past_test(void); + +/** Test that ticker can be rescheduled repeatedly before the handler has been called. + * + * Given ticker is available, initialised. + * When ticker interrupt is set and then rescheduled (interrupt time is modified). + * Then ticker interrupt is triggered according the rescheduled time. + */ +void ticker_repeat_reschedule_test(void); + +/** Test that ticker_fire_interrupt causes the interrupt to get fired immediately. + * + * Given ticker is available. + * When ticker_fire_interrupt is called. + * Then ticker interrupt is triggered. + */ +void ticker_fire_now_test(void); + +/** Test that common ticker functions complete with the required amount of time. + * + * Given ticker is available. + * When ticker_read, ticker_clear_interrupt, ticker_set_interrupt, ticker_fire_interrupt or ticker_disable_interrupt function is called. + * Then its execution is not longer than 20 us. + */ +void ticker_speed_test(void); + +/** Test that the ticker correctly handles overflow. + * + * Note that for high frequency timers we will only prove that ticker counter rollovers and + * continue counting (it is not possible to prove in deterministic way that after rollover next value is 0). + * + * Given ticker is available. + * When ticker has overflows. + * Then ticker continues counting from the beginning and interrupt scheduling works. + */ +void ticker_overflow_test(void); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif + +/**@}*/ diff --git a/TESTS/mbed_hal/common_tickers_freq/main.cpp b/TESTS/mbed_hal/common_tickers_freq/main.cpp new file mode 100644 index 0000000000..c9952f1161 --- /dev/null +++ b/TESTS/mbed_hal/common_tickers_freq/main.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2013-2016, ARM Limited, All Rights Reserved + * 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. + */ + +/* + * This is the mbed device part of the test to verify if mbed board ticker + * freqency is valid. + */ + + +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" +#include "ticker_api_test_freq.h" +#include "hal/us_ticker_api.h" +#include "hal/lp_ticker_api.h" + +#if !DEVICE_USTICKER +#error [NOT_SUPPORTED] test not supported +#endif + +#define US_PER_S 1000000 + +using namespace utest::v1; + +const ticker_interface_t* intf; + +static volatile unsigned int overflowCounter; + +uint32_t ticks_to_us(uint32_t ticks, uint32_t freq) +{ + return (uint32_t)((uint64_t)ticks * US_PER_S / freq); +} + +void ticker_event_handler_stub(const ticker_data_t * const ticker) +{ + if (ticker == get_us_ticker_data()) { + us_ticker_clear_interrupt(); + } else { +#if DEVICE_LPTICKER + lp_ticker_clear_interrupt(); +#endif + } + + overflowCounter++; +} + +/* Test that the ticker is operating at the frequency it specifies. */ +void ticker_frequency_test() +{ + char _key[11] = { }; + char _value[128] = { }; + int expected_key = 1; + const uint32_t ticker_freq = intf->get_info()->frequency; + const uint32_t ticker_bits = intf->get_info()->bits; + const uint32_t ticker_max = (1 << ticker_bits) - 1; + + intf->init(); + + /* Detect overflow for tickers with lower counters width. */ + intf->set_interrupt(0); + + greentea_send_kv("timing_drift_check_start", 0); + + /* Wait for 1st signal from host. */ + do { + greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); + expected_key = strcmp(_key, "base_time"); + } while (expected_key); + + overflowCounter = 0; + + const uint32_t begin_ticks = intf->read(); + + /* Assume that there was no overflow at this point - we are just after init. */ + greentea_send_kv(_key, ticks_to_us(begin_ticks, ticker_freq)); + + /* Wait for 2nd signal from host. */ + greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); + + const uint32_t end_ticks = intf->read(); + + greentea_send_kv(_key, ticks_to_us(end_ticks + overflowCounter * ticker_max, ticker_freq)); + + /* Get the results from host. */ + greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); + + TEST_ASSERT_EQUAL_STRING_MESSAGE("pass", _key,"Host side script reported a fail..."); + + intf->disable_interrupt(); +} + +utest::v1::status_t us_ticker_case_setup_handler_t(const Case * const source, const size_t index_of_case) +{ + intf = get_us_ticker_data()->interface; + set_us_ticker_irq_handler(ticker_event_handler_stub); + return greentea_case_setup_handler(source, index_of_case); +} + +#if DEVICE_LPTICKER +utest::v1::status_t lp_ticker_case_setup_handler_t(const Case * const source, const size_t index_of_case) +{ + intf = get_lp_ticker_data()->interface; + set_lp_ticker_irq_handler(ticker_event_handler_stub); + return greentea_case_setup_handler(source, index_of_case); +} +#endif + +utest::v1::status_t ticker_case_teardown_handler_t(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); +} + +// Test cases +Case cases[] = { + Case("Microsecond ticker frequency test", us_ticker_case_setup_handler_t, ticker_frequency_test, + ticker_case_teardown_handler_t), +#if DEVICE_LPTICKER + Case("Low power ticker frequency test", lp_ticker_case_setup_handler_t, ticker_frequency_test, + ticker_case_teardown_handler_t), +#endif + }; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(120, "timing_drift_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() +{ + Harness::run(specification); +} diff --git a/TESTS/mbed_hal/common_tickers_freq/ticker_api_test_freq.h b/TESTS/mbed_hal/common_tickers_freq/ticker_api_test_freq.h new file mode 100644 index 0000000000..06221a7926 --- /dev/null +++ b/TESTS/mbed_hal/common_tickers_freq/ticker_api_test_freq.h @@ -0,0 +1,47 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 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_ticker_tests */ +/** @{*/ + +#ifndef TICKER_API_TEST_FREQ_H +#define TICKER_API_TEST_FREQ_H + +#include "device.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/** Test that the ticker is operating at the frequency it specifies. + * + * Given ticker is available. + * When ticker specifies its frequency. + * Then the specified frequency is valid. + */ +void ticker_frequency_test(void); + + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif + +/**@}*/ diff --git a/TESTS/mbed_hal/flash/functional_tests/main.cpp b/TESTS/mbed_hal/flash/functional_tests/main.cpp index 8ca81ecb8b..b5bdc51aff 100644 --- a/TESTS/mbed_hal/flash/functional_tests/main.cpp +++ b/TESTS/mbed_hal/flash/functional_tests/main.cpp @@ -29,12 +29,7 @@ using namespace utest::v1; #define TEST_CYCLES 10000000 -#ifdef TARGET_NRF52 -/* The increased tolerance is to account for the imprecise timers on the NRF52. */ -#define ALLOWED_DRIFT_PPM (1000000/50000) //5.0% -#else #define ALLOWED_DRIFT_PPM (1000000/5000) //0.5% -#endif /* return values to be checked are documented at: @@ -103,16 +98,18 @@ MBED_NOINLINE static int time_cpu_cycles(uint32_t cycles) { Timer timer; + + core_util_critical_section_enter(); + timer.start(); - int timer_start = timer.read_us(); - - uint32_t delay = cycles; - delay_loop(delay); - int timer_end = timer.read_us(); + delay_loop(cycles); timer.stop(); - return timer_end - timer_start; + + core_util_critical_section_exit(); + + return timer.read_us(); } void flash_init_test() diff --git a/TESTS/mbed_hal/lp_ticker/lp_ticker_api_tests.h b/TESTS/mbed_hal/lp_ticker/lp_ticker_api_tests.h new file mode 100644 index 0000000000..34942d2810 --- /dev/null +++ b/TESTS/mbed_hal/lp_ticker/lp_ticker_api_tests.h @@ -0,0 +1,62 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 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_lp_ticker_tests + * @{ + */ + +#ifndef LP_TICKER_API_TESTS_H +#define LP_TICKER_API_TESTS_H + +#include "device.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/** Test that the ticker has the correct frequency and number of bits. + * + * Given ticker is available. + * When ticker information data is obtained. + * Then collected data indicates that ticker frequency is between 4KHz and 64KHz and the counter is at least 12 bits wide. + */ +void lp_ticker_info_test(void); + +/** Test that the ticker continues operating in deep sleep mode. + * + * Given ticker is available. + * When ticker has interrupt set and board enters deep-sleep mode. + * Then ticker continues operating. + */ +void lp_ticker_deepsleep_test(void); + +/** Test that the ticker does not glitch backwards due to an incorrectly implemented ripple counter driver. + * + * Given ticker is available. + * When ticker is enabled and counts. + * Then ticker does not glitch backwards due to an incorrectly implemented ripple counter driver. + */ +void lp_ticker_glitch_test(void); +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif + +/**@}*/ diff --git a/TESTS/mbed_hal/lp_ticker/main.cpp b/TESTS/mbed_hal/lp_ticker/main.cpp index 5802644c58..8c40e9c667 100644 --- a/TESTS/mbed_hal/lp_ticker/main.cpp +++ b/TESTS/mbed_hal/lp_ticker/main.cpp @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2016 ARM Limited + * Copyright (c) 2017 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,177 +13,145 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "rtos.h" +#include "lp_ticker_api_tests.h" +#include "hal/lp_ticker_api.h" -#if !DEVICE_LOWPOWERTIMER +#if !DEVICE_LPTICKER #error [NOT_SUPPORTED] Low power timer not supported for this target #endif -#include "utest/utest.h" -#include "unity/unity.h" -#include "greentea-client/test_env.h" - -#include "mbed.h" -#include "lp_ticker_api.h" - using namespace utest::v1; -static volatile bool complete; -static volatile timestamp_t complete_time; -static ticker_event_t delay_event; -static const ticker_data_t *lp_ticker_data = get_lp_ticker_data(); -static Timer timer; -static LowPowerTimer lp_timer; +volatile int intFlag = 0; -/* Timeouts are quite arbitrary due to large number of boards with varying level of accuracy */ -#define LONG_TIMEOUT (100000) -#define SHORT_TIMEOUT (600) +#define TICKER_GLITCH_TEST_TICKS 1000 -void cb_done(uint32_t id) { - if ((uint32_t)&delay_event == id) { - complete_time = timer.read_us(); - complete = true; - } else { - // Normal ticker handling - TimerEvent::irq(id); - } -} +#define TICKER_INT_VAL 500 +#define TICKER_DELTA 10 -void cb_done_deepsleep(uint32_t id) { - if ((uint32_t)&delay_event == id) { - complete_time = lp_timer.read_us(); - complete = true; - } else { - // Normal ticker handling - TimerEvent::irq(id); - } -} +#define LP_TICKER_OV_LIMIT 4000 -void lp_ticker_delay_us(uint32_t delay_us, uint32_t tolerance) +/* Since according to the ticker requirements min acceptable counter size is + * - 12 bits for low power timer - max count = 4095, + * then all test cases must be executed in this time windows. + * HAL ticker layer handles counter overflow and it is not handled in the target + * ticker drivers. Ensure we have enough time to execute test case without overflow. + */ +void overflow_protect() { - complete = false; - uint32_t delay_ts; + uint32_t time_window; - ticker_set_handler(lp_ticker_data, cb_done); - ticker_remove_event(lp_ticker_data, &delay_event); - delay_ts = ticker_read(lp_ticker_data) + delay_us; + time_window = LP_TICKER_OV_LIMIT; - timer.reset(); - timer.start(); - ticker_insert_event(lp_ticker_data, &delay_event, delay_ts, (uint32_t)&delay_event); - while (!complete); - timer.stop(); + const uint32_t ticks_now = lp_ticker_read(); + const ticker_info_t* p_ticker_info = lp_ticker_get_info(); - TEST_ASSERT_UINT32_WITHIN(tolerance, delay_us, complete_time); - TEST_ASSERT_TRUE(complete); + const uint32_t max_count = ((1 << p_ticker_info->bits) - 1); + + if ((max_count - ticks_now) > time_window) { + return; + } + + while (lp_ticker_read() > ticks_now); +} + +void ticker_event_handler_stub(const ticker_data_t * const ticker) +{ + /* Indicate that ISR has been executed in interrupt context. */ + if (IsIrqMode()) { + intFlag++; + } + + /* Clear and disable ticker interrupt. */ + lp_ticker_clear_interrupt(); + lp_ticker_disable_interrupt(); +} + +void wait_cycles(volatile unsigned int cycles) +{ + while (cycles--); +} + +/* Test that the ticker has the correct frequency and number of bits. */ +void lp_ticker_info_test() +{ + const ticker_info_t* p_ticker_info = lp_ticker_get_info(); + + TEST_ASSERT(p_ticker_info->frequency >= 4000); + TEST_ASSERT(p_ticker_info->frequency <= 64000); + TEST_ASSERT(p_ticker_info->bits >= 12); } #if DEVICE_SLEEP -void lp_ticker_1s_deepsleep() +/* Test that the ticker continues operating in deep sleep mode. */ +void lp_ticker_deepsleep_test() { - complete = false; - uint32_t delay_ts; + intFlag = 0; - /* - * Since deepsleep() may shut down the UART peripheral, we wait for 10ms - * to allow for hardware serial buffers to completely flush. + set_lp_ticker_irq_handler(ticker_event_handler_stub); - * This should be replaced with a better function that checks if the - * hardware buffers are empty. However, such an API does not exist now, - * so we'll use the wait_ms() function for now. - */ - wait_ms(10); + lp_ticker_init(); - ticker_set_handler(lp_ticker_data, cb_done_deepsleep); - ticker_remove_event(lp_ticker_data, &delay_event); - delay_ts = ticker_read(lp_ticker_data) + 1000000; + /* Wait for green tea UART transmission before entering deep-sleep mode. */ + wait_cycles(400000); - /* - * We use here the low power timer instead of microsecond timer for start and - * end because the microseconds timer might be disable during deepsleep. - */ - lp_timer.reset(); - lp_timer.start(); - ticker_insert_event(lp_ticker_data, &delay_event, delay_ts, (uint32_t)&delay_event); - /* Make sure deepsleep is allowed, to go to deepsleep */ - bool deep_sleep_allowed = sleep_manager_can_deep_sleep(); - TEST_ASSERT_TRUE_MESSAGE(deep_sleep_allowed, "Deep sleep should be allowed"); - sleep(); - while (!complete); - lp_timer.stop(); + overflow_protect(); - TEST_ASSERT_UINT32_WITHIN(LONG_TIMEOUT, 1000000, complete_time); - TEST_ASSERT_TRUE(complete); + const uint32_t tick_count = lp_ticker_read(); + + /* Set interrupt. Interrupt should be fired when tick count is equal to: + * tick_count + TICKER_INT_VAL. */ + lp_ticker_set_interrupt(tick_count + TICKER_INT_VAL); + + TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep()); + + while (!intFlag) { + sleep(); + } + + TEST_ASSERT_EQUAL(1, intFlag); +} +#endif + +/* Test that the ticker does not glitch backwards due to an incorrectly implemented ripple counter driver. */ +void lp_ticker_glitch_test() +{ + lp_ticker_init(); + + overflow_protect(); + + uint32_t last = lp_ticker_read(); + const uint32_t start = last; + + while (last < (start + TICKER_GLITCH_TEST_TICKS)) { + const uint32_t cur = lp_ticker_read(); + TEST_ASSERT(cur >= last); + last = cur; + } } -void lp_ticker_1s_sleep() +utest::v1::status_t test_setup(const size_t number_of_cases) { - complete = false; - uint32_t delay_ts; - - ticker_set_handler(lp_ticker_data, cb_done); - ticker_remove_event(lp_ticker_data, &delay_event); - delay_ts = ticker_read(lp_ticker_data) + 1000000; - - sleep_manager_lock_deep_sleep(); - timer.reset(); - timer.start(); - bool deep_sleep_allowed = sleep_manager_can_deep_sleep(); - TEST_ASSERT_FALSE_MESSAGE(deep_sleep_allowed, "Deep sleep should be disallowed"); - ticker_insert_event(lp_ticker_data, &delay_event, delay_ts, (uint32_t)&delay_event); - sleep(); - while (!complete); - timer.stop(); - sleep_manager_unlock_deep_sleep(); - - TEST_ASSERT_UINT32_WITHIN(LONG_TIMEOUT, 1000000, complete_time); - TEST_ASSERT_TRUE(complete); -} -#endif /* DEVICE_SLEEP */ - -void lp_ticker_500us(void) -{ - lp_ticker_delay_us(500, SHORT_TIMEOUT); -} - -void lp_ticker_1ms(void) -{ - lp_ticker_delay_us(1000, SHORT_TIMEOUT); -} - -void lp_ticker_1s(void) -{ - lp_ticker_delay_us(1000000, LONG_TIMEOUT); -} - -void lp_ticker_5s(void) -{ - lp_ticker_delay_us(5000000, LONG_TIMEOUT); -} - -utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) { - greentea_case_failure_abort_handler(source, reason); - return STATUS_CONTINUE; + GREENTEA_SETUP(20, "default_auto"); + return verbose_test_setup_handler(number_of_cases); } Case cases[] = { - Case("500us lp_ticker", lp_ticker_500us, greentea_failure_handler), - Case("1ms lp_ticker", lp_ticker_1ms, greentea_failure_handler), - Case("1s lp_ticker", lp_ticker_1s, greentea_failure_handler), - Case("5s lp_ticker", lp_ticker_5s, greentea_failure_handler), + Case("lp ticker info test", lp_ticker_info_test), #if DEVICE_SLEEP - Case("1s lp_ticker sleep", lp_ticker_1s_sleep, greentea_failure_handler), - Case("1s lp_ticker deepsleep", lp_ticker_1s_deepsleep, greentea_failure_handler), -#endif /* DEVICE_SLEEP */ + Case("lp ticker sleep test", lp_ticker_deepsleep_test), +#endif + Case("lp ticker glitch test", lp_ticker_glitch_test) }; -utest::v1::status_t greentea_test_setup(const size_t number_of_cases) { - GREENTEA_SETUP(20, "default_auto"); - lp_ticker_data->interface->init(); - return greentea_test_setup_handler(number_of_cases); -} +Specification specification(test_setup, cases); -Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); - -int main() { - Harness::run(specification); +int main() +{ + return !Harness::run(specification); } diff --git a/TESTS/mbed_hal/lp_us_tickers/main.cpp b/TESTS/mbed_hal/lp_us_tickers/main.cpp deleted file mode 100644 index ddeab5de49..0000000000 --- a/TESTS/mbed_hal/lp_us_tickers/main.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 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 "utest/utest.h" -#include "unity/unity.h" -#include "greentea-client/test_env.h" - -#include "mbed.h" -#include "us_ticker_api.h" -#include "ticker_api.h" - -using namespace utest::v1; - -namespace { - volatile bool complete; - const ticker_interface_t* intf; -} - -/* Ticker init should be run just once, thus read should always return a value that - * increases (no reset). - */ -void test_ticker_init(void) -{ - intf->init(); - uint32_t previous = intf->read(); - - intf->init(); - uint32_t current = intf->read(); - TEST_ASSERT_TRUE_MESSAGE(previous <= current, "init() changed the counter"); - - previous = intf->read(); - intf->init(); - current = intf->read(); - TEST_ASSERT_TRUE_MESSAGE(previous <= current, "init() changed the counter"); -} - -/* Read multiple times, each returned time should be bigger than the previous one - * Counter up. - */ -void test_ticker_read(void) -{ - // this test assumes that to wrap around we would need to run >60 minutes - // therefore wrapping should not happen - previous <= current - const uint32_t test_loop = 15000; - uint32_t previous = intf->read(); - uint32_t current; - for (uint32_t i = 0UL; i < test_loop; i++) { - current = intf->read(); - TEST_ASSERT_TRUE_MESSAGE(previous <= current, "us ticker counter wrapped around"); - } -} - -/* Implement simple read while loop to check if time is increasing (counter up) - */ -void test_ticker_read_loop() -{ - uint32_t future_time = intf->read() + 10000UL; - while (intf->read() < future_time); - TEST_ASSERT_TRUE_MESSAGE(future_time <= intf->read(), "Future time is in the past"); -} - -utest::v1::status_t us_ticker_setup(const Case *const source, const size_t index_of_case) -{ - intf = get_us_ticker_data()->interface; - return greentea_case_setup_handler(source, index_of_case); -} - -#if DEVICE_LOWPOWERTIMER -utest::v1::status_t lp_ticker_setup(const Case *const source, const size_t index_of_case) -{ - intf = get_lp_ticker_data()->interface; - return greentea_case_setup_handler(source, index_of_case); -} -#endif - -Case cases[] = { - Case("us ticker HAL - Init", us_ticker_setup, test_ticker_init), - Case("us ticker HAL - Read", us_ticker_setup, test_ticker_read), - Case("us ticker HAL - Read in the loop", us_ticker_setup, test_ticker_read_loop), -#if DEVICE_LOWPOWERTIMER - Case("lp ticker HAL - Init", lp_ticker_setup, test_ticker_init), - Case("lp ticker HAL - Read", lp_ticker_setup, test_ticker_read), - Case("lp ticker HAL - Read in the loop", lp_ticker_setup, test_ticker_read_loop), -#endif -}; - -utest::v1::status_t greentea_test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(20, "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); -} diff --git a/TESTS/mbed_hal/rtc/main.cpp b/TESTS/mbed_hal/rtc/main.cpp new file mode 100644 index 0000000000..0aab34531d --- /dev/null +++ b/TESTS/mbed_hal/rtc/main.cpp @@ -0,0 +1,258 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 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. + */ + +#if !DEVICE_RTC + #error [NOT_SUPPORTED] RTC API not supported for this target +#endif + +#include "utest/utest.h" +#include "unity/unity.h" +#include "greentea-client/test_env.h" +#include "rtc_test.h" + +#include "mbed.h" +#include "rtc_api.h" + +using namespace utest::v1; + +static const uint32_t WAIT_TIME = 4; +static const uint32_t WAIT_TOLERANCE = 1; + +#define US_PER_SEC 1000000 +#define ACCURACY_FACTOR 10 + +static const uint32_t DELAY_4S = 4; +static const uint32_t DELAY_10S = 10; +static const uint32_t RTC_TOLERANCE = 1; +static const uint32_t TOLERANCE_ACCURACY_US = (DELAY_10S * US_PER_SEC / ACCURACY_FACTOR); + +#if DEVICE_LPTICKER +volatile bool expired; + +void callback(void) +{ + expired = true; +} + +/* Auxiliary function to test if RTC continue counting in + * sleep and deep-sleep modes. */ +void rtc_sleep_test_support (bool deepsleep_mode) +{ + LowPowerTimeout timeout; + const uint32_t start = 100; + expired = false; + + /* + * Since deepsleep() may shut down the UART peripheral, we wait for 10ms + * to allow for hardware serial buffers to completely flush. + * This should be replaced with a better function that checks if the + * hardware buffers are empty. However, such an API does not exist now, + * so we'll use the wait_ms() function for now. + */ + wait_ms(10); + + rtc_init(); + + if(deepsleep_mode == false) { + sleep_manager_lock_deep_sleep(); + } + + rtc_write(start); + + timeout.attach(callback, DELAY_4S); + + TEST_ASSERT(sleep_manager_can_deep_sleep() == deepsleep_mode); + + while(!expired) sleep(); + + const uint32_t stop = rtc_read(); + + TEST_ASSERT_UINT32_WITHIN(RTC_TOLERANCE, DELAY_4S, stop - start); + + timeout.detach(); + + if(deepsleep_mode == false) { + sleep_manager_unlock_deep_sleep(); + } + + rtc_free(); +} +#endif + +/* Test that ::rtc_init can be called multiple times. */ +void rtc_init_test() +{ + for (int i = 0; i < 10; i++) { + rtc_init(); + } + + rtc_free(); +} + +#if DEVICE_LPTICKER +/** Test that the RTC keeps counting in the various sleep modes. */ + +void rtc_sleep_test() +{ + /* Test sleep mode. */ + rtc_sleep_test_support(false); + + /* Test deep-sleep mode. */ + rtc_sleep_test_support(true); +} +#endif + +/* Test that the RTC keeps counting even after ::rtc_free has been called. */ +void rtc_persist_test() +{ + const uint32_t start = 100; + rtc_init(); + rtc_write(start); + rtc_free(); + + wait(WAIT_TIME); + + rtc_init(); + const uint32_t stop = rtc_read(); + const int enabled = rtc_isenabled(); + rtc_free(); + + TEST_ASSERT_TRUE(enabled); + TEST_ASSERT_UINT32_WITHIN(WAIT_TOLERANCE, WAIT_TIME, stop - start); +} + +/* Test time does not glitch backwards due to an incorrectly implemented ripple counter driver. */ +void rtc_glitch_test() +{ + const uint32_t start = 0xffffe; + rtc_init(); + + rtc_write(start); + uint32_t last = start; + while (last < start + 4) { + const uint32_t cur = rtc_read(); + TEST_ASSERT(cur >= last); + last = cur; + } + + rtc_free(); +} + +/* Test that the RTC correctly handles different time values. */ +void rtc_range_test() +{ + static const uint32_t starts[] = { + 0x00000000, + 0xEFFFFFFF, + 0x00001000, + 0x00010000, + }; + + rtc_init(); + for (uint32_t i = 0; i < sizeof(starts) / sizeof(starts[0]); i++) { + const uint32_t start = starts[i]; + rtc_write(start); + wait(WAIT_TIME); + const uint32_t stop = rtc_read(); + TEST_ASSERT_UINT32_WITHIN(WAIT_TOLERANCE, WAIT_TIME, stop - start); + } + rtc_free(); +} + +/* Test that the RTC accuracy is at least 10%. */ +void rtc_accuracy_test() +{ + Timer timer1; + + const uint32_t start = 100; + rtc_init(); + rtc_write(start); + + timer1.start(); + while(rtc_read() < (start + DELAY_10S)) { + /* Just wait. */ + } + timer1.stop(); + + /* RTC accuracy is at least 10%. */ + TEST_ASSERT_INT32_WITHIN(TOLERANCE_ACCURACY_US, DELAY_10S * US_PER_SEC, timer1.read_us()); +} + +/* Test that ::rtc_write/::rtc_read functions provides availability to set/get RTC time. */ +void rtc_write_read_test() +{ + static const uint32_t rtc_init_val = 100; + + rtc_init(); + + for (int i = 0; i < 3; i++) { + const uint32_t init_val = (rtc_init_val + i * rtc_init_val); + + core_util_critical_section_enter(); + + rtc_write(init_val); + const uint32_t read_val = rtc_read(); + + core_util_critical_section_exit(); + + /* No tolerance is provided since we should have 1 second to + * execute this case after the RTC time is set. + */ + TEST_ASSERT_EQUAL_UINT32(init_val, read_val); + } + + rtc_free(); +} + +/* Test that ::is_enabled function returns 1 if the RTC is counting and the time has been set. */ +void rtc_enabled_test() +{ + /* Since some platforms use RTC for low power timer RTC may be already enabled. + * Because of that we will only verify if rtc_isenabled() returns 1 in case when init is done + * and RTC time is set. + */ + + rtc_init(); + rtc_write(0); + TEST_ASSERT_EQUAL_INT(1, rtc_isenabled()); + rtc_free(); +} + +Case cases[] = { + Case("RTC - init", rtc_init_test), +#if DEVICE_LPTICKER + Case("RTC - sleep", rtc_sleep_test), +#endif + Case("RTC - persist", rtc_persist_test), + Case("RTC - glitch", rtc_glitch_test), + Case("RTC - range", rtc_range_test), + Case("RTC - accuracy", rtc_accuracy_test), + Case("RTC - write/read", rtc_write_read_test), + Case("RTC - enabled", rtc_enabled_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); +} diff --git a/TESTS/mbed_hal/rtc/rtc_test.h b/TESTS/mbed_hal/rtc/rtc_test.h new file mode 100644 index 0000000000..b0b529a460 --- /dev/null +++ b/TESTS/mbed_hal/rtc/rtc_test.h @@ -0,0 +1,115 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 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_rtc_tests + * @{ + */ + +#ifndef MBED_RTC_TEST_H +#define MBED_RTC_TEST_H + +#if DEVICE_RTC + +#ifdef __cplusplus +extern "C" { +#endif + +/** Test that ::rtc_init can be called multiple times. + * + * Given board provides RTC. + * When ::rtc_init is called multiple times. + * Then ::rtc_init are successfully performed (no exception is generated). + * + */ +void rtc_init_test(void); + +/** Test that the RTC keeps counting in the various sleep modes. + * + * Given board provides RTC. + * When system enters sleep/deep-sleep mode. + * RTC keeps counting. + * + */ +void rtc_sleep_test(void); + +/** Test that the RTC keeps counting even after ::rtc_free has been called. + * + * Given board provides RTC. + * When ::rtc_free has been called. + * RTC keeps counting. + * + */ +void rtc_persist_test(void); + +/** Test time does not glitch backwards due to an incorrectly implemented ripple counter driver. + * + * Given board provides RTC. + * When RTC is enabled and counts. + * Then time does not glitch backwards due to an incorrectly implemented ripple counter driver. + * + */ +void rtc_glitch_test(void); + +/** Test that the RTC correctly handles large time values. + * + * Given board provides RTC. + * When RTC is enabled and counts. + * The RTC correctly handles different time values. + */ +void rtc_range_test(void); + +/** Test that the RTC accuracy is at least 10%. + * + * Given platform provides Real Time Clock. + * When delay is performed based on RTC (10 sec delay). + * Then the delay time measured using high frequency timer indicate that RTC accuracy is at least 10%. + * + */ +void rtc_accuracy_test(void); + +/** Test that ::rtc_write/::rtc_read functions provides availability to set/get RTC time. + * + * Given platform provides Real Time Clock. + * When an example RTC time is set by means of rtc_write function and rtc_read is performed immediately after this operation. + * Then rtc_read function returns time which has been set. + * + */ +void rtc_write_read_test(void); + +/** Test that ::rtc_isenabled function returns 1 if the RTC is counting and the time has been set, 0 otherwise + * + * NOTE: RTC is counting when it has been initialised by means of rtc_init(). + * RTC time is set by means of rtc_write() function. + * RTC must be initialised before rtc_isenabled() function can be called. + * + * Given platform provides Real Time Clock. + * When rtc_isenabled() function is called. + * Then the result is 1 if RTC time has been set, otherwise the result is 0. + * + */ +void rtc_enabled_test(void); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +/** @}*/ diff --git a/TESTS/mbed_hal/rtc_reset/main.cpp b/TESTS/mbed_hal/rtc_reset/main.cpp new file mode 100644 index 0000000000..f07b194e9d --- /dev/null +++ b/TESTS/mbed_hal/rtc_reset/main.cpp @@ -0,0 +1,102 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 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. + */ + +#if !DEVICE_RTC + #error [NOT_SUPPORTED] RTC API not supported for this target +#endif + +#include "utest/utest.h" +#include "unity/unity.h" +#include "greentea-client/test_env.h" +#include "rtc_reset_test.h" + +#include "mbed.h" +#include "rtc_api.h" + + +typedef enum { + CMD_STATUS_PASS, + CMD_STATUS_FAIL, + CMD_STATUS_CONTINUE, + CMD_STATUS_ERROR +} cmd_status_t; + +static cmd_status_t handle_command(const char *key, const char *value) +{ + if (strcmp(key, "init") == 0) { + rtc_init(); + greentea_send_kv("ack", 0); + return CMD_STATUS_CONTINUE; + + } else if (strcmp(key, "free") == 0) { + rtc_free(); + greentea_send_kv("ack", 0); + return CMD_STATUS_CONTINUE; + + } else if (strcmp(key, "read") == 0) { + static char time_buf[64]; + memset(time_buf, 0, sizeof(time_buf)); + sprintf(time_buf, "%lu", (uint32_t)rtc_read()); + greentea_send_kv("read", time_buf); + return CMD_STATUS_CONTINUE; + + } else if (strcmp(key, "write") == 0) { + uint32_t time; + sscanf(value, "%lu", &time); + rtc_write(time); + greentea_send_kv("ack", 0); + return CMD_STATUS_CONTINUE; + + } else if (strcmp(key, "reset") == 0) { + NVIC_SystemReset(); + // Code shouldn't read this due to the reset + return CMD_STATUS_ERROR; + + } else if (strcmp(key, "exit") == 0) { + return strcmp(value, "pass") == 0 ? CMD_STATUS_PASS : CMD_STATUS_FAIL; + + } else { + return CMD_STATUS_ERROR; + + } +} + +/* Test that software reset doesn't stop RTC from counting. */ +void rtc_reset_test() +{ + GREENTEA_SETUP(100, "rtc_reset"); + + static char _key[10 + 1] = {}; + static char _value[128 + 1] = {}; + + greentea_send_kv("start", 1); + + // Handshake with host + cmd_status_t cmd_status = CMD_STATUS_CONTINUE; + while (CMD_STATUS_CONTINUE == cmd_status) { + memset(_key, 0, sizeof(_key)); + memset(_value, 0, sizeof(_value)); + greentea_parse_kv(_key, _value, sizeof(_key) - 1, sizeof(_value) - 1); + cmd_status = handle_command(_key, _value); + } + + GREENTEA_TESTSUITE_RESULT(CMD_STATUS_PASS == cmd_status); +} + +int main() +{ + rtc_reset_test(); +} diff --git a/TESTS/mbed_hal/rtc_reset/rtc_reset_test.h b/TESTS/mbed_hal/rtc_reset/rtc_reset_test.h new file mode 100644 index 0000000000..4f14e98b87 --- /dev/null +++ b/TESTS/mbed_hal/rtc_reset/rtc_reset_test.h @@ -0,0 +1,49 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 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_rtc_tests + * @{ + */ + +#ifndef MBED_RTC_TEST_H +#define MBED_RTC_TEST_H + +#if DEVICE_RTC + +#ifdef __cplusplus +extern "C" { +#endif + +/** Test that the RTC does not stop counting after a software reset. + * + * Given board provides RTC. + * When software reset is performed. + * Then the RTC does not stop counting. + * + */ +void rtc_reset_test(); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +/** @}*/ diff --git a/TESTS/mbed_hal/sleep/main.cpp b/TESTS/mbed_hal/sleep/main.cpp new file mode 100644 index 0000000000..1621dd18ff --- /dev/null +++ b/TESTS/mbed_hal/sleep/main.cpp @@ -0,0 +1,246 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 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. + */ + +#if 1 || !DEVICE_SLEEP +#error [NOT_SUPPORTED] sleep not supported for this target +#endif + +#include "mbed.h" + +#include "utest/utest.h" +#include "unity/unity.h" +#include "greentea-client/test_env.h" + +#include "sleep_api_tests.h" + +#define US_PER_S 1000000 + +using namespace utest::v1; + +/* The following ticker frequencies are possible: + * high frequency ticker: 250 KHz (1 tick per 4 us) - 8 Mhz (1 tick per 1/8 us) + * low power ticker: 8 KHz (1 tick per 125 us) - 64 KHz (1 tick per ~15.6 us) + */ + +/* Used for regular sleep mode, a target should be awake within 10 us. Define us delta value as follows: + * delta = default 10 us + worst ticker resolution + extra time for code execution */ +static const uint32_t sleep_mode_delta_us = (10 + 4 + 5); + +/* Used for deep-sleep mode, a target should be awake within 10 ms. Define us delta value as follows: + * delta = default 10 ms + worst ticker resolution + extra time for code execution */ +static const uint32_t deepsleep_mode_delta_us = (10000 + 125 + 5); + +unsigned int ticks_to_us(unsigned int ticks, unsigned int freq) +{ + return (unsigned int) ((unsigned long long) ticks * US_PER_S / freq); +} + +unsigned int us_to_ticks(unsigned int us, unsigned int freq) +{ + return (unsigned int) ((unsigned long long) us * freq / US_PER_S); +} + +unsigned int overflow_protect(unsigned int timestamp, unsigned int ticker_width) +{ + unsigned int counter_mask = ((1 << ticker_width) - 1); + + return (timestamp & counter_mask); +} + +bool compare_timestamps(unsigned int delta_ticks, unsigned int ticker_width, unsigned int expected, unsigned int actual) +{ + const unsigned int counter_mask = ((1 << ticker_width) - 1); + + const unsigned int lower_bound = ((expected - delta_ticks) & counter_mask); + const unsigned int upper_bound = ((expected + delta_ticks) & counter_mask); + + if (lower_bound < upper_bound) { + if (actual >= lower_bound && actual <= upper_bound) { + return true; + } else { + return false; + } + } else { + if ((actual >= lower_bound && actual <= counter_mask) || (actual >= 0 && actual <= upper_bound)) { + return true; + } else { + return false; + } + } +} + +void us_ticker_isr(const ticker_data_t * const ticker_data) +{ + us_ticker_clear_interrupt(); +} + +#ifdef DEVICE_LPTICKER +void lp_ticker_isr(const ticker_data_t *const ticker_data) +{ + lp_ticker_clear_interrupt(); +} +#endif + +/* Test that wake-up time from sleep should be less than 10 us and + * high frequency ticker interrupt can wake-up target from sleep. */ +void sleep_usticker_test() +{ +#if 0 + const ticker_data_t * ticker = get_us_ticker_data(); + const unsigned int ticker_freq = ticker->interface->get_info()->frequency; + const unsigned int ticker_width = ticker->interface->get_info()->bits; + + const ticker_irq_handler_type us_ticker_irq_handler_org = set_us_ticker_irq_handler(us_ticker_isr); + + /* Test only sleep functionality. */ + sleep_manager_lock_deep_sleep(); + TEST_ASSERT_FALSE_MESSAGE(sleep_manager_can_deep_sleep(), "deep sleep should be locked"); + + /* Testing wake-up time 10 us. */ + for (timestamp_t i = 100; i < 1000; i += 100) { + /* note: us_ticker_read() operates on ticks. */ + const timestamp_t next_match_timestamp = overflow_protect(us_ticker_read() + us_to_ticks(i, ticker_freq), + ticker_width); + + us_ticker_set_interrupt(next_match_timestamp); + + sleep(); + + const unsigned int wakeup_timestamp = us_ticker_read(); + + TEST_ASSERT( + compare_timestamps(us_to_ticks(sleep_mode_delta_us, ticker_freq), ticker_width, next_match_timestamp, + wakeup_timestamp)); + } + + set_us_ticker_irq_handler(us_ticker_irq_handler_org); + + sleep_manager_unlock_deep_sleep(); + TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep()); +#endif +} + +#ifdef DEVICE_LPTICKER + +/* Test that wake-up time from sleep should be less than 10 ms and + * low power ticker interrupt can wake-up target from sleep. */ +void deepsleep_lpticker_test() +{ + const ticker_data_t * ticker = get_lp_ticker_data(); + const unsigned int ticker_freq = ticker->interface->get_info()->frequency; + const unsigned int ticker_width = ticker->interface->get_info()->bits; + + const ticker_irq_handler_type lp_ticker_irq_handler_org = set_lp_ticker_irq_handler(lp_ticker_isr); + + /* Give some time Green Tea to finish UART transmission before entering + * deep-sleep mode. + */ + wait_ms(10); + + TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep(), "deep sleep should not be locked"); + + /* Testing wake-up time 10 ms. */ + for (timestamp_t i = 20000; i < 200000; i += 20000) { + /* note: lp_ticker_read() operates on ticks. */ + const timestamp_t next_match_timestamp = overflow_protect(lp_ticker_read() + us_to_ticks(i, ticker_freq), ticker_width); + + lp_ticker_set_interrupt(next_match_timestamp); + + sleep(); + + const timestamp_t wakeup_timestamp = lp_ticker_read(); + + TEST_ASSERT(compare_timestamps(us_to_ticks(deepsleep_mode_delta_us, ticker_freq), ticker_width, next_match_timestamp, wakeup_timestamp)); + } + + set_lp_ticker_irq_handler(lp_ticker_irq_handler_org); + +} + +void deepsleep_high_speed_clocks_turned_off_test() +{ + const ticker_data_t * us_ticker = get_us_ticker_data(); + const ticker_data_t * lp_ticker = get_lp_ticker_data(); + const unsigned int us_ticker_freq = us_ticker->interface->get_info()->frequency; + const unsigned int lp_ticker_freq = lp_ticker->interface->get_info()->frequency; + const unsigned int us_ticker_width = us_ticker->interface->get_info()->bits; + const unsigned int lp_ticker_width = lp_ticker->interface->get_info()->bits; + const unsigned int us_ticker_mask = ((1 << us_ticker_width) - 1); + + /* Give some time Green Tea to finish UART transmission before entering + * deep-sleep mode. + */ + wait_ms(10); + + TEST_ASSERT_TRUE_MESSAGE(sleep_manager_can_deep_sleep(), "deep sleep should not be locked"); + + const unsigned int us_ticks_before_sleep = us_ticker_read(); + + const timestamp_t wakeup_time = lp_ticker_read() + us_to_ticks(20000, lp_ticker_freq); + lp_ticker_set_interrupt(wakeup_time); + + sleep(); + + const unsigned int us_ticks_after_sleep = us_ticker_read(); + const unsigned int lp_ticks_after_sleep = lp_ticker_read(); + + /* High freqency ticker should be disabled in deep-sleep mode. We expect that time difference between + * ticker reads before and after the sleep represents only code execution time between calls. + * Since we went to sleep for about 20 ms check if time counted by high frequency timer does not + * exceed 1 ms. + */ + const unsigned int us_ticks_diff = (us_ticks_before_sleep <= us_ticks_after_sleep) ? (us_ticks_after_sleep - us_ticks_before_sleep) : (us_ticker_mask - us_ticks_before_sleep + us_ticks_after_sleep + 1); + + TEST_ASSERT_UINT32_WITHIN(1000, 0, ticks_to_us(us_ticks_diff, us_ticker_freq)); + + /* Check if we have woken-up after expected time. */ + TEST_ASSERT(compare_timestamps(us_to_ticks(deepsleep_mode_delta_us, lp_ticker_freq), lp_ticker_width, wakeup_time, lp_ticks_after_sleep)); +} + +#endif + +utest::v1::status_t greentea_failure_handler(const Case * const source, const failure_t reason) +{ + greentea_case_failure_abort_handler(source, reason); + return STATUS_CONTINUE; +} + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(60, "default_auto"); + us_ticker_init(); +#if DEVICE_LPTICKER + lp_ticker_init(); +#endif + /* Suspend RTOS Kernel to enable sleep modes. */ + osKernelSuspend(); + return greentea_test_setup_handler(number_of_cases); +} + +Case cases[] = + { Case("sleep - source of wake-up - us ticker", sleep_usticker_test, greentea_failure_handler), +#if DEVICE_LPTICKER + Case("deep-sleep - source of wake-up - lp ticker",deepsleep_lpticker_test, greentea_failure_handler), + Case("deep-sleep - high-speed clocks are turned off",deepsleep_high_speed_clocks_turned_off_test, greentea_failure_handler), +#endif + }; + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() +{ + Harness::run(specification); +} diff --git a/TESTS/mbed_hal/sleep/sleep_api_tests.h b/TESTS/mbed_hal/sleep/sleep_api_tests.h new file mode 100644 index 0000000000..6a48a98db5 --- /dev/null +++ b/TESTS/mbed_hal/sleep/sleep_api_tests.h @@ -0,0 +1,69 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 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_sleep_tests */ +/** @{*/ + +#ifndef MBED_SLEEP_API_TESTS_H +#define MBED_SLEEP_API_TESTS_H + +#include "device.h" + +#if DEVICE_SLEEP + +#ifdef __cplusplus +extern "C" { +#endif + +/** High frequency ticker interrupt can wake up from sleep (locked deep-sleep). + * + * Given is an environment with high frequency ticker. + * When the board enters sleep mode. + * Then the board can be wake up from the sleep by high frequency ticker interrupt and + * wake-up time should be less than 10 us. + */ +void sleep_usticker_test(); + +/** Low power ticker interrupt to wake up from deep-sleep (unlocked deep-sleep). + * + * Given is an environment with low power ticker. + * When the board enters deep-sleep mode. + * Then the board can be wake up from the sleep by low power ticker interrupt and + * wake-up time should be less than 10 ms. + * + */ +void deepsleep_lpticker_test(); + +/** High speed clocks are turned off in deep-sleep (unlocked deep-sleep) + * + * Given is an environment with high frequency ticker. + * When the board enters deep-sleep mode. + * Then high frequency ticker does not count while the board is in the deep-sleep mode. + * + */ +void deepsleep_high_speed_clocks_turned_off_test(); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +/**@}*/ diff --git a/TESTS/mbed_hal/sleep_manager_racecondition/main.cpp b/TESTS/mbed_hal/sleep_manager_racecondition/main.cpp index ed2aa2f345..ee4158fa13 100644 --- a/TESTS/mbed_hal/sleep_manager_racecondition/main.cpp +++ b/TESTS/mbed_hal/sleep_manager_racecondition/main.cpp @@ -22,6 +22,10 @@ #error [NOT_SUPPORTED] test not supported #endif +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif + using namespace utest::v1; #define TEST_STACK_SIZE 256 diff --git a/TESTS/mbed_hal/us_ticker/main.cpp b/TESTS/mbed_hal/us_ticker/main.cpp new file mode 100644 index 0000000000..0aa8550817 --- /dev/null +++ b/TESTS/mbed_hal/us_ticker/main.cpp @@ -0,0 +1,54 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 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 "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "us_ticker_api_tests.h" +#include "hal/us_ticker_api.h" + +#if !DEVICE_USTICKER +#error [NOT_SUPPORTED] test not supported +#endif + +using namespace utest::v1; + +/* Test that the ticker has the correct frequency and number of bits. */ +void us_ticker_info_test() +{ + const ticker_info_t* p_ticker_info = us_ticker_get_info(); + + TEST_ASSERT(p_ticker_info->frequency >= 250000); + TEST_ASSERT(p_ticker_info->frequency <= 8000000); + TEST_ASSERT(p_ticker_info->bits >= 16); +} + +utest::v1::status_t test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(20, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("us ticker info test", us_ticker_info_test), +}; + +Specification specification(test_setup, cases); + +int main() +{ + return !Harness::run(specification); +} diff --git a/TESTS/mbed_hal/us_ticker/us_ticker_api_tests.h b/TESTS/mbed_hal/us_ticker/us_ticker_api_tests.h new file mode 100644 index 0000000000..ab1eb2ea39 --- /dev/null +++ b/TESTS/mbed_hal/us_ticker/us_ticker_api_tests.h @@ -0,0 +1,47 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 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_us_ticker_tests */ +/** @{*/ + +#ifndef US_TICKER_API_TESTS_H +#define US_TICKER_API_TESTS_H + +#include "device.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/** Test that the ticker has the correct frequency and number of bits. + * + * Given ticker is available. + * When ticker information data is obtained. + * Then ticker information indicate that frequency between 250KHz and 8MHz and the counter is at least 16 bits wide. + */ +void us_ticker_info_test(void); + + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif + +/**@}*/ diff --git a/TESTS/mbed_platform/stats_cpu/main.cpp b/TESTS/mbed_platform/stats_cpu/main.cpp index 188e9dbeae..077d7199f2 100644 --- a/TESTS/mbed_platform/stats_cpu/main.cpp +++ b/TESTS/mbed_platform/stats_cpu/main.cpp @@ -21,7 +21,7 @@ #include "mbed.h" -#if !defined(MBED_CPU_STATS_ENABLED) || !defined(DEVICE_LOWPOWERTIMER) || !defined(DEVICE_SLEEP) +#if !defined(MBED_CPU_STATS_ENABLED) || !defined(DEVICE_LPTICKER) || !defined(DEVICE_SLEEP) #error [NOT_SUPPORTED] test not supported #endif diff --git a/TESTS/mbedmicro-rtos-mbed/basic/main.cpp b/TESTS/mbedmicro-rtos-mbed/basic/main.cpp index 87b1e6712f..f2448f6646 100644 --- a/TESTS/mbedmicro-rtos-mbed/basic/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/basic/main.cpp @@ -23,6 +23,10 @@ #error [NOT_SUPPORTED] test not supported #endif +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif + using utest::v1::Case; #define TEST_STACK_SIZE 256 diff --git a/TESTS/mbedmicro-rtos-mbed/condition_variable/main.cpp b/TESTS/mbedmicro-rtos-mbed/condition_variable/main.cpp index d33c9c7bac..9d63b20afb 100644 --- a/TESTS/mbedmicro-rtos-mbed/condition_variable/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/condition_variable/main.cpp @@ -23,6 +23,10 @@ #error [NOT_SUPPORTED] test not supported #endif +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif + using namespace utest::v1; #define TEST_STACK_SIZE 512 diff --git a/TESTS/mbedmicro-rtos-mbed/event_flags/main.cpp b/TESTS/mbedmicro-rtos-mbed/event_flags/main.cpp index 4ec343bf33..d18d4d64d4 100644 --- a/TESTS/mbedmicro-rtos-mbed/event_flags/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/event_flags/main.cpp @@ -26,6 +26,10 @@ using utest::v1::Case; #error [NOT_SUPPORTED] test not supported #endif +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif + #define THREAD_STACK_SIZE 320 /* 512B stack on GCC_ARM compiler cause out of memory on some 16kB RAM boards e.g. NUCLEO_F070RB */ #define MAX_FLAG_POS 30 diff --git a/TESTS/mbedmicro-rtos-mbed/heap_and_stack/main.cpp b/TESTS/mbedmicro-rtos-mbed/heap_and_stack/main.cpp index b5b6b4cbf9..54f26c0ae4 100644 --- a/TESTS/mbedmicro-rtos-mbed/heap_and_stack/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/heap_and_stack/main.cpp @@ -16,7 +16,11 @@ */ #if defined(TARGET_CORTEX_A) - #error [NOT_SUPPORTED] This function not supported for this target + #error [NOT_SUPPORTED] This function not supported for this target +#endif + +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported #endif #include diff --git a/TESTS/mbedmicro-rtos-mbed/mail/main.cpp b/TESTS/mbedmicro-rtos-mbed/mail/main.cpp index 6c9aa96d1f..e80cc758b6 100644 --- a/TESTS/mbedmicro-rtos-mbed/mail/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/mail/main.cpp @@ -23,6 +23,10 @@ #error [NOT_SUPPORTED] test not supported #endif +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif + using namespace utest::v1; #define THREAD_STACK_SIZE 320 /* larger stack cause out of heap memory on some 16kB RAM boards in multi thread test*/ diff --git a/TESTS/mbedmicro-rtos-mbed/malloc/main.cpp b/TESTS/mbedmicro-rtos-mbed/malloc/main.cpp index 6655bc33b7..904a493e43 100644 --- a/TESTS/mbedmicro-rtos-mbed/malloc/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/malloc/main.cpp @@ -23,6 +23,10 @@ #error [NOT_SUPPORTED] test not supported #endif +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif + using utest::v1::Case; extern uint32_t mbed_heap_size; diff --git a/TESTS/mbedmicro-rtos-mbed/mutex/main.cpp b/TESTS/mbedmicro-rtos-mbed/mutex/main.cpp index 0506a66dbd..6c0a0138f9 100644 --- a/TESTS/mbedmicro-rtos-mbed/mutex/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/mutex/main.cpp @@ -23,6 +23,10 @@ #error [NOT_SUPPORTED] test not supported #endif +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif + using namespace utest::v1; #define TEST_STACK_SIZE 512 diff --git a/TESTS/mbedmicro-rtos-mbed/queue/main.cpp b/TESTS/mbedmicro-rtos-mbed/queue/main.cpp index 81fe8177bd..efa5d9a30e 100644 --- a/TESTS/mbedmicro-rtos-mbed/queue/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/queue/main.cpp @@ -23,6 +23,10 @@ #error [NOT_SUPPORTED] test not supported #endif +#if !DEVICE_USTICKER +#error [NOT_SUPPORTED] test not supported +#endif + using namespace utest::v1; #define THREAD_STACK_SIZE 512 diff --git a/TESTS/mbedmicro-rtos-mbed/rtostimer/main.cpp b/TESTS/mbedmicro-rtos-mbed/rtostimer/main.cpp index 6ec123a112..12baae3b65 100644 --- a/TESTS/mbedmicro-rtos-mbed/rtostimer/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/rtostimer/main.cpp @@ -30,6 +30,10 @@ using namespace utest::v1; #error invalid RESTART_DELAY_MS value #endif +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif + class Stopwatch: public Timer { private: Semaphore _sem; diff --git a/TESTS/mbedmicro-rtos-mbed/semaphore/main.cpp b/TESTS/mbedmicro-rtos-mbed/semaphore/main.cpp index ce21175208..7e23c1f609 100644 --- a/TESTS/mbedmicro-rtos-mbed/semaphore/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/semaphore/main.cpp @@ -25,6 +25,10 @@ using namespace utest::v1; #error [NOT_SUPPORTED] test not supported #endif +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif + #define THREAD_DELAY 30 #define SEMAPHORE_SLOTS 2 #define SEM_CHANGES 100 diff --git a/TESTS/mbedmicro-rtos-mbed/signals/main.cpp b/TESTS/mbedmicro-rtos-mbed/signals/main.cpp index 324329397b..2e66b5d86d 100644 --- a/TESTS/mbedmicro-rtos-mbed/signals/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/signals/main.cpp @@ -20,11 +20,14 @@ using utest::v1::Case; - #if defined(MBED_RTOS_SINGLE_THREAD) #error [NOT_SUPPORTED] test not supported #endif +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif + #define TEST_STACK_SIZE 512 #define MAX_FLAG_POS 30 diff --git a/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp b/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp index 68d27977da..4f688799ba 100644 --- a/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/systimer/main.cpp @@ -17,7 +17,7 @@ #error [NOT_SUPPORTED] Tickless mode not supported for this target. #endif -#if !DEVICE_LOWPOWERTIMER +#if !DEVICE_LPTICKER #error [NOT_SUPPORTED] Current SysTimer implementation requires lp ticker support. #endif @@ -251,6 +251,7 @@ void test_handler_called_once(void) TEST_ASSERT_EQUAL_UINT32(1, st.get_tick()); } +#if DEVICE_SLEEP /** Test wake up from sleep * * Given a SysTimer with a tick scheduled in the future @@ -279,7 +280,7 @@ void test_sleep(void) TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, timer.read_high_resolution_us()); } -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER /** Test wake up from deepsleep * * Given a SysTimer with a tick scheduled in the future @@ -316,6 +317,7 @@ void test_deepsleep(void) TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, lptimer.read_high_resolution_us()); } #endif +#endif utest::v1::status_t test_setup(const size_t number_of_cases) { @@ -330,10 +332,12 @@ Case cases[] = { Case("Tick can be cancelled", test_cancel_tick), Case("Schedule zero ticks", test_schedule_zero), Case("Handler called once", test_handler_called_once), +#if DEVICE_SLEEP Case("Wake up from sleep", test_sleep), -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER Case("Wake up from deep sleep", test_deepsleep), #endif +#endif }; diff --git a/TESTS/mbedmicro-rtos-mbed/threads/main.cpp b/TESTS/mbedmicro-rtos-mbed/threads/main.cpp index 7ebf09e795..f98b7f1a30 100644 --- a/TESTS/mbedmicro-rtos-mbed/threads/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/threads/main.cpp @@ -25,6 +25,10 @@ #error [NOT_SUPPORTED] test not supported #endif +#if !DEVICE_USTICKER + #error [NOT_SUPPORTED] test not supported +#endif + #define THREAD_STACK_SIZE 512 #if defined(__CORTEX_A9) #define PARALLEL_THREAD_STACK_SIZE 512 diff --git a/doxyfile_options b/doxyfile_options index 2764893f9b..747208a585 100644 --- a/doxyfile_options +++ b/doxyfile_options @@ -2079,7 +2079,7 @@ PREDEFINED = DOXYGEN_ONLY \ DEVICE_I2C_ASYNCH \ DEVICE_INTERRUPTIN \ DEVICE_ITM \ - DEVICE_LOWPOWERTIMER \ + DEVICE_LPTICKER \ DEVICE_PORTIN \ DEVICE_PORTINOUT \ DEVICE_PORTOUT \ diff --git a/doxygen_options.json b/doxygen_options.json index 3677ddc441..b1c6fd8220 100644 --- a/doxygen_options.json +++ b/doxygen_options.json @@ -6,7 +6,7 @@ "SEARCH_INCLUDES": "YES", "INCLUDE_PATH": "", "INCLUDE_FILE_PATTERNS": "", - "PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_CRC DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LOWPOWERTIMER DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_STORAGE \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\"", + "PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_CRC DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LPTICKER DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_STORAGE \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\"", "EXPAND_AS_DEFINED": "", "SKIP_FUNCTION_MACROS": "NO", "STRIP_CODE_COMMENTS": "NO", diff --git a/drivers/LowPowerTicker.h b/drivers/LowPowerTicker.h index 2df8ef34eb..9a4caf8218 100644 --- a/drivers/LowPowerTicker.h +++ b/drivers/LowPowerTicker.h @@ -20,7 +20,7 @@ #include "drivers/Ticker.h" #include "platform/NonCopyable.h" -#if defined (DEVICE_LOWPOWERTIMER) || defined(DOXYGEN_ONLY) +#if defined (DEVICE_LPTICKER) || defined(DOXYGEN_ONLY) #include "hal/lp_ticker_api.h" diff --git a/drivers/LowPowerTimeout.h b/drivers/LowPowerTimeout.h index 6aaefe2da8..ef96006738 100644 --- a/drivers/LowPowerTimeout.h +++ b/drivers/LowPowerTimeout.h @@ -18,7 +18,7 @@ #include "platform/platform.h" -#if defined (DEVICE_LOWPOWERTIMER) || defined(DOXYGEN_ONLY) +#if defined (DEVICE_LPTICKER) || defined(DOXYGEN_ONLY) #include "hal/lp_ticker_api.h" #include "drivers/LowPowerTicker.h" diff --git a/drivers/LowPowerTimer.h b/drivers/LowPowerTimer.h index e7e00377d9..20959d6721 100644 --- a/drivers/LowPowerTimer.h +++ b/drivers/LowPowerTimer.h @@ -20,7 +20,7 @@ #include "drivers/Timer.h" #include "platform/NonCopyable.h" -#if defined (DEVICE_LOWPOWERTIMER) || defined(DOXYGEN_ONLY) +#if defined (DEVICE_LPTICKER) || defined(DOXYGEN_ONLY) #include "hal/lp_ticker_api.h" diff --git a/drivers/Ticker.h b/drivers/Ticker.h index 646f8261c8..59a24dff43 100644 --- a/drivers/Ticker.h +++ b/drivers/Ticker.h @@ -71,7 +71,7 @@ public: // When low power ticker is in use, then do not disable deep-sleep. Ticker(const ticker_data_t *data) : TimerEvent(data), _function(0), _lock_deepsleep(true) { -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER _lock_deepsleep = (data != get_lp_ticker_data()); #endif } diff --git a/drivers/Timer.cpp b/drivers/Timer.cpp index f523974e6b..b8af5dc3d8 100644 --- a/drivers/Timer.cpp +++ b/drivers/Timer.cpp @@ -27,7 +27,7 @@ Timer::Timer() : _running(), _start(), _time(), _ticker_data(get_us_ticker_data( Timer::Timer(const ticker_data_t *data) : _running(), _start(), _time(), _ticker_data(data), _lock_deepsleep(true) { reset(); -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER _lock_deepsleep = (data != get_lp_ticker_data()); #endif } diff --git a/features/unsupported/tests/utest/lp_ticker/lp_ticker.cpp b/features/unsupported/tests/utest/lp_ticker/lp_ticker.cpp index cdac572144..61a569f9f1 100644 --- a/features/unsupported/tests/utest/lp_ticker/lp_ticker.cpp +++ b/features/unsupported/tests/utest/lp_ticker/lp_ticker.cpp @@ -21,7 +21,7 @@ /* Low power timer test. */ -#if !DEVICE_LOWPOWERTIMER +#if !DEVICE_LPTICKER #error This test unit requires low power to be defined for a target #endif diff --git a/hal/lp_ticker_api.h b/hal/lp_ticker_api.h index d1ce69a102..30a243edeb 100644 --- a/hal/lp_ticker_api.h +++ b/hal/lp_ticker_api.h @@ -21,7 +21,7 @@ #include "device.h" -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER #include "hal/ticker_api.h" @@ -30,10 +30,37 @@ extern "C" { #endif /** - * \defgroup hal_LpTicker Low Power Ticker Functions + * \defgroup hal_lp_ticker Low Power Ticker + * Low level interface to the low power ticker of a target + * + * # Defined behavior + * * Has a reported frequency between 4KHz and 64KHz - verified by ::lp_ticker_info_test + * * Has a counter that is at least 12 bits wide - verified by ::lp_ticker_info_test + * * Continues operating in deep sleep mode - verified by ::lp_ticker_deepsleep_test + * * All behavior defined by the @ref hal_ticker_shared "ticker specification" + * + * # Undefined behavior + * * See the @ref hal_ticker_shared "ticker specification" + * * Calling any function other than lp_ticker_init after calling lp_ticker_free + * + * # Potential bugs + * * Glitches due to ripple counter - Verified by ::lp_ticker_glitch_test + * + * @see hal_lp_ticker_tests + * * @{ */ +/** + * \defgroup hal_lp_ticker_tests Low Power Ticker tests + * Tests to validate the proper implementation of the low power ticker + * + * To run the low power ticker hal tests use the command: + * + * mbed test -t -m -n tests-mbed_hal-common_ticker*,tests-mbed_hal-lp_ticker* + * + */ + typedef void (*ticker_irq_handler_type)(const ticker_data_t *const); /** Set low power ticker IRQ handler @@ -42,7 +69,7 @@ typedef void (*ticker_irq_handler_type)(const ticker_data_t *const); * * @return previous ticker IRQ handler * - * @note by default IRQ handler is set to ticker_irq_handler() + * @note by default IRQ handler is set to ::ticker_irq_handler * @note this function is primarily for testing purposes and it's not required part of HAL implementation * */ @@ -63,39 +90,147 @@ void lp_ticker_irq_handler(void); /** Initialize the low power ticker * + * Initialize or re-initialize the ticker. This resets all the + * clocking and prescaler registers, along with disabling + * the compare interrupt. + * + * Pseudo Code: + * @code + * void lp_ticker_init() + * { + * // Enable clock gate so processor can read LPTMR registers + * POWER_CTRL |= POWER_CTRL_LPTMR_Msk; + * + * // Disable the timer and ensure it is powered down + * LPTMR_CTRL &= ~(LPTMR_CTRL_ENABLE_Msk | LPTMR_CTRL_COMPARE_ENABLE_Msk); + * + * // Configure divisors - no division necessary + * LPTMR_PRESCALE = 0; + * LPTMR_CTRL |= LPTMR_CTRL_ENABLE_Msk; + * + * // Install the interrupt handler + * NVIC_SetVector(LPTMR_IRQn, (uint32_t)lp_ticker_irq_handler); + * NVIC_EnableIRQ(LPTMR_IRQn); + * } + * @endcode */ void lp_ticker_init(void); -/** Read the current counter +/** Deinitialize the lower power ticker * - * @return The current timer's counter value in microseconds + * Powerdown the lp ticker in preparation for sleep, powerdown, or reset. + * + * After calling this function no other ticker functions should be called except + * lp_ticker_init(). Calling any function other than init after freeing is + * undefined. + * + * @note This function stops the ticker from counting. + */ +void lp_ticker_free(void); + +/** Read the current tick + * + * If no rollover has occurred, the seconds passed since lp_ticker_init() + * was called can be found by dividing the ticks returned by this function + * by the frequency returned by ::lp_ticker_get_info. + * + * @return The current timer's counter value in ticks + * + * Pseudo Code: + * @code + * uint32_t lp_ticker_read() + * { + * uint16_t count; + * uint16_t last_count; + * + * // Loop until the same tick is read twice since this + * // is ripple counter on a different clock domain. + * count = LPTMR_COUNT; + * do { + * last_count = count; + * count = LPTMR_COUNT; + * } while (last_count != count); + * + * return count; + * } + * @endcode */ uint32_t lp_ticker_read(void); /** Set interrupt for specified timestamp * - * @param timestamp The time in microseconds to be set + * @param timestamp The time in ticks to be set + * + * @note no special handling needs to be done for times in the past + * as the common timer code will detect this and call + * lp_ticker_fire_interrupt() if this is the case + * + * @note calling this function with timestamp of more than the supported + * number of bits returned by ::lp_ticker_get_info results in undefined + * behavior. + * + * Pseudo Code: + * @code + * void lp_ticker_set_interrupt(timestamp_t timestamp) + * { + * LPTMR_COMPARE = timestamp; + * LPTMR_CTRL |= LPTMR_CTRL_COMPARE_ENABLE_Msk; + * } + * @endcode */ void lp_ticker_set_interrupt(timestamp_t timestamp); /** Disable low power ticker interrupt * + * Pseudo Code: + * @code + * void lp_ticker_disable_interrupt(void) + * { + * // Disable the compare interrupt + * LPTMR_CTRL &= ~LPTMR_CTRL_COMPARE_ENABLE_Msk; + * } + * @endcode */ void lp_ticker_disable_interrupt(void); /** Clear the low power ticker interrupt * + * Pseudo Code: + * @code + * void lp_ticker_clear_interrupt(void) + * { + * // Write to the ICR (interrupt clear register) of the LPTMR + * LPTMR_ICR = LPTMR_ICR_COMPARE_Msk; + * } + * @endcode */ void lp_ticker_clear_interrupt(void); /** Set pending interrupt that should be fired right away. * - * The ticker should be initialized prior calling this function. + * Pseudo Code: + * @code + * void lp_ticker_fire_interrupt(void) + * { + * NVIC_SetPendingIRQ(LPTMR_IRQn); + * } + * @endcode */ void lp_ticker_fire_interrupt(void); /** Get frequency and counter bits of this ticker. * + * Pseudo Code: + * @code + * const ticker_info_t* lp_ticker_get_info() + * { + * static const ticker_info_t info = { + * 32768, // 32KHz + * 16 // 16 bit counter + * }; + * return &info; + * } + * @endcode */ const ticker_info_t* lp_ticker_get_info(void); diff --git a/hal/mbed_lp_ticker_api.c b/hal/mbed_lp_ticker_api.c index d9bfd866b1..020d36454e 100644 --- a/hal/mbed_lp_ticker_api.c +++ b/hal/mbed_lp_ticker_api.c @@ -15,7 +15,7 @@ */ #include "hal/lp_ticker_api.h" -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER void lp_ticker_set_interrupt_wrapper(timestamp_t timestamp); @@ -28,7 +28,7 @@ static const ticker_interface_t lp_interface = { .read = lp_ticker_read, .disable_interrupt = lp_ticker_disable_interrupt, .clear_interrupt = lp_ticker_clear_interrupt, -#if LOWPOWERTIMER_DELAY_TICKS > 0 +#if LPTICKER_DELAY_TICKS > 0 .set_interrupt = lp_ticker_set_interrupt_wrapper, #else .set_interrupt = lp_ticker_set_interrupt, diff --git a/hal/mbed_lp_ticker_wrapper.cpp b/hal/mbed_lp_ticker_wrapper.cpp index 1e2af74097..53817bf152 100644 --- a/hal/mbed_lp_ticker_wrapper.cpp +++ b/hal/mbed_lp_ticker_wrapper.cpp @@ -15,12 +15,12 @@ */ #include "hal/lp_ticker_api.h" -#if DEVICE_LOWPOWERTIMER && (LOWPOWERTIMER_DELAY_TICKS > 0) +#if DEVICE_LPTICKER && (LPTICKER_DELAY_TICKS > 0) #include "Timeout.h" #include "mbed_critical.h" -static const timestamp_t min_delta = LOWPOWERTIMER_DELAY_TICKS; +static const timestamp_t min_delta = LPTICKER_DELAY_TICKS; static bool init = false; static bool pending = false; @@ -108,7 +108,7 @@ static void set_interrupt_later() * Wrapper around lp_ticker_set_interrupt to prevent blocking * * Problems this function is solving: - * 1. Interrupt may not fire if set earlier than LOWPOWERTIMER_DELAY_TICKS low power clock cycles + * 1. Interrupt may not fire if set earlier than LPTICKER_DELAY_TICKS low power clock cycles * 2. Setting the interrupt back-to-back will block * * This wrapper function prevents lp_ticker_set_interrupt from being called diff --git a/hal/mbed_sleep_manager.c b/hal/mbed_sleep_manager.c index 6704ca542f..12cd7cfb00 100644 --- a/hal/mbed_sleep_manager.c +++ b/hal/mbed_sleep_manager.c @@ -34,13 +34,13 @@ static uint16_t deep_sleep_lock = 0U; static us_timestamp_t sleep_time = 0; static us_timestamp_t deep_sleep_time = 0; -#if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LOWPOWERTIMER) +#if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LPTICKER) static ticker_data_t *sleep_ticker = NULL; #endif static inline us_timestamp_t read_us(void) { -#if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LOWPOWERTIMER) +#if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LPTICKER) if (NULL == sleep_ticker) { sleep_ticker = (ticker_data_t *)get_lp_ticker_data(); } diff --git a/hal/mbed_ticker_api.c b/hal/mbed_ticker_api.c index 6a20006180..2dabd56a21 100644 --- a/hal/mbed_ticker_api.c +++ b/hal/mbed_ticker_api.c @@ -42,6 +42,14 @@ static void initialize(const ticker_data_t *ticker) frequency = 1000000; } + uint8_t frequency_shifts = 0; + for (uint8_t i = 31; i > 0; --i) { + if ((1 << i) == frequency) { + frequency_shifts = i; + break; + } + } + uint32_t bits = info->bits; if ((info->bits > 32) || (info->bits < 4)) { MBED_ASSERT(0); @@ -56,6 +64,7 @@ static void initialize(const ticker_data_t *ticker) ticker->queue->tick_last_read = ticker->interface->read(); ticker->queue->tick_remainder = 0; ticker->queue->frequency = frequency; + ticker->queue->frequency_shifts = frequency_shifts; ticker->queue->bitmask = ((uint64_t)1 << bits) - 1; ticker->queue->max_delta = max_delta; ticker->queue->max_delta_us = max_delta_us; @@ -125,14 +134,13 @@ static void update_present_time(const ticker_data_t *const ticker) // Optimized for 1MHz elapsed_us = elapsed_ticks; - } else if (32768 == queue->frequency) { - // Optimized for 32KHz - + } else if (0 != queue->frequency_shifts) { + // Optimized for frequencies divisible by 2 uint64_t us_x_ticks = elapsed_ticks * 1000000; - elapsed_us = us_x_ticks >> 15; + elapsed_us = us_x_ticks >> queue->frequency_shifts; // Update remainder - queue->tick_remainder += us_x_ticks - (elapsed_us << 15); + queue->tick_remainder += us_x_ticks - (elapsed_us << queue->frequency_shifts); if (queue->tick_remainder >= queue->frequency) { elapsed_us += 1; queue->tick_remainder -= queue->frequency; @@ -174,10 +182,10 @@ static timestamp_t compute_tick(const ticker_data_t *const ticker, us_timestamp_ if (delta > ticker->queue->max_delta) { delta = ticker->queue->max_delta; } - } else if (32768 == queue->frequency) { - // Optimized for 32KHz + } else if (0 != queue->frequency_shifts) { + // Optimized frequencies divisible by 2 - delta = (delta_us << 15) / 1000000; + delta = (delta_us << ticker->queue->frequency_shifts) / 1000000; if (delta > ticker->queue->max_delta) { delta = ticker->queue->max_delta; } diff --git a/hal/rtc_api.h b/hal/rtc_api.h index 5dc87eb529..b049087968 100644 --- a/hal/rtc_api.h +++ b/hal/rtc_api.h @@ -1,6 +1,3 @@ - -/** \addtogroup hal */ -/** @{*/ /* mbed Microcontroller Library * Copyright (c) 2006-2013 ARM Limited * @@ -16,13 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +/** \addtogroup hal */ +/** @{*/ + #ifndef MBED_RTC_API_H #define MBED_RTC_API_H #include "device.h" -#if DEVICE_RTC - #include #ifdef __cplusplus @@ -30,37 +29,150 @@ extern "C" { #endif /** - * \defgroup hal_rtc RTC hal functions + * \defgroup hal_rtc RTC hal + * + * The RTC hal provides a low level interface to the Real Time Counter (RTC) of a + * target. + * + * # Defined behaviour + * * The function ::rtc_init is safe to call repeatedly - Verified by test ::rtc_init_test. + * * RTC accuracy is at least 10% - Verified by test ::rtc_accuracy_test. + * * Init/free doesn't stop RTC from counting - Verified by test ::rtc_persist_test. + * * Software reset doesn't stop RTC from counting - Verified by test ::rtc_reset_test. + * * Sleep modes don't stop RTC from counting - Verified by test ::rtc_sleep_test. + * * Shutdown mode doesn't stop RTC from counting - Not verified. + * * The functions ::rtc_write/::rtc_read provides availability to set/get RTC time + * - Verified by test ::rtc_write_read_test. + * * The functions ::rtc_isenabled returns 1 if the RTC is counting and the time has been set, + * 0 otherwise - Verified by test ::rtc_enabled_test. + * + * # Undefined behaviour + * * Calling any function other than ::rtc_init before the initialisation of the RTC + * + * # Potential bugs + * * Incorrect overflow handling - Verified by ::rtc_range_test + * * Glitches due to ripple counter - Verified by ::rtc_glitch_test + * + * @see hal_rtc_tests + * * @{ */ +/** + * \defgroup hal_rtc_tests RTC hal tests + * The RTC test validate proper implementation of the RTC hal. + * + * To run the RTC hal tests use the command: + * + * mbed test -t -m -n tests-mbed_hal-rtc* + */ + + /** Initialize the RTC peripheral * + * Powerup the RTC in perpetration for access. This function must be called + * before any other RTC functions ares called. This does not change the state + * of the RTC. It just enables access to it. + * + * @note This function is safe to call repeatedly - Tested by ::rtc_init_test + * + * Example Implementation Pseudo Code: + * @code + * void rtc_init() + * { + * // Enable clock gate so processor can read RTC registers + * POWER_CTRL |= POWER_CTRL_RTC_Msk; + * + * // See if the RTC is already setup + * if (!(RTC_STATUS & RTC_STATUS_COUNTING_Msk)) { + * + * // Setup the RTC clock source + * RTC_CTRL |= RTC_CTRL_CLK32_Msk; + * } + * } + * @endcode */ void rtc_init(void); /** Deinitialize RTC * - * TODO: The function is not used by rtc api in mbed-drivers. + * Powerdown the RTC in preparation for sleep, powerdown or reset. That should only + * affect the CPU domain and not the time keeping logic. + * After this function is called no other RTC functions should be called + * except for ::rtc_init. + * + * @note This function does not stop the RTC from counting - Tested by ::rtc_persist_test + * + * Example Implementation Pseudo Code: + * @code + * void rtc_free() + * { + * // Disable clock gate since processor no longer needs to read RTC registers + * POWER_CTRL &= ~POWER_CTRL_RTC_Msk; + * } + * @endcode */ void rtc_free(void); -/** Get the RTC enable status +/** Check if the RTC has the time set and is counting * - * @retval 0 disabled - * @retval 1 enabled + * @retval 0 The time reported by the RTC is not valid + * @retval 1 The time has been set the RTC is counting + * + * Example Implementation Pseudo Code: + * @code + * int rtc_isenabled() + * { + * if (RTC_STATUS & RTC_STATUS_COUNTING_Msk) { + * return 1; + * } else { + * return 0; + * } + * } + * @endcode */ int rtc_isenabled(void); /** Get the current time from the RTC peripheral * - * @return The current time + * @return The current time in seconds + * + * @note Some RTCs are not synchronized with the main clock. If + * this is the case with your RTC then you must read the RTC time + * in a loop to prevent reading the wrong time due to a glitch. + * The test ::rtc_glitch_test is intended to catch this bug. + * + * Example implementation for an unsynchronized ripple counter: + * @code + * time_t rtc_read() + * { + * uint32_t val; + * uint32_t last_val; + * + * // Loop until the same value is read twice + * val = RTC_SECONDS; + * do { + * last_val = val; + * val = RTC_SECONDS; + * } while (last_val != val); + * + * return (time_t)val; + * } + * @endcode */ time_t rtc_read(void); -/** Set the current time to the RTC peripheral +/** Write the current time in seconds to the RTC peripheral * - * @param t The current time to be set + * @param t The current time to be set in seconds. + * + * Example Implementation Pseudo Code: + * @code + * void rtc_write(time_t t) + * { + * RTC_SECONDS = t; + * } + * @endcode */ void rtc_write(time_t t); @@ -72,6 +184,4 @@ void rtc_write(time_t t); #endif -#endif - /** @}*/ diff --git a/hal/sleep_api.h b/hal/sleep_api.h index 8747459cb9..88c3875005 100644 --- a/hal/sleep_api.h +++ b/hal/sleep_api.h @@ -27,37 +27,70 @@ extern "C" { #endif +/** + * \defgroup hal_sleep sleep hal requirements + * Low level interface to the sleep mode of a target. + * + * # Defined behaviour + * + * * Sleep mode + * * wake-up time should be less than 10 us - Verified by sleep_usticker_test(). + * * the processor can be woken up by any internal peripheral interrupt - Verified by sleep_usticker_test(). + * * all peripherals operate as in run mode - not verified. + * * the processor can be woken up by external pin interrupt - not verified. + * * Deep sleep + * * the wake-up time should be less than 10 ms - Verified by deepsleep_lpticker_test(). + * * lp ticker should wake up a target from this mode - Verified by deepsleep_lpticker_test(). + * * RTC should wake up a target from this mode - not verified. + * * an external interrupt on a pin should wake up a target from this mode - not verified. + * * a watchdog timer should wake up a target from this mode - not verified. + * * High-speed clocks are turned off - Verified by deepsleep_high_speed_clocks_turned_off_test(). + * * RTC keeps time - Verified by rtc_sleep_test(). + * + * # Undefined behaviour + * + * * peripherals aside from RTC, GPIO and lp ticker result in undefined behaviour in deep sleep. + * @{ + */ + +/** + * \defgroup hal_sleep_tests sleep hal tests + * The sleep HAL tests ensure driver conformance to defined behaviour. + * + * To run the sleep hal tests use the command: + * + * mbed test -t -m -n tests-mbed_hal-sleep* + * + */ + /** Send the microcontroller to sleep * - * The processor is setup ready for sleep, and sent to sleep using __WFI(). In this mode, the + * The processor is setup ready for sleep, and sent to sleep. In this mode, the * system clock to the core is stopped until a reset or an interrupt occurs. This eliminates * dynamic power used by the processor, memory systems and buses. The processor, peripheral and * memory state are maintained, and the peripherals continue to work and can generate interrupts. * * The processor can be woken up by any internal peripheral interrupt or external pin interrupt. * - * @note - * The mbed interface semihosting is disconnected as part of going to sleep, and can not be restored. - * Flash re-programming and the USB serial port will remain active, but the mbed program will no longer be - * able to access the LocalFileSystem + * The wake-up time shall be less than 10 us. + * */ void hal_sleep(void); /** Send the microcontroller to deep sleep * * This processor is setup ready for deep sleep, and sent to sleep using __WFI(). This mode - * has the same sleep features as sleep plus it powers down peripherals and clocks. All state - * is still maintained. + * has the same sleep features as sleep plus it powers down peripherals and high frequency clocks. + * All state is still maintained. * - * The processor can only be woken up by an external interrupt on a pin or a watchdog timer. + * The processor can only be woken up by low power ticker, RTC, an external interrupt on a pin or a watchdog timer. * - * @note - * The mbed interface semihosting is disconnected as part of going to sleep, and can not be restored. - * Flash re-programming and the USB serial port will remain active, but the mbed program will no longer be - * able to access the LocalFileSystem + * The wake-up time shall be less than 10 ms. */ void hal_deepsleep(void); +/**@}*/ + #ifdef __cplusplus } #endif @@ -66,4 +99,4 @@ void hal_deepsleep(void); #endif -/** @}*/ +/**@}*/ diff --git a/hal/ticker_api.h b/hal/ticker_api.h index 605fa235ed..8b2c9ffccb 100644 --- a/hal/ticker_api.h +++ b/hal/ticker_api.h @@ -80,6 +80,7 @@ typedef struct { uint64_t tick_remainder; /**< Ticks that have not been added to base_time */ us_timestamp_t present_time; /**< Store the timestamp used for present time */ bool initialized; /**< Indicate if the instance is initialized */ + uint8_t frequency_shifts; /**< If frequency is a value of 2^n, this is n, otherwise 0 */ } ticker_event_queue_t; /** Ticker's data structure diff --git a/hal/us_ticker_api.h b/hal/us_ticker_api.h index f880a55564..3b40805b9b 100644 --- a/hal/us_ticker_api.h +++ b/hal/us_ticker_api.h @@ -27,10 +27,82 @@ extern "C" { #endif /** - * \defgroup hal_UsTicker Microseconds Ticker Functions + * \defgroup hal_us_ticker Microsecond Ticker + * Low level interface to the microsecond ticker of a target + * + * # Defined behavior + * * Has a reported frequency between 250KHz and 8MHz - Verified by test ::us_ticker_info_test + * * Has a counter that is at least 16 bits wide - Verified by test ::us_ticker_info_test + * * All behavior defined by the @ref hal_ticker_shared "ticker specification" + * + * # Undefined behavior + * * See the @ref hal_ticker_shared "ticker specification" + * + * @see hal_us_ticker_tests + * * @{ */ +/** + * \defgroup hal_us_ticker_tests Microsecond Ticker tests + * Tests to validate the proper implementation of the microsecond ticker + * + * To run the microsecond ticker hal tests use the command: + * + * mbed test -t -m -n tests-mbed_hal-common_ticker*,tests-mbed_hal-us_ticker* + * + * @see hal_ticker_tests + * + */ + +/** + * \defgroup hal_ticker_shared Ticker Hal + * Low level interface to the ticker of a target + * + * # Defined behavior + * * The function ticker_init is safe to call repeatedly - Verified by test ::ticker_init_test + * * The function ticker_init allows the ticker to keep counting and disables the ticker interrupt - Verified by test ::ticker_init_test + * * Ticker frequency is non-zero and counter is at least 8 bits - Verified by ::ticker_info_test + * * The ticker rolls over at (1 << bits) and continues counting starting from 0 - Verified by ::ticker_overflow_test + * * The ticker counts at the specified frequency +- 10% - Verified by ::ticker_frequency_test + * * The ticker increments by 1 each tick - Verified by ::ticker_increment_test + * * The ticker interrupt fires only when the ticker times increments to or past the value set by ticker_set_interrupt. + * Verified by ::ticker_interrupt_test and ::ticker_past_test + * * It is safe to call ticker_set_interrupt repeatedly before the handler is called - Verified by ::ticker_repeat_reschedule_test + * * The function ticker_fire_interrupt causes ticker_irq_handler to be called immediately from interrupt context - + * Verified by ::ticker_fire_now_test + * * The ticker operations ticker_read, ticker_clear_interrupt, ticker_set_interrupt and ticker_fire_interrupt + * take less than 20us to complete - Verified by ::ticker_speed_test + * + * # Undefined behavior + * * Calling any function other than ticker_init before the initialization of the ticker + * * Whether ticker_irq_handler is called a second time if the time wraps and matches the value set by ticker_set_interrupt again + * * Calling ticker_set_interrupt with a value that has more than the supported number of bits + * * Calling any function other than us_ticker_init after calling us_ticker_free + * + * # Potential bugs + * * Drift due to reschedule - Verified by ::ticker_repeat_reschedule_test + * * Incorrect overflow handling of timers - Verified by ::ticker_overflow_test + * * Interrupting at a time of 0 - Verified by ::ticker_overflow_test + * * Interrupt triggered more than once - Verified by ::ticker_interrupt_test + * + * @ingroup hal_us_ticker + * @ingroup hal_lp_ticker + */ + +/** + * \defgroup hal_ticker_tests Ticker Tests + * Tests to validate the proper implementation of a ticker + * + * To run the ticker hal tests use the command: + * + * mbed test -t -m -n tests-mbed_hal-common_ticker* + * + * @ingroup hal_us_ticker + * @ingroup hal_lp_ticker + */ + + typedef void (*ticker_irq_handler_type)(const ticker_data_t *const); /** Set ticker IRQ handler @@ -39,7 +111,7 @@ typedef void (*ticker_irq_handler_type)(const ticker_data_t *const); * * @return previous ticker IRQ handler * - * @note by default IRQ handler is set to ticker_irq_handler() + * @note by default IRQ handler is set to ::ticker_irq_handler * @note this function is primarily for testing purposes and it's not required part of HAL implementation * */ @@ -47,7 +119,7 @@ ticker_irq_handler_type set_us_ticker_irq_handler(ticker_irq_handler_type ticker /** Get ticker's data * - * @return The low power ticker data + * @return The microsecond ticker data */ const ticker_data_t* get_us_ticker_data(void); @@ -61,39 +133,141 @@ void us_ticker_irq_handler(void); /** Initialize the ticker * + * Initialize or re-initialize the ticker. This resets all the + * clocking and prescaler registers, along with disabling + * the compare interrupt. + * + * @note Initialization properties tested by ::ticker_init_test + * + * Pseudo Code: + * @code + * void us_ticker_init() + * { + * // Enable clock gate so processor can read TIMER registers + * POWER_CTRL |= POWER_CTRL_TIMER_Msk; + * + * // Disable the timer and ensure it is powered down + * TIMER_CTRL &= ~(TIMER_CTRL_ENABLE_Msk | TIMER_CTRL_COMPARE_ENABLE_Msk); + * + * // Configure divisors + * uint32_t prescale = SystemCoreClock / 1000000; + * TIMER_PRESCALE = prescale - 1; + * TIMER_CTRL |= TIMER_CTRL_ENABLE_Msk; + * + * // Install the interrupt handler + * NVIC_SetVector(TIMER_IRQn, (uint32_t)us_ticker_irq_handler); + * NVIC_EnableIRQ(TIMER_IRQn); + * } + * @endcode */ void us_ticker_init(void); +/** Deinitialize the us ticker + * + * Powerdown the us ticker in preparation for sleep, powerdown, or reset. + * + * After this function is called, no other ticker functions should be called + * except us_ticker_init(), calling any function other than init is undefined. + * + * @note This function stops the ticker from counting. + */ +void us_ticker_free(void); + /** Read the current counter * - * @return The current timer's counter value in microseconds + * Read the current counter value without performing frequency conversions. + * If no rollover has occurred, the seconds passed since us_ticker_init() + * was called can be found by dividing the ticks returned by this function + * by the frequency returned by ::us_ticker_get_info. + * + * @return The current timer's counter value in ticks + * + * Pseudo Code: + * @code + * uint32_t us_ticker_read() + * { + * return TIMER_COUNT; + * } + * @endcode */ uint32_t us_ticker_read(void); /** Set interrupt for specified timestamp * - * @param timestamp The time in microseconds to be set + * @param timestamp The time in ticks to be set + * + * @note no special handling needs to be done for times in the past + * as the common timer code will detect this and call + * us_ticker_fire_interrupt() if this is the case + * + * @note calling this function with timestamp of more than the supported + * number of bits returned by ::us_ticker_get_info results in undefined + * behavior. + * + * Pseudo Code: + * @code + * void us_ticker_set_interrupt(timestamp_t timestamp) + * { + * TIMER_COMPARE = timestamp; + * TIMER_CTRL |= TIMER_CTRL_COMPARE_ENABLE_Msk; + * } + * @endcode */ void us_ticker_set_interrupt(timestamp_t timestamp); /** Disable us ticker interrupt * + * Pseudo Code: + * @code + * void us_ticker_disable_interrupt(void) + * { + * // Disable the compare interrupt + * TIMER_CTRL &= ~TIMER_CTRL_COMPARE_ENABLE_Msk; + * } + * @endcode */ void us_ticker_disable_interrupt(void); /** Clear us ticker interrupt * + * Pseudo Code: + * @code + * void us_ticker_clear_interrupt(void) + * { + * // Write to the ICR (interrupt clear register) of the TIMER + * TIMER_ICR = TIMER_ICR_COMPARE_Msk; + * } + * @endcode */ void us_ticker_clear_interrupt(void); /** Set pending interrupt that should be fired right away. - * + * * The ticker should be initialized prior calling this function. + * + * Pseudo Code: + * @code + * void us_ticker_fire_interrupt(void) + * { + * NVIC_SetPendingIRQ(TIMER_IRQn); + * } + * @endcode */ void us_ticker_fire_interrupt(void); /** Get frequency and counter bits of this ticker. * + * Pseudo Code: + * @code + * const ticker_info_t* us_ticker_get_info() + * { + * static const ticker_info_t info = { + * 1000000, // 1 MHz + * 32 // 32 bit counter + * }; + * return &info; + * } + * @endcode */ const ticker_info_t* us_ticker_get_info(void); diff --git a/platform/mbed_rtc_time.cpp b/platform/mbed_rtc_time.cpp index cb8449cf3f..f259513c59 100644 --- a/platform/mbed_rtc_time.cpp +++ b/platform/mbed_rtc_time.cpp @@ -29,7 +29,7 @@ static int (*_rtc_isenabled)(void) = rtc_isenabled; static time_t (*_rtc_read)(void) = rtc_read; static void (*_rtc_write)(time_t t) = rtc_write; -#elif DEVICE_LOWPOWERTIMER +#elif DEVICE_LPTICKER #include "drivers/LowPowerTimer.h" @@ -63,13 +63,13 @@ static int (*_rtc_isenabled)(void) = _rtc_lpticker_isenabled; static time_t (*_rtc_read)(void) = _rtc_lpticker_read; static void (*_rtc_write)(time_t t) = _rtc_lpticker_write; -#else /* DEVICE_LOWPOWERTIMER */ +#else /* DEVICE_LPTICKER */ static void (*_rtc_init)(void) = NULL; static int (*_rtc_isenabled)(void) = NULL; static time_t (*_rtc_read)(void) = NULL; static void (*_rtc_write)(time_t t) = NULL; -#endif /* DEVICE_LOWPOWERTIMER */ +#endif /* DEVICE_LPTICKER */ #ifdef __cplusplus extern "C" { diff --git a/platform/mbed_stats.c b/platform/mbed_stats.c index eb0c5e5e35..beaac014ce 100644 --- a/platform/mbed_stats.c +++ b/platform/mbed_stats.c @@ -12,7 +12,7 @@ #warning Statistics are currently not supported without the rtos. #endif -#if defined(MBED_CPU_STATS_ENABLED) && (!defined(DEVICE_LOWPOWERTIMER) || !defined(DEVICE_SLEEP)) +#if defined(MBED_CPU_STATS_ENABLED) && (!defined(DEVICE_LPTICKER) || !defined(DEVICE_SLEEP)) #warning CPU statistics are not supported without low power timer support. #endif @@ -20,7 +20,7 @@ void mbed_stats_cpu_get(mbed_stats_cpu_t *stats) { MBED_ASSERT(stats != NULL); memset(stats, 0, sizeof(mbed_stats_cpu_t)); -#if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LOWPOWERTIMER) && defined(DEVICE_SLEEP) +#if defined(MBED_CPU_STATS_ENABLED) && defined(DEVICE_LPTICKER) && defined(DEVICE_SLEEP) stats->uptime = mbed_uptime(); stats->idle_time = mbed_time_idle(); stats->sleep_time = mbed_time_sleep(); diff --git a/rtos/TARGET_CORTEX/SysTimer.cpp b/rtos/TARGET_CORTEX/SysTimer.cpp index 1eece6c501..8d09532bf7 100644 --- a/rtos/TARGET_CORTEX/SysTimer.cpp +++ b/rtos/TARGET_CORTEX/SysTimer.cpp @@ -21,7 +21,7 @@ */ #include "rtos/TARGET_CORTEX/SysTimer.h" -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER #include "hal/lp_ticker_api.h" #include "mbed_critical.h" diff --git a/rtos/TARGET_CORTEX/SysTimer.h b/rtos/TARGET_CORTEX/SysTimer.h index 267714c907..dd6b30cf33 100644 --- a/rtos/TARGET_CORTEX/SysTimer.h +++ b/rtos/TARGET_CORTEX/SysTimer.h @@ -22,7 +22,7 @@ #ifndef MBED_SYS_TIMER_H #define MBED_SYS_TIMER_H -#if defined(DEVICE_LOWPOWERTIMER) || defined(DOXYGEN_ONLY) +#if defined(DEVICE_LPTICKER) || defined(DOXYGEN_ONLY) #include "platform/NonCopyable.h" #include "drivers/TimerEvent.h" diff --git a/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp b/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp index 3d0e6a12ab..83db8253aa 100644 --- a/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp +++ b/rtos/TARGET_CORTEX/mbed_rtx_idle.cpp @@ -34,7 +34,7 @@ extern "C" { using namespace mbed; -#ifdef MBED_TICKLESS +#if (defined(MBED_TICKLESS) && defined(DEVICE_LPTICKER)) #include "rtos/TARGET_CORTEX/SysTimer.h" @@ -129,7 +129,7 @@ static void default_idle_hook(void) core_util_critical_section_exit(); } -#endif // MBED_TICKLESS +#endif // (defined(MBED_TICKLESS) && defined(DEVICE_LPTICKER)) static void (*idle_hook_fptr)(void) = &default_idle_hook; diff --git a/targets/TARGET_ARM_SSG/TARGET_BEETLE/lp_ticker.c b/targets/TARGET_ARM_SSG/TARGET_BEETLE/lp_ticker.c index 50d3039029..e96379af47 100644 --- a/targets/TARGET_ARM_SSG/TARGET_BEETLE/lp_ticker.c +++ b/targets/TARGET_ARM_SSG/TARGET_BEETLE/lp_ticker.c @@ -30,7 +30,7 @@ static uint32_t lp_ticker_overflows_delta = 0; /* lp_ticker Overflow limit */ static uint32_t lp_ticker_overflow_limit = 0; -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER /** * Interrupt Handler */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/lp_ticker.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/lp_ticker.c index 26d12b83a5..6458408610 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/lp_ticker.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/lp_ticker.c @@ -25,6 +25,7 @@ #include "lp_ticker_api.h" #include "platform_devices.h" +#if DEVICE_LPTICKER /** * \brief Calculate clocks to us * @@ -111,3 +112,5 @@ void TIMER1_IRQHandler(void) { cmsdk_ticker_irq_handler(&timer_data); } + +#endif diff --git a/targets/TARGET_Analog_Devices/TARGET_ADUCM302X/TARGET_ADUCM3029/api/us_ticker.c b/targets/TARGET_Analog_Devices/TARGET_ADUCM302X/TARGET_ADUCM3029/api/us_ticker.c index 553c0237b0..631536700d 100755 --- a/targets/TARGET_Analog_Devices/TARGET_ADUCM302X/TARGET_ADUCM3029/api/us_ticker.c +++ b/targets/TARGET_Analog_Devices/TARGET_ADUCM302X/TARGET_ADUCM3029/api/us_ticker.c @@ -56,7 +56,7 @@ void us_ticker_irq_handler(void); static int us_ticker_inited = 0; -static ADI_TMR_CONFIG tmrConfig, tmr2Config; +static ADI_TMR_CONFIG tmrConfig; static volatile uint32_t Upper_count = 0, largecnt = 0; @@ -201,14 +201,14 @@ static void event_timer() cnt = 65536u - cnt; } - tmr2Config.nLoad = cnt; - tmr2Config.nAsyncLoad = cnt; - adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP2, &tmr2Config); + tmrConfig.nLoad = cnt; + tmrConfig.nAsyncLoad = cnt; + adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP2, &tmrConfig); adi_tmr_Enable(ADI_TMR_DEVICE_GP2, true); } else { - tmr2Config.nLoad = 65535u; - tmr2Config.nAsyncLoad = 65535u; - adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP2, &tmr2Config); + tmrConfig.nLoad = 65535u; + tmrConfig.nAsyncLoad = 65535u; + adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP2, &tmrConfig); adi_tmr_Enable(ADI_TMR_DEVICE_GP2, true); } } @@ -249,6 +249,8 @@ static void GP2CallbackFunction(void *pCBParam, uint32_t Event, void * pArg) void us_ticker_init(void) { if (us_ticker_inited) { + // Disable ticker interrupt on reinitialization + adi_tmr_Enable(ADI_TMR_DEVICE_GP2, false); return; } @@ -283,15 +285,15 @@ void us_ticker_init(void) adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP1, &tmrConfig); /* Configure GP2 for doing event counts */ - tmr2Config.bCountingUp = true; - tmr2Config.bPeriodic = true; - tmr2Config.ePrescaler = ADI_TMR_PRESCALER_256; // TMR2 at 26MHz/256 - tmr2Config.eClockSource = ADI_TMR_CLOCK_PCLK; // TMR source is PCLK (most examples use HFOSC) - tmr2Config.nLoad = 0; - tmr2Config.nAsyncLoad = 0; - tmr2Config.bReloading = false; - tmr2Config.bSyncBypass = true; // Allow x1 prescale - adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP2, &tmr2Config); + tmrConfig.bCountingUp = true; + tmrConfig.bPeriodic = true; + tmrConfig.ePrescaler = ADI_TMR_PRESCALER_256; // TMR2 at 26MHz/256 + tmrConfig.eClockSource = ADI_TMR_CLOCK_PCLK; // TMR source is PCLK (most examples use HFOSC) + tmrConfig.nLoad = 0; + tmrConfig.nAsyncLoad = 0; + tmrConfig.bReloading = false; + tmrConfig.bSyncBypass = true; // Allow x1 prescale + adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP2, &tmrConfig); /*------------------------- GP TIMER ENABLE ------------------------------*/ @@ -328,14 +330,15 @@ void us_ticker_clear_interrupt(void) void us_ticker_set_interrupt(timestamp_t timestamp) { - + // if timestamp is already past, do not set interrupt + if ((timestamp + 10) <= us_ticker_read()) return; /* timestamp is when interrupt should fire. * * This MUST not be called if another timer event is currently enabled. * */ calc_event_counts(timestamp); // use timestamp to calculate largecnt to control number of timer interrupts - tmr2Config.ePrescaler = ADI_TMR_PRESCALER_256; // TMR2 at 26MHz/256 + tmrConfig.ePrescaler = ADI_TMR_PRESCALER_256; // TMR2 at 26MHz/256 event_timer(); // uses largecnt to initiate timer interrupts } @@ -348,7 +351,7 @@ void us_ticker_set_interrupt(timestamp_t timestamp) void us_ticker_fire_interrupt(void) { largecnt = 1; // set a minimal interval so interrupt fire immediately - tmr2Config.ePrescaler = ADI_TMR_PRESCALER_1; // TMR2 at 26MHz/1 + tmrConfig.ePrescaler = ADI_TMR_PRESCALER_1; // TMR2 at 26MHz/1 event_timer(); // enable the timer and interrupt } diff --git a/targets/TARGET_Analog_Devices/TARGET_ADUCM302X/TARGET_ADUCM3029/bsp/rtc/adi_rtc.c b/targets/TARGET_Analog_Devices/TARGET_ADUCM302X/TARGET_ADUCM3029/bsp/rtc/adi_rtc.c index 3efa64d911..f19d06bcfa 100755 --- a/targets/TARGET_Analog_Devices/TARGET_ADUCM302X/TARGET_ADUCM3029/bsp/rtc/adi_rtc.c +++ b/targets/TARGET_Analog_Devices/TARGET_ADUCM302X/TARGET_ADUCM3029/bsp/rtc/adi_rtc.c @@ -6,7 +6,7 @@ * @date: $Date: 2016-07-26 13:09:22 -0400 (Tue, 26 Jul 2016) $ *---------------------------------------------------------------------------- * -Copyright (c) 2010-2016 Analog Devices, Inc. +Copyright (c) 2010-2018 Analog Devices, Inc. All rights reserved. @@ -56,7 +56,7 @@ POSSIBILITY OF SUCH DAMAGE. /*! \cond PRIVATE */ #if defined(__ADUCM302x__) -#define BITP_CLKG_OSC_CTL_LFX_FAIL_STA BITP_CLKG_OSC_CTL_LFX_FAIL_STAT +#define BITP_CLKG_OSC_CTL_LFX_FAIL_STA BITP_CLKG_OSC_CTL_LFX_FAIL_STAT #endif /* __ADUCM302x__ */ #if defined ( __ADSPGCC__ ) @@ -93,27 +93,27 @@ POSSIBILITY OF SUCH DAMAGE. * Pm150 (rule 20.2): the names of standard library macros, objects and function shall not be reused * Needed to implement the functions here. * -* Pm129 (rule 12.7): bitwise operations shall not be performed on signed integer types +* Pm129 (rule 12.7): bitwise operations shall not be performed on signed integer types * The rule makes an exception for valid expressions. * -* Pm029: this bitwise operation is in a boolean context - logical operators should not be confused with bitwise operators +* Pm029: this bitwise operation is in a boolean context - logical operators should not be confused with bitwise operators * The rule is suppressed as the bitwise and logical operators are being used correctly and are not being confused * * Pm126: if the bitwise operators ~ and << are applied to an operand of underlying type 'unsigned char' or 'unsigned short', the result shall be immediately cast to the underlying type of the operand * The behaviour as described is correct * -* Pm031: bitwise operations shall not be performed on signed integer types +* Pm031: bitwise operations shall not be performed on signed integer types * Device drivers often require bit banging on MMRs that are defined as signed */ #pragma diag_suppress=Pm011,Pm123,Pm073,Pm143,Pm050,Pm109,Pm150,Pm140,Pm129,Pm029,Pm126,Pm031 #endif /* __ICCARM__ */ /*! \endcond */ - + #include - + /*! \cond PRIVATE */ @@ -132,13 +132,13 @@ static uint16_t cr0 = 0u, cr1 = 0u, cr3oc = 0u, cr4oc = 0u, cr2ic = 0u, cr5ocs = struct xxx { uint16_t *cr; - uint16_t bitPositionl; + uint16_t bitPositionl; } Interrupt_Details[ADI_RTC_NUM_INTERRUPTS] = { - { &cr0, BITP_RTC_CR0_ALMINTEN }, - { &cr0, BITP_RTC_CR0_MOD60ALMINTEN }, + { &cr0, BITP_RTC_CR0_ALMINTEN }, + { &cr0, BITP_RTC_CR0_MOD60ALMINTEN }, { &cr0, BITP_RTC_CR0_ISOINTEN }, { &cr0, BITP_RTC_CR0_WPNDERRINTEN }, { &cr0, BITP_RTC_CR0_WSYNCINTEN }, @@ -158,17 +158,17 @@ Interrupt_Details[ADI_RTC_NUM_INTERRUPTS] = { &cr2ic, BITP_RTC_CR2IC_IC4IRQEN }, { &cr2ic, BITP_CLKG_OSC_CTL_LFX_FAIL_STA }, { &cr3oc, BITM_RTC_CR3SS_SS4FEIRQEN}, - { &cr3oc, BITM_RTC_CR3SS_SS3FEIRQEN}, - { &cr3oc, BITM_RTC_CR3SS_SS2FEIRQEN}, - { &cr3oc, BITM_RTC_CR3SS_SS1FEIRQEN}, - { &cr4oc, BITP_RTC_CR4SS_SS4MSKEN}, - { &cr4oc, BITP_RTC_CR4SS_SS3MSKEN}, - { &cr4oc, BITP_RTC_CR4SS_SS2MSKEN}, - { &cr4oc, BITP_RTC_CR4SS_SS1MSKEN}, - { &cr5ocs, BITP_RTC_CR5SSS_SS3SMPMTCHIRQEN}, - { &cr5ocs, BITP_RTC_CR5SSS_SS2SMPMTCHIRQEN}, + { &cr3oc, BITM_RTC_CR3SS_SS3FEIRQEN}, + { &cr3oc, BITM_RTC_CR3SS_SS2FEIRQEN}, + { &cr3oc, BITM_RTC_CR3SS_SS1FEIRQEN}, + { &cr4oc, BITP_RTC_CR4SS_SS4MSKEN}, + { &cr4oc, BITP_RTC_CR4SS_SS3MSKEN}, + { &cr4oc, BITP_RTC_CR4SS_SS2MSKEN}, + { &cr4oc, BITP_RTC_CR4SS_SS1MSKEN}, + { &cr5ocs, BITP_RTC_CR5SSS_SS3SMPMTCHIRQEN}, + { &cr5ocs, BITP_RTC_CR5SSS_SS2SMPMTCHIRQEN}, { &cr5ocs, BITP_RTC_CR5SSS_SS1SMPMTCHIRQEN} - + }; #elif defined(__ADUCM302x__) @@ -178,13 +178,13 @@ static uint16_t cr0 = 0u, cr1 = 0u, cr3oc = 0u, cr4oc = 0u, cr2ic = 0u; struct xxx { uint16_t *cr; - uint16_t bitPositionl; + uint16_t bitPositionl; } Interrupt_Details[ADI_RTC_NUM_INTERRUPTS] = { - { &cr0, BITP_RTC_CR0_ALMINTEN }, - { &cr0, BITP_RTC_CR0_MOD60ALMINTEN }, + { &cr0, BITP_RTC_CR0_ALMINTEN }, + { &cr0, BITP_RTC_CR0_MOD60ALMINTEN }, { &cr0, BITP_RTC_CR0_ISOINTEN }, { &cr0, BITP_RTC_CR0_WPNDERRINTEN }, { &cr0, BITP_RTC_CR0_WSYNCINTEN }, @@ -198,7 +198,7 @@ Interrupt_Details[ADI_RTC_NUM_INTERRUPTS] = { &cr2ic, BITP_RTC_CR2IC_IC0IRQEN }, { &cr2ic, BITP_RTC_CR2IC_IC2IRQEN }, { &cr2ic, BITP_RTC_CR2IC_IC3IRQEN }, - { &cr2ic, BITP_RTC_CR2IC_IC4IRQEN }, + { &cr2ic, BITP_RTC_CR2IC_IC4IRQEN }, }; #else #error RTC is not ported for this processor @@ -291,31 +291,32 @@ ADI_RTC_RESULT adi_rtc_Open( memset(pDeviceMemory,0,MemorySize); /* initialize device data entries */ pDevice->pRTCRegs = aRTCDeviceInfo[DeviceNumber].pRTCRegs; - + PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) pDevice->pRTCRegs->CR0 = 0u; pDevice->pRTCRegs->CR1 = 0u; - - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDSR0) pDevice->pRTCRegs->SR0 = ADI_RTC_SR3_IRQ_STATUS_MASK; - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCSR0) - + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCSR0) + /* Preserve RTC counter value while re-initialization pDevice->pRTCRegs->CNT0 = 0u; pDevice->pRTCRegs->CNT1 = 0u; - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCNT0) - + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCNT0) + */ /* local pointer to instance data */ aRTCDeviceInfo[DeviceNumber].hDevice = pDevice; pDevice->pDeviceInfo = &aRTCDeviceInfo[DeviceNumber]; - /* Use static configuration to initialize the RTC */ + /* Do not use static configuration to + preserve RTC counter value while re-initialization rtc_init(pDevice,&aRTCConfig[DeviceNumber]); - + */ /* store handle at application handle pointer */ *phDevice = pDevice; pDevice->eIRQn = aRTCDeviceInfo[DeviceNumber].eIRQn; @@ -358,7 +359,7 @@ ADI_RTC_RESULT adi_rtc_Close(ADI_RTC_HANDLE const hDevice) pDevice->pfCallback = NULL; pDevice->pCBParam = NULL; pDevice->cbWatch = 0u; - + pDevice->pDeviceInfo->hDevice = NULL; return ADI_RTC_SUCCESS; } @@ -412,9 +413,9 @@ ADI_RTC_RESULT adi_rtc_EnableAlarm(ADI_RTC_HANDLE const hDevice, bool bEnable) } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); /* set/clear RTC alarm enable */ @@ -427,9 +428,9 @@ ADI_RTC_RESULT adi_rtc_EnableAlarm(ADI_RTC_HANDLE const hDevice, bool bEnable) pDevice->pRTCRegs->CR0 &= (uint16_t)(~BITM_RTC_CR0_ALMEN); } ADI_EXIT_CRITICAL_REGION(); - - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) return ADI_RTC_SUCCESS; } @@ -481,7 +482,7 @@ ADI_RTC_RESULT adi_rtc_EnableMod60Alarm(ADI_RTC_HANDLE const hDevice, bool bEnab #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) ADI_INT_STATUS_ALLOC(); @@ -496,9 +497,9 @@ ADI_RTC_RESULT adi_rtc_EnableMod60Alarm(ADI_RTC_HANDLE const hDevice, bool bEnab pDevice->pRTCRegs->CR0 &= (uint16_t)(~BITM_RTC_CR0_MOD60ALMEN); } ADI_EXIT_CRITICAL_REGION(); - - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) return ADI_RTC_SUCCESS; } @@ -538,9 +539,9 @@ ADI_RTC_RESULT adi_rtc_Enable(ADI_RTC_HANDLE const hDevice, bool bEnable) } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); @@ -554,10 +555,10 @@ ADI_RTC_RESULT adi_rtc_Enable(ADI_RTC_HANDLE const hDevice, bool bEnable) pDevice->pRTCRegs->CR0 &=(uint16_t)(~BITM_RTC_CR0_CNTEN); } ADI_EXIT_CRITICAL_REGION(); - - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) - + + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + return ADI_RTC_SUCCESS; } @@ -576,7 +577,7 @@ ADI_RTC_RESULT adi_rtc_Enable(ADI_RTC_HANDLE const hDevice, bool bEnable) * - #ADI_RTC_INVALID_HANDLE [D] Invalid device handle parameter. * * Enable/disable RTC interrupt as well as manage global NVIC enable/disable for the RTC. - * Input parameter \a Interrupts is a interrupt ID of type #ADI_RTC_INT_TYPE designating the + * Input parameter \a Interrupts is a interrupt ID of type #ADI_RTC_INT_TYPE designating the * interrupt to be enabled or disabled. The interrupt parameter may be zero, which will then simply * manage the NVIC RTC enable and leave the individual RTC interrupt enables unchanged. * Input parameter \a bEnable controls whether to enable or disable the designated set of interrupts. @@ -597,28 +598,28 @@ ADI_RTC_RESULT adi_rtc_EnableInterrupts (ADI_RTC_HANDLE const hDevice, ADI_RTC_I return eResult; } if( (pDevice->pRTCRegs == pADI_RTC0) &&(((uint16_t)((ADI_RTC_MOD60ALM_INT | ADI_RTC_ISO_DONE_INT| - ADI_RTC_COUNT_INT | + ADI_RTC_COUNT_INT | ADI_RTC_TRIM_INT | ADI_RTC_COUNT_ROLLOVER_INT | ADI_RTC_MOD60_ROLLOVER_INT )) & (uint16_t)Interrupts) != 0u)) { return(ADI_RTC_INVALID_PARAM); } - + assert(sizeof(Interrupt_Details)/sizeof(Interrupt_Details[0]) == ADI_RTC_NUM_INTERRUPTS); #endif - + /* TODO - more sync for new registers */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) PEND_BEFORE_WRITE(SR2,BITM_RTC_SR2_WPNDCR1MIR) - + uint8_t ndx = 0u; - cr0 = 0u; cr1 = 0u; cr3oc = 0u; cr4oc = 0u; cr2ic = 0u; - -#if defined(__ADUCM4x50__) + cr0 = 0u; cr1 = 0u; cr3oc = 0u; cr4oc = 0u; cr2ic = 0u; + +#if defined(__ADUCM4x50__) cr5ocs = 0u; #endif /* __ADUCM4x50__ */ - + while( Interrupts ) { if( 0u != (Interrupts & 1u) ) @@ -638,11 +639,11 @@ ADI_RTC_RESULT adi_rtc_EnableInterrupts (ADI_RTC_HANDLE const hDevice, ADI_RTC_I pDevice->pRTCRegs->CR3SS |= cr3oc; pDevice->pRTCRegs->CR4SS |= cr4oc; pDevice->pRTCRegs->CR2IC |= cr2ic; - -#if defined(__ADUCM4x50__) + +#if defined(__ADUCM4x50__) pDevice->pRTCRegs->CR5SSS |= cr5ocs; -#endif /* __ADUCM4x50__ */ - } +#endif /* __ADUCM4x50__ */ + } else { pDevice->pRTCRegs->CR0 &= ~cr0; @@ -650,12 +651,12 @@ ADI_RTC_RESULT adi_rtc_EnableInterrupts (ADI_RTC_HANDLE const hDevice, ADI_RTC_I pDevice->pRTCRegs->CR3SS &= ~cr3oc; pDevice->pRTCRegs->CR4SS &= ~cr4oc; pDevice->pRTCRegs->CR2IC &= ~cr2ic; -#if defined(__ADUCM4x50__) +#if defined(__ADUCM4x50__) pDevice->pRTCRegs->CR5SSS &= ~cr5ocs; -#endif /* __ADUCM4x50__ */ +#endif /* __ADUCM4x50__ */ } - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) - SYNC_AFTER_WRITE(SR2,BITM_RTC_SR2_WSYNCCR1MIR) + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + SYNC_AFTER_WRITE(SR2,BITM_RTC_SR2_WSYNCCR1MIR) return ADI_RTC_SUCCESS; } @@ -697,9 +698,9 @@ ADI_RTC_RESULT adi_rtc_EnableTrim (ADI_RTC_HANDLE const hDevice, bool bEnable) return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); /* set/clear trim enable bit(s) in control register */ @@ -713,16 +714,16 @@ ADI_RTC_RESULT adi_rtc_EnableTrim (ADI_RTC_HANDLE const hDevice, bool bEnable) } ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + return ADI_RTC_SUCCESS; } /*! * @brief Enable input capture for the specified channel. * * @param[in] hDevice Device handle obtained from adi_rtc_Open(). - * @param[in] eInpChannel Specify input compare channel. + * @param[in] eInpChannel Specify input compare channel. * @param[in] bEnable Flag for enabling RTC input capture for specified channel. * - true Enable input capture. * - false Disable input capture. @@ -743,9 +744,9 @@ ADI_RTC_RESULT adi_rtc_EnableInputCapture (ADI_RTC_HANDLE const hDevice,ADI_RTC_ return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDCR2IC) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); /* set/clear trim input capture enable for specified channel*/ @@ -759,9 +760,9 @@ ADI_RTC_RESULT adi_rtc_EnableInputCapture (ADI_RTC_HANDLE const hDevice,ADI_RTC_ } ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR2IC) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR2IC) + return ADI_RTC_SUCCESS; } @@ -789,9 +790,9 @@ ADI_RTC_RESULT adi_rtc_EnableOverwriteSnapshot (ADI_RTC_HANDLE const hDevice, bo return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDCR2IC) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); /* set/clear trim input capture enable for specified channel*/ @@ -805,9 +806,9 @@ ADI_RTC_RESULT adi_rtc_EnableOverwriteSnapshot (ADI_RTC_HANDLE const hDevice, bo } ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR2IC) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR2IC) + return ADI_RTC_SUCCESS; } @@ -815,7 +816,7 @@ ADI_RTC_RESULT adi_rtc_EnableOverwriteSnapshot (ADI_RTC_HANDLE const hDevice, bo * @brief Set input capture polarity for the specified channel. * * @param[in] hDevice Device handle obtained from adi_rtc_Open(). - * @param[in] eInpChannel Specify which input capture channel. + * @param[in] eInpChannel Specify which input capture channel. * @param[in] bEnable Flag for selecting RTC input capture polarity. * - false channel uses a *high-to-low* transition on its GPIO pin to signal an input capture event * - true channel uses a *low-to-high* transition on its GPIO pin to signal an input capture event. @@ -837,9 +838,9 @@ ADI_RTC_RESULT adi_rtc_SetInputCapturePolarity (ADI_RTC_HANDLE const hDevice,ADI return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDCR2IC) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); /* set/clear trim input capture enable for specified channel*/ @@ -853,9 +854,9 @@ ADI_RTC_RESULT adi_rtc_SetInputCapturePolarity (ADI_RTC_HANDLE const hDevice,ADI } ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR2IC) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR2IC) + return ADI_RTC_SUCCESS; } /*! @@ -883,9 +884,9 @@ ADI_RTC_RESULT adi_rtc_EnableSensorStrobeOutput (ADI_RTC_HANDLE const hDevice, A return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDCR3SS) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); /* set/clear Sensor Strobe enable for specified channel*/ @@ -899,9 +900,9 @@ ADI_RTC_RESULT adi_rtc_EnableSensorStrobeOutput (ADI_RTC_HANDLE const hDevice, A } ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR3SS) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR3SS) + return ADI_RTC_SUCCESS; } @@ -930,9 +931,9 @@ ADI_RTC_RESULT adi_rtc_EnableAutoReload(ADI_RTC_HANDLE const hDevice, ADI_RTC_SS return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDCR4SS) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); /* set/clear auto reload enable options */ @@ -944,18 +945,18 @@ ADI_RTC_RESULT adi_rtc_EnableAutoReload(ADI_RTC_HANDLE const hDevice, ADI_RTC_SS case ADI_RTC_SS_CHANNEL_1: pDevice->pRTCRegs->CR4SS |= BITM_RTC_CR4SS_SS1ARLEN; break; -#if defined(__ADUCM4x50__) +#if defined(__ADUCM4x50__) case ADI_RTC_SS_CHANNEL_2: pDevice->pRTCRegs->CR4SS |= BITM_RTC_CR4SS_SS2ARLEN; break; case ADI_RTC_SS_CHANNEL_3: pDevice->pRTCRegs->CR4SS |= BITM_RTC_CR4SS_SS3ARLEN; break; -#endif /* __ADUCM4x50__ */ +#endif /* __ADUCM4x50__ */ default: return ADI_RTC_FAILURE; } - + } else { @@ -964,36 +965,36 @@ ADI_RTC_RESULT adi_rtc_EnableAutoReload(ADI_RTC_HANDLE const hDevice, ADI_RTC_SS case ADI_RTC_SS_CHANNEL_1: pDevice->pRTCRegs->CR4SS &= (uint16_t)~BITM_RTC_CR4SS_SS1ARLEN; break; -#if defined(__ADUCM4x50__) +#if defined(__ADUCM4x50__) case ADI_RTC_SS_CHANNEL_2: pDevice->pRTCRegs->CR4SS &= (uint16_t)~BITM_RTC_CR4SS_SS2ARLEN; break; case ADI_RTC_SS_CHANNEL_3: pDevice->pRTCRegs->CR4SS &= (uint16_t)~BITM_RTC_CR4SS_SS3ARLEN; break; -#endif /* __ADUCM4x50__ */ +#endif /* __ADUCM4x50__ */ default: return ADI_RTC_FAILURE; } } ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR4SS) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR4SS) + return ADI_RTC_SUCCESS; } /*! * @brief Set auto reload value for the given Sensor Strobe channel. * * @param[in] hDevice Device handle obtained from adi_rtc_Open(). - * @param[in] eSSChannel Sensor Strobe channel for which auto reload to be set. + * @param[in] eSSChannel Sensor Strobe channel for which auto reload to be set. * @param[in] nValue Auto reload value to be set. * * @return Status * - #ADI_RTC_SUCCESS Call completed successfully. * - #ADI_RTC_INVALID_HANDLE [D] Invalid device handle parameter. - * + * * */ ADI_RTC_RESULT adi_rtc_SetAutoReloadValue(ADI_RTC_HANDLE const hDevice, ADI_RTC_SS_CHANNEL eSSChannel, uint16_t nValue) @@ -1007,53 +1008,53 @@ ADI_RTC_RESULT adi_rtc_SetAutoReloadValue(ADI_RTC_HANDLE const hDevice, ADI_RTC_ return eResult; } #endif - + switch( eSSChannel ) { case ADI_RTC_SS_CHANNEL_1: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS1) pDevice->pRTCRegs->SS1 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS1) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS1) break; -#if defined(__ADUCM4x50__) +#if defined(__ADUCM4x50__) case ADI_RTC_SS_CHANNEL_2: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS2) pDevice->pRTCRegs->SS2 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS2) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS2) break; - + case ADI_RTC_SS_CHANNEL_3: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS3) pDevice->pRTCRegs->SS3 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS3) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS3) break; case ADI_RTC_SS_CHANNEL_4: PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS4) pDevice->pRTCRegs->SS4 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS4) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS4) break; #endif /* __ADUCM4x50__ */ - + default: return ADI_RTC_FAILURE; } - + return ADI_RTC_SUCCESS; } /*! * @brief Enable or disable thermometer-code masking for the given Sensor Strobe Channel. * * @param[in] hDevice Device handle obtained from adi_rtc_Open(). - * @param[in] eSSChannel Sensor Strobe channel for which thermometer-code masking to be enabled or disabled. + * @param[in] eSSChannel Sensor Strobe channel for which thermometer-code masking to be enabled or disabled. * @param[in] bEnable Flag to enable or disable masking for the given Sensor Strobe channel. * - true Enable masking . * - false Disable masking. @@ -1074,11 +1075,11 @@ ADI_RTC_RESULT adi_rtc_EnableSensorStrobeChannelMask(ADI_RTC_HANDLE const hDevic return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5, BITM_RTC_SR5_WPENDCR4SS) - + ADI_INT_STATUS_ALLOC(); - ADI_ENTER_CRITICAL_REGION(); + ADI_ENTER_CRITICAL_REGION(); /* set/clear auto reload enable options */ if (bEnable) { @@ -1090,9 +1091,9 @@ ADI_RTC_RESULT adi_rtc_EnableSensorStrobeChannelMask(ADI_RTC_HANDLE const hDevic } ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR4SS) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR4SS) + return ADI_RTC_SUCCESS; } @@ -1100,7 +1101,7 @@ ADI_RTC_RESULT adi_rtc_EnableSensorStrobeChannelMask(ADI_RTC_HANDLE const hDevic * @brief To set channel mask for the given Sensor Strobe channel. * * @param[in] hDevice Device handle obtained from adi_rtc_Open(). - * @param[in] eSSChannel Sensor Strobe Channel for which the mask to be set. + * @param[in] eSSChannel Sensor Strobe Channel for which the mask to be set. * @param[in] nMask Channel Mask to be set for Sensor Strobe channel. * * @return Status @@ -1120,37 +1121,37 @@ ADI_RTC_RESULT adi_rtc_SetSensorStrobeChannelMask(ADI_RTC_HANDLE const hDevice, return eResult; } #endif - + switch( eSSChannel ) { case ADI_RTC_SS_CHANNEL_1: MaskPos = (uint16_t)BITP_RTC_SSMSK_SS1MSK; break; -#if defined(__ADUCM4x50__) +#if defined(__ADUCM4x50__) case ADI_RTC_SS_CHANNEL_2: MaskPos = (uint16_t)BITP_RTC_SSMSK_SS2MSK; break; - + case ADI_RTC_SS_CHANNEL_3: MaskPos = (uint16_t)BITP_RTC_SSMSK_SS3MSK; break; case ADI_RTC_SS_CHANNEL_4: - MaskPos = (uint16_t)BITP_RTC_SSMSK_SS4MSK; + MaskPos = (uint16_t)BITP_RTC_SSMSK_SS4MSK; break; -#endif /* __ADUCM4x50__ */ +#endif /* __ADUCM4x50__ */ default: return ADI_RTC_INVALID_CHANNEL; } - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5, BITM_RTC_SR5_WPENDSSMSK) - + pDevice->pRTCRegs->SSMSK = ((uint16_t)nMask & 0xFu) << MaskPos; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4, BITM_RTC_SR4_WSYNCSSMSK) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4, BITM_RTC_SR4_WSYNCSSMSK) + return ADI_RTC_SUCCESS; } @@ -1189,7 +1190,7 @@ ADI_RTC_RESULT adi_rtc_GetAlarm (ADI_RTC_HANDLE hDevice, uint32_t *pAlarm) } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDALM0|BITM_RTC_SR1_WPNDALM1)) /* disable interrupts during paired read */ @@ -1232,7 +1233,7 @@ ADI_RTC_RESULT adi_rtc_GetAlarmEx (ADI_RTC_HANDLE hDevice, float *pAlarm) } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDALM0|BITM_RTC_SR1_WPNDALM1)) nPreScale = (pDevice->pRTCRegs->CR1&BITM_RTC_CR1_PRESCALE2EXP)>>BITP_RTC_CR1_PRESCALE2EXP; /* disable interrupts during paired read */ @@ -1278,7 +1279,7 @@ ADI_RTC_RESULT adi_rtc_GetControl (ADI_RTC_HANDLE hDevice, ADI_RTC_CONTROL_REGIS return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) switch(eRegister) @@ -1325,7 +1326,7 @@ ADI_RTC_RESULT adi_rtc_GetCount(ADI_RTC_HANDLE const hDevice, uint32_t *pCount) } #endif - /* Wait till previously posted write to couunt Register to complete */ + /* Wait till previously posted write to couunt Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDCNT0|BITM_RTC_SR1_WPNDCNT1)) /* disable interrupts during paired read */ @@ -1367,7 +1368,7 @@ ADI_RTC_RESULT adi_rtc_GetCountEx(ADI_RTC_HANDLE const hDevice, float *pfCount) return eResult; } #endif - /* Wait till previously posted write to couunt Register to complete */ + /* Wait till previously posted write to couunt Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDCNT0|BITM_RTC_SR1_WPNDCNT1)) nPrescale = (pDevice->pRTCRegs->CR1&BITM_RTC_CR1_PRESCALE2EXP)>>BITP_RTC_CR1_PRESCALE2EXP; /* disable interrupts during paired read */ @@ -1375,7 +1376,7 @@ ADI_RTC_RESULT adi_rtc_GetCountEx(ADI_RTC_HANDLE const hDevice, float *pfCount) nCount = (uint32_t)pDevice->pRTCRegs->CNT1 << 16u; nCount |= pDevice->pRTCRegs->CNT0; nTemp = (1lu<pRTCRegs->CNT2/(float)(nTemp); + fFraction = (float)pDevice->pRTCRegs->CNT2/(float)(nTemp); NVIC_EnableIRQ((IRQn_Type)pDevice->eIRQn); *pfCount = (float)nCount+ fFraction; @@ -1410,14 +1411,14 @@ ADI_RTC_RESULT adi_rtc_GetCountRegs(ADI_RTC_HANDLE const hDevice, uint32_t *pnCo return eResult; } #endif - /* Wait till previously posted write to couunt Register to complete */ + /* Wait till previously posted write to couunt Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDCNT0|BITM_RTC_SR1_WPNDCNT1)) /* disable interrupts during paired read */ NVIC_DisableIRQ(pDevice->eIRQn); nCount = (uint32_t)pDevice->pRTCRegs->CNT1 << 16u; nCount |= pDevice->pRTCRegs->CNT0; *pnCount= nCount; - *pfCount = (uint32_t)pDevice->pRTCRegs->CNT2; + *pfCount = (uint32_t)pDevice->pRTCRegs->CNT2; NVIC_EnableIRQ((IRQn_Type)pDevice->eIRQn); return ADI_RTC_SUCCESS; } @@ -1459,7 +1460,7 @@ ADI_RTC_RESULT adi_rtc_GetTrim (ADI_RTC_HANDLE hDevice, ADI_RTC_TRIM_VALUE *peTr } #endif - /* Wait till previously posted write to couunt Register to complete */ + /* Wait till previously posted write to couunt Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDTRM); *peTrim =(ADI_RTC_TRIM_VALUE)(pDevice->pRTCRegs->TRM & BITM_RTC_TRM_VALUE); @@ -1486,7 +1487,7 @@ ADI_RTC_RESULT adi_rtc_GetTrim (ADI_RTC_HANDLE hDevice, ADI_RTC_TRIM_VALUE *peTr ADI_RTC_RESULT adi_rtc_GetSensorStrobeValue(ADI_RTC_HANDLE const hDevice, ADI_RTC_SS_CHANNEL eSSChannel, uint16_t *pValue) { ADI_RTC_DEVICE *pDevice = hDevice; - + #ifdef ADI_DEBUG ADI_RTC_RESULT eResult; if((eResult = ValidateHandle(pDevice)) != ADI_RTC_SUCCESS) @@ -1500,37 +1501,37 @@ ADI_RTC_RESULT adi_rtc_GetSensorStrobeValue(ADI_RTC_HANDLE const hDevice, ADI_RT PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS1) *pValue = pDevice->pRTCRegs->SS1; break; -#if defined(__ADUCM4x50__) +#if defined(__ADUCM4x50__) case ADI_RTC_SS_CHANNEL_2: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS2) *pValue = pDevice->pRTCRegs->SS2; break; - + case ADI_RTC_SS_CHANNEL_3: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS3) *pValue = pDevice->pRTCRegs->SS3; break; - + case ADI_RTC_SS_CHANNEL_4: PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS4) *pValue = pDevice->pRTCRegs->SS4; break; -#endif /* __ADUCM4x50__ */ +#endif /* __ADUCM4x50__ */ default: return ADI_RTC_FAILURE; } - - - + + + return ADI_RTC_SUCCESS; } /*! * @brief Set Sensor Strobe value for the given Sensor Strobe channel. * * @param[in] hDevice Device handle obtained from adi_rtc_Open(). - * @param[in] eSSChannel Sensor Strobe Channel. + * @param[in] eSSChannel Sensor Strobe Channel. * @param[out] nValue Sensor Strobe value to be set for the given Sensor Strobe channel . * * @return Status @@ -1553,46 +1554,46 @@ ADI_RTC_RESULT adi_rtc_SetSensorStrobeValue(ADI_RTC_HANDLE const hDevice, ADI_RT return eResult; } #endif - + switch( eSSChannel ) { case ADI_RTC_SS_CHANNEL_1: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS1) pDevice->pRTCRegs->SS1 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS1) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS1) break; - -#if defined(__ADUCM4x50__) + +#if defined(__ADUCM4x50__) case ADI_RTC_SS_CHANNEL_2: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS2) pDevice->pRTCRegs->SS2 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS2) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS2) break; - + case ADI_RTC_SS_CHANNEL_3: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS3) pDevice->pRTCRegs->SS3 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS3) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS3) break; - + case ADI_RTC_SS_CHANNEL_4: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS4) pDevice->pRTCRegs->SS4 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS4) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS4) break; -#endif /* __ADUCM4x50__ */ +#endif /* __ADUCM4x50__ */ default: return ADI_RTC_FAILURE; } - + return ADI_RTC_SUCCESS; } @@ -1600,14 +1601,14 @@ ADI_RTC_RESULT adi_rtc_SetSensorStrobeValue(ADI_RTC_HANDLE const hDevice, ADI_RT * @brief Get input capture value for specified input channel. * * @param[in] hDevice Device handle obtained from adi_rtc_Open(). - * @param[in] eChannel Specify which input capture channel. + * @param[in] eChannel Specify which input capture channel. * @param[out] pValue Pointer to application memory where the input capture value to be written. * * @return Status * - #ADI_RTC_SUCCESS Call completed successfully. * - #ADI_RTC_INVALID_HANDLE [D] Invalid device handle parameter. * - #ADI_RTC_INVALID_PARAM [D] NULL pointer for input parameter. - * - #ADI_RTC_INVALID_CHANNEL [D] Input channel-0 is not valid for this operation since + * - #ADI_RTC_INVALID_CHANNEL [D] Input channel-0 is not valid for this operation since * channel-0 can provide precise (47bit) capture value. * * @@ -1621,7 +1622,7 @@ ADI_RTC_RESULT adi_rtc_GetInputCaptureValue(ADI_RTC_HANDLE const hDevice,ADI_RTC { ADI_RTC_DEVICE *pDevice = hDevice; ADI_RTC_RESULT eResult= ADI_RTC_SUCCESS; - + #ifdef ADI_DEBUG if((eResult = ValidateHandle(pDevice)) != ADI_RTC_SUCCESS) { @@ -1636,11 +1637,11 @@ ADI_RTC_RESULT adi_rtc_GetInputCaptureValue(ADI_RTC_HANDLE const hDevice,ADI_RTC case ADI_RTC_INPUT_CHANNEL_3: *pValue = pDevice->pRTCRegs->IC3; break; - + case ADI_RTC_INPUT_CHANNEL_4: *pValue = pDevice->pRTCRegs->IC4; break; - default: + default: eResult = ADI_RTC_INVALID_CHANNEL; break; } @@ -1798,7 +1799,7 @@ ADI_RTC_RESULT adi_rtc_GetWriteSyncStatus (ADI_RTC_HANDLE const hDevice, ADI_RT return eResult; } #endif - /* Wait till previously posted write to couunt Register to complete */ + /* Wait till previously posted write to couunt Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDSR0); /* get the value */ @@ -1848,7 +1849,7 @@ ADI_RTC_RESULT adi_rtc_SetAlarm (ADI_RTC_HANDLE const hDevice, uint32_t nAlarm) } #endif - /* Wait till previously posted write to Alram Register to complete */ + /* Wait till previously posted write to Alram Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDALM0|BITM_RTC_SR1_WPNDALM1)) ADI_INT_STATUS_ALLOC(); @@ -1858,9 +1859,9 @@ ADI_RTC_RESULT adi_rtc_SetAlarm (ADI_RTC_HANDLE const hDevice, uint32_t nAlarm) pDevice->pRTCRegs->ALM1 = (uint16_t)(nAlarm >> 16); pDevice->pRTCRegs->ALM2 = 0u; ADI_EXIT_CRITICAL_REGION(); - - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,(BITM_RTC_SR0_WSYNCALM0|BITM_RTC_SR0_WSYNCALM1)) + + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,(BITM_RTC_SR0_WSYNCALM0|BITM_RTC_SR0_WSYNCALM1)) return ADI_RTC_SUCCESS; } @@ -1908,8 +1909,8 @@ ADI_RTC_RESULT adi_rtc_SetPreScale(ADI_RTC_HANDLE const hDevice, uint8_t nPreSc nTemp |= (uint16_t)((uint16_t)nPreScale << BITP_RTC_CR1_PRESCALE2EXP); pDevice->pRTCRegs->CR1 = nTemp; ADI_EXIT_CRITICAL_REGION(); - - SYNC_AFTER_WRITE(SR2,BITM_RTC_SR2_WSYNCCR1MIR) + + SYNC_AFTER_WRITE(SR2,BITM_RTC_SR2_WSYNCCR1MIR) return ADI_RTC_SUCCESS; } /*! @@ -1948,7 +1949,7 @@ ADI_RTC_RESULT adi_rtc_SetMod60AlarmPeriod(ADI_RTC_HANDLE const hDevice, uint8_t #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) ADI_INT_STATUS_ALLOC(); @@ -1959,8 +1960,8 @@ ADI_RTC_RESULT adi_rtc_SetMod60AlarmPeriod(ADI_RTC_HANDLE const hDevice, uint8_t nTemp |= (uint16_t)((uint16_t)nPeriod << BITP_RTC_CR0_MOD60ALM); pDevice->pRTCRegs->CR0 = nTemp; ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) return ADI_RTC_SUCCESS; } @@ -2005,7 +2006,7 @@ ADI_RTC_RESULT adi_rtc_SetAlarmEx(ADI_RTC_HANDLE const hDevice, float fAlarm) #endif - /* Wait till previously posted write to Alarm Register to complete */ + /* Wait till previously posted write to Alarm Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDALM0|BITM_RTC_SR1_WPNDALM1)) nPreScale = (pDevice->pRTCRegs->CR1&BITM_RTC_CR1_PRESCALE2EXP)>>BITP_RTC_CR1_PRESCALE2EXP; ADI_INT_STATUS_ALLOC(); @@ -2018,8 +2019,8 @@ ADI_RTC_RESULT adi_rtc_SetAlarmEx(ADI_RTC_HANDLE const hDevice, float fAlarm) fFraction = (fAlarm - (float)nAlarm) *(float)(nTemp); pDevice->pRTCRegs->ALM2 = (uint16_t)(fFraction); ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Alarm Register to take effect */ - SYNC_AFTER_WRITE(SR0,(BITM_RTC_SR0_WSYNCALM0|BITM_RTC_SR0_WSYNCALM1)) + /* Wait till write to Alarm Register to take effect */ + SYNC_AFTER_WRITE(SR0,(BITM_RTC_SR0_WSYNCALM0|BITM_RTC_SR0_WSYNCALM1)) return ADI_RTC_SUCCESS; } @@ -2056,7 +2057,7 @@ ADI_RTC_RESULT adi_rtc_SetControlRegister(ADI_RTC_HANDLE const hDevice,ADI_RTC_C return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) switch(eRegister) @@ -2070,9 +2071,9 @@ ADI_RTC_RESULT adi_rtc_SetControlRegister(ADI_RTC_HANDLE const hDevice,ADI_RTC_C default: return(ADI_RTC_FAILURE); } - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + return ADI_RTC_SUCCESS; } @@ -2165,7 +2166,7 @@ ADI_RTC_RESULT adi_rtc_SetCount (ADI_RTC_HANDLE const hDevice, uint32_t nCount) } #endif - /* Wait till previously posted write to count Register to complete */ + /* Wait till previously posted write to count Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDCNT0|BITM_RTC_SR1_WPNDCNT1)) ADI_INT_STATUS_ALLOC(); @@ -2175,8 +2176,8 @@ ADI_RTC_RESULT adi_rtc_SetCount (ADI_RTC_HANDLE const hDevice, uint32_t nCount) pDevice->pRTCRegs->CNT1 = (uint16_t)(nCount >> 16); ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to count Register to take effect */ - SYNC_AFTER_WRITE(SR0,(BITM_RTC_SR0_WSYNCCNT0|BITM_RTC_SR0_WSYNCCNT1)) + /* Wait till write to count Register to take effect */ + SYNC_AFTER_WRITE(SR0,(BITM_RTC_SR0_WSYNCCNT0|BITM_RTC_SR0_WSYNCCNT1)) return ADI_RTC_SUCCESS; } @@ -2259,13 +2260,13 @@ ADI_RTC_RESULT adi_rtc_SetTrim(ADI_RTC_HANDLE const hDevice, ADI_RTC_TRIM_INTER #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDTRM) pDevice->pRTCRegs->TRM = (uint16_t)trm; - - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCTRM) + + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCTRM) return ADI_RTC_SUCCESS; } @@ -2318,7 +2319,7 @@ ADI_RTC_RESULT adi_rtc_SynchronizeAllWrites (ADI_RTC_HANDLE const hDevice) /*! \cond PRIVATE */ /* - * @brief Initializes the device using static configuration + * @brief Initializes the device using static configuration * * @param[in] pDevice Pointer to RTC device . pConfig Pointer to static configuration device structure. @@ -2327,16 +2328,16 @@ ADI_RTC_RESULT adi_rtc_SynchronizeAllWrites (ADI_RTC_HANDLE const hDevice) static void rtc_init(ADI_RTC_DEVICE *pDevice,ADI_RTC_CONFIG *pConfig) { - + /* FIXME - static init is even more now */ - + /* Control register -0 which controls all main stream activity of RTC0 */ pDevice->pRTCRegs->CR0 = pConfig->CR0; - /* Control register -1 which is granularity of RTC control register */ + /* Control register -1 which is granularity of RTC control register */ pDevice->pRTCRegs->CR1 = pConfig->CR1; - /*CNT0 contains the lower 16 bits of the RTC counter */ + /*CNT0 contains the lower 16 bits of the RTC counter */ pDevice->pRTCRegs->CNT0 = pConfig->CNT0; - /*CNT1 contains the lower 16 bits of the RTC counter */ + /*CNT1 contains the lower 16 bits of the RTC counter */ pDevice->pRTCRegs->CNT1 = pConfig->CNT1; /* ALM0 contains the lower 16 bits of the Alarm register */ pDevice->pRTCRegs->ALM0 = pConfig->ALM0; @@ -2352,13 +2353,13 @@ static void rtc_init(ADI_RTC_DEVICE *pDevice,ADI_RTC_CONFIG *pConfig) pDevice->pRTCRegs->CR4SS = pConfig->CR4SS; pDevice->pRTCRegs->SSMSK = pConfig->SSMSK; pDevice->pRTCRegs->SS1 = pConfig->SS1; -#if defined(__ADUCM4x50__) +#if defined(__ADUCM4x50__) pDevice->pRTCRegs->CR5SSS = pConfig->CR5SSS; pDevice->pRTCRegs->CR6SSS = pConfig->CR6SSS; pDevice->pRTCRegs->CR7SSS = pConfig->CR7SSS; pDevice->pRTCRegs->GPMUX0 = pConfig->GPMUX0; pDevice->pRTCRegs->GPMUX1 = pConfig->GPMUX1; -#endif /* __ADUCM4x50__ */ +#endif /* __ADUCM4x50__ */ } } @@ -2367,7 +2368,7 @@ static void rtc_init(ADI_RTC_DEVICE *pDevice,ADI_RTC_CONFIG *pConfig) /*! @brief RTC device driver interrupt handler. Overrides weakly-bound default interrupt handler in _startup.c. */ void RTC0_Int_Handler(void) { - ISR_PROLOG(); + ISR_PROLOG(); uint16_t nIntSrc0, nIntSrc2, nIntSrc3; uint32_t fired = 0u, enables = 0u; ADI_RTC_DEVICE *pDevice = aRTCDeviceInfo[0].hDevice; @@ -2406,7 +2407,7 @@ void RTC0_Int_Handler(void) fired |= ADI_RTC_WRITE_PENDERR_INT; } } - + /* CR1 SR2 */ enables = (uint32_t)pDevice->pRTCRegs->CR1 & ADI_RTC_INT_ENA_MASK_CR1; nIntSrc2 = pDevice->pRTCRegs->SR2 & ADI_RTC_INT_SOURCE_MASK_SR2; @@ -2433,13 +2434,13 @@ void RTC0_Int_Handler(void) fired |= ADI_RTC_COUNT_INT; } } - + /* CR3OC, CR2IC SR3*/ enables = pDevice->pRTCRegs->CR3SS & (uint16_t)ADI_RTC_INT_ENA_MASK_CR3SS; nIntSrc3 = pDevice->pRTCRegs->SR3 & ADI_RTC_SR3_IRQ_STATUS_MASK; if( nIntSrc3 && enables ) { -#if defined(__ADUCM4x50__) +#if defined(__ADUCM4x50__) if( (enables & BITM_RTC_CR3SS_SS4IRQEN) && (nIntSrc3 & BITM_RTC_SR3_SS4IRQ)) { fired |= ADI_RTC_SENSOR_STROBE_CH4_INT; @@ -2453,13 +2454,13 @@ void RTC0_Int_Handler(void) fired |= ADI_RTC_SENSOR_STROBE_CH2_INT; } #endif /* __ADUCM4x50__ */ - + if( (enables & BITM_RTC_CR3SS_SS1IRQEN) && (nIntSrc3 & BITM_RTC_SR3_SS1IRQ)) { fired |= ADI_RTC_SENSOR_STROBE_CH1_INT; } - -#if defined(__ADUCM4x50__) + +#if defined(__ADUCM4x50__) if( (enables & BITM_RTC_CR3SS_SS4FEIRQEN) && (nIntSrc3 & BITM_RTC_SR3_SS4FEIRQ)) { fired |= ADI_RTC_RTCSS4_FE_INT; @@ -2476,7 +2477,7 @@ void RTC0_Int_Handler(void) { fired |= ADI_RTC_RTCSS1_FE_INT; } -#endif /* __ADUCM4x50__ */ +#endif /* __ADUCM4x50__ */ } enables = pDevice->pRTCRegs->CR3SS & (uint16_t)ADI_RTC_INT_ENA_MASK_CR2IC; if( nIntSrc3 && enables ) @@ -2498,8 +2499,8 @@ void RTC0_Int_Handler(void) fired |= ADI_RTC_INPUT_CAPTURE_CH0_INT; } } - - + + if (pDevice->pfCallback != NULL) { /* forward to the user if he is watching this interrupt */ @@ -2509,18 +2510,18 @@ void RTC0_Int_Handler(void) pDevice->pfCallback (pDevice->pCBParam, fired, NULL); } } - - /* Write 1 to clear the interrupts */ + + /* Write 1 to clear the interrupts */ pDevice->pRTCRegs->SR0 |= nIntSrc0; pDevice->pRTCRegs->SR2 |= nIntSrc2; pDevice->pRTCRegs->SR3 |= nIntSrc3; - ISR_EPILOG(); + ISR_EPILOG(); } /*! @brief RTC device driver interrupt handler. Overrides weakly-bound default interrupt handler in _startup.c. */ void RTC1_Int_Handler(void) { - ISR_PROLOG(); + ISR_PROLOG(); uint16_t nIntSrc0, nIntSrc2, nIntSrc3; uint32_t fired = 0u, enables = 0u; ADI_RTC_DEVICE *pDevice = aRTCDeviceInfo[1].hDevice; @@ -2559,7 +2560,7 @@ void RTC1_Int_Handler(void) fired |= ADI_RTC_WRITE_PENDERR_INT; } } - + /* CR1 SR2 */ enables = (uint32_t)pDevice->pRTCRegs->CR1 & ADI_RTC_INT_ENA_MASK_CR1; nIntSrc2 = pDevice->pRTCRegs->SR2 & ADI_RTC_INT_SOURCE_MASK_SR2; @@ -2586,13 +2587,13 @@ void RTC1_Int_Handler(void) fired |= ADI_RTC_COUNT_INT; } } - + /* CR3OC, CR2IC SR3*/ enables = pDevice->pRTCRegs->CR3SS & (uint32_t)ADI_RTC_INT_ENA_MASK_CR3SS; nIntSrc3 = pDevice->pRTCRegs->SR3 & ADI_RTC_SR3_IRQ_STATUS_MASK; if( nIntSrc3 && enables ) { -#if defined(__ADUCM4x50__) +#if defined(__ADUCM4x50__) if( (enables & BITM_RTC_CR3SS_SS4IRQEN) && (nIntSrc3 & BITM_RTC_SR3_SS4IRQ)) { fired |= ADI_RTC_SENSOR_STROBE_CH4_INT; @@ -2605,12 +2606,12 @@ void RTC1_Int_Handler(void) { fired |= ADI_RTC_SENSOR_STROBE_CH2_INT; } -#endif /* __ADUCM4x50__ */ +#endif /* __ADUCM4x50__ */ if( (enables & BITM_RTC_CR3SS_SS1IRQEN) && (nIntSrc3 & BITM_RTC_SR3_SS1IRQ)) { fired |= ADI_RTC_SENSOR_STROBE_CH1_INT; } -#if defined(__ADUCM4x50__) +#if defined(__ADUCM4x50__) if( (enables & BITM_RTC_CR3SS_SS4FEIRQEN) && (nIntSrc3 & BITM_RTC_SR3_SS4FEIRQ)) { fired |= ADI_RTC_RTCSS4_FE_INT; @@ -2627,7 +2628,7 @@ void RTC1_Int_Handler(void) { fired |= ADI_RTC_RTCSS1_FE_INT; } -#endif /* __ADUCM4x50__ */ +#endif /* __ADUCM4x50__ */ } enables = pDevice->pRTCRegs->CR2IC & (uint32_t)ADI_RTC_INT_ENA_MASK_CR2IC; if( nIntSrc3 && enables ) @@ -2649,7 +2650,7 @@ void RTC1_Int_Handler(void) fired |= ADI_RTC_INPUT_CAPTURE_CH0_INT; } } - + if (pDevice->pfCallback != NULL) { /* forward to the user if he is watching this interrupt */ @@ -2659,13 +2660,13 @@ void RTC1_Int_Handler(void) pDevice->pfCallback (pDevice->pCBParam, fired, NULL); } } - - /* Write 1 to clear the interrupts */ + + /* Write 1 to clear the interrupts */ pDevice->pRTCRegs->SR0 |= nIntSrc0; pDevice->pRTCRegs->SR2 |= nIntSrc2; pDevice->pRTCRegs->SR3 |= nIntSrc3; - - ISR_EPILOG(); + + ISR_EPILOG(); } /*! \endcond */ diff --git a/targets/TARGET_Analog_Devices/TARGET_ADUCM4X50/TARGET_ADUCM4050/api/us_ticker.c b/targets/TARGET_Analog_Devices/TARGET_ADUCM4X50/TARGET_ADUCM4050/api/us_ticker.c index ec7d1b5232..37853a78de 100755 --- a/targets/TARGET_Analog_Devices/TARGET_ADUCM4X50/TARGET_ADUCM4050/api/us_ticker.c +++ b/targets/TARGET_Analog_Devices/TARGET_ADUCM4X50/TARGET_ADUCM4050/api/us_ticker.c @@ -56,7 +56,7 @@ void us_ticker_irq_handler(void); static int us_ticker_inited = 0; -static ADI_TMR_CONFIG tmrConfig, tmr2Config; +static ADI_TMR_CONFIG tmrConfig; static volatile uint32_t Upper_count = 0, largecnt = 0; @@ -200,14 +200,14 @@ static void event_timer() } else cnt = 65536u - cnt; - tmr2Config.nLoad = cnt; - tmr2Config.nAsyncLoad = cnt; - adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP2, tmr2Config); + tmrConfig.nLoad = cnt; + tmrConfig.nAsyncLoad = cnt; + adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP2, tmrConfig); adi_tmr_Enable(ADI_TMR_DEVICE_GP2, true); } else { - tmr2Config.nLoad = 65535u; - tmr2Config.nAsyncLoad = 65535u; - adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP2, tmr2Config); + tmrConfig.nLoad = 65535u; + tmrConfig.nAsyncLoad = 65535u; + adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP2, tmrConfig); adi_tmr_Enable(ADI_TMR_DEVICE_GP2, true); } } @@ -247,6 +247,8 @@ static void GP2CallbackFunction(void *pCBParam, uint32_t Event, void * pArg) void us_ticker_init(void) { if (us_ticker_inited) { + // Disable ticker interrupt on reinitialization + adi_tmr_Enable(ADI_TMR_DEVICE_GP2, false); return; } @@ -281,15 +283,15 @@ void us_ticker_init(void) adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP1, tmrConfig); /* Configure GP2 for doing event counts */ - tmr2Config.bCountingUp = true; - tmr2Config.bPeriodic = true; - tmr2Config.ePrescaler = ADI_TMR_PRESCALER_256; // TMR2 at 26MHz/256 - tmr2Config.eClockSource = ADI_TMR_CLOCK_PCLK; // TMR source is PCLK (most examples use HFOSC) - tmr2Config.nLoad = 0; - tmr2Config.nAsyncLoad = 0; - tmr2Config.bReloading = false; - tmr2Config.bSyncBypass = true; // Allow x1 prescale - adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP2, tmr2Config); + tmrConfig.bCountingUp = true; + tmrConfig.bPeriodic = true; + tmrConfig.ePrescaler = ADI_TMR_PRESCALER_256; // TMR2 at 26MHz/256 + tmrConfig.eClockSource = ADI_TMR_CLOCK_PCLK; // TMR source is PCLK (most examples use HFOSC) + tmrConfig.nLoad = 0; + tmrConfig.nAsyncLoad = 0; + tmrConfig.bReloading = false; + tmrConfig.bSyncBypass = true; // Allow x1 prescale + adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP2, tmrConfig); /*------------------------- GP TIMER ENABLE ------------------------------*/ @@ -326,14 +328,15 @@ void us_ticker_clear_interrupt(void) void us_ticker_set_interrupt(timestamp_t timestamp) { - + // if timestamp is already past, do not set interrupt + if ((timestamp + 10) <= us_ticker_read()) return; /* timestamp is when interrupt should fire. * * This MUST not be called if another timer event is currently enabled. * */ calc_event_counts(timestamp); // use timestamp to calculate largecnt to control number of timer interrupts - tmr2Config.ePrescaler = ADI_TMR_PRESCALER_256; // TMR2 at 26MHz/256 + tmrConfig.ePrescaler = ADI_TMR_PRESCALER_256; // TMR2 at 26MHz/256 event_timer(); // uses largecnt to initiate timer interrupts } @@ -346,7 +349,7 @@ void us_ticker_set_interrupt(timestamp_t timestamp) void us_ticker_fire_interrupt(void) { largecnt = 1; // set a minimal interval so interrupt fire immediately - tmr2Config.ePrescaler = ADI_TMR_PRESCALER_1; // TMR2 at 26MHz/1 + tmrConfig.ePrescaler = ADI_TMR_PRESCALER_1; // TMR2 at 26MHz/1 event_timer(); // enable the timer and interrupt } diff --git a/targets/TARGET_Analog_Devices/TARGET_ADUCM4X50/TARGET_ADUCM4050/bsp/rtc/adi_rtc.c b/targets/TARGET_Analog_Devices/TARGET_ADUCM4X50/TARGET_ADUCM4050/bsp/rtc/adi_rtc.c index f4b91d4adb..29ecd20207 100755 --- a/targets/TARGET_Analog_Devices/TARGET_ADUCM4X50/TARGET_ADUCM4050/bsp/rtc/adi_rtc.c +++ b/targets/TARGET_Analog_Devices/TARGET_ADUCM4X50/TARGET_ADUCM4050/bsp/rtc/adi_rtc.c @@ -6,7 +6,7 @@ * @date: $Date: 2016-07-26 13:09:22 -0400 (Tue, 26 Jul 2016) $ *---------------------------------------------------------------------------- * -Copyright (c) 2010-2016 Analog Devices, Inc. +Copyright (c) 2010-2018 Analog Devices, Inc. All rights reserved. @@ -90,27 +90,27 @@ POSSIBILITY OF SUCH DAMAGE. * Pm150 (rule 20.2): the names of standard library macros, objects and function shall not be reused * Needed to implement the functions here. * -* Pm129 (rule 12.7): bitwise operations shall not be performed on signed integer types +* Pm129 (rule 12.7): bitwise operations shall not be performed on signed integer types * The rule makes an exception for valid expressions. * -* Pm029: this bitwise operation is in a boolean context - logical operators should not be confused with bitwise operators +* Pm029: this bitwise operation is in a boolean context - logical operators should not be confused with bitwise operators * The rule is suppressed as the bitwise and logical operators are being used correctly and are not being confused * * Pm126: if the bitwise operators ~ and << are applied to an operand of underlying type 'unsigned char' or 'unsigned short', the result shall be immediately cast to the underlying type of the operand * The behaviour as described is correct * -* Pm031: bitwise operations shall not be performed on signed integer types +* Pm031: bitwise operations shall not be performed on signed integer types * Device drivers often require bit banging on MMRs that are defined as signed */ #pragma diag_suppress=Pm011,Pm123,Pm073,Pm143,Pm050,Pm109,Pm150,Pm140,Pm129,Pm029,Pm126,Pm031 #endif /* __ICCARM__ */ /*! \endcond */ - - + + #include - + /*! \cond PRIVATE */ @@ -205,31 +205,32 @@ ADI_RTC_RESULT adi_rtc_Open( memset(pDeviceMemory,0,MemorySize); /* initialize device data entries */ pDevice->pRTCRegs = aRTCDeviceInfo[DeviceNumber].pRTCRegs; - + PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) pDevice->pRTCRegs->CR0 = 0u; pDevice->pRTCRegs->CR1 = 0u; - - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDSR0) pDevice->pRTCRegs->SR0 = ADI_RTC_SR3_IRQ_STATUS_MASK; - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCSR0) - + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCSR0) + /* Preserve RTC counter value while re-initialization pDevice->pRTCRegs->CNT0 = 0u; pDevice->pRTCRegs->CNT1 = 0u; - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCNT0) - + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCNT0) + */ /* local pointer to instance data */ aRTCDeviceInfo[DeviceNumber].hDevice = pDevice; pDevice->pDeviceInfo = &aRTCDeviceInfo[DeviceNumber]; - /* Use static configuration to initialize the RTC */ + /* Do not use static configuration to + preserve RTC counter value while re-initialization rtc_init(pDevice,&aRTCConfig[DeviceNumber]); - + */ /* store handle at application handle pointer */ *phDevice = pDevice; pDevice->eIRQn = aRTCDeviceInfo[DeviceNumber].eIRQn; @@ -272,7 +273,7 @@ ADI_RTC_RESULT adi_rtc_Close(ADI_RTC_HANDLE const hDevice) pDevice->pfCallback = NULL; pDevice->pCBParam = NULL; pDevice->cbWatch = 0u; - + pDevice->pDeviceInfo->hDevice = NULL; return ADI_RTC_SUCCESS; } @@ -326,9 +327,9 @@ ADI_RTC_RESULT adi_rtc_EnableAlarm(ADI_RTC_HANDLE const hDevice, bool bEnable) } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); /* set/clear RTC alarm enable */ @@ -341,9 +342,9 @@ ADI_RTC_RESULT adi_rtc_EnableAlarm(ADI_RTC_HANDLE const hDevice, bool bEnable) pDevice->pRTCRegs->CR0 &= (uint16_t)(~BITM_RTC_CR0_ALMEN); } ADI_EXIT_CRITICAL_REGION(); - - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) return ADI_RTC_SUCCESS; } @@ -395,7 +396,7 @@ ADI_RTC_RESULT adi_rtc_EnableMod60Alarm(ADI_RTC_HANDLE const hDevice, bool bEnab #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) ADI_INT_STATUS_ALLOC(); @@ -410,9 +411,9 @@ ADI_RTC_RESULT adi_rtc_EnableMod60Alarm(ADI_RTC_HANDLE const hDevice, bool bEnab pDevice->pRTCRegs->CR0 &= (uint16_t)(~BITM_RTC_CR0_MOD60ALMEN); } ADI_EXIT_CRITICAL_REGION(); - - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) return ADI_RTC_SUCCESS; } @@ -452,9 +453,9 @@ ADI_RTC_RESULT adi_rtc_Enable(ADI_RTC_HANDLE const hDevice, bool bEnable) } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); @@ -468,10 +469,10 @@ ADI_RTC_RESULT adi_rtc_Enable(ADI_RTC_HANDLE const hDevice, bool bEnable) pDevice->pRTCRegs->CR0 &=(uint16_t)(~BITM_RTC_CR0_CNTEN); } ADI_EXIT_CRITICAL_REGION(); - - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) - + + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + return ADI_RTC_SUCCESS; } @@ -482,12 +483,12 @@ static uint16_t cr0 = 0u, cr1 = 0u, cr3oc = 0u, cr4oc = 0u, cr2ic = 0u, cr5ocs = static struct xxx { uint16_t *cr; - uint16_t bitPositionl; -} + uint16_t bitPositionl; +} Interrupt_Details[ADI_RTC_NUM_INTERRUPTS] = { - { &cr0, BITP_RTC_CR0_ALMINTEN }, - { &cr0, BITP_RTC_CR0_MOD60ALMINTEN }, + { &cr0, BITP_RTC_CR0_ALMINTEN }, + { &cr0, BITP_RTC_CR0_MOD60ALMINTEN }, { &cr0, BITP_RTC_CR0_ISOINTEN }, { &cr0, BITP_RTC_CR0_WPNDERRINTEN }, { &cr0, BITP_RTC_CR0_WSYNCINTEN }, @@ -507,17 +508,17 @@ Interrupt_Details[ADI_RTC_NUM_INTERRUPTS] = { &cr2ic, BITP_RTC_CR2IC_IC4IRQEN }, { &cr2ic, BITP_CLKG_OSC_CTL_LFX_FAIL_STA }, { &cr3oc, BITM_RTC_CR3SS_SS4FEIRQEN}, - { &cr3oc, BITM_RTC_CR3SS_SS3FEIRQEN}, - { &cr3oc, BITM_RTC_CR3SS_SS2FEIRQEN}, - { &cr3oc, BITM_RTC_CR3SS_SS1FEIRQEN}, - { &cr4oc, BITP_RTC_CR4SS_SS4MSKEN}, - { &cr4oc, BITP_RTC_CR4SS_SS3MSKEN}, - { &cr4oc, BITP_RTC_CR4SS_SS2MSKEN}, - { &cr4oc, BITP_RTC_CR4SS_SS1MSKEN}, - { &cr5ocs, BITP_RTC_CR5SSS_SS3SMPMTCHIRQEN}, - { &cr5ocs, BITP_RTC_CR5SSS_SS2SMPMTCHIRQEN}, + { &cr3oc, BITM_RTC_CR3SS_SS3FEIRQEN}, + { &cr3oc, BITM_RTC_CR3SS_SS2FEIRQEN}, + { &cr3oc, BITM_RTC_CR3SS_SS1FEIRQEN}, + { &cr4oc, BITP_RTC_CR4SS_SS4MSKEN}, + { &cr4oc, BITP_RTC_CR4SS_SS3MSKEN}, + { &cr4oc, BITP_RTC_CR4SS_SS2MSKEN}, + { &cr4oc, BITP_RTC_CR4SS_SS1MSKEN}, + { &cr5ocs, BITP_RTC_CR5SSS_SS3SMPMTCHIRQEN}, + { &cr5ocs, BITP_RTC_CR5SSS_SS2SMPMTCHIRQEN}, { &cr5ocs, BITP_RTC_CR5SSS_SS1SMPMTCHIRQEN} - + }; @@ -535,7 +536,7 @@ Interrupt_Details[ADI_RTC_NUM_INTERRUPTS] = * - #ADI_RTC_INVALID_HANDLE [D] Invalid device handle parameter. * * Enable/disable RTC interrupt as well as manage global NVIC enable/disable for the RTC. - * Input parameter \a Interrupts is a interrupt ID of type #ADI_RTC_INT_TYPE designating the + * Input parameter \a Interrupts is a interrupt ID of type #ADI_RTC_INT_TYPE designating the * interrupt to be enabled or disabled. The interrupt parameter may be zero, which will then simply * manage the NVIC RTC enable and leave the individual RTC interrupt enables unchanged. * Input parameter \a bEnable controls whether to enable or disable the designated set of interrupts. @@ -556,21 +557,21 @@ ADI_RTC_RESULT adi_rtc_EnableInterrupts (ADI_RTC_HANDLE const hDevice, ADI_RTC_I return eResult; } if( (pDevice->pRTCRegs == pADI_RTC0) &&(((uint16_t)((ADI_RTC_MOD60ALM_INT | ADI_RTC_ISO_DONE_INT| - ADI_RTC_COUNT_INT | + ADI_RTC_COUNT_INT | ADI_RTC_TRIM_INT | ADI_RTC_COUNT_ROLLOVER_INT | ADI_RTC_MOD60_ROLLOVER_INT )) & (uint16_t)Interrupts) != 0u)) { return(ADI_RTC_INVALID_PARAM); } - + assert(sizeof(Interrupt_Details)/sizeof(Interrupt_Details[0]) == ADI_RTC_NUM_INTERRUPTS); #endif - + /* TODO - more sync for new registers */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) PEND_BEFORE_WRITE(SR2,BITM_RTC_SR2_WPNDCR1MIR) - + uint8_t ndx = 0u; cr0 = 0u; cr1 = 0u; cr3oc = 0u; cr4oc = 0u; cr2ic = 0u; cr5ocs = 0u; @@ -594,8 +595,8 @@ ADI_RTC_RESULT adi_rtc_EnableInterrupts (ADI_RTC_HANDLE const hDevice, ADI_RTC_I pDevice->pRTCRegs->CR4SS |= cr4oc; pDevice->pRTCRegs->CR2IC |= cr2ic; pDevice->pRTCRegs->CR5SSS |= cr5ocs; - - } + + } else { pDevice->pRTCRegs->CR0 &= ~cr0; @@ -605,8 +606,8 @@ ADI_RTC_RESULT adi_rtc_EnableInterrupts (ADI_RTC_HANDLE const hDevice, ADI_RTC_I pDevice->pRTCRegs->CR2IC &= ~cr2ic; pDevice->pRTCRegs->CR5SSS &= ~cr5ocs; } - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) - SYNC_AFTER_WRITE(SR2,BITM_RTC_SR2_WSYNCCR1MIR) + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + SYNC_AFTER_WRITE(SR2,BITM_RTC_SR2_WSYNCCR1MIR) return ADI_RTC_SUCCESS; } @@ -648,9 +649,9 @@ ADI_RTC_RESULT adi_rtc_EnableTrim (ADI_RTC_HANDLE const hDevice, bool bEnable) return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); /* set/clear trim enable bit(s) in control register */ @@ -664,16 +665,16 @@ ADI_RTC_RESULT adi_rtc_EnableTrim (ADI_RTC_HANDLE const hDevice, bool bEnable) } ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + return ADI_RTC_SUCCESS; } /*! * @brief Enable input capture for the specified channel. * * @param[in] hDevice Device handle obtained from adi_rtc_Open(). - * @param[in] eInpChannel Specify input compare channel. + * @param[in] eInpChannel Specify input compare channel. * @param[in] bEnable Flag for enabling RTC input capture for specified channel. * - true Enable input capture. * - false Disable input capture. @@ -694,9 +695,9 @@ ADI_RTC_RESULT adi_rtc_EnableInputCapture (ADI_RTC_HANDLE const hDevice,ADI_RTC_ return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDCR2IC) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); /* set/clear trim input capture enable for specified channel*/ @@ -710,9 +711,9 @@ ADI_RTC_RESULT adi_rtc_EnableInputCapture (ADI_RTC_HANDLE const hDevice,ADI_RTC_ } ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR2IC) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR2IC) + return ADI_RTC_SUCCESS; } @@ -740,9 +741,9 @@ ADI_RTC_RESULT adi_rtc_EnableOverwriteSnapshot (ADI_RTC_HANDLE const hDevice, bo return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDCR2IC) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); /* set/clear trim input capture enable for specified channel*/ @@ -756,9 +757,9 @@ ADI_RTC_RESULT adi_rtc_EnableOverwriteSnapshot (ADI_RTC_HANDLE const hDevice, bo } ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR2IC) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR2IC) + return ADI_RTC_SUCCESS; } @@ -766,7 +767,7 @@ ADI_RTC_RESULT adi_rtc_EnableOverwriteSnapshot (ADI_RTC_HANDLE const hDevice, bo * @brief Set input capture polarity for the specified channel. * * @param[in] hDevice Device handle obtained from adi_rtc_Open(). - * @param[in] eInpChannel Specify which input capture channel. + * @param[in] eInpChannel Specify which input capture channel. * @param[in] bEnable Flag for selecting RTC input capture polarity. * - false channel uses a *high-to-low* transition on its GPIO pin to signal an input capture event * - true channel uses a *low-to-high* transition on its GPIO pin to signal an input capture event. @@ -788,9 +789,9 @@ ADI_RTC_RESULT adi_rtc_SetInputCapturePolarity (ADI_RTC_HANDLE const hDevice,ADI return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDCR2IC) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); /* set/clear trim input capture enable for specified channel*/ @@ -804,9 +805,9 @@ ADI_RTC_RESULT adi_rtc_SetInputCapturePolarity (ADI_RTC_HANDLE const hDevice,ADI } ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR2IC) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR2IC) + return ADI_RTC_SUCCESS; } /*! @@ -834,9 +835,9 @@ ADI_RTC_RESULT adi_rtc_EnableSensorStrobeOutput (ADI_RTC_HANDLE const hDevice, A return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDCR3SS) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); /* set/clear Sensor Strobe enable for specified channel*/ @@ -850,9 +851,9 @@ ADI_RTC_RESULT adi_rtc_EnableSensorStrobeOutput (ADI_RTC_HANDLE const hDevice, A } ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR3SS) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR3SS) + return ADI_RTC_SUCCESS; } @@ -881,9 +882,9 @@ ADI_RTC_RESULT adi_rtc_EnableAutoReload(ADI_RTC_HANDLE const hDevice, ADI_RTC_SS return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDCR4SS) - + ADI_INT_STATUS_ALLOC(); ADI_ENTER_CRITICAL_REGION(); /* set/clear auto reload enable options */ @@ -904,7 +905,7 @@ ADI_RTC_RESULT adi_rtc_EnableAutoReload(ADI_RTC_HANDLE const hDevice, ADI_RTC_SS default: return ADI_RTC_FAILURE; } - + } else { @@ -925,22 +926,22 @@ ADI_RTC_RESULT adi_rtc_EnableAutoReload(ADI_RTC_HANDLE const hDevice, ADI_RTC_SS } ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR4SS) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR4SS) + return ADI_RTC_SUCCESS; } /*! * @brief Set auto reload value for the given Sensor Strobe channel. * * @param[in] hDevice Device handle obtained from adi_rtc_Open(). - * @param[in] eSSChannel Sensor Strobe channel for which auto reload to be set. + * @param[in] eSSChannel Sensor Strobe channel for which auto reload to be set. * @param[in] nValue Auto reload value to be set. * * @return Status * - #ADI_RTC_SUCCESS Call completed successfully. * - #ADI_RTC_INVALID_HANDLE [D] Invalid device handle parameter. - * + * * */ ADI_RTC_RESULT adi_rtc_SetAutoReloadValue(ADI_RTC_HANDLE const hDevice, ADI_RTC_SS_CHANNEL eSSChannel, uint16_t nValue) @@ -954,52 +955,52 @@ ADI_RTC_RESULT adi_rtc_SetAutoReloadValue(ADI_RTC_HANDLE const hDevice, ADI_RTC_ return eResult; } #endif - + switch( eSSChannel ) { case ADI_RTC_SS_CHANNEL_1: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS1) pDevice->pRTCRegs->SS1 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS1) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS1) break; - + case ADI_RTC_SS_CHANNEL_2: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS2) pDevice->pRTCRegs->SS2 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS2) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS2) break; - + case ADI_RTC_SS_CHANNEL_3: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS3) pDevice->pRTCRegs->SS3 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS3) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS3) break; case ADI_RTC_SS_CHANNEL_4: PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS4) pDevice->pRTCRegs->SS4 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS4) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS4) break; - + default: return ADI_RTC_FAILURE; } - + return ADI_RTC_SUCCESS; } /*! * @brief Enable or disable thermometer-code masking for the given Sensor Strobe Channel. * * @param[in] hDevice Device handle obtained from adi_rtc_Open(). - * @param[in] eSSChannel Sensor Strobe channel for which thermometer-code masking to be enabled or disabled. + * @param[in] eSSChannel Sensor Strobe channel for which thermometer-code masking to be enabled or disabled. * @param[in] bEnable Flag to enable or disable masking for the given Sensor Strobe channel. * - true Enable masking . * - false Disable masking. @@ -1020,11 +1021,11 @@ ADI_RTC_RESULT adi_rtc_EnableSensorStrobeChannelMask(ADI_RTC_HANDLE const hDevic return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5, BITM_RTC_SR5_WPENDCR4SS) - + ADI_INT_STATUS_ALLOC(); - ADI_ENTER_CRITICAL_REGION(); + ADI_ENTER_CRITICAL_REGION(); /* set/clear auto reload enable options */ if (bEnable) { @@ -1036,9 +1037,9 @@ ADI_RTC_RESULT adi_rtc_EnableSensorStrobeChannelMask(ADI_RTC_HANDLE const hDevic } ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR4SS) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCCR4SS) + return ADI_RTC_SUCCESS; } @@ -1046,7 +1047,7 @@ ADI_RTC_RESULT adi_rtc_EnableSensorStrobeChannelMask(ADI_RTC_HANDLE const hDevic * @brief To set channel mask for the given Sensor Strobe channel. * * @param[in] hDevice Device handle obtained from adi_rtc_Open(). - * @param[in] eSSChannel Sensor Strobe Channel for which the mask to be set. + * @param[in] eSSChannel Sensor Strobe Channel for which the mask to be set. * @param[in] nMask Channel Mask to be set for Sensor Strobe channel. * * @return Status @@ -1066,37 +1067,37 @@ ADI_RTC_RESULT adi_rtc_SetSensorStrobeChannelMask(ADI_RTC_HANDLE const hDevice, return eResult; } #endif - + switch( eSSChannel ) { case ADI_RTC_SS_CHANNEL_1: MaskPos = (uint16_t)BITP_RTC_SSMSK_SS1MSK; break; - + case ADI_RTC_SS_CHANNEL_2: MaskPos = (uint16_t)BITP_RTC_SSMSK_SS2MSK; break; - + case ADI_RTC_SS_CHANNEL_3: MaskPos = (uint16_t)BITP_RTC_SSMSK_SS3MSK; break; case ADI_RTC_SS_CHANNEL_4: - MaskPos = (uint16_t)BITP_RTC_SSMSK_SS4MSK; + MaskPos = (uint16_t)BITP_RTC_SSMSK_SS4MSK; break; - + default: return ADI_RTC_INVALID_CHANNEL; } - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5, BITM_RTC_SR5_WPENDSSMSK) - + pDevice->pRTCRegs->SSMSK = ((uint16_t)nMask & 0xFu) << MaskPos; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4, BITM_RTC_SR4_WSYNCSSMSK) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4, BITM_RTC_SR4_WSYNCSSMSK) + return ADI_RTC_SUCCESS; } @@ -1135,7 +1136,7 @@ ADI_RTC_RESULT adi_rtc_GetAlarm (ADI_RTC_HANDLE hDevice, uint32_t *pAlarm) } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDALM0|BITM_RTC_SR1_WPNDALM1)) /* disable interrupts during paired read */ @@ -1178,7 +1179,7 @@ ADI_RTC_RESULT adi_rtc_GetAlarmEx (ADI_RTC_HANDLE hDevice, float *pAlarm) } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDALM0|BITM_RTC_SR1_WPNDALM1)) nPreScale = (pDevice->pRTCRegs->CR1&BITM_RTC_CR1_PRESCALE2EXP)>>BITP_RTC_CR1_PRESCALE2EXP; /* disable interrupts during paired read */ @@ -1224,7 +1225,7 @@ ADI_RTC_RESULT adi_rtc_GetControl (ADI_RTC_HANDLE hDevice, ADI_RTC_CONTROL_REGIS return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) switch(eRegister) @@ -1271,7 +1272,7 @@ ADI_RTC_RESULT adi_rtc_GetCount(ADI_RTC_HANDLE const hDevice, uint32_t *pCount) } #endif - /* Wait till previously posted write to couunt Register to complete */ + /* Wait till previously posted write to couunt Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDCNT0|BITM_RTC_SR1_WPNDCNT1)) /* disable interrupts during paired read */ @@ -1313,7 +1314,7 @@ ADI_RTC_RESULT adi_rtc_GetCountEx(ADI_RTC_HANDLE const hDevice, float *pfCount) return eResult; } #endif - /* Wait till previously posted write to couunt Register to complete */ + /* Wait till previously posted write to couunt Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDCNT0|BITM_RTC_SR1_WPNDCNT1)) nPrescale = (pDevice->pRTCRegs->CR1&BITM_RTC_CR1_PRESCALE2EXP)>>BITP_RTC_CR1_PRESCALE2EXP; /* disable interrupts during paired read */ @@ -1321,7 +1322,7 @@ ADI_RTC_RESULT adi_rtc_GetCountEx(ADI_RTC_HANDLE const hDevice, float *pfCount) nCount = (uint32_t)pDevice->pRTCRegs->CNT1 << 16u; nCount |= pDevice->pRTCRegs->CNT0; nTemp = (1lu<pRTCRegs->CNT2/(float)(nTemp); + fFraction = (float)pDevice->pRTCRegs->CNT2/(float)(nTemp); NVIC_EnableIRQ((IRQn_Type)pDevice->eIRQn); *pfCount = (float)nCount+ fFraction; @@ -1356,14 +1357,14 @@ ADI_RTC_RESULT adi_rtc_GetCountRegs(ADI_RTC_HANDLE const hDevice, uint32_t *pnCo return eResult; } #endif - /* Wait till previously posted write to couunt Register to complete */ + /* Wait till previously posted write to couunt Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDCNT0|BITM_RTC_SR1_WPNDCNT1)) /* disable interrupts during paired read */ NVIC_DisableIRQ(pDevice->eIRQn); nCount = (uint32_t)pDevice->pRTCRegs->CNT1 << 16u; nCount |= pDevice->pRTCRegs->CNT0; *pnCount= nCount; - *pfCount = (uint32_t)pDevice->pRTCRegs->CNT2; + *pfCount = (uint32_t)pDevice->pRTCRegs->CNT2; NVIC_EnableIRQ((IRQn_Type)pDevice->eIRQn); return ADI_RTC_SUCCESS; } @@ -1405,7 +1406,7 @@ ADI_RTC_RESULT adi_rtc_GetTrim (ADI_RTC_HANDLE hDevice, ADI_RTC_TRIM_VALUE *peTr } #endif - /* Wait till previously posted write to couunt Register to complete */ + /* Wait till previously posted write to couunt Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDTRM); *peTrim =(ADI_RTC_TRIM_VALUE)(pDevice->pRTCRegs->TRM & BITM_RTC_TRM_VALUE); @@ -1432,7 +1433,7 @@ ADI_RTC_RESULT adi_rtc_GetTrim (ADI_RTC_HANDLE hDevice, ADI_RTC_TRIM_VALUE *peTr ADI_RTC_RESULT adi_rtc_GetSensorStrobeValue(ADI_RTC_HANDLE const hDevice, ADI_RTC_SS_CHANNEL eSSChannel, uint16_t *pValue) { ADI_RTC_DEVICE *pDevice = hDevice; - + #ifdef ADI_DEBUG ADI_RTC_RESULT eResult; if((eResult = ValidateHandle(pDevice)) != ADI_RTC_SUCCESS) @@ -1446,37 +1447,37 @@ ADI_RTC_RESULT adi_rtc_GetSensorStrobeValue(ADI_RTC_HANDLE const hDevice, ADI_RT PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS1) *pValue = pDevice->pRTCRegs->SS1; break; - + case ADI_RTC_SS_CHANNEL_2: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS2) *pValue = pDevice->pRTCRegs->SS2; break; - + case ADI_RTC_SS_CHANNEL_3: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS3) *pValue = pDevice->pRTCRegs->SS3; break; - + case ADI_RTC_SS_CHANNEL_4: PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS4) *pValue = pDevice->pRTCRegs->SS4; break; - + default: return ADI_RTC_FAILURE; } - - - + + + return ADI_RTC_SUCCESS; } /*! * @brief Set Sensor Strobe value for the given Sensor Strobe channel. * * @param[in] hDevice Device handle obtained from adi_rtc_Open(). - * @param[in] eSSChannel Sensor Strobe Channel. + * @param[in] eSSChannel Sensor Strobe Channel. * @param[out] nValue Sensor Strobe value to be set for the given Sensor Strobe channel . * * @return Status @@ -1499,45 +1500,45 @@ ADI_RTC_RESULT adi_rtc_SetSensorStrobeValue(ADI_RTC_HANDLE const hDevice, ADI_RT return eResult; } #endif - + switch( eSSChannel ) { case ADI_RTC_SS_CHANNEL_1: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS1) pDevice->pRTCRegs->SS1 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS1) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS1) break; - + case ADI_RTC_SS_CHANNEL_2: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS2) pDevice->pRTCRegs->SS2 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS2) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS2) break; - + case ADI_RTC_SS_CHANNEL_3: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS3) pDevice->pRTCRegs->SS3 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS3) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS3) break; - + case ADI_RTC_SS_CHANNEL_4: - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR5,BITM_RTC_SR5_WPENDSS4) pDevice->pRTCRegs->SS4 = nValue; - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS4) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR4,BITM_RTC_SR4_WSYNCSS4) break; - + default: return ADI_RTC_FAILURE; } - + return ADI_RTC_SUCCESS; } @@ -1545,14 +1546,14 @@ ADI_RTC_RESULT adi_rtc_SetSensorStrobeValue(ADI_RTC_HANDLE const hDevice, ADI_RT * @brief Get input capture value for specified input channel. * * @param[in] hDevice Device handle obtained from adi_rtc_Open(). - * @param[in] eChannel Specify which input capture channel. + * @param[in] eChannel Specify which input capture channel. * @param[out] pValue Pointer to application memory where the input capture value to be written. * * @return Status * - #ADI_RTC_SUCCESS Call completed successfully. * - #ADI_RTC_INVALID_HANDLE [D] Invalid device handle parameter. * - #ADI_RTC_INVALID_PARAM [D] NULL pointer for input parameter. - * - #ADI_RTC_INVALID_CHANNEL [D] Input channel-0 is not valid for this operation since + * - #ADI_RTC_INVALID_CHANNEL [D] Input channel-0 is not valid for this operation since * channel-0 can provide precise (47bit) capture value. * * @@ -1566,7 +1567,7 @@ ADI_RTC_RESULT adi_rtc_GetInputCaptureValue(ADI_RTC_HANDLE const hDevice,ADI_RTC { ADI_RTC_DEVICE *pDevice = hDevice; ADI_RTC_RESULT eResult= ADI_RTC_SUCCESS; - + #ifdef ADI_DEBUG if((eResult = ValidateHandle(pDevice)) != ADI_RTC_SUCCESS) { @@ -1581,11 +1582,11 @@ ADI_RTC_RESULT adi_rtc_GetInputCaptureValue(ADI_RTC_HANDLE const hDevice,ADI_RTC case ADI_RTC_INPUT_CHANNEL_3: *pValue = pDevice->pRTCRegs->IC3; break; - + case ADI_RTC_INPUT_CHANNEL_4: *pValue = pDevice->pRTCRegs->IC4; break; - default: + default: eResult = ADI_RTC_INVALID_CHANNEL; break; } @@ -1743,7 +1744,7 @@ ADI_RTC_RESULT adi_rtc_GetWriteSyncStatus (ADI_RTC_HANDLE const hDevice, ADI_RT return eResult; } #endif - /* Wait till previously posted write to couunt Register to complete */ + /* Wait till previously posted write to couunt Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDSR0); /* get the value */ @@ -1793,7 +1794,7 @@ ADI_RTC_RESULT adi_rtc_SetAlarm (ADI_RTC_HANDLE const hDevice, uint32_t nAlarm) } #endif - /* Wait till previously posted write to Alram Register to complete */ + /* Wait till previously posted write to Alram Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDALM0|BITM_RTC_SR1_WPNDALM1)) ADI_INT_STATUS_ALLOC(); @@ -1803,9 +1804,9 @@ ADI_RTC_RESULT adi_rtc_SetAlarm (ADI_RTC_HANDLE const hDevice, uint32_t nAlarm) pDevice->pRTCRegs->ALM1 = (uint16_t)(nAlarm >> 16); pDevice->pRTCRegs->ALM2 = 0u; ADI_EXIT_CRITICAL_REGION(); - - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,(BITM_RTC_SR0_WSYNCALM0|BITM_RTC_SR0_WSYNCALM1)) + + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,(BITM_RTC_SR0_WSYNCALM0|BITM_RTC_SR0_WSYNCALM1)) return ADI_RTC_SUCCESS; } @@ -1853,8 +1854,8 @@ ADI_RTC_RESULT adi_rtc_SetPreScale(ADI_RTC_HANDLE const hDevice, uint8_t nPreSc nTemp |= (uint16_t)((uint16_t)nPreScale << BITP_RTC_CR1_PRESCALE2EXP); pDevice->pRTCRegs->CR1 = nTemp; ADI_EXIT_CRITICAL_REGION(); - - SYNC_AFTER_WRITE(SR2,BITM_RTC_SR2_WSYNCCR1MIR) + + SYNC_AFTER_WRITE(SR2,BITM_RTC_SR2_WSYNCCR1MIR) return ADI_RTC_SUCCESS; } /*! @@ -1893,7 +1894,7 @@ ADI_RTC_RESULT adi_rtc_SetMod60AlarmPeriod(ADI_RTC_HANDLE const hDevice, uint8_t #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) ADI_INT_STATUS_ALLOC(); @@ -1904,8 +1905,8 @@ ADI_RTC_RESULT adi_rtc_SetMod60AlarmPeriod(ADI_RTC_HANDLE const hDevice, uint8_t nTemp |= (uint16_t)((uint16_t)nPeriod << BITP_RTC_CR0_MOD60ALM); pDevice->pRTCRegs->CR0 = nTemp; ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) return ADI_RTC_SUCCESS; } @@ -1950,7 +1951,7 @@ ADI_RTC_RESULT adi_rtc_SetAlarmEx(ADI_RTC_HANDLE const hDevice, float fAlarm) #endif - /* Wait till previously posted write to Alarm Register to complete */ + /* Wait till previously posted write to Alarm Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDALM0|BITM_RTC_SR1_WPNDALM1)) nPreScale = (pDevice->pRTCRegs->CR1&BITM_RTC_CR1_PRESCALE2EXP)>>BITP_RTC_CR1_PRESCALE2EXP; ADI_INT_STATUS_ALLOC(); @@ -1963,8 +1964,8 @@ ADI_RTC_RESULT adi_rtc_SetAlarmEx(ADI_RTC_HANDLE const hDevice, float fAlarm) fFraction = (fAlarm - (float)nAlarm) *(float)(nTemp); pDevice->pRTCRegs->ALM2 = (uint16_t)(fFraction); ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to Alarm Register to take effect */ - SYNC_AFTER_WRITE(SR0,(BITM_RTC_SR0_WSYNCALM0|BITM_RTC_SR0_WSYNCALM1)) + /* Wait till write to Alarm Register to take effect */ + SYNC_AFTER_WRITE(SR0,(BITM_RTC_SR0_WSYNCALM0|BITM_RTC_SR0_WSYNCALM1)) return ADI_RTC_SUCCESS; } @@ -2001,7 +2002,7 @@ ADI_RTC_RESULT adi_rtc_SetControlRegister(ADI_RTC_HANDLE const hDevice,ADI_RTC_C return eResult; } #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDCR0) switch(eRegister) @@ -2015,9 +2016,9 @@ ADI_RTC_RESULT adi_rtc_SetControlRegister(ADI_RTC_HANDLE const hDevice,ADI_RTC_C default: return(ADI_RTC_FAILURE); } - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) - + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCCR0) + return ADI_RTC_SUCCESS; } @@ -2110,7 +2111,7 @@ ADI_RTC_RESULT adi_rtc_SetCount (ADI_RTC_HANDLE const hDevice, uint32_t nCount) } #endif - /* Wait till previously posted write to count Register to complete */ + /* Wait till previously posted write to count Register to complete */ PEND_BEFORE_WRITE(SR1,(BITM_RTC_SR1_WPNDCNT0|BITM_RTC_SR1_WPNDCNT1)) ADI_INT_STATUS_ALLOC(); @@ -2120,8 +2121,8 @@ ADI_RTC_RESULT adi_rtc_SetCount (ADI_RTC_HANDLE const hDevice, uint32_t nCount) pDevice->pRTCRegs->CNT1 = (uint16_t)(nCount >> 16); ADI_EXIT_CRITICAL_REGION(); - /* Wait till write to count Register to take effect */ - SYNC_AFTER_WRITE(SR0,(BITM_RTC_SR0_WSYNCCNT0|BITM_RTC_SR0_WSYNCCNT1)) + /* Wait till write to count Register to take effect */ + SYNC_AFTER_WRITE(SR0,(BITM_RTC_SR0_WSYNCCNT0|BITM_RTC_SR0_WSYNCCNT1)) return ADI_RTC_SUCCESS; } @@ -2204,13 +2205,13 @@ ADI_RTC_RESULT adi_rtc_SetTrim(ADI_RTC_HANDLE const hDevice, ADI_RTC_TRIM_INTER #endif - /* Wait till previously posted write to Control Register to complete */ + /* Wait till previously posted write to Control Register to complete */ PEND_BEFORE_WRITE(SR1,BITM_RTC_SR1_WPNDTRM) pDevice->pRTCRegs->TRM = (uint16_t)trm; - - /* Wait till write to Control Register to take effect */ - SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCTRM) + + /* Wait till write to Control Register to take effect */ + SYNC_AFTER_WRITE(SR0,BITM_RTC_SR0_WSYNCTRM) return ADI_RTC_SUCCESS; } @@ -2263,7 +2264,7 @@ ADI_RTC_RESULT adi_rtc_SynchronizeAllWrites (ADI_RTC_HANDLE const hDevice) /*! \cond PRIVATE */ /* - * @brief Initializes the device using static configuration + * @brief Initializes the device using static configuration * * @param[in] pDevice Pointer to RTC device . pConfig Pointer to static configuration device structure. @@ -2272,16 +2273,16 @@ ADI_RTC_RESULT adi_rtc_SynchronizeAllWrites (ADI_RTC_HANDLE const hDevice) static void rtc_init(ADI_RTC_DEVICE *pDevice,ADI_RTC_CONFIG *pConfig) { - + /* FIXME - static init is even more now */ - + /* Control register -0 which controls all main stream activity of RTC0 */ pDevice->pRTCRegs->CR0 = pConfig->CR0; - /* Control register -1 which is granularity of RTC control register */ + /* Control register -1 which is granularity of RTC control register */ pDevice->pRTCRegs->CR1 = pConfig->CR1; - /*CNT0 contains the lower 16 bits of the RTC counter */ + /*CNT0 contains the lower 16 bits of the RTC counter */ pDevice->pRTCRegs->CNT0 = pConfig->CNT0; - /*CNT1 contains the lower 16 bits of the RTC counter */ + /*CNT1 contains the lower 16 bits of the RTC counter */ pDevice->pRTCRegs->CNT1 = pConfig->CNT1; /* ALM0 contains the lower 16 bits of the Alarm register */ pDevice->pRTCRegs->ALM0 = pConfig->ALM0; @@ -2310,7 +2311,7 @@ static void rtc_init(ADI_RTC_DEVICE *pDevice,ADI_RTC_CONFIG *pConfig) /*! @brief RTC device driver interrupt handler. Overrides weakly-bound default interrupt handler in _startup.c. */ void RTC0_Int_Handler(void) { - ISR_PROLOG(); + ISR_PROLOG(); uint16_t nIntSrc0, nIntSrc2, nIntSrc3; uint32_t fired = 0u, enables = 0u; ADI_RTC_DEVICE *pDevice = aRTCDeviceInfo[0].hDevice; @@ -2349,7 +2350,7 @@ void RTC0_Int_Handler(void) fired |= ADI_RTC_WRITE_PENDERR_INT; } } - + /* CR1 SR2 */ enables = (uint32_t)pDevice->pRTCRegs->CR1 & ADI_RTC_INT_ENA_MASK_CR1; nIntSrc2 = pDevice->pRTCRegs->SR2 & ADI_RTC_INT_SOURCE_MASK_SR2; @@ -2376,7 +2377,7 @@ void RTC0_Int_Handler(void) fired |= ADI_RTC_COUNT_INT; } } - + /* CR3OC, CR2IC SR3*/ enables = pDevice->pRTCRegs->CR3SS & (uint16_t)ADI_RTC_INT_ENA_MASK_CR3SS; nIntSrc3 = pDevice->pRTCRegs->SR3 & ADI_RTC_SR3_IRQ_STATUS_MASK; @@ -2398,7 +2399,7 @@ void RTC0_Int_Handler(void) { fired |= ADI_RTC_SENSOR_STROBE_CH1_INT; } - + if( (enables & BITM_RTC_CR3SS_SS4FEIRQEN) && (nIntSrc3 & BITM_RTC_SR3_SS4FEIRQ)) { fired |= ADI_RTC_RTCSS4_FE_INT; @@ -2436,8 +2437,8 @@ void RTC0_Int_Handler(void) fired |= ADI_RTC_INPUT_CAPTURE_CH0_INT; } } - - + + if (pDevice->pfCallback != NULL) { /* forward to the user if he is watching this interrupt */ @@ -2447,18 +2448,18 @@ void RTC0_Int_Handler(void) pDevice->pfCallback (pDevice->pCBParam, fired, NULL); } } - - /* Write 1 to clear the interrupts */ + + /* Write 1 to clear the interrupts */ pDevice->pRTCRegs->SR0 |= nIntSrc0; pDevice->pRTCRegs->SR2 |= nIntSrc2; pDevice->pRTCRegs->SR3 |= nIntSrc3; - ISR_EPILOG(); + ISR_EPILOG(); } /*! @brief RTC device driver interrupt handler. Overrides weakly-bound default interrupt handler in _startup.c. */ void RTC1_Int_Handler(void) { - ISR_PROLOG(); + ISR_PROLOG(); uint16_t nIntSrc0, nIntSrc2, nIntSrc3; uint32_t fired = 0u, enables = 0u; ADI_RTC_DEVICE *pDevice = aRTCDeviceInfo[1].hDevice; @@ -2497,7 +2498,7 @@ void RTC1_Int_Handler(void) fired |= ADI_RTC_WRITE_PENDERR_INT; } } - + /* CR1 SR2 */ enables = (uint32_t)pDevice->pRTCRegs->CR1 & ADI_RTC_INT_ENA_MASK_CR1; nIntSrc2 = pDevice->pRTCRegs->SR2 & ADI_RTC_INT_SOURCE_MASK_SR2; @@ -2524,7 +2525,7 @@ void RTC1_Int_Handler(void) fired |= ADI_RTC_COUNT_INT; } } - + /* CR3OC, CR2IC SR3*/ enables = pDevice->pRTCRegs->CR3SS & (uint32_t)ADI_RTC_INT_ENA_MASK_CR3SS; nIntSrc3 = pDevice->pRTCRegs->SR3 & ADI_RTC_SR3_IRQ_STATUS_MASK; @@ -2546,7 +2547,7 @@ void RTC1_Int_Handler(void) { fired |= ADI_RTC_SENSOR_STROBE_CH1_INT; } - + if( (enables & BITM_RTC_CR3SS_SS4FEIRQEN) && (nIntSrc3 & BITM_RTC_SR3_SS4FEIRQ)) { fired |= ADI_RTC_RTCSS4_FE_INT; @@ -2584,7 +2585,7 @@ void RTC1_Int_Handler(void) fired |= ADI_RTC_INPUT_CAPTURE_CH0_INT; } } - + if (pDevice->pfCallback != NULL) { /* forward to the user if he is watching this interrupt */ @@ -2594,13 +2595,13 @@ void RTC1_Int_Handler(void) pDevice->pfCallback (pDevice->pCBParam, fired, NULL); } } - - /* Write 1 to clear the interrupts */ + + /* Write 1 to clear the interrupts */ pDevice->pRTCRegs->SR0 |= nIntSrc0; pDevice->pRTCRegs->SR2 |= nIntSrc2; pDevice->pRTCRegs->SR3 |= nIntSrc3; - - ISR_EPILOG(); + + ISR_EPILOG(); } /*! \endcond */ diff --git a/targets/TARGET_Freescale/TARGET_KLXX/us_ticker.c b/targets/TARGET_Freescale/TARGET_KLXX/us_ticker.c index 6fcaa1d94b..ffd9cc05c4 100644 --- a/targets/TARGET_Freescale/TARGET_KLXX/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_KLXX/us_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited + * Copyright (c) 2006-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. @@ -18,15 +18,29 @@ #include "PeripheralNames.h" #include "clk_freqs.h" +const ticker_info_t* us_ticker_get_info() +{ + static const ticker_info_t info = { + 1000000, // 1 MHz + 32 // 32 bit counter + }; + return &info; +} + +static bool us_ticker_inited = false; + static void pit_init(void); static void lptmr_init(void); -static int us_ticker_inited = 0; void us_ticker_init(void) { - if (us_ticker_inited) return; - us_ticker_inited = 1; - + if (us_ticker_inited) { + /* calling init again should cancel current interrupt */ + us_ticker_disable_interrupt(); + return; + } + us_ticker_inited = true; + pit_init(); lptmr_init(); } @@ -37,28 +51,25 @@ void us_ticker_init(void) { static void pit_init(void) { SIM->SCGC6 |= SIM_SCGC6_PIT_MASK; // Clock PIT PIT->MCR = 0; // Enable PIT - + // Channel 1 PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF; PIT->CHANNEL[1].TCTRL = PIT_TCTRL_CHN_MASK; // Chain to timer 0, disable Interrupts PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK; // Start timer 1 - + // Use channel 0 as a prescaler for channel 1 PIT->CHANNEL[0].LDVAL = (bus_frequency() + 500000) / 1000000 - 1; PIT->CHANNEL[0].TCTRL = PIT_TCTRL_TEN_MASK; // Start timer 0, disable interrupts } uint32_t us_ticker_read() { - if (!us_ticker_inited) - us_ticker_init(); - // The PIT is a countdown timer return ~(PIT->CHANNEL[1].CVAL); } /****************************************************************************** * Timer Event - * + * * It schedules interrupts at given (32bit)us interval of time. * It is implemented used the 16bit Low Power Timer that remains powered in all * power modes. @@ -66,11 +77,11 @@ uint32_t us_ticker_read() { static void lptmr_isr(void); static void lptmr_init(void) { - uint32_t extosc; + uint32_t extosc; /* Clock the timer */ SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK; - + /* Reset */ LPTMR0->CSR = 0; @@ -114,7 +125,7 @@ static void lptmr_init(void) { } } #if defined(TARGET_KL43Z) - //No suitable actual IRC oscillator clock -> Set it to (8MHz / divider) + //No suitable actual IRC oscillator clock -> Set it to (8MHz / divider) MCG->SC &= ~MCG_SC_FCRDIV_MASK; MCG->MC &= ~MCG->MC & MCG_MC_LIRC_DIV2_MASK; LPTMR0->PSR = LPTMR_PSR_PCS(0) | LPTMR_PSR_PRESCALE(2); @@ -135,7 +146,7 @@ static void lptmr_init(void) { MCG->SC |= MCG_SC_FCRDIV(2); LPTMR0->PSR |= LPTMR_PSR_PBYP_MASK; } -#endif +#endif } void us_ticker_disable_interrupt(void) { @@ -152,13 +163,13 @@ static uint16_t us_ticker_int_remainder = 0; static void lptmr_set(unsigned short count) { /* Reset */ LPTMR0->CSR = 0; - + /* Set the compare register */ LPTMR0->CMR = count; - + /* Enable interrupt */ LPTMR0->CSR |= LPTMR_CSR_TIE_MASK; - + /* Start the timer */ LPTMR0->CSR |= LPTMR_CSR_TEN_MASK; } @@ -166,17 +177,20 @@ static void lptmr_set(unsigned short count) { static void lptmr_isr(void) { // write 1 to TCF to clear the LPT timer compare flag LPTMR0->CSR |= LPTMR_CSR_TCF_MASK; - + if (us_ticker_int_counter > 0) { lptmr_set(0xFFFF); us_ticker_int_counter--; - + } else { if (us_ticker_int_remainder > 0) { lptmr_set(us_ticker_int_remainder); us_ticker_int_remainder = 0; - + } else { + /* Stop the timer */ + LPTMR0->CSR &= ~LPTMR_CSR_TEN_MASK; + // This function is going to disable the interrupts if there are // no other events in the queue us_ticker_irq_handler(); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/us_ticker.c index a7e1a96896..1666223e10 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/us_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited + * Copyright (c) 2006-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. @@ -19,7 +19,16 @@ #include "fsl_pit.h" #include "fsl_clock_config.h" -static int us_ticker_inited = 0; +const ticker_info_t* us_ticker_get_info() +{ + static const ticker_info_t info = { + 1000000, // 1 MHz + 32 // 32 bit counter + }; + return &info; +} + +static bool us_ticker_inited = false; static void pit_isr(void) { @@ -31,15 +40,14 @@ static void pit_isr(void) us_ticker_irq_handler(); } +/** Initialize the high frequency ticker + * + */ void us_ticker_init(void) { - if (us_ticker_inited) { - return; - } - us_ticker_inited = 1; - //Common for ticker/timer + /* Common for ticker/timer. */ uint32_t busClock; - // Structure to initialize PIT + /* Structure to initialize PIT. */ pit_config_t pitConfig; PIT_GetDefaultConfig(&pitConfig); @@ -47,55 +55,83 @@ void us_ticker_init(void) busClock = CLOCK_GetFreq(kCLOCK_BusClk); - //Timer - PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); - PIT_StartTimer(PIT, kPIT_Chnl_0); - PIT_StartTimer(PIT, kPIT_Chnl_1); - - //Ticker - PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); - NVIC_SetVector(PIT3_IRQn, (uint32_t)pit_isr); - NVIC_EnableIRQ(PIT3_IRQn); -} - - -uint32_t us_ticker_read() -{ + /* Let the timer to count if re-init. */ if (!us_ticker_inited) { - us_ticker_init(); + + PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); + PIT_StartTimer(PIT, kPIT_Chnl_0); + PIT_StartTimer(PIT, kPIT_Chnl_1); } + /* Configure interrupt generation counters and disable ticker interrupts. */ + PIT_StopTimer(PIT, kPIT_Chnl_3); + PIT_StopTimer(PIT, kPIT_Chnl_2); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); + NVIC_SetVector(PIT3_IRQn, (uint32_t) pit_isr); + NVIC_EnableIRQ(PIT3_IRQn); + PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); + + us_ticker_inited = true; +} + +/** Read the current counter + * + * @return The current timer's counter value in ticks + */ +uint32_t us_ticker_read() +{ return ~(PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_1)); } +/** Disable us ticker interrupt + * + */ void us_ticker_disable_interrupt(void) { PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); } +/** Clear us ticker interrupt + * + */ void us_ticker_clear_interrupt(void) { PIT_ClearStatusFlags(PIT, kPIT_Chnl_3, PIT_TFLG_TIF_MASK); } +/** Set interrupt for specified timestamp + * + * @param timestamp The time in ticks when interrupt should be generated + */ void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now_us, delta_us; + /* We get here absolute interrupt time which takes into account counter overflow. + * Since we use additional count-down timer to generate interrupt we need to calculate + * load value based on time-stamp. + */ + const uint32_t now_ticks = us_ticker_read(); + uint32_t delta_ticks = + timestamp >= now_ticks ? timestamp - now_ticks : (uint32_t)((uint64_t) timestamp + 0xFFFFFFFF - now_ticks); - now_us = us_ticker_read(); - delta_us = timestamp >= now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); + if (delta_ticks == 0) { + /* The requested delay is less than the minimum resolution of this counter. */ + delta_ticks = 1; + } PIT_StopTimer(PIT, kPIT_Chnl_3); PIT_StopTimer(PIT, kPIT_Chnl_2); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, (uint32_t)delta_us); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, delta_ticks); PIT_EnableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); PIT_StartTimer(PIT, kPIT_Chnl_3); PIT_StartTimer(PIT, kPIT_Chnl_2); } +/** Fire us ticker interrupt + * + */ void us_ticker_fire_interrupt(void) { NVIC_SetPendingIRQ(PIT3_IRQn); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/us_ticker.c index a7e1a96896..1666223e10 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/us_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited + * Copyright (c) 2006-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. @@ -19,7 +19,16 @@ #include "fsl_pit.h" #include "fsl_clock_config.h" -static int us_ticker_inited = 0; +const ticker_info_t* us_ticker_get_info() +{ + static const ticker_info_t info = { + 1000000, // 1 MHz + 32 // 32 bit counter + }; + return &info; +} + +static bool us_ticker_inited = false; static void pit_isr(void) { @@ -31,15 +40,14 @@ static void pit_isr(void) us_ticker_irq_handler(); } +/** Initialize the high frequency ticker + * + */ void us_ticker_init(void) { - if (us_ticker_inited) { - return; - } - us_ticker_inited = 1; - //Common for ticker/timer + /* Common for ticker/timer. */ uint32_t busClock; - // Structure to initialize PIT + /* Structure to initialize PIT. */ pit_config_t pitConfig; PIT_GetDefaultConfig(&pitConfig); @@ -47,55 +55,83 @@ void us_ticker_init(void) busClock = CLOCK_GetFreq(kCLOCK_BusClk); - //Timer - PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); - PIT_StartTimer(PIT, kPIT_Chnl_0); - PIT_StartTimer(PIT, kPIT_Chnl_1); - - //Ticker - PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); - NVIC_SetVector(PIT3_IRQn, (uint32_t)pit_isr); - NVIC_EnableIRQ(PIT3_IRQn); -} - - -uint32_t us_ticker_read() -{ + /* Let the timer to count if re-init. */ if (!us_ticker_inited) { - us_ticker_init(); + + PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); + PIT_StartTimer(PIT, kPIT_Chnl_0); + PIT_StartTimer(PIT, kPIT_Chnl_1); } + /* Configure interrupt generation counters and disable ticker interrupts. */ + PIT_StopTimer(PIT, kPIT_Chnl_3); + PIT_StopTimer(PIT, kPIT_Chnl_2); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); + NVIC_SetVector(PIT3_IRQn, (uint32_t) pit_isr); + NVIC_EnableIRQ(PIT3_IRQn); + PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); + + us_ticker_inited = true; +} + +/** Read the current counter + * + * @return The current timer's counter value in ticks + */ +uint32_t us_ticker_read() +{ return ~(PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_1)); } +/** Disable us ticker interrupt + * + */ void us_ticker_disable_interrupt(void) { PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); } +/** Clear us ticker interrupt + * + */ void us_ticker_clear_interrupt(void) { PIT_ClearStatusFlags(PIT, kPIT_Chnl_3, PIT_TFLG_TIF_MASK); } +/** Set interrupt for specified timestamp + * + * @param timestamp The time in ticks when interrupt should be generated + */ void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now_us, delta_us; + /* We get here absolute interrupt time which takes into account counter overflow. + * Since we use additional count-down timer to generate interrupt we need to calculate + * load value based on time-stamp. + */ + const uint32_t now_ticks = us_ticker_read(); + uint32_t delta_ticks = + timestamp >= now_ticks ? timestamp - now_ticks : (uint32_t)((uint64_t) timestamp + 0xFFFFFFFF - now_ticks); - now_us = us_ticker_read(); - delta_us = timestamp >= now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); + if (delta_ticks == 0) { + /* The requested delay is less than the minimum resolution of this counter. */ + delta_ticks = 1; + } PIT_StopTimer(PIT, kPIT_Chnl_3); PIT_StopTimer(PIT, kPIT_Chnl_2); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, (uint32_t)delta_us); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, delta_ticks); PIT_EnableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); PIT_StartTimer(PIT, kPIT_Chnl_3); PIT_StartTimer(PIT, kPIT_Chnl_2); } +/** Fire us ticker interrupt + * + */ void us_ticker_fire_interrupt(void) { NVIC_SetPendingIRQ(PIT3_IRQn); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/TARGET_FRDM/PeripheralNames.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/TARGET_FRDM/PeripheralNames.h index 5e9ed77bcf..c5f47e2015 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/TARGET_FRDM/PeripheralNames.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/TARGET_FRDM/PeripheralNames.h @@ -50,9 +50,7 @@ typedef enum { PWM_5 = (0 << TPM_SHIFT) | (4), // TPM0 CH4 PWM_6 = (0 << TPM_SHIFT) | (5), // TPM0 CH5 PWM_7 = (1 << TPM_SHIFT) | (0), // TPM1 CH0 - PWM_8 = (1 << TPM_SHIFT) | (1), // TPM1 CH1 - PWM_9 = (2 << TPM_SHIFT) | (0), // TPM2 CH0 - PWM_10 = (2 << TPM_SHIFT) | (1), // TPM2 CH1 + PWM_8 = (1 << TPM_SHIFT) | (1) // TPM1 CH1 } PWMName; #define ADC_INSTANCE_SHIFT 8 diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/TARGET_FRDM/PeripheralPins.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/TARGET_FRDM/PeripheralPins.c index ff132832b6..4f514e438b 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/TARGET_FRDM/PeripheralPins.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/TARGET_FRDM/PeripheralPins.c @@ -180,15 +180,6 @@ const PinMap PinMap_PWM[] = { {PTB0, PWM_7 , 3}, {PTB1, PWM_8 , 3}, - {PTE22, PWM_9 , 3}, - {PTE23, PWM_10, 3}, - {PTA1 , PWM_9 , 3}, - {PTA2 , PWM_10, 3}, - {PTB2 , PWM_9 , 3}, - {PTB3 , PWM_10, 3}, - {PTB18, PWM_9 , 3}, - {PTB19, PWM_10, 3}, - {NC , NC , 0} }; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/TARGET_FRDM/mbed_overrides.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/TARGET_FRDM/mbed_overrides.c index d4577de95f..1018bac9e4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/TARGET_FRDM/mbed_overrides.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/TARGET_FRDM/mbed_overrides.c @@ -22,6 +22,8 @@ void mbed_sdk_init() { BOARD_BootClockRUN(); + /* Set the TPM clock source to be IRC48M, do not change as TPM2 is used for the usticker */ + CLOCK_SetTpmClock(1U); } // Enable the RTC oscillator if available on the board diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/pwmout_api.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/pwmout_api.c index 405446e694..56148464c2 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/pwmout_api.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/pwmout_api.c @@ -36,8 +36,7 @@ void pwmout_init(pwmout_t* obj, PinName pin) uint32_t pwm_base_clock; - /* Set the TPM clock source to be IRC 48M */ - CLOCK_SetTpmClock(1U); + /* TPM clock source is set to IRC48M during init */ pwm_base_clock = CLOCK_GetFreq(kCLOCK_McgIrc48MClk); float clkval = (float)pwm_base_clock / 1000000.0f; uint32_t clkdiv = 0; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/us_ticker.c index e2af074052..3b784bc08e 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL27Z/us_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited + * Copyright (c) 2006-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. @@ -17,91 +17,138 @@ #include "us_ticker_api.h" #include "PeripheralNames.h" #include "fsl_pit.h" -#include "fsl_lptmr.h" +#include "fsl_tpm.h" #include "fsl_clock_config.h" -static int us_ticker_inited = 0; - -static void lptmr_isr(void) +const ticker_info_t* us_ticker_get_info() { - LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag); - LPTMR_StopTimer(LPTMR0); + static const ticker_info_t info = { + 3000000, + 32 + }; + return &info; +} - us_ticker_irq_handler(); +static bool us_ticker_inited = false; + +static uint32_t us_ticker_int_counter = 0; +static uint16_t us_ticker_int_remainder = 0; + +static void tpm_isr(void) +{ + // Clear the TPM timer overflow flag + TPM_ClearStatusFlags(TPM2, kTPM_TimeOverflowFlag); + TPM_StopTimer(TPM2); + + if (us_ticker_int_counter > 0) { + TPM2->MOD = 0xFFFF; + TPM_StartTimer(TPM2, kTPM_SystemClock); + us_ticker_int_counter--; + } else { + if (us_ticker_int_remainder > 0) { + TPM2->MOD = us_ticker_int_remainder; + TPM_StartTimer(TPM2, kTPM_SystemClock); + us_ticker_int_remainder = 0; + } else { + // This function is going to disable the interrupts if there are + // no other events in the queue + us_ticker_irq_handler(); + } + } } void us_ticker_init(void) { + /* Common for ticker/timer. */ + uint32_t busClock; + /* Structure to initialize PIT. */ + pit_config_t pitConfig; + if (us_ticker_inited) { + /* calling init again should cancel current interrupt */ + TPM_DisableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable); return; } - us_ticker_inited = 1; - - //Timer uses PIT - //Common for ticker/timer - uint32_t busClock; - - // Structure to initialize PIT - pit_config_t pitConfig; PIT_GetDefaultConfig(&pitConfig); PIT_Init(PIT, &pitConfig); busClock = CLOCK_GetFreq(kCLOCK_BusClk); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, (busClock / 3000000) - 1); PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); PIT_StartTimer(PIT, kPIT_Chnl_0); PIT_StartTimer(PIT, kPIT_Chnl_1); - //Ticker uses LPTMR - lptmr_config_t lptmrConfig; - LPTMR_GetDefaultConfig(&lptmrConfig); - lptmrConfig.prescalerClockSource = kLPTMR_PrescalerClock_0; - LPTMR_Init(LPTMR0, &lptmrConfig); + /* Configure interrupt generation counters and disable ticker interrupts. */ + tpm_config_t tpmConfig; - busClock = CLOCK_GetFreq(kCLOCK_McgInternalRefClk); - LPTMR_SetTimerPeriod(LPTMR0, busClock / 1000000 - 1); - /* Set interrupt handler */ - NVIC_SetVector(LPTMR0_IRQn, (uint32_t)lptmr_isr); - NVIC_EnableIRQ(LPTMR0_IRQn); + TPM_GetDefaultConfig(&tpmConfig); + /* Set to Div 16 to get 3MHz clock source for TPM */ + tpmConfig.prescale = kTPM_Prescale_Divide_16; + TPM_Init(TPM2, &tpmConfig); + NVIC_SetVector(TPM2_IRQn, (uint32_t)tpm_isr); + NVIC_EnableIRQ(TPM2_IRQn); + + us_ticker_inited = true; } uint32_t us_ticker_read() { - if (!us_ticker_inited) { - us_ticker_init(); - } - return ~(PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_1)); } void us_ticker_disable_interrupt(void) { - LPTMR_DisableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); + TPM_DisableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable); } void us_ticker_clear_interrupt(void) { - LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag); + TPM_ClearStatusFlags(TPM2, kTPM_TimeOverflowFlag); } void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now_us, delta_us; + /* We get here absolute interrupt time which takes into account counter overflow. + * Since we use additional count-down timer to generate interrupt we need to calculate + * load value based on time-stamp. + */ + const uint32_t now_ticks = us_ticker_read(); + uint32_t delta_ticks = + timestamp >= now_ticks ? timestamp - now_ticks : (uint32_t)((uint64_t) timestamp + 0xFFFFFFFF - now_ticks); - now_us = us_ticker_read(); - delta_us = timestamp >= now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); + if (delta_ticks == 0) { + /* The requested delay is less than the minimum resolution of this counter. */ + delta_ticks = 1; + } - LPTMR_StopTimer(LPTMR0); - LPTMR_SetTimerPeriod(LPTMR0, (uint32_t)delta_us); - LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); - LPTMR_StartTimer(LPTMR0); + us_ticker_int_counter = (uint32_t)(delta_ticks >> 16); + us_ticker_int_remainder = (uint16_t)(0xFFFF & delta_ticks); + + TPM_StopTimer(TPM2); + TPM2->CNT = 0; + + if (us_ticker_int_counter > 0) { + TPM2->MOD = 0xFFFF; + us_ticker_int_counter--; + } else { + TPM2->MOD = us_ticker_int_remainder; + us_ticker_int_remainder = 0; + } + + /* Clear the count and set match value */ + TPM_ClearStatusFlags(TPM2, kTPM_TimeOverflowFlag); + TPM_EnableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable); + TPM_StartTimer(TPM2, kTPM_SystemClock); } void us_ticker_fire_interrupt(void) { - NVIC_SetPendingIRQ(LPTMR0_IRQn); + us_ticker_int_counter = 0; + us_ticker_int_remainder = 0; + + NVIC_SetPendingIRQ(TPM2_IRQn); } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralNames.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralNames.h index 48e2fbccd8..aadbf0c23d 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralNames.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralNames.h @@ -50,9 +50,7 @@ typedef enum { PWM_5 = (0 << TPM_SHIFT) | (4), // TPM0 CH4 PWM_6 = (0 << TPM_SHIFT) | (5), // TPM0 CH5 PWM_7 = (1 << TPM_SHIFT) | (0), // TPM1 CH0 - PWM_8 = (1 << TPM_SHIFT) | (1), // TPM1 CH1 - PWM_9 = (2 << TPM_SHIFT) | (0), // TPM2 CH0 - PWM_10 = (2 << TPM_SHIFT) | (1), // TPM2 CH1 + PWM_8 = (1 << TPM_SHIFT) | (1) // TPM1 CH1 } PWMName; #define ADC_INSTANCE_SHIFT 8 diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralPins.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralPins.c index 2fcfe76e65..644f696113 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralPins.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralPins.c @@ -137,21 +137,15 @@ const PinMap PinMap_SPI_SSEL[] = { /************PWM***************/ const PinMap PinMap_PWM[] = { - {PTA0, PWM_6, 3}, // PTA0 , TPM0 CH5 - {PTA1, PWM_9 , 3}, // PTA1 , TPM2 CH0 - {PTA2, PWM_10, 3}, // PTA2 , TPM2 CH1 + {PTA0, PWM_6, 3}, // PTA0 , TPM0 CH5 {PTA3, PWM_1, 3}, // PTA3 , TPM0 CH0 {PTA4, PWM_2 , 3}, // PTA4 , TPM0 CH1 {PTA5, PWM_3 , 3}, // PTA5 , TPM0 CH2 {PTA12, PWM_7 , 3}, // PTA12, TPM1 CH0 - {PTA13, PWM_8 , 3}, // PTA13, TPM1 CH1 + {PTA13, PWM_8 , 3}, // PTA13, TPM1 CH1 {PTB0, PWM_7, 3}, // PTB0 , TPM1 CH0 {PTB1, PWM_8, 3}, // PTB1 , TPM1 CH1 - {PTB2, PWM_9, 3}, // PTB2 , TPM2 CH0 - {PTB3, PWM_10, 3}, // PTB3 , TPM2 CH1 - {PTB18, PWM_9, 3}, // PTB18, TPM2 CH0 - {PTB19, PWM_10, 3}, // PTB18, TPM2 CH1 {PTC1, PWM_1, 4}, // PTC1 , TPM0 CH0 {PTC2, PWM_2, 4}, // PTC2 , TPM0 CH1 @@ -161,14 +155,12 @@ const PinMap PinMap_PWM[] = { {PTD0, PWM_1 , 4}, // PTD0 , TPM0 CH0 {PTD1, PWM_2 , 4}, // PTD0 , TPM0 CH1 {PTD2, PWM_3 , 4}, // PTD2 , TPM0 CH2 - {PTD3, PWM_4 , 4}, // PTD3 , TPM0 CH3 + {PTD3, PWM_4 , 4}, // PTD3 , TPM0 CH3 {PTD4, PWM_5 , 4}, // PTD4 , TPM0 CH4 {PTD5, PWM_6 , 4}, // PTD5 , TPM0 CH5 {PTE20, PWM_7, 3}, // PTE20, TPM1 CH0 {PTE21, PWM_8, 3}, // PTE21, TPM1 CH1 - {PTE22, PWM_9, 3}, // PTE22, TPM2 CH0 - {PTE23, PWM_10, 3}, // PTE23, TPM2 CH1 {PTE24, PWM_1, 3}, // PTE24, TPM0 CH0 {PTE25, PWM_2, 3}, // PTE25, TPM0 CH1 {PTE29, PWM_3, 3}, // PTE29, TPM0 CH2 diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/mbed_overrides.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/mbed_overrides.c index d4577de95f..1018bac9e4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/mbed_overrides.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/mbed_overrides.c @@ -22,6 +22,8 @@ void mbed_sdk_init() { BOARD_BootClockRUN(); + /* Set the TPM clock source to be IRC48M, do not change as TPM2 is used for the usticker */ + CLOCK_SetTpmClock(1U); } // Enable the RTC oscillator if available on the board diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/pwmout_api.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/pwmout_api.c index 405446e694..56148464c2 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/pwmout_api.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/pwmout_api.c @@ -36,8 +36,7 @@ void pwmout_init(pwmout_t* obj, PinName pin) uint32_t pwm_base_clock; - /* Set the TPM clock source to be IRC 48M */ - CLOCK_SetTpmClock(1U); + /* TPM clock source is set to IRC48M during init */ pwm_base_clock = CLOCK_GetFreq(kCLOCK_McgIrc48MClk); float clkval = (float)pwm_base_clock / 1000000.0f; uint32_t clkdiv = 0; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/us_ticker.c index e2af074052..3b784bc08e 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/us_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited + * Copyright (c) 2006-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. @@ -17,91 +17,138 @@ #include "us_ticker_api.h" #include "PeripheralNames.h" #include "fsl_pit.h" -#include "fsl_lptmr.h" +#include "fsl_tpm.h" #include "fsl_clock_config.h" -static int us_ticker_inited = 0; - -static void lptmr_isr(void) +const ticker_info_t* us_ticker_get_info() { - LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag); - LPTMR_StopTimer(LPTMR0); + static const ticker_info_t info = { + 3000000, + 32 + }; + return &info; +} - us_ticker_irq_handler(); +static bool us_ticker_inited = false; + +static uint32_t us_ticker_int_counter = 0; +static uint16_t us_ticker_int_remainder = 0; + +static void tpm_isr(void) +{ + // Clear the TPM timer overflow flag + TPM_ClearStatusFlags(TPM2, kTPM_TimeOverflowFlag); + TPM_StopTimer(TPM2); + + if (us_ticker_int_counter > 0) { + TPM2->MOD = 0xFFFF; + TPM_StartTimer(TPM2, kTPM_SystemClock); + us_ticker_int_counter--; + } else { + if (us_ticker_int_remainder > 0) { + TPM2->MOD = us_ticker_int_remainder; + TPM_StartTimer(TPM2, kTPM_SystemClock); + us_ticker_int_remainder = 0; + } else { + // This function is going to disable the interrupts if there are + // no other events in the queue + us_ticker_irq_handler(); + } + } } void us_ticker_init(void) { + /* Common for ticker/timer. */ + uint32_t busClock; + /* Structure to initialize PIT. */ + pit_config_t pitConfig; + if (us_ticker_inited) { + /* calling init again should cancel current interrupt */ + TPM_DisableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable); return; } - us_ticker_inited = 1; - - //Timer uses PIT - //Common for ticker/timer - uint32_t busClock; - - // Structure to initialize PIT - pit_config_t pitConfig; PIT_GetDefaultConfig(&pitConfig); PIT_Init(PIT, &pitConfig); busClock = CLOCK_GetFreq(kCLOCK_BusClk); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, (busClock / 3000000) - 1); PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); PIT_StartTimer(PIT, kPIT_Chnl_0); PIT_StartTimer(PIT, kPIT_Chnl_1); - //Ticker uses LPTMR - lptmr_config_t lptmrConfig; - LPTMR_GetDefaultConfig(&lptmrConfig); - lptmrConfig.prescalerClockSource = kLPTMR_PrescalerClock_0; - LPTMR_Init(LPTMR0, &lptmrConfig); + /* Configure interrupt generation counters and disable ticker interrupts. */ + tpm_config_t tpmConfig; - busClock = CLOCK_GetFreq(kCLOCK_McgInternalRefClk); - LPTMR_SetTimerPeriod(LPTMR0, busClock / 1000000 - 1); - /* Set interrupt handler */ - NVIC_SetVector(LPTMR0_IRQn, (uint32_t)lptmr_isr); - NVIC_EnableIRQ(LPTMR0_IRQn); + TPM_GetDefaultConfig(&tpmConfig); + /* Set to Div 16 to get 3MHz clock source for TPM */ + tpmConfig.prescale = kTPM_Prescale_Divide_16; + TPM_Init(TPM2, &tpmConfig); + NVIC_SetVector(TPM2_IRQn, (uint32_t)tpm_isr); + NVIC_EnableIRQ(TPM2_IRQn); + + us_ticker_inited = true; } uint32_t us_ticker_read() { - if (!us_ticker_inited) { - us_ticker_init(); - } - return ~(PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_1)); } void us_ticker_disable_interrupt(void) { - LPTMR_DisableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); + TPM_DisableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable); } void us_ticker_clear_interrupt(void) { - LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag); + TPM_ClearStatusFlags(TPM2, kTPM_TimeOverflowFlag); } void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now_us, delta_us; + /* We get here absolute interrupt time which takes into account counter overflow. + * Since we use additional count-down timer to generate interrupt we need to calculate + * load value based on time-stamp. + */ + const uint32_t now_ticks = us_ticker_read(); + uint32_t delta_ticks = + timestamp >= now_ticks ? timestamp - now_ticks : (uint32_t)((uint64_t) timestamp + 0xFFFFFFFF - now_ticks); - now_us = us_ticker_read(); - delta_us = timestamp >= now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); + if (delta_ticks == 0) { + /* The requested delay is less than the minimum resolution of this counter. */ + delta_ticks = 1; + } - LPTMR_StopTimer(LPTMR0); - LPTMR_SetTimerPeriod(LPTMR0, (uint32_t)delta_us); - LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); - LPTMR_StartTimer(LPTMR0); + us_ticker_int_counter = (uint32_t)(delta_ticks >> 16); + us_ticker_int_remainder = (uint16_t)(0xFFFF & delta_ticks); + + TPM_StopTimer(TPM2); + TPM2->CNT = 0; + + if (us_ticker_int_counter > 0) { + TPM2->MOD = 0xFFFF; + us_ticker_int_counter--; + } else { + TPM2->MOD = us_ticker_int_remainder; + us_ticker_int_remainder = 0; + } + + /* Clear the count and set match value */ + TPM_ClearStatusFlags(TPM2, kTPM_TimeOverflowFlag); + TPM_EnableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable); + TPM_StartTimer(TPM2, kTPM_SystemClock); } void us_ticker_fire_interrupt(void) { - NVIC_SetPendingIRQ(LPTMR0_IRQn); + us_ticker_int_counter = 0; + us_ticker_int_remainder = 0; + + NVIC_SetPendingIRQ(TPM2_IRQn); } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_USENSE/mbed_overrides.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_USENSE/mbed_overrides.c index 963b89fea1..19ab30c8a4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_USENSE/mbed_overrides.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/TARGET_USENSE/mbed_overrides.c @@ -46,7 +46,7 @@ void NMI_Handler(void) gpio_init_in(&gpio, PTA4); } -#ifdef DEVICE_RTC +#if DEVICE_RTC || DEVICE_LPTICKER // Enable the RTC oscillator if available on the board void rtc_setup_oscillator(RTC_Type *base) { diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/us_ticker.c index 7205210a3f..456855c4ff 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/us_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited + * Copyright (c) 2006-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. @@ -19,7 +19,16 @@ #include "fsl_pit.h" #include "fsl_clock_config.h" -static int us_ticker_inited = 0; +const ticker_info_t* us_ticker_get_info() +{ + static const ticker_info_t info = { + 1000000, // 1 MHz + 32 // 32 bit counter + }; + return &info; +} + +static bool us_ticker_inited = false; static void pit_isr(void) { @@ -31,15 +40,14 @@ static void pit_isr(void) us_ticker_irq_handler(); } +/** Initialize the high frequency ticker + * + */ void us_ticker_init(void) { - if (us_ticker_inited) { - return; - } - us_ticker_inited = 1; - //Common for ticker/timer + /* Common for ticker/timer. */ uint32_t busClock; - // Structure to initialize PIT + /* Structure to initialize PIT. */ pit_config_t pitConfig; PIT_GetDefaultConfig(&pitConfig); @@ -47,55 +55,83 @@ void us_ticker_init(void) busClock = CLOCK_GetFreq(kCLOCK_BusClk); - //Timer - PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); - PIT_StartTimer(PIT, kPIT_Chnl_0); - PIT_StartTimer(PIT, kPIT_Chnl_1); - - //Ticker - PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); - NVIC_SetVector(PIT0_IRQn, (uint32_t)pit_isr); - NVIC_EnableIRQ(PIT0_IRQn); -} - - -uint32_t us_ticker_read() -{ + /* Let the timer to count if re-init. */ if (!us_ticker_inited) { - us_ticker_init(); + + PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); + PIT_StartTimer(PIT, kPIT_Chnl_0); + PIT_StartTimer(PIT, kPIT_Chnl_1); } + /* Configure interrupt generation counters and disable ticker interrupts. */ + PIT_StopTimer(PIT, kPIT_Chnl_3); + PIT_StopTimer(PIT, kPIT_Chnl_2); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); + NVIC_SetVector(PIT0_IRQn, (uint32_t) pit_isr); + NVIC_EnableIRQ(PIT0_IRQn); + PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); + + us_ticker_inited = true; +} + +/** Read the current counter + * + * @return The current timer's counter value in ticks + */ +uint32_t us_ticker_read() +{ return ~(PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_1)); } +/** Disable us ticker interrupt + * + */ void us_ticker_disable_interrupt(void) { PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); } +/** Clear us ticker interrupt + * + */ void us_ticker_clear_interrupt(void) { PIT_ClearStatusFlags(PIT, kPIT_Chnl_3, PIT_TFLG_TIF_MASK); } +/** Set interrupt for specified timestamp + * + * @param timestamp The time in ticks when interrupt should be generated + */ void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now_us, delta_us; + /* We get here absolute interrupt time which takes into account counter overflow. + * Since we use additional count-down timer to generate interrupt we need to calculate + * load value based on time-stamp. + */ + const uint32_t now_ticks = us_ticker_read(); + uint32_t delta_ticks = + timestamp >= now_ticks ? timestamp - now_ticks : (uint32_t)((uint64_t) timestamp + 0xFFFFFFFF - now_ticks); - now_us = us_ticker_read(); - delta_us = timestamp >= now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); + if (delta_ticks == 0) { + /* The requested delay is less than the minimum resolution of this counter. */ + delta_ticks = 1; + } PIT_StopTimer(PIT, kPIT_Chnl_3); PIT_StopTimer(PIT, kPIT_Chnl_2); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, (uint32_t)delta_us); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, delta_ticks); PIT_EnableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); PIT_StartTimer(PIT, kPIT_Chnl_3); PIT_StartTimer(PIT, kPIT_Chnl_2); } +/** Fire us ticker interrupt + * + */ void us_ticker_fire_interrupt(void) { NVIC_SetPendingIRQ(PIT0_IRQn); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/us_ticker.c index a7e1a96896..1666223e10 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/us_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited + * Copyright (c) 2006-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. @@ -19,7 +19,16 @@ #include "fsl_pit.h" #include "fsl_clock_config.h" -static int us_ticker_inited = 0; +const ticker_info_t* us_ticker_get_info() +{ + static const ticker_info_t info = { + 1000000, // 1 MHz + 32 // 32 bit counter + }; + return &info; +} + +static bool us_ticker_inited = false; static void pit_isr(void) { @@ -31,15 +40,14 @@ static void pit_isr(void) us_ticker_irq_handler(); } +/** Initialize the high frequency ticker + * + */ void us_ticker_init(void) { - if (us_ticker_inited) { - return; - } - us_ticker_inited = 1; - //Common for ticker/timer + /* Common for ticker/timer. */ uint32_t busClock; - // Structure to initialize PIT + /* Structure to initialize PIT. */ pit_config_t pitConfig; PIT_GetDefaultConfig(&pitConfig); @@ -47,55 +55,83 @@ void us_ticker_init(void) busClock = CLOCK_GetFreq(kCLOCK_BusClk); - //Timer - PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); - PIT_StartTimer(PIT, kPIT_Chnl_0); - PIT_StartTimer(PIT, kPIT_Chnl_1); - - //Ticker - PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); - NVIC_SetVector(PIT3_IRQn, (uint32_t)pit_isr); - NVIC_EnableIRQ(PIT3_IRQn); -} - - -uint32_t us_ticker_read() -{ + /* Let the timer to count if re-init. */ if (!us_ticker_inited) { - us_ticker_init(); + + PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); + PIT_StartTimer(PIT, kPIT_Chnl_0); + PIT_StartTimer(PIT, kPIT_Chnl_1); } + /* Configure interrupt generation counters and disable ticker interrupts. */ + PIT_StopTimer(PIT, kPIT_Chnl_3); + PIT_StopTimer(PIT, kPIT_Chnl_2); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); + NVIC_SetVector(PIT3_IRQn, (uint32_t) pit_isr); + NVIC_EnableIRQ(PIT3_IRQn); + PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); + + us_ticker_inited = true; +} + +/** Read the current counter + * + * @return The current timer's counter value in ticks + */ +uint32_t us_ticker_read() +{ return ~(PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_1)); } +/** Disable us ticker interrupt + * + */ void us_ticker_disable_interrupt(void) { PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); } +/** Clear us ticker interrupt + * + */ void us_ticker_clear_interrupt(void) { PIT_ClearStatusFlags(PIT, kPIT_Chnl_3, PIT_TFLG_TIF_MASK); } +/** Set interrupt for specified timestamp + * + * @param timestamp The time in ticks when interrupt should be generated + */ void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now_us, delta_us; + /* We get here absolute interrupt time which takes into account counter overflow. + * Since we use additional count-down timer to generate interrupt we need to calculate + * load value based on time-stamp. + */ + const uint32_t now_ticks = us_ticker_read(); + uint32_t delta_ticks = + timestamp >= now_ticks ? timestamp - now_ticks : (uint32_t)((uint64_t) timestamp + 0xFFFFFFFF - now_ticks); - now_us = us_ticker_read(); - delta_us = timestamp >= now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); + if (delta_ticks == 0) { + /* The requested delay is less than the minimum resolution of this counter. */ + delta_ticks = 1; + } PIT_StopTimer(PIT, kPIT_Chnl_3); PIT_StopTimer(PIT, kPIT_Chnl_2); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, (uint32_t)delta_us); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, delta_ticks); PIT_EnableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); PIT_StartTimer(PIT, kPIT_Chnl_3); PIT_StartTimer(PIT, kPIT_Chnl_2); } +/** Fire us ticker interrupt + * + */ void us_ticker_fire_interrupt(void) { NVIC_SetPendingIRQ(PIT3_IRQn); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/TARGET_FRDM/PeripheralNames.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/TARGET_FRDM/PeripheralNames.h index 025a53573d..3436ae848e 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/TARGET_FRDM/PeripheralNames.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/TARGET_FRDM/PeripheralNames.h @@ -46,9 +46,7 @@ typedef enum { PWM_3 = (0 << TPM_SHIFT) | (2), // TPM0 CH2 PWM_4 = (0 << TPM_SHIFT) | (3), // TPM0 CH3 PWM_5 = (1 << TPM_SHIFT) | (0), // TPM1 CH0 - PWM_6 = (1 << TPM_SHIFT) | (1), // TPM1 CH1 - PWM_7 = (2 << TPM_SHIFT) | (0), // TPM2 CH0 - PWM_8 = (2 << TPM_SHIFT) | (1), // TPM2 CH1 + PWM_6 = (1 << TPM_SHIFT) | (1) // TPM1 CH1 } PWMName; #define ADC_INSTANCE_SHIFT 8 diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/TARGET_FRDM/PeripheralPins.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/TARGET_FRDM/PeripheralPins.c index 9aa121301d..3363bda072 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/TARGET_FRDM/PeripheralPins.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/TARGET_FRDM/PeripheralPins.c @@ -132,12 +132,5 @@ const PinMap PinMap_PWM[] = { {PTB3, PWM_6, 5}, {PTC4, PWM_5, 5}, {PTC5, PWM_6, 5}, - /* TPM 2 */ - {PTA18, PWM_7, 5}, - {PTA19, PWM_8, 5}, - {PTB16, PWM_7, 5}, - {PTB17, PWM_8, 5}, - {PTC6, PWM_7, 5}, - {PTC7, PWM_8, 5}, {NC , NC , 0} }; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/TARGET_FRDM/mbed_overrides.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/TARGET_FRDM/mbed_overrides.c index 1e168d771b..ff33f79a84 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/TARGET_FRDM/mbed_overrides.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/TARGET_FRDM/mbed_overrides.c @@ -21,6 +21,8 @@ void mbed_sdk_init() { BOARD_BootClockRUN(); + /* Set the TPM clock source to be OSCERCLK, do not change as TPM2 is used for the usticker */ + CLOCK_SetTpmClock(2U); } // Enable the RTC oscillator if available on the board diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/pwmout_api.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/pwmout_api.c index 4692859965..2f0e6b0f99 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/pwmout_api.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/pwmout_api.c @@ -36,9 +36,8 @@ void pwmout_init(pwmout_t* obj, PinName pin) uint32_t pwm_base_clock; - /* Set the TPM clock source to be MCG FLL clock */ - CLOCK_SetTpmClock(1U); - pwm_base_clock = CLOCK_GetFreq(kCLOCK_McgFllClk); + /* TPM clock source is set to OSCERCLK during init */ + pwm_base_clock = CLOCK_GetFreq(kCLOCK_Osc0ErClk); float clkval = (float)pwm_base_clock / 1000000.0f; uint32_t clkdiv = 0; while (clkval > 1) { diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/us_ticker.c index e2af074052..fb2eba2aea 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/us_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited + * Copyright (c) 2006-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. @@ -17,32 +17,58 @@ #include "us_ticker_api.h" #include "PeripheralNames.h" #include "fsl_pit.h" -#include "fsl_lptmr.h" +#include "fsl_tpm.h" #include "fsl_clock_config.h" -static int us_ticker_inited = 0; - -static void lptmr_isr(void) +const ticker_info_t* us_ticker_get_info() { - LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag); - LPTMR_StopTimer(LPTMR0); + static const ticker_info_t info = { + 1000000, + 32 + }; + return &info; +} - us_ticker_irq_handler(); +static bool us_ticker_inited = false; + +static uint32_t us_ticker_int_counter = 0; +static uint16_t us_ticker_int_remainder = 0; + +static void tpm_isr(void) +{ + // Clear the TPM timer overflow flag + TPM_ClearStatusFlags(TPM2, kTPM_TimeOverflowFlag); + TPM_StopTimer(TPM2); + + if (us_ticker_int_counter > 0) { + TPM2->MOD = 0xFFFF; + TPM_StartTimer(TPM2, kTPM_SystemClock); + us_ticker_int_counter--; + } else { + if (us_ticker_int_remainder > 0) { + TPM2->MOD = us_ticker_int_remainder; + TPM_StartTimer(TPM2, kTPM_SystemClock); + us_ticker_int_remainder = 0; + } else { + // This function is going to disable the interrupts if there are + // no other events in the queue + us_ticker_irq_handler(); + } + } } void us_ticker_init(void) { + /* Common for ticker/timer. */ + uint32_t busClock; + /* Structure to initialize PIT. */ + pit_config_t pitConfig; + if (us_ticker_inited) { + /* calling init again should cancel current interrupt */ + TPM_DisableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable); return; } - us_ticker_inited = 1; - - //Timer uses PIT - //Common for ticker/timer - uint32_t busClock; - - // Structure to initialize PIT - pit_config_t pitConfig; PIT_GetDefaultConfig(&pitConfig); PIT_Init(PIT, &pitConfig); @@ -55,53 +81,74 @@ void us_ticker_init(void) PIT_StartTimer(PIT, kPIT_Chnl_0); PIT_StartTimer(PIT, kPIT_Chnl_1); - //Ticker uses LPTMR - lptmr_config_t lptmrConfig; - LPTMR_GetDefaultConfig(&lptmrConfig); - lptmrConfig.prescalerClockSource = kLPTMR_PrescalerClock_0; - LPTMR_Init(LPTMR0, &lptmrConfig); + /* Configure interrupt generation counters and disable ticker interrupts. */ + tpm_config_t tpmConfig; - busClock = CLOCK_GetFreq(kCLOCK_McgInternalRefClk); - LPTMR_SetTimerPeriod(LPTMR0, busClock / 1000000 - 1); - /* Set interrupt handler */ - NVIC_SetVector(LPTMR0_IRQn, (uint32_t)lptmr_isr); - NVIC_EnableIRQ(LPTMR0_IRQn); + TPM_GetDefaultConfig(&tpmConfig); + /* Set to Div 32 to get 1MHz clock source for TPM */ + tpmConfig.prescale = kTPM_Prescale_Divide_32; + TPM_Init(TPM2, &tpmConfig); + NVIC_SetVector(TPM2_IRQn, (uint32_t)tpm_isr); + NVIC_EnableIRQ(TPM2_IRQn); + + us_ticker_inited = true; } uint32_t us_ticker_read() { - if (!us_ticker_inited) { - us_ticker_init(); - } - return ~(PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_1)); } void us_ticker_disable_interrupt(void) { - LPTMR_DisableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); + TPM_DisableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable); } void us_ticker_clear_interrupt(void) { - LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag); + TPM_ClearStatusFlags(TPM2, kTPM_TimeOverflowFlag); } void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now_us, delta_us; + /* We get here absolute interrupt time which takes into account counter overflow. + * Since we use additional count-down timer to generate interrupt we need to calculate + * load value based on time-stamp. + */ + const uint32_t now_ticks = us_ticker_read(); + uint32_t delta_ticks = + timestamp >= now_ticks ? timestamp - now_ticks : (uint32_t)((uint64_t) timestamp + 0xFFFFFFFF - now_ticks); - now_us = us_ticker_read(); - delta_us = timestamp >= now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); + if (delta_ticks == 0) { + /* The requested delay is less than the minimum resolution of this counter. */ + delta_ticks = 1; + } - LPTMR_StopTimer(LPTMR0); - LPTMR_SetTimerPeriod(LPTMR0, (uint32_t)delta_us); - LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); - LPTMR_StartTimer(LPTMR0); + us_ticker_int_counter = (uint32_t)(delta_ticks >> 16); + us_ticker_int_remainder = (uint16_t)(0xFFFF & delta_ticks); + + TPM_StopTimer(TPM2); + TPM2->CNT = 0; + + if (us_ticker_int_counter > 0) { + TPM2->MOD = 0xFFFF; + us_ticker_int_counter--; + } else { + TPM2->MOD = us_ticker_int_remainder; + us_ticker_int_remainder = 0; + } + + /* Clear the count and set match value */ + TPM_ClearStatusFlags(TPM2, kTPM_TimeOverflowFlag); + TPM_EnableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable); + TPM_StartTimer(TPM2, kTPM_SystemClock); } void us_ticker_fire_interrupt(void) { - NVIC_SetPendingIRQ(LPTMR0_IRQn); + us_ticker_int_counter = 0; + us_ticker_int_remainder = 0; + + NVIC_SetPendingIRQ(TPM2_IRQn); } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/us_ticker.c index a7e1a96896..1666223e10 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/us_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited + * Copyright (c) 2006-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. @@ -19,7 +19,16 @@ #include "fsl_pit.h" #include "fsl_clock_config.h" -static int us_ticker_inited = 0; +const ticker_info_t* us_ticker_get_info() +{ + static const ticker_info_t info = { + 1000000, // 1 MHz + 32 // 32 bit counter + }; + return &info; +} + +static bool us_ticker_inited = false; static void pit_isr(void) { @@ -31,15 +40,14 @@ static void pit_isr(void) us_ticker_irq_handler(); } +/** Initialize the high frequency ticker + * + */ void us_ticker_init(void) { - if (us_ticker_inited) { - return; - } - us_ticker_inited = 1; - //Common for ticker/timer + /* Common for ticker/timer. */ uint32_t busClock; - // Structure to initialize PIT + /* Structure to initialize PIT. */ pit_config_t pitConfig; PIT_GetDefaultConfig(&pitConfig); @@ -47,55 +55,83 @@ void us_ticker_init(void) busClock = CLOCK_GetFreq(kCLOCK_BusClk); - //Timer - PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); - PIT_StartTimer(PIT, kPIT_Chnl_0); - PIT_StartTimer(PIT, kPIT_Chnl_1); - - //Ticker - PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); - NVIC_SetVector(PIT3_IRQn, (uint32_t)pit_isr); - NVIC_EnableIRQ(PIT3_IRQn); -} - - -uint32_t us_ticker_read() -{ + /* Let the timer to count if re-init. */ if (!us_ticker_inited) { - us_ticker_init(); + + PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); + PIT_StartTimer(PIT, kPIT_Chnl_0); + PIT_StartTimer(PIT, kPIT_Chnl_1); } + /* Configure interrupt generation counters and disable ticker interrupts. */ + PIT_StopTimer(PIT, kPIT_Chnl_3); + PIT_StopTimer(PIT, kPIT_Chnl_2); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); + NVIC_SetVector(PIT3_IRQn, (uint32_t) pit_isr); + NVIC_EnableIRQ(PIT3_IRQn); + PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); + + us_ticker_inited = true; +} + +/** Read the current counter + * + * @return The current timer's counter value in ticks + */ +uint32_t us_ticker_read() +{ return ~(PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_1)); } +/** Disable us ticker interrupt + * + */ void us_ticker_disable_interrupt(void) { PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); } +/** Clear us ticker interrupt + * + */ void us_ticker_clear_interrupt(void) { PIT_ClearStatusFlags(PIT, kPIT_Chnl_3, PIT_TFLG_TIF_MASK); } +/** Set interrupt for specified timestamp + * + * @param timestamp The time in ticks when interrupt should be generated + */ void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now_us, delta_us; + /* We get here absolute interrupt time which takes into account counter overflow. + * Since we use additional count-down timer to generate interrupt we need to calculate + * load value based on time-stamp. + */ + const uint32_t now_ticks = us_ticker_read(); + uint32_t delta_ticks = + timestamp >= now_ticks ? timestamp - now_ticks : (uint32_t)((uint64_t) timestamp + 0xFFFFFFFF - now_ticks); - now_us = us_ticker_read(); - delta_us = timestamp >= now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); + if (delta_ticks == 0) { + /* The requested delay is less than the minimum resolution of this counter. */ + delta_ticks = 1; + } PIT_StopTimer(PIT, kPIT_Chnl_3); PIT_StopTimer(PIT, kPIT_Chnl_2); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, (uint32_t)delta_us); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, delta_ticks); PIT_EnableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); PIT_StartTimer(PIT, kPIT_Chnl_3); PIT_StartTimer(PIT, kPIT_Chnl_2); } +/** Fire us ticker interrupt + * + */ void us_ticker_fire_interrupt(void) { NVIC_SetPendingIRQ(PIT3_IRQn); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/us_ticker.c index 3ce51d72d3..1666223e10 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/us_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2017 ARM Limited + * Copyright (c) 2006-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. @@ -19,7 +19,16 @@ #include "fsl_pit.h" #include "fsl_clock_config.h" -static int us_ticker_inited = 0; +const ticker_info_t* us_ticker_get_info() +{ + static const ticker_info_t info = { + 1000000, // 1 MHz + 32 // 32 bit counter + }; + return &info; +} + +static bool us_ticker_inited = false; static void pit_isr(void) { @@ -31,15 +40,14 @@ static void pit_isr(void) us_ticker_irq_handler(); } +/** Initialize the high frequency ticker + * + */ void us_ticker_init(void) { - if (us_ticker_inited) { - return; - } - us_ticker_inited = 1; - //Common for ticker/timer + /* Common for ticker/timer. */ uint32_t busClock; - // Structure to initialize PIT + /* Structure to initialize PIT. */ pit_config_t pitConfig; PIT_GetDefaultConfig(&pitConfig); @@ -47,55 +55,83 @@ void us_ticker_init(void) busClock = CLOCK_GetFreq(kCLOCK_BusClk); - //Timer - PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); - PIT_StartTimer(PIT, kPIT_Chnl_0); - PIT_StartTimer(PIT, kPIT_Chnl_1); - - //Ticker - PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); - NVIC_SetVector(PIT3_IRQn, (uint32_t)pit_isr); - NVIC_EnableIRQ(PIT3_IRQn); -} - - -uint32_t us_ticker_read() -{ + /* Let the timer to count if re-init. */ if (!us_ticker_inited) { - us_ticker_init(); + + PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); + PIT_StartTimer(PIT, kPIT_Chnl_0); + PIT_StartTimer(PIT, kPIT_Chnl_1); } + /* Configure interrupt generation counters and disable ticker interrupts. */ + PIT_StopTimer(PIT, kPIT_Chnl_3); + PIT_StopTimer(PIT, kPIT_Chnl_2); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); + NVIC_SetVector(PIT3_IRQn, (uint32_t) pit_isr); + NVIC_EnableIRQ(PIT3_IRQn); + PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); + + us_ticker_inited = true; +} + +/** Read the current counter + * + * @return The current timer's counter value in ticks + */ +uint32_t us_ticker_read() +{ return ~(PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_1)); } +/** Disable us ticker interrupt + * + */ void us_ticker_disable_interrupt(void) { PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); } +/** Clear us ticker interrupt + * + */ void us_ticker_clear_interrupt(void) { PIT_ClearStatusFlags(PIT, kPIT_Chnl_3, PIT_TFLG_TIF_MASK); } +/** Set interrupt for specified timestamp + * + * @param timestamp The time in ticks when interrupt should be generated + */ void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now_us, delta_us; + /* We get here absolute interrupt time which takes into account counter overflow. + * Since we use additional count-down timer to generate interrupt we need to calculate + * load value based on time-stamp. + */ + const uint32_t now_ticks = us_ticker_read(); + uint32_t delta_ticks = + timestamp >= now_ticks ? timestamp - now_ticks : (uint32_t)((uint64_t) timestamp + 0xFFFFFFFF - now_ticks); - now_us = us_ticker_read(); - delta_us = timestamp >= now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); + if (delta_ticks == 0) { + /* The requested delay is less than the minimum resolution of this counter. */ + delta_ticks = 1; + } PIT_StopTimer(PIT, kPIT_Chnl_3); PIT_StopTimer(PIT, kPIT_Chnl_2); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, (uint32_t)delta_us); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, delta_ticks); PIT_EnableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); PIT_StartTimer(PIT, kPIT_Chnl_3); PIT_StartTimer(PIT, kPIT_Chnl_2); } +/** Fire us ticker interrupt + * + */ void us_ticker_fire_interrupt(void) { NVIC_SetPendingIRQ(PIT3_IRQn); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/us_ticker.c index a7e1a96896..1666223e10 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/us_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited + * Copyright (c) 2006-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. @@ -19,7 +19,16 @@ #include "fsl_pit.h" #include "fsl_clock_config.h" -static int us_ticker_inited = 0; +const ticker_info_t* us_ticker_get_info() +{ + static const ticker_info_t info = { + 1000000, // 1 MHz + 32 // 32 bit counter + }; + return &info; +} + +static bool us_ticker_inited = false; static void pit_isr(void) { @@ -31,15 +40,14 @@ static void pit_isr(void) us_ticker_irq_handler(); } +/** Initialize the high frequency ticker + * + */ void us_ticker_init(void) { - if (us_ticker_inited) { - return; - } - us_ticker_inited = 1; - //Common for ticker/timer + /* Common for ticker/timer. */ uint32_t busClock; - // Structure to initialize PIT + /* Structure to initialize PIT. */ pit_config_t pitConfig; PIT_GetDefaultConfig(&pitConfig); @@ -47,55 +55,83 @@ void us_ticker_init(void) busClock = CLOCK_GetFreq(kCLOCK_BusClk); - //Timer - PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); - PIT_StartTimer(PIT, kPIT_Chnl_0); - PIT_StartTimer(PIT, kPIT_Chnl_1); - - //Ticker - PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); - NVIC_SetVector(PIT3_IRQn, (uint32_t)pit_isr); - NVIC_EnableIRQ(PIT3_IRQn); -} - - -uint32_t us_ticker_read() -{ + /* Let the timer to count if re-init. */ if (!us_ticker_inited) { - us_ticker_init(); + + PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); + PIT_StartTimer(PIT, kPIT_Chnl_0); + PIT_StartTimer(PIT, kPIT_Chnl_1); } + /* Configure interrupt generation counters and disable ticker interrupts. */ + PIT_StopTimer(PIT, kPIT_Chnl_3); + PIT_StopTimer(PIT, kPIT_Chnl_2); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); + NVIC_SetVector(PIT3_IRQn, (uint32_t) pit_isr); + NVIC_EnableIRQ(PIT3_IRQn); + PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); + + us_ticker_inited = true; +} + +/** Read the current counter + * + * @return The current timer's counter value in ticks + */ +uint32_t us_ticker_read() +{ return ~(PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_1)); } +/** Disable us ticker interrupt + * + */ void us_ticker_disable_interrupt(void) { PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); } +/** Clear us ticker interrupt + * + */ void us_ticker_clear_interrupt(void) { PIT_ClearStatusFlags(PIT, kPIT_Chnl_3, PIT_TFLG_TIF_MASK); } +/** Set interrupt for specified timestamp + * + * @param timestamp The time in ticks when interrupt should be generated + */ void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now_us, delta_us; + /* We get here absolute interrupt time which takes into account counter overflow. + * Since we use additional count-down timer to generate interrupt we need to calculate + * load value based on time-stamp. + */ + const uint32_t now_ticks = us_ticker_read(); + uint32_t delta_ticks = + timestamp >= now_ticks ? timestamp - now_ticks : (uint32_t)((uint64_t) timestamp + 0xFFFFFFFF - now_ticks); - now_us = us_ticker_read(); - delta_us = timestamp >= now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); + if (delta_ticks == 0) { + /* The requested delay is less than the minimum resolution of this counter. */ + delta_ticks = 1; + } PIT_StopTimer(PIT, kPIT_Chnl_3); PIT_StopTimer(PIT, kPIT_Chnl_2); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, (uint32_t)delta_us); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, delta_ticks); PIT_EnableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); PIT_StartTimer(PIT, kPIT_Chnl_3); PIT_StartTimer(PIT, kPIT_Chnl_2); } +/** Fire us ticker interrupt + * + */ void us_ticker_fire_interrupt(void) { NVIC_SetPendingIRQ(PIT3_IRQn); diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/lp_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/lp_ticker.c index 996bf22f53..9d493eac7c 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/lp_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/lp_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2016 ARM Limited + * Copyright (c) 2016 - 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. @@ -14,53 +14,30 @@ * limitations under the License. */ -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER #include "lp_ticker_api.h" -#include "fsl_rtc.h" #include "fsl_lptmr.h" #include "cmsis.h" -#include "rtc_api.h" -#define MAX_SEC_BITS (12) -#define MAX_SEC_MASK ((1 << MAX_SEC_BITS) - 1) -#define SEC_IN_USEC (1000000) +const ticker_info_t* lp_ticker_get_info() +{ + static const ticker_info_t info = { + 32768, // 32kHz + 16 // 16 bit counter + }; + return &info; +} + #define OSC32K_CLK_HZ (32768) -#define MAX_LPTMR_SLEEP ((1 << 16) - 1) static bool lp_ticker_inited = false; -static int lptmr_schedule = 0; -static void rtc_isr(void) -{ - uint32_t sr = RTC->SR; - if (sr & RTC_SR_TOF_MASK) { - // Reset RTC to 0 so it keeps counting - RTC_StopTimer(RTC); - RTC->TSR = 0; - RTC_StartTimer(RTC); - } else if (sr & RTC_SR_TAF_MASK) { - RTC_DisableInterrupts(RTC, kRTC_AlarmInterruptEnable); - RTC->TAR = 0; /* Write clears the IRQ flag */ - - /* Wait subsecond remainder if any */ - if (lptmr_schedule) { - LPTMR_SetTimerPeriod(LPTMR0, lptmr_schedule); - LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); - LPTMR_StartTimer(LPTMR0); - } else { - lp_ticker_irq_handler(); - } - } else if (sr & RTC_SR_TIF_MASK) { - RTC_DisableInterrupts(RTC, kRTC_TimeOverflowInterruptEnable); - } -} +extern void rtc_setup_oscillator(RTC_Type *base); static void lptmr_isr(void) { LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag); - LPTMR_StopTimer(LPTMR0); - lp_ticker_irq_handler(); } @@ -71,106 +48,52 @@ void lp_ticker_init(void) { lptmr_config_t lptmrConfig; - if (lp_ticker_inited) { - return; + if (!lp_ticker_inited) { + /* Setup high resolution clock - LPTMR */ + LPTMR_GetDefaultConfig(&lptmrConfig); + + /* Setup the RTC 32KHz oscillator */ + CLOCK_EnableClock(kCLOCK_Rtc0); + rtc_setup_oscillator(RTC); + /* Use 32kHz drive */ + CLOCK_SetXtal32Freq(OSC32K_CLK_HZ); + + lptmrConfig.prescalerClockSource = kLPTMR_PrescalerClock_2; + lptmrConfig.enableFreeRunning = true; + LPTMR_Init(LPTMR0, &lptmrConfig); + LPTMR_DisableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); + NVIC_ClearPendingIRQ(LPTMR0_IRQn); + NVIC_SetVector(LPTMR0_IRQn, (uint32_t)lptmr_isr); + EnableIRQ(LPTMR0_IRQn); + + lp_ticker_inited = true; + } else { + LPTMR_DisableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); } - lp_ticker_inited = true; - - /* Setup low resolution clock - RTC */ - if (!rtc_isenabled()) { - rtc_init(); - RTC_DisableInterrupts(RTC, kRTC_AlarmInterruptEnable | kRTC_SecondsInterruptEnable); - RTC_StartTimer(RTC); - } - - RTC->TAR = 0; /* Write clears the IRQ flag */ - NVIC_ClearPendingIRQ(RTC_IRQn); - NVIC_SetVector(RTC_IRQn, (uint32_t)rtc_isr); - NVIC_EnableIRQ(RTC_IRQn); - - /* Setup high resolution clock - LPTMR */ - LPTMR_GetDefaultConfig(&lptmrConfig); - /* Use 32kHz drive */ - CLOCK_SetXtal32Freq(OSC32K_CLK_HZ); - lptmrConfig.prescalerClockSource = kLPTMR_PrescalerClock_2; - LPTMR_Init(LPTMR0, &lptmrConfig); - LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); - NVIC_ClearPendingIRQ(LPTMR0_IRQn); - NVIC_SetVector(LPTMR0_IRQn, (uint32_t)lptmr_isr); - EnableIRQ(LPTMR0_IRQn); } /** Read the current counter * - * @return The current timer's counter value in microseconds + * @return The current timer's counter value in ticks */ uint32_t lp_ticker_read(void) { - uint32_t sec, pre; - - if (!lp_ticker_inited) { - lp_ticker_init(); - } - - sec = RTC->TSR; /* 32b: Seconds */ - pre = RTC->TPR; /* 16b: Increments every 32.768kHz clock cycle (30us) */ - - /* Final value: 11b (4095) for sec and 21b for usec (pre can reach 1,000,000us which is close to 1<<20) */ - uint32_t ret = (((sec & MAX_SEC_MASK) * SEC_IN_USEC) + (((uint64_t)pre * SEC_IN_USEC) / OSC32K_CLK_HZ)); - - return ret; + return LPTMR_GetCurrentTimerCount(LPTMR0); } /** Set interrupt for specified timestamp * - * @param timestamp The time in microseconds to be set + * @param timestamp The time in ticks to be set */ void lp_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now_us, delta_us, delta_ticks; - - if (!lp_ticker_inited) { - lp_ticker_init(); - } - - lptmr_schedule = 0; - now_us = lp_ticker_read(); - delta_us = timestamp >= now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); - - /* Checking if LPTRM can handle this sleep */ - delta_ticks = USEC_TO_COUNT(delta_us, CLOCK_GetFreq(kCLOCK_Er32kClk)); - if (delta_ticks == 0) { - /* The requested delay is less than the minimum resolution of this counter */ - delta_ticks = 1; - } - - if (delta_ticks > MAX_LPTMR_SLEEP) { - /* Using RTC if wait time is over 16b (2s @32kHz) */ - uint32_t delta_sec; - - delta_us += COUNT_TO_USEC(RTC->TPR, CLOCK_GetFreq(kCLOCK_Er32kClk)); /* Accounting for started second */ - delta_sec = delta_us / SEC_IN_USEC; - delta_us -= delta_sec * SEC_IN_USEC; - - RTC->TAR = RTC->TSR + delta_sec - 1; - - RTC_EnableInterrupts(RTC, kRTC_AlarmInterruptEnable); - - /* Set aditional, subsecond, sleep time */ - if (delta_us) { - lptmr_schedule = USEC_TO_COUNT(delta_us, CLOCK_GetFreq(kCLOCK_Er32kClk)); - if (lptmr_schedule == 0) { - /* The requested delay is less than the minimum resolution of this counter */ - lptmr_schedule = 1; - } - - } - } else { - /* Below RTC resolution using LPTMR */ - LPTMR_SetTimerPeriod(LPTMR0, delta_ticks); - LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); - LPTMR_StartTimer(LPTMR0); + if (timestamp == 0) { + timestamp = 1; } + LPTMR_SetTimerPeriod(LPTMR0, timestamp); + LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag); + LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); + LPTMR_StartTimer(LPTMR0); } void lp_ticker_fire_interrupt(void) @@ -184,7 +107,6 @@ void lp_ticker_fire_interrupt(void) void lp_ticker_disable_interrupt(void) { LPTMR_DisableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); - RTC_DisableInterrupts(RTC, kRTC_AlarmInterruptEnable); } /** Clear the low power ticker interrupt @@ -192,8 +114,7 @@ void lp_ticker_disable_interrupt(void) */ void lp_ticker_clear_interrupt(void) { - RTC->TAR = 0; /* Write clears the IRQ flag */ LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag); } -#endif /* DEVICE_LOWPOWERTIMER */ +#endif /* DEVICE_LPTICKER */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/rtc_api.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/rtc_api.c index 5de7164ac1..91334e9d59 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/rtc_api.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/rtc_api.c @@ -15,7 +15,7 @@ */ #include "rtc_api.h" -#if DEVICE_RTC +#if DEVICE_RTC || DEVICE_LPTICKER #include "pinmap.h" #include "fsl_rtc.h" @@ -23,6 +23,8 @@ extern void rtc_setup_oscillator(RTC_Type *base); +static bool rtc_time_set = false; + void rtc_init(void) { rtc_config_t rtcConfig; @@ -37,17 +39,30 @@ void rtc_init(void) void rtc_free(void) { - RTC_Deinit(RTC); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + /* Gate the module clock */ + CLOCK_DisableClock(kCLOCK_Rtc0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } /* - * Little check routine to see if the RTC has been enabled + * Little check routine to see if the RTC has been initialized and time has been set * 0 = Disabled, 1 = Enabled */ int rtc_isenabled(void) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(kCLOCK_Rtc0); - return (int)((RTC->SR & RTC_SR_TCE_MASK) >> RTC_SR_TCE_SHIFT); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + + const bool rtc_init_done = ((RTC->SR & RTC_SR_TCE_MASK) >> RTC_SR_TCE_SHIFT); + + /* If RTC is not initialized, then disable the clock gate on exit. */ + if(!rtc_init_done) { + rtc_free(); + } + + return (rtc_init_done & rtc_time_set); } time_t rtc_read(void) @@ -60,6 +75,8 @@ void rtc_write(time_t t) RTC_StopTimer(RTC); RTC->TSR = t; RTC_StartTimer(RTC); + + rtc_time_set = true; } #endif diff --git a/targets/TARGET_Maxim/TARGET_MAX32600/rtc_api.c b/targets/TARGET_Maxim/TARGET_MAX32600/rtc_api.c index 67bd74ce3c..981a1b64cd 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32600/rtc_api.c +++ b/targets/TARGET_Maxim/TARGET_MAX32600/rtc_api.c @@ -33,6 +33,7 @@ #include "rtc_api.h" #include "lp_ticker_api.h" +#include "ticker_api.h" #include "cmsis.h" #include "rtc_regs.h" #include "pwrseq_regs.h" @@ -73,8 +74,10 @@ void rtc_init(void) MXC_PWRSEQ->reg0 |= MXC_F_PWRSEQ_REG0_PWR_RTCEN_RUN; // Prepare interrupt handlers +#ifdef DEVICE_LPTICKER NVIC_SetVector(RTC0_IRQn, (uint32_t)lp_ticker_irq_handler); NVIC_EnableIRQ(RTC0_IRQn); +#endif NVIC_SetVector(RTC3_IRQn, (uint32_t)overflow_handler); NVIC_EnableIRQ(RTC3_IRQn); @@ -235,20 +238,20 @@ void lp_ticker_fire_interrupt(void) } //****************************************************************************** -inline void lp_ticker_disable_interrupt(void) +void lp_ticker_disable_interrupt(void) { MXC_RTCTMR->inten &= ~MXC_F_RTC_INTEN_COMP0; } //****************************************************************************** -inline void lp_ticker_clear_interrupt(void) +void lp_ticker_clear_interrupt(void) { MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS; MXC_PWRSEQ->flags = MXC_F_PWRSEQ_MSK_FLAGS_RTC_CMPR0; } //****************************************************************************** -inline uint32_t lp_ticker_read(void) +uint32_t lp_ticker_read(void) { return rtc_read64(); } diff --git a/targets/TARGET_Maxim/TARGET_MAX32620C/rtc_api.c b/targets/TARGET_Maxim/TARGET_MAX32620C/rtc_api.c index 38ce17209c..aa0a86f76b 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32620C/rtc_api.c +++ b/targets/TARGET_Maxim/TARGET_MAX32620C/rtc_api.c @@ -31,6 +31,7 @@ ******************************************************************************* */ +#include #include "rtc_api.h" #include "lp_ticker_api.h" #include "rtc.h" @@ -83,78 +84,66 @@ static void init_rtc(void) static void overflow_handler(void) { MXC_RTCTMR->comp[1] += ((UINT32_MAX >> LOG2(LP_TIMER_RATE_HZ)) + 1); - RTC_ClearFlags(MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS); + RTC_ClearFlags(MXC_F_RTC_FLAGS_OVERFLOW); } //****************************************************************************** void rtc_init(void) { - if (rtc_inited) { - return; - } - NVIC_SetVector(RTC3_IRQn, (uint32_t)overflow_handler); NVIC_EnableIRQ(RTC3_IRQn); - // Enable wakeup on RTC overflow - LP_ConfigRTCWakeUp(lp_ticker_inited, 0, 0, 1); + + // Enable as LP wakeup source + MXC_PWRSEQ->msk_flags |= MXC_F_PWRSEQ_FLAGS_RTC_ROLLOVER; + init_rtc(); - rtc_inited = 1; } //****************************************************************************** void rtc_free(void) { - if (rtc_inited) { - rtc_inited = 0; - if (lp_ticker_inited) { - RTC_DisableINT(MXC_F_RTC_FLAGS_OVERFLOW); - } else { - MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_CLEAR; - RTC_Stop(); - } - } + while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING); } //****************************************************************************** int rtc_isenabled(void) { - return rtc_inited; + return !!RTC_IsActive(); } //****************************************************************************** void rtc_write(time_t t) { - if (!rtc_inited) { - rtc_init(); - } - MXC_RTCTMR->comp[1] = t - (MXC_RTCTMR->timer >> LOG2(LP_TIMER_RATE_HZ)); - - // Wait for pending transactions while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING); } //****************************************************************************** time_t rtc_read(void) { - if (!rtc_inited) { - rtc_init(); - } - return (MXC_RTCTMR->timer >> LOG2(LP_TIMER_RATE_HZ)) + MXC_RTCTMR->comp[1]; } //****************************************************************************** void lp_ticker_init(void) { - if (lp_ticker_inited) { - return; - } - + RTC_DisableINT(MXC_F_RTC_INTEN_COMP0); NVIC_SetVector(RTC0_IRQn, (uint32_t)lp_ticker_irq_handler); NVIC_EnableIRQ(RTC0_IRQn); init_rtc(); - lp_ticker_inited = 1; +} + +//****************************************************************************** +void lp_ticker_free(void) +{ + // Disable interrupt associated with LPTICKER API + RTC_DisableINT(MXC_F_RTC_INTEN_COMP0); + + // RTC hardware is shared by LPTICKER and RTC APIs. + // Prior initialization of the RTC API gates disabling the RTC hardware. + if (!(MXC_RTCTMR->inten & MXC_F_RTC_INTEN_OVERFLOW)) { + RTC_Stop(); + } } //****************************************************************************** @@ -167,13 +156,13 @@ uint32_t lp_ticker_read(void) void lp_ticker_set_interrupt(timestamp_t timestamp) { MXC_RTCTMR->comp[0] = timestamp; - MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS; - MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0; + MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_COMP0; + RTC_EnableINT(MXC_F_RTC_INTEN_COMP0); - // Enable wakeup from RTC compare 0 - LP_ConfigRTCWakeUp(1, 0, 0, rtc_inited); + // Enable as LP wakeup source + MXC_PWRSEQ->msk_flags |= MXC_F_PWRSEQ_FLAGS_RTC_CMPR0; - // Wait for pending transactions + // Postponed write pending wait for comp0 and flags while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING); } @@ -186,7 +175,7 @@ void lp_ticker_disable_interrupt(void) //****************************************************************************** void lp_ticker_clear_interrupt(void) { - RTC_ClearFlags(MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS); + RTC_ClearFlags(MXC_F_RTC_FLAGS_COMP0); } //****************************************************************************** diff --git a/targets/TARGET_Maxim/TARGET_MAX32620C/us_ticker.c b/targets/TARGET_Maxim/TARGET_MAX32620C/us_ticker.c index baf095b742..dc74a02166 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32620C/us_ticker.c +++ b/targets/TARGET_Maxim/TARGET_MAX32620C/us_ticker.c @@ -41,36 +41,33 @@ #define US_TIMER_MODE TMR32_MODE_COMPARE #define US_TIMER_WIDTH 32 -static volatile int us_ticker_inited = 0; - //****************************************************************************** void us_ticker_init(void) { - tmr32_cfg_t cfg; + // Disable and deconfigure + US_TIMER->ctrl = 0; + US_TIMER->term_cnt32 = 0; + US_TIMER->inten = 0; + US_TIMER->intfl = MXC_F_TMR_INTFL_TIMER0; - if (us_ticker_inited) { - return; - } - us_ticker_inited = 1; + // Configure and enable + US_TIMER->ctrl = MXC_F_TMR_CTRL_ENABLE0 | + (US_TIMER_MODE << MXC_F_TMR_CTRL_MODE_POS) | + (US_TIMER_PRESCALE << MXC_F_TMR_CTRL_PRESCALE_POS); - cfg.mode = US_TIMER_MODE; - cfg.polarity = TMR_POLARITY_UNUSED; - cfg.compareCount = UINT32_MAX; - - TMR_Init(US_TIMER, US_TIMER_PRESCALE, NULL); - TMR32_Config(US_TIMER, &cfg); NVIC_SetVector(US_TIMER_IRQn, (uint32_t)us_ticker_irq_handler); NVIC_EnableIRQ(US_TIMER_IRQn); - TMR32_Start(US_TIMER); +} + +//****************************************************************************** +void us_ticker_free(void) +{ + US_TIMER->ctrl = 0; } //****************************************************************************** uint32_t us_ticker_read(void) { - if (!us_ticker_inited) { - us_ticker_init(); - } - return US_TIMER->count32; } @@ -78,7 +75,7 @@ uint32_t us_ticker_read(void) void us_ticker_set_interrupt(timestamp_t timestamp) { US_TIMER->ctrl = 0; - US_TIMER->term_cnt32 = timestamp; + US_TIMER->term_cnt32 = (timestamp) ? timestamp : 1; US_TIMER->inten = MXC_F_TMR_INTEN_TIMER0; US_TIMER->ctrl = MXC_F_TMR_CTRL_ENABLE0 | (US_TIMER_MODE << MXC_F_TMR_CTRL_MODE_POS) | diff --git a/targets/TARGET_Maxim/TARGET_MAX32625/rtc_api.c b/targets/TARGET_Maxim/TARGET_MAX32625/rtc_api.c index 38ce17209c..aa0a86f76b 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32625/rtc_api.c +++ b/targets/TARGET_Maxim/TARGET_MAX32625/rtc_api.c @@ -31,6 +31,7 @@ ******************************************************************************* */ +#include #include "rtc_api.h" #include "lp_ticker_api.h" #include "rtc.h" @@ -83,78 +84,66 @@ static void init_rtc(void) static void overflow_handler(void) { MXC_RTCTMR->comp[1] += ((UINT32_MAX >> LOG2(LP_TIMER_RATE_HZ)) + 1); - RTC_ClearFlags(MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS); + RTC_ClearFlags(MXC_F_RTC_FLAGS_OVERFLOW); } //****************************************************************************** void rtc_init(void) { - if (rtc_inited) { - return; - } - NVIC_SetVector(RTC3_IRQn, (uint32_t)overflow_handler); NVIC_EnableIRQ(RTC3_IRQn); - // Enable wakeup on RTC overflow - LP_ConfigRTCWakeUp(lp_ticker_inited, 0, 0, 1); + + // Enable as LP wakeup source + MXC_PWRSEQ->msk_flags |= MXC_F_PWRSEQ_FLAGS_RTC_ROLLOVER; + init_rtc(); - rtc_inited = 1; } //****************************************************************************** void rtc_free(void) { - if (rtc_inited) { - rtc_inited = 0; - if (lp_ticker_inited) { - RTC_DisableINT(MXC_F_RTC_FLAGS_OVERFLOW); - } else { - MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_CLEAR; - RTC_Stop(); - } - } + while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING); } //****************************************************************************** int rtc_isenabled(void) { - return rtc_inited; + return !!RTC_IsActive(); } //****************************************************************************** void rtc_write(time_t t) { - if (!rtc_inited) { - rtc_init(); - } - MXC_RTCTMR->comp[1] = t - (MXC_RTCTMR->timer >> LOG2(LP_TIMER_RATE_HZ)); - - // Wait for pending transactions while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING); } //****************************************************************************** time_t rtc_read(void) { - if (!rtc_inited) { - rtc_init(); - } - return (MXC_RTCTMR->timer >> LOG2(LP_TIMER_RATE_HZ)) + MXC_RTCTMR->comp[1]; } //****************************************************************************** void lp_ticker_init(void) { - if (lp_ticker_inited) { - return; - } - + RTC_DisableINT(MXC_F_RTC_INTEN_COMP0); NVIC_SetVector(RTC0_IRQn, (uint32_t)lp_ticker_irq_handler); NVIC_EnableIRQ(RTC0_IRQn); init_rtc(); - lp_ticker_inited = 1; +} + +//****************************************************************************** +void lp_ticker_free(void) +{ + // Disable interrupt associated with LPTICKER API + RTC_DisableINT(MXC_F_RTC_INTEN_COMP0); + + // RTC hardware is shared by LPTICKER and RTC APIs. + // Prior initialization of the RTC API gates disabling the RTC hardware. + if (!(MXC_RTCTMR->inten & MXC_F_RTC_INTEN_OVERFLOW)) { + RTC_Stop(); + } } //****************************************************************************** @@ -167,13 +156,13 @@ uint32_t lp_ticker_read(void) void lp_ticker_set_interrupt(timestamp_t timestamp) { MXC_RTCTMR->comp[0] = timestamp; - MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS; - MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0; + MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_COMP0; + RTC_EnableINT(MXC_F_RTC_INTEN_COMP0); - // Enable wakeup from RTC compare 0 - LP_ConfigRTCWakeUp(1, 0, 0, rtc_inited); + // Enable as LP wakeup source + MXC_PWRSEQ->msk_flags |= MXC_F_PWRSEQ_FLAGS_RTC_CMPR0; - // Wait for pending transactions + // Postponed write pending wait for comp0 and flags while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING); } @@ -186,7 +175,7 @@ void lp_ticker_disable_interrupt(void) //****************************************************************************** void lp_ticker_clear_interrupt(void) { - RTC_ClearFlags(MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS); + RTC_ClearFlags(MXC_F_RTC_FLAGS_COMP0); } //****************************************************************************** diff --git a/targets/TARGET_Maxim/TARGET_MAX32625/us_ticker.c b/targets/TARGET_Maxim/TARGET_MAX32625/us_ticker.c index baf095b742..dc74a02166 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32625/us_ticker.c +++ b/targets/TARGET_Maxim/TARGET_MAX32625/us_ticker.c @@ -41,36 +41,33 @@ #define US_TIMER_MODE TMR32_MODE_COMPARE #define US_TIMER_WIDTH 32 -static volatile int us_ticker_inited = 0; - //****************************************************************************** void us_ticker_init(void) { - tmr32_cfg_t cfg; + // Disable and deconfigure + US_TIMER->ctrl = 0; + US_TIMER->term_cnt32 = 0; + US_TIMER->inten = 0; + US_TIMER->intfl = MXC_F_TMR_INTFL_TIMER0; - if (us_ticker_inited) { - return; - } - us_ticker_inited = 1; + // Configure and enable + US_TIMER->ctrl = MXC_F_TMR_CTRL_ENABLE0 | + (US_TIMER_MODE << MXC_F_TMR_CTRL_MODE_POS) | + (US_TIMER_PRESCALE << MXC_F_TMR_CTRL_PRESCALE_POS); - cfg.mode = US_TIMER_MODE; - cfg.polarity = TMR_POLARITY_UNUSED; - cfg.compareCount = UINT32_MAX; - - TMR_Init(US_TIMER, US_TIMER_PRESCALE, NULL); - TMR32_Config(US_TIMER, &cfg); NVIC_SetVector(US_TIMER_IRQn, (uint32_t)us_ticker_irq_handler); NVIC_EnableIRQ(US_TIMER_IRQn); - TMR32_Start(US_TIMER); +} + +//****************************************************************************** +void us_ticker_free(void) +{ + US_TIMER->ctrl = 0; } //****************************************************************************** uint32_t us_ticker_read(void) { - if (!us_ticker_inited) { - us_ticker_init(); - } - return US_TIMER->count32; } @@ -78,7 +75,7 @@ uint32_t us_ticker_read(void) void us_ticker_set_interrupt(timestamp_t timestamp) { US_TIMER->ctrl = 0; - US_TIMER->term_cnt32 = timestamp; + US_TIMER->term_cnt32 = (timestamp) ? timestamp : 1; US_TIMER->inten = MXC_F_TMR_INTEN_TIMER0; US_TIMER->ctrl = MXC_F_TMR_CTRL_ENABLE0 | (US_TIMER_MODE << MXC_F_TMR_CTRL_MODE_POS) | diff --git a/targets/TARGET_Maxim/TARGET_MAX32630/rtc_api.c b/targets/TARGET_Maxim/TARGET_MAX32630/rtc_api.c index 5c1d3274a6..aa0a86f76b 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32630/rtc_api.c +++ b/targets/TARGET_Maxim/TARGET_MAX32630/rtc_api.c @@ -31,6 +31,7 @@ ******************************************************************************* */ +#include #include "rtc_api.h" #include "lp_ticker_api.h" #include "rtc.h" @@ -83,78 +84,66 @@ static void init_rtc(void) static void overflow_handler(void) { MXC_RTCTMR->comp[1] += ((UINT32_MAX >> LOG2(LP_TIMER_RATE_HZ)) + 1); - RTC_ClearFlags(MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS); + RTC_ClearFlags(MXC_F_RTC_FLAGS_OVERFLOW); } //****************************************************************************** void rtc_init(void) { - if (rtc_inited) { - return; - } - NVIC_SetVector(RTC3_IRQn, (uint32_t)overflow_handler); NVIC_EnableIRQ(RTC3_IRQn); - // Enable wakeup on RTC overflow - LP_ConfigRTCWakeUp(lp_ticker_inited, 0, 0, 1); + + // Enable as LP wakeup source + MXC_PWRSEQ->msk_flags |= MXC_F_PWRSEQ_FLAGS_RTC_ROLLOVER; + init_rtc(); - rtc_inited = 1; } //****************************************************************************** void rtc_free(void) { - if (rtc_inited) { - rtc_inited = 0; - if (lp_ticker_inited) { - RTC_DisableINT(MXC_F_RTC_FLAGS_OVERFLOW); - } else { - MXC_RTCTMR->ctrl |= MXC_F_RTC_CTRL_CLEAR; - RTC_Stop(); - } - } + while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING); } //****************************************************************************** int rtc_isenabled(void) { - return rtc_inited; + return !!RTC_IsActive(); } //****************************************************************************** void rtc_write(time_t t) { - if (!rtc_inited) { - rtc_init(); - } - MXC_RTCTMR->comp[1] = t - (MXC_RTCTMR->timer >> LOG2(LP_TIMER_RATE_HZ)); - - // Wait for pending transactions while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING); } //****************************************************************************** time_t rtc_read(void) { - if (!rtc_inited) { - rtc_init(); - } - return (MXC_RTCTMR->timer >> LOG2(LP_TIMER_RATE_HZ)) + MXC_RTCTMR->comp[1]; } //****************************************************************************** void lp_ticker_init(void) { - if (lp_ticker_inited) { - return; - } - + RTC_DisableINT(MXC_F_RTC_INTEN_COMP0); NVIC_SetVector(RTC0_IRQn, (uint32_t)lp_ticker_irq_handler); NVIC_EnableIRQ(RTC0_IRQn); init_rtc(); - lp_ticker_inited = 1; +} + +//****************************************************************************** +void lp_ticker_free(void) +{ + // Disable interrupt associated with LPTICKER API + RTC_DisableINT(MXC_F_RTC_INTEN_COMP0); + + // RTC hardware is shared by LPTICKER and RTC APIs. + // Prior initialization of the RTC API gates disabling the RTC hardware. + if (!(MXC_RTCTMR->inten & MXC_F_RTC_INTEN_OVERFLOW)) { + RTC_Stop(); + } } //****************************************************************************** @@ -167,13 +156,13 @@ uint32_t lp_ticker_read(void) void lp_ticker_set_interrupt(timestamp_t timestamp) { MXC_RTCTMR->comp[0] = timestamp; - MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS; - MXC_RTCTMR->inten |= MXC_F_RTC_INTEN_COMP0; + MXC_RTCTMR->flags = MXC_F_RTC_FLAGS_COMP0; + RTC_EnableINT(MXC_F_RTC_INTEN_COMP0); - // Enable wakeup from RTC compare 0 - LP_ConfigRTCWakeUp(1, 0, 0, rtc_inited); + // Enable as LP wakeup source + MXC_PWRSEQ->msk_flags |= MXC_F_PWRSEQ_FLAGS_RTC_CMPR0; - // Wait for pending transactions + // Postponed write pending wait for comp0 and flags while (MXC_RTCTMR->ctrl & MXC_F_RTC_CTRL_PENDING); } @@ -186,7 +175,7 @@ void lp_ticker_disable_interrupt(void) //****************************************************************************** void lp_ticker_clear_interrupt(void) { - RTC_ClearFlags(MXC_F_RTC_FLAGS_ASYNC_CLR_FLAGS); + RTC_ClearFlags(MXC_F_RTC_FLAGS_COMP0); } //****************************************************************************** diff --git a/targets/TARGET_Maxim/TARGET_MAX32630/us_ticker.c b/targets/TARGET_Maxim/TARGET_MAX32630/us_ticker.c index 8a33b4c550..dc74a02166 100644 --- a/targets/TARGET_Maxim/TARGET_MAX32630/us_ticker.c +++ b/targets/TARGET_Maxim/TARGET_MAX32630/us_ticker.c @@ -35,42 +35,39 @@ #include "us_ticker_api.h" #include "tmr.h" -#define US_TIMER MXC_TMR0 -#define US_TIMER_IRQn TMR0_0_IRQn -#define US_TIMER_PRESCALE TMR_PRESCALE_DIV_2_5 -#define US_TIMER_MODE TMR32_MODE_COMPARE -#define US_TIMER_WIDTH 32 - -static volatile int us_ticker_inited = 0; +#define US_TIMER MXC_TMR0 +#define US_TIMER_IRQn TMR0_0_IRQn +#define US_TIMER_PRESCALE TMR_PRESCALE_DIV_2_5 +#define US_TIMER_MODE TMR32_MODE_COMPARE +#define US_TIMER_WIDTH 32 //****************************************************************************** void us_ticker_init(void) { - tmr32_cfg_t cfg; + // Disable and deconfigure + US_TIMER->ctrl = 0; + US_TIMER->term_cnt32 = 0; + US_TIMER->inten = 0; + US_TIMER->intfl = MXC_F_TMR_INTFL_TIMER0; - if (us_ticker_inited) { - return; - } - us_ticker_inited = 1; + // Configure and enable + US_TIMER->ctrl = MXC_F_TMR_CTRL_ENABLE0 | + (US_TIMER_MODE << MXC_F_TMR_CTRL_MODE_POS) | + (US_TIMER_PRESCALE << MXC_F_TMR_CTRL_PRESCALE_POS); - cfg.mode = US_TIMER_MODE; - cfg.polarity = TMR_POLARITY_UNUSED; - cfg.compareCount = UINT32_MAX; - - TMR_Init(US_TIMER, US_TIMER_PRESCALE, NULL); - TMR32_Config(US_TIMER, &cfg); NVIC_SetVector(US_TIMER_IRQn, (uint32_t)us_ticker_irq_handler); NVIC_EnableIRQ(US_TIMER_IRQn); - TMR32_Start(US_TIMER); +} + +//****************************************************************************** +void us_ticker_free(void) +{ + US_TIMER->ctrl = 0; } //****************************************************************************** uint32_t us_ticker_read(void) { - if (!us_ticker_inited) { - us_ticker_init(); - } - return US_TIMER->count32; } @@ -78,12 +75,12 @@ uint32_t us_ticker_read(void) void us_ticker_set_interrupt(timestamp_t timestamp) { US_TIMER->ctrl = 0; - US_TIMER->term_cnt32 = timestamp; + US_TIMER->term_cnt32 = (timestamp) ? timestamp : 1; US_TIMER->inten = MXC_F_TMR_INTEN_TIMER0; US_TIMER->ctrl = MXC_F_TMR_CTRL_ENABLE0 | (US_TIMER_MODE << MXC_F_TMR_CTRL_MODE_POS) | (US_TIMER_PRESCALE << MXC_F_TMR_CTRL_PRESCALE_POS); - } +} //****************************************************************************** void us_ticker_fire_interrupt(void) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/common_rtc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/common_rtc.h index 2ebe70ecf7..dae27b263c 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/common_rtc.h +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/common_rtc.h @@ -20,29 +20,21 @@ #include "nrf_rtc.h" #define RTC_COUNTER_BITS 24u +#define RTC_FREQ 32768u // Instance 0 is reserved for SoftDevice. -// Instance 1 is used as a common one for us_ticker, lp_ticker and (in case +// Instance 1 is used as a common one for lp_ticker and (in case // of NRF51) as an alternative tick source for RTOS. -// ["us_ticker.c" uses hard coded addresses of the 'NRF_RTC1->EVENT_COMPARE[1]' -// register in inline assembly implementations of COMMON_RTC_IRQ_HANDLER, -// please remember to update those in case of doing changes here] #define COMMON_RTC_INSTANCE NRF_RTC1 #define COMMON_RTC_IRQ_HANDLER RTC1_IRQHandler -#define US_TICKER_CC_CHANNEL 0 -#define OS_TICK_CC_CHANNEL 1 -#define LP_TICKER_CC_CHANNEL 2 - -#define US_TICKER_SW_IRQ_MASK 0x1 -#define LP_TICKER_SW_IRQ_MASK 0x2 +#define OS_TICK_CC_CHANNEL 0 +#define LP_TICKER_CC_CHANNEL 1 #define COMMON_RTC_EVENT_COMPARE(channel) \ CONCAT_2(NRF_RTC_EVENT_COMPARE_, channel) #define COMMON_RTC_INT_COMPARE_MASK(channel) \ CONCAT_3(NRF_RTC_INT_COMPARE, channel, _MASK) -#define US_TICKER_EVENT COMMON_RTC_EVENT_COMPARE(US_TICKER_CC_CHANNEL) -#define US_TICKER_INT_MASK COMMON_RTC_INT_COMPARE_MASK(US_TICKER_CC_CHANNEL) #define OS_TICK_EVENT COMMON_RTC_EVENT_COMPARE(OS_TICK_CC_CHANNEL) #define OS_TICK_INT_MASK COMMON_RTC_INT_COMPARE_MASK(OS_TICK_CC_CHANNEL) #define LP_TICKER_EVENT COMMON_RTC_EVENT_COMPARE(LP_TICKER_CC_CHANNEL) @@ -50,7 +42,7 @@ extern bool m_common_rtc_enabled; extern uint32_t volatile m_common_rtc_overflows; -extern uint8_t volatile m_common_sw_irq_flag; +extern bool volatile lp_ticker_interrupt_fire; void common_rtc_init(void); uint32_t common_rtc_32bit_ticks_get(void); diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/flash_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/flash_api.c index be592b8b36..032dfd2ae1 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/flash_api.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/flash_api.c @@ -36,7 +36,7 @@ * */ -#if DEVICE_FLASH +#if (defined(DEVICE_FLASH) && defined(DEVICE_LPTICKER)) #include "hal/flash_api.h" #include "hal/lp_ticker_api.h" diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/lp_ticker.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/lp_ticker.c index def44835e2..9e197d8555 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/lp_ticker.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/lp_ticker.c @@ -14,20 +14,35 @@ * limitations under the License. */ #include "lp_ticker_api.h" - -#if DEVICE_LOWPOWERTIMER - #include "common_rtc.h" -#include "mbed_critical.h" +#include "platform/mbed_critical.h" + +#if DEVICE_LPTICKER + +/* LP ticker is driven by 32kHz clock and counter length is 24 bits. */ +const ticker_info_t* lp_ticker_get_info() +{ + static const ticker_info_t info = { + RTC_FREQ, + RTC_COUNTER_BITS + }; + return &info; +} void lp_ticker_init(void) { common_rtc_init(); } +void lp_ticker_free(void) +{ + // A common counter is used for RTC, lp_ticker and us_ticker, so it can't be + // disabled here, but this does not cause any extra cost. +} + uint32_t lp_ticker_read() { - return (uint32_t)common_rtc_64bit_us_get(); + return nrf_rtc_counter_get(COMMON_RTC_INSTANCE); } void lp_ticker_set_interrupt(timestamp_t timestamp) @@ -39,14 +54,17 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) void lp_ticker_fire_interrupt(void) { core_util_critical_section_enter(); - m_common_sw_irq_flag |= LP_TICKER_SW_IRQ_MASK; + + lp_ticker_interrupt_fire = true; + NVIC_SetPendingIRQ(RTC1_IRQn); + core_util_critical_section_exit(); } void lp_ticker_disable_interrupt(void) { - nrf_rtc_event_disable(COMMON_RTC_INSTANCE, LP_TICKER_INT_MASK); + nrf_rtc_int_disable(COMMON_RTC_INSTANCE, LP_TICKER_INT_MASK); } void lp_ticker_clear_interrupt(void) @@ -54,4 +72,4 @@ void lp_ticker_clear_interrupt(void) nrf_rtc_event_clear(COMMON_RTC_INSTANCE, LP_TICKER_EVENT); } -#endif // DEVICE_LOWPOWERTIMER +#endif // DEVICE_LPTICKER diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/sleep.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/sleep.c index f806e7a0a6..97e22c6541 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/sleep.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/sleep.c @@ -18,6 +18,8 @@ #include "mbed_interface.h" #include "softdevice_handler.h" #include "nrf_soc.h" +#include "nrf_timer.h" +#include "us_ticker.h" // Mask of reserved bits of the register ICSR in the System Control Block peripheral // In this case, bits which are equal to 0 are the bits reserved in this register @@ -25,6 +27,8 @@ #define FPU_EXCEPTION_MASK 0x0000009F +extern bool us_ticker_initialized; + void hal_sleep(void) { // ensure debug is disconnected if semihost is enabled.... @@ -75,6 +79,15 @@ void hal_sleep(void) void hal_deepsleep(void) { + if (us_ticker_initialized) { + nrf_timer_task_trigger(NRF_TIMER1, NRF_TIMER_TASK_STOP); + } + hal_sleep(); + + if (us_ticker_initialized) { + nrf_timer_task_trigger(NRF_TIMER1, NRF_TIMER_TASK_START); + } + // NRF_POWER->SYSTEMOFF=1; } diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/trng_api.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/trng_api.c index 532f18fd6d..7837eb4cb8 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/trng_api.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/trng_api.c @@ -36,7 +36,7 @@ * */ -#if defined(DEVICE_TRNG) +#if (defined(DEVICE_TRNG) && defined(DEVICE_LPTICKER)) #include "hal/trng_api.h" #include "hal/lp_ticker_api.h" diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/us_ticker.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/us_ticker.c index a830545d53..0ab3738bb1 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/us_ticker.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/us_ticker.c @@ -36,132 +36,57 @@ * */ +#include "us_ticker.h" + #include "us_ticker_api.h" -#include "common_rtc.h" -#include "app_util.h" +#include "nrf_timer.h" +#include "app_util_platform.h" #include "nrf_drv_common.h" -#include "lp_ticker_api.h" #include "mbed_critical.h" -#if defined(NRF52_ERRATA_20) - #include "softdevice_handler.h" -#endif +bool us_ticker_initialized = false; -//------------------------------------------------------------------------------ -// Common stuff used also by lp_ticker and rtc_api (see "common_rtc.h"). -// -#include "app_util_platform.h" - -bool m_common_rtc_enabled = false; -uint32_t volatile m_common_rtc_overflows = 0; - -// lp/us ticker fire interrupt flag for IRQ handler -volatile uint8_t m_common_sw_irq_flag = 0; - -__STATIC_INLINE void rtc_ovf_event_check(void) +/* us ticker is driven by 1MHz clock and counter length is 16 bits. */ +const ticker_info_t* us_ticker_get_info() { - if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW)) { - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); - // Don't disable this event. It shall occur periodically. - - ++m_common_rtc_overflows; - } + static const ticker_info_t info = { + US_TICKER_FREQ, + US_TICKER_COUNTER_BITS + }; + return &info; } -#if defined(TARGET_MCU_NRF51822) -void common_rtc_irq_handler(void) -#else -void COMMON_RTC_IRQ_HANDLER(void) -#endif +void us_ticker_init(void) { - - rtc_ovf_event_check(); - - if ((m_common_sw_irq_flag & US_TICKER_SW_IRQ_MASK) || nrf_rtc_event_pending(COMMON_RTC_INSTANCE, US_TICKER_EVENT)) { - us_ticker_irq_handler(); - } - -#if DEVICE_LOWPOWERTIMER - if (m_common_sw_irq_flag & LP_TICKER_SW_IRQ_MASK) { - m_common_sw_irq_flag &= ~LP_TICKER_SW_IRQ_MASK; - lp_ticker_irq_handler(); - } - if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, LP_TICKER_EVENT)) { - - lp_ticker_irq_handler(); - } -#endif -} - -// Function for fix errata 20: RTC Register values are invalid -__STATIC_INLINE void errata_20(void) -{ -#if defined(NRF52_ERRATA_20) - if (!softdevice_handler_is_enabled()) - { - NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; - NRF_CLOCK->TASKS_LFCLKSTART = 1; - - while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) - { - } - } - NRF_RTC1->TASKS_STOP = 0; -#endif -} - -void RTC1_IRQHandler(void); - -void common_rtc_init(void) -{ - if (m_common_rtc_enabled) { + if (us_ticker_initialized) { + nrf_timer_event_clear(NRF_TIMER1, NRF_TIMER_EVENT_COMPARE0); + nrf_timer_int_disable(NRF_TIMER1, nrf_timer_compare_int_get(NRF_TIMER_CC_CHANNEL0)); return; } - errata_20(); + nrf_timer_task_trigger(NRF_TIMER1, NRF_TIMER_TASK_STOP); - NVIC_SetVector(RTC1_IRQn, (uint32_t)RTC1_IRQHandler); - - // RTC is driven by the low frequency (32.768 kHz) clock, a proper request - // must be made to have it running. - // Currently this clock is started in 'SystemInit' (see "system_nrf51.c" - // or "system_nrf52.c", respectively). + nrf_timer_int_disable(NRF_TIMER1, nrf_timer_compare_int_get(NRF_TIMER_CC_CHANNEL0)); - nrf_rtc_prescaler_set(COMMON_RTC_INSTANCE, 0); + /* Configure timer as follows: + * - timer mode, + * - timer width 16 bits, + * - timer freq 1 MHz. + */ + nrf_timer_mode_set(NRF_TIMER1, NRF_TIMER_MODE_TIMER); - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, US_TICKER_EVENT); -#if defined(TARGET_MCU_NRF51822) - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, OS_TICK_EVENT); -#endif -#if DEVICE_LOWPOWERTIMER - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, LP_TICKER_EVENT); -#endif - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); + nrf_timer_frequency_set(NRF_TIMER1, NRF_TIMER_FREQ_1MHz); - // Interrupts on all related events are enabled permanently. Particular - // events will be enabled or disabled as needed (such approach is more - // energy efficient). - nrf_rtc_int_enable(COMMON_RTC_INSTANCE, -#if DEVICE_LOWPOWERTIMER - LP_TICKER_INT_MASK | -#endif - US_TICKER_INT_MASK | - NRF_RTC_INT_OVERFLOW_MASK); + nrf_timer_bit_width_set(NRF_TIMER1, NRF_TIMER_BIT_WIDTH_16); - // This event is enabled permanently, since overflow indications are needed - // continuously. - nrf_rtc_event_enable(COMMON_RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK); - // All other relevant events are initially disabled. - nrf_rtc_event_disable(COMMON_RTC_INSTANCE, -#if defined(TARGET_MCU_NRF51822) - OS_TICK_INT_MASK | -#endif -#if DEVICE_LOWPOWERTIMER - LP_TICKER_INT_MASK | -#endif - US_TICKER_INT_MASK); + nrf_timer_cc_write(NRF_TIMER1, NRF_TIMER_CC_CHANNEL0, 0); + + nrf_timer_event_clear(NRF_TIMER1, NRF_TIMER_EVENT_COMPARE0); + + NVIC_SetVector(TIMER1_IRQn, (uint32_t)us_ticker_irq_handler); + + nrf_drv_common_irq_enable(TIMER1_IRQn, - nrf_drv_common_irq_enable(nrf_drv_get_IRQn(COMMON_RTC_INSTANCE), #ifdef NRF51 APP_IRQ_PRIORITY_LOW #elif defined(NRF52) || defined(NRF52840_XXAA) @@ -169,161 +94,49 @@ void common_rtc_init(void) #endif ); - nrf_rtc_task_trigger(COMMON_RTC_INSTANCE, NRF_RTC_TASK_START); + nrf_timer_task_trigger(NRF_TIMER1, NRF_TIMER_TASK_START); - m_common_rtc_enabled = true; -} - -__STATIC_INLINE void rtc_ovf_event_safe_check(void) -{ - core_util_critical_section_enter(); - - rtc_ovf_event_check(); - - core_util_critical_section_exit(); -} - - -uint32_t common_rtc_32bit_ticks_get(void) -{ - uint32_t ticks; - uint32_t prev_overflows; - - do { - prev_overflows = m_common_rtc_overflows; - - ticks = nrf_rtc_counter_get(COMMON_RTC_INSTANCE); - // The counter used for time measurements is less than 32 bit wide, - // so its value is complemented with the number of registered overflows - // of the counter. - ticks += (m_common_rtc_overflows << RTC_COUNTER_BITS); - - // Check in case that OVF occurred during execution of a RTC handler (apply if call was from RTC handler) - // m_common_rtc_overflows might been updated in this call. - rtc_ovf_event_safe_check(); - - // If call was made from a low priority level m_common_rtc_overflows might have been updated in RTC handler. - } while (m_common_rtc_overflows != prev_overflows); - - return ticks; -} - -uint64_t common_rtc_64bit_us_get(void) -{ - uint32_t ticks = common_rtc_32bit_ticks_get(); - // [ticks -> microseconds] - return ROUNDED_DIV(((uint64_t)ticks) * 1000000, RTC_INPUT_FREQ); -} - -void common_rtc_set_interrupt(uint32_t us_timestamp, uint32_t cc_channel, - uint32_t int_mask) -{ - // The internal counter is clocked with a frequency that cannot be easily - // multiplied to 1 MHz, therefore besides the translation of values - // (microsecond <-> ticks) a special care of overflows handling must be - // taken. Here the 32-bit timestamp value is complemented with information - // about current the system up time of (ticks + number of overflows of tick - // counter on upper bits, converted to microseconds), and such 64-bit value - // is then translated to counter ticks. Finally, the lower 24 bits of thus - // calculated value is written to the counter compare register to prepare - // the interrupt generation. - uint64_t current_time64 = common_rtc_64bit_us_get(); - // [add upper 32 bits from the current time to the timestamp value] - uint64_t timestamp64 = us_timestamp + - (current_time64 & ~(uint64_t)0xFFFFFFFF); - // [if the original timestamp value happens to be after the 32 bit counter - // of microsends overflows, correct the upper 32 bits accordingly] - if (us_timestamp < (uint32_t)(current_time64 & 0xFFFFFFFF)) { - timestamp64 += ((uint64_t)1 << 32); - } - // [microseconds -> ticks, always round the result up to avoid too early - // interrupt generation] - uint32_t compare_value = - (uint32_t)CEIL_DIV((timestamp64) * RTC_INPUT_FREQ, 1000000); - - - core_util_critical_section_enter(); - // The COMPARE event occurs when the value in compare register is N and - // the counter value changes from N-1 to N. Therefore, the minimal safe - // difference between the compare value to be set and the current counter - // value is 2 ticks. This guarantees that the compare trigger is properly - // setup before the compare condition occurs. - uint32_t closest_safe_compare = common_rtc_32bit_ticks_get() + 2; - if ((int)(compare_value - closest_safe_compare) <= 0) { - compare_value = closest_safe_compare; - } - - nrf_rtc_cc_set(COMMON_RTC_INSTANCE, cc_channel, RTC_WRAP(compare_value)); - nrf_rtc_event_enable(COMMON_RTC_INSTANCE, int_mask); - - core_util_critical_section_exit(); -} -//------------------------------------------------------------------------------ - - -void us_ticker_init(void) -{ - common_rtc_init(); + us_ticker_initialized = true; } uint32_t us_ticker_read() { - us_ticker_init(); - return (uint32_t)common_rtc_64bit_us_get(); + nrf_timer_task_trigger(NRF_TIMER1, NRF_TIMER_TASK_CAPTURE1); + + return nrf_timer_cc_read(NRF_TIMER1, NRF_TIMER_CC_CHANNEL1); } void us_ticker_set_interrupt(timestamp_t timestamp) { - common_rtc_set_interrupt(timestamp, - US_TICKER_CC_CHANNEL, US_TICKER_INT_MASK); + core_util_critical_section_enter(); + + nrf_timer_cc_write(NRF_TIMER1, NRF_TIMER_CC_CHANNEL0, timestamp & 0xFFFF); + + if (!nrf_timer_int_enable_check(NRF_TIMER1, nrf_timer_compare_int_get(NRF_TIMER_CC_CHANNEL0))) { + nrf_timer_event_clear(NRF_TIMER1, NRF_TIMER_EVENT_COMPARE0); + nrf_timer_int_enable(NRF_TIMER1, nrf_timer_compare_int_get(NRF_TIMER_CC_CHANNEL0)); + } + + core_util_critical_section_exit(); } void us_ticker_fire_interrupt(void) { - core_util_critical_section_enter(); - m_common_sw_irq_flag |= US_TICKER_SW_IRQ_MASK; - NVIC_SetPendingIRQ(RTC1_IRQn); - core_util_critical_section_exit(); + NVIC_SetPendingIRQ(TIMER1_IRQn); } void us_ticker_disable_interrupt(void) { - nrf_rtc_event_disable(COMMON_RTC_INSTANCE, US_TICKER_INT_MASK); + nrf_timer_int_disable(NRF_TIMER1, nrf_timer_compare_int_get(NRF_TIMER_CC_CHANNEL0)); } void us_ticker_clear_interrupt(void) { - m_common_sw_irq_flag &= ~US_TICKER_SW_IRQ_MASK; - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, US_TICKER_EVENT); + nrf_timer_event_clear(NRF_TIMER1, NRF_TIMER_EVENT_COMPARE0); } - -// Since there is no SysTick on NRF51, the RTC1 channel 1 is used as an -// alternative source of RTOS ticks. -#if defined(TARGET_MCU_NRF51822) - -#include "mbed_toolchain.h" - - -#define MAX_RTC_COUNTER_VAL ((1uL << RTC_COUNTER_BITS) - 1) - -#ifndef RTC1_CONFIG_FREQUENCY - #define RTC1_CONFIG_FREQUENCY 32678 // [Hz] -#endif - - - -void COMMON_RTC_IRQ_HANDLER(void) +void us_ticker_free(void) { - if(!nrf_rtc_event_pending(COMMON_RTC_INSTANCE, OS_TICK_EVENT)) { - common_rtc_irq_handler(); - } + // A common counter is used for RTC, lp_ticker and us_ticker, so it can't be + // disabled here, but this does not cause any extra cost. } - -IRQn_Type mbed_get_m0_tick_irqn() -{ - return SWI3_IRQn; -} - - -#endif // defined(TARGET_MCU_NRF51822) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/us_ticker.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/us_ticker.h new file mode 100644 index 0000000000..f9bf80424c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF51/us_ticker.h @@ -0,0 +1,26 @@ +/* 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. + */ + +#ifndef US_TICKER_H +#define US_TICKER_H + +/* TIMER0 is reserved for SoftDevice. We will use TIMER1 for us ticker + * which counter size is 16 bits. */ + +#define US_TICKER_COUNTER_BITS 16u +#define US_TICKER_FREQ 1000000 + +#endif // US_TICKER_H diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.h index 2ebe70ecf7..dae27b263c 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.h +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/common_rtc.h @@ -20,29 +20,21 @@ #include "nrf_rtc.h" #define RTC_COUNTER_BITS 24u +#define RTC_FREQ 32768u // Instance 0 is reserved for SoftDevice. -// Instance 1 is used as a common one for us_ticker, lp_ticker and (in case +// Instance 1 is used as a common one for lp_ticker and (in case // of NRF51) as an alternative tick source for RTOS. -// ["us_ticker.c" uses hard coded addresses of the 'NRF_RTC1->EVENT_COMPARE[1]' -// register in inline assembly implementations of COMMON_RTC_IRQ_HANDLER, -// please remember to update those in case of doing changes here] #define COMMON_RTC_INSTANCE NRF_RTC1 #define COMMON_RTC_IRQ_HANDLER RTC1_IRQHandler -#define US_TICKER_CC_CHANNEL 0 -#define OS_TICK_CC_CHANNEL 1 -#define LP_TICKER_CC_CHANNEL 2 - -#define US_TICKER_SW_IRQ_MASK 0x1 -#define LP_TICKER_SW_IRQ_MASK 0x2 +#define OS_TICK_CC_CHANNEL 0 +#define LP_TICKER_CC_CHANNEL 1 #define COMMON_RTC_EVENT_COMPARE(channel) \ CONCAT_2(NRF_RTC_EVENT_COMPARE_, channel) #define COMMON_RTC_INT_COMPARE_MASK(channel) \ CONCAT_3(NRF_RTC_INT_COMPARE, channel, _MASK) -#define US_TICKER_EVENT COMMON_RTC_EVENT_COMPARE(US_TICKER_CC_CHANNEL) -#define US_TICKER_INT_MASK COMMON_RTC_INT_COMPARE_MASK(US_TICKER_CC_CHANNEL) #define OS_TICK_EVENT COMMON_RTC_EVENT_COMPARE(OS_TICK_CC_CHANNEL) #define OS_TICK_INT_MASK COMMON_RTC_INT_COMPARE_MASK(OS_TICK_CC_CHANNEL) #define LP_TICKER_EVENT COMMON_RTC_EVENT_COMPARE(LP_TICKER_CC_CHANNEL) @@ -50,7 +42,7 @@ extern bool m_common_rtc_enabled; extern uint32_t volatile m_common_rtc_overflows; -extern uint8_t volatile m_common_sw_irq_flag; +extern bool volatile lp_ticker_interrupt_fire; void common_rtc_init(void); uint32_t common_rtc_32bit_ticks_get(void); diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/lp_ticker.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/lp_ticker.c index def44835e2..9e197d8555 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/lp_ticker.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/lp_ticker.c @@ -14,20 +14,35 @@ * limitations under the License. */ #include "lp_ticker_api.h" - -#if DEVICE_LOWPOWERTIMER - #include "common_rtc.h" -#include "mbed_critical.h" +#include "platform/mbed_critical.h" + +#if DEVICE_LPTICKER + +/* LP ticker is driven by 32kHz clock and counter length is 24 bits. */ +const ticker_info_t* lp_ticker_get_info() +{ + static const ticker_info_t info = { + RTC_FREQ, + RTC_COUNTER_BITS + }; + return &info; +} void lp_ticker_init(void) { common_rtc_init(); } +void lp_ticker_free(void) +{ + // A common counter is used for RTC, lp_ticker and us_ticker, so it can't be + // disabled here, but this does not cause any extra cost. +} + uint32_t lp_ticker_read() { - return (uint32_t)common_rtc_64bit_us_get(); + return nrf_rtc_counter_get(COMMON_RTC_INSTANCE); } void lp_ticker_set_interrupt(timestamp_t timestamp) @@ -39,14 +54,17 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) void lp_ticker_fire_interrupt(void) { core_util_critical_section_enter(); - m_common_sw_irq_flag |= LP_TICKER_SW_IRQ_MASK; + + lp_ticker_interrupt_fire = true; + NVIC_SetPendingIRQ(RTC1_IRQn); + core_util_critical_section_exit(); } void lp_ticker_disable_interrupt(void) { - nrf_rtc_event_disable(COMMON_RTC_INSTANCE, LP_TICKER_INT_MASK); + nrf_rtc_int_disable(COMMON_RTC_INSTANCE, LP_TICKER_INT_MASK); } void lp_ticker_clear_interrupt(void) @@ -54,4 +72,4 @@ void lp_ticker_clear_interrupt(void) nrf_rtc_event_clear(COMMON_RTC_INSTANCE, LP_TICKER_EVENT); } -#endif // DEVICE_LOWPOWERTIMER +#endif // DEVICE_LPTICKER diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/sleep.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/sleep.c index f7ec7911a6..a58591dd65 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/sleep.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/sleep.c @@ -17,6 +17,8 @@ #include "cmsis.h" #include "mbed_interface.h" #include "nrf_soc.h" +#include "nrf_timer.h" +#include "us_ticker.h" #if defined(SOFTDEVICE_PRESENT) #include "nrf_sdh.h" @@ -31,6 +33,8 @@ #define FPU_EXCEPTION_MASK 0x0000009F +extern bool us_ticker_initialized; + void hal_sleep(void) { // ensure debug is disconnected if semihost is enabled.... @@ -83,6 +87,14 @@ void hal_sleep(void) void hal_deepsleep(void) { + if (us_ticker_initialized) { + nrf_timer_task_trigger(NRF_TIMER1, NRF_TIMER_TASK_STOP); + } + hal_sleep(); + + if (us_ticker_initialized) { + nrf_timer_task_trigger(NRF_TIMER1, NRF_TIMER_TASK_START); + } // NRF_POWER->SYSTEMOFF=1; } diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.c index 64b5a267bf..0ab3738bb1 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.c +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.c @@ -36,137 +36,57 @@ * */ +#include "us_ticker.h" + #include "us_ticker_api.h" -#include "common_rtc.h" -#include "app_util.h" +#include "nrf_timer.h" +#include "app_util_platform.h" #include "nrf_drv_common.h" -#include "lp_ticker_api.h" #include "mbed_critical.h" -#if defined(NRF52_ERRATA_20) -#if defined(SOFTDEVICE_PRESENT) -#include "nrf_sdh.h" -#define NRF_HAL_US_TICKER_SD_IS_ENABLED() nrf_sdh_is_enabled() -#else -#define NRF_HAL_US_TICKER_SD_IS_ENABLED() 0 -#endif -#endif +bool us_ticker_initialized = false; -//------------------------------------------------------------------------------ -// Common stuff used also by lp_ticker and rtc_api (see "common_rtc.h"). -// -#include "app_util_platform.h" - -bool m_common_rtc_enabled = false; -uint32_t volatile m_common_rtc_overflows = 0; - -// lp/us ticker fire interrupt flag for IRQ handler -volatile uint8_t m_common_sw_irq_flag = 0; - -__STATIC_INLINE void rtc_ovf_event_check(void) +/* us ticker is driven by 1MHz clock and counter length is 16 bits. */ +const ticker_info_t* us_ticker_get_info() { - if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW)) { - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); - // Don't disable this event. It shall occur periodically. - - ++m_common_rtc_overflows; - } + static const ticker_info_t info = { + US_TICKER_FREQ, + US_TICKER_COUNTER_BITS + }; + return &info; } -#if defined(TARGET_MCU_NRF51822) -void common_rtc_irq_handler(void) -#else -void COMMON_RTC_IRQ_HANDLER(void) -#endif +void us_ticker_init(void) { - - rtc_ovf_event_check(); - - if ((m_common_sw_irq_flag & US_TICKER_SW_IRQ_MASK) || nrf_rtc_event_pending(COMMON_RTC_INSTANCE, US_TICKER_EVENT)) { - us_ticker_irq_handler(); - } - -#if DEVICE_LOWPOWERTIMER - if (m_common_sw_irq_flag & LP_TICKER_SW_IRQ_MASK) { - m_common_sw_irq_flag &= ~LP_TICKER_SW_IRQ_MASK; - lp_ticker_irq_handler(); - } - if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, LP_TICKER_EVENT)) { - - lp_ticker_irq_handler(); - } -#endif -} - -// Function for fix errata 20: RTC Register values are invalid -__STATIC_INLINE void errata_20(void) -{ -#if defined(NRF52_ERRATA_20) - if (!NRF_HAL_US_TICKER_SD_IS_ENABLED()) - { - NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; - NRF_CLOCK->TASKS_LFCLKSTART = 1; - - while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) - { - } - } - NRF_RTC1->TASKS_STOP = 0; -#endif -} - -void RTC1_IRQHandler(void); - -void common_rtc_init(void) -{ - if (m_common_rtc_enabled) { + if (us_ticker_initialized) { + nrf_timer_event_clear(NRF_TIMER1, NRF_TIMER_EVENT_COMPARE0); + nrf_timer_int_disable(NRF_TIMER1, nrf_timer_compare_int_get(NRF_TIMER_CC_CHANNEL0)); return; } - errata_20(); + nrf_timer_task_trigger(NRF_TIMER1, NRF_TIMER_TASK_STOP); - NVIC_SetVector(RTC1_IRQn, (uint32_t)RTC1_IRQHandler); + nrf_timer_int_disable(NRF_TIMER1, nrf_timer_compare_int_get(NRF_TIMER_CC_CHANNEL0)); - // RTC is driven by the low frequency (32.768 kHz) clock, a proper request - // must be made to have it running. - // Currently this clock is started in 'SystemInit' (see "system_nrf51.c" - // or "system_nrf52.c", respectively). + /* Configure timer as follows: + * - timer mode, + * - timer width 16 bits, + * - timer freq 1 MHz. + */ + nrf_timer_mode_set(NRF_TIMER1, NRF_TIMER_MODE_TIMER); - nrf_rtc_prescaler_set(COMMON_RTC_INSTANCE, 0); + nrf_timer_frequency_set(NRF_TIMER1, NRF_TIMER_FREQ_1MHz); - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, US_TICKER_EVENT); -#if defined(TARGET_MCU_NRF51822) - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, OS_TICK_EVENT); -#endif -#if DEVICE_LOWPOWERTIMER - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, LP_TICKER_EVENT); -#endif - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); + nrf_timer_bit_width_set(NRF_TIMER1, NRF_TIMER_BIT_WIDTH_16); - // Interrupts on all related events are enabled permanently. Particular - // events will be enabled or disabled as needed (such approach is more - // energy efficient). - nrf_rtc_int_enable(COMMON_RTC_INSTANCE, -#if DEVICE_LOWPOWERTIMER - LP_TICKER_INT_MASK | -#endif - US_TICKER_INT_MASK | - NRF_RTC_INT_OVERFLOW_MASK); + nrf_timer_cc_write(NRF_TIMER1, NRF_TIMER_CC_CHANNEL0, 0); - // This event is enabled permanently, since overflow indications are needed - // continuously. - nrf_rtc_event_enable(COMMON_RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK); - // All other relevant events are initially disabled. - nrf_rtc_event_disable(COMMON_RTC_INSTANCE, -#if defined(TARGET_MCU_NRF51822) - OS_TICK_INT_MASK | -#endif -#if DEVICE_LOWPOWERTIMER - LP_TICKER_INT_MASK | -#endif - US_TICKER_INT_MASK); + nrf_timer_event_clear(NRF_TIMER1, NRF_TIMER_EVENT_COMPARE0); + + NVIC_SetVector(TIMER1_IRQn, (uint32_t)us_ticker_irq_handler); + + nrf_drv_common_irq_enable(TIMER1_IRQn, - nrf_drv_common_irq_enable(nrf_drv_get_IRQn(COMMON_RTC_INSTANCE), #ifdef NRF51 APP_IRQ_PRIORITY_LOW #elif defined(NRF52) || defined(NRF52840_XXAA) @@ -174,158 +94,49 @@ void common_rtc_init(void) #endif ); - nrf_rtc_task_trigger(COMMON_RTC_INSTANCE, NRF_RTC_TASK_START); + nrf_timer_task_trigger(NRF_TIMER1, NRF_TIMER_TASK_START); - m_common_rtc_enabled = true; -} - -__STATIC_INLINE void rtc_ovf_event_safe_check(void) -{ - core_util_critical_section_enter(); - - rtc_ovf_event_check(); - - core_util_critical_section_exit(); -} - - -uint32_t common_rtc_32bit_ticks_get(void) -{ - uint32_t ticks; - uint32_t prev_overflows; - - do { - prev_overflows = m_common_rtc_overflows; - - ticks = nrf_rtc_counter_get(COMMON_RTC_INSTANCE); - // The counter used for time measurements is less than 32 bit wide, - // so its value is complemented with the number of registered overflows - // of the counter. - ticks += (m_common_rtc_overflows << RTC_COUNTER_BITS); - - // Check in case that OVF occurred during execution of a RTC handler (apply if call was from RTC handler) - // m_common_rtc_overflows might been updated in this call. - rtc_ovf_event_safe_check(); - - // If call was made from a low priority level m_common_rtc_overflows might have been updated in RTC handler. - } while (m_common_rtc_overflows != prev_overflows); - - return ticks; -} - -uint64_t common_rtc_64bit_us_get(void) -{ - uint32_t ticks = common_rtc_32bit_ticks_get(); - // [ticks -> microseconds] - return ROUNDED_DIV(((uint64_t)ticks) * 1000000, RTC_INPUT_FREQ); -} - -void common_rtc_set_interrupt(uint32_t us_timestamp, uint32_t cc_channel, - uint32_t int_mask) -{ - // The internal counter is clocked with a frequency that cannot be easily - // multiplied to 1 MHz, therefore besides the translation of values - // (microsecond <-> ticks) a special care of overflows handling must be - // taken. Here the 32-bit timestamp value is complemented with information - // about current the system up time of (ticks + number of overflows of tick - // counter on upper bits, converted to microseconds), and such 64-bit value - // is then translated to counter ticks. Finally, the lower 24 bits of thus - // calculated value is written to the counter compare register to prepare - // the interrupt generation. - uint64_t current_time64 = common_rtc_64bit_us_get(); - // [add upper 32 bits from the current time to the timestamp value] - uint64_t timestamp64 = (current_time64 & ~(uint64_t)0xFFFFFFFF) | us_timestamp; - // [if the original timestamp value happens to be after the 32 bit counter - // of microsends overflows, correct the upper 32 bits accordingly] - if (timestamp64 < current_time64) { - timestamp64 += ((uint64_t)1 << 32); - } - // [microseconds -> ticks, always round the result up to avoid too early - // interrupt generation] - uint32_t compare_value = RTC_WRAP((uint32_t)CEIL_DIV((timestamp64) * RTC_INPUT_FREQ, 1000000)); - - core_util_critical_section_enter(); - // The COMPARE event occurs when the value in compare register is N and - // the counter value changes from N-1 to N. Therefore, the minimal safe - // difference between the compare value to be set and the current counter - // value is 2 ticks. This guarantees that the compare trigger is properly - // setup before the compare condition occurs. - uint32_t closest_safe_compare = RTC_WRAP(common_rtc_32bit_ticks_get() + 2); - if (closest_safe_compare - compare_value < 2) { - compare_value = closest_safe_compare; - } - - nrf_rtc_cc_set(COMMON_RTC_INSTANCE, cc_channel, compare_value); - nrf_rtc_event_enable(COMMON_RTC_INSTANCE, int_mask); - - core_util_critical_section_exit(); -} -//------------------------------------------------------------------------------ - - -void us_ticker_init(void) -{ - common_rtc_init(); + us_ticker_initialized = true; } uint32_t us_ticker_read() { - us_ticker_init(); - return (uint32_t)common_rtc_64bit_us_get(); + nrf_timer_task_trigger(NRF_TIMER1, NRF_TIMER_TASK_CAPTURE1); + + return nrf_timer_cc_read(NRF_TIMER1, NRF_TIMER_CC_CHANNEL1); } void us_ticker_set_interrupt(timestamp_t timestamp) { - common_rtc_set_interrupt(timestamp, - US_TICKER_CC_CHANNEL, US_TICKER_INT_MASK); + core_util_critical_section_enter(); + + nrf_timer_cc_write(NRF_TIMER1, NRF_TIMER_CC_CHANNEL0, timestamp & 0xFFFF); + + if (!nrf_timer_int_enable_check(NRF_TIMER1, nrf_timer_compare_int_get(NRF_TIMER_CC_CHANNEL0))) { + nrf_timer_event_clear(NRF_TIMER1, NRF_TIMER_EVENT_COMPARE0); + nrf_timer_int_enable(NRF_TIMER1, nrf_timer_compare_int_get(NRF_TIMER_CC_CHANNEL0)); + } + + core_util_critical_section_exit(); } void us_ticker_fire_interrupt(void) { - core_util_critical_section_enter(); - m_common_sw_irq_flag |= US_TICKER_SW_IRQ_MASK; - NVIC_SetPendingIRQ(RTC1_IRQn); - core_util_critical_section_exit(); + NVIC_SetPendingIRQ(TIMER1_IRQn); } void us_ticker_disable_interrupt(void) { - nrf_rtc_event_disable(COMMON_RTC_INSTANCE, US_TICKER_INT_MASK); + nrf_timer_int_disable(NRF_TIMER1, nrf_timer_compare_int_get(NRF_TIMER_CC_CHANNEL0)); } void us_ticker_clear_interrupt(void) { - m_common_sw_irq_flag &= ~US_TICKER_SW_IRQ_MASK; - nrf_rtc_event_clear(COMMON_RTC_INSTANCE, US_TICKER_EVENT); + nrf_timer_event_clear(NRF_TIMER1, NRF_TIMER_EVENT_COMPARE0); } - -// Since there is no SysTick on NRF51, the RTC1 channel 1 is used as an -// alternative source of RTOS ticks. -#if defined(TARGET_MCU_NRF51822) - -#include "mbed_toolchain.h" - - -#define MAX_RTC_COUNTER_VAL ((1uL << RTC_COUNTER_BITS) - 1) - -#ifndef RTC1_CONFIG_FREQUENCY - #define RTC1_CONFIG_FREQUENCY 32678 // [Hz] -#endif - - - -void COMMON_RTC_IRQ_HANDLER(void) +void us_ticker_free(void) { - if(!nrf_rtc_event_pending(COMMON_RTC_INSTANCE, OS_TICK_EVENT)) { - common_rtc_irq_handler(); - } + // A common counter is used for RTC, lp_ticker and us_ticker, so it can't be + // disabled here, but this does not cause any extra cost. } - -IRQn_Type mbed_get_m0_tick_irqn() -{ - return SWI3_IRQn; -} - - -#endif // defined(TARGET_MCU_NRF51822) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.h new file mode 100644 index 0000000000..f9bf80424c --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/us_ticker.h @@ -0,0 +1,26 @@ +/* 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. + */ + +#ifndef US_TICKER_H +#define US_TICKER_H + +/* TIMER0 is reserved for SoftDevice. We will use TIMER1 for us ticker + * which counter size is 16 bits. */ + +#define US_TICKER_COUNTER_BITS 16u +#define US_TICKER_FREQ 1000000 + +#endif // US_TICKER_H diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/common_rtc.c b/targets/TARGET_NORDIC/TARGET_NRF5x/common_rtc.c new file mode 100644 index 0000000000..38db0a4bf1 --- /dev/null +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/common_rtc.c @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2013 Nordic Semiconductor ASA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA + * integrated circuit in a product or a software update for such product, must reproduce + * the above copyright notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific prior + * written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary or object form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "us_ticker_api.h" +#include "common_rtc.h" +#include "app_util.h" +#include "nrf_drv_common.h" +#include "lp_ticker_api.h" +#include "mbed_critical.h" + +#if defined(NRF52_PAN_20) +/* Macro for testing if the SoftDevice is active, regardless of whether the + * application is build with the SoftDevice or not. + */ +#if defined(SOFTDEVICE_PRESENT) +#include "nrf_sdh.h" +#define NRF_HAL_SD_IS_ENABLED() nrf_sdh_is_enabled() +#else +#define NRF_HAL_SD_IS_ENABLED() 0 +#endif +#endif + + +//------------------------------------------------------------------------------ +// Common stuff used also by lp_ticker and rtc_api (see "common_rtc.h"). +// +#include "app_util_platform.h" + +bool m_common_rtc_enabled = false; +uint32_t volatile m_common_rtc_overflows = 0; +bool volatile lp_ticker_interrupt_fire = false; + +__STATIC_INLINE void rtc_ovf_event_check(void) +{ + if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW)) { + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); + /* Don't disable this event. It shall occur periodically. + * It is needed for RTC. */ + + ++m_common_rtc_overflows; + } +} + +#if defined(TARGET_MCU_NRF51822) +void common_rtc_irq_handler(void) +#else +void COMMON_RTC_IRQ_HANDLER(void) +#endif +{ + rtc_ovf_event_check(); + +#if DEVICE_LPTICKER + if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, LP_TICKER_EVENT) || + lp_ticker_interrupt_fire) { + + if (lp_ticker_interrupt_fire) { + lp_ticker_interrupt_fire = false; + } + + lp_ticker_irq_handler(); + } +#endif +} + +/* Function for fix errata 20: RTC Register values are invalid. */ +__STATIC_INLINE void errata_20(void) +{ +#if defined(NRF52_PAN_20) + if (!NRF_HAL_SD_IS_ENABLED()) + { + NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; + NRF_CLOCK->TASKS_LFCLKSTART = 1; + + while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) + { + } + } + NRF_RTC1->TASKS_STOP = 0; +#endif +} + +void RTC1_IRQHandler(void); + +void common_rtc_init(void) +{ + if (m_common_rtc_enabled) { +#if DEVICE_LPTICKER + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, LP_TICKER_EVENT); + nrf_rtc_int_disable(COMMON_RTC_INSTANCE, LP_TICKER_INT_MASK); +#endif + return; + } + + errata_20(); + + nrf_rtc_task_trigger(COMMON_RTC_INSTANCE, NRF_RTC_TASK_STOP); + + NVIC_SetVector(RTC1_IRQn, (uint32_t)RTC1_IRQHandler); + + /* RTC is driven by the low frequency (32.768 kHz) clock, a proper request + * must be made to have it running. + * Currently this clock is started in 'SystemInit' (see "system_nrf51.c" + * or "system_nrf52.c", respectively). + */ + + nrf_rtc_prescaler_set(COMMON_RTC_INSTANCE, 0); + + /* Clear all RTC events. */ +#if defined(TARGET_MCU_NRF51822) + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, OS_TICK_EVENT); +#endif +#if DEVICE_LPTICKER + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, LP_TICKER_EVENT); +#endif + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); + + /* Disable all RTC events (According to NRF_51 Reference Manual + * RTC events can not be used to control RTC interrupts). + * IRQ signal to NVIC is provided if interrupt is enabled. + */ + + nrf_rtc_event_disable(COMMON_RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK +#if defined(TARGET_MCU_NRF51822) + | OS_TICK_INT_MASK +#endif +#if DEVICE_LPTICKER + | LP_TICKER_INT_MASK +#endif + ); + + /* This interrupt is enabled permanently, since overflow indications are needed + * continuously. + */ + nrf_rtc_int_enable(COMMON_RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK); + + /* Disable LP ticker interrupt for now. */ +#if DEVICE_LPTICKER + nrf_rtc_int_disable(COMMON_RTC_INSTANCE, LP_TICKER_INT_MASK); +#endif + + nrf_drv_common_irq_enable(nrf_drv_get_IRQn(COMMON_RTC_INSTANCE), +#ifdef NRF51 + APP_IRQ_PRIORITY_LOW +#elif defined(NRF52) || defined(NRF52840_XXAA) + APP_IRQ_PRIORITY_LOWEST +#endif + ); + + nrf_rtc_task_trigger(COMMON_RTC_INSTANCE, NRF_RTC_TASK_START); + + m_common_rtc_enabled = true; +} + +void common_rtc_set_interrupt(uint32_t ticks_count, uint32_t cc_channel, + uint32_t int_mask) +{ + /* Set ticks value when interrupt should be fired. + * Interrupt scheduling is performed in upper layers. */ + + core_util_critical_section_enter(); + + /* COMPARE occurs when a CC register is N and the COUNTER value transitions from N-1 to N. + * If the COUNTER is N, writing N+2 to a CC register is guaranteed to trigger a + * COMPARE event at N+2. + */ + const uint32_t now = nrf_rtc_counter_get(COMMON_RTC_INSTANCE); + + if (now == ticks_count || + RTC_WRAP(now + 1) == ticks_count) { + ticks_count += 2; + } + + nrf_rtc_cc_set(COMMON_RTC_INSTANCE, cc_channel, RTC_WRAP(ticks_count)); + + if (!nrf_rtc_int_is_enabled(COMMON_RTC_INSTANCE, int_mask)) { + nrf_rtc_event_clear(COMMON_RTC_INSTANCE, LP_TICKER_EVENT); + nrf_rtc_int_enable(COMMON_RTC_INSTANCE, int_mask); + } + + core_util_critical_section_exit(); +} + +/* Since there is no SysTick on NRF51, the RTC1 channel 0 is used as an + * alternative source of RTOS ticks. + */ +#if defined(TARGET_MCU_NRF51822) + +#include "mbed_toolchain.h" + + +#define MAX_RTC_COUNTER_VAL ((1uL << RTC_COUNTER_BITS) - 1) + +#ifndef RTC1_CONFIG_FREQUENCY + #define RTC1_CONFIG_FREQUENCY 32678 // [Hz] +#endif + + + +void COMMON_RTC_IRQ_HANDLER(void) +{ + if(!nrf_rtc_event_pending(COMMON_RTC_INSTANCE, OS_TICK_EVENT)) { + common_rtc_irq_handler(); + } +} + +IRQn_Type mbed_get_m0_tick_irqn() +{ + return SWI3_IRQn; +} + + +#endif // defined(TARGET_MCU_NRF51822) diff --git a/targets/TARGET_NUVOTON/TARGET_M451/lp_ticker.c b/targets/TARGET_NUVOTON/TARGET_M451/lp_ticker.c index 8f1e209a26..282005904f 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/lp_ticker.c +++ b/targets/TARGET_NUVOTON/TARGET_M451/lp_ticker.c @@ -16,7 +16,7 @@ #include "lp_ticker_api.h" -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER #include "sleep_api.h" #include "mbed_wait_api.h" diff --git a/targets/TARGET_NUVOTON/TARGET_M480/lp_ticker.c b/targets/TARGET_NUVOTON/TARGET_M480/lp_ticker.c index b39587dd14..a09360608e 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/lp_ticker.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/lp_ticker.c @@ -16,7 +16,7 @@ #include "lp_ticker_api.h" -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER #include "sleep_api.h" #include "mbed_wait_api.h" diff --git a/targets/TARGET_NUVOTON/TARGET_NANO100/lp_ticker.c b/targets/TARGET_NUVOTON/TARGET_NANO100/lp_ticker.c index aef86aacee..6355531d33 100644 --- a/targets/TARGET_NUVOTON/TARGET_NANO100/lp_ticker.c +++ b/targets/TARGET_NUVOTON/TARGET_NANO100/lp_ticker.c @@ -16,7 +16,7 @@ #include "lp_ticker_api.h" -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER #include "sleep_api.h" #include "mbed_wait_api.h" diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/lp_ticker.c b/targets/TARGET_NUVOTON/TARGET_NUC472/lp_ticker.c index a7c634b92c..08ce7f8989 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/lp_ticker.c +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/lp_ticker.c @@ -16,7 +16,7 @@ #include "lp_ticker_api.h" -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER #include "sleep_api.h" #include "mbed_wait_api.h" diff --git a/targets/TARGET_NXP/TARGET_LPC176X/sleep.c b/targets/TARGET_NXP/TARGET_LPC176X/sleep.c index c9f6ad4145..22127e0728 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/sleep.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/sleep.c @@ -17,6 +17,13 @@ #include "cmsis.h" #include "mbed_interface.h" +/* + * @note + * The mbed interface semihosting is disconnected as part of going to sleep, and can not be restored. + * Flash re-programming and the USB serial port will remain active, but the mbed program will no longer be + * able to access the LocalFileSystem + */ + void hal_sleep(void) { #if (DEVICE_SEMIHOST == 1) diff --git a/targets/TARGET_NXP/TARGET_LPC176X/us_ticker.c b/targets/TARGET_NXP/TARGET_LPC176X/us_ticker.c index 5b79d4223c..5b1b0b7237 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/us_ticker.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/us_ticker.c @@ -17,34 +17,44 @@ #include "us_ticker_api.h" #include "PeripheralNames.h" +const ticker_info_t* us_ticker_get_info() +{ + static const ticker_info_t info = { + 1000000, // 1 MHz + 32 // 32 bit counter + }; + return &info; +} + +static bool us_ticker_inited = false; + #define US_TICKER_TIMER ((LPC_TIM_TypeDef *)LPC_TIM3_BASE) #define US_TICKER_TIMER_IRQn TIMER3_IRQn -int us_ticker_inited = 0; - void us_ticker_init(void) { - if (us_ticker_inited) return; - us_ticker_inited = 1; - + if (us_ticker_inited) { + /* calling init again should cancel current interrupt */ + us_ticker_disable_interrupt(); + return; + } + us_ticker_inited = true; + LPC_SC->PCONP |= 1 << 23; // Clock TIMER_3 - + US_TICKER_TIMER->CTCR = 0x0; // timer mode uint32_t PCLK = SystemCoreClock / 4; - + US_TICKER_TIMER->TCR = 0x2; // reset - + uint32_t prescale = PCLK / 1000000; // default to 1MHz (1 us ticks) US_TICKER_TIMER->PR = prescale - 1; US_TICKER_TIMER->TCR = 1; // enable = 1, reset = 0 - + NVIC_SetVector(US_TICKER_TIMER_IRQn, (uint32_t)us_ticker_irq_handler); NVIC_EnableIRQ(US_TICKER_TIMER_IRQn); } uint32_t us_ticker_read() { - if (!us_ticker_inited) - us_ticker_init(); - return US_TICKER_TIMER->TC; } diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/lp_ticker.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/lp_ticker.c index 163457c7d3..25be648495 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/lp_ticker.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/lp_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2016 ARM Limited + * 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. @@ -14,23 +14,27 @@ * limitations under the License. */ -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER #include "lp_ticker_api.h" -#include "fsl_snvs_hp.h" #include "fsl_gpt.h" #include "cmsis.h" -#include "rtc_api.h" -#define LOWFREQ_REF_CLK_HZ (32768) +const ticker_info_t* lp_ticker_get_info() +{ + static const ticker_info_t info = { + 32768, // 32kHz + 32 // 32 bit counter + }; + return &info; +} static bool lp_ticker_inited = false; static void gpt_isr(void) { GPT_ClearStatusFlags(GPT2, kGPT_OutputCompare1Flag); - GPT_StopTimer(GPT2); - + GPT_DisableInterrupts(GPT2, kGPT_OutputCompare1InterruptEnable); lp_ticker_irq_handler(); } @@ -41,71 +45,48 @@ void lp_ticker_init(void) { gpt_config_t gptConfig; - if (lp_ticker_inited) { - return; - } - lp_ticker_inited = true; + if (!lp_ticker_inited) { + /* Setup GPT */ + GPT_GetDefaultConfig(&gptConfig); + /* Use 32kHz drive */ + gptConfig.clockSource = kGPT_ClockSource_LowFreq; + gptConfig.enableFreeRun = true; + gptConfig.enableMode = false; - /* Setup low resolution clock - RTC */ - if (!rtc_isenabled()) { - rtc_init(); + GPT_Init(GPT2, &gptConfig); + GPT_EnableInterrupts(GPT2, kGPT_OutputCompare1InterruptEnable); + NVIC_ClearPendingIRQ(GPT2_IRQn); + NVIC_SetVector(GPT2_IRQn, (uint32_t)gpt_isr); + EnableIRQ(GPT2_IRQn); + GPT_StartTimer(GPT2); + lp_ticker_inited = true; + } else { + GPT_DisableInterrupts(GPT2, kGPT_OutputCompare1InterruptEnable); } - - /* Setup GPT */ - GPT_GetDefaultConfig(&gptConfig); - /* Use 32kHz drive */ - gptConfig.clockSource = kGPT_ClockSource_LowFreq; - GPT_Init(GPT2, &gptConfig); - GPT_EnableInterrupts(GPT2, kGPT_OutputCompare1InterruptEnable); - NVIC_ClearPendingIRQ(GPT2_IRQn); - NVIC_SetVector(GPT2_IRQn, (uint32_t)gpt_isr); - EnableIRQ(GPT2_IRQn); } /** Read the current counter * - * @return The current timer's counter value in microseconds + * @return The current timer's counter value in ticks */ uint32_t lp_ticker_read(void) { - uint32_t ticks = 0; - uint64_t tmp = 0; - - if (!lp_ticker_inited) { - lp_ticker_init(); - } - - /* Do consecutive reads until value is correct */ - do - { - ticks = tmp; - tmp = SNVS->HPRTCLR; - } while (tmp != ticks); - - return COUNT_TO_USEC(ticks, LOWFREQ_REF_CLK_HZ);; + return GPT_GetCurrentTimerCount(GPT2); } /** Set interrupt for specified timestamp * - * @param timestamp The time in microseconds to be set + * @param timestamp The time in ticks to be set */ void lp_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now_us, delta_us, delta_ticks; - - if (!lp_ticker_inited) { - lp_ticker_init(); + if (timestamp == 0) { + timestamp = 1; } - now_us = lp_ticker_read(); - delta_us = timestamp > now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); - - delta_ticks = USEC_TO_COUNT(delta_us, LOWFREQ_REF_CLK_HZ); - if (delta_ticks == 0) { - delta_ticks = 1; - } - - GPT_SetOutputCompareValue(GPT2, kGPT_OutputCompare_Channel1, delta_ticks); + GPT_StopTimer(GPT2); + GPT_SetOutputCompareValue(GPT2, kGPT_OutputCompare_Channel1, timestamp); + GPT_ClearStatusFlags(GPT2, kGPT_OutputCompare1Flag); GPT_EnableInterrupts(GPT2, kGPT_OutputCompare1InterruptEnable); GPT_StartTimer(GPT2); } @@ -131,4 +112,4 @@ void lp_ticker_clear_interrupt(void) GPT_ClearStatusFlags(GPT2, kGPT_OutputCompare1Flag); } -#endif /* DEVICE_LOWPOWERTIMER */ +#endif /* DEVICE_LPTICKER */ diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/us_ticker.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/us_ticker.c index 3724dd0d7e..188209d049 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/us_ticker.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_IMX/us_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited + * Copyright (c) 2006-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. @@ -18,7 +18,16 @@ #include "fsl_pit.h" #include "fsl_clock_config.h" -static int us_ticker_inited = 0; +const ticker_info_t* us_ticker_get_info() +{ + static const ticker_info_t info = { + 1000000, // 1 MHz + 32 // 32 bit counter + }; + return &info; +} + +static bool us_ticker_inited = false; extern void us_ticker_setup_clock(); extern uint32_t us_ticker_get_clock(); @@ -33,15 +42,14 @@ static void pit_isr(void) us_ticker_irq_handler(); } +/** Initialize the high frequency ticker + * + */ void us_ticker_init(void) { - if (us_ticker_inited) { - return; - } - us_ticker_inited = 1; - //Common for ticker/timer + /* Common for ticker/timer. */ uint32_t busClock; - // Structure to initialize PIT + /* Structure to initialize PIT. */ pit_config_t pitConfig; us_ticker_setup_clock(); @@ -51,55 +59,83 @@ void us_ticker_init(void) busClock = us_ticker_get_clock(); - //Timer - PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); - PIT_StartTimer(PIT, kPIT_Chnl_0); - PIT_StartTimer(PIT, kPIT_Chnl_1); - - //Ticker - PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); - PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); - NVIC_SetVector(PIT_IRQn, (uint32_t)pit_isr); - NVIC_EnableIRQ(PIT_IRQn); -} - - -uint32_t us_ticker_read() -{ + /* Let the timer to count if re-init. */ if (!us_ticker_inited) { - us_ticker_init(); + + PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); + PIT_StartTimer(PIT, kPIT_Chnl_0); + PIT_StartTimer(PIT, kPIT_Chnl_1); } + /* Configure interrupt generation counters and disable ticker interrupts. */ + PIT_StopTimer(PIT, kPIT_Chnl_3); + PIT_StopTimer(PIT, kPIT_Chnl_2); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_2, busClock / 1000000 - 1); + PIT_SetTimerChainMode(PIT, kPIT_Chnl_3, true); + NVIC_SetVector(PIT_IRQn, (uint32_t) pit_isr); + NVIC_EnableIRQ(PIT_IRQn); + PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); + + us_ticker_inited = true; +} + +/** Read the current counter + * + * @return The current timer's counter value in ticks + */ +uint32_t us_ticker_read() +{ return ~(PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_1)); } +/** Disable us ticker interrupt + * + */ void us_ticker_disable_interrupt(void) { PIT_DisableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); } +/** Clear us ticker interrupt + * + */ void us_ticker_clear_interrupt(void) { PIT_ClearStatusFlags(PIT, kPIT_Chnl_3, PIT_TFLG_TIF_MASK); } +/** Set interrupt for specified timestamp + * + * @param timestamp The time in ticks when interrupt should be generated + */ void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now_us, delta_us; + /* We get here absolute interrupt time which takes into account counter overflow. + * Since we use additional count-down timer to generate interrupt we need to calculate + * load value based on time-stamp. + */ + const uint32_t now_ticks = us_ticker_read(); + uint32_t delta_ticks = + timestamp >= now_ticks ? timestamp - now_ticks : (uint32_t)((uint64_t) timestamp + 0xFFFFFFFF - now_ticks); - now_us = us_ticker_read(); - delta_us = timestamp >= now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); + if (delta_ticks == 0) { + /* The requested delay is less than the minimum resolution of this counter. */ + delta_ticks = 1; + } PIT_StopTimer(PIT, kPIT_Chnl_3); PIT_StopTimer(PIT, kPIT_Chnl_2); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, (uint32_t)delta_us); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_3, delta_ticks); PIT_EnableInterrupts(PIT, kPIT_Chnl_3, kPIT_TimerInterruptEnable); PIT_StartTimer(PIT, kPIT_Chnl_3); PIT_StartTimer(PIT, kPIT_Chnl_2); } +/** Fire us ticker interrupt + * + */ void us_ticker_fire_interrupt(void) { NVIC_SetPendingIRQ(PIT_IRQn); diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC/rtc_api.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC/rtc_api.c index 0fa0f3d080..c2e87bc96c 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC/rtc_api.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC/rtc_api.c @@ -15,7 +15,7 @@ */ #include "rtc_api.h" -#if DEVICE_RTC +#if DEVICE_RTC || DEVICE_LPTICKER #include "pinmap.h" #include "fsl_rtc.h" @@ -23,6 +23,8 @@ extern void rtc_setup_oscillator(void); +static bool rtc_time_set = false; + void rtc_init(void) { rtc_setup_oscillator(); @@ -34,7 +36,10 @@ void rtc_init(void) void rtc_free(void) { - RTC_Deinit(RTC); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + /* Gate the module clock */ + CLOCK_DisableClock(kCLOCK_Rtc); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } /* @@ -43,8 +48,19 @@ void rtc_free(void) */ int rtc_isenabled(void) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + /* Enable the RTC peripheral clock */ CLOCK_EnableClock(kCLOCK_Rtc); - return (int)((RTC->CTRL & RTC_CTRL_RTC_EN_MASK) >> RTC_CTRL_RTC_EN_SHIFT); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + + const bool rtc_init_done = ((RTC->CTRL & RTC_CTRL_RTC_EN_MASK) >> RTC_CTRL_RTC_EN_SHIFT); + + /* If RTC is not initialized, then disable the clock gate on exit. */ + if(!rtc_init_done) { + rtc_free(); + } + + return (rtc_init_done & rtc_time_set); } time_t rtc_read(void) @@ -57,6 +73,8 @@ void rtc_write(time_t t) RTC_StopTimer(RTC); RTC->COUNT = t; RTC_StartTimer(RTC); + + rtc_time_set = true; } #endif diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC/us_ticker.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC/us_ticker.c index 05b84c3092..9c033c3690 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC/us_ticker.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC/us_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited + * Copyright (c) 2006-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. @@ -18,37 +18,54 @@ #include "fsl_ctimer.h" #include "PeripheralNames.h" -int us_ticker_inited = 0; +const ticker_info_t* us_ticker_get_info() +{ + static const ticker_info_t info = { + 1000000, // 1 MHz + 32 // 32 bit counter + }; + return &info; +} +static bool us_ticker_inited = false; + +/** Initialize the high frequency ticker + * + */ void us_ticker_init(void) { ctimer_config_t config; - if (us_ticker_inited) { - return; - } - - us_ticker_inited = 1; - uint32_t pclk = CLOCK_GetFreq(kCLOCK_BusClk); uint32_t prescale = pclk / 1000000; // default to 1MHz (1 us ticks) - CTIMER_GetDefaultConfig(&config); - config.prescale = prescale - 1; - CTIMER_Init(CTIMER1, &config); - CTIMER_Reset(CTIMER1); - CTIMER_StartTimer(CTIMER1); + /* Let the timer to count if re-init. */ + if (!us_ticker_inited) { + CTIMER_GetDefaultConfig(&config); + config.prescale = prescale - 1; + CTIMER_Init(CTIMER1, &config); + CTIMER_Reset(CTIMER1); + CTIMER_StartTimer(CTIMER1); + } NVIC_SetVector(CTIMER1_IRQn, (uint32_t)us_ticker_irq_handler); NVIC_EnableIRQ(CTIMER1_IRQn); + CTIMER1->MCR &= ~1; + + us_ticker_inited = true; } +/** Read the current counter + * + * @return The current timer's counter value in ticks + */ uint32_t us_ticker_read(void) { - if (!us_ticker_inited) - us_ticker_init(); - return CTIMER1->TC; } +/** Set interrupt for specified timestamp + * + * @param timestamp The time in ticks when interrupt should be generated + */ void us_ticker_set_interrupt(timestamp_t timestamp) { ctimer_match_config_t matchConfig; @@ -62,10 +79,16 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { CTIMER_SetupMatch(CTIMER1, kCTIMER_Match_0, &matchConfig); } +/** Disable us ticker interrupt + * + */ void us_ticker_disable_interrupt(void) { CTIMER1->MCR &= ~1; } +/** Clear us ticker interrupt + * + */ void us_ticker_clear_interrupt(void) { CTIMER1->IR = 1; } diff --git a/targets/TARGET_ONSEMI/TARGET_NCS36510/exceptions.c b/targets/TARGET_ONSEMI/TARGET_NCS36510/exceptions.c index a11176bf9c..b125ecb42c 100644 --- a/targets/TARGET_ONSEMI/TARGET_NCS36510/exceptions.c +++ b/targets/TARGET_ONSEMI/TARGET_NCS36510/exceptions.c @@ -117,11 +117,13 @@ void fIrqUart2Handler(void) Uart2_Irq(); } +#ifdef DEVICE_RTC /** Call the RTC IRQ handler */ void fIrqRtcHandler(void) { fRtcHandler(); } +#endif /** Call the I2C IRQ handler */ void fIrqI2CHandler(void) diff --git a/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_lp_ticker_api.c b/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_lp_ticker_api.c index fec4c07246..2e80f07f5d 100644 --- a/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_lp_ticker_api.c +++ b/targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_lp_ticker_api.c @@ -7,11 +7,11 @@ * $Rev: $ * $Date: $ ****************************************************************************** - * Copyright 2016 Semiconductor Components Industries LLC (d/b/a “ON Semiconductor”). + * Copyright 2016 Semiconductor Components Industries LLC (d/b/a �ON Semiconductor�). * All rights reserved. This software and/or documentation is licensed by ON Semiconductor * under limited terms and conditions. The terms and conditions pertaining to the software * and/or documentation are available at http://www.onsemi.com/site/pdf/ONSEMI_T&C.pdf - * (“ON Semiconductor Standard Terms and Conditions of Sale, Section 8 Software”) and + * (�ON Semiconductor Standard Terms and Conditions of Sale, Section 8 Software�) and * if applicable the software license agreement. Do not use this software and/or * documentation unless you have carefully read and you agree to the limited terms and * conditions. By using this software and/or documentation, you agree to the limited @@ -32,7 +32,7 @@ */ #include "device.h" -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER #include "cmsis_nvic.h" #include "lp_ticker_api.h" @@ -79,4 +79,4 @@ void lp_ticker_clear_interrupt(void) fRtcClearInterrupt(); } -#endif /* DEVICE_LOWPOWERTIMER */ +#endif /* DEVICE_LPTICKER */ diff --git a/targets/TARGET_ONSEMI/TARGET_NCS36510/rtc.c b/targets/TARGET_ONSEMI/TARGET_NCS36510/rtc.c index de035dc3fa..e174828949 100644 --- a/targets/TARGET_ONSEMI/TARGET_NCS36510/rtc.c +++ b/targets/TARGET_ONSEMI/TARGET_NCS36510/rtc.c @@ -41,6 +41,9 @@ * if the alarm occurs upon a Counter increment condition. * */ + +#ifdef DEVICE_RTC + #include "rtc.h" #include "mbed_assert.h" #include "lp_ticker_api.h" @@ -300,3 +303,5 @@ boolean fIsRtcEnabled(void) return False; } } + +#endif diff --git a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_GR_LYCHEE/mbed_drv_cfg.h b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_GR_LYCHEE/mbed_drv_cfg.h index 05ad76fae1..23585cffdf 100644 --- a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_GR_LYCHEE/mbed_drv_cfg.h +++ b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_GR_LYCHEE/mbed_drv_cfg.h @@ -32,4 +32,6 @@ //#define USE_EXTAL_CLK //#define USE_RTCX3_CLK +#define RENESAS_RZ_A1_P0_CLK CM1_RENESAS_RZ_A1_P0_CLK + #endif diff --git a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_RZ_A1H/mbed_drv_cfg.h b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_RZ_A1H/mbed_drv_cfg.h index 827ad7fce3..cb9f0ede02 100644 --- a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_RZ_A1H/mbed_drv_cfg.h +++ b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_RZ_A1H/mbed_drv_cfg.h @@ -32,4 +32,6 @@ #define USE_EXTAL_CLK //#define USE_RTCX3_CLK +#define RENESAS_RZ_A1_P0_CLK CM0_RENESAS_RZ_A1_P0_CLK + #endif diff --git a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_VK_RZ_A1H/mbed_drv_cfg.h b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_VK_RZ_A1H/mbed_drv_cfg.h index 9b3c35d31f..39dc188f49 100644 --- a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_VK_RZ_A1H/mbed_drv_cfg.h +++ b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_VK_RZ_A1H/mbed_drv_cfg.h @@ -32,4 +32,6 @@ //#define USE_EXTAL_CLK //#define USE_RTCX3_CLK +#define RENESAS_RZ_A1_P0_CLK CM0_RENESAS_RZ_A1_P0_CLK + #endif diff --git a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/rtc_api.c b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/rtc_api.c index 51347827f5..4175911ce7 100644 --- a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/rtc_api.c +++ b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/rtc_api.c @@ -82,7 +82,8 @@ static uint16_t rtc_hex16_to_dec(uint16_t hex_val); * [out] * None. */ -void rtc_init(void) { +void rtc_init(void) +{ volatile uint8_t dummy_read; CPG.STBCR6 &= ~(CPG_STBCR6_BIT_MSTP60); @@ -109,31 +110,12 @@ void rtc_init(void) { dummy_read = RTC.RCR2; dummy_read = RTC.RCR2; - RTC.RCR2 = RCR2_VAL_RESET; // RESET = 1 + RTC.RCR2 = RCR2_VAL_START; // SRART = 1 // Dummy read dummy_read = RTC.RCR2; dummy_read = RTC.RCR2; - // Set timer and alarm. Default value :01-01-1970 00:00:00 - RTC.RSECCNT = 0; - RTC.RMINCNT = 0; - RTC.RHRCNT = 0; - RTC.RWKCNT = 0; - RTC.RDAYCNT = 1; - RTC.RMONCNT = 1; - RTC.RYRCNT = 0x1970; - RTC.RSECAR = 0; - RTC.RMINAR = 0; - RTC.RHRAR = 0; - RTC.RWKAR = 0; - RTC.RDAYAR = 1; - RTC.RMONAR = 1; - RTC.RYRAR = 0x1970; - - // Dummy read - dummy_read = RTC.RYRCNT; - dummy_read = RTC.RYRCNT; (void)dummy_read; } @@ -141,52 +123,14 @@ void rtc_init(void) { /* * Release the RTC based on a time structure. + * @note This function does not stop the RTC from counting * [in] * None. * [out] * None. */ -void rtc_free(void) { - volatile uint8_t dummy_read; - - // Set control register - RTC.RCR2 = RCR2_VAL_ALLSTOP; - RTC.RCR1 = RCR1_VAL_OFF; - RTC.RCR3 = RCR3_VAL; - RTC.RCR5 = RCR5_VAL; - RTC.RFRH = RFRH_VAL_MAX; - RTC.RFRL = RFRL_VAL_MAX; - - // Dummy read - dummy_read = RTC.RCR2; - dummy_read = RTC.RCR2; - RTC.RCR2 = RCR2_VAL_RESET; // RESET = 1 - - // Dummy read - dummy_read = RTC.RCR2; - dummy_read = RTC.RCR2; - - // Set timer and alarm. Default value :01-01-1970 00:00:00 - RTC.RSECCNT = 0; - RTC.RMINCNT = 0; - RTC.RHRCNT = 0; - RTC.RWKCNT = 0; - RTC.RDAYCNT = 1; - RTC.RMONCNT = 1; - RTC.RYRCNT = 0x1970; - RTC.RSECAR = 0; - RTC.RMINAR = 0; - RTC.RHRAR = 0; - RTC.RWKAR = 0; - RTC.RDAYAR = 1; - RTC.RMONAR = 1; - RTC.RYRAR = 0x1970; - - // Dummy read - dummy_read = RTC.RYRCNT; - dummy_read = RTC.RYRCNT; - (void)dummy_read; - +void rtc_free(void) +{ } @@ -198,7 +142,8 @@ void rtc_free(void) { * [out] * 0:Disabled, 1:Enabled. */ -int rtc_isenabled(void) { +int rtc_isenabled(void) +{ int ret_val = 0; if ((RTC.RCR1 & RCR1_VAL_ON) != 0) { // RTC ON ? @@ -216,7 +161,8 @@ int rtc_isenabled(void) { * [out] * UNIX timestamp value. */ -time_t rtc_read(void) { +time_t rtc_read(void) +{ struct tm timeinfo; int err = 0; @@ -267,7 +213,8 @@ time_t rtc_read(void) { * 0:Success * 1:Error */ -static int rtc_dec8_to_hex(uint8_t dec_val, uint8_t offset, int *hex_val) { +static int rtc_dec8_to_hex(uint8_t dec_val, uint8_t offset, int *hex_val) +{ int err = 0; uint8_t ret_val; @@ -301,7 +248,8 @@ static int rtc_dec8_to_hex(uint8_t dec_val, uint8_t offset, int *hex_val) { * 0:Success * 1:Error */ -static int rtc_dec16_to_hex(uint16_t dec_val, uint16_t offset, int *hex_val) { +static int rtc_dec16_to_hex(uint16_t dec_val, uint16_t offset, int *hex_val) +{ int err = 0; uint16_t ret_val; @@ -336,7 +284,8 @@ static int rtc_dec16_to_hex(uint16_t dec_val, uint16_t offset, int *hex_val) { * [out] * None. */ -void rtc_write(time_t t) { +void rtc_write(time_t t) +{ struct tm timeinfo; if (_rtc_localtime(t, &timeinfo, RTC_FULL_LEAP_YEAR_SUPPORT) == false) { @@ -377,7 +326,8 @@ void rtc_write(time_t t) { * [out] * decimal value:From 0x00 to 0x99. */ -static uint8_t rtc_hex8_to_dec(uint8_t hex_val) { +static uint8_t rtc_hex8_to_dec(uint8_t hex_val) +{ uint32_t calc_data; calc_data = hex_val / 10 * 0x10; @@ -397,7 +347,8 @@ static uint8_t rtc_hex8_to_dec(uint8_t hex_val) { * [out] * decimal value:From 0x0000 to 0x9999. */ -static uint16_t rtc_hex16_to_dec(uint16_t hex_val) { +static uint16_t rtc_hex16_to_dec(uint16_t hex_val) +{ uint32_t calc_data; calc_data = hex_val / 1000 * 0x1000; calc_data += ((hex_val / 100) % 10) * 0x100; diff --git a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/sleep.c b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/sleep.c new file mode 100644 index 0000000000..025231f2bb --- /dev/null +++ b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/sleep.c @@ -0,0 +1,198 @@ +/* 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 "sleep_api.h" +#include "cmsis.h" +#include "mbed_interface.h" +#include "mbed_critical.h" +#include "iodefine.h" + +#if DEVICE_SLEEP +static volatile uint8_t wk_CPGSTBCR3; +static volatile uint8_t wk_CPGSTBCR4; +static volatile uint8_t wk_CPGSTBCR5; +static volatile uint8_t wk_CPGSTBCR6; +static volatile uint8_t wk_CPGSTBCR7; +static volatile uint8_t wk_CPGSTBCR8; +static volatile uint8_t wk_CPGSTBCR9; +static volatile uint8_t wk_CPGSTBCR10; +static volatile uint8_t wk_CPGSTBCR11; +static volatile uint8_t wk_CPGSTBCR12; +#if defined(TARGET_RZA1H) || defined(TARGET_VK_RZ_A1H) +static volatile uint8_t wk_CPGSTBCR13; +#endif +static volatile uint8_t wk_CPGSTBREQ1; +static volatile uint8_t wk_CPGSTBREQ2; + +typedef struct { + volatile uint8_t * p_wk_stbcr; + volatile uint8_t * p_stbcr; + volatile uint8_t * p_stbreq; + volatile uint8_t * p_stback; + uint8_t mstp; + uint8_t stbrq; +} module_stanby_t; + +static const module_stanby_t module_stanby[] = { + {&wk_CPGSTBCR6, &CPGSTBCR6, &CPGSTBREQ1, &CPGSTBACK1, CPG_STBCR6_BIT_MSTP61, CPG_STBREQ1_BIT_STBRQ13}, /* JCU */ + {&wk_CPGSTBCR6, &CPGSTBCR6, &CPGSTBREQ1, &CPGSTBACK1, CPG_STBCR6_BIT_MSTP66, CPG_STBREQ1_BIT_STBRQ10}, /* CEU */ + {&wk_CPGSTBCR6, &CPGSTBCR8, &CPGSTBREQ1, &CPGSTBACK1, CPG_STBCR8_BIT_MSTP82, CPG_STBREQ1_BIT_STBRQ12}, /* EthernetAVB */ + {&wk_CPGSTBCR7, &CPGSTBCR7, &CPGSTBREQ2, &CPGSTBACK2, CPG_STBCR7_BIT_MSTP74, CPG_STBREQ2_BIT_STBRQ26}, /* Ethernet */ + {&wk_CPGSTBCR8, &CPGSTBCR8, &CPGSTBREQ2, &CPGSTBACK2, CPG_STBCR8_BIT_MSTP83, CPG_STBREQ2_BIT_STBRQ27}, /* MediaLB */ + {&wk_CPGSTBCR9, &CPGSTBCR9, &CPGSTBREQ2, &CPGSTBACK2, CPG_STBCR9_BIT_MSTP91, CPG_STBREQ2_BIT_STBRQ25}, /* VDC5_0 */ +#if defined(TARGET_RZA1H) || defined(TARGET_VK_RZ_A1H) + {&wk_CPGSTBCR8, &CPGSTBCR8, &CPGSTBREQ2, &CPGSTBACK2, CPG_STBCR8_BIT_MSTP85, CPG_STBREQ2_BIT_STBRQ21}, /* IMR-LSD */ + {&wk_CPGSTBCR8, &CPGSTBCR8, &CPGSTBREQ2, &CPGSTBACK2, CPG_STBCR8_BIT_MSTP86, CPG_STBREQ2_BIT_STBRQ22}, /* IMR-LS2_1 */ + {&wk_CPGSTBCR8, &CPGSTBCR8, &CPGSTBREQ2, &CPGSTBACK2, CPG_STBCR8_BIT_MSTP87, CPG_STBREQ2_BIT_STBRQ23}, /* IMR-LS2_0 */ + {&wk_CPGSTBCR9, &CPGSTBCR9, &CPGSTBREQ2, &CPGSTBACK2, CPG_STBCR9_BIT_MSTP90, CPG_STBREQ2_BIT_STBRQ24}, /* VDC5_1 */ + {&wk_CPGSTBCR10, &CPGSTBCR10, &CPGSTBREQ2, &CPGSTBACK2, CPG_STBCR10_BIT_MSTP100, CPG_STBREQ2_BIT_STBRQ20}, /* OpenVG */ +#endif + {0, 0, 0, 0, 0} /* None */ +}; + +static void module_standby_in(void) { + volatile uint32_t cnt; + volatile uint8_t dummy_8; + const module_stanby_t * p_module = &module_stanby[0]; + + while (p_module->p_wk_stbcr != 0) { + if ((*p_module->p_wk_stbcr & p_module->mstp) == 0) { + *p_module->p_stbreq |= p_module->stbrq; + dummy_8 = *p_module->p_stbreq; + for (cnt = 0; cnt < 1000; cnt++) { // wait time + if ((*p_module->p_stback & p_module->stbrq) != 0) { + break; + } + } + *p_module->p_stbcr |= p_module->mstp; + dummy_8 = *p_module->p_stbcr; + } + p_module++; + } + (void)dummy_8; +} + +static void module_standby_out(void) { + volatile uint32_t cnt; + volatile uint8_t dummy_8; + const module_stanby_t * p_module = &module_stanby[0]; + + while (p_module->p_wk_stbcr != 0) { + if ((*p_module->p_wk_stbcr & p_module->mstp) == 0) { + *p_module->p_stbreq &= ~(p_module->stbrq); + dummy_8 = *p_module->p_stbreq; + for (cnt = 0; cnt < 1000; cnt++) { + if ((*p_module->p_stback & p_module->stbrq) == 0) { + break; + } + } + } + p_module++; + } + (void)dummy_8; +} + +void hal_sleep(void) { + // Transition to Sleep Mode + __WFI(); +} + +void hal_deepsleep(void) { + volatile uint8_t dummy_8; + + core_util_critical_section_enter(); + /* For powerdown the peripheral module, save current standby control register values(just in case) */ + wk_CPGSTBCR3 = CPGSTBCR3; + wk_CPGSTBCR4 = CPGSTBCR4; + wk_CPGSTBCR5 = CPGSTBCR5; + wk_CPGSTBCR6 = CPGSTBCR6; + wk_CPGSTBCR7 = CPGSTBCR7; + wk_CPGSTBCR8 = CPGSTBCR8; + wk_CPGSTBCR9 = CPGSTBCR9; + wk_CPGSTBCR10 = CPGSTBCR10; + wk_CPGSTBCR11 = CPGSTBCR11; + wk_CPGSTBCR12 = CPGSTBCR12; +#if defined(TARGET_RZA1H) || defined(TARGET_VK_RZ_A1H) + wk_CPGSTBCR13 = CPGSTBCR13; +#endif + + /* MTU2 (for low power ticker) */ + CPGSTBCR3 |= ~(CPG_STBCR3_BIT_MSTP33); + dummy_8 = CPGSTBCR3; + CPGSTBCR4 = 0xFF; + dummy_8 = CPGSTBCR4; + CPGSTBCR5 = 0xFF; + dummy_8 = CPGSTBCR5; + /* Realtime Clock, JCU, CEU */ + CPGSTBCR6 |= ~(CPG_STBCR6_BIT_MSTP60 | CPG_STBCR6_BIT_MSTP61 | CPG_STBCR6_BIT_MSTP66); + dummy_8 = CPGSTBCR6; + /* Video Decoder0, Video Decoder1, Ethernet */ + CPGSTBCR7 |= ~(CPG_STBCR7_BIT_MSTP77 | CPG_STBCR7_BIT_MSTP76 | CPG_STBCR7_BIT_MSTP74); + dummy_8 = CPGSTBCR7; + /* EthernetAVB, MediaLB, IMR-LSD, IMR-LS2_1, IMR-LS2_0 */ + CPGSTBCR8 |= ~(CPG_STBCR8_BIT_MSTP82 | CPG_STBCR8_BIT_MSTP83 | CPG_STBCR8_BIT_MSTP85 | CPG_STBCR8_BIT_MSTP86 | CPG_STBCR8_BIT_MSTP87); + dummy_8 = CPGSTBCR8; + /* VDC5_1, SPI Multi I/O Bus Controller0 */ + CPGSTBCR9 |= ~(CPG_STBCR9_BIT_MSTP90 | CPG_STBCR9_BIT_MSTP93); + dummy_8 = CPGSTBCR9; + /* OpenVG */ + CPGSTBCR10 |= ~(CPG_STBCR10_BIT_MSTP100); + dummy_8 = CPGSTBCR10; + CPGSTBCR11 = 0xFF; + dummy_8 = CPGSTBCR11; + CPGSTBCR12 = 0xFF; + dummy_8 = CPGSTBCR12; +#if defined(TARGET_RZA1H) || defined(TARGET_VK_RZ_A1H) + CPGSTBCR13 = 0xFF; + dummy_8 = CPGSTBCR13; +#endif + + module_standby_in(); + + // Transition to Sleep Mode + __WFI(); + + /* Revert standby control register values */ + CPGSTBCR3 = wk_CPGSTBCR3; + dummy_8 = CPGSTBCR3; + CPGSTBCR4 = wk_CPGSTBCR4; + dummy_8 = CPGSTBCR4; + CPGSTBCR5 = wk_CPGSTBCR5; + dummy_8 = CPGSTBCR5; + CPGSTBCR6 = wk_CPGSTBCR6; + dummy_8 = CPGSTBCR6; + CPGSTBCR7 = wk_CPGSTBCR7; + dummy_8 = CPGSTBCR7; + CPGSTBCR8 = wk_CPGSTBCR8; + dummy_8 = CPGSTBCR8; + CPGSTBCR9 = wk_CPGSTBCR9; + dummy_8 = CPGSTBCR9; + CPGSTBCR10 = wk_CPGSTBCR10; + dummy_8 = CPGSTBCR10; + CPGSTBCR11 = wk_CPGSTBCR11; + dummy_8 = CPGSTBCR11; + CPGSTBCR12 = wk_CPGSTBCR12; + dummy_8 = CPGSTBCR12; +#if defined(TARGET_RZA1H) || defined(TARGET_VK_RZ_A1H) + CPGSTBCR13 = wk_CPGSTBCR13; + dummy_8 = CPGSTBCR13; +#endif + + module_standby_out(); + core_util_critical_section_exit(); + + (void)dummy_8; +} +#endif diff --git a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/us_ticker.c b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/us_ticker.c index e6951fb7c9..3fb58a3884 100644 --- a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/us_ticker.c +++ b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/us_ticker.c @@ -13,139 +13,78 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include #include "us_ticker_api.h" -#include "PeripheralNames.h" -#include "iodefine.h" -#include "cmsis.h" +#include "mbed_drv_cfg.h" -#include "RZ_A1_Init.h" -#include "vfp_neon_push_pop.h" -#include "mbed_critical.h" +#define SHIFT_NUM 5 /* P0/32 */ -#define US_TICKER_TIMER_IRQn (OSTMI1TINT_IRQn) -#define CPG_STBCR5_BIT_MSTP50 (0x01u) /* OSTM1 */ +static int us_ticker_inited = 0; -#define US_TICKER_CLOCK_US_DEV (1000000) - -int us_ticker_inited = 0; -static double count_clock = 0; -static uint32_t last_read = 0; -static uint32_t wrap_arround = 0; -static uint64_t ticker_us_last64 = 0; -static uint64_t set_cmp_val64 = 0; -static uint64_t timestamp64 = 0; - -void us_ticker_interrupt(void) { - us_ticker_irq_handler(); -} - -void us_ticker_init(void) { - if (us_ticker_inited) return; - us_ticker_inited = 1; - - /* set Counter Clock(us) */ - if (false == RZ_A1_IsClockMode0()) { - count_clock = ((double)CM1_RENESAS_RZ_A1_P0_CLK / (double)US_TICKER_CLOCK_US_DEV); - } else { - count_clock = ((double)CM0_RENESAS_RZ_A1_P0_CLK / (double)US_TICKER_CLOCK_US_DEV); - } +void us_ticker_init(void) +{ + GIC_DisableIRQ(OSTMI1TINT_IRQn); + GIC_ClearPendingIRQ(OSTMI1TINT_IRQn); /* Power Control for Peripherals */ CPGSTBCR5 &= ~(CPG_STBCR5_BIT_MSTP50); /* enable OSTM1 clock */ + if (us_ticker_inited) return; + us_ticker_inited = 1; + // timer settings OSTM1TT = 0x01; /* Stop the counter and clears the OSTM1TE bit. */ OSTM1CTL = 0x02; /* Free running timer mode. Interrupt disabled when star counter */ - OSTM1TS = 0x1; /* Start the counter and sets the OSTM0TE bit. */ + OSTM1TS = 0x1; /* Start the counter and sets the OSTM0TE bit. */ // INTC settings - InterruptHandlerRegister(US_TICKER_TIMER_IRQn, (void (*)(uint32_t))us_ticker_interrupt); - GIC_SetPriority(US_TICKER_TIMER_IRQn, 5); - GIC_SetConfiguration(US_TICKER_TIMER_IRQn, 3); - GIC_EnableIRQ(US_TICKER_TIMER_IRQn); + InterruptHandlerRegister(OSTMI1TINT_IRQn, (void (*)(uint32_t))us_ticker_irq_handler); + GIC_SetPriority(OSTMI1TINT_IRQn, 5); + GIC_SetConfiguration(OSTMI1TINT_IRQn, 3); } -static uint64_t ticker_read_counter64(void) { - uint32_t cnt_val; - uint64_t cnt_val64; +void us_ticker_free(void) +{ + GIC_DisableIRQ(OSTMI1TINT_IRQn); + GIC_ClearPendingIRQ(OSTMI1TINT_IRQn); - if (!us_ticker_inited) - us_ticker_init(); - - /* read counter */ - cnt_val = OSTM1CNT; - if (last_read > cnt_val) { - wrap_arround++; - } - last_read = cnt_val; - cnt_val64 = ((uint64_t)wrap_arround << 32) + cnt_val; - - return cnt_val64; + /* Power Control for Peripherals */ + CPGSTBCR5 |= (CPG_STBCR5_BIT_MSTP50); /* disable OSTM1 clock */ } -static void us_ticker_read_last(void) { - uint64_t cnt_val64; - - cnt_val64 = ticker_read_counter64(); - - ticker_us_last64 = (cnt_val64 / count_clock); +uint32_t us_ticker_read() +{ + return (uint32_t)(OSTM1CNT >> SHIFT_NUM); } -uint32_t us_ticker_read() { - core_util_critical_section_enter(); - - __vfp_neon_push(); - us_ticker_read_last(); - __vfp_neon_pop(); - - core_util_critical_section_exit(); - - /* clock to us */ - return (uint32_t)ticker_us_last64; +void us_ticker_set_interrupt(timestamp_t timestamp) +{ + OSTM1CMP = (uint32_t)(timestamp << SHIFT_NUM); + GIC_EnableIRQ(OSTMI1TINT_IRQn); } -static void us_ticker_calc_compare_match(void) { - set_cmp_val64 = timestamp64 * count_clock; +void us_ticker_fire_interrupt(void) +{ + GIC_SetPendingIRQ(OSTMI1TINT_IRQn); + GIC_EnableIRQ(OSTMI1TINT_IRQn); } -void us_ticker_set_interrupt(timestamp_t timestamp) { - // set match value - volatile uint32_t set_cmp_val; - uint64_t count_val_64; - - /* calc compare mach timestamp */ - timestamp64 = (ticker_us_last64 & 0xFFFFFFFF00000000) + timestamp; - if (timestamp < (ticker_us_last64 & 0x00000000FFFFFFFF)) { - /* This event is wrap arround */ - timestamp64 += 0x100000000; - } - - /* calc compare mach timestamp */ - __vfp_neon_push(); - us_ticker_calc_compare_match(); - __vfp_neon_pop(); - - set_cmp_val = (uint32_t)(set_cmp_val64 & 0x00000000FFFFFFFF); - count_val_64 = ticker_read_counter64(); - if (set_cmp_val64 <= (count_val_64 + 500)) { - GIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); - GIC_EnableIRQ(US_TICKER_TIMER_IRQn); - return; - } - OSTM1CMP = set_cmp_val; - GIC_EnableIRQ(US_TICKER_TIMER_IRQn); +void us_ticker_disable_interrupt(void) +{ + GIC_DisableIRQ(OSTMI1TINT_IRQn); } -void us_ticker_fire_interrupt(void) { - GIC_SetPendingIRQ(US_TICKER_TIMER_IRQn); +void us_ticker_clear_interrupt(void) +{ + GIC_ClearPendingIRQ(OSTMI1TINT_IRQn); } -void us_ticker_disable_interrupt(void) { - GIC_DisableIRQ(US_TICKER_TIMER_IRQn); +const ticker_info_t* us_ticker_get_info() +{ + static const ticker_info_t info = { + (uint32_t)((float)RENESAS_RZ_A1_P0_CLK / (float)(1 << SHIFT_NUM) + 0.5f), + (32 - SHIFT_NUM) + }; + return &info; } -void us_ticker_clear_interrupt(void) { - GIC_ClearPendingIRQ(US_TICKER_TIMER_IRQn); -} diff --git a/targets/TARGET_STM/hal_tick_16b.c b/targets/TARGET_STM/hal_tick_16b.c index 041c22c304..a617e2dd65 100644 --- a/targets/TARGET_STM/hal_tick_16b.c +++ b/targets/TARGET_STM/hal_tick_16b.c @@ -22,9 +22,6 @@ extern TIM_HandleTypeDef TimMasterHandle; -extern volatile uint32_t SlaveCounter; -extern volatile uint32_t oc_int_part; - volatile uint32_t PreviousVal = 0; void us_ticker_irq_handler(void); @@ -37,14 +34,6 @@ void timer_irq_handler(void) #endif TimMasterHandle.Instance = TIM_MST; - // Clear Update interrupt flag - if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_UPDATE) == SET) { - if (__HAL_TIM_GET_IT_SOURCE(&TimMasterHandle, TIM_IT_UPDATE) == SET) { - __HAL_TIM_CLEAR_IT(&TimMasterHandle, TIM_IT_UPDATE); - SlaveCounter++; - } - } - #if defined(TARGET_STM32F0) } // end timer_update_irq_handler function // Used for mbed timeout (channel 1) and HAL tick (channel 2) @@ -57,12 +46,7 @@ void timer_oc_irq_handler(void) if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1) == SET) { if (__HAL_TIM_GET_IT_SOURCE(&TimMasterHandle, TIM_IT_CC1) == SET) { __HAL_TIM_CLEAR_IT(&TimMasterHandle, TIM_IT_CC1); - - if (oc_int_part > 0) { - oc_int_part--; - } else { us_ticker_irq_handler(); - } } } @@ -142,7 +126,6 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) #endif // Enable interrupts - __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_UPDATE); // For 32-bit counter __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC2); // For HAL tick // Enable timer diff --git a/targets/TARGET_STM/lp_ticker.c b/targets/TARGET_STM/lp_ticker.c index 7b12b34736..e089cd05d4 100644 --- a/targets/TARGET_STM/lp_ticker.c +++ b/targets/TARGET_STM/lp_ticker.c @@ -1,6 +1,6 @@ /* mbed Microcontroller Library ******************************************************************************* - * Copyright (c) 2017, STMicroelectronics + * Copyright (c) 2018, STMicroelectronics * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,25 +28,40 @@ ******************************************************************************* */ -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER -#include "rtc_api_hal.h" +/***********************************************************************/ +/* lpticker_lptim config is 1 in json config file */ +/* LPTICKER is based on LPTIM feature from ST drivers. RTC is not used */ +#if MBED_CONF_TARGET_LPTICKER_LPTIM -#if MBED_CONF_TARGET_LOWPOWERTIMER_LPTIM +#include "lp_ticker_api.h" +#include "mbed_error.h" LPTIM_HandleTypeDef LptimHandle; -volatile uint32_t lp_SlaveCounter = 0; -volatile uint32_t lp_oc_int_part = 0; -volatile uint16_t lp_TickPeriod_us; +const ticker_info_t* lp_ticker_get_info() +{ + static const ticker_info_t info = { +#if MBED_CONF_TARGET_LSE_AVAILABLE + LSE_VALUE, +#else + LSI_VALUE, +#endif + 16 + }; + return &info; +} + volatile uint8_t lp_Fired = 0; static void LPTIM1_IRQHandler(void); static void (*irq_handler)(void); - void lp_ticker_init(void) { + NVIC_DisableIRQ(LPTIM1_IRQn); + /* Check if LPTIM is already configured */ #if (TARGET_STM32L0) if (READ_BIT(RCC->APB1ENR, RCC_APB1ENR_LPTIM1EN) != RESET) { @@ -111,21 +126,7 @@ void lp_ticker_init(void) LptimHandle.Instance = LPTIM1; LptimHandle.State = HAL_LPTIM_STATE_RESET; LptimHandle.Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC; - - /* Prescaler impact: - tick period = Prescaler division factor / LPTIM clock - Example with LPTIM clock = 32768 Hz LSE - Prescaler = LPTIM_PRESCALER_DIV1 => lp_TickPeriod_us = 31us => 2s with 16b timer - Prescaler = LPTIM_PRESCALER_DIV2 => lp_TickPeriod_us = 61us => 4s with 16b timer - Prescaler = LPTIM_PRESCALER_DIV4 => lp_TickPeriod_us = 122us => 8s with 16b timer - Prescaler = LPTIM_PRESCALER_DIV8 => lp_TickPeriod_us = 244us => 16s with 16b timer - Prescaler = LPTIM_PRESCALER_DIV16 => lp_TickPeriod_us = 488us => 32s with 16b timer - Prescaler = LPTIM_PRESCALER_DIV32 => lp_TickPeriod_us = 976us => 64s with 16b timer - Prescaler = LPTIM_PRESCALER_DIV64 => lp_TickPeriod_us = 1.9ms => 128s with 16b timer - Prescaler = LPTIM_PRESCALER_DIV128 => lp_TickPeriod_us = 3.9ms => 256s with 16b timer - */ - LptimHandle.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV2; - lp_TickPeriod_us = 2 * 1000000 / RTC_CLOCK; + LptimHandle.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV1; LptimHandle.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE; LptimHandle.Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH; @@ -142,7 +143,6 @@ void lp_ticker_init(void) } NVIC_SetVector(LPTIM1_IRQn, (uint32_t)LPTIM1_IRQHandler); - NVIC_EnableIRQ(LPTIM1_IRQn); #if !(TARGET_STM32L4) /* EXTI lines are not configured by default */ @@ -150,10 +150,10 @@ void lp_ticker_init(void) __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE(); #endif - __HAL_LPTIM_ENABLE_IT(&LptimHandle, LPTIM_IT_ARRM); __HAL_LPTIM_ENABLE_IT(&LptimHandle, LPTIM_IT_CMPM); - __HAL_LPTIM_ENABLE_IT(&LptimHandle, LPTIM_IT_CMPOK); HAL_LPTIM_Counter_Start(&LptimHandle, 0xFFFF); + + __HAL_LPTIM_COMPARE_SET(&LptimHandle, 0); } static void LPTIM1_IRQHandler(void) @@ -173,140 +173,102 @@ static void LPTIM1_IRQHandler(void) /* Clear Compare match flag */ __HAL_LPTIM_CLEAR_FLAG(&LptimHandle, LPTIM_FLAG_CMPM); - if (lp_oc_int_part > 0) { - lp_oc_int_part--; - } else { - if (irq_handler) { - irq_handler(); - } + if (irq_handler) { + irq_handler(); } } } - /* Compare write interrupt */ - if (__HAL_LPTIM_GET_FLAG(&LptimHandle, LPTIM_FLAG_CMPOK) != RESET) { - if (__HAL_LPTIM_GET_IT_SOURCE(&LptimHandle, LPTIM_IT_CMPOK) != RESET) { - /* Clear Compare write flag */ - __HAL_LPTIM_CLEAR_FLAG(&LptimHandle, LPTIM_FLAG_CMPOK); - } - } - - /* Autoreload match interrupt */ - if (__HAL_LPTIM_GET_FLAG(&LptimHandle, LPTIM_FLAG_ARRM) != RESET) { - if (__HAL_LPTIM_GET_IT_SOURCE(&LptimHandle, LPTIM_IT_ARRM) != RESET) { - /* Clear Autoreload match flag */ - __HAL_LPTIM_CLEAR_FLAG(&LptimHandle, LPTIM_FLAG_ARRM); - lp_SlaveCounter++; - } - } - #if !(TARGET_STM32L4) __HAL_LPTIM_WAKEUPTIMER_EXTI_CLEAR_FLAG(); #endif } - -uint32_t lp_ticker_read_TickCounter(void) -{ - uint16_t cntH_old, cntH, cntL; - - LptimHandle.Instance = LPTIM1; - - /* same algo as us_ticker_read in us_ticker_16b.c */ - do { - cntH_old = lp_SlaveCounter; - if (__HAL_LPTIM_GET_FLAG(&LptimHandle, LPTIM_FLAG_ARRM) == SET) { - cntH_old += 1; - } - cntL = LPTIM1->CNT; - cntH = lp_SlaveCounter; - if (__HAL_LPTIM_GET_FLAG(&LptimHandle, LPTIM_FLAG_ARRM) == SET) { - cntH += 1; - } - } while (cntH_old != cntH); - uint32_t lp_time = (uint32_t)(cntH << 16 | cntL); - return lp_time; -} - uint32_t lp_ticker_read(void) { - lp_ticker_init(); - return lp_ticker_read_TickCounter() * (uint32_t)lp_TickPeriod_us; + uint32_t lp_time = LPTIM1->CNT; + /* Reading the LPTIM_CNT register may return unreliable values. + It is necessary to perform two consecutive read accesses and verify that the two returned values are identical */ + while (lp_time != LPTIM1->CNT) { + lp_time = LPTIM1->CNT; + } + return lp_time; } void lp_ticker_set_interrupt(timestamp_t timestamp) { - // Disable IRQs - core_util_critical_section_enter(); - - uint32_t timestamp_TickCounter = timestamp / (uint32_t)lp_TickPeriod_us; - LptimHandle.Instance = LPTIM1; irq_handler = (void (*)(void))lp_ticker_irq_handler; - __HAL_LPTIM_CLEAR_FLAG(&LptimHandle, LPTIM_FLAG_CMPOK); - __HAL_LPTIM_CLEAR_FLAG(&LptimHandle, LPTIM_FLAG_CMPM); - __HAL_LPTIM_COMPARE_SET(&LptimHandle, timestamp_TickCounter & 0xFFFF); - /* CMPOK is set by hardware to inform application that the APB bus write operation to the LPTIM_CMP register has been successfully completed */ + /* Any successive write before respectively the ARROK flag or the CMPOK flag be set, will lead to unpredictable results */ while (__HAL_LPTIM_GET_FLAG(&LptimHandle, LPTIM_FLAG_CMPOK) == RESET) { } - /* same algo as us_ticker_set_interrupt in us_ticker_16b.c */ - uint32_t current_time_TickCounter = lp_ticker_read_TickCounter(); - uint32_t delta = timestamp_TickCounter - current_time_TickCounter; - lp_oc_int_part = (delta - 1) >> 16; - if ( ((delta - 1) & 0xFFFF) >= 0x8000 && - __HAL_LPTIM_GET_FLAG(&LptimHandle, LPTIM_FLAG_CMPM) == SET ) { - ++lp_oc_int_part; - } + __HAL_LPTIM_CLEAR_FLAG(&LptimHandle, LPTIM_FLAG_CMPOK); + __HAL_LPTIM_CLEAR_FLAG(&LptimHandle, LPTIM_FLAG_CMPM); + __HAL_LPTIM_COMPARE_SET(&LptimHandle, timestamp); - // Enable IRQs - core_util_critical_section_exit(); + NVIC_EnableIRQ(LPTIM1_IRQn); } void lp_ticker_fire_interrupt(void) { lp_Fired = 1; NVIC_SetPendingIRQ(LPTIM1_IRQn); + NVIC_EnableIRQ(LPTIM1_IRQn); } void lp_ticker_disable_interrupt(void) { LptimHandle.Instance = LPTIM1; - __HAL_LPTIM_DISABLE_IT(&LptimHandle, LPTIM_IT_CMPM); + NVIC_DisableIRQ(LPTIM1_IRQn); } void lp_ticker_clear_interrupt(void) { LptimHandle.Instance = LPTIM1; __HAL_LPTIM_CLEAR_FLAG(&LptimHandle, LPTIM_FLAG_CMPM); + NVIC_ClearPendingIRQ(LPTIM1_IRQn); } -#else /* MBED_CONF_TARGET_LOWPOWERTIMER_LPTIM */ + + +/*****************************************************************/ +/* lpticker_lptim config is 0 or not defined in json config file */ +/* LPTICKER is based on RTC wake up feature from ST drivers */ +#else /* MBED_CONF_TARGET_LPTICKER_LPTIM */ + +#include "rtc_api_hal.h" + +const ticker_info_t* lp_ticker_get_info() +{ + static const ticker_info_t info = { + RTC_CLOCK/4, // RTC_WAKEUPCLOCK_RTCCLK_DIV4 + 32 + }; + return &info; +} void lp_ticker_init(void) { rtc_init(); + lp_ticker_disable_interrupt(); } uint32_t lp_ticker_read(void) { - uint32_t usecs = rtc_read_us(); - return usecs; + return rtc_read_lp(); } void lp_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t delta; - - delta = timestamp - lp_ticker_read(); - rtc_set_wake_up_timer(delta); + rtc_set_wake_up_timer(timestamp); } void lp_ticker_fire_interrupt(void) { - NVIC_SetPendingIRQ(RTC_WKUP_IRQn); + rtc_fire_interrupt(); } void lp_ticker_disable_interrupt(void) @@ -316,9 +278,9 @@ void lp_ticker_disable_interrupt(void) void lp_ticker_clear_interrupt(void) { - NVIC_ClearPendingIRQ(RTC_WKUP_IRQn); + NVIC_DisableIRQ(RTC_WKUP_IRQn); } -#endif /* MBED_CONF_TARGET_LOWPOWERTIMER_LPTIM */ +#endif /* MBED_CONF_TARGET_LPTICKER_LPTIM */ -#endif /* DEVICE_LOWPOWERTIMER */ +#endif /* DEVICE_LPTICKER */ diff --git a/targets/TARGET_STM/rtc_api.c b/targets/TARGET_STM/rtc_api.c index 8c091d5835..0b4439fbbb 100644 --- a/targets/TARGET_STM/rtc_api.c +++ b/targets/TARGET_STM/rtc_api.c @@ -1,6 +1,6 @@ /* mbed Microcontroller Library ******************************************************************************* - * Copyright (c) 2017, STMicroelectronics + * Copyright (c) 2018, STMicroelectronics * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,18 +32,10 @@ #include "rtc_api_hal.h" #include "mbed_mktime.h" +#include "mbed_error.h" static RTC_HandleTypeDef RtcHandle; -#if DEVICE_LOWPOWERTIMER && !MBED_CONF_TARGET_LOWPOWERTIMER_LPTIM - -#define GET_TICK_PERIOD(VALUE) (2048 * 1000000 / VALUE) /* 1s / SynchPrediv value * 2^11 (value to get the maximum precision value with no u32 overflow) */ - -static void (*irq_handler)(void); -static void RTC_IRQHandler(void); -static uint32_t lp_TickPeriod_us = GET_TICK_PERIOD(4095); /* default SynchPrediv value = 4095 */ -#endif /* DEVICE_LOWPOWERTIMER && !MBED_CONF_TARGET_LOWPOWERTIMER_LPTIM */ - void rtc_init(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; @@ -53,11 +45,11 @@ void rtc_init(void) __HAL_RCC_PWR_CLK_ENABLE(); HAL_PWR_EnableBkUpAccess(); -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER if ( (rtc_isenabled()) && ((RTC->PRER & RTC_PRER_PREDIV_S) == PREDIV_S_VALUE) ) { -#else /* DEVICE_LOWPOWERTIMER */ +#else /* DEVICE_LPTICKER */ if (rtc_isenabled()) { -#endif /* DEVICE_LOWPOWERTIMER */ +#endif /* DEVICE_LPTICKER */ return; } @@ -118,10 +110,6 @@ void rtc_init(void) RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; #endif /* TARGET_STM32F1 */ -#if DEVICE_LOWPOWERTIMER && !MBED_CONF_TARGET_LOWPOWERTIMER_LPTIM - lp_TickPeriod_us = GET_TICK_PERIOD(RtcHandle.Init.SynchPrediv); -#endif - if (HAL_RTC_Init(&RtcHandle) != HAL_OK) { error("RTC initialization failed"); } @@ -285,20 +273,43 @@ void rtc_synchronize(void) } } -#if DEVICE_LOWPOWERTIMER && !MBED_CONF_TARGET_LOWPOWERTIMER_LPTIM +#if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM + +static void RTC_IRQHandler(void); +static void (*irq_handler)(void); + +volatile uint8_t lp_Fired = 0; +volatile uint32_t LP_continuous_time = 0; +volatile uint32_t LP_last_RTC_time = 0; static void RTC_IRQHandler(void) { /* Update HAL state */ RtcHandle.Instance = RTC; - HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle); - /* In case of registered handler, call it. */ - if (irq_handler) { - irq_handler(); + if(__HAL_RTC_WAKEUPTIMER_GET_IT(&RtcHandle, RTC_IT_WUT)) { + /* Get the status of the Interrupt */ + if((uint32_t)(RTC->CR & RTC_IT_WUT) != (uint32_t)RESET) { + /* Clear the WAKEUPTIMER interrupt pending bit */ + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RtcHandle, RTC_FLAG_WUTF); + + lp_Fired = 0; + if (irq_handler) { + irq_handler(); + } + } } + + if (lp_Fired) { + lp_Fired = 0; + if (irq_handler) { + irq_handler(); + } + } + + __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); } -uint32_t rtc_read_us(void) +uint32_t rtc_read_lp(void) { RTC_TimeTypeDef timeStruct = {0}; RTC_DateTypeDef dateStruct = {0}; @@ -315,52 +326,52 @@ uint32_t rtc_read_us(void) time/date is one second less than as indicated by RTC_TR/RTC_DR. */ timeStruct.Seconds -= 1; } - uint32_t RTCTime = timeStruct.Seconds + timeStruct.Minutes * 60 + timeStruct.Hours * 60 * 60; - uint32_t Time_us = ((timeStruct.SecondFraction - timeStruct.SubSeconds) * lp_TickPeriod_us) >> 11; + uint32_t RTC_time_s = timeStruct.Seconds + timeStruct.Minutes * 60 + timeStruct.Hours * 60 * 60; // Max 0x0001-517F => * 8191 + 8191 = 0x2A2E-AE80 - return (RTCTime * 1000000) + Time_us ; + if (LP_last_RTC_time <= RTC_time_s) { + LP_continuous_time += (RTC_time_s - LP_last_RTC_time); + } else { + LP_continuous_time += (24 * 60 * 60 + RTC_time_s - LP_last_RTC_time); + } + LP_last_RTC_time = RTC_time_s; + + return LP_continuous_time * PREDIV_S_VALUE + timeStruct.SecondFraction - timeStruct.SubSeconds; } -void rtc_set_wake_up_timer(uint32_t delta) +void rtc_set_wake_up_timer(timestamp_t timestamp) { -#define RTC_CLOCK_US (((uint64_t)RTC_CLOCK << 32 ) / 1000000) - uint32_t WakeUpCounter; - uint32_t WakeUpClock; + uint32_t current_lp_time; - /* Ex for Wakeup period resolution with RTCCLK=32768 Hz : - * RTCCLK_DIV2: ~122us < wakeup period < ~4s - * RTCCLK_DIV4: ~244us < wakeup period < ~8s - * RTCCLK_DIV8: ~488us < wakeup period < ~16s - * RTCCLK_DIV16: ~976us < wakeup period < ~32s - * CK_SPRE_16BITS: 1s < wakeup period < (0xFFFF+ 1) x 1 s = 65536 s (18 hours) - * CK_SPRE_17BITS: 18h+1s < wakeup period < (0x1FFFF+ 1) x 1 s = 131072 s (36 hours) - */ - if (delta < (0x10000 * 2 / RTC_CLOCK * 1000000) ) { // (0xFFFF + 1) * RTCCLK_DIV2 / RTC_CLOCK * 1s - WakeUpCounter = (((uint64_t)delta * RTC_CLOCK_US) >> 32) >> 1 ; - WakeUpClock = RTC_WAKEUPCLOCK_RTCCLK_DIV2; - } else if (delta < (0x10000 * 4 / RTC_CLOCK * 1000000) ) { - WakeUpCounter = (((uint64_t)delta * RTC_CLOCK_US) >> 32) >> 2 ; - WakeUpClock = RTC_WAKEUPCLOCK_RTCCLK_DIV4; - } else if (delta < (0x10000 * 8 / RTC_CLOCK * 1000000) ) { - WakeUpCounter = (((uint64_t)delta * RTC_CLOCK_US) >> 32) >> 3 ; - WakeUpClock = RTC_WAKEUPCLOCK_RTCCLK_DIV8; - } else if (delta < (0x10000 * 16 / RTC_CLOCK * 1000000) ) { - WakeUpCounter = (((uint64_t)delta * RTC_CLOCK_US) >> 32) >> 4 ; - WakeUpClock = RTC_WAKEUPCLOCK_RTCCLK_DIV16; + current_lp_time = rtc_read_lp(); + + if (timestamp < current_lp_time) { + WakeUpCounter = 0xFFFFFFFF - current_lp_time + timestamp; } else { - WakeUpCounter = (delta / 1000000) ; - WakeUpClock = RTC_WAKEUPCLOCK_CK_SPRE_16BITS; + WakeUpCounter = timestamp - current_lp_time; } - irq_handler = (void (*)(void))lp_ticker_irq_handler; - NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler); - NVIC_EnableIRQ(RTC_WKUP_IRQn); + if (WakeUpCounter > 0xFFFF) { + WakeUpCounter = 0xFFFF; + } RtcHandle.Instance = RTC; - if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, (uint32_t)WakeUpCounter, WakeUpClock) != HAL_OK) { + if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, WakeUpCounter, RTC_WAKEUPCLOCK_RTCCLK_DIV4) != HAL_OK) { error("rtc_set_wake_up_timer init error\n"); } + + NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler); + irq_handler = (void (*)(void))lp_ticker_irq_handler; + NVIC_EnableIRQ(RTC_WKUP_IRQn); +} + +void rtc_fire_interrupt(void) +{ + lp_Fired = 1; + NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler); + irq_handler = (void (*)(void))lp_ticker_irq_handler; + NVIC_SetPendingIRQ(RTC_WKUP_IRQn); + NVIC_EnableIRQ(RTC_WKUP_IRQn); } void rtc_deactivate_wake_up_timer(void) @@ -369,6 +380,6 @@ void rtc_deactivate_wake_up_timer(void) HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle); } -#endif /* DEVICE_LOWPOWERTIMER && !MBED_CONF_TARGET_LOWPOWERTIMER_LPTIM */ +#endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */ #endif /* DEVICE_RTC */ diff --git a/targets/TARGET_STM/rtc_api_hal.h b/targets/TARGET_STM/rtc_api_hal.h index 32dad0386d..296ea9cec2 100644 --- a/targets/TARGET_STM/rtc_api_hal.h +++ b/targets/TARGET_STM/rtc_api_hal.h @@ -1,6 +1,6 @@ /* mbed Microcontroller Library ******************************************************************************* -* Copyright (c) 2017, STMicroelectronics +* Copyright (c) 2018, STMicroelectronics * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,15 +31,8 @@ #ifndef MBED_RTC_API_HAL_H #define MBED_RTC_API_HAL_H -#include #include "rtc_api.h" -#include "ticker_api.h" #include "lp_ticker_api.h" -#include "us_ticker_api.h" -#include "hal_tick.h" -#include "mbed_critical.h" -#include "mbed_error.h" -#include "mbed_debug.h" #ifdef __cplusplus extern "C" { @@ -51,31 +44,26 @@ extern "C" { #define RTC_CLOCK LSI_VALUE #endif +#if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM /* PREDIV_A : 7-bit asynchronous prescaler */ -/* PREDIV_S : 15-bit synchronous prescaler */ -/* PREDIV_S is set in order to get a 1 Hz clock */ -#if DEVICE_LOWPOWERTIMER && !MBED_CONF_TARGET_LOWPOWERTIMER_LPTIM -/* PREDIV_A is set to a small value to improve the SubSeconds resolution */ -/* with a 32768Hz clock, PREDIV_A=7 gives a precision of 244us */ -#define PREDIV_A_VALUE 7 -#else /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */ -/* PREDIV_A is set to the maximum value to improve the consumption */ -#define PREDIV_A_VALUE 127 -#endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */ +/* PREDIV_A is set to set LPTICKER frequency to RTC_CLOCK/4 */ +#define PREDIV_A_VALUE 3 -#define PREDIV_S_VALUE RTC_CLOCK / (PREDIV_A_VALUE + 1) - 1 - -/** Read RTC time with subsecond precision. +/** Read RTC counter with sub second precision * - * @return Time is microsecond + * @return LP ticker counter */ -uint32_t rtc_read_us(void); +uint32_t rtc_read_lp(void); -/** Program a wake up timer event in delta microseconds. +/** Program a wake up timer event * - * @param delta The time to wait + * @param timestamp: counter to set */ -void rtc_set_wake_up_timer(uint32_t delta); +void rtc_set_wake_up_timer(timestamp_t timestamp); + +/** Call RTC Wake Up IT + */ +void rtc_fire_interrupt(void); /** Disable the wake up timer event. * @@ -83,13 +71,24 @@ void rtc_set_wake_up_timer(uint32_t delta); */ void rtc_deactivate_wake_up_timer(void); +#else /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */ + +/* PREDIV_A : 7-bit asynchronous prescaler */ +/* PREDIV_A is set to the maximum value to improve the consumption */ +#define PREDIV_A_VALUE 127 + +#endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */ + +/* PREDIV_S : 15-bit synchronous prescaler */ +/* PREDIV_S is set in order to get a 1 Hz clock */ +#define PREDIV_S_VALUE RTC_CLOCK / (PREDIV_A_VALUE + 1) - 1 + /** Synchronise the RTC shadow registers. * * Must be called after a deepsleep. */ void rtc_synchronize(void); - #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/sleep.c b/targets/TARGET_STM/sleep.c index 10c3cefde5..09fbd79bc3 100644 --- a/targets/TARGET_STM/sleep.c +++ b/targets/TARGET_STM/sleep.c @@ -1,6 +1,6 @@ /* mbed Microcontroller Library ******************************************************************************* - * Copyright (c) 2016, STMicroelectronics + * Copyright (c) 2018, STMicroelectronics * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,10 +30,14 @@ #if DEVICE_SLEEP #include "sleep_api.h" -#include "rtc_api_hal.h" +#include "us_ticker_api.h" +#include "hal_tick.h" +#include "mbed_critical.h" +#include "mbed_error.h" extern void HAL_SuspendTick(void); extern void HAL_ResumeTick(void); +extern void rtc_synchronize(void); /* Wait loop - assuming tick is 1 us */ static void wait_loop(uint32_t timeout) diff --git a/targets/TARGET_STM/us_ticker_32b.c b/targets/TARGET_STM/us_ticker.c similarity index 78% rename from targets/TARGET_STM/us_ticker_32b.c rename to targets/TARGET_STM/us_ticker.c index b642413641..b6bb210baa 100644 --- a/targets/TARGET_STM/us_ticker_32b.c +++ b/targets/TARGET_STM/us_ticker.c @@ -18,14 +18,27 @@ #include "PeripheralNames.h" #include "hal_tick.h" -// A 32-bit timer is used -#if !TIM_MST_16BIT +#if TIM_MST_16BIT +#define TIMER_TICKER_BIT_WIDTH 16 +#else +#define TIMER_TICKER_BIT_WIDTH 32 +#endif TIM_HandleTypeDef TimMasterHandle; +const ticker_info_t* us_ticker_get_info() +{ + static const ticker_info_t info = { + 1000000, + TIMER_TICKER_BIT_WIDTH + }; + return &info; +} + void us_ticker_init(void) { /* NOTE: assuming that HAL tick has already been initialized! */ + __HAL_TIM_DISABLE_IT(&TimMasterHandle, TIM_IT_CC1); } uint32_t us_ticker_read() @@ -37,18 +50,20 @@ void us_ticker_set_interrupt(timestamp_t timestamp) { // NOTE: This function must be called with interrupts disabled to keep our // timer interrupt setup atomic - - // disable IT while we are handling the correct timestamp - __HAL_TIM_DISABLE_IT(&TimMasterHandle, TIM_IT_CC1); // Set new output compare value __HAL_TIM_SET_COMPARE(&TimMasterHandle, TIM_CHANNEL_1, (uint32_t)timestamp); + // Ensure the compare event starts clear + __HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1); // Enable IT __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC1); } void us_ticker_fire_interrupt(void) { + __HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1); LL_TIM_GenerateEvent_CC1(TimMasterHandle.Instance); + // Enable IT + __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC1); } /* NOTE: must be called with interrupts disabled! */ @@ -63,4 +78,3 @@ void us_ticker_clear_interrupt(void) __HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1); } -#endif // !TIM_MST_16BIT diff --git a/targets/TARGET_STM/us_ticker_16b.c b/targets/TARGET_STM/us_ticker_16b.c deleted file mode 100644 index 1197783cca..0000000000 --- a/targets/TARGET_STM/us_ticker_16b.c +++ /dev/null @@ -1,191 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2016 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 -#include "us_ticker_api.h" -#include "PeripheralNames.h" -#include "hal_tick.h" - -// A 16-bit timer is used -#if TIM_MST_16BIT - -TIM_HandleTypeDef TimMasterHandle; - -volatile uint32_t SlaveCounter = 0; -volatile uint32_t oc_int_part = 0; - -void us_ticker_init(void) -{ - /* NOTE: assuming that HAL tick has already been initialized! */ -} - -uint32_t us_ticker_read() -{ - uint16_t cntH_old, cntH, cntL; - do { - cntH_old = SlaveCounter; - /* SlaveCounter needs to be checked before AND after we read the - * current counter TIM_MST->CNT, in case it wraps around. - * there are 2 possible cases of wrap around - * 1) in case this function is interrupted by timer_irq_handler and - * the SlaveCounter is updated. In that case we will loop again. - * 2) in case this function is called from interrupt context during - * wrap-around condtion. That would prevent/delay the timer_irq_handler - * from being called so we need to locally check the FLAG_UPDATE and - * update the cntH accordingly. The SlaveCounter variable itself will - * be updated in the interrupt handler just after ... - */ - if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_UPDATE) == SET) { - cntH_old += 1; - } - cntL = TIM_MST->CNT; - cntH = SlaveCounter; - if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_UPDATE) == SET) { - cntH += 1; - } - } while(cntH_old != cntH); - // Glue the upper and lower part together to get a 32 bit timer - return (uint32_t)(cntH << 16 | cntL); -} - -void us_ticker_set_interrupt(timestamp_t timestamp) -{ - // NOTE: This function must be called with interrupts disabled to keep our - // timer interrupt setup atomic - - // Set new output compare value - __HAL_TIM_SET_COMPARE(&TimMasterHandle, TIM_CHANNEL_1, timestamp & 0xFFFF); - // Ensure the compare event starts clear - __HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1); - // Enable IT - __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC1); - - /* Set the number of timer wrap-around loops before the actual timestamp - * is reached. If the calculated delta time is more than halfway to the - * next compare event, check to see if a compare event has already been - * set, and if so, add one to the wrap-around count. This is done to - * ensure the correct wrap count is used in the corner cases where the - * 16 bit counter passes the compare value during the process of - * configuring this interrupt. - * - * Assumption: The time to execute this function is less than 32ms - * (otherwise incorrect behaviour could result) - * - * Consider the following corner cases: - * 1) timestamp is 1 us in the future: - * oc_int_part = 0 initially - * oc_int_part left at 0 because ((delta - 1) & 0xFFFF) < 0x8000 - * Compare event should happen in 1 us and us_ticker_irq_handler() - * called - * 2) timestamp is 0x8000 us in the future: - * oc_int_part = 0 initially - * oc_int_part left at 0 because ((delta - 1) & 0xFFFF) < 0x8000 - * There should be no possibility of the CC1 flag being set yet - * (see assumption above). When the compare event does occur in - * 32768 us, us_ticker_irq_handler() will be called - * 3) timestamp is 0x8001 us in the future: - * oc_int_part = 0 initially - * ((delta - 1) & 0xFFFF) >= 0x8000 but there should be no - * possibility of the CC1 flag being set yet (see assumption above), - * so oc_int_part will be left at 0, and when the compare event - * does occur in 32769 us, us_ticker_irq_handler() will be called - * 4) timestamp is 0x10000 us in the future: - * oc_int_part = 0 initially - * ((delta - 1) & 0xFFFF) >= 0x8000 - * There are two subcases: - * a) The timer counter has not incremented past the compare - * value while setting up the interrupt. In this case, the - * CC1 flag will not be set, so oc_int_part will be - * left at 0, and when the compare event occurs in 65536 us, - * us_ticker_irq_handler() will be called - * b) The timer counter has JUST incremented past the compare - * value. In this case, the CC1 flag will be set, so - * oc_int_part will be incremented to 1, and the interrupt will - * occur immediately after this function returns, where - * oc_int_part will decrement to 0 without calling - * us_ticker_irq_handler(). Then about 65536 us later, the - * compare event will occur again, and us_ticker_irq_handler() - * will be called - * 5) timestamp is 0x10001 us in the future: - * oc_int_part = 1 initially - * oc_int_part left at 1 because ((delta - 1) & 0xFFFF) < 0x8000 - * CC1 flag will not be set (see assumption above). In 1 us the - * compare event will cause an interrupt, where oc_int_part will be - * decremented to 0 without calling us_ticker_irq_handler(). Then - * about 65536 us later, the compare event will occur again, and - * us_ticker_irq_handler() will be called - * 6) timestamp is 0x18000 us in the future: - * oc_int_part = 1 initially - * oc_int_part left at 1 because ((delta - 1) & 0xFFFF) < 0x8000 - * There should be no possibility of the CC1 flag being set yet - * (see assumption above). When the compare event does occur in - * 32768 us, oc_int_part will be decremented to 0 without calling - * us_ticker_irq_handler(). Then about 65536 us later, the - * compare event will occur again, and us_ticker_irq_handler() will - * be called - * 7) timestamp is 0x18001 us in the future: - * oc_int_part = 1 initially - * ((delta - 1) & 0xFFFF) >= 0x8000 but there should be no - * possibility of the CC1 flag being set yet (see assumption above), - * so oc_int_part will be left at 1, and when the compare event - * does occur in 32769 us, oc_int_part will be decremented to 0 - * without calling us_ticker_irq_handler(). Then about 65536 us - * later, the compare event will occur again, and - * us_ticker_irq_handler() will be called - * - * delta - 1 is used because the timer compare event happens on the - * counter incrementing to match the compare value, and it won't occur - * immediately when the compare value is set to the current counter - * value. - */ - uint32_t current_time = us_ticker_read(); - uint32_t delta = timestamp - current_time; - /* Note: The case of delta <= 0 is handled in MBED upper layer */ - oc_int_part = (delta - 1) >> 16; - if ( ((delta - 1) & 0xFFFF) >= 0x8000 && - __HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1) == SET ) { - ++oc_int_part; - /* NOTE: Instead of incrementing oc_int_part here, we could clear - * the CC1 flag, but then you'd have to wait to ensure the - * interrupt is knocked down before returning and reenabling - * interrupts. Since this is a rare case, it's not worth it - * to try and optimize it, and it keeps the code simpler and - * safer to just do this increment instead. - */ - } - -} - -void us_ticker_fire_interrupt(void) -{ - /* When firing the event, the number of 16 bits counter wrap-ups (oc_int) - * must be re-initialized */ - oc_int_part = 0; - HAL_TIM_GenerateEvent(&TimMasterHandle, TIM_EVENTSOURCE_CC1); -} - -/* NOTE: must be called with interrupts disabled! */ -void us_ticker_disable_interrupt(void) -{ - __HAL_TIM_DISABLE_IT(&TimMasterHandle, TIM_IT_CC1); -} - -/* NOTE: must be called with interrupts disabled! */ -void us_ticker_clear_interrupt(void) -{ - __HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1); -} - -#endif // TIM_MST_16BIT diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/burtc.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/burtc.c new file mode 100644 index 0000000000..5c86ad9f14 --- /dev/null +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/burtc.c @@ -0,0 +1,106 @@ +/***************************************************************************//** + * @file rtc_burtc.c + ******************************************************************************* + * @section License + * (C) Copyright 2018 Silicon Labs, http://www.silabs.com + ******************************************************************************* + * + * 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 "device.h" +#if DEVICE_RTC + +/* Use BURTC on devices that have it, and don't use the RTCC abstraction */ +#if defined(BURTC_PRESENT) && !defined(RTCC_PRESENT) + +#include "clocking.h" +#include "em_cmu.h" +#include "em_emu.h" +#include "em_burtc.h" +#include "rtc_api.h" + +void rtc_init(void) +{ + /* Only reset & configure the RTC if it has never run before */ + if(BUS_RegBitRead(&BURTC->CTRL, _BURTC_CTRL_RSTEN_SHIFT)) { + EMU_EM4Init_TypeDef em4_init = EMU_EM4INIT_DEFAULT; +#if (LOW_ENERGY_CLOCK_SOURCE == LFXO) + em4_init.osc = emuEM4Osc_LFXO; +#elif (LOW_ENERGY_CLOCK_SOURCE == LFRCO) + em4_init.osc = emuEM4Osc_LFRCO; +#else +#error "Can't use BURTC on mbed with ULFRCO" +#endif + EMU_EM4Init(&em4_init); + + BURTC_Init_TypeDef burtc_init = BURTC_INIT_DEFAULT; + burtc_init.mode = burtcModeEM4; +#if (LOW_ENERGY_CLOCK_SOURCE == LFXO) + burtc_init.clkSel = burtcClkSelLFXO; +#elif (LOW_ENERGY_CLOCK_SOURCE == LFRCO) + burtc_init.clkSel = burtcClkSelLFRCO; +#else +#error "Can't use BURTC on mbed with ULFRCO" +#endif + burtc_init.clkDiv = burtcClkDiv_128; + burtc_init.lowPowerMode = burtcLPEnable; + + BURTC_Reset(); + BUS_RegBitWrite(&RMU->CTRL, _RMU_CTRL_BURSTEN_SHIFT, 0); + BURTC_Init(&burtc_init); + BURTC_RetRegSet(0, 0); + BURTC_RetRegSet(1, 0); + } +} + +void rtc_free(void) +{ + /* Nothing to release here */ +} + +int rtc_isenabled(void) +{ + return (BUS_RegBitRead(&BURTC->CTRL, _BURTC_CTRL_RSTEN_SHIFT) == 0); +} + +time_t rtc_read(void) +{ + uint32_t ts = 0; + uint32_t ts2 = 1; + do { + if (BURTC->IF & BURTC_IF_OF) { + BURTC_RetRegSet(1, BURTC_RetRegGet(1)+1); + BURTC->IFC = BURTC_IFC_OF; + } + + ts = ts2; + ts2 = (BURTC_CounterGet() >> 8) + BURTC_RetRegGet(0) + (BURTC_RetRegGet(1) << 16); + } while (ts != ts2); + return ts2; +} + +void rtc_write(time_t t) +{ + BURTC_RetRegSet(0, t - (BURTC_CounterGet() >> 8)); + BURTC_RetRegSet(1, 0); + if (BURTC->IF & BURTC_IF_OF) { + BURTC->IFC = BURTC_IFC_OF; + } +} + +#endif /* BURTC_PRESENT && !RTCC_PRESENT */ +#endif /* DEVICE_RTC */ \ No newline at end of file diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/common/clocking.h b/targets/TARGET_Silicon_Labs/TARGET_EFM32/common/clocking.h index b9ad628edc..4eac51774a 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/common/clocking.h +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/common/clocking.h @@ -106,12 +106,12 @@ #endif /* Adjust this to change speed of RTC and LP ticker ticks */ -#define RTC_CLOCKDIV cmuClkDiv_8 +#define RTC_CLOCKDIV cmuClkDiv_1 /* Adjust this to match RTC_CLOCKDIV as integer value */ -#define RTC_CLOCKDIV_INT 8U +#define RTC_CLOCKDIV_INT 1U /* Adjust this to match RTC_CLOCKDIV as shift for 1 second worth of ticks. * E.g. with 32768 Hz crystal and CLOCKDIV of 8, 1 second is 4096 ticks. * 4096 equals 1 << 12, so RTC_FREQ_SHIFT needs to be 12. */ -#define RTC_FREQ_SHIFT 12U +#define RTC_FREQ_SHIFT 15U #endif diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/common/mbed_overrides.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/common/mbed_overrides.c index bc8f479a6c..c39707e7f0 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/common/mbed_overrides.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/common/mbed_overrides.c @@ -117,6 +117,11 @@ void mbed_sdk_init() # error "Low energy clock selection not valid" #endif +#if defined(RTCC_PRESENT) + /* Turn RTCC clock gate back on to keep RTC time correct */ + CMU_ClockEnable(cmuClock_RTCC, true); +#endif + #if defined(EFM_BC_EN) /* Enable BC line driver to avoid garbage on CDC port */ gpio_init_out_ex(&bc_enable, EFM_BC_EN, 1); diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/lp_ticker.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/lp_ticker.c index 9c08b32090..ca06c916a0 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/lp_ticker.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/lp_ticker.c @@ -23,7 +23,7 @@ #include "device.h" #include "clocking.h" -#if DEVICE_LOWPOWERTIMER +#if DEVICE_LPTICKER /******************************************************************************* * The Silicon Labs lp_ticker implementation is mapped on top of an extended RTC @@ -32,6 +32,17 @@ * for the low power timer, which should be good enough for a low power use * case. * + * Mapping of mbed APIs to Silicon Labs peripherals: + * ---: Does not meet mbed API requirements + * X : Implemented to provide mbed API functionality + * + * -------------------------------------------- + * | ------------- | RTCC | BURTC | RTC | TIMER | + * | rtc_api | X | X | --- | ----- | + * | lp_ticker_api | X | | X | ----- | + * | us_ticker_api | --- | ----- | --- | X | + * -------------------------------------------- + * * On Silicon Labs devices, the lowest width RTC implementation has a 24-bit * counter, which gets extended with a further 32-bit software counter. This * gives 56 bits of actual width, which with the default speed maps to @@ -40,91 +51,115 @@ * (At max speed the wraparound is at 69730 years, which is unlikely as well) ******************************************************************************/ -#include "rtc_api.h" -#include "rtc_api_HAL.h" +#if defined(RTC_PRESENT) +#include "em_rtc.h" +#include "em_cmu.h" #include "lp_ticker_api.h" #include "mbed_critical.h" -static int rtc_reserved = 0; +#if RTC_CLOCKDIV_INT > 16 +#error invalid prescaler value RTC_CLOCKDIV_INT, since LP ticker resolution will exceed 1ms. +#endif + +#define RTC_BITS (24U) +#define RTC_MAX_VALUE (0xFFFFFFUL) + +static bool rtc_inited = false; + +const ticker_info_t* lp_ticker_get_info(void) +{ + static const ticker_info_t rtc_info = { + LOW_ENERGY_CLOCK_FREQUENCY, + RTC_BITS + }; + return &rtc_info; +} + +void RTC_IRQHandler(void) +{ + uint32_t flags; + flags = RTC_IntGet(); + if ((flags & RTC_IF_COMP0) && rtc_inited) { + RTC_IntClear(RTC_IF_COMP0); + lp_ticker_irq_handler(); + } +} void lp_ticker_init() { - if(!rtc_reserved) { - core_util_critical_section_enter(); - rtc_init_real(RTC_INIT_LPTIMER); - rtc_set_comp0_handler((uint32_t)lp_ticker_irq_handler); - rtc_reserved = 1; - core_util_critical_section_exit(); + core_util_critical_section_enter(); + if (!rtc_inited) { + CMU_ClockEnable(cmuClock_RTC, true); + + /* Initialize RTC */ + RTC_Init_TypeDef init = RTC_INIT_DEFAULT; + init.enable = 1; + /* Don't use compare register 0 as top value */ + init.comp0Top = 0; + + /* Initialize */ + RTC_Init(&init); + RTC_CounterSet(20); + + /* Enable Interrupt from RTC */ + RTC_IntDisable(RTC_IF_COMP0); + RTC_IntClear(RTC_IF_COMP0); + NVIC_SetVector(RTC_IRQn, (uint32_t)RTC_IRQHandler); + NVIC_EnableIRQ(RTC_IRQn); + + rtc_inited = true; + } else { + /* Cancel current interrupt by virtue of calling init again */ + RTC_IntDisable(RTC_IF_COMP0); + RTC_IntClear(RTC_IF_COMP0); } + core_util_critical_section_exit(); } void lp_ticker_free() { - if(rtc_reserved) { - core_util_critical_section_enter(); - rtc_free_real(RTC_INIT_LPTIMER); - rtc_reserved = 0; - core_util_critical_section_exit(); + /* Disable the RTC if it was inited and is no longer in use by anyone. */ + if (rtc_inited) { + NVIC_DisableIRQ(RTC_IRQn); + RTC_Reset(); + CMU_ClockEnable(cmuClock_RTC, false); + rtc_inited = false; } + RTC_FreezeEnable(false); } void lp_ticker_set_interrupt(timestamp_t timestamp) { - uint64_t rtc_compare_value; - uint64_t current_ticks = rtc_get_full(); - timestamp_t current_time = lp_ticker_read(); - - /* calculate offset value */ - timestamp_t offset = timestamp - current_time; - - /* If the requested timestamp is too far in the future, we might not be able - * to set the interrupt accurately due to potentially having ticked between - * calculating the timestamp to set and us calculating the offset. */ - if(offset > 0xFFFF0000) offset = 100; - - /* map offset to RTC value */ - // ticks = offset * RTC frequency div 1000000 - rtc_compare_value = ((uint64_t)offset * (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) / 1000000; - - /* If RTC offset is less then 2 RTC ticks, the interrupt won't fire */ - if(rtc_compare_value < 2) { - rtc_compare_value = 2; - } - - rtc_compare_value += current_ticks; - - rtc_set_comp0_value(rtc_compare_value, true); + RTC_IntDisable(RTC_IF_COMP0); + RTC_IntClear(RTC_IF_COMP0); + RTC_FreezeEnable(true); + RTC_CompareSet(0, (uint32_t) (timestamp & RTC_MAX_VALUE)); + RTC_FreezeEnable(false); + RTC_IntEnable(RTC_IF_COMP0); } -inline void lp_ticker_fire_interrupt(void) +void lp_ticker_fire_interrupt(void) { - rtc_force_comp0(); + RTC_IntEnable(RTC_IF_COMP0); + RTC_IntSet(RTC_IF_COMP0); } -inline void lp_ticker_disable_interrupt() +void lp_ticker_disable_interrupt() { - rtc_enable_comp0(false); + RTC_IntDisable(RTC_IF_COMP0); } -inline void lp_ticker_clear_interrupt() +void lp_ticker_clear_interrupt() { - /* No need to clear interrupt flag, since that already happens at RTC level */ + RTC_IntClear(RTC_IF_COMP0); } timestamp_t lp_ticker_read() { - lp_ticker_init(); - - uint64_t ticks_temp; - uint64_t ticks = rtc_get_full(); - - /* ticks = counter tick value - * timestamp = value in microseconds - * timestamp = ticks * 1.000.000 / RTC frequency - */ - - ticks_temp = (ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT); - return (timestamp_t) (ticks_temp & 0xFFFFFFFF); + return (timestamp_t) RTC_CounterGet(); } -#endif +#elif defined(RTCC_PRESENT) +/* lp_ticker api is implemented in rtc_rtcc.c */ +#endif /* RTC_PRESENT */ +#endif /* DEVICE_LPTICKER */ diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/rtc_api.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/rtc_api.c deleted file mode 100644 index 81e64cbc00..0000000000 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/rtc_api.c +++ /dev/null @@ -1,345 +0,0 @@ -/***************************************************************************//** - * @file rtc_api.c - ******************************************************************************* - * @section License - * (C) Copyright 2015 Silicon Labs, http://www.silabs.com - ******************************************************************************* - * - * 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 "device.h" -#if DEVICE_RTC - -#include "rtc_api.h" -#include "rtc_api_HAL.h" -#include "em_cmu.h" -#include "sleep_api.h" - -#if (defined RTC_COUNT) && (RTC_COUNT > 0) -#include "em_rtc.h" -#endif - -#if (defined RTCC_COUNT) && (RTCC_COUNT > 0) -#include "em_rtcc.h" -#endif - -static bool rtc_inited = false; -static bool rtc_cancelled = false; -static time_t time_base = 0; -static uint32_t useflags = 0; -static uint32_t time_extend = 0; -static uint32_t extended_comp0 = 0; - -static void (*comp0_handler)(void) = NULL; - -#ifndef RTCC_PRESENT -/* Using RTC API */ - -#if RTC_CLOCKDIV_INT > 16 -#error invalid prescaler value RTC_CLOCKDIV_INT, since LP ticker resolution will exceed 1ms. -#endif - -void RTC_IRQHandler(void) -{ - uint32_t flags; - flags = RTC_IntGet(); - if (flags & RTC_IF_OF) { - RTC_IntClear(RTC_IF_OF); - /* RTC has overflowed (24 bits). Use time_extend as software counter for 32 more bits. */ - time_extend += 1; - } - if (flags & RTC_IF_COMP0) { - RTC_IntClear(RTC_IF_COMP0); - if (comp0_handler != NULL && ((time_extend == extended_comp0) || (rtc_cancelled))) { - rtc_cancelled = false; - comp0_handler(); - } - } -} - -uint64_t rtc_get_full(void) -{ - uint64_t ticks = 0; - - do - { - ticks = RTC_CounterGet(); - - if (RTC_IntGet() & RTC_IF_OF) { - RTC_IntClear(RTC_IF_OF); - /* RTC has overflowed in a critical section, so handle the overflow here */ - time_extend += 1; - } - - ticks += (uint64_t)time_extend << RTC_BITS; - } - while ( (ticks & RTC_MAX_VALUE) != RTC_CounterGet() ); - - return ticks; -} - -void rtc_init_real(uint32_t flags) -{ - useflags |= flags; - - if (!rtc_inited) { - CMU_ClockEnable(cmuClock_RTC, true); - - /* Enable clock to the interface of the low energy modules */ - CMU_ClockEnable(cmuClock_CORELE, true); - - /* Scale clock to save power */ - CMU_ClockDivSet(cmuClock_RTC, RTC_CLOCKDIV); - - /* Initialize RTC */ - RTC_Init_TypeDef init = RTC_INIT_DEFAULT; - init.enable = 1; - /* Don't use compare register 0 as top value */ - init.comp0Top = 0; - - /* Enable Interrupt from RTC */ - RTC_IntEnable(RTC_IEN_OF); - NVIC_SetVector(RTC_IRQn, (uint32_t)RTC_IRQHandler); - NVIC_EnableIRQ(RTC_IRQn); - - /* Initialize */ - RTC_Init(&init); - - rtc_inited = true; - } -} - -void rtc_free(void) -{ - rtc_free_real(RTC_INIT_RTC); -} - -void rtc_free_real(uint32_t flags) -{ - /* Clear use flag */ - useflags &= ~flags; - - /* Disable the RTC if it was inited and is no longer in use by anyone. */ - if (rtc_inited && (useflags == 0)) { - NVIC_DisableIRQ(RTC_IRQn); - RTC_Reset(); - CMU_ClockEnable(cmuClock_RTC, false); - rtc_inited = false; - } -} - -void rtc_enable_comp0(bool enable) -{ - RTC_FreezeEnable(true); - if (!enable) { - RTC_IntDisable(RTC_IF_COMP0); - } else { - RTC_IntEnable(RTC_IF_COMP0); - } - RTC_FreezeEnable(false); -} - -void rtc_set_comp0_value(uint64_t value, bool enable) -{ - rtc_enable_comp0(false); - - /* Set callback */ - RTC_FreezeEnable(true); - extended_comp0 = (uint32_t) (value >> RTC_BITS); - RTC_CompareSet(0, (uint32_t) (value & RTC_MAX_VALUE)); - RTC_FreezeEnable(false); - - rtc_enable_comp0(enable); -} - -void rtc_force_comp0(void) -{ - rtc_cancelled = true; - RTC_IntSet(RTC_IFS_COMP0); -} - -#else -/* Using RTCC API */ - -void RTCC_IRQHandler(void) -{ - uint32_t flags; - flags = RTCC_IntGet(); - - if (flags & RTCC_IF_OF) { - RTCC_IntClear(RTCC_IF_OF); - /* RTC has overflowed (32 bits). Use time_extend as software counter for 32 more bits. */ - time_extend += 1; - } - - if (flags & RTCC_IF_CC0) { - RTCC_IntClear(RTCC_IF_CC0); - if (comp0_handler != NULL && ((time_extend == extended_comp0) || (rtc_cancelled))) { - comp0_handler(); - } - } -} - -uint64_t rtc_get_full(void) -{ - uint64_t ticks = 0; - - do - { - ticks = RTCC_CounterGet(); - - if (RTCC_IntGet() & RTCC_IF_OF) { - RTCC_IntClear(RTCC_IF_OF); - /* RTCC has overflowed in critical section, so handle the rollover here */ - time_extend += 1; - } - - ticks += (uint64_t)time_extend << RTC_BITS; - } - while ( (ticks & RTC_MAX_VALUE) != RTCC_CounterGet() ); - - return ticks; -} - -void rtc_init_real(uint32_t flags) -{ - useflags |= flags; - - if (!rtc_inited) { - CMU_ClockEnable(cmuClock_RTCC, true); - - /* Enable clock to the interface of the low energy modules */ - CMU_ClockEnable(cmuClock_CORELE, true); - - /* Initialize RTC */ - RTCC_Init_TypeDef init = RTCC_INIT_DEFAULT; - init.enable = 1; - init.precntWrapOnCCV0 = false; - init.cntWrapOnCCV1 = false; -#if RTC_CLOCKDIV_INT == 1 - init.presc = rtccCntPresc_1; -#elif RTC_CLOCKDIV_INT == 2 - init.presc = rtccCntPresc_2; -#elif RTC_CLOCKDIV_INT == 4 - init.presc = rtccCntPresc_4; -#elif RTC_CLOCKDIV_INT == 8 - init.presc = rtccCntPresc_8; -#elif RTC_CLOCKDIV_INT == 16 - init.presc = rtccCntPresc_16; -#else -#error invalid prescaler value RTC_CLOCKDIV_INT, since LP ticker resolution will exceed 1ms. -#endif - - /* Enable Interrupt from RTC */ - RTCC_IntEnable(RTCC_IEN_OF); - NVIC_SetVector(RTCC_IRQn, (uint32_t)RTCC_IRQHandler); - NVIC_EnableIRQ(RTCC_IRQn); - - /* Initialize */ - RTCC_Init(&init); - rtc_inited = true; - } -} - -void rtc_free(void) -{ - rtc_free_real(RTC_INIT_RTC); -} - -void rtc_free_real(uint32_t flags) -{ - /* Clear use flag */ - useflags &= ~flags; - - /* Disable the RTC if it was inited and is no longer in use by anyone. */ - if (rtc_inited && (useflags == 0)) { - NVIC_DisableIRQ(RTCC_IRQn); - RTCC_Reset(); - CMU_ClockEnable(cmuClock_RTCC, false); - rtc_inited = false; - } -} - -void rtc_enable_comp0(bool enable) -{ - if(!enable) { - RTCC_IntDisable(RTCC_IF_CC0); - } else { - RTCC_IntEnable(RTCC_IF_CC0); - } -} - -void rtc_set_comp0_value(uint64_t value, bool enable) -{ - rtc_enable_comp0(false); - - /* init channel */ - RTCC_CCChConf_TypeDef ccchConf = RTCC_CH_INIT_COMPARE_DEFAULT; - RTCC_ChannelInit(0,&ccchConf); - /* Set callback */ - extended_comp0 = (uint32_t) (value >> RTC_BITS); - RTCC_ChannelCCVSet(0, (uint32_t) (value & RTC_MAX_VALUE)); - - rtc_enable_comp0(enable); -} - -void rtc_force_comp0(void) -{ - rtc_cancelled = true; - RTCC_IntSet(RTCC_IFS_CC0); -} - -#endif /* RTCC_COUNT */ - -void rtc_set_comp0_handler(uint32_t handler) -{ - comp0_handler = (void (*)(void)) handler; -} - -void rtc_init(void) -{ - /* Register that the RTC is used for timekeeping. */ - rtc_init_real(RTC_INIT_RTC); -} - -int rtc_isenabled(void) -{ - return rtc_inited; -} - -time_t rtc_read(void) -{ - return (time_t) (rtc_get_full() >> RTC_FREQ_SHIFT) + time_base; -} - -time_t rtc_read_uncompensated(void) -{ - return (time_t) (rtc_get_full() >> RTC_FREQ_SHIFT); -} - -void rtc_write(time_t t) -{ - /* We have to check that the RTC did not tick while doing this. */ - /* If the RTC ticks we just redo this. */ - uint32_t time; - do { - time = rtc_read_uncompensated(); - time_base = t - time; - } while (time != (uint32_t)rtc_read_uncompensated()); -} - -#endif diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/rtc_api_HAL.h b/targets/TARGET_Silicon_Labs/TARGET_EFM32/rtc_api_HAL.h deleted file mode 100644 index 702c42ccd7..0000000000 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/rtc_api_HAL.h +++ /dev/null @@ -1,61 +0,0 @@ -/***************************************************************************//** - * @file rtc_api_HAL.h - ******************************************************************************* - * @section License - * (C) Copyright 2015 Silicon Labs, http://www.silabs.com - ******************************************************************************* - * - * 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. - * - ******************************************************************************/ - -#ifndef MBED_RTC_API_HAL_H -#define MBED_RTC_API_HAL_H - -#include -#include "rtc_api.h" -#include "clocking.h" - -#define RTC_INIT_LPTIMER (1U << 1) -#define RTC_INIT_RTC (1U << 0) - -#if defined(RTCC_PRESENT) -#define RTC_BITS (32U) -#define RTC_MAX_VALUE (0xFFFFFFFFUL) -#elif defined(RTC_PRESENT) -#define RTC_BITS (24U) -#define RTC_MAX_VALUE (0xFFFFFFUL) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Purpose of this file: extend rtc_api.h to include EFM-specific stuff*/ -void rtc_set_comp0_handler(uint32_t handler); -void rtc_enable_comp0(bool enable); -void rtc_set_comp0_value(uint64_t value, bool enable); -void rtc_force_comp0(void); - -uint64_t rtc_get_full(void); - -void rtc_init_real(uint32_t flags); -void rtc_free_real(uint32_t flags); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/rtcc.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/rtcc.c new file mode 100644 index 0000000000..91fcda9852 --- /dev/null +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/rtcc.c @@ -0,0 +1,173 @@ +/***************************************************************************//** + * @file rtc_rtcc.c + ******************************************************************************* + * @section License + * (C) Copyright 2018 Silicon Labs, http://www.silabs.com + ******************************************************************************* + * + * 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 "device.h" +#if DEVICE_RTC || DEVICE_LPTICKER + +/* Use RTCC on devices that have it */ +#if defined(RTCC_PRESENT) + +#include "em_cmu.h" +#include "em_rmu.h" +#include "em_rtcc.h" +#include "rtc_api.h" +#include "lp_ticker_api.h" +#include "clocking.h" + +static bool lptick_inited = false; +static uint32_t lptick_offset = 0; + +void rtc_init(void) +{ + if (BUS_RegBitRead((&RTCC->CTRL), _RTCC_CTRL_ENABLE_SHIFT) != 0) { + /* RTCC already up & running */ + return; + } + + /* Make sure RTCC doesn't get reset (mbed specification) */ + RMU_ResetControl(rmuResetWdog, rmuResetModeLimited); + RMU_ResetControl(rmuResetCoreLockup, rmuResetModeLimited); + RMU_ResetControl(rmuResetSys, rmuResetModeLimited); + RMU_ResetControl(rmuResetPin, rmuResetModeFull); + + /* Set up the RTCC and let it run, Forrest, run */ + RTCC_Reset(); + RTCC_Init_TypeDef rtcc_init = RTCC_INIT_DEFAULT; + rtcc_init.presc = rtccCntPresc_32768; + RTCC_Init(&rtcc_init); + RTCC_Enable(true); +} + +void rtc_free(void) +{ + /* Can't turn off any clock gates here since other parts of the + * system might be using the CORELE clock. */ +} + +int rtc_isenabled(void) +{ + return BUS_RegBitRead((&RTCC->CTRL), _RTCC_CTRL_ENABLE_SHIFT); +} + +time_t rtc_read(void) +{ + return RTCC_CounterGet(); +} + +void rtc_write(time_t t) +{ + core_util_critical_section_enter(); + uint32_t diff = t - RTCC_CounterGet(); + lptick_offset += diff; + + if(RTCC_IntGetEnabled() & RTCC_IF_CC0) { + RTCC->CC[0].CCV += diff << 15; + } + + RTCC_CounterSet(t); + core_util_critical_section_exit(); +} + +/************************* LP_TICKER **************************/ +const ticker_info_t* lp_ticker_get_info(void) +{ + static const ticker_info_t rtc_info = { + LOW_ENERGY_CLOCK_FREQUENCY, + 32 + }; + return &rtc_info; +} + +void RTCC_IRQHandler(void) +{ + uint32_t flags; + flags = RTCC_IntGet(); + if (flags & RTCC_IF_CC0) { + lp_ticker_irq_handler(); + } +} + +void lp_ticker_init() +{ + if (!lptick_inited) { + rtc_init(); + core_util_critical_section_enter(); + lptick_offset = RTCC_CounterGet(); + core_util_critical_section_exit(); + RTCC_CCChConf_TypeDef lp_chan_init = RTCC_CH_INIT_COMPARE_DEFAULT; + lp_chan_init.compBase = rtccCompBasePreCnt; + lp_chan_init.compMask = 0; + RTCC_ChannelInit(0, &lp_chan_init); + lptick_inited = true; + + /* Enable Interrupt from RTCC in NVIC, but don't start generating them */ + RTCC_IntDisable(RTCC_IF_CC0); + RTCC_IntClear(RTCC_IF_CC0); + NVIC_EnableIRQ(RTCC_IRQn); + } else { + RTCC_IntDisable(RTCC_IF_CC0); + RTCC_IntClear(RTCC_IF_CC0); + } +} + +void lp_ticker_free() +{ + if (lptick_inited) { + lp_ticker_disable_interrupt(); + lp_ticker_clear_interrupt(); + lptick_inited = false; + } +} + +void lp_ticker_set_interrupt(timestamp_t timestamp) +{ + RTCC_ChannelCCVSet(0, timestamp + (lptick_offset << 15)); + RTCC_IntEnable(RTCC_IF_CC0); +} + +void lp_ticker_fire_interrupt(void) +{ + RTCC_IntEnable(RTCC_IF_CC0); + RTCC_IntSet(RTCC_IF_CC0); +} + +void lp_ticker_disable_interrupt() +{ + RTCC_IntDisable(RTCC_IF_CC0); +} + +void lp_ticker_clear_interrupt() +{ + RTCC_IntClear(RTCC_IF_CC0); +} + +timestamp_t lp_ticker_read() +{ + core_util_critical_section_enter(); + uint32_t ticks = RTCC_CombinedCounterGet() - (lptick_offset << 15); + core_util_critical_section_exit(); + + return (timestamp_t) (ticks); +} +#endif /* RTCC_PRESENT */ +#endif /* DEVICE_RTC */ \ No newline at end of file diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/us_ticker.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/us_ticker.c index 74ac081768..ab38dd2fac 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/us_ticker.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/us_ticker.c @@ -29,80 +29,42 @@ #include "em_timer.h" #include "clocking.h" -/** - * Timer functions for microsecond ticker. - * mbed expects a 32-bit timer. Since the EFM32 only has 16-bit timers, - * the upper 16 bits are implemented in software. - */ +#define TICKER_FREQUENCY ((REFERENCE_FREQUENCY > 24000000) ? REFERENCE_FREQUENCY / 16 : REFERENCE_FREQUENCY / 8) -static uint8_t us_ticker_inited = 0; // Is ticker initialized yet - -static volatile uint32_t ticker_cnt = 0; // Internal overflow count, used to extend internal 16-bit counter to (MHz * 32-bit) -static volatile uint32_t ticker_int_cnt = 0; // Amount of overflows until user interrupt -static volatile uint32_t ticker_freq_khz = 0; // Frequency of timer in MHz -static volatile uint32_t ticker_top_ms = 0; // Amount of ms corresponding to the top value of the timer -static volatile uint32_t soft_timer_top = 0; // When to wrap the software counter - -void us_ticker_irq_handler_internal(void) +const ticker_info_t* us_ticker_get_info(void) { - /* Handle timer overflow */ - if (TIMER_IntGet(US_TICKER_TIMER) & TIMER_IF_OF) { - ticker_cnt++; - - /* Wrap ticker_cnt when we've gone over 32-bit us value */ - if (ticker_cnt >= soft_timer_top) { - ticker_cnt = 0; - } - - TIMER_IntClear(US_TICKER_TIMER, TIMER_IF_OF); - } - - /* Check for user interrupt expiration */ - if (TIMER_IntGet(US_TICKER_TIMER) & TIMER_IF_CC0) { - if (ticker_int_cnt > 0) { - ticker_int_cnt--; - TIMER_IntClear(US_TICKER_TIMER, TIMER_IF_CC0); - } else { - us_ticker_irq_handler(); - } - } + static const ticker_info_t info = { + TICKER_FREQUENCY, + 16 + }; + return &info; } +static bool us_ticker_inited = false; // Is ticker initialized yet + void us_ticker_init(void) { if (us_ticker_inited) { + /* calling init again should cancel current interrupt */ + us_ticker_disable_interrupt(); return; } - us_ticker_inited = 1; + us_ticker_inited = true; /* Enable clock for TIMERs */ CMU_ClockEnable(US_TICKER_TIMER_CLOCK, true); + if (REFERENCE_FREQUENCY > 24000000) { + US_TICKER_TIMER->CTRL = (US_TICKER_TIMER->CTRL & ~_TIMER_CTRL_PRESC_MASK) | (4 << _TIMER_CTRL_PRESC_SHIFT); + } else { + US_TICKER_TIMER->CTRL = (US_TICKER_TIMER->CTRL & ~_TIMER_CTRL_PRESC_MASK) | (3 << _TIMER_CTRL_PRESC_SHIFT); + } + /* Clear TIMER counter value */ TIMER_CounterSet(US_TICKER_TIMER, 0); - /* Get frequency of clock in kHz for scaling ticks to microseconds */ - ticker_freq_khz = (REFERENCE_FREQUENCY / 1000); - MBED_ASSERT(ticker_freq_khz > 0); - - /* - * Calculate maximum prescaler that gives at least 1 MHz frequency, giving us 1us resolution. - * Limit prescaling to maximum prescaler value, which is 10 (DIV1024). - */ - uint32_t prescaler = 0; - while((ticker_freq_khz >= 2000) && prescaler <= 10) { - ticker_freq_khz = ticker_freq_khz >> 1; - prescaler++; - } - - /* Set prescaler */ - US_TICKER_TIMER->CTRL = (US_TICKER_TIMER->CTRL & ~_TIMER_CTRL_PRESC_MASK) | (prescaler << _TIMER_CTRL_PRESC_SHIFT); - - /* calculate top value.*/ - ticker_top_ms = (uint32_t) 0x10000 / ticker_freq_khz; - - /* calculate software timer overflow */ - soft_timer_top = ((0xFFFFFFFFUL / 1000UL) / ticker_top_ms) + 1; + /* Start TIMER */ + TIMER_Enable(US_TICKER_TIMER, true); /* Select Compare Channel parameters */ TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT; @@ -112,98 +74,47 @@ void us_ticker_init(void) TIMER_InitCC(US_TICKER_TIMER, 0, &timerCCInit); /* Enable interrupt vector in NVIC */ - TIMER_IntEnable(US_TICKER_TIMER, TIMER_IEN_OF); - NVIC_SetVector(US_TICKER_TIMER_IRQ, (uint32_t) us_ticker_irq_handler_internal); + TIMER_IntClear(US_TICKER_TIMER, TIMER_IEN_CC0); + NVIC_SetVector(US_TICKER_TIMER_IRQ, (uint32_t) us_ticker_irq_handler); NVIC_EnableIRQ(US_TICKER_TIMER_IRQ); +} - /* Set top value */ - TIMER_TopSet(US_TICKER_TIMER, (ticker_top_ms * ticker_freq_khz) - 1); +void us_ticker_free(void) +{ + if (us_ticker_inited) { + us_ticker_disable_interrupt(); + NVIC_DisableIRQ(US_TICKER_TIMER_IRQ); - /* Start TIMER */ - TIMER_Enable(US_TICKER_TIMER, true); + TIMER_Enable(US_TICKER_TIMER, false); + + CMU_ClockEnable(US_TICKER_TIMER_CLOCK, false); + + us_ticker_inited = false; + } } uint32_t us_ticker_read() { - uint32_t countH_old, countH; - uint32_t countL; - if (!us_ticker_inited) { us_ticker_init(); } - /* Avoid jumping in time by reading high bits twice */ - do { - countH_old = ticker_cnt; - if (TIMER_IntGet(US_TICKER_TIMER) & TIMER_IF_OF) { - countH_old++; - } - countL = US_TICKER_TIMER->CNT; - countH = ticker_cnt; - if (TIMER_IntGet(US_TICKER_TIMER) & TIMER_IF_OF) { - countH++; - } - } while (countH_old != countH); - - /* Timer count value needs to be div'ed by the frequency to get to 1MHz ticks. - * For the software-extended part, the amount of us in one overflow is constant. - */ - return ((countL * 1000UL) / ticker_freq_khz) + (countH * ticker_top_ms * 1000); + return US_TICKER_TIMER->CNT; } void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t goal = timestamp; - uint32_t trigger; - TIMER_IntDisable(US_TICKER_TIMER, TIMER_IEN_CC0); - /* convert us delta value back to timer ticks */ - trigger = us_ticker_read(); - if (trigger < goal) { - goal -= trigger; - } else { - goal = (0xFFFFFFFFUL - (trigger - goal)); - } - trigger = US_TICKER_TIMER->CNT; - - /* Catch "Going back in time" */ - if(goal < 10 || - goal >= 0xFFFFFF00UL) { - TIMER_IntClear(US_TICKER_TIMER, TIMER_IFC_CC0); - TIMER_CompareSet(US_TICKER_TIMER, 0, (US_TICKER_TIMER->CNT + 3 >= US_TICKER_TIMER->TOP ? 3 : US_TICKER_TIMER->CNT + 3)); - TIMER_IntEnable(US_TICKER_TIMER, TIMER_IEN_CC0); - return; - } - - uint32_t timer_top = TIMER_TopGet(US_TICKER_TIMER); - uint32_t top_us = 1000 * ticker_top_ms; - - /* Amount of times we expect to overflow: us offset / us period of timer */ - ticker_int_cnt = goal / top_us; - - /* Leftover microseconds need to be converted to timer timebase */ - trigger += (((goal % top_us) * ticker_freq_khz) / 1000); - - /* Cap compare value to timer top */ - if (trigger >= timer_top) { - trigger -= timer_top; - } - - /* Set compare channel 0 to (current position + lower 16 bits of target). - * When lower 16 bits match, run complete cycles with ticker_int_rem as trigger value - * for ticker_int_cnt times. */ TIMER_IntClear(US_TICKER_TIMER, TIMER_IEN_CC0); - TIMER_CompareSet(US_TICKER_TIMER, 0, trigger); + TIMER_CompareSet(US_TICKER_TIMER, 0, timestamp); TIMER_IntEnable(US_TICKER_TIMER, TIMER_IEN_CC0); } void us_ticker_fire_interrupt(void) { - ticker_int_cnt = 0; - TIMER_IntSet(US_TICKER_TIMER, TIMER_IF_CC0); NVIC_SetPendingIRQ(US_TICKER_TIMER_IRQ); } diff --git a/targets/targets.json b/targets/targets.json index 552a23eff9..e8e83d7568 100755 --- a/targets/targets.json +++ b/targets/targets.json @@ -210,7 +210,7 @@ "supported_toolchains": ["ARM", "uARM", "GCC_CR", "GCC_ARM", "IAR"], "inherits": ["LPCTarget"], "detect_code": ["1168"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PWMOUT", "SERIAL", "SLEEP", "SPI"], "default_lib": "small", "release_versions": ["2"], "device_name": "LPC11U68JBD100" @@ -232,7 +232,7 @@ "supported_toolchains": ["uARM", "GCC_CR", "GCC_ARM", "IAR"], "inherits": ["LPCTarget"], "detect_code": ["1549"], - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "INTERRUPTIN", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SPI", "SPISLAVE"], + "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "INTERRUPTIN", "PWMOUT", "SERIAL", "SERIAL_FC", "SPI", "SPISLAVE"], "default_lib": "small", "release_versions": ["2"], "device_name": "LPC1549JBD64" @@ -243,7 +243,7 @@ "extra_labels": ["NXP", "LPC176X", "MBED_LPC1768"], "supported_toolchains": ["ARM", "uARM", "GCC_ARM", "GCC_CR", "IAR"], "detect_code": ["1010"], - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOCALFILESYSTEM", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], + "device_has": ["USTICKER", "ANALOGIN", "ANALOGOUT", "CAN", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOCALFILESYSTEM", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SEMIHOST", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], "release_versions": ["2", "5"], "features": ["LWIP"], "device_name": "LPC1768", @@ -263,7 +263,7 @@ "extra_labels": ["NXP", "LPC176X"], "macros": ["TARGET_LPC1768"], "inherits": ["LPCTarget"], - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], + "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], "release_versions": ["2", "5"], "features": ["LWIP"], "device_name": "LPC1768", @@ -291,7 +291,7 @@ }, "macros": ["TARGET_LPC1768"], "inherits": ["LPCTarget"], - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], + "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], "release_versions": ["2", "5"], "features": ["LWIP"], "device_name": "LPC1768", @@ -307,7 +307,7 @@ "extra_labels": ["NXP", "LPC176X", "XBED_LPC1768"], "macros": ["TARGET_LPC1768"], "detect_code": ["1010"], - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOCALFILESYSTEM", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], + "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOCALFILESYSTEM", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SEMIHOST", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], "device_name": "LPC1768" }, "LPC810": { @@ -368,7 +368,7 @@ "post_binary_hook": { "function": "LPC4088Code.binary_hook" }, - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "features": ["LWIP"], "device_name": "LPC4088FBD144", "overrides": { @@ -388,7 +388,7 @@ "core": "Cortex-M4F", "extra_labels": ["NXP", "LPC43XX", "LPC4330"], "supported_toolchains": ["ARM", "GCC_CR", "IAR", "GCC_ARM"], - "device_has": ["ANALOGIN", "ANALOGOUT", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "device_name": "LPC4330" }, "LPC4330_M0": { @@ -396,14 +396,14 @@ "core": "Cortex-M0", "extra_labels": ["NXP", "LPC43XX", "LPC4330"], "supported_toolchains": ["ARM", "GCC_CR", "IAR"], - "device_has": ["ANALOGIN", "ANALOGOUT", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"] + "device_has": ["ANALOGIN", "ANALOGOUT", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"] }, "LPC4337": { "inherits": ["LPCTarget"], "core": "Cortex-M4F", "extra_labels": ["NXP", "LPC43XX", "LPC4337"], "supported_toolchains": ["ARM"], - "device_has": ["ANALOGIN", "ANALOGOUT", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "DEBUG_AWARENESS", "ETHERNET", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "release_versions": ["2"], "device_name": "LPC4337" }, @@ -446,7 +446,7 @@ "is_disk_virtual": true, "supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"], "inherits": ["Target"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["USTICKER", "ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "default_lib": "small", "release_versions": ["2"], "device_name": "MKL05Z32xxx4" @@ -459,7 +459,7 @@ "supported_toolchains": ["ARM", "GCC_ARM", "IAR"], "inherits": ["Target"], "detect_code": ["0200"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["USTICKER", "ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "release_versions": ["2", "5"], "device_name": "MKL25Z128xxx4" }, @@ -470,7 +470,7 @@ "is_disk_virtual": true, "supported_toolchains": ["ARM", "GCC_ARM", "IAR"], "inherits": ["Target"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["USTICKER", "ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "device_name": "MKL26Z128xxx4" }, "KL46Z": { @@ -481,7 +481,7 @@ "supported_toolchains": ["GCC_ARM", "ARM", "IAR"], "inherits": ["Target"], "detect_code": ["0220"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], + "device_has": ["USTICKER", "ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], "release_versions": ["2", "5"], "device_name": "MKL46Z256xxx4", "bootloader_supported": true @@ -493,7 +493,7 @@ "is_disk_virtual": true, "supported_toolchains": ["GCC_ARM", "ARM", "IAR"], "detect_code": ["0230"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "release_versions": ["2"], "device_name": "MK20DX128xxx5" }, @@ -509,7 +509,7 @@ "toolchains": ["ARM_STD", "ARM_MICRO", "GCC_ARM"] }, "detect_code": ["0230"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "release_versions": ["2"], "device_name": "MK20DX256xxx7" }, @@ -522,7 +522,7 @@ "macros": ["CPU_MK22FN512VLH12", "FSL_RTOS_MBED"], "inherits": ["Target"], "detect_code": ["0231"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG"], + "device_has": ["USTICKER", "LPTICKER", "RTC", "ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG"], "device_name": "MK22DN512xxx5" }, "K22F": { @@ -541,7 +541,7 @@ "is_disk_virtual": true, "default_toolchain": "ARM", "detect_code": ["0261"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["USTICKER", "LPTICKER", "RTC", "ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTOUT", "PWMOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "default_lib": "std", "release_versions": ["2"], "device_name": "MKL27Z64xxx4" @@ -555,7 +555,7 @@ "is_disk_virtual": true, "inherits": ["Target"], "detect_code": ["0262"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["USTICKER", "LPTICKER", "RTC", "ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "release_versions": ["2", "5"], "device_name": "MKL43Z256xxx4" }, @@ -568,13 +568,12 @@ "is_disk_virtual": true, "inherits": ["Target"], "detect_code": ["0218"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG"], + "device_has": ["USTICKER", "LPTICKER", "RTC", "ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG"], "release_versions": ["2", "5"], "device_name": "MKL82Z128xxx7" }, "USENSE": { "inherits": ["KL82Z"], - "device_has_add": ["LOWPOWERTIMER"], "extra_labels_remove": ["FRDM"], "supported_form_factors": [] }, @@ -587,7 +586,7 @@ "macros": ["CPU_MKW24D512VHA5", "FSL_RTOS_MBED"], "inherits": ["Target"], "detect_code": ["0250"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH"], + "device_has": ["USTICKER", "LPTICKER", "RTC", "ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "MKW24D512xxx5", "bootloader_supported": true @@ -601,7 +600,7 @@ "macros": ["CPU_MKW41Z512VHT4", "FSL_RTOS_MBED"], "inherits": ["Target"], "detect_code": ["0201"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "TRNG", "STDIO_MESSAGES"], + "device_has": ["USTICKER", "LPTICKER", "RTC", "ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "TRNG", "STDIO_MESSAGES"], "release_versions": ["2", "5"], "device_name": "MKW41Z512xxx4" }, @@ -613,7 +612,7 @@ "public": false, "macros": ["CPU_MK24FN1M0VDC12", "FSL_RTOS_MBED"], "inherits": ["Target"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH"], + "device_has": ["USTICKER", "LPTICKER", "RTC", "ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH"], "device_name": "MK24FN1M0xxx12" }, "RO359B": { @@ -631,7 +630,7 @@ "macros": ["CPU_MK64FN1M0VMD12", "FSL_RTOS_MBED"], "inherits": ["Target"], "detect_code": ["0240"], - "device_has": ["ANALOGIN", "ANALOGOUT", "CRC", "EMAC", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "STORAGE", "TRNG", "FLASH"], + "device_has": ["USTICKER", "LPTICKER", "RTC", "CRC", "ANALOGIN", "ANALOGOUT", "EMAC", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "STORAGE", "TRNG", "FLASH"], "features": ["LWIP", "STORAGE"], "release_versions": ["2", "5"], "device_name": "MK64FN1M0xxx12", @@ -645,8 +644,8 @@ "core": "Cortex-M4F", "supported_toolchains": ["ARM", "GCC_ARM", "IAR"], "macros": ["__ADUCM4050__", "EV_COG_AD4050LZ"], - "extra_labels": ["Analog_Devices", "ADUCM4X50", "ADUCM4050", "EV_COG_AD4050LZ", "FLASH_CMSIS_ALGO"], - "device_has": ["SERIAL", "STDIO_MESSAGES", "TRNG", "SLEEP", "INTERRUPTIN", "RTC", "SPI", "I2C", "FLASH", "ANALOGIN"], + "extra_labels": ["Analog_Devices", "ADUCM4X50", "ADUCM4050", "EV_COG_AD4050LZ"], + "device_has": ["USTICKER", "RTC", "SERIAL", "STDIO_MESSAGES", "TRNG", "SLEEP", "INTERRUPTIN", "SPI", "I2C", "ANALOGIN"], "device_name": "ADuCM4050", "detect_code": ["0603"], "release_versions": ["5"], @@ -657,8 +656,8 @@ "core": "Cortex-M3", "supported_toolchains": ["ARM", "GCC_ARM", "IAR"], "macros": ["__ADUCM3029__", "EV_COG_AD3029LZ"], - "extra_labels": ["Analog_Devices", "ADUCM302X", "ADUCM3029", "EV_COG_AD3029LZ", "FLASH_CMSIS_ALGO"], - "device_has": ["SERIAL", "STDIO_MESSAGES", "TRNG", "SLEEP", "INTERRUPTIN", "RTC", "SPI", "I2C", "FLASH", "ANALOGIN"], + "extra_labels": ["Analog_Devices", "ADUCM302X", "ADUCM3029", "EV_COG_AD3029LZ"], + "device_has": ["USTICKER", "RTC", "SERIAL", "STDIO_MESSAGES", "TRNG", "SLEEP", "INTERRUPTIN", "SPI", "I2C", "ANALOGIN"], "device_name": "ADuCM3029", "detect_code": ["0602"], "release_versions": ["5"], @@ -671,7 +670,7 @@ "extra_labels": ["Freescale", "MCUXpresso_MCUS", "KSDK2_MCUS", "KPSDK_MCUS", "KPSDK_CODE", "MCU_K64F"], "is_disk_virtual": true, "macros": ["CPU_MK64FN1M0VMD12", "FSL_RTOS_MBED", "TARGET_K64F"], - "device_has": ["I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], + "device_has": ["USTICKER", "LPTICKER", "RTC", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], "device_name": "MK64FN1M0xxx12" }, "HEXIWEAR": { @@ -683,7 +682,7 @@ "is_disk_virtual": true, "default_toolchain": "ARM", "detect_code": ["0214"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH"], + "device_has": ["USTICKER", "LPTICKER", "RTC", "ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH"], "default_lib": "std", "release_versions": ["2", "5"], "device_name": "MK64FN1M0xxx12", @@ -698,7 +697,7 @@ "macros": ["CPU_MK66FN2M0VMD18", "FSL_RTOS_MBED"], "inherits": ["Target"], "detect_code": ["0311"], - "device_has": ["ANALOGIN", "ANALOGOUT", "EMAC", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH"], + "device_has": ["USTICKER", "LPTICKER", "RTC", "ANALOGIN", "ANALOGOUT", "EMAC", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH"], "features": ["LWIP"], "release_versions": ["2", "5"], "device_name": "MK66FN2M0xxx18", @@ -716,7 +715,7 @@ "macros": ["CPU_MK82FN256VDC15", "FSL_RTOS_MBED"], "inherits": ["Target"], "detect_code": ["0217"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH"], + "device_has": ["USTICKER", "LPTICKER", "RTC", "ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "MK82FN256xxx15" }, @@ -730,7 +729,7 @@ "public": false, "extra_labels": ["STM"], "supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"], - "macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"], + "macros": ["TRANSACTION_QUEUE_SIZE_SPI=2", "LPTICKER_DELAY_TICKS=3"], "config": { "lse_available": { "help": "Define if a Low Speed External xtal (LSE) is available on the board (0 = No, 1 = Yes). If Yes, the LSE will be used to clock the RTC, LPUART, ... otherwise the Low Speed Internal clock (LSI) will be used", @@ -743,7 +742,7 @@ "help": "default RX STDIO pins is defined in PinNames.h file, but it can be overridden" } }, - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"] + "device_has": ["USTICKER", "LPTICKER", "RTC", "ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"] }, "MIMXRT1050_EVK": { "supported_form_factors": ["ARDUINO"], @@ -754,7 +753,7 @@ "macros": ["CPU_MIMXRT1052DVL6A", "FSL_RTOS_MBED"], "inherits": ["Target"], "detect_code": ["0227"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "ERROR_RED", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["USTICKER", "LPTICKER", "ANALOGIN", "I2C", "I2CSLAVE", "ERROR_RED", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "release_versions": ["2", "5"], "device_name": "MIMXRT1052" }, @@ -767,7 +766,7 @@ "macros": ["CPU_LPC54114J256BD64_cm4", "FSL_RTOS_MBED"], "inherits": ["Target"], "detect_code": ["1054"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], + "device_has": ["USTICKER", "RTC", "ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], "release_versions": ["2", "5"], "device_name" : "LPC54114J256BD64" }, @@ -778,7 +777,7 @@ "is_disk_virtual": true, "macros": ["CPU_LPC54628J512ET180", "FSL_RTOS_MBED"], "inherits": ["Target"], - "device_has": ["ANALOGIN", "EMAC", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH", "TRNG"], + "device_has": ["USTICKER", "RTC", "ANALOGIN", "EMAC", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH", "TRNG"], "features": ["LWIP"], "device_name" : "LPC54628J512ET180", "overrides": { @@ -872,7 +871,7 @@ }, "detect_code": ["0755"], "macros_add": ["CMSIS_VECTAB_VIRTUAL", "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\""], - "device_has_add": ["CRC", "LOWPOWERTIMER", "SERIAL_FC", "SERIAL_ASYNCH", "FLASH"], + "device_has_add": ["CRC", "SERIAL_FC", "SERIAL_ASYNCH", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F070RB" }, @@ -890,7 +889,7 @@ }, "detect_code": ["0730"], "macros_add": ["CMSIS_VECTAB_VIRTUAL", "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\""], - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "LOWPOWERTIMER", "SERIAL_FC", "SERIAL_ASYNCH", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "CRC", "SERIAL_FC", "SERIAL_ASYNCH", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F072RB" }, @@ -908,7 +907,7 @@ }, "detect_code": ["0750"], "macros_add": ["CMSIS_VECTAB_VIRTUAL", "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\""], - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "LOWPOWERTIMER", "SERIAL_FC", "SERIAL_ASYNCH", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "CRC", "SERIAL_FC", "SERIAL_ASYNCH", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F091RC" }, @@ -931,6 +930,7 @@ }, "detect_code": ["0700"], "device_has_add": ["CAN", "SERIAL_FC", "SERIAL_ASYNCH", "FLASH"], + "device_has_remove": ["LPTICKER"], "release_versions": ["2", "5"], "device_name": "STM32F103RB" }, @@ -954,6 +954,7 @@ "detect_code": ["0835"], "macros_add": ["USBHOST_OTHER"], "device_has_add": ["ANALOGOUT", "CAN", "EMAC", "SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], + "device_has_remove": ["LPTICKER"], "features": ["LWIP"], "release_versions": ["2", "5"], "device_name": "STM32F207ZG", @@ -974,7 +975,7 @@ } }, "detect_code": ["0705"], - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC"], + "device_has_add": ["ANALOGOUT", "CAN", "CRC", "SERIAL_ASYNCH", "SERIAL_FC"], "default_lib": "small", "release_versions": ["2"], "device_name": "STM32F302R8" @@ -994,7 +995,7 @@ "overrides": {"lse_available": 0}, "detect_code": ["0775"], "default_lib": "small", - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "LOWPOWERTIMER", "SERIAL_FC"], + "device_has_add": ["ANALOGOUT", "CAN", "CRC", "SERIAL_FC"], "release_versions": ["2"], "device_name": "STM32F303K8" }, @@ -1011,7 +1012,7 @@ } }, "detect_code": ["0745"], - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "CRC", "SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F303RE" }, @@ -1028,7 +1029,7 @@ } }, "detect_code": ["0747"], - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "LOWPOWERTIMER", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "CRC", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F303ZE" }, @@ -1045,7 +1046,7 @@ } }, "detect_code": ["0735"], - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC"], + "device_has_add": ["ANALOGOUT", "CAN", "CRC", "SERIAL_ASYNCH", "SERIAL_FC"], "default_lib": "small", "release_versions": ["2"], "device_name": "STM32F334R8" @@ -1064,7 +1065,7 @@ }, "detect_code": ["0720"], "macros_add": ["USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["SERIAL_ASYNCH", "SERIAL_FC", "FLASH", "LOWPOWERTIMER"], + "device_has_add": ["SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F401RE" }, @@ -1080,7 +1081,7 @@ } }, "macros_add": ["USB_STM_HAL", "USBHOST_OTHER", "HSE_VALUE=25000000"], - "device_has_add": ["SERIAL_ASYNCH", "SERIAL_FC", "FLASH", "LOWPOWERTIMER"], + "device_has_add": ["SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], "overrides": {"lse_available": 0}, "release_versions": ["2", "5"], "device_name": "STM32F401VE" @@ -1096,13 +1097,13 @@ "value": "USE_PLL_HSE_EXTC|USE_PLL_HSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0744"], - "device_has_add": ["ANALOGOUT", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F410RB" }, @@ -1125,7 +1126,7 @@ } }, "macros_add": ["USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], + "device_has_add": ["SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F411RE", "bootloader_supported": true @@ -1144,7 +1145,7 @@ }, "detect_code": ["0826"], "macros_add": ["USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["CAN", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["CAN", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F412ZG", "bootloader_supported": true @@ -1154,7 +1155,7 @@ "core": "Cortex-M4F", "extra_labels_add": ["STM32F4", "STM32F412xG", "STM32F412ZG"], "macros_add": ["USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["CAN", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["CAN", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F412ZG", "bootloader_supported": true, @@ -1204,14 +1205,14 @@ "value": "USE_PLL_HSE_EXTC|USE_PLL_HSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0743"], "macros_add": ["USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["ANALOGOUT", "CAN", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F413ZH" }, @@ -1225,11 +1226,15 @@ "help": "Mask value : USE_PLL_HSE_EXTC | USE_PLL_HSE_XTAL (need HW patch) | USE_PLL_HSI", "value": "USE_PLL_HSE_EXTC|USE_PLL_HSI", "macro_name": "CLOCK_SOURCE" + }, + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", + "value": 1 } }, "detect_code": ["0743"], "macros_add": ["USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["ANALOGOUT", "CAN", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F413ZH" }, @@ -1269,7 +1274,7 @@ }, "extra_labels_add": ["STM32F4", "STM32F429", "STM32F429ZI", "STM32F429xx", "STM32F429xI", "STM_EMAC"], "macros_add": ["USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["ANALOGOUT", "CAN", "EMAC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "EMAC", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], "detect_code": ["0796"], "features": ["LWIP"], "release_versions": ["2", "5"], @@ -1302,7 +1307,7 @@ }, "extra_labels_add": ["STM32F4", "STM32F439", "STM32F439ZI", "STM32F439xx", "STM32F439xI", "STM_EMAC"], "macros_add": ["MBEDTLS_CONFIG_HW_SUPPORT", "USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["ANALOGOUT", "CAN", "EMAC", "LOWPOWERTIMER", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "EMAC", "SERIAL_FC", "TRNG", "FLASH"], "detect_code": ["0797"], "features": ["LWIP"], "release_versions": ["2", "5"], @@ -1326,7 +1331,7 @@ }, "detect_code": ["0777"], "macros_add": ["USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["ANALOGOUT", "CAN", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F446RE", "bootloader_supported": true @@ -1345,7 +1350,7 @@ }, "detect_code": ["0778"], "macros_add": ["USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["ANALOGOUT", "CAN", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F446ZE" }, @@ -1355,7 +1360,7 @@ "core": "Cortex-M4F", "extra_labels_add": ["STM32F4", "STM32F446xE", "STM32F446VE"], "detect_code": ["0840"], - "device_has_add": ["ANALOGOUT", "CAN", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], "release_versions": ["2", "5"], "device_name":"STM32F446VE" }, @@ -1374,15 +1379,15 @@ "value": "USE_PLL_HSE_EXTC|USE_PLL_HSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "macros_add": ["USBHOST_OTHER"], "supported_form_factors": ["ARDUINO"], "detect_code": ["0816"], - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "EMAC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "TRNG", "FLASH"], + "device_has_add": ["LPTICKER", "ANALOGOUT", "CAN", "CRC", "EMAC", "SERIAL_ASYNCH", "TRNG", "FLASH"], "features": ["LWIP"], "release_versions": ["2", "5"], "device_name": "STM32F746ZG", @@ -1406,15 +1411,15 @@ "value": "USE_PLL_HSE_EXTC|USE_PLL_HSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "macros_add": ["TRANSACTION_QUEUE_SIZE_SPI=2", "USBHOST_OTHER", "MBEDTLS_CONFIG_HW_SUPPORT"], "supported_form_factors": ["ARDUINO"], "detect_code": ["0819"], - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "EMAC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "TRNG", "FLASH"], + "device_has_add": ["LPTICKER", "ANALOGOUT", "CAN", "CRC", "EMAC", "SERIAL_ASYNCH", "TRNG", "FLASH"], "features": ["LWIP"], "release_versions": ["2", "5"], "device_name": "STM32F756ZG", @@ -1437,15 +1442,15 @@ "value": "USE_PLL_HSE_EXTC|USE_PLL_HSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "supported_form_factors": ["ARDUINO"], "macros_add": ["USBHOST_OTHER"], "detect_code": ["0818"], - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "EMAC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "TRNG", "FLASH"], + "device_has_add": ["LPTICKER", "ANALOGOUT", "CAN", "CRC", "EMAC", "SERIAL_ASYNCH", "TRNG", "FLASH"], "features": ["LWIP"], "release_versions": ["2", "5"], "device_name": "STM32F767ZI", @@ -1467,13 +1472,13 @@ "value": "USE_PLL_HSE_EXTC|USE_PLL_HSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0780"], - "device_has_add": ["CRC", "LOWPOWERTIMER", "SERIAL_FC", "FLASH"], + "device_has_add": ["CRC", "SERIAL_FC", "FLASH"], "default_lib": "small", "release_versions": ["2"], "device_name": "STM32L011K4" @@ -1490,13 +1495,13 @@ "value": "USE_PLL_HSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0790"], - "device_has_add": ["CRC", "LOWPOWERTIMER", "SERIAL_FC", "FLASH"], + "device_has_add": ["CRC", "SERIAL_FC", "FLASH"], "default_lib": "small", "release_versions": ["2"], "device_name": "STM32L031K6" @@ -1512,13 +1517,13 @@ "value": "USE_PLL_HSE_EXTC|USE_PLL_HSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0715"], - "device_has_add": ["ANALOGOUT", "CRC", "LOWPOWERTIMER", "SERIAL_FC", "SERIAL_ASYNCH", "FLASH"], + "device_has_add": ["ANALOGOUT", "CRC", "SERIAL_FC", "SERIAL_ASYNCH", "FLASH"], "default_lib": "small", "release_versions": ["2"], "device_name": "STM32L053R8" @@ -1534,13 +1539,13 @@ "value": "USE_PLL_HSE_EXTC|USE_PLL_HSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0760"], - "device_has_add": ["ANALOGOUT", "CRC", "LOWPOWERTIMER", "SERIAL_FC", "SERIAL_ASYNCH", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CRC", "SERIAL_FC", "SERIAL_ASYNCH", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32L073RZ" }, @@ -1557,7 +1562,7 @@ } }, "detect_code": ["0710"], - "device_has_add": ["ANALOGOUT", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], + "device_has_add": ["ANALOGOUT", "SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32L152RE" }, @@ -1572,13 +1577,13 @@ "value": "USE_PLL_MSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0770"], - "device_has_add": ["ANALOGOUT", "CRC", "LOWPOWERTIMER", "SERIAL_FC", "SERIAL_ASYNCH", "CAN", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CRC", "SERIAL_FC", "SERIAL_ASYNCH", "CAN", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32L432KC", "bootloader_supported": true @@ -1594,13 +1599,13 @@ "value": "USE_PLL_MSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0779"], - "device_has_add": ["ANALOGOUT", "CRC", "LOWPOWERTIMER", "SERIAL_FC", "SERIAL_ASYNCH", "CAN", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CRC", "SERIAL_FC", "SERIAL_ASYNCH", "CAN", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32L433RC", "bootloader_supported": true @@ -1620,6 +1625,7 @@ "overrides": {"lse_available": 0}, "release_versions": ["5"], "device_has_add": ["ANALOGOUT", "CRC", "SERIAL_FC", "SERIAL_ASYNCH", "CAN", "TRNG", "FLASH"], + "device_has_remove": ["LPTICKER"], "macros_add": ["MBEDTLS_CONFIG_HW_SUPPORT"], "device_name" : "STM32L443RC", "detect_code": ["0458"], @@ -1636,14 +1642,14 @@ "value": "USE_PLL_MSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0765"], "macros_add": ["USBHOST_OTHER", "TWO_RAM_REGIONS"], - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "CRC", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32L476RG", "bootloader_supported": true @@ -1662,7 +1668,7 @@ }, "detect_code": ["0766"], "macros_add": ["USBHOST_OTHER", "TWO_RAM_REGIONS"], - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "CRC", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["5"], "device_name": "STM32L476JG" }, @@ -1677,14 +1683,14 @@ "value": "USE_PLL_MSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0827"], "macros_add": ["USBHOST_OTHER", "MBEDTLS_CONFIG_HW_SUPPORT", "TWO_RAM_REGIONS"], - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "CRC", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32L486RG" }, @@ -1701,7 +1707,8 @@ }, "detect_code": ["0460"], "macros_add": ["MBEDTLS_CONFIG_HW_SUPPORT", "WISE_1570", "TWO_RAM_REGIONS"], - "device_has_add": ["ANALOGOUT", "CRC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CRC", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_remove": ["LPTICKER"], "release_versions": ["5"], "device_name": "STM32L486RG", "OUTPUT_EXT": "hex" @@ -1739,6 +1746,7 @@ "extra_labels_add": ["STM32F1", "STM32F100RB"], "supported_toolchains": ["GCC_ARM"], "device_has_add": [], + "device_has_remove": ["LPTICKER"], "device_name": "STM32F100RB" }, "DISCO_F303VC": { @@ -1755,7 +1763,7 @@ }, "supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"], "release_versions": ["2", "5"], - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "LOWPOWERTIMER", "SERIAL_FC"], + "device_has_add": ["ANALOGOUT", "CAN", "CRC", "SERIAL_FC"], "device_name": "STM32F303VC" }, "DISCO_F334C8": { @@ -1771,7 +1779,7 @@ }, "overrides": {"lse_available": 0}, "detect_code": ["0810"], - "device_has_add": ["ANALOGOUT", "CRC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC"], + "device_has_add": ["ANALOGOUT", "CRC", "SERIAL_ASYNCH", "SERIAL_FC"], "default_lib": "small", "release_versions": ["2"], "device_name": "STM32F334C8" @@ -1831,7 +1839,7 @@ }, "detect_code": ["0788"], "macros_add": ["USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["ANALOGOUT", "CAN", "LOWPOWERTIMER", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32F469NI" }, @@ -1845,14 +1853,14 @@ "value": "USE_PLL_HSE_EXTC|USE_PLL_HSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "overrides": {"lse_available": 0}, - "device_has_add": ["ANALOGOUT", "CRC", "LOWPOWERTIMER", "SERIAL_FC", "FLASH"], + "device_has_add": ["ANALOGOUT", "CRC", "SERIAL_FC", "FLASH"], "default_lib": "small", "release_versions": ["2"], "device_name": "STM32L053C8" @@ -1868,13 +1876,13 @@ "value": "USE_PLL_HSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0833"], - "device_has_add": ["ANALOGOUT", "LOWPOWERTIMER", "SERIAL_FC", "SERIAL_ASYNCH", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "SERIAL_FC", "SERIAL_ASYNCH", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32L072CZ" }, @@ -1884,6 +1892,7 @@ "extra_labels_add": ["STM32L0", "STM32L0x2xZ", "STM32L082CZ", "STM32L082xx"], "detect_code": ["0456"], "device_has_add": ["ANALOGOUT", "SERIAL_FC", "SERIAL_ASYNCH", "TRNG", "FLASH"], + "device_has_remove": ["LPTICKER"], "release_versions": ["5"], "device_name": "STM32L082CZ" }, @@ -1902,14 +1911,14 @@ "help": "Select the USB speed/connector (0=FullSpeed, 1=HighSpeed)", "value": "1" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0815"], "macros_add": ["USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["ANALOGOUT", "CAN", "EMAC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "TRNG", "FLASH"], + "device_has_add": ["LPTICKER", "ANALOGOUT", "CAN", "EMAC", "SERIAL_ASYNCH", "TRNG", "FLASH"], "features": ["LWIP"], "release_versions": ["2", "5"], "device_name": "STM32F746NG", @@ -1928,14 +1937,14 @@ "value": "USE_PLL_HSE_EXTC|USE_PLL_HSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0817"], "macros_add": ["USB_STM_HAL", "USBHOST_OTHER"], - "device_has_add": ["ANALOGOUT", "CAN", "EMAC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "TRNG", "FLASH"], + "device_has_add": ["LPTICKER", "ANALOGOUT", "CAN", "EMAC", "SERIAL_ASYNCH", "TRNG", "FLASH"], "features": ["LWIP"], "release_versions": ["2", "5"], "device_name": "STM32F769NI", @@ -1953,15 +1962,15 @@ "value": "USE_PLL_MSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "supported_form_factors": ["ARDUINO"], "detect_code": ["0764"], - "macros_add": ["USBHOST_OTHER", "TWO_RAM_REGIONS"], - "device_has_add": ["ANALOGOUT", "CAN", "LOWPOWERTIMER", "SERIAL_FC", "TRNG", "FLASH"], + "macros_add": ["USBHOST_OTHER"], + "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32L475VG", "bootloader_supported": true @@ -1976,14 +1985,14 @@ "value": "USE_PLL_MSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0820"], - "macros_add": ["USBHOST_OTHER", "TWO_RAM_REGIONS"], - "device_has_add": ["ANALOGOUT", "CAN", "LOWPOWERTIMER", "SERIAL_FC", "TRNG", "FLASH"], + "macros_add": ["USBHOST_OTHER"], + "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32L476VG", "bootloader_supported": true @@ -2146,7 +2155,7 @@ "extra_labels_add": ["STM32F4", "STM32F439", "STM32F439ZI","STM32F439xx", "STM32F439xI", "STM_EMAC"], "macros": ["MBEDTLS_CONFIG_HW_SUPPORT", "HSE_VALUE=24000000", "HSE_STARTUP_TIMEOUT=5000", "CB_INTERFACE_SDIO","CB_CHIP_WL18XX","SUPPORT_80211D_ALWAYS","WLAN_ENABLED","CB_FEATURE_802DOT11W","CB_FEATURE_802DOT11R","MBEDTLS_ARC4_C","MBEDTLS_DES_C","MBEDTLS_MD4_C","MBEDTLS_MD5_C","MBEDTLS_SHA1_C"], "device_has_add": ["CAN", "EMAC", "TRNG", "FLASH", "WIFI"], - "device_has_remove": ["RTC", "SLEEP"], + "device_has_remove": [], "features": ["LWIP"], "device_name": "STM32F439ZI", "public": false, @@ -2159,6 +2168,7 @@ "inherits": ["MODULE_UBLOX_ODIN_W2"], "supported_form_factors": ["ARDUINO"], "release_versions": ["5"], + "device_has_remove": [], "config": { "stdio_uart_tx_help": { "help": "Value: D8(default) or D1" @@ -2190,6 +2200,7 @@ }, "MTB_UBLOX_ODIN_W2": { "inherits": ["MODULE_UBLOX_ODIN_W2"], + "device_has_add": [], "release_versions": ["5"] }, "UBLOX_C030": { @@ -2524,7 +2535,7 @@ "inherits": ["MCU_NRF51_32K"], "program_cycle_s": 10, "macros_add": ["TARGET_NRF_LFCLK_RC"], - "device_has": ["ANALOGIN", "DEBUG_AWARENESS", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE"], + "device_has": ["ANALOGIN", "DEBUG_AWARENESS", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE"], "release_versions": ["2"], "device_name": "nRF51822_xxAA" }, @@ -2543,7 +2554,7 @@ "DELTA_DFCM_NNN50": { "supported_form_factors": ["ARDUINO"], "inherits": ["MCU_NRF51_32K_UNIFIED"], - "device_has": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], + "device_has": ["USTICKER", "LPTICKER", "ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], "device_name": "nRF51822_xxAC" }, "DELTA_DFCM_NNN50_BOOT": { @@ -2640,7 +2651,7 @@ }, "MTB_LAIRD_BL600": { "inherits": ["MCU_NRF51_32K_UNIFIED"], - "device_has": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], + "device_has": ["USTICKER", "LPTICKER", "ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], "device_name": "nRF51822_xxAA", "release_versions" : ["5"], "extra_labels_add": ["MTB_LAIRD_BL600"], @@ -2666,7 +2677,7 @@ "TY51822R3": { "inherits": ["MCU_NRF51_32K_UNIFIED"], "macros_add": ["TARGET_NRF_32MHZ_XTAL"], - "device_has": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], + "device_has": ["USTICKER", "LPTICKER", "ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], "detect_code": ["1019"], "release_versions": ["2", "5"], "overrides": {"uart_hwfc": 0}, @@ -2753,7 +2764,7 @@ "extra_labels": ["ARM_SSG", "CM3DS_MPS2"], "OUTPUT_EXT": "elf", "macros": ["CMSDK_CM3DS"], - "device_has": ["ANALOGIN", "ETHERNET", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SPI", "RTC", "LOWPOWERTIMER", "TRNG"], + "device_has": ["ANALOGIN", "ETHERNET", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SPI", "TRNG"], "release_versions": ["2", "5"], "copy_method": "mps2", "reset_method": "reboot.txt" @@ -2765,7 +2776,7 @@ "default_toolchain": "ARM", "extra_labels": ["ARM_SSG", "BEETLE"], "macros": ["CMSDK_BEETLE", "WSF_MS_PER_TICK=20", "WSF_TOKEN_ENABLED=FALSE", "WSF_TRACE_ENABLED=TRUE", "WSF_ASSERT_ENABLED=FALSE", "WSF_PRINTF_MAX_LEN=128", "ASIC", "CONFIG_HOST_REV=0x20", "CONFIG_ALLOW_DEEP_SLEEP=FALSE", "HCI_VS_TARGET", "CONFIG_ALLOW_SETTING_WRITE=TRUE", "WSF_MAX_HANDLERS=20", "NO_LEDS"], - "device_has": ["ANALOGIN", "CLCD", "I2C", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SLEEP", "SPI"], + "device_has": ["ANALOGIN", "CLCD", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SLEEP", "SPI"], "features": ["BLE"], "release_versions": ["2", "5"] }, @@ -2774,7 +2785,7 @@ "core": "Cortex-A9", "supported_toolchains": ["ARM", "GCC_ARM", "IAR"], "extra_labels": ["RENESAS", "RZ_A1XX"], - "device_has": ["ANALOGIN", "CAN", "ETHERNET", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], + "device_has": ["SLEEP", "USTICKER", "RTC", "ANALOGIN", "CAN", "ETHERNET", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], "features": ["LWIP"], "program_cycle_s": 2, "overrides": { @@ -2812,9 +2823,9 @@ "macros": ["__SYSTEM_HFX=24000000"], "extra_labels": ["Maxim", "MAX32610"], "supported_toolchains": ["GCC_ARM", "IAR", "ARM"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "STDIO_MESSAGES"], "features": ["BLE"], - "release_versions": ["2", "5"] + "release_versions": [] }, "MAX32600MBED": { "inherits": ["Target"], @@ -2822,7 +2833,7 @@ "macros": ["__SYSTEM_HFX=24000000"], "extra_labels": ["Maxim", "MAX32600"], "supported_toolchains": ["GCC_ARM", "IAR", "ARM"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "STDIO_MESSAGES"], "release_versions": ["2", "5"] }, "MAX32620HSP": { @@ -2830,9 +2841,9 @@ "core": "Cortex-M4F", "extra_labels": ["Maxim", "MAX32620"], "supported_toolchains": ["GCC_ARM", "IAR", "ARM"], - "device_has": ["ANALOGIN", "I2C", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "STDIO_MESSAGES"], "features": ["BLE"], - "release_versions": ["2", "5"] + "release_versions": [] }, "MAX32620FTHR": { "inherits": ["Target"], @@ -2840,7 +2851,7 @@ "macros": ["__SYSTEM_HFX=96000000","TARGET=MAX32620","TARGET_REV=0x4332","OPEN_DRAIN_LEDS"], "extra_labels": ["Maxim", "MAX32620C"], "supported_toolchains": ["GCC_ARM", "IAR", "ARM"], - "device_has": ["ANALOGIN", "I2C", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "I2C", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "STDIO_MESSAGES", "USTICKER"], "release_versions": ["2", "5"] }, "MAX32625_BASE": { @@ -2849,7 +2860,7 @@ "macros": ["TARGET=MAX32625","TARGET_REV=0x4132", "OPEN_DRAIN_LEDS"], "extra_labels": ["Maxim", "MAX32625"], "supported_toolchains": ["GCC_ARM", "IAR", "ARM"], - "device_has": ["ANALOGIN", "I2C", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "I2C", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "STDIO_MESSAGES", "USTICKER"], "release_versions": ["2", "5"], "public": false }, @@ -2884,7 +2895,7 @@ "macros": ["__SYSTEM_HFX=96000000", "TARGET=MAX32630", "TARGET_REV=0x4132", "BLE_HCI_UART", "OPEN_DRAIN_LEDS"], "extra_labels": ["Maxim", "MAX32630"], "supported_toolchains": ["GCC_ARM", "IAR", "ARM"], - "device_has": ["ANALOGIN", "I2C", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "I2C", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_FC", "SPI", "STDIO_MESSAGES", "USTICKER"], "features": ["BLE"], "release_versions": ["2", "5"] }, @@ -2908,7 +2919,7 @@ "EFM32GG_STK3700": { "inherits": ["EFM32GG990F1024"], "progen": {"target": "efm32gg-stk"}, - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "FLASH", "ITM"], + "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH", "ITM"], "forced_reset_timeout": 2, "config": { "hf_clock_src": { @@ -2961,7 +2972,7 @@ }, "EFM32LG_STK3600": { "inherits": ["EFM32LG990F256"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "FLASH"], + "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"], "forced_reset_timeout": 2, "device_name": "EFM32LG990F256", "config": { @@ -3016,7 +3027,7 @@ "EFM32WG_STK3800": { "inherits": ["EFM32WG990F256"], "progen": {"target": "efm32wg-stk"}, - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "FLASH"], + "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"], "forced_reset_timeout": 2, "config": { "hf_clock_src": { @@ -3070,7 +3081,7 @@ }, "EFM32ZG_STK3200": { "inherits": ["EFM32ZG222F32"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER"], "forced_reset_timeout": 2, "config": { "hf_clock_src": { @@ -3124,7 +3135,7 @@ }, "EFM32HG_STK3400": { "inherits": ["EFM32HG322F64"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER"], "forced_reset_timeout": 2, "config": { "hf_clock_src": { @@ -3177,7 +3188,7 @@ }, "EFM32PG_STK3401": { "inherits": ["EFM32PG1B100F256GM32"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "FLASH"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"], "forced_reset_timeout": 2, "config": { "hf_clock_src": { @@ -3240,7 +3251,7 @@ }, "EFR32MG1_BRD4150": { "inherits": ["EFR32MG1P132F256GM48"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "FLASH"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"], "forced_reset_timeout": 2, "config": { "hf_clock_src": { @@ -3283,7 +3294,7 @@ }, "TB_SENSE_1": { "inherits": ["EFR32MG1P233F256GM48"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "FLASH"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"], "forced_reset_timeout": 5, "config": { "hf_clock_src": { @@ -3331,7 +3342,7 @@ }, "EFM32PG12_STK3402": { "inherits": ["EFM32PG12B500F1024GL125"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG", "FLASH"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "TRNG", "FLASH"], "forced_reset_timeout": 2, "config": { "hf_clock_src": { @@ -3385,7 +3396,7 @@ "TB_SENSE_12": { "inherits": ["EFR32MG12P332F1024GL125"], "device_name": "EFR32MG12P332F1024GL125", - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG", "FLASH"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "TRNG", "FLASH"], "forced_reset_timeout": 5, "config": { "hf_clock_src": { @@ -3455,7 +3466,7 @@ "macros": ["__SAMR21G18A__", "I2C_MASTER_CALLBACK_MODE=true", "EXTINT_CALLBACK_MODE=true", "USART_CALLBACK_MODE=true", "TC_ASYNC=true"], "extra_labels": ["Atmel", "SAM_CortexM0P", "SAMR21"], "supported_toolchains": ["GCC_ARM", "ARM", "uARM"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH"], "release_versions": ["2"], "device_name": "ATSAMR21G18A" }, @@ -3465,7 +3476,7 @@ "macros": ["__SAMD21J18A__", "I2C_MASTER_CALLBACK_MODE=true", "EXTINT_CALLBACK_MODE=true", "USART_CALLBACK_MODE=true", "TC_ASYNC=true"], "extra_labels": ["Atmel", "SAM_CortexM0P", "SAMD21"], "supported_toolchains": ["GCC_ARM", "ARM", "uARM"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH"], + "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH"], "release_versions": ["2"], "device_name": "ATSAMD21J18A" }, @@ -3475,7 +3486,7 @@ "macros": ["__SAMD21G18A__", "I2C_MASTER_CALLBACK_MODE=true", "EXTINT_CALLBACK_MODE=true", "USART_CALLBACK_MODE=true", "TC_ASYNC=true"], "extra_labels": ["Atmel", "SAM_CortexM0P", "SAMD21"], "supported_toolchains": ["GCC_ARM", "ARM", "uARM"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH"], + "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH"], "release_versions": ["2"], "device_name": "ATSAMD21G18A" }, @@ -3485,7 +3496,7 @@ "macros": ["__SAML21J18A__", "I2C_MASTER_CALLBACK_MODE=true", "EXTINT_CALLBACK_MODE=true", "USART_CALLBACK_MODE=true", "TC_ASYNC=true"], "extra_labels": ["Atmel", "SAM_CortexM0P", "SAML21"], "supported_toolchains": ["GCC_ARM", "ARM", "uARM"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH"], + "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH"], "device_name": "ATSAML21J18A" }, "SAMG55J19": { @@ -3495,7 +3506,7 @@ "macros": ["__SAMG55J19__", "BOARD=75", "I2C_MASTER_CALLBACK_MODE=true", "EXTINT_CALLBACK_MODE=true", "USART_CALLBACK_MODE=true", "TC_ASYNC=true"], "supported_toolchains": ["GCC_ARM", "ARM", "uARM"], "default_toolchain": "ARM", - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH"], "default_lib": "std", "device_name": "ATSAMG55J19" }, @@ -3565,20 +3576,20 @@ "NRF51_DK": { "supported_form_factors": ["ARDUINO"], "inherits": ["MCU_NRF51_32K_UNIFIED"], - "device_has": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], + "device_has": ["USTICKER", "LPTICKER", "ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], "release_versions": ["2", "5"], "device_name": "nRF51822_xxAA" }, "NRF51_DONGLE": { "inherits": ["MCU_NRF51_32K_UNIFIED"], "progen": {"target": "nrf51-dongle"}, - "device_has": ["I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], + "device_has": ["USTICKER", "LPTICKER", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], "release_versions": ["2", "5"] }, "OSHCHIP": { "inherits": ["MCU_NRF51_32K_UNIFIED"], "overrides": {"lf_clock_src": "NRF_LF_SRC_RC"}, - "device_has": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE"], + "device_has": ["USTICKER", "LPTICKER", "ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SLEEP", "SPI", "SPISLAVE"], "device_name": "nRF51822_xxAC" }, "MCU_NRF52832": { @@ -3599,20 +3610,19 @@ "I2C_ASYNCH", "INTERRUPTIN", "ITM", - "LOWPOWERTIMER", + "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", - "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", - "SLEEP", "SPI", "SPI_ASYNCH", "STCLK_OFF_DURING_SLEEP", - "TRNG" + "TRNG", + "USTICKER" ], "extra_labels": [ "NORDIC", @@ -3698,7 +3708,7 @@ "I2C_ASYNCH", "INTERRUPTIN", "ITM", - "LOWPOWERTIMER", + "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", @@ -3711,7 +3721,8 @@ "SPI", "SPI_ASYNCH", "STCLK_OFF_DURING_SLEEP", - "TRNG" + "TRNG", + "USTICKER" ], "extra_labels": [ "NORDIC", @@ -3757,7 +3768,7 @@ "extra_labels_add": ["STM32F1", "STM32F103C8"], "supported_toolchains": ["GCC_ARM"], "device_has_add": [], - "device_has_remove": ["RTC", "STDIO_MESSAGES"] + "device_has_remove": ["STDIO_MESSAGES"] }, "NUMAKER_PFM_NUC472": { "core": "Cortex-M4F", @@ -3785,7 +3796,7 @@ }, "inherits": ["Target"], "macros_add": ["MBEDTLS_CONFIG_HW_SUPPORT"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "TRNG", "CAN", "FLASH", "EMAC"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "TRNG", "CAN", "FLASH", "EMAC"], "features": ["LWIP"], "release_versions": ["5"], "device_name": "NUC472HI8AE", @@ -3828,7 +3839,7 @@ "post_binary_hook": {"function": "NCS36510TargetCode.ncs36510_addfib"}, "macros": ["CM3", "CPU_NCS36510", "TARGET_NCS36510", "LOAD_ADDRESS=0x3000"], "supported_toolchains": ["GCC_ARM", "ARM", "IAR"], - "device_has": ["ANALOGIN", "SERIAL", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "LOWPOWERTIMER", "TRNG", "SPISLAVE", "RTC"], + "device_has": ["ANALOGIN", "SERIAL", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "TRNG", "SPISLAVE"], "release_versions": ["2", "5"] }, "NUMAKER_PFM_M453": { @@ -3857,7 +3868,7 @@ }, "inherits": ["Target"], "progen": {"target": "numaker-pfm-m453"}, - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "CAN", "FLASH"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "CAN", "FLASH"], "release_versions": ["2", "5"], "device_name": "M453VG6AE", "bootloader_supported": true @@ -3888,7 +3899,7 @@ }, "inherits": ["Target"], "macros": ["CMSIS_VECTAB_VIRTUAL", "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\"","MBED_FAULT_HANDLER_DISABLED"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH"], "release_versions": ["5"], "device_name": "NANO130KE3BN" }, @@ -3905,9 +3916,9 @@ "core.stdio-flush-at-exit": false } }, - "device_has": ["INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SLEEP", "STDIO_MESSAGES"], + "device_has": ["INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SLEEP", "STDIO_MESSAGES"], "default_lib": "std", - "release_versions": ["5"] + "release_versions": [] }, "SARA_NBIOT": { "inherits": ["HI2110"], @@ -3927,7 +3938,7 @@ "extra_labels": ["Realtek", "AMEBA", "RTL8195A", "RTW_EMAC"], "macros": ["__RTL8195A__","CONFIG_PLATFORM_8195A","CONFIG_MBED_ENABLED","PLATFORM_CMSIS_RTOS","MBED_FAULT_HANDLER_DISABLED"], "supported_toolchains": ["GCC_ARM", "ARM", "IAR"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SPI", "TRNG", "FLASH", "EMAC"], + "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SPI", "TRNG", "FLASH", "EMAC"], "features": ["LWIP"], "post_binary_hook": { "function": "RTL8195ACode.binary_hook", @@ -3966,7 +3977,7 @@ "inherits": ["MCU_NRF51_32K_UNIFIED"], "detect_code": ["C006"], "overrides": {"uart_hwfc": 0}, - "device_has": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], + "device_has": ["USTICKER", "LPTICKER", "ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"], "release_versions": ["2"], "device_name": "nRF51822_xxAC" }, @@ -3981,13 +3992,13 @@ "value": "USE_PLL_MSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0822"], - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "CRC", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32L496AG" }, @@ -4002,13 +4013,13 @@ "value": "USE_PLL_MSI", "macro_name": "CLOCK_SOURCE" }, - "lowpowertimer_lptim": { - "help": "This target supports LPTIM. Set value 1 to use LPTIM for LOWPOWERTIMER, or 0 to use RTC wakeup timer", + "lpticker_lptim": { + "help": "This target supports LPTIM. Set value 1 to use LPTIM for LPTICKER, or 0 to use RTC wakeup timer", "value": 1 } }, "detect_code": ["0823"], - "device_has_add": ["ANALOGOUT", "CAN", "CRC", "LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], + "device_has_add": ["ANALOGOUT", "CAN", "CRC", "SERIAL_ASYNCH", "SERIAL_FC", "TRNG", "FLASH"], "release_versions": ["2", "5"], "device_name": "STM32L496ZG" }, @@ -4056,7 +4067,7 @@ }, "inherits": ["Target"], "macros_add": ["MBEDTLS_CONFIG_HW_SUPPORT"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "TRNG", "FLASH", "CAN", "EMAC"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "TRNG", "FLASH", "CAN", "EMAC"], "features": ["LWIP"], "release_versions": ["5"], "device_name": "M487JIDAE", @@ -4090,7 +4101,7 @@ "macro_name": "CLOCK_SOURCE" } }, - "device_has_add": ["LOWPOWERTIMER", "SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], + "device_has_add": ["SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], "release_versions": ["2"], "device_name": "STM32F411RE" }, diff --git a/tools/build_travis.py b/tools/build_travis.py index 0eb928f1d6..c3684fe0d3 100644 --- a/tools/build_travis.py +++ b/tools/build_travis.py @@ -149,15 +149,6 @@ build_list = [ ) }, - { - "MAXIM": - ( - { "target": "MAXWSNENV", "toolchains": "GCC_ARM", "libs": ["dsp"] }, - { "target": "MAX32600MBED", "toolchains": "GCC_ARM", "libs": ["dsp"] }, - { "target": "MAX32620HSP", "toolchains": "GCC_ARM", "libs": ["dsp"] }, - ) - }, - { "ATMEL": ( diff --git a/tools/targets/lint.py b/tools/targets/lint.py index 826bbb56b8..1c09bad995 100644 --- a/tools/targets/lint.py +++ b/tools/targets/lint.py @@ -79,7 +79,7 @@ def check_inherits(dict): DEVICE_HAS_ALLOWED = ["ANALOGIN", "ANALOGOUT", "CAN", "ETHERNET", "EMAC", "FLASH", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", - "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", + "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "TRNG","SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STORAGE", "STCLK_OFF_DURING_SLEEP"]