Reputation: 1
I'm using an Arty A7 board and have implemented the Echo Server example on it. It works without any problems. I then modified the code to send back other data. It works, but only via the receive callback!
Now I want to send data to the computer at the touch of a button, using tcp_write! The button is read in the main loop and runs the function transfer_data. Here I would like to send data via tcp_write! I actually thought that it should work like this, because it also works in the receive callback. So far, however, I have not been able to get this to work. I get "-16" => Illegal argument (ERR_ARG) as an error code. Here is the modified code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "lwip/err.h"
#include "lwip/tcp.h"
#if defined (__arm__) || defined (__aarch64__)
#include "xil_printf.h"
#endif
//************************************************************
//************************************************************
int transfer_data() {
err_t err;
struct tcp_pcb *tpcb;
xil_printf("transfer data\n\r");
err = tcp_write(tpcb, "data", 4, 1);
xil_printf("%d\n\r", err);
return 0;
}
//************************************************************
//************************************************************
void print_app_header()
{
#if (LWIP_IPV6==0)
xil_printf("\n\r\n\r-----lwIP TCP echo server ------\n\r");
#else
xil_printf("\n\r\n\r-----lwIPv6 TCP echo server ------\n\r");
#endif
xil_printf("TCP packets sent to port 6001 will be echoed back\n\r");
}
//************************************************************
//************************************************************
err_t recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
/* do not read the packet if we are not in ESTABLISHED state */
if (!p) {
tcp_close(tpcb);
tcp_recv(tpcb, NULL);
return ERR_OK;
}
/* indicate that the packet has been received */
tcp_recved(tpcb, p->len);
/* echo back the payload */
/* in this case, we assume that the payload is < TCP_SND_BUF */
/* change: we receive "Hello" and send back "World" */
if (tcp_sndbuf(tpcb) > p->len) {
//err = tcp_write(tpcb, p->payload, p->len, 1);
xil_printf("data received: %s (%d)\r\n", p->payload, strlen(p->payload));
//xil_printf("Total data received: %s (%d)\r\n", p->payload, p->len);
//xil_printf("data received: %s (%d)\r\n", cmd, strlen(cmd));
char tdata[128];
memset(tdata, 0, sizeof(tdata));
char buf[128];
memset(buf, 0, sizeof(buf));
memcpy(buf, p->payload, p->len);
char * cmd = strtok(buf, "\r\n");
xil_printf("cmd received: %s (%d)\r\n", cmd, strlen(cmd));
while(cmd != NULL) {
if(strcmp(cmd, "Hello") == 0) {
strcat(tdata,"World");
xil_printf("World\n\r");
}
else if(strcmp(cmd, "TEST") == 0) {
strcat(tdata,"0123456789");
xil_printf("Test\n\r");
}
// look for next part
cmd = strtok(NULL, "\r\n");
}
free (cmd);
if(strlen(tdata) > 0) {
err = tcp_write(tpcb, &tdata, strlen(tdata), 1);
}
}
else
xil_printf("no space in tcp_sndbuf\n\r");
/* free the received pbuf */
pbuf_free(p);
return ERR_OK;
}
//************************************************************
//************************************************************
// active for debugging
err_t sent_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err){
xil_printf("data were sent\n\r");
return ERR_OK;
}
//************************************************************
//************************************************************
err_t accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err)
{
static int connection = 1;
xil_printf("Incoming connection: %d.%d.%d.%d - port: %d \r\n",
(u8)(newpcb->remote_ip.addr),
(u8)(newpcb->remote_ip.addr >> 8),
(u8)(newpcb->remote_ip.addr >> 16),
(u8)(newpcb->remote_ip.addr >> 24),
newpcb->remote_port);
/* set the receive callback for this connection */
// tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv)
tcp_recv(newpcb, recv_callback);
//set the sent callback for this connection
//info = void tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent)
tcp_sent(newpcb, sent_callback);
/* just use an integer number indicating the connection id as the
callback argument */
tcp_arg(newpcb, (void*)(UINTPTR)connection);
/* increment for subsequent accepted connections */
connection++;
return ERR_OK;
}
//************************************************************
//************************************************************
int start_application()
{
struct tcp_pcb *pcb;
err_t err;
unsigned port = 7;
/* create new TCP PCB structure */
pcb = tcp_new_ip_type(IPADDR_TYPE_ANY);
if (!pcb) {
xil_printf("Error creating PCB. Out of Memory\n\r");
return -1;
}
/* bind to specified @port */
err = tcp_bind(pcb, IP_ANY_TYPE, port);
if (err != ERR_OK) {
xil_printf("Unable to bind to port %d: err = %d\n\r", port, err);
return -2;
}
/* we do not need any arguments to callback functions */
tcp_arg(pcb, NULL);
/* listen for connections */
pcb = tcp_listen(pcb);
if (!pcb) {
xil_printf("Out of memory while tcp_listen\n\r");
return -3;
}
/* specify callback to use for incoming connections */
tcp_accept(pcb, accept_callback);
xil_printf("TCP echo server started @ port %d\n\r", port);
return 0;
}
Because of the error message I think that no memory was allocated for sending data. Or I made a mistake when assigning pcb! I have tried to allocate memory and re-establish a connection only for sending! There are only a few applicable examples in the lwip documentation. I have therefore searched for similar contributions, but have not found a suitable solution!
Perhaps the community can point me in the right direction. I would be very grateful for your help!
Upvotes: 0
Views: 929