Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 /* 00002 * Copyright (c) 2013-2017, ARM Limited, All Rights Reserved 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00006 * not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #ifndef MBED_CONF_APP_CONNECT_STATEMENT 00019 #error [NOT_SUPPORTED] No network configuration found for this target. 00020 #endif 00021 00022 #ifndef MBED_EXTENDED_TESTS 00023 #error [NOT_SUPPORTED] Pressure tests are not supported by default 00024 #endif 00025 00026 #include "mbed.h" 00027 #include MBED_CONF_APP_HEADER_FILE 00028 #include "UDPSocket.h" 00029 #include "greentea-client/test_env.h" 00030 #include "unity/unity.h" 00031 #include "utest.h" 00032 00033 using namespace utest::v1; 00034 00035 00036 #ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN 00037 #define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN 64 00038 #endif 00039 00040 #ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX 00041 #define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000 00042 #endif 00043 00044 #ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 00045 #define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100 00046 #endif 00047 00048 #ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED 00049 #define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 00050 #endif 00051 00052 #ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG 00053 #define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG false 00054 #endif 00055 00056 #define STRINGIZE(x) STRINGIZE2(x) 00057 #define STRINGIZE2(x) #x 00058 00059 00060 // Simple xorshift pseudorandom number generator 00061 class RandSeq { 00062 private: 00063 uint32_t x; 00064 uint32_t y; 00065 static const int A = 15; 00066 static const int B = 18; 00067 static const int C = 11; 00068 00069 public: 00070 RandSeq(uint32_t seed=MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED) 00071 : x(seed), y(seed) {} 00072 00073 uint32_t next(void) { 00074 x ^= x << A; 00075 x ^= x >> B; 00076 x ^= y ^ (y >> C); 00077 return x + y; 00078 } 00079 00080 void skip(size_t size) { 00081 for (size_t i = 0; i < size; i++) { 00082 next(); 00083 } 00084 } 00085 00086 void buffer(uint8_t *buffer, size_t size) { 00087 RandSeq lookahead = *this; 00088 00089 for (size_t i = 0; i < size; i++) { 00090 buffer[i] = lookahead.next() & 0xff; 00091 } 00092 } 00093 00094 int cmp(uint8_t *buffer, size_t size) { 00095 RandSeq lookahead = *this; 00096 00097 for (size_t i = 0; i < size; i++) { 00098 int diff = buffer[i] - (lookahead.next() & 0xff); 00099 if (diff != 0) { 00100 return diff; 00101 } 00102 } 00103 return 0; 00104 } 00105 }; 00106 00107 // Shared buffer for network transactions 00108 uint8_t *buffer; 00109 size_t buffer_size; 00110 00111 // Tries to get the biggest buffer possible on the device. Exponentially 00112 // grows a buffer until heap runs out of space, and uses half to leave 00113 // space for the rest of the program 00114 void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { 00115 size_t i = min; 00116 while (i < max) { 00117 void *b = malloc(i); 00118 if (!b) { 00119 i /= 4; 00120 if (i < min) { 00121 i = min; 00122 } 00123 break; 00124 } 00125 free(b); 00126 i *= 2; 00127 } 00128 00129 *buffer = (uint8_t *)malloc(i); 00130 *size = i; 00131 TEST_ASSERT(buffer); 00132 } 00133 00134 void test_udp_packet_pressure() { 00135 generate_buffer(&buffer, &buffer_size, 00136 MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN, 00137 MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX); 00138 printf("MBED: Generated buffer %d\r\n", buffer_size); 00139 00140 NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION; 00141 int err = MBED_CONF_APP_CONNECT_STATEMENT; 00142 TEST_ASSERT_EQUAL(0, err); 00143 00144 printf("MBED: UDPClient IP address is '%s'\n", net->get_ip_address()); 00145 00146 UDPSocket sock; 00147 SocketAddress udp_addr(MBED_CONF_APP_ECHO_SERVER_ADDR, MBED_CONF_APP_ECHO_SERVER_PORT); 00148 00149 Timer timer; 00150 timer.start(); 00151 00152 // Tests exponentially growing sequences 00153 for (size_t size = MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; 00154 size < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX; 00155 size *= 2) { 00156 err = sock.open(net); 00157 TEST_ASSERT_EQUAL(0, err); 00158 printf("UDP: %s:%d streaming %d bytes\r\n", 00159 udp_addr.get_ip_address(), udp_addr.get_port(), size); 00160 00161 sock.set_blocking(false); 00162 00163 // Loop to send/recv all data 00164 RandSeq tx_seq; 00165 RandSeq rx_seq; 00166 size_t rx_count = 0; 00167 size_t tx_count = 0; 00168 int known_time = timer.read_ms(); 00169 size_t window = buffer_size; 00170 00171 while (tx_count < size || rx_count < size) { 00172 // Send out packets 00173 if (tx_count < size) { 00174 size_t chunk_size = size - tx_count; 00175 if (chunk_size > window) { 00176 chunk_size = window; 00177 } 00178 00179 tx_seq.buffer(buffer, chunk_size); 00180 int td = sock.sendto(udp_addr, buffer, chunk_size); 00181 00182 if (td > 0) { 00183 if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { 00184 printf("UDP: tx -> %d\r\n", td); 00185 } 00186 tx_seq.skip(td); 00187 tx_count += td; 00188 } else if (td != NSAPI_ERROR_WOULD_BLOCK ) { 00189 // We may fail to send because of buffering issues, revert to 00190 // last good sequence and cut buffer in half 00191 if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { 00192 window /= 2; 00193 } 00194 00195 if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { 00196 printf("UDP: Not sent (%d), window = %d\r\n", td, window); 00197 } 00198 } 00199 } 00200 00201 // Prioritize recieving over sending packets to avoid flooding 00202 // the network while handling erronous packets 00203 while (rx_count < size) { 00204 int rd = sock.recvfrom(NULL, buffer, buffer_size); 00205 TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK ); 00206 00207 if (rd > 0) { 00208 if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { 00209 printf("UDP: rx <- %d\r\n", rd); 00210 } 00211 00212 if (rx_seq.cmp(buffer, rd) == 0) { 00213 rx_seq.skip(rd); 00214 rx_count += rd; 00215 known_time = timer.read_ms(); 00216 if (window < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX) { 00217 window += MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; 00218 } 00219 } 00220 } else if (timer.read_ms() - known_time > 00221 MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT) { 00222 // Dropped packet or out of order, revert to last good sequence 00223 // and cut buffer in half 00224 tx_seq = rx_seq; 00225 tx_count = rx_count; 00226 known_time = timer.read_ms(); 00227 if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { 00228 window /= 2; 00229 } 00230 00231 if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { 00232 printf("UDP: Dropped, window = %d\r\n", window); 00233 } 00234 } else if (rd == NSAPI_ERROR_WOULD_BLOCK ) { 00235 break; 00236 } 00237 } 00238 } 00239 00240 err = sock.close(); 00241 TEST_ASSERT_EQUAL(0, err); 00242 } 00243 00244 timer.stop(); 00245 printf("MBED: Time taken: %fs\r\n", timer.read()); 00246 printf("MBED: Speed: %.3fkb/s\r\n", 00247 8*(2*MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX - 00248 MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); 00249 00250 net->disconnect(); 00251 } 00252 00253 00254 // Test setup 00255 utest::v1::status_t test_setup(const size_t number_of_cases) { 00256 GREENTEA_SETUP(120, "udp_echo"); 00257 return verbose_test_setup_handler(number_of_cases); 00258 } 00259 00260 Case cases[] = { 00261 Case("UDP packet pressure", test_udp_packet_pressure), 00262 }; 00263 00264 Specification specification(test_setup, cases); 00265 00266 int main() { 00267 return !Harness::run(specification); 00268 }
Generated on Sun Jul 17 2022 08:25:27 by 1.7.2