<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/rpp-lib/lwip/src/include/ipv6}""/>
</option>
<option id="com.ti.ccstudio.buildDefinitions.TMS470_5.0.compilerID.GCC.795138235" name="Enable support for GCC extensions (--gcc)" superClass="com.ti.ccstudio.buildDefinitions.TMS470_5.0.compilerID.GCC" value="true" valueType="boolean"/>
- <option id="com.ti.ccstudio.buildDefinitions.TMS470_5.0.compilerID.DEFINE.35615475" name="Pre-define NAME (--define, -D)" superClass="com.ti.ccstudio.buildDefinitions.TMS470_5.0.compilerID.DEFINE" valueType="definedSymbols">
- <listOptionValue builtIn="false" value="DEBUG"/>
- <listOptionValue builtIn="false" value="LWIP_DEBUG"/>
- </option>
+ <option id="com.ti.ccstudio.buildDefinitions.TMS470_5.0.compilerID.DEFINE.35615475" name="Pre-define NAME (--define, -D)" superClass="com.ti.ccstudio.buildDefinitions.TMS470_5.0.compilerID.DEFINE" valueType="definedSymbols"/>
<option id="com.ti.ccstudio.buildDefinitions.TMS470_5.0.compilerID.DIAG_WARNING.1682379727" name="Treat diagnostic <id> as warning (--diag_warning, -pdsw)" superClass="com.ti.ccstudio.buildDefinitions.TMS470_5.0.compilerID.DIAG_WARNING" valueType="stringList">
<listOptionValue builtIn="false" value="225"/>
</option>
#include "cmd_lin.h"
#include "cmd_lout.h"
#include "cmd_lwip.h"
+#include "cmd_netstats.h"
#include "cmd_pin.h"
#include "cmd_port.h"
#include "cmd_sdram.h"
CMD_DES_INCLUDE_SUBLIST(cmd_list_lin),
CMD_DES_INCLUDE_SUBLIST(cmd_list_lout),
CMD_DES_INCLUDE_SUBLIST(cmd_list_lwip),
+ CMD_DES_INCLUDE_SUBLIST(cmd_list_netstats),
CMD_DES_INCLUDE_SUBLIST(cmd_list_pin),
CMD_DES_INCLUDE_SUBLIST(cmd_list_port),
CMD_DES_INCLUDE_SUBLIST(cmd_list_sdram),
#include <ctype.h>
#include "rpp/rpp.h"
-#include "lwip/api.h" //netconn
#include "lwip/udp.h"
+#if !NO_SYS
+#include "lwip/api.h" //netconn
+#else
+#include "lwip/timers.h" //for updating timers, when NO_SYS == 1
+#include "lwip/tcp.h"
+#include "lwip/tcp_impl.h"
+#endif
#define INTERFACE_INSTANCE_NUMBER 0
ip_addr_t remoteIP = nc_arg->remoteIP;
boolean_t udp = nc_arg->udp, listen = nc_arg->listen, srcPortSpec = nc_arg->srcPortSpec, netLoop = nc_arg->netLoop, test = nc_arg->test;
boolean_t thread = nc_arg->thread; /* variable controling whether this instance should run as thread */
+#if DEBUG
uint8_t thread_inst = (taskNameNum-1); /* store number of this thread */
+#endif
tasks_running++;
if(test) /* -d option; sends packets to the opposite node and doesn't receive anything */
{
index = 0;
- char strbuf[10];
+ char strbuf[13];
int strlen;
//netconn_set_recvtimeout(newconn, 1);
while(!closeths && index++ < 4294967295){
nc_arg->err = err; /* only user controlled task is in front */
if(thread)vTaskDelete(NULL);
}
+#else
+boolean_t connected;
+boolean_t sent;
+boolean_t ncStop;
+
+err_t nc_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
+{
+ uint16_t index;
+ uint8_t *payload;
+ if(err == ERR_ABRT)
+ {
+ rpp_sci_printk((const char *) "recv abrt\n");
+ return ERR_ABRT;
+ }
+ /* print remote data to SCI */
+ while(p != NULL)
+ {
+ index = 0;
+ payload = p->payload;
+ while(index<p->len)
+ {
+ rpp_sci_printk((const char *) "%c",payload[index]);
+ index++;
+ }
+ p = p->next;
+ }
+ return ERR_OK;
+}
+
+void nc_udp_recv_callback(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
+{
+ uint16_t index;
+ uint8_t *payload;
+ /* print remote data to SCI */
+ while(p != NULL)
+ {
+ index = 0;
+ payload = p->payload;
+ while(index<p->len)
+ {
+ rpp_sci_printk((const char *) "%c",payload[index]);
+ index++;
+ }
+ p = p->next;
+ }
+ //pbuf_free(p);
+}
+
+void nc_udp_listen_recv_callback(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
+{
+ connected = TRUE;
+ err_t err = udp_connect(pcb, addr, port);
+ LWIP_ASSERT(("nc_init: udp_listen_connect failed"), err == ERR_OK);
+ udp_recv(pcb, nc_udp_recv_callback, NULL);
+ nc_udp_recv_callback(arg, pcb, p, addr, port);
+}
+
+void nc_err_callback(void *arg, err_t err)
+{
+ rpp_sci_printk((const char *) "err clbck\n");
+ LWIP_DEBUGF(LWIP_DBG_ON, ("nc_err: %s", lwip_strerr(err)));
+
+ ncStop = TRUE;
+}
+
+err_t nc_sent_callback(void *arg, struct tcp_pcb *pcb, u16_t len)
+{
+ sent = TRUE;
+ return ERR_OK;
+}
+
+err_t nc_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err)
+{
+ struct tcp_pcb **newone = arg;
+ *newone = newpcb; /* pass accepted connection to main app loop */
+
+ connected = TRUE;
+
+ /* Set up the various callback functions */
+ tcp_recv(newpcb, nc_recv_callback);
+ tcp_err(newpcb, nc_err_callback);
+ tcp_sent(newpcb, nc_sent_callback);
+
+ return ERR_OK;
+}
+
+err_t nc_connected_callback(void *arg, struct tcp_pcb *tpcb, err_t err)
+{
+
+ /* Set up the various callback functions */
+ tcp_recv(tpcb, nc_recv_callback);
+ tcp_err(tpcb, nc_err_callback);
+ tcp_sent(tpcb, nc_sent_callback);
+
+ connected = TRUE;
+ rpp_sci_printk((const char *) "connected\n");
+ return ERR_OK;
+}
+
+err_t nc_tmirror_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
+{
+ if(err == ERR_ABRT)
+ {
+ rpp_sci_printk((const char *) "recv abrt\n");
+ return ERR_ABRT;
+ }
+ while(p != NULL)
+ {
+ if(tcp_write(tpcb, p->payload, p->len, TCP_WRITE_FLAG_COPY)!=ERR_OK){
+ rpp_sci_printk((const char *) "error writing to newpcb - tcp_write\n");
+ return -1;
+ }
+ if(tcp_output(tpcb)!=ERR_OK){ /* when we want to send data immediately */
+ rpp_sci_printk((const char *) "newpcb output err - tcp\n");
+ return -1;
+ }
+ p = p->next;
+ }
+ return ERR_OK;
+}
+
+void nc_umirror_callback(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
+{
+ struct pbuf *pbuf;
+ while(p != NULL)
+ {
+ pbuf = pbuf_alloc(PBUF_TRANSPORT, p->len, PBUF_RAM);
+ if(pbuf == NULL)
+ {
+ rpp_sci_printk((const char *) "error allocating pbuf - udp_send\n");
+ //p = p->next;
+ continue;
+ }
+ if(pbuf_take(pbuf, p->payload, p->len)!=ERR_OK)
+ {
+ rpp_sci_printk((const char *) "pbuf mem err (small pbuf) - udp_send\n");
+ continue;
+ }
+ if(udp_send (pcb, pbuf)!=ERR_OK)
+ {
+ rpp_sci_printk((const char *) "error sending to pcb - udp_send\n");
+ continue;
+ }
+ p = p->next;
+ }
+}
+
+
#endif /* !NO_SYS */
+/*
+ * this function has two operational modes, depending on LwIP settings
+ * NO_SYS == 1 - this is for testing raw API, there is only one task working with IP stack allowed when using this mode
+ * NO_SYS == 0 - this is for testing netconn API, you can let more tasks to work with IP stack
+ */
int cmd_do_init_nc(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
{
err_t err = ERR_OK;
ip_addr_t remoteIP;
boolean_t help = FALSE, udp = FALSE, listen = FALSE, netLoop = FALSE, test = FALSE, srcPortSpec = FALSE;
uint8_t pindex;
- uint8_t name[5] = "nc";
- name[4] = '\0';
- /* initialize arguments */
+ buff_index = 0;
+ /* initialize arguments and thread name */
#if !NO_SYS
+ uint8_t name[5] = "nc";
+ name[4] = '\0';
struct nc_arg nc_arg; /* create space for handing args to nc_run() */
nc_arg.thread = FALSE;
+#else
+ uint8_t input = 0;
+ boolean_t flush = FALSE;
+ uint32_t index;
+ struct netif *netif = rpp_eth_get_netif(INTERFACE_INSTANCE_NUMBER);
+ struct tcp_pcb *tpcb, *tnewpcb;
+ struct udp_pcb *pcb;
+ struct pbuf *p; /* udp send */
#endif
/* examine parameters */
/* determine srcPortNO from predefined value if not done yet (from argument given) */
if(!srcPortSpec)
{
+ //udp_new_port();
srcPortNO = srcPort++;
}
return nc_arg.err;
}
#else /* raw LwIP API */
- rpp_sci_printf((const char *) "nc does not support NO_SYS yet\r\n");
+ ncStop = FALSE;
+ connected = FALSE;
+ sent = TRUE;
+ if(udp)
+ {
+ pcb = udp_new();
+ LWIP_ASSERT(("nc_init: udp_new failed"), pcb != NULL);
+ if(pcb == NULL)return -1;
+ err = udp_bind(pcb, &(netif->ip_addr), srcPortNO);
+ CC_ASSERT(("nc_init: udp_bind failed: %s", lwip_strerr(err)), err == ERR_OK);
+ if(err != ERR_OK)return -1;
+ }
+ else
+ {
+ tpcb = tcp_new();
+ LWIP_ASSERT(("nc_init: tcp_new failed"), tpcb != NULL);
+ if(tpcb == NULL)return -1;
+ err = tcp_bind(tpcb, &(netif->ip_addr), srcPortNO);
+ CC_ASSERT(("nc_init: tcp_bind failed: %s", lwip_strerr(err)), err == ERR_OK);
+ if(err != ERR_OK)return -1;
+ }
+
+ if(!udp)
+ {
+ if(listen)
+ {
+ tpcb = tcp_listen(tpcb);
+ LWIP_ASSERT(("nc_init: tcp_listen failed"), tpcb != NULL);
+ /* initialize callback arg and accept callback */
+ tcp_arg(tpcb, &tnewpcb);
+ tcp_accept(tpcb, nc_accept_callback);
+ }
+ else
+ {
+ tnewpcb = tpcb;
+ tpcb = NULL;
+ err = tcp_connect(tnewpcb, &remoteIP, portNO, nc_connected_callback);
+ LWIP_ASSERT(("nc_init: tcp_connect failed"), err == ERR_OK);
+ }
+ }
+ else
+ {
+ if(listen)
+ {
+ udp_recv(pcb, nc_udp_listen_recv_callback, NULL);
+ }
+ else
+ {
+ err = udp_connect(pcb, &remoteIP, portNO);
+ LWIP_ASSERT(("nc_init: udp_connect failed"), err == ERR_OK);
+ //connected = TRUE;
+ /* set udp recv callback */
+ udp_recv(pcb, nc_udp_recv_callback, NULL);
+ }
+ }
+
+ /* wait for connection to be established */
+ if(listen || !udp)
+ {
+ while(!connected)
+ {
+ if(rpp_sci_read_nb(1, &input) == SUCCESS)
+ {
+ ncStop = TRUE;
+ break;
+ }
+ sys_check_timeouts();
+ vTaskDelay(10); /* just because we have no other business here */
+ }
+ if(!udp && listen && tcp_close(tpcb) != ERR_OK)rpp_sci_printk((const char *) "closing listening tcp pcb err\n"); /* close listening pcb */
+ }
+
+ /* mode handlers in loop, so we can jump out of it on error or finish and clean after us */
+ do{
+ /*************************************** 1 mirror mode *****************************************/
+
+ if(netLoop) /* -m option */
+ {
+ err = ERR_OK;
+ /* send some data to opposite node so it knows its peer (this node) ; ATENTION if opposite node was not running in time this is send, then it wont get known this node's connection info */
+/* if(udp && !listen){
+ payload = netbuf_alloc(localData,1);
+ if(payload != NULL){
+ input = 0;
+ netbuf_take(localData,&input,1);
+ netbuf_len(localData) = 1;
+ if((err = netconn_send(newconn, localData)) != ERR_OK)break;
+ }
+ else
+ {
+ err = ERR_MEM;
+ break;
+ }
+ }*/
+ /* register callback function which sends all the recevd data back to remote host */
+ if(!udp)
+ {
+ tcp_recv(tnewpcb, nc_tmirror_callback);
+ }
+ else
+ {
+ udp_recv(pcb, nc_umirror_callback, NULL);
+ }
+
+ while(rpp_sci_read_nb(1, &input) != SUCCESS)
+ {
+ sys_check_timeouts();
+ vTaskDelay(10);
+ }
+ break;
+ }
+
+ /*************************************** 2 testing mode *****************************************/
+
+ if(test) /* -d option; sends packets to the opposite node and doesn't receive anything */
+ {
+ index = 0;
+ char strbuf[13];
+ int strlen;
+ //netconn_set_recvtimeout(newconn, 1);
+ while(index++ < 4294967295){
+ /* allow user to interrupt sending */
+ if(rpp_sci_read_nb(1, &input) == SUCCESS)break;
+ strlen = sprintf(strbuf,"%d\r\n",index);
+ if(!udp)
+ {
+ sys_check_timeouts();
+ if(tcp_write(tnewpcb, strbuf, strlen, TCP_WRITE_FLAG_COPY)!=ERR_OK){
+ rpp_sci_printf((const char *) "error writing to newpcb - tcp_write testing\n");
+ break;
+ }
+ if(tcp_output(tnewpcb)!=ERR_OK){ /* when we want to send data immediately */
+ rpp_sci_printf((const char *) "newpcb output err - tcp testing\n");
+ break;
+ }
+ }
+ else
+ {
+ p = pbuf_alloc(PBUF_TRANSPORT, strlen, PBUF_RAM);
+ if(p == NULL)
+ {
+ rpp_sci_printf((const char *) "error allocating pbuf - udp_send testing\n");
+ continue;
+ }
+ if(pbuf_take(p, strbuf, strlen)!=ERR_OK)
+ {
+ rpp_sci_printf((const char *) "pbuf mem err (small pbuf) - udp_send testing\n");
+ continue;
+ }
+ if(udp_send (pcb, p)!=ERR_OK)
+ {
+ rpp_sci_printf((const char *) "error sending to pcb - udp_send testing\n");
+ continue;
+ }
+ }
+ }
+ break;
+ }
+
+ /*************************************** 3 interactive mode *****************************************/
+
+ while(!ncStop)
+ {
+ if(!udp && tnewpcb->state != ESTABLISHED)
+ {
+ ncStop = TRUE;
+ break;
+ }
+ if(rpp_sci_read_nb(1, &input) != SUCCESS) {
+ /* updating lwip timers here */
+ sys_check_timeouts();
+ continue;
+ }
+
+ // Backspace and Delete
+ if(input == 8 || input == 127) {
+ if(buff_index > 0) {
+ buff_index--;
+ rpp_sci_putc('\b');
+ rpp_sci_putc(' ' );
+ rpp_sci_putc('\b');
+ }
+
+ // Line feed or Carriage return
+ } else if(input == 10 || input == 13) {
+ in_buffer[buff_index] = 13;
+ buff_index++;
+ in_buffer[buff_index] = 10;
+ buff_index++;
+ flush = TRUE;
+ rpp_sci_putc('\r');
+ rpp_sci_putc('\n');
+
+ // If is any printable character
+ } else if(isprint(input) || input == 9) {
+
+ // Store character and increment buffer index
+ in_buffer[buff_index] = input;
+ buff_index++;
+ rpp_sci_putc(input);
+
+ // Check if buffer is full and force flush
+ if(buff_index == BUF_SIZE - 3) {
+ flush = TRUE;
+ }
+ // All other character stops nc
+ } else {
+ ncStop = TRUE;
+ flush = TRUE;
+ }
+
+ if(flush)
+ {
+ while(!udp && !ncStop && !sent)
+ {
+ sys_check_timeouts();
+ vTaskDelay(10);
+ }
+ if(ncStop)break;
+ if(!udp)
+ {
+ if(tcp_write(tnewpcb, in_buffer, buff_index, TCP_WRITE_FLAG_COPY)!=ERR_OK){
+ rpp_sci_printf((const char *) "error writing to newpcb - tcp_write\n");
+ continue;
+ }
+ if(tcp_output(tnewpcb)!=ERR_OK){ /* when we want to send data immediately */
+ rpp_sci_printf((const char *) "newpcb output err - tcp\n");
+ continue;
+ }
+ }
+ else
+ {
+ p = pbuf_alloc(PBUF_TRANSPORT, buff_index, PBUF_RAM);
+ if(p == NULL)
+ {
+ rpp_sci_printf((const char *) "error allocating pbuf - udp_send\n");
+ continue;
+ }
+ if(pbuf_take(p, in_buffer, buff_index)!=ERR_OK)
+ {
+ rpp_sci_printf((const char *) "pbuf mem err (small pbuf) - udp_send\n");
+ continue;
+ }
+ if(udp_send (pcb, p)!=ERR_OK)
+ {
+ rpp_sci_printf((const char *) "error sending to pcb - udp_send\n");
+ continue;
+ }
+ }
+ // Reset variables
+ sent = FALSE;
+ buff_index = 0;
+ flush = FALSE;
+ }
+ }
+
+ }while(0);
+
+/* close connection and clean */
+ if(!udp)
+ {
+ tcp_recv(tnewpcb, NULL);
+ err = tcp_close(tnewpcb);
+ if (err != ERR_OK) {
+ rpp_sci_printf((const char *) "newpcb closing error\n");
+ /* closing failed, try again later */
+ LWIP_DEBUGF(LWIP_DBG_ON, ("Error %s closing pcb=0x%08X\n", lwip_strerr(err), pcb));
+ tcp_recv(tnewpcb, nc_recv_callback);
+ } else {
+ /* closing succeeded */
+ tcp_arg(tnewpcb, NULL);
+ tcp_sent(tnewpcb, NULL);
+ }
+ }
+ else
+ {
+ udp_disconnect(pcb);
+ udp_remove(pcb);
+ }
+ buff_index = 0;
#endif
return ERR_OK;
}
--- /dev/null
+/*
+ * Copyright (C) 2012-2013 Czech Technical University in Prague
+ *
+ * Created on: Aug 23, 2013
+ *
+ * Authors:
+ * - Jan Dolezal <pm.jenik@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * File : cmd_netstats.c
+ *
+ * Abstract:
+ * This file contains commands for net statistics (ethernet interface and LwIP)
+ *
+ */
+
+#include "cmd_netstats.h"
+
+#ifndef DOCGEN
+
+#include "rpp/rpp.h"
+#include "drv/emac.h"
+#include "lwip/opt.h"
+
+#define INTERFACE_INSTANCE_NUMBER 0
+
+
+/* --- EMAC DESCRIPTOR FORMAT ---
+ * bit fields
+ * WORD |
+ * OFFSET | 31 16 | 15 0
+ * ------------------------------------------------------------------------------------
+ * 0 | *Next Descriptor Pointer
+ * 1 | *Data Buffer Pointer
+ * 2 | Buffer Offset | Buffer Length
+ * 3 | Flags | Packet Length
+ * 4 | *pbuf
+ */
+
+boolean_t bd_SOP(volatile struct emac_tx_bd *bufferDescriptor)
+{
+ return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_SOP);
+}
+
+boolean_t bd_EOP(volatile struct emac_tx_bd *bufferDescriptor)
+{
+ return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_EOP);
+}
+
+boolean_t bd_OWNER(volatile struct emac_tx_bd *bufferDescriptor)
+{
+ return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_OWNER);
+}
+
+boolean_t bd_EOQ(volatile struct emac_tx_bd *bufferDescriptor)
+{
+ return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_EOQ);
+}
+
+uint32_t bd_addr(uint16_t bd_num)
+{
+ return EMAC_CTRL_RAM_BASE_m(0) + bd_num*sizeof(struct emac_tx_bd);
+}
+
+volatile struct emac_tx_bd *findPreviousBD(volatile struct emac_tx_bd *bufferDescriptor)
+{
+ volatile struct emac_tx_bd *temporary = bufferDescriptor - 1;
+
+ /* first try space before given bd */
+ if((uint32_t) temporary >= EMAC_CTRL_RAM_BASE_m(0) && temporary->next == bufferDescriptor)
+ return temporary;
+ temporary = bufferDescriptor->next;
+ while(temporary != bufferDescriptor && temporary != NULL)
+ {
+ if(temporary->next == bufferDescriptor)
+ return temporary;
+ temporary = (temporary + 1); /* going through memory, if you want to go through bd chains put here 'temporary = temporary->next;' */
+ if( (uint32_t)(temporary+1) > EMAC_CTRL_RAM_BASE_m(0)+SIZE_EMAC_CTRL_RAM){ /* when out of CPPI RAM */
+ temporary = (struct emac_tx_bd *) EMAC_CTRL_RAM_BASE_m(0); /* continue scanning from the beginning */
+ }
+ }
+ return (struct emac_tx_bd *)-1; /* not found */
+}
+
+void print_bd_content(volatile struct emac_tx_bd *bufferDescriptor, boolean_t humanReadable)
+{
+ uint16_t data;
+ rpp_sci_printf((const char *) "Buffer Descriptor at 0x%08x\n", bufferDescriptor);
+ rpp_sci_printf((const char *) "Next BD:\t0x%08x\n", bufferDescriptor->next);
+ rpp_sci_printf((const char *) "Data ptr:\t0x%08x\n", bufferDescriptor->bufptr);
+ rpp_sci_printf((const char *) "Buf offset:\t%d\tBuf length:\t%d\n", (bufferDescriptor->bufoff_len >> 16), (bufferDescriptor->bufoff_len & 0xffff));
+ if(!humanReadable)
+ {
+ rpp_sci_printf((const char *) "Flags:\t\t0x%04x\t", (bufferDescriptor->flags_pktlen >> 16));
+ }
+ else
+ {
+ data = bufferDescriptor->flags_pktlen;
+ rpp_sci_printf((const char *) "Flags:\t%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n", (data & EMAC_DSC_FLAG_SOP)?"SOP":"", (data & EMAC_DSC_FLAG_EOP)?"EOP":"", (data & EMAC_DSC_FLAG_OWNER)?"OWNER":"", (data & EMAC_DSC_FLAG_EOQ)?"EOQ":"", (data & EMAC_DSC_FLAG_TDOWNCMPLT)?"TDWN":"", (data & EMAC_DSC_FLAG_PASSCRC)?"PSCRC":"", (data & EMAC_DSC_FLAG_JABBER)?"JBR":"", (data & EMAC_DSC_FLAG_OVERSIZE)?"OVSZ":"", (data & EMAC_DSC_FLAG_FRAGMENT)?"FRGM":"", (data & EMAC_DSC_FLAG_UNDERSIZED)?"UNSZ":"", (data & EMAC_DSC_FLAG_CONTROL)?"CTRL":"", (data & EMAC_DSC_FLAG_OVERRUN)?"OVRUN":"", (data & EMAC_DSC_FLAG_CODEERROR)?"CODEERR":"", (data & EMAC_DSC_FLAG_ALIGNERROR)?"ALGNERR":"", (data & EMAC_DSC_FLAG_CRCERROR)?"CRCERR":"", (data & EMAC_DSC_FLAG_NOMATCH)?"NOMATCH":"");
+ }
+ rpp_sci_printf((const char *) "Pkt length:\t%d\n", (bufferDescriptor->flags_pktlen & 0xffff));
+ rpp_sci_printf((const char *) "Pbuf ptr:\t0x%08x\n", bufferDescriptor->pbuf);
+}
+
+/*
+ * mode: 0 flags -> param says which flag (0-15)
+ * 1 bd->next == NULL, no param
+ */
+void print_bds_state(uint8_t mode, uint8_t param)
+{
+ volatile struct emac_tx_bd *bufferDescriptor = (struct emac_tx_bd *) EMAC_CTRL_RAM_BASE_m(0);
+ uint16_t index = 0;
+ rpp_sci_printf((const char *) "TX:");
+ while(index < 409)
+ {
+ if(!(index%10)){
+ rpp_sci_printf((const char *) " ");
+ if(!(index%20))rpp_sci_printf((const char *) "\n");
+ }
+ if(index == 204){
+ rpp_sci_printf((const char *) "\nRX: ");
+ }
+ if (mode == 0){
+ if(bufferDescriptor->flags_pktlen & ((1 << 15) >> (param%16))){
+ rpp_sci_printf((const char *) "f");
+ }else{
+ rpp_sci_printf((const char *) ".");
+ }
+ }else if(mode == 1){
+ if(bufferDescriptor->next == NULL){
+ rpp_sci_printf((const char *) "0");
+ }else{
+ rpp_sci_printf((const char *) ".");
+ }
+ }else return;
+ bufferDescriptor++;
+ index++;
+ }
+ rpp_sci_printf((const char *) "\n");
+}
+
+#if RPP_ETH_STATS
+void print_tx_channel_stat()
+{
+ rpp_sci_printf((const char *) "Transmit:\n");
+ rpp_sci_printf((const char *) "\t\tbeforeHandled\tafterHandled\n");
+ rpp_sci_printf((const char *) "active_tail:\t0x%08x\t0x%08x\n",
+ beforeHandled.active_tail, afterHandled.active_tail);
+ rpp_sci_printf((const char *) "free_head:\t0x%08x\t0x%08x\n",
+ beforeHandled.free_head, afterHandled.free_head);
+ rpp_sci_printf((const char *) "nxt_bd_to_proc:\t0x%08x\t0x%08x\n\n",
+ beforeHandled.next_bd_to_process, afterHandled.next_bd_to_process);
+}
+
+void print_rx_channel_stat()
+{
+ rpp_sci_printf((const char *) "Receive:\n");
+ rpp_sci_printf((const char *) "\t\tbeforeRecv\tafterRecv\n");
+ rpp_sci_printf((const char *) "active_head:\t0x%08x\t0x%08x\n",
+ beforeRecv.active_head, afterRecv.active_head);
+ rpp_sci_printf((const char *) "active_tail:\t0x%08x\t0x%08x\n",
+ beforeRecv.active_tail, afterRecv.active_tail);
+ rpp_sci_printf((const char *) "free_head:\t0x%08x\t0x%08x\n",
+ beforeRecv.free_head, afterRecv.free_head);
+ rpp_sci_printf((const char *) "freed_pbuf_len:\t%d\t\t%d\n\n",
+ beforeRecv.freed_pbuf_len, afterRecv.freed_pbuf_len);
+}
+
+void printStatistics()
+{
+ rpp_sci_printf((const char *) "BDs:\t\tTX\tRX\n");
+ rpp_sci_printf((const char *) "NO of filled PKTs:\t%d\t%d",filledTXPKTs,filledRXPKTs);
+ rpp_sci_printf((const char *) "\n");
+ rpp_sci_printf((const char *) "NO of sent PKTs:\t%d\t%d",handledTXPKTs,handledRXPKTs);
+ rpp_sci_printf((const char *) "\n");
+ rpp_sci_printf((const char *) "NO of filled BDs:\t%d\t%d",filledTXbds,filledRXbds);
+ rpp_sci_printf((const char *) "\n");
+ rpp_sci_printf((const char *) "NO of sent BDs:\t%d\t%d",handledTXbds,handledRXbds);
+ rpp_sci_printf((const char *) "\n");
+ rpp_sci_printf((const char *) "NO of runs of ISR:\t%d\t%d",countEMACCore0TxIsr,countEMACCore0RxIsr);
+ rpp_sci_printf((const char *) "\n");
+ rpp_sci_printf((const char *) "\n");
+
+ rpp_sci_printf((const char *) "PBUFs:\t\tTX\tRX\n");
+ rpp_sci_printf((const char *) "PBUF Chains prepared:\t%d\t%d",preparedTxPBUFChains,preparedRxPBUFChains);
+ rpp_sci_printf((const char *) "\n");
+ rpp_sci_printf((const char *) "PBUFs prepared:\t%d\t%d",preparedTxPBUFs,preparedRxPBUFs);
+ rpp_sci_printf((const char *) "\n");
+ rpp_sci_printf((const char *) "PBUF Chains filled:\t%d\t%d",filledTxPBUFChains,filledRxPBUFChains);
+ rpp_sci_printf((const char *) "\n");
+ rpp_sci_printf((const char *) "PBUFs filled:\t%d\t%d",filledTxPBUFs,filledRxPBUFs);
+ rpp_sci_printf((const char *) "\n");
+ rpp_sci_printf((const char *) "\n");
+}
+#endif
+
+#define BUF_SIZE 15
+
+unsigned long readNum(uint8_t minamount, uint8_t maxamount, boolean_t hex){
+ unsigned long out = 0;
+ uint8_t input_buffer[BUF_SIZE];
+ uint8_t buf_index = 0;
+ uint8_t input;
+ do{
+ input = rpp_sci_getc();
+ if(input == '\b' && buf_index>0){
+ input_buffer[buf_index] = '\0';
+ buf_index--;
+ echo('\b');
+ echo( ' ');
+ echo('\b');
+ }else if(buf_index>=maxamount){
+ continue;
+ }else if(input <= '9' && input >= '0'){
+ input_buffer[buf_index] = input - '0';
+ echo(input);
+ buf_index++;
+ }else if(hex && (input <= 'f' && input >= 'a')){
+ input_buffer[buf_index] = input - ('a' - 10);
+ echo(input);
+ buf_index++;
+ }else if(hex && (input <= 'F' && input >= 'A')){
+ input_buffer[buf_index] = input - ('A' - 10);
+ echo((input + ('a' - 'A')));
+ buf_index++;
+ }
+ }while( (input != '\r' && input != '\n' && buf_index<BUF_SIZE) || buf_index<minamount);
+ input = 0; /* use as index */
+ while(input < buf_index){
+ if(hex){
+ out = (out << 4) + input_buffer[input];
+ }else{
+ out = (out*10) + input_buffer[input];
+ }
+ input++;
+ }
+ return out;
+}
+
+int cmd_do_bufferdescriptors(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
+{
+ uint8_t input;
+ volatile struct emac_tx_bd *bufferDescriptor;
+ boolean_t run = TRUE;
+ struct netif *netif = rpp_eth_get_netif(INTERFACE_INSTANCE_NUMBER);
+ if(netif == NULL)
+ {
+ rpp_sci_printf((const char *) "netif err\n");
+ return -1;
+ }
+
+ while(run){
+ input = rpp_sci_getc();
+
+ if(input == 'b'){ /* print buffer descriptor at given address */
+ rpp_sci_printf((const char *) "-? 0x");
+ bufferDescriptor = (struct emac_tx_bd *) readNum(8,8,TRUE);
+ rpp_sci_printf((const char *) "\n");
+ /* check it fits EMAC CPPI RAM */
+ /*if(bufferDescriptor >= EMAC_CTRL_RAM_BASE_m(INTERFACE_INSTANCE_NUMBER) && (bufferDescriptor + sizeof(struct emac_tx_bd)) <= EMAC_CTRL_RAM_BASE_m(INTERFACE_INSTANCE_NUMBER) + SIZE_EMAC_CTRL_RAM)
+ {*/
+ print_bd_content(bufferDescriptor, FALSE);
+ /*}
+ else
+ {
+ rpp_sci_printf((const char *) "address not from BD CPPI RAM range\n");
+ }*/
+ while(1){
+ input = rpp_sci_getc();
+ if (input == 'n'){ /* next */
+ bufferDescriptor = bufferDescriptor->next;
+ if(bufferDescriptor != NULL){
+ print_bd_content(bufferDescriptor, FALSE);
+ }else{
+ rpp_sci_printf((const char *) "NULL\n");
+ break;
+ }
+ }else if(input == 'p'){ /* previous */
+ bufferDescriptor = findPreviousBD(bufferDescriptor);
+ if((int32_t)bufferDescriptor != -1)
+ {
+ if(bufferDescriptor == NULL){
+ rpp_sci_printf((const char *) "NULL\n");
+ break;
+ }else{
+ print_bd_content(bufferDescriptor, FALSE);
+ }
+ }
+ else
+ {
+ rpp_sci_printf((const char *) "not found\n");
+ break;
+ }
+ }else if(input == 'r'){ /* reprint */
+ if((int32_t)bufferDescriptor == -1 || bufferDescriptor == NULL)break;
+ print_bd_content(bufferDescriptor, FALSE);
+ }else break;
+ }
+ }
+
+ if (input == 'q'){ /* quit */
+ run = FALSE;
+ continue;
+ }
+#if RPP_ETH_STATS
+ else if(input == 's'){ /* general statistics */
+ printStatistics();
+ }else if(input == 't'){ /* print tx channel */
+ print_tx_channel_stat();
+ continue;
+ }else if(input == 'r'){ /* print rx channel */
+ print_rx_channel_stat();
+ continue;
+ }
+#endif
+ else if(input == 'a'){ /* autocheck consistency of buffer descriptors */
+
+ }else if(input == 'o'){ /* overview */
+ uint8_t mode = rpp_sci_getc() - '0';
+ uint8_t param = rpp_sci_getc() - '0';
+ print_bds_state(mode, param);
+ }else if(input == 'c'){ /* convert */
+ rpp_sci_printf((const char *) "0x%08x", bd_addr((uint16_t)readNum(1, 3, FALSE)));
+ }
+ }
+
+ return ERR_OK;
+}
+
+int cmd_do_dhcp(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
+{
+ rpp_sci_printf((const char *) "not implemented yet.");
+ return ERR_OK;
+}
+
+#if LWIP_STATS_DISPLAY
+int cmd_do_lwip(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
+{
+ rpp_sci_printf((const char *) "not implemented yet.");
+ void stats_display();
+ /*
+ void stats_display_proto(struct stats_proto *proto, const char *name);
+ void stats_display_igmp(struct stats_igmp *igmp, const char *name);
+ void stats_display_mem(struct stats_mem *mem, const char *name);
+ void stats_display_memp(struct stats_mem *mem, int index);
+ void stats_display_sys(struct stats_sys *sys);*/
+ return ERR_OK;
+}
+#endif
+
+#endif /* DOCGEN */
+
+cmd_des_t const cmd_des_bufferdescriptors={
+ 0,0,
+ "bd","Examine emac buffer descriptors",
+
+ "=== Command syntax ===\n"
+ "\n"
+ " bd\n"
+ "\n"
+ "=== Description ===\n"
+ "After startup you use keys to control what will be done.\n"
+ " q - quit\n"
+ " s - general statistics\n"
+ " t - transmit channel status\n"
+ " r - receive channel status\n"
+ " b - after giving address of bd it prints bd content\n"
+ " a - checks consistency of buffer descriptors\n"
+ "\n"
+ "\n"
+ "=== Example ===\n"
+ "\n"
+ " --> bd\n"
+ " \n",
+ CMD_HANDLER(cmd_do_bufferdescriptors), (void *)&cmd_list_netstats
+};
+
+cmd_des_t const cmd_des_dhcp={
+ 0,0,
+ "dhcp","Prints and controls DHCP",
+
+ "=== Command syntax ===\n"
+ "\n"
+ " dhcp\n"
+ "\n"
+ "=== Description ===\n"
+ "\n"
+ "\n"
+ ".\n"
+ "\n"
+ "=== Example ===\n"
+ "\n"
+ " --> dhcp\n"
+ " \n",
+ CMD_HANDLER(cmd_do_dhcp), (void *)&cmd_list_netstats
+};
+
+#if LWIP_STATS_DISPLAY
+cmd_des_t const cmd_des_lwip={
+ 0,0,
+ "lwip","Prints statistics for the LwIP stack",
+
+ "=== Command syntax ===\n"
+ "\n"
+ " lwip\n"
+ "\n"
+ "=== Description ===\n"
+ "\n"
+ "\n"
+ ".\n"
+ "\n"
+ "=== Example ===\n"
+ "\n"
+ " --> lwip\n"
+ " \n",
+ CMD_HANDLER(cmd_do_lwip), (void *)&cmd_list_netstats
+};
+#endif
+
+/** List of commands for lwip, defined as external */
+cmd_des_t const *cmd_list_netstats[]={
+ &cmd_des_bufferdescriptors,
+ &cmd_des_dhcp,
+#if LWIP_STATS_DISPLAY
+ &cmd_des_lwip,
+#endif
+ NULL
+};
+
--- /dev/null
+/*
+ * cmd_netstats.h
+ *
+ * Created on: 23.8.2013
+ * Author: Jan Doležal
+ */
+
+#ifndef CMD_NETSTATS_H_
+#define CMD_NETSTATS_H_
+
+#include "cmdproc.h"
+
+#define echo(x) rpp_sci_putc(x)
+
+extern cmd_des_t const *cmd_list_netstats[];
+
+#endif /* CMD_NETSTATS_H_ */
-Subproject commit 32fffc216a30394bfedd3a3b20a5c2f42afa8a10
+Subproject commit a4d0cb921de99b9a39c4a96b570c5ec184e9c3e0