EL4121 Embedded System / mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 "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_DEBUG
00049 #define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG false
00050 #endif
00051 
00052 #define STRINGIZE(x) STRINGIZE2(x)
00053 #define STRINGIZE2(x) #x
00054 
00055 
00056 // Simple xorshift pseudorandom number generator
00057 class RandSeq {
00058 private:
00059     uint32_t x;
00060     uint32_t y;
00061     static const int A = 15;
00062     static const int B = 18;
00063     static const int C = 11;
00064 
00065 public:
00066     RandSeq(uint32_t seed=MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED)
00067         : x(seed), y(seed) {}
00068 
00069     uint32_t next(void) {
00070         x ^= x << A;
00071         x ^= x >> B;
00072         x ^= y ^ (y >> C);
00073         return x + y;
00074     }
00075 
00076     void skip(size_t size) {
00077         for (size_t i = 0; i < size; i++) {
00078             next();
00079         }
00080     }
00081 
00082     void buffer(uint8_t *buffer, size_t size) {
00083         RandSeq lookahead = *this;
00084 
00085         for (size_t i = 0; i < size; i++) {
00086             buffer[i] = lookahead.next() & 0xff;
00087         }
00088     }
00089 
00090     int cmp(uint8_t *buffer, size_t size) {
00091         RandSeq lookahead = *this;
00092 
00093         for (size_t i = 0; i < size; i++) {
00094             int diff = buffer[i] - (lookahead.next() & 0xff);
00095             if (diff != 0) {
00096                 return diff;
00097             }
00098         }
00099         return 0;
00100     }
00101 };
00102 
00103 // Shared buffer for network transactions
00104 uint8_t *buffer;
00105 size_t buffer_size;
00106 
00107 // Tries to get the biggest buffer possible on the device. Exponentially
00108 // grows a buffer until heap runs out of space, and uses half to leave
00109 // space for the rest of the program
00110 void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) {
00111     size_t i = min;
00112     while (i < max) {
00113         void *b = malloc(i);
00114         if (!b) {
00115             i /= 4;
00116             if (i < min) {
00117                 i = min;
00118             }
00119             break;
00120         }
00121         free(b);
00122         i *= 2;
00123     }
00124 
00125     *buffer = (uint8_t *)malloc(i);
00126     *size = i;
00127     TEST_ASSERT(buffer);
00128 }
00129 
00130 
00131 void test_tcp_packet_pressure() {
00132     generate_buffer(&buffer, &buffer_size,
00133         MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN,
00134         MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX);
00135     printf("MBED: Generated buffer %d\r\n", buffer_size);
00136 
00137     NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION;
00138     int err =  MBED_CONF_APP_CONNECT_STATEMENT;
00139     TEST_ASSERT_EQUAL(0, err);
00140 
00141     printf("MBED: TCPClient IP address is '%s'\n", net->get_ip_address());
00142 
00143     TCPSocket sock;
00144     SocketAddress tcp_addr(MBED_CONF_APP_ECHO_SERVER_ADDR, MBED_CONF_APP_ECHO_SERVER_PORT);
00145 
00146     Timer timer;
00147     timer.start();
00148 
00149     // Tests exponentially growing sequences
00150     for (size_t size = MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN;
00151          size < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX;
00152          size *= 2) {
00153         err = sock.open(net);
00154         TEST_ASSERT_EQUAL(0, err);
00155         err = sock.connect(tcp_addr);
00156         TEST_ASSERT_EQUAL(0, err);
00157         printf("TCP: %s:%d streaming %d bytes\r\n",
00158             tcp_addr.get_ip_address(), tcp_addr.get_port(), size);
00159 
00160         //recv connection prefix message
00161         sock.recv(buffer, sizeof(MBED_CONF_APP_TCP_ECHO_PREFIX));
00162         memset(buffer, 0, sizeof(buffer));
00163 
00164         sock.set_blocking(false);
00165 
00166         // Loop to send/recv all data
00167         RandSeq tx_seq;
00168         RandSeq rx_seq;
00169         size_t rx_count = 0;
00170         size_t tx_count = 0;
00171         size_t window = buffer_size;
00172 
00173         while (tx_count < size || rx_count < size) {
00174             // Send out data
00175             if (tx_count < size) {
00176                 size_t chunk_size = size - tx_count;
00177                 if (chunk_size > window) {
00178                     chunk_size = window;
00179                 }
00180 
00181                 tx_seq.buffer(buffer, chunk_size);
00182                 int td = sock.send(buffer, chunk_size);
00183 
00184                 if (td > 0) {
00185                     if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) {
00186                         printf("TCP: tx -> %d\r\n", td);
00187                     }
00188                     tx_seq.skip(td);
00189                     tx_count += td;
00190                 } else if (td != NSAPI_ERROR_WOULD_BLOCK ) {
00191                     // We may fail to send because of buffering issues,
00192                     // cut buffer in half
00193                     if (window > MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) {
00194                         window /= 2;
00195                     }
00196 
00197                     if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) {
00198                         printf("TCP: Not sent (%d), window = %d\r\n", td, window);
00199                     }
00200                 }
00201             }
00202 
00203             // Verify recieved data
00204             while (rx_count < size) {
00205                 int rd = sock.recv(buffer, buffer_size);
00206                 TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK );
00207                 if (rd > 0) {
00208                     if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) {
00209                         printf("TCP: rx <- %d\r\n", rd);
00210                     }
00211                     int diff = rx_seq.cmp(buffer, rd);
00212                     TEST_ASSERT_EQUAL(0, diff);
00213                     rx_seq.skip(rd);
00214                     rx_count += rd;
00215                 } else if (rd == NSAPI_ERROR_WOULD_BLOCK ) {
00216                     break;
00217                 }
00218             }
00219         }
00220 
00221         err = sock.close();
00222         TEST_ASSERT_EQUAL(0, err);
00223     }
00224 
00225     timer.stop();
00226     printf("MBED: Time taken: %fs\r\n", timer.read());
00227     printf("MBED: Speed: %.3fkb/s\r\n",
00228             8*(2*MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX -
00229             MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read()));
00230 
00231     net->disconnect();
00232 }
00233 
00234 
00235 // Test setup
00236 utest::v1::status_t test_setup(const size_t number_of_cases) {
00237     GREENTEA_SETUP(120, "tcp_echo");
00238     return verbose_test_setup_handler(number_of_cases);
00239 }
00240 
00241 Case cases[] = {
00242     Case("TCP packet pressure", test_tcp_packet_pressure),
00243 };
00244 
00245 Specification specification(test_setup, cases);
00246 
00247 int main() {
00248     return !Harness::run(specification);
00249 }