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.
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 Mon Aug 29 2022 19:53:40 by
