Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2017 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 !MODEM_ON_BOARD 00018 #error [NOT_SUPPORTED] MODEM_ON_BOARD should be set for this test to be functional 00019 #endif 00020 00021 #include "mbed.h" 00022 #include "gmd_ut_config_header.h" 00023 #include "greentea-client/test_env.h" 00024 #include "unity.h" 00025 #include "utest.h" 00026 //Add your driver's header file here 00027 #include "OnboardCellularInterface.h" 00028 #include "UDPSocket.h" 00029 #include "TCPSocket.h" 00030 #if defined(FEATURE_COMMON_PAL) 00031 #include "mbed_trace.h" 00032 #define TRACE_GROUP "TEST" 00033 #else 00034 #define tr_debug(...) (void(0)) //dummies if feature common pal is not added 00035 #define tr_info(...) (void(0)) //dummies if feature common pal is not added 00036 #define tr_error(...) (void(0)) //dummies if feature common pal is not added 00037 #endif //defined(FEATURE_COMMON_PAL) 00038 00039 using namespace utest::v1; 00040 00041 #if !defined(MBED_CONF_APP_DEFAULT_PIN) 00042 #error [NOT_SUPPORTED] A json configuration file is needed. Skipping this build. 00043 #endif 00044 00045 /** How to run port verification tests 00046 * 00047 * i) Copy this file in your implementation directory 00048 * e.g., netsocket/cellular/YOUR_IMPLEMENTATION/TESTS/unit_tests/default/ 00049 * ii) Rename OnboardCellularInterface everywhere in this file with your Class 00050 * iii) Make an empty test application with the fork of mbed-os where your implementation resides 00051 * iv) Create a json file in the root directory of your application and copy the contents of 00052 * template_mbed_app.txt into it 00053 * v) Now from the root of your application, enter this command: 00054 * mbed test --compile-list 00055 * Look for the name of of your test suite matching to the directory path 00056 * vi) Run tests with the command: 00057 * mbed test -n YOUR_TEST_SUITE_NAME 00058 * 00059 * For more information on mbed-greentea testing suite, please visit: 00060 * https://docs.mbed.com/docs/mbed-os-handbook/en/latest/advanced/greentea/ 00061 */ 00062 00063 // Lock for debug prints 00064 static Mutex mtx; 00065 00066 // An instance of the cellular driver 00067 // change this with the name of your driver 00068 static OnboardCellularInterface driver(true); 00069 00070 // Test data 00071 static const char test_data[] = TEST_DATA; 00072 00073 //Private Function prototypes 00074 static nsapi_error_t do_connect(OnboardCellularInterface *iface); 00075 static int fix(int size, int limit); 00076 static void do_udp_echo(UDPSocket *sock, SocketAddress *host_address, int size); 00077 static int send_all(TCPSocket *sock, const char *data, int size); 00078 static void async_cb(bool *callback_triggered); 00079 static void do_tcp_echo_async(TCPSocket *sock, int size, bool *callback_triggered); 00080 static void use_connection(OnboardCellularInterface *driver); 00081 static void drop_connection(OnboardCellularInterface *driver); 00082 static void lock(); 00083 static void unlock(); 00084 00085 /* 00086 * Verification tests for a successful porting 00087 * These tests must pass: 00088 * 00089 * test_udp_echo() 00090 * test_tcp_echo_async 00091 * test_connect_credentials 00092 * test_connect_preset_credentials 00093 */ 00094 00095 /** 00096 * Test UDP data exchange 00097 */ 00098 void test_udp_echo() 00099 { 00100 UDPSocket sock; 00101 SocketAddress host_address; 00102 int x; 00103 int size; 00104 00105 driver.disconnect(); 00106 TEST_ASSERT(do_connect(&driver) == 0); 00107 00108 TEST_ASSERT(driver.gethostbyname(MBED_CONF_APP_ECHO_SERVER, &host_address) == 0); 00109 host_address.set_port(MBED_CONF_APP_ECHO_UDP_PORT); 00110 00111 tr_debug("UDP: Server %s address: %s on port %d.", 00112 MBED_CONF_APP_ECHO_SERVER, host_address.get_ip_address(), 00113 host_address.get_port()); 00114 00115 TEST_ASSERT(sock.open(&driver) == 0) 00116 00117 sock.set_timeout(10000); 00118 00119 // Test min, max, and some random sizes in-between 00120 do_udp_echo(&sock, &host_address, 1); 00121 do_udp_echo(&sock, &host_address, MBED_CONF_APP_UDP_MAX_PACKET_SIZE); 00122 for (x = 0; x < 10; x++) { 00123 size = (rand() % MBED_CONF_APP_UDP_MAX_PACKET_SIZE) + 1; 00124 size = fix(size, MBED_CONF_APP_UDP_MAX_PACKET_SIZE + 1); 00125 do_udp_echo(&sock, &host_address, size); 00126 } 00127 00128 sock.close(); 00129 00130 drop_connection(&driver); 00131 00132 tr_debug("%d UDP packets of size up to %d byte(s) echoed successfully.", x, 00133 MBED_CONF_APP_UDP_MAX_PACKET_SIZE); 00134 } 00135 00136 /** 00137 * Test TCP data exchange via the asynchronous sigio() mechanism 00138 */ 00139 void test_tcp_echo_async() 00140 { 00141 TCPSocket sock; 00142 SocketAddress host_address; 00143 bool callback_triggered = false; 00144 int x; 00145 int size; 00146 00147 driver.disconnect(); 00148 TEST_ASSERT(do_connect(&driver) == 0); 00149 00150 TEST_ASSERT( 00151 driver.gethostbyname(MBED_CONF_APP_ECHO_SERVER, &host_address) == 0); 00152 host_address.set_port(MBED_CONF_APP_ECHO_TCP_PORT); 00153 00154 tr_debug("TCP: Server %s address: %s on port %d.", 00155 MBED_CONF_APP_ECHO_SERVER, host_address.get_ip_address(), 00156 host_address.get_port()); 00157 00158 TEST_ASSERT(sock.open(&driver) == 0) 00159 00160 // Set up the async callback and set the timeout to zero 00161 sock.sigio(callback(async_cb, &callback_triggered)); 00162 sock.set_timeout(0); 00163 00164 TEST_ASSERT(sock.connect(host_address) == 0); 00165 // Test min, max, and some random sizes in-between 00166 do_tcp_echo_async(&sock, 1, &callback_triggered); 00167 do_tcp_echo_async(&sock, MBED_CONF_APP_TCP_MAX_PACKET_SIZE, 00168 &callback_triggered); 00169 00170 sock.close(); 00171 00172 drop_connection(&driver); 00173 00174 tr_debug("TCP packets of size up to %d byte(s) echoed asynchronously and successfully.", 00175 MBED_CONF_APP_TCP_MAX_PACKET_SIZE); 00176 } 00177 00178 /** 00179 * Connect with credentials included in the connect request 00180 */ 00181 void test_connect_credentials() 00182 { 00183 00184 driver.disconnect(); 00185 00186 TEST_ASSERT(do_connect(&driver) == 0); 00187 use_connection(&driver); 00188 drop_connection(&driver); 00189 } 00190 00191 /** 00192 * Test with credentials preset 00193 */ 00194 void test_connect_preset_credentials() 00195 { 00196 driver.disconnect(); 00197 driver.set_sim_pin(MBED_CONF_APP_DEFAULT_PIN); 00198 driver.set_credentials(MBED_CONF_APP_APN, MBED_CONF_APP_USERNAME, 00199 MBED_CONF_APP_PASSWORD); 00200 int num_retries = 0; 00201 nsapi_error_t err = NSAPI_ERROR_OK ; 00202 while (!driver.is_connected()) { 00203 err = driver.connect(); 00204 if (err == NSAPI_ERROR_OK || num_retries > MBED_CONF_APP_MAX_RETRIES) { 00205 break; 00206 } 00207 } 00208 00209 TEST_ASSERT(err == 0); 00210 use_connection(&driver); 00211 drop_connection(&driver); 00212 } 00213 00214 /** 00215 * Setup Test Environment 00216 */ 00217 utest::v1::status_t test_setup(const size_t number_of_cases) 00218 { 00219 // Setup Greentea with a timeout 00220 GREENTEA_SETUP(600, "default_auto"); 00221 return verbose_test_setup_handler(number_of_cases); 00222 } 00223 00224 /** 00225 * Array defining test cases 00226 */ 00227 Case cases[] = { Case("UDP echo test", test_udp_echo), 00228 #if MBED_CONF_LWIP_TCP_ENABLED 00229 Case("TCP async echo test", test_tcp_echo_async), 00230 #endif 00231 Case("Connect with credentials", test_connect_credentials), 00232 Case("Connect with preset credentials", test_connect_preset_credentials) }; 00233 00234 Specification specification(test_setup, cases); 00235 00236 /** 00237 * main test harness 00238 */ 00239 int main() 00240 { 00241 mbed_trace_init(); 00242 00243 mbed_trace_mutex_wait_function_set(lock); 00244 mbed_trace_mutex_release_function_set(unlock); 00245 00246 // Run tests 00247 return !Harness::run(specification); 00248 } 00249 /** 00250 * connect to the network 00251 */ 00252 static nsapi_error_t do_connect(OnboardCellularInterface *iface) 00253 { 00254 int num_retries = 0; 00255 nsapi_error_t err = NSAPI_ERROR_OK ; 00256 while (!iface->is_connected()) { 00257 err = driver.connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 00258 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD); 00259 if (err == NSAPI_ERROR_OK || num_retries > MBED_CONF_APP_MAX_RETRIES) { 00260 break; 00261 } 00262 num_retries++; 00263 } 00264 00265 return err; 00266 } 00267 00268 /** 00269 * Get a random size for the test packet 00270 */ 00271 static int fix(int size, int limit) 00272 { 00273 if (size <= 0) { 00274 size = limit / 2; 00275 } else if (size > limit) { 00276 size = limit; 00277 } 00278 return size; 00279 } 00280 00281 /** 00282 * Do a UDP socket echo test to a given host of a given packet size 00283 */ 00284 static void do_udp_echo(UDPSocket *sock, SocketAddress *host_address, int size) 00285 { 00286 bool success = false; 00287 void * recv_data = malloc(size); 00288 TEST_ASSERT(recv_data != NULL); 00289 00290 // Retry this a few times, don't want to fail due to a flaky link 00291 for (int x = 0; !success && (x < NUM_UDP_RETRIES); x++) { 00292 tr_debug("Echo testing UDP packet size %d byte(s), try %d.", size, x + 1); 00293 if ((sock->sendto(*host_address, (void*) test_data, size) == size) 00294 && (sock->recvfrom(host_address, recv_data, size) == size)) { 00295 TEST_ASSERT(memcmp(test_data, recv_data, size) == 0); 00296 success = true; 00297 } 00298 } 00299 TEST_ASSERT(success); 00300 00301 free(recv_data); 00302 } 00303 00304 /** 00305 * Send an entire TCP data buffer until done 00306 */ 00307 static int send_all(TCPSocket *sock, const char *data, int size) 00308 { 00309 int x; 00310 int count = 0; 00311 Timer timer; 00312 00313 timer.start(); 00314 while ((count < size) && (timer.read_ms() < ASYNC_TEST_WAIT_TIME)) { 00315 x = sock->send(data + count, size - count); 00316 if (x > 0) { 00317 count += x; 00318 tr_debug("%d byte(s) sent, %d left to send.", count, size - count); 00319 } 00320 wait_ms(10); 00321 } 00322 timer.stop(); 00323 00324 return count; 00325 } 00326 00327 /** 00328 * The asynchronous callback 00329 */ 00330 static void async_cb(bool *callback_triggered) 00331 { 00332 00333 TEST_ASSERT(callback_triggered != NULL); 00334 *callback_triggered = true; 00335 } 00336 00337 /** 00338 * Do a TCP echo using the asynchronous driver 00339 */ 00340 static void do_tcp_echo_async(TCPSocket *sock, int size, 00341 bool *callback_triggered) 00342 { 00343 void * recv_data = malloc(size); 00344 int recv_size = 0; 00345 int remaining_size; 00346 int x, y; 00347 Timer timer; 00348 TEST_ASSERT(recv_data != NULL); 00349 00350 *callback_triggered = false; 00351 tr_debug("Echo testing TCP packet size %d byte(s) async.", size); 00352 TEST_ASSERT(send_all(sock, test_data, size) == size); 00353 // Wait for all the echoed data to arrive 00354 timer.start(); 00355 remaining_size = size; 00356 while ((recv_size < size) && (timer.read_ms() < ASYNC_TEST_WAIT_TIME)) { 00357 if (*callback_triggered) { 00358 *callback_triggered = false; 00359 x = sock->recv((char *) recv_data + recv_size, remaining_size); 00360 if (x > 0) { 00361 recv_size += x; 00362 remaining_size = size - recv_size; 00363 tr_debug("%d byte(s) echoed back so far, %d to go.", recv_size, 00364 remaining_size); 00365 } 00366 } 00367 wait_ms(10); 00368 } 00369 TEST_ASSERT(recv_size == size); 00370 y = memcmp(test_data, recv_data, size); 00371 if (y != 0) { 00372 tr_debug("Sent %d, |%*.*s|", size, size, size, test_data); 00373 tr_debug("Rcvd %d, |%*.*s|", size, size, size, (char * ) recv_data); 00374 // We do not assert a failure here because ublox TCP echo server doesn't send 00375 // back original data. It actually constructs a ublox message string. They need to fix it as 00376 // at the minute in case of TCP, their server is not behaving like a echo TCP server. 00377 //TEST_ASSERT(false); 00378 } 00379 timer.stop(); 00380 free(recv_data); 00381 } 00382 00383 /** 00384 * Use a connection, checking that it is good 00385 * Checks via doing an NTP transaction 00386 */ 00387 static void use_connection(OnboardCellularInterface *driver) 00388 { 00389 const char * ip_address = driver->get_ip_address(); 00390 const char * net_mask = driver->get_netmask(); 00391 const char * gateway = driver->get_gateway(); 00392 00393 TEST_ASSERT(driver->is_connected()); 00394 00395 TEST_ASSERT(ip_address != NULL); 00396 tr_debug("IP address %s.", ip_address); 00397 TEST_ASSERT(net_mask != NULL); 00398 tr_debug("Net mask %s.", net_mask); 00399 TEST_ASSERT(gateway != NULL); 00400 tr_debug("Gateway %s.", gateway); 00401 00402 UDPSocket sock; 00403 SocketAddress host_address; 00404 00405 TEST_ASSERT(driver->gethostbyname(MBED_CONF_APP_ECHO_SERVER, &host_address) == 0); 00406 host_address.set_port(MBED_CONF_APP_ECHO_UDP_PORT); 00407 00408 tr_debug("UDP: Server %s address: %s on port %d.", 00409 MBED_CONF_APP_ECHO_SERVER, host_address.get_ip_address(), 00410 host_address.get_port()); 00411 00412 TEST_ASSERT(sock.open(driver) == 0) 00413 00414 sock.set_timeout(10000); 00415 do_udp_echo(&sock, &host_address, 1); 00416 00417 sock.close(); 00418 } 00419 00420 /** 00421 * Drop a connection and check that it has dropped 00422 */ 00423 static void drop_connection(OnboardCellularInterface *driver) 00424 { 00425 TEST_ASSERT(driver->disconnect() == 0); 00426 TEST_ASSERT(!driver->is_connected()); 00427 } 00428 00429 /** 00430 * Locks for debug prints 00431 */ 00432 static void lock() 00433 { 00434 mtx.lock(); 00435 } 00436 00437 static void unlock() 00438 { 00439 mtx.unlock(); 00440 }
Generated on Sun Jul 17 2022 08:25:26 by 1.7.2