ZYNQ TCP client 断连检测
- 定时向服务器发送数据,如果数据发送失败,lwip会执行用户注册的错误回调函数
- 在回调函数中删除连接,并复位phy(硬复位或软复位,防止 phy内部出现错误)
- 在主循环定时检测连接状态,进行重新连接
1.在应用层读写phy寄存器
在应用层能获取phy状态的关键是使用phy读取函数,phy读取函数的关键参数是XEmacPs的实例。
LONG XEmacPs_PhyRead(XEmacPs *InstancePtr, u32 PhyAddress,
u32 RegisterNum, u16 *PhyDataPtr)
追踪zynq lwip初始化步骤就会发现,在low_level_init 函数返回时,netif->state中保存了xemac的指针,而xemac->state 中保存了 xemacpsif的指针。
static err_t low_level_init(struct netif *netif)
{
UINTPTR mac_address = (UINTPTR)(netif->state);
struct xemac_s *xemac;
xemacpsif_s *xemacpsif;
s32_t status = XST_SUCCESS;
NetIf = netif;
xemacpsif = mem_malloc(sizeof *xemacpsif);
xemac = mem_malloc(sizeof *xemac);
xemac->state = (void *)xemacpsif;
...........省略.............
/* replace the state in netif (currently the emac baseaddress)
* with the mac instance pointer.
*/
netif->state = (void *)xemac;
return ERR_OK;
}
而xemacpsif 结构体中保存了我们需要的XEmacPs实例。
/* structure within each netif, encapsulating all information required for
* using a particular temac instance
*/
typedef struct {
XEmacPs emacps;
/* queue to store overflow packets */
pq_queue_t *recv_q;
pq_queue_t *send_q;
/* pointers to memory holding buffer descriptors (used only with SDMA) */
void *rx_bdspace;
void *tx_bdspace;
unsigned int last_rx_frms_cntr;
} xemacpsif_s;
2. 网线断开重连逻辑
//错误处理函数
static void client_err(void *arg, err_t err)
{
close_tcp_client();
}
void close_tcp_client(void)
{
err_t err1;
if (client_pcb != NULL) {
tcp_close(client_pcb);
tcp_sent(client_pcb, NULL);
tcp_err(client_pcb, NULL);
err1 = tcp_close(client_pcb);
if (err1 != ERR_OK) {
/* Free memory with abort */
tcp_abort(client_pcb);
}
client_pcb = NULL;
}
tcp_connect_ok = ERR_CLSD;
reconnect_flag = 1;
}
void rfid_reconnect(void)
{
uint16_t reg_val;
struct xemac_s *xemac = (struct xemac_s *)(server_netif.state);
xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
if(reconnect_flag == 1)
{
XEmacPs_PhyRead(&(xemacpsif->emacps),1,1,®_val);
if(reg_val & 0x04){
//添加client 连接初始化函数
client_init();
reconnect_flag = 0;
}
}
}
//主循环中调用方式
while (1) {
if (TcpFastTmrFlag) {
rfid_reconnect();
tcp_fasttmr();
TcpFastTmrFlag = 0;
}
if (TcpSlowTmrFlag) {
tcp_slowtmr();
TcpSlowTmrFlag = 0;
}
xemacif_input(netif);
transfer_data();
}
在应用层通过mdio接口获取phy第一个寄存器(BMSR)的bit2,检测网线插拔状态
3. SDK工程源码
https://download.csdn.net/download/qq_33878427/87842487