EL4121 Embedded System / mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2016 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #if !DEVICE_LOWPOWERTIMER
00018     #error [NOT_SUPPORTED] Low power timer not supported for this target
00019 #endif
00020 
00021 #include "utest/utest.h"
00022 #include "unity/unity.h"
00023 #include "greentea-client/test_env.h"
00024 
00025 #include "mbed.h"
00026 #include "lp_ticker_api.h"
00027 
00028 using namespace utest::v1;
00029 
00030 static volatile bool complete;
00031 static volatile timestamp_t complete_time;
00032 static ticker_event_t delay_event;
00033 static const ticker_data_t *lp_ticker_data = get_lp_ticker_data();
00034 static Timer timer;
00035 static LowPowerTimer lp_timer;
00036 
00037 /* Timeouts are quite arbitrary due to large number of boards with varying level of accuracy */
00038 #define LONG_TIMEOUT (100000)
00039 #define SHORT_TIMEOUT (600)
00040 
00041 void cb_done(uint32_t id) {
00042     if ((uint32_t)&delay_event == id) {
00043         complete_time = timer.read_us();
00044         complete = true;
00045     } else {
00046         // Normal ticker handling
00047         TimerEvent::irq(id);
00048     }
00049 }
00050 
00051 void cb_done_deepsleep(uint32_t id) {
00052     if ((uint32_t)&delay_event == id) {
00053         complete_time = lp_timer.read_us();
00054         complete = true;
00055     } else {
00056         // Normal ticker handling
00057         TimerEvent::irq(id);
00058     }
00059 }
00060 
00061 void lp_ticker_delay_us(uint32_t delay_us, uint32_t tolerance)
00062 {
00063     complete = false;
00064     uint32_t delay_ts;
00065 
00066     ticker_set_handler(lp_ticker_data, cb_done);
00067     ticker_remove_event(lp_ticker_data, &delay_event);
00068     delay_ts = ticker_read(lp_ticker_data) + delay_us;
00069 
00070     timer.reset();
00071     timer.start();
00072     ticker_insert_event(lp_ticker_data, &delay_event, delay_ts, (uint32_t)&delay_event);
00073     while (!complete);
00074     timer.stop();
00075 
00076     TEST_ASSERT_UINT32_WITHIN(tolerance, delay_us, complete_time);
00077     TEST_ASSERT_TRUE(complete);
00078 }
00079 
00080 #if DEVICE_SLEEP
00081 void lp_ticker_1s_deepsleep()
00082 {
00083     complete = false;
00084     uint32_t delay_ts;
00085 
00086     /*
00087      * Since deepsleep() may shut down the UART peripheral, we wait for 10ms
00088      * to allow for hardware serial buffers to completely flush.
00089 
00090      * This should be replaced with a better function that checks if the
00091      * hardware buffers are empty. However, such an API does not exist now,
00092      * so we'll use the wait_ms() function for now.
00093      */
00094     wait_ms(10);
00095 
00096     ticker_set_handler(lp_ticker_data, cb_done_deepsleep);
00097     ticker_remove_event(lp_ticker_data, &delay_event);
00098     delay_ts = ticker_read(lp_ticker_data) + 1000000;
00099 
00100     /*
00101      * We use here the low power timer instead of microsecond timer for start and
00102      * end because the microseconds timer might be disable during deepsleep.
00103      */
00104     lp_timer.reset();
00105     lp_timer.start();
00106     ticker_insert_event(lp_ticker_data, &delay_event, delay_ts, (uint32_t)&delay_event);
00107     /* Make sure deepsleep is allowed, to go to deepsleep */
00108     bool deep_sleep_allowed = sleep_manager_can_deep_sleep();
00109     TEST_ASSERT_TRUE_MESSAGE(deep_sleep_allowed, "Deep sleep should be allowed");
00110     sleep();
00111     while (!complete);
00112     lp_timer.stop();
00113 
00114     TEST_ASSERT_UINT32_WITHIN(LONG_TIMEOUT, 1000000, complete_time);
00115     TEST_ASSERT_TRUE(complete);
00116 }
00117 
00118 void lp_ticker_1s_sleep()
00119 {
00120     complete = false;
00121     uint32_t delay_ts;
00122 
00123     ticker_set_handler(lp_ticker_data, cb_done);
00124     ticker_remove_event(lp_ticker_data, &delay_event);
00125     delay_ts = ticker_read(lp_ticker_data) + 1000000;
00126 
00127     sleep_manager_lock_deep_sleep();
00128     timer.reset();
00129     timer.start();
00130     bool deep_sleep_allowed = sleep_manager_can_deep_sleep();
00131     TEST_ASSERT_FALSE_MESSAGE(deep_sleep_allowed, "Deep sleep should be disallowed");
00132     ticker_insert_event(lp_ticker_data, &delay_event, delay_ts, (uint32_t)&delay_event);
00133     sleep();
00134     while (!complete);
00135     timer.stop();
00136     sleep_manager_unlock_deep_sleep();
00137 
00138     TEST_ASSERT_UINT32_WITHIN(LONG_TIMEOUT, 1000000, complete_time);
00139     TEST_ASSERT_TRUE(complete);
00140 }
00141 #endif /* DEVICE_SLEEP */
00142 
00143 void lp_ticker_500us(void)
00144 {
00145     lp_ticker_delay_us(500, SHORT_TIMEOUT);
00146 }
00147 
00148 void lp_ticker_1ms(void)
00149 {
00150     lp_ticker_delay_us(1000, SHORT_TIMEOUT);
00151 }
00152 
00153 void lp_ticker_1s(void)
00154 {
00155     lp_ticker_delay_us(1000000, LONG_TIMEOUT);
00156 }
00157 
00158 void lp_ticker_5s(void)
00159 {
00160     lp_ticker_delay_us(5000000, LONG_TIMEOUT);
00161 }
00162 
00163 utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) {
00164     greentea_case_failure_abort_handler(source, reason);
00165     return STATUS_CONTINUE;
00166 }
00167 
00168 Case cases[] = {
00169     Case("500us lp_ticker", lp_ticker_500us, greentea_failure_handler),
00170     Case("1ms lp_ticker", lp_ticker_1ms, greentea_failure_handler),
00171     Case("1s lp_ticker", lp_ticker_1s, greentea_failure_handler),
00172     Case("5s lp_ticker", lp_ticker_5s, greentea_failure_handler),
00173 #if DEVICE_SLEEP
00174     Case("1s lp_ticker sleep", lp_ticker_1s_sleep, greentea_failure_handler),
00175     Case("1s lp_ticker deepsleep", lp_ticker_1s_deepsleep, greentea_failure_handler),
00176 #endif /* DEVICE_SLEEP */
00177 };
00178 
00179 utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
00180     GREENTEA_SETUP(20, "default_auto");
00181     lp_ticker_data->interface->init();
00182     return greentea_test_setup_handler(number_of_cases);
00183 }
00184 
00185 Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
00186 
00187 int main() {
00188     Harness::run(specification);
00189 }