Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FXAS21002 FXOS8700Q
main.cpp
00001 /* 00002 * mbed Microcontroller Library 00003 * Copyright (c) 2006-2018 ARM Limited 00004 * 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); 00008 * you may not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, 00015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 */ 00019 00020 #include "mbed.h" 00021 #include "FATFileSystem.h" 00022 #include "LittleFileSystem.h" 00023 #include "simple-mbed-cloud-client.h" 00024 #include "greentea-client/test_env.h" 00025 #include "common_defines_test.h" 00026 00027 #ifndef MBED_CONF_APP_TESTS_FS_SIZE 00028 #define MBED_CONF_APP_TESTS_FS_SIZE (2*1024*1024) 00029 #endif 00030 00031 uint32_t test_timeout = 30*60; 00032 00033 #if !defined(MBED_CONF_APP_NO_LED) 00034 DigitalOut led1(LED1); 00035 DigitalOut led2(LED2); 00036 void led_thread() { 00037 led1 = !led1; 00038 led2 = !led1; 00039 } 00040 #endif 00041 RawSerial pc(USBTX, USBRX); 00042 00043 void wait_nb(uint16_t ms) { 00044 wait_ms(ms); 00045 } 00046 00047 void logger(const char* message, const char* decor) { 00048 wait_nb(10); 00049 pc.printf(message, decor); 00050 wait_nb(10); 00051 } 00052 void logger(const char* message) { 00053 wait_nb(10); 00054 pc.printf(message); 00055 wait_nb(10); 00056 } 00057 void test_failed() { 00058 greentea_send_kv("test_failed", 1); 00059 } 00060 void test_case_start(const char *name, size_t index) { 00061 wait_nb(10); 00062 pc.printf("\r\n>>> Running case #%u: '%s'...\n", index, name); 00063 GREENTEA_TESTCASE_START(name); 00064 } 00065 void test_case_finish(const char *name, size_t passed, size_t failed) { 00066 GREENTEA_TESTCASE_FINISH(name, passed, failed); 00067 wait_nb(10); 00068 pc.printf(">>> '%s': %u passed, %u failed\r\n", name, passed, failed); 00069 } 00070 00071 uint32_t dl_last_rpercent = 0; 00072 bool dl_started = false; 00073 Timer dl_timer; 00074 void update_progress(uint32_t progress, uint32_t total) { 00075 if (!dl_started) { 00076 dl_started = true; 00077 dl_timer.start(); 00078 pc.printf("[INFO] Firmware download started. Size: %.2fKB\r\n", float(total) / 1024); 00079 } else { 00080 float speed = float(progress) / dl_timer.read(); 00081 float percent = float(progress) * 100 / float(total); 00082 uint32_t time_left = (total - progress) / speed; 00083 pc.printf("[INFO] Downloading: %.2f%% (%.2fKB/s, ETA: %02d:%02d:%02d)\r\n", percent, speed / 1024, 00084 time_left / 3600, (time_left / 60) % 60, time_left % 60); 00085 00086 // // this is disabled until htrun is extended to support dynamic change of the duration of tests 00087 // // see https://github.com/ARMmbed/htrun/pull/228 00088 // // extend the timeout of the test based on current progress 00089 // uint32_t round_percent = progress * 100 / total; 00090 // if (round_percent != dl_last_rpercent) { 00091 // dl_last_rpercent = round_percent; 00092 // uint32_t new_timeout = test_timeout + int(dl_timer.read() * (round_percent + 1) / round_percent); 00093 // greentea_send_kv("__timeout_set", new_timeout); 00094 // } 00095 } 00096 00097 if (progress == total) { 00098 dl_timer.stop(); 00099 dl_started = false; 00100 pc.printf("[INFO] Firmware download completed. %.2fKB in %.2f seconds (%.2fKB/s)\r\n", 00101 float(total) / 1024, dl_timer.read(), float(total) / dl_timer.read() / 1024); 00102 test_case_finish("Pelion Firmware Download", 1, 0); 00103 test_case_start("Pelion Firmware Update", 9); 00104 } 00105 } 00106 00107 static const ConnectorClientEndpointInfo* endpointInfo; 00108 void registered(const ConnectorClientEndpointInfo *endpoint) { 00109 logger("[INFO] Connected to Pelion Device Management. Device ID: %s\n", 00110 endpoint->internal_endpoint_name.c_str()); 00111 endpointInfo = endpoint; 00112 } 00113 00114 void spdmc_testsuite_update(void) { 00115 int i = 0; 00116 int iteration = 0; 00117 char _key[20] = { }; 00118 char _value[128] = { }; 00119 00120 greentea_send_kv("spdmc_ready_chk", true); 00121 while (1) { 00122 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00123 00124 if (strcmp(_key, "iteration") == 0) { 00125 iteration = atoi(_value); 00126 break; 00127 } 00128 } 00129 00130 // provide manifest to greentea so it can correct show skipped and failed tests 00131 if (iteration == 0) { 00132 greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_COUNT, 10); 00133 greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Initialize " TEST_BLOCK_DEVICE_TYPE "+" TEST_FILESYSTEM_TYPE); 00134 greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Connect to " TEST_NETWORK_TYPE); 00135 greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Format " TEST_FILESYSTEM_TYPE); 00136 greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Initialize Simple PDMC"); 00137 greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Pelion Bootstrap & Reg."); 00138 greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Pelion Directory"); 00139 greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Pelion Firmware Prepare"); 00140 greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Pelion Firmware Download"); 00141 greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Pelion Firmware Update"); 00142 greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Pelion Re-register"); 00143 greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Post-update Erase"); 00144 greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Post-update Identity"); 00145 } else { 00146 test_case_finish("Pelion Firmware Update", true, false); 00147 } 00148 00149 test_case_start("Initialize " TEST_BLOCK_DEVICE_TYPE "+" TEST_FILESYSTEM_TYPE, 1); 00150 logger("[INFO] Attempting to initialize storage.\r\n"); 00151 00152 // Default storage definition. 00153 BlockDevice* bd = BlockDevice::get_default_instance(); 00154 SlicingBlockDevice sd(bd, 0, MBED_CONF_APP_TESTS_FS_SIZE); 00155 #if TEST_USE_FILESYSTEM == FS_FAT 00156 FATFileSystem fs("fs", &sd); 00157 #else 00158 LittleFileSystem fs("fs", &sd); 00159 #endif 00160 00161 test_case_finish("Initialize " TEST_BLOCK_DEVICE_TYPE "+" TEST_FILESYSTEM_TYPE, iteration + 1, 0); 00162 00163 // Corrupt the image after successful firmware update to ensure that the bootloader won't try to apply it for other test runs 00164 if (iteration) { 00165 #if defined(MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS) && defined(MBED_CONF_UPDATE_CLIENT_STORAGE_SIZE) 00166 test_case_start("Post-update Erase", 11); 00167 00168 int erase_status; 00169 if (bd->get_erase_value() >= 0) { 00170 // Blockdevice supports a straight erase 00171 erase_status = bd->erase(MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS, bd->get_erase_size(MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS)); 00172 } else { 00173 // Blockdevice supports an overwrite 00174 uint32_t garbage[8]; 00175 erase_status = bd->program(garbage, MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS, bd->get_program_size()); 00176 } 00177 if (erase_status != 0) { 00178 logger("[ERROR] Post-update image invalidation failed.\n"); 00179 } 00180 test_case_finish("Post-update Erase", (erase_status == 0), (erase_status != 0)); 00181 #endif 00182 } 00183 00184 // Start network connection test. 00185 test_case_start("Connect to " TEST_NETWORK_TYPE, 2); 00186 logger("[INFO] Attempting to connect to network.\r\n"); 00187 00188 // Connection definition. 00189 NetworkInterface *net = NetworkInterface::get_default_instance(); 00190 nsapi_error_t net_status = -1; 00191 for (int tries = 0; tries < 3; tries++) { 00192 net_status = net->connect(); 00193 if (net_status == NSAPI_ERROR_OK) { 00194 break; 00195 } else { 00196 logger("[WARN] Unable to connect to network. Retrying..."); 00197 } 00198 } 00199 00200 // Report status to console. 00201 if (net_status != 0) { 00202 logger("[ERROR] Device failed to connect to Network.\r\n"); 00203 test_failed(); 00204 } else { 00205 logger("[INFO] Connected to network successfully. IP address: %s\n", net->get_ip_address()); 00206 } 00207 00208 test_case_finish("Connect to " TEST_NETWORK_TYPE, iteration + (net_status == 0), (net_status != 0)); 00209 00210 if (iteration == 0) { 00211 test_case_start("Format " TEST_FILESYSTEM_TYPE, 3); 00212 logger("[INFO] Resetting storage to a clean state for test.\n"); 00213 00214 int storage_status = fs.reformat(&sd); 00215 if (storage_status != 0) { 00216 storage_status = sd.erase(0, sd.size()); 00217 if (storage_status == 0) { 00218 storage_status = fs.format(&sd); 00219 if (storage_status != 0) { 00220 logger("[ERROR] Filesystem init failed\n"); 00221 } 00222 } 00223 } 00224 00225 // Report status to console. 00226 if (storage_status == 0) { 00227 logger("[INFO] Storage format successful.\r\n"); 00228 } else { 00229 logger("[ERROR] Storage format failed.\r\n"); 00230 test_failed(); 00231 } 00232 00233 test_case_finish("Format " TEST_FILESYSTEM_TYPE, (storage_status == 0), (storage_status != 0)); 00234 } 00235 00236 // SimpleMbedCloudClient initialization must be successful. 00237 test_case_start("Initialize Simple PDMC", 4); 00238 00239 SimpleMbedCloudClient client(net, &sd, &fs); 00240 int client_status = client.init(); 00241 00242 // Report status to console. 00243 if (client_status == 0) { 00244 logger("[INFO] Simple PDMC initialization successful.\r\n"); 00245 } else { 00246 logger("[ERROR] Simple PDMC failed to initialize.\r\n"); 00247 // End the test early, cannot continue without successful cloud client initialization. 00248 test_failed(); 00249 } 00250 00251 test_case_finish("Initialize Simple PDMC", iteration + (client_status == 0), (client_status != 0)); 00252 00253 //Create LwM2M resources 00254 MbedCloudClientResource *res_get_test; 00255 res_get_test = client.create_resource("5000/0/1", "get_resource"); 00256 res_get_test->observable(true); 00257 res_get_test->methods(M2MMethod::GET); 00258 res_get_test->set_value("test0"); 00259 00260 // Register to Pelion Device Management. 00261 if (iteration == 0) { 00262 test_case_start("Pelion Bootstrap & Reg.", 5); 00263 } else { 00264 test_case_start("Pelion Re-register", 10); 00265 } 00266 // Set client callback to report endpoint name. 00267 client.on_registered(®istered); 00268 client.register_and_connect(); 00269 00270 i = 600; // wait 60 seconds 00271 while (i-- > 0 && !client.is_client_registered()) { 00272 wait_ms(100); 00273 } 00274 00275 // Get registration status. 00276 bool client_registered = client.is_client_registered(); 00277 if (client_registered) { 00278 client_status = 0; 00279 wait_nb(100); 00280 logger("[INFO] Device successfully registered to Pelion DM.\r\n"); 00281 } else { 00282 client_status = -1; 00283 logger("[ERROR] Device failed to register.\r\n"); 00284 test_failed(); 00285 } 00286 if (iteration == 0) { 00287 test_case_finish("Pelion Bootstrap & Reg.", (client_status == 0), (client_status != 0)); 00288 } else { 00289 test_case_finish("Pelion Re-register", (client_status == 0), (client_status != 0)); 00290 } 00291 00292 if (iteration == 0) { 00293 //Start registration status test 00294 test_case_start("Pelion Directory", 6); 00295 int reg_status; 00296 00297 logger("[INFO] Wait up to 10 seconds for Device Directory to update after initial registration.\r\n"); 00298 i = 100; 00299 while (i-- > 0 and !endpointInfo) { 00300 wait(100); 00301 } 00302 00303 // Start host tests with device id 00304 logger("[INFO] Starting Pelion verification using Python SDK...\r\n"); 00305 greentea_send_kv("verify_registration", endpointInfo->internal_endpoint_name.c_str()); 00306 while (1) { 00307 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00308 00309 if (strcmp(_key, "registered") == 0) { 00310 if (atoi(_value)) { 00311 reg_status = 0; 00312 logger("[INFO] Device is registered in the Device Directory.\r\n"); 00313 } else { 00314 reg_status = -1; 00315 logger("[ERROR] Device could not be verified as registered in Device Directory.\r\n"); 00316 test_failed(); 00317 } 00318 break; 00319 } 00320 } 00321 00322 test_case_finish("Pelion Directory", (reg_status == 0), (reg_status != 0)); 00323 00324 if (reg_status == 0) { 00325 test_case_start("Pelion Firmware Prepare", 7); 00326 wait_nb(500); 00327 int fw_status; 00328 greentea_send_kv("firmware_prepare", 1); 00329 while (1) { 00330 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00331 if (strcmp(_key, "firmware_sent") == 0) { 00332 if (atoi(_value)) { 00333 fw_status = 0; 00334 } else { 00335 fw_status = -1; 00336 logger("[ERROR] While preparing firmware.\r\n"); 00337 } 00338 break; 00339 } 00340 } 00341 test_case_finish("Pelion Firmware Prepare", (fw_status == 0), (fw_status != 0)); 00342 00343 test_case_start("Pelion Firmware Download", 8); 00344 logger("[INFO] Update campaign has started.\r\n"); 00345 // The device should download firmware and reset at this stage 00346 } 00347 00348 while (1) { 00349 wait_nb(1000); 00350 } 00351 } else { 00352 //Start consistent identity test. 00353 test_case_start("Post-update Identity", 12); 00354 int identity_status; 00355 00356 logger("[INFO] Wait up to 5 seconds for Device Directory to update after reboot.\r\n"); 00357 i = 50; 00358 while (i-- > 0 and !endpointInfo) { 00359 wait(100); 00360 } 00361 00362 // Wait for Host Test to verify consistent device ID (blocking here) 00363 logger("[INFO] Verifying consistent Device ID...\r\n"); 00364 greentea_send_kv("verify_identity", endpointInfo->internal_endpoint_name.c_str()); 00365 while (1) { 00366 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value)); 00367 00368 if (strcmp(_key, "verified") == 0) { 00369 if (atoi(_value)) { 00370 identity_status = 0; 00371 logger("[INFO] Device ID consistent, SOTP and Secure Storage is preserved correctly.\r\n"); 00372 } else { 00373 identity_status = -1; 00374 logger("[ERROR] Device ID is inconsistent. SOTP and Secure Storage was not preserved.\r\n"); 00375 } 00376 break; 00377 } 00378 } 00379 00380 test_case_finish("Post-update Identity", (identity_status == 0), (identity_status != 0)); 00381 00382 GREENTEA_TESTSUITE_RESULT(identity_status == 0); 00383 00384 while (1) { 00385 wait(100); 00386 } 00387 } 00388 } 00389 00390 int main(void) { 00391 //Create a thread to blink an LED and signal that the device is alive 00392 #if !defined(MBED_CONF_APP_NO_LED) 00393 Ticker t; 00394 t.attach(led_thread, 0.5); 00395 #endif 00396 00397 greentea_send_kv("device_booted", 1); 00398 00399 GREENTEA_SETUP(test_timeout, "sdk_host_tests"); 00400 spdmc_testsuite_update(); 00401 00402 return 0; 00403 }
Generated on Tue Jul 12 2022 20:21:01 by
