![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
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] Parallel pressure tests are not supported by default 00024 #endif 00025 00026 #include "mbed.h" 00027 #include MBED_CONF_APP_HEADER_FILE 00028 #include "TCPSocket.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_TCP_CLIENT_PACKET_PRESSURE_MIN 00037 #define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN 64 00038 #endif 00039 00040 #ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX 00041 #define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX 0x80000 00042 #endif 00043 00044 #ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED 00045 #define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 00046 #endif 00047 00048 #ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS 00049 #define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS 3 00050 #endif 00051 00052 #ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG 00053 #define MBED_CFG_TCP_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_TCP_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 00108 // Tries to get the biggest buffer possible on the device. Exponentially 00109 // grows a buffer until heap runs out of space, and uses half to leave 00110 // space for the rest of the program 00111 void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { 00112 size_t i = min; 00113 while (i < max) { 00114 void *b = malloc(i); 00115 if (!b) { 00116 i /= 4; 00117 if (i < min) { 00118 i = min; 00119 } 00120 break; 00121 } 00122 free(b); 00123 i *= 2; 00124 } 00125 00126 *buffer = (uint8_t *)malloc(i); 00127 *size = i; 00128 TEST_ASSERT(buffer); 00129 } 00130 00131 00132 // Global variables shared between pressure tests 00133 NetworkInterface* net; 00134 SocketAddress tcp_addr; 00135 Timer timer; 00136 Mutex iomutex; 00137 00138 // Single instance of a pressure test 00139 class PressureTest { 00140 private: 00141 uint8_t *buffer; 00142 size_t buffer_size; 00143 00144 TCPSocket sock; 00145 Thread thread; 00146 00147 public: 00148 PressureTest(uint8_t *buffer, size_t buffer_size) 00149 : buffer(buffer), buffer_size(buffer_size) { 00150 } 00151 00152 void start() { 00153 osStatus status = thread.start(callback(this, &PressureTest::run)); 00154 TEST_ASSERT_EQUAL(osOK, status); 00155 } 00156 00157 void join() { 00158 osStatus status = thread.join(); 00159 TEST_ASSERT_EQUAL(osOK, status); 00160 } 00161 00162 void run() { 00163 // Tests exponentially growing sequences 00164 for (size_t size = MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN; 00165 size < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX; 00166 size *= 2) { 00167 int err = sock.open(net); 00168 TEST_ASSERT_EQUAL(0, err); 00169 err = sock.connect(tcp_addr); 00170 TEST_ASSERT_EQUAL(0, err); 00171 sock.recv(buffer, sizeof(MBED_CONF_APP_TCP_ECHO_PREFIX)); 00172 00173 iomutex.lock(); 00174 printf("TCP: %s:%d streaming %d bytes\r\n", 00175 tcp_addr.get_ip_address(), tcp_addr.get_port(), size); 00176 iomutex.unlock(); 00177 00178 sock.set_blocking(false); 00179 00180 // Loop to send/recv all data 00181 RandSeq tx_seq; 00182 RandSeq rx_seq; 00183 size_t rx_count = 0; 00184 size_t tx_count = 0; 00185 size_t window = buffer_size; 00186 00187 while (tx_count < size || rx_count < size) { 00188 // Send out data 00189 if (tx_count < size) { 00190 size_t chunk_size = size - tx_count; 00191 if (chunk_size > window) { 00192 chunk_size = window; 00193 } 00194 00195 tx_seq.buffer(buffer, chunk_size); 00196 int td = sock.send(buffer, chunk_size); 00197 00198 if (td > 0) { 00199 if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { 00200 iomutex.lock(); 00201 printf("TCP: tx -> %d\r\n", td); 00202 iomutex.unlock(); 00203 } 00204 tx_seq.skip(td); 00205 tx_count += td; 00206 } else if (td != NSAPI_ERROR_WOULD_BLOCK ) { 00207 // We may fail to send because of buffering issues, 00208 // cut buffer in half 00209 if (window > MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) { 00210 window /= 2; 00211 } 00212 00213 if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { 00214 iomutex.lock(); 00215 printf("TCP: Not sent (%d), window = %d\r\n", td, window); 00216 iomutex.unlock(); 00217 } 00218 } 00219 } 00220 00221 // Verify recieved data 00222 while (rx_count < size) { 00223 int rd = sock.recv(buffer, buffer_size); 00224 TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK ); 00225 if (rd > 0) { 00226 if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { 00227 iomutex.lock(); 00228 printf("TCP: rx <- %d\r\n", rd); 00229 iomutex.unlock(); 00230 } 00231 int diff = rx_seq.cmp(buffer, rd); 00232 TEST_ASSERT_EQUAL(0, diff); 00233 rx_seq.skip(rd); 00234 rx_count += rd; 00235 } else if (rd == NSAPI_ERROR_WOULD_BLOCK ) { 00236 break; 00237 } 00238 } 00239 } 00240 00241 err = sock.close(); 00242 TEST_ASSERT_EQUAL(0, err); 00243 } 00244 } 00245 }; 00246 00247 PressureTest *pressure_tests[MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS]; 00248 00249 00250 void test_tcp_packet_pressure_parallel() { 00251 uint8_t *buffer; 00252 size_t buffer_size; 00253 generate_buffer(&buffer, &buffer_size, 00254 MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN, 00255 MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX); 00256 00257 size_t buffer_subsize = buffer_size / MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; 00258 printf("MBED: Generated buffer %d\r\n", buffer_size); 00259 printf("MBED: Split into %d buffers %d\r\n", 00260 MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS, 00261 buffer_subsize); 00262 00263 net = MBED_CONF_APP_OBJECT_CONSTRUCTION; 00264 int err = MBED_CONF_APP_CONNECT_STATEMENT; 00265 TEST_ASSERT_EQUAL(0, err); 00266 00267 printf("MBED: TCPClient IP address is '%s'\n", net->get_ip_address()); 00268 00269 tcp_addr.set_ip_address(MBED_CONF_APP_ECHO_SERVER_ADDR); 00270 tcp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT); 00271 00272 timer.start(); 00273 00274 // Startup pressure tests in parallel 00275 for (int i = 0; i < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) { 00276 pressure_tests[i] = new PressureTest(&buffer[i*buffer_subsize], buffer_subsize); 00277 pressure_tests[i]->start(); 00278 } 00279 00280 for (int i = 0; i < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) { 00281 pressure_tests[i]->join(); 00282 delete pressure_tests[i]; 00283 } 00284 00285 timer.stop(); 00286 printf("MBED: Time taken: %fs\r\n", timer.read()); 00287 printf("MBED: Speed: %.3fkb/s\r\n", 00288 MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS* 00289 8*(2*MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX - 00290 MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); 00291 00292 net->disconnect(); 00293 } 00294 00295 00296 // Test setup 00297 utest::v1::status_t test_setup(const size_t number_of_cases) { 00298 GREENTEA_SETUP(120, "tcp_echo"); 00299 return verbose_test_setup_handler(number_of_cases); 00300 } 00301 00302 Case cases[] = { 00303 Case("TCP packet pressure parallel", test_tcp_packet_pressure_parallel), 00304 }; 00305 00306 Specification specification(test_setup, cases); 00307 00308 int main() { 00309 return !Harness::run(specification); 00310 }
Generated on Sun Jul 17 2022 08:25:27 by
![doxygen](doxygen.png)