最近做一个东西需要使用网络协议,使用SPI接亚信AX88796C。 使用开源的LWIP协议栈。看了一下从tcp_recv到底层驱动的调用,以便移植。查了一下tcp_recv
/** * Used to specify the function that should be called when a TCP * connection receives data. * * @param pcb tcp_pcb to set the recv callback * @param recv callback function to call for this pcb when data is received */ void tcp_recv(struct tcp_pcb *pcb, err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)) { pcb->recv = recv; }
只是把用户的接收函数挂在pcb结构里。需要找到recv真正调用的地方。
其实是下面这个宏:
#define TCP_EVENT_RECV(pcb,p,err,ret) \
do { \
if((pcb)->recv != NULL) { \
(ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); \
} else { \
(ret) = ERR_OK; \
if (p != NULL) \
pbuf_free(p); \
} \
} while (0)
找到这个宏是在
/**
* The initial input processing of TCP. It verifies the TCP header, demultiplexes
* the segment between the PCBs and passes it on to tcp_process(), which implements
* the TCP finite state machine. This function is called by the IP layer (in
* ip_input()).
*
* @param p received TCP segment to process (p->payload pointing to the IP header)
* @param inp network interface on which this segment was received
*/
void
tcp_input(struct pbuf *p, struct netif *inp)
{
:
/* Notify application that data has been received. */
TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
:
}
在tcp_in.c中有段注释
/**
* @file
* Transmission Control Protocol, incoming traffic
*
* The input processing functions of the TCP layer.
*
* These functions are generally called in the order (ip_input() ->)
* tcp_input() -> * tcp_process() -> tcp_receive() (-> application).
*
*/
就是数据的处理流程从ip到tcp到用户的app,就是这个顺序。在数据准备好之后调用TCP_EVENT_RECV().
ip_input()则由ethernet_input调用。
ethernet_input则在xxxx_if.c中被xxxxif_input()调用
xxxxif_input()是在网络芯片的中断函数中调用。
所以基本流程就是
中断处理函数----〉xxxxif_input()-----〉ethernet_input() -----〉ip_input()------〉tcp_input()------〉tcp_process()-----〉 tcp_receive() (-> application)
||
--------〉CP_EVENT_RECV()
所以用户的recv函数应该也是属于在中断中执行的,如果recv函数中还需要使用中断则需要注意中断嵌套等问题。