diff --git a/README.md b/README.md index 17a5a6f..e1e3e45 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ### How-to-compile/upload ```bash -arduino-cli compile -b arduino:renesas_uno:unor4wifi -v examples/iperf-client -u -p /dev/ttyACM0 +arduino-cli compile -b arduino:renesas_uno:unor4wifi -v examples/UDP_Client -u -p /dev/ttyACM0 ``` ### How-to-[`EVB-LAN8670-USB`](https://www.microchip.com/en-us/development-tool/EV08L38A) diff --git a/examples/iperf-client/README.md b/examples/iperf-client/README.md deleted file mode 100644 index d274683..0000000 --- a/examples/iperf-client/README.md +++ /dev/null @@ -1,36 +0,0 @@ -:floppy_disk: `iperf-client` -============================= - -This example sketch can be used to measure 10BASE-T1S network performance using this software stack. - -### How-to-compile/upload -```bash -arduino-cli compile -b arduino:renesas_uno:minima -v examples/iperf-client -u -p /dev/ttyACM0 -``` - -### How-to-`iperf` -The following commands assume that you've set up 10BASE-T1S interface on your PC (i.e. [`EVB-LAN8670-USB`](https://www.microchip.com/en-us/development-tool/EV08L38A)) with an IP address of `192.168.42.100`. - -Open a serial monitor on your PC in order to start running the sketch: -```bash -cat /dev/ttyACM0 -``` -```bash -IP 192.168.42.101 -MAC FC:C2:3D:46:26:F8 -... -``` -Verify that you can ping your board running this sketch from your PC: -```bash -ping 192.168.42.101 -``` -```bash -PING 192.168.42.101 (192.168.42.101) 56(84) bytes of data. -64 bytes from 192.168.42.101: icmp_seq=1 ttl=255 time=3.16 ms -64 bytes from 192.168.42.101: icmp_seq=2 ttl=255 time=3.26 ms -... -``` -Start `iperf` on your PC: -```bash -iperf --client 192.168.42.101 --udp --bandwidth 10M -``` diff --git a/examples/iperf-client/iperf-client.ino b/examples/iperf-client/iperf-client.ino deleted file mode 100644 index 4b0ea51..0000000 --- a/examples/iperf-client/iperf-client.ino +++ /dev/null @@ -1,144 +0,0 @@ -/* - * This example has been tested with the Arduino 10BASE-T1S (T1TOS) shield. - * - * Author: - * Alexander Entinger - */ - -/************************************************************************************** - * INCLUDE - **************************************************************************************/ - -#include - -#include -#include - -#include "udp_perf_client.h" - -/************************************************************************************** - * CONSTANTS - **************************************************************************************/ - -static uint8_t const T1S_PLCA_NODE_ID = 1; -static uint8_t const T1S_PLCA_NODE_COUNT = 8; -static uint8_t const T1S_PLCA_BURST_COUNT = 0; -static uint8_t const T1S_PLCA_BURST_TIMER = 0x80; -static bool const MAC_PROMISCUOUS_MODE = false; -static bool const MAC_TX_CUT_THROUGH = false; -static bool const MAC_RX_CUT_THROUGH = false; - -static IPAddress const ip_addr {192, 168, 42, 100 + T1S_PLCA_NODE_ID}; -static IPAddress const network_mask{255, 255, 255, 0}; -static IPAddress const gateway {192, 168, 42, 100}; - -static T1SPlcaSettings const t1s_plca_settings{T1S_PLCA_NODE_ID, T1S_PLCA_NODE_COUNT, T1S_PLCA_BURST_COUNT, T1S_PLCA_BURST_TIMER}; -static T1SMacSettings const t1s_mac_settings{MAC_PROMISCUOUS_MODE, MAC_TX_CUT_THROUGH, MAC_RX_CUT_THROUGH}; - -/************************************************************************************** - * GLOBAL VARIABLES - **************************************************************************************/ - -auto const tc6_io = new TC6::TC6_Io( -#if defined(ARDUINO_GIGA) || defined(ARDUINO_PORTENTA_C33) - SPI1 -#else - SPI -#endif - , CS_PIN - , RESET_PIN - , IRQ_PIN); -auto const tc6_inst = new TC6::TC6_Arduino_10BASE_T1S(tc6_io); - -/************************************************************************************** - * SETUP/LOOP - **************************************************************************************/ - -void setup() -{ - Serial.begin(115200); - while (!Serial) { } - delay(1000); - - /* I2C (Wire) is needed to obtain an individual MAC - * address from the AT24MAC402 EEPROM located on the - * Mikroe Two-Wire ETH click board. - */ - Wire.begin(); - - /* Initialize digital IO interface for interfacing - * with the LAN8651. - */ - pinMode(IRQ_PIN, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(IRQ_PIN), - []() { tc6_io->onInterrupt(); }, - FALLING); - - /* Initialize IO module. */ - if (!tc6_io->begin()) - { - Serial.println("'TC6_Io::begin(...)' failed."); - for (;;) { } - } - - MacAddress const mac_addr = MacAddress::create_from_uid(); - - if (!tc6_inst->begin( ip_addr - , network_mask - , gateway - , mac_addr - , t1s_plca_settings - , t1s_mac_settings)) - { - Serial.println("'TC6::begin(...)' failed."); - for (;;) { } - } - - Serial.print("IP\t"); - Serial.println(ip_addr); - Serial.println(mac_addr); - Serial.println(t1s_plca_settings); - Serial.println(t1s_mac_settings); - - iperf_init(tc6_inst); - iperf_print_app_header(); - iperf_start_application(); -} - -void loop() -{ - /* Services the hardware and the protocol stack. - * Must be called cyclic. The faster the better. - */ - tc6_inst->service(); - - iperf_service(); - - static unsigned long prev_beacon_check = 0; - - auto const now = millis(); - - if ((now - prev_beacon_check) > 1000) - { - prev_beacon_check = now; - if (!tc6_inst->getPlcaStatus(OnPlcaStatus)) - Serial.println("getPlcaStatus(...) failed"); - } -} - - -static void OnPlcaStatus(bool success, bool plcaStatus) -{ - if (!success) - { - Serial.println("PLCA status register read failed"); - return; - } - - if (plcaStatus) - Serial.println("PLCA Mode active"); - else { - Serial.println("CSMA/CD fallback"); - tc6_inst->enablePlca(); - } -} diff --git a/examples/iperf-client/udp_perf_client.cpp b/examples/iperf-client/udp_perf_client.cpp deleted file mode 100644 index 39508f1..0000000 --- a/examples/iperf-client/udp_perf_client.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (C) 2017 - 2019 Xilinx, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - */ - -/* Connection handle for a UDP Client session */ - -#include -#include -#include -#include -//#include "lwip/udp.h" -#include "udp_perf_client.h" -//#include "peripheral/systick/plib_systick.h" -//#include "microchip/tc6-lwip.h" /* For performance improvement addon */ -#include - -#define START_DELAY (10) - -//extern SYSTICK_OBJECT systick; /* Instanced in plib_systick.c */ -#define GET_TICKS() (millis()) - -static uint32_t startDelay = 0; -static bool running = false; -static struct perf_stats client; -static struct perf_stats server; -static ip_addr_t remoteIP; -static struct udp_pcb *sock[NUM_OF_PARALLEL_CLIENTS]; -static uint32_t packet_id[NUM_OF_PARALLEL_CLIENTS] = { 0 }; -static uint8_t iPayload[UDP_SEND_BUFSIZE]; -static uint16_t iPayloadSize = UDP_SEND_BUFSIZE; - -#define FINISH 1 -/* Report interval time in ms */ -#define REPORT_INTERVAL_TIME (INTERIM_REPORT_INTERVAL * 1000) -/* End time in ms */ -#define END_TIME (UDP_TIME_INTERVAL * 1000) - -/* labels for formats [KMG] */ -const char kLabel[] = -{ - ' ', - 'K', - 'M', - 'G' -}; - -TC6::TC6_Arduino_10BASE_T1S * priv_tc6_inst = NULL; - -void iperf_print_app_header(void) -{ - printf("UDP client connecting to %s on port %d\r\n", - UDP_SERVER_IP_ADDRESS, UDP_CONN_PORT); - printf("On Host: Run $iperf -s -i %d -u\r\r\n\n", - INTERIM_REPORT_INTERVAL); -} - -static void print_udp_conn_stats(void) -{ - printf("[%3d] connected with ", client.client_id); - printf("%s port %d\r\n", UDP_SERVER_IP_ADDRESS, UDP_CONN_PORT); - printf("[ ID] Interval\t\tTransfer Bandwidth\r\n"); -} - -static void stats_buffer(char* outString, - uint32_t data, enum measure_t type) -{ - const uint32_t mega = 1000000; - sprintf(outString, "%ld.%ld %c", data/mega, data%mega, 'M'); -} - - -/* The report function of a UDP client session */ -static void udp_conn_report(uint32_t diff, - enum report_type report_type) -{ - uint32_t total_len; - uint32_t duration, bandwidth = 0; - char data[16], perf[16], time[64]; - - if (report_type == INTER_REPORT) { - total_len = client.i_report.total_bytes; - } else { - client.i_report.last_report_time = 0; - total_len = client.total_bytes; - } - - /* Converting duration from milliseconds to secs, - * and bandwidth to bits/sec . - */ - duration = diff / 1000; /* secs */ - if (duration) - bandwidth = (total_len / duration) * 8; - - stats_buffer(data, total_len, BYTES); - stats_buffer(perf, bandwidth, SPEED); - - /* On 32-bit platforms, xil_printf is not able to print - * uint32_t values, so converting these values in strings and - * displaying results - */ - sprintf(time, "%ld-%ld sec", - client.i_report.last_report_time, - (client.i_report.last_report_time + duration)); - printf("[%3d] %s %sBytes %sbits/sec\r\n", client.client_id, - time, data, perf); - - if (report_type == INTER_REPORT) - client.i_report.last_report_time += duration; - else - printf("[%3d] sent %lu datagrams\r\n", - client.client_id, client.cnt_datagrams); -} - -static void reset_stats(void) -{ - client.client_id++; - - /* Print connection statistics */ - print_udp_conn_stats(); - - /* Save start time for final report */ - client.start_time = GET_TICKS(); - client.total_bytes = 0; - client.cnt_datagrams = 0; - - /* Initialize Interim report parameters */ - client.i_report.start_time = 0; - client.i_report.total_bytes = 0; - client.i_report.last_report_time = 0; -} - -static int udp_packet_send(u8_t finished) -{ - int32_t i, *payload; - for (i = 0; !priv_tc6_inst->sendWouldBlock() && (i < NUM_OF_PARALLEL_CLIENTS); i++) { - struct pbuf *send_buf; - int32_t result; - send_buf = pbuf_alloc(PBUF_TRANSPORT, iPayloadSize, PBUF_RAM); - if (!send_buf) { - return 0; - } - if (pbuf_take(send_buf, iPayload, iPayloadSize) == ERR_OK) { - payload = (int32_t*) send_buf->payload; - if (finished == FINISH) { - packet_id[i] = -1; - } else { - packet_id[i]++; - } - *payload = htonl(packet_id[i]); - } else { - assert(send_buf->ref != 0); - pbuf_free(send_buf); - printf("UDP Iperf: Can not take send buffer\r\n"); - return 0; - } - result = udp_sendto(sock[i], send_buf, &remoteIP, UDP_CONN_PORT); - if (ERR_OK == result) { - client.total_bytes += iPayloadSize; - client.cnt_datagrams++; - client.i_report.total_bytes += iPayloadSize; - assert(send_buf->ref != 0); - pbuf_free(send_buf); - send_buf = NULL; - return 0; - } else if ((ERR_WOULDBLOCK == result) || (ERR_MEM == result)) { - assert(send_buf->ref != 0); - if (finished != FINISH) { - packet_id[i]--; - } - pbuf_free(send_buf); - send_buf = NULL; - return 0; - } else { - /* Terminate this app */ - uint32_t now = GET_TICKS(); - uint32_t diff_ms = now - client.start_time; - printf("Send failed with error code=%ld, ", result); - printf("Terminating application\r\n"); - udp_conn_report(diff_ms, UDP_DONE_CLIENT); - printf("UDP test failed\r\n"); - assert(send_buf->ref != 0); - pbuf_free(send_buf); - send_buf = NULL; - running = false; - return -1; - } - } - return 0; -} - -/* Transmit data on a udp session */ -static int transfer_data(void) -{ - if (END_TIME || REPORT_INTERVAL_TIME) { - uint32_t now = GET_TICKS(); - if (REPORT_INTERVAL_TIME) { - if (client.i_report.start_time) { - uint32_t diff_ms = now - client.i_report.start_time; - if (diff_ms >= REPORT_INTERVAL_TIME) { - udp_conn_report(diff_ms, INTER_REPORT); - client.i_report.start_time = 0; - client.i_report.total_bytes = 0; - } - } else { - client.i_report.start_time = now; - } - } - - if (END_TIME) { - /* this session is time-limited */ - uint32_t diff_ms = now - client.start_time; - if (diff_ms >= END_TIME) { - /* time specified is over, - * close the connection */ - udp_packet_send(FINISH); - udp_conn_report(diff_ms, UDP_DONE_CLIENT); - printf("UDP test passed Successfully\r\n"); - running = false; - return FINISH; - } - } - } - - if (udp_packet_send(!FINISH) < 0) - return FINISH; - - return 0; -} - -static void OnReceive(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - server.cnt_datagrams++; - server.total_bytes += p->tot_len; - pbuf_free(p); -} - -static void PrintServerStats(void) -{ - uint32_t now; - if (!server.cnt_datagrams) - return; - now = GET_TICKS(); - if (now - server.start_time >= 1000) { - server.start_time = now; - printf("IPERF RX bandwidth=%ld kbit/s packets=%ld 1/s\r\n", (server.total_bytes * 8 / 1000), server.cnt_datagrams); - server.total_bytes = 0; - server.cnt_datagrams = 0; - } -} - -void iperf_init(TC6::TC6_Arduino_10BASE_T1S * tc6_inst) -{ - priv_tc6_inst = tc6_inst; - - uint32_t i; - memset(&server, 0, sizeof(server)); - - if (!ipaddr_aton(UDP_SERVER_IP_ADDRESS, &remoteIP)) { - printf("UDP client: Remote IP wrong formatted\r\n"); - } - - for (i = 0; i < NUM_OF_PARALLEL_CLIENTS; i++) { - if ((sock[i] = udp_new()) == NULL) { - printf("UDP client: Error creating Socket\r\n"); - return; - } - if (0 == i) { - if (ERR_OK != udp_bind(sock[i], IP_ADDR_ANY, UDP_CONN_PORT)) { - printf("UDP client: Error binding Socket\r\n"); - return; - } - udp_recv(sock[i], OnReceive, NULL); - } - } - - /* initialize data buffer being sent with same as used in iperf */ - for (i = 0; i < UDP_SEND_BUFSIZE; i++) { - iPayload[i] = (i % 10) + '0'; - } -} - -void iperf_start_application(void) -{ - running = false; - startDelay = GET_TICKS(); - reset_stats(); - transfer_data(); -} - -void iperf_stop_application(void) -{ - running = false; -} - -bool iperf_get_running_state(void) -{ - return running || (0 != startDelay); -} - -void iperf_service(void) -{ - if (startDelay && ((GET_TICKS() - startDelay) > START_DELAY)) { - startDelay = 0; - running = true; - } - if (running) { - transfer_data(); - } - PrintServerStats(); -} - -void iperf_set_packet_size(uint16_t packetLength) -{ - if (packetLength < UDP_SEND_BUFSIZE) { - iPayloadSize = packetLength; - } else { - iPayloadSize = UDP_SEND_BUFSIZE; - } - printf("iperf packet size set to %d Bytes\r\n", iPayloadSize); -} \ No newline at end of file diff --git a/examples/iperf-client/udp_perf_client.h b/examples/iperf-client/udp_perf_client.h deleted file mode 100644 index 08650a0..0000000 --- a/examples/iperf-client/udp_perf_client.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2017 - 2019 Xilinx, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Source from: https://github.com/Xilinx/embeddedsw/tree/master/lib/sw_apps/freertos_lwip_udp_perf_client/src - */ - -#ifndef __UDP_PERF_CLIENT_H_ -#define __UDP_PERF_CLIENT_H_ - -//#include "lwipopts.h" -//#include "lwip/ip_addr.h" -//#include "lwip/err.h" -//#include "lwip/udp.h" -//#include "lwip/inet.h" -//#include "lwip/sockets.h" -//#include "lwip/sys.h" -#include "errno.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* used as indices into kLabel[] */ -enum { - KCONV_UNIT, - KCONV_KILO, - KCONV_MEGA, - KCONV_GIGA, -}; - -/* used as type of print */ -enum measure_t { - BYTES, - SPEED -}; - -/* Report Type */ -enum report_type { - /* The Intermediate report */ - INTER_REPORT, - /* The client side test is done */ - UDP_DONE_CLIENT, - /* Remote side aborted the test */ - UDP_ABORTED_REMOTE -}; - -struct interim_report { - uint32_t start_time; - uint32_t last_report_time; - uint32_t total_bytes; -}; - -struct perf_stats { - uint8_t client_id; - uint32_t start_time; - uint32_t total_bytes; - uint32_t cnt_datagrams; - struct interim_report i_report; -}; - -/* seconds between periodic bandwidth reports */ -#define INTERIM_REPORT_INTERVAL 5 - -/* Client port to connect */ -#define UDP_CONN_PORT 5001 - -/* time in seconds to transmit packets */ -#define UDP_TIME_INTERVAL 300 - -/* Server to connect with */ -#define UDP_SERVER_IP_ADDRESS "192.168.42.100" - -/* UDP buffer length in bytes */ -#define UDP_SEND_BUFSIZE 1460 - -/* Number of parallel UDP clients */ -#define NUM_OF_PARALLEL_CLIENTS 1 - -void iperf_init(TC6::TC6_Arduino_10BASE_T1S * tc6_inst); -void iperf_print_app_header(void); -void iperf_start_application(void); -void iperf_stop_application(void); -bool iperf_get_running_state(void); -void iperf_service(void); -void iperf_set_packet_size(uint16_t packetLength); - -#ifdef __cplusplus -} -#endif -#endif /* __UDP_PERF_CLIENT_H_ */