Before porting the LWIP is simply to do a DHCP program, but the actual work is often used to communicate, that today to talk about how to use LWIP for UDP communication
The first step to using data communication is to know how the LWIP is to keep it, and when communicating with Netconn packets, NETBUF is the main data structure, which is composed of the following
struct netbuf { struct pbuf *p, *ptr; ip_addr_t addr; u16_t Port; #if Lwip_netbuf_recvinfo | | Lwip_checksum_on_copy#if lwip_checksum_on_copy u8_t flags; #endif /* lwip_checksum_on_copy */ u16_t toport_chksum; #if Lwip_netbuf_recvinfo ip_addr_t toaddr; #endif /* lwip_netbuf_recvinfo */#endif /* lwip_netbuf_recvinfo | | Lwip_checksum_on_copy */};
It's a long string, but you don't have to figure it all out. Just pay attention to the few
struct pbuf *p, *ptr;ip_addr_t addr;u16_t port;
First, there is a pbuf list in the system, p points to the top of the pbuf, and PTR points to the Pbuf,netbuf_next () and Netbuf_first () operation PTR fields that are currently in use. The addr and port fields are used to record the IP address and port number of the data sender, and the two macros, NETBUF_FROMADDR and netbuf_fromport, are defined to return the fields addr and port. the relationship between Netbuf and Pbuf
Whether it is a TCP connection or a UDP connection, receiving the packet will encapsulate the data in a netbuf and then hand the NETBUF to the application for processing. When data is sent, there are different processes depending on the connection: for TCP connections
Then, the user only needs to provide the starting address and length of the data to be sent, the kernel will encapsulate the data in the appropriate size packet according to the actual situation, and put it into the send queue, for UDP, the user will need to encapsulate the data in the NETBUF structure.
, the kernel sends the data in the packet directly when the sending function is called.
The API for operating netbuf is mainly the following
This is just the data structure, followed by the API that uses these data structures, mainly the following
Here is a new data structure called Netconn, which is our core today, and his composition is as follows
/** A Netconn descriptor*/structNetconn {/** Connection Type (TCP, UDP or RAW)*/ enumNetconn_type type; /** Current Connection status*/ enumNetconn_state State; /** The control block pointers in the kernel associated with this*/Union {structIP_PCB *IP; structTCP_PCB *TCP; structUDP_PCB *UDP; structRAW_PCB *Raw; } PCB; /** This link is a recent error*/err_t Last_err; /** Semaphores for two API context synchronization*/sys_sem_t op_completed; /** Message mailbox to receive data*/sys_mbox_t Recvmbox;#ifLwip_tcp/** Buffer queue for TCP server, connection request*/sys_mbox_t Acceptmbox;#endif/* LWIP_TCP *//** Socket descriptor for the Socket class API*/#ifLwip_socketintsocket;#endif/* Lwip_socket */#ifLwip_so_sndtimeo/** Timeout period for sending data*/s32_t send_timeout;#endif/* Lwip_so_rcvtimeo */#ifLwip_so_rcvtimeo/** Timeout period for receiving data*/ intrecv_timeout;#endif/* Lwip_so_rcvtimeo */#ifLwip_so_rcvbuf/** Receive Message Queue Length*/ intrecv_bufsize; /** Data length that is already cached in the current receive mailbox*/s16_t Recv_avail;#endif/* LWIP_SO_RCVBUF *//** Netconn Internal status identifier*/u8_t flags;#ifLwip_tcp/** When the call Netconn_write sends the data but the cache is insufficient, the data is temporarily stored in the current_msg, waiting for the next data to be sent, Write_offset to record the next time the index is sent*/size_t Write_offset; /** Tcp:when data passed to Netconn_write doesn ' t fit into the send buffer, this temporarily stores the message. Also used during connect and close. */ structApi_msg_msg *current_msg;#endif/* LWIP_TCP *//**//Connect related callback function, use when implementing socket API*/Netconn_callback callback;};
There are some enumerations associated with this API, so let's not say this, basically through these APIs to network communication, then see how to implement UDP communication
The process is this: Create a UDP link-bind a UDP port-set the destination port and IP, and then can send, because the UDP itself is not connected, so we do not need to wait for UDP repeatedly on the operation, the specific code is as follows
//Create a UDP thread//return Value: 0 UDP creation succeeded//other UDP creation failedInt8u Udp_demo_init (void) {int8u res; OS_CPU_SR Cpu_sr; Os_enter_critical (); //off Interruptres = Ostaskcreate (Udp_thread, (void*)0, (os_stk*) &udp_task_stk[udp_stk_size-1],udp_prio);//Create a UDP threadOs_exit_critical ();//Open Interrupt returnRes;}
Tasks after creating a task are as follows
//UDP task FunctionStatic voidUdp_thread (void*Arg) {OS_CPU_SR cpu_sr; err_t err; Static structNetconn *Udpconn; Static structNETBUF *Recvbuf; Static structNETBUF *Sentbuf; structip_addr destipaddr; U32 Data_len=0; structPBUF *Q; while(Dhcpstatus! =2)//wait for DHCP to succeed{ostimedly (Ten); printf ("wait dhcp\r\n"); } lwip_unused_arg (ARG); Udpconn= Netconn_new (NETCONN_UDP);//Create a UDP linkUdpconn->recv_timeout =Ten; if(Udpconn! = NULL)//Create UDP connection succeeded{Err=Netconn_bind (Udpconn,ip_addr_any,udp_demo_port); IP4_ADDR (&DESTIPADDR,192,168,1, the);//construct Destination IP addressNetconn_connect (Udpconn,&destipaddr,udp_demo_port);//connecting to a remote host if(Err = = ERR_OK)//Binding Complete { while(1) { if(KeyValue = =Key_down) {Udp_flag=Lwip_send_data; } if((Udp_flag & lwip_send_data) = = Lwip_send_data)//have data to send{sentbuf=netbuf_new (); Netbuf_alloc (Sentbuf,strlen (Char*) (UDP_DEMO_SENDBUF)) ; Sentbuf->p->payload = (Char*) Udp_demo_sendbuf;//refers to the UDP_DEMO_SENDBUF groupErr = Netconn_send (UDPCONN,SENTBUF);//send the data from the Netbuf if(Err! =ERR_OK) {printf ("send failed \ r \ n"); Netbuf_delete (SENTBUF); //Delete buf} udp_flag&= ~lwip_send_data;//Clear Data Send flagNetbuf_delete (SENTBUF);//Delete bufKeyValue =0; } netconn_recv (Udpconn,&RECVBUF);//Receive Data if(Recvbuf! = NULL)//receiving Data{os_enter_critical ();//off Interruptprintf"Receive data\r\n"); memset (Udp_demo_recvbuf,0, udp_demo_rx_bufsize);//data receive buffer clear 0 for(Q=recvbuf->p;q!=null;q=q->next)//traverse the complete list of Pbuf { //determine if the data to be copied to the udp_demo_rx_bufsize is greater than the remaining space of udp_demo_rx_bufsize, if it is greater than//only copy the remaining length of data in the udp_demo_rx_bufsize, otherwise copy all the data if(Q->len > (udp_demo_rx_bufsize-Data_len)) memcpy (Udp_demo_recvbuf+data_len,q->payload, (Udp_demo_rx_bufsize-data_len));//Copy Data Elsememcpy (Udp_demo_recvbuf+data_len,q->payload,q->Len); Data_len+ = Q->Len; if(Data_len >udp_demo_rx_bufsize) Break;//beyond the TCP client receive array, jump out} os_exit_critical (); //Open Interruptdata_len=0;//after the copy is complete, Data_len to clear zero. //print the Received dataprintf"%s\r\n", UDP_DEMO_RECVBUF); Netbuf_delete (RECVBUF); //Delete buf } ElseOstimedlyhmsm (0,0,0,Ten);//Delay 5ms } } Elseprintf ("UDP bind failed \ r \ n"); } Elseprintf ("UDP connection creation failed \ r \ n");}
There's nothing to say, but note that it's best to set the priority of UDP below the priority of the data Query task
The project code is as follows
http://download.csdn.net/detail/dengrengong/8599069
LWIP_STM32_ENC28J60_NETCONN_UDP (3)