這裏只講raw編程,如果你使用LWIP-socket或netconn,那就不存在這個問題,這些高級函數會自己在合適的地方調用tcp_recved函數。
問題的來源
對於初學者而言,LWIP收不到數據是個常見的問題。有不少網絡上流傳的源碼,一個典型的例子是tcp_echoserver。各個教學的資料中也都提供源碼。但很可惜,這些教學板提供的源碼缺乏可移植性。一具最常見的錯誤在於,大家對於什麼時候調用tcp_reved沒什麼概念。有不少源碼是在tcp_server_sent發送函數中調用該功能的。問題就是,如果用戶不是用來echo(立即發回相同的報文),而是真正要處理事務的時候,這種用法是錯誤的:此時,接收窗口大小由發送窗口決定,如果沒有發送新數據,接收窗口就會越來越小,直到最後無法接收數據。
正確的用法是:在收到數據後,應用層調用tcp_recved函數恢復原來的窗口大小;而在發送函數中,不用管窗口的事!
源碼全部貼在後面,這裏講解一些需要注意的地方
第一點
接收數據的PCB控制塊只能是tcp_active_pcbs上面的,而不是我們創建的那個用於tcp_listen的監聽控制塊,這個塊其實一直處於LISTEN狀態,是不能收發數據的。所以,如果你想在程序的任意位置發送信息,調用tcp_write(tcp_active_pcbs, ......) 是沒有問題的,當然要注意,如果你建立了多個鏈接,這裏tcp_active_pcbs只會使用到前面第一個。
通常,如果你要找的剛剛ESTALISHED的那個PCB,是在tcp_echoserver_accept中傳遞進來的,在下面的代碼中,就是這個, pcb = tcp_echoserver_es->pcb;
第二點
接收完數據後,調用tcp_recved擴大窗口。tcp_recved函數中,最關鍵的代碼是
pcb->rcv_wnd += len;
也就是恢復或擴大窗口的意思。爲什麼呢?
因爲tcp_receive函數在收到數據後,會把窗口縮小,表示接收數據的空間被剛收到的數據佔用了,所以你在tcp_receive中可以看到這樣的語句,
pcb->rcv_wnd -= tcplen;
pcb->rcv_wnd -= TCP_TCPLEN(cseg);
故而,在應用層處理完這些數據後,要通知LWIP,這些空間可以恢復到原來大小了,那些數據已經用過了。
源碼
源碼就不貼全部了,STM32CUBEMX配置就可以了,爲了方便,我隨便找個鏈接
https://blog.csdn.net/hustwf/article/details/80040578
按歸上面的做完了,把下面的代碼加進去就差不多了;如果還有,就是再把自己要用的如串口什麼自己加進去。
注意下面這個源碼也是從網絡上弄來的,但我改寫並增加了部分代碼:
1)print_msg函數是一個相當於重定位的printf到串口發送。網上隨便找一個都差不多。
2)養成習慣,收信息的地方只管收信息,絕不在收信息的函數中處理髮送問題;同樣,發信息的地方只管發信息,也不在這裏處理收信息的問題;這樣做的好處是,儘量解耦函數的功能,可以在任意地方在方便的時候處理消息。
DEMO中文有亂碼,無關緊要,湊和着看吧。
main.c
函數很簡單,MX_LWIP_Init(); 是自動生成的,調用初始化;User_notification(&gnetif); 是打印信息的;循環中使用按鍵0創建連接,1關閉連接。
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t key = 0;
HAL_DeInit();
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_LWIP_Init();
//MX_UART5_Init();
/* USER CODE BEGIN 2 */
User_notification(&gnetif);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
MX_LWIP_Process(); // <==> ethernetif_input(&gnetif); sys_check_timeouts();
key = key_scan(0);
if(key == KEY0_PRES){
tcp_echoserver_connect(); // create a receive/transmission connection
}
if(key == KEY1_PRES){
tcp_echoserver_close();
}
#ifdef USE_DHCP
DHCP_Periodic_Handle(&gnetif);
#endif
// send out all received data!
TransData();
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
tcp_echoserver.h
#ifndef __TCP_ECHOSERVER_H__
#define __TCP_ECHOSERVER_H__
/* °üº¬Í·Îļþ ----------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
#include "tcp_def.h"
#include "stdio.h"
#include "string.h"
/* ÀàÐͶ¨Òå ------------------------------------------------------------------*/
// TCP server connection status
enum tcp_echoserver_states
{
ES_NONE = 0,
ES_ACCEPTED,
ES_RECEIVED,
ES_CLOSING
};
// LwIP struct use by callback
struct tcp_echoserver_struct
{
u8_t state; // current connection status
u8_t retries;
struct tcp_pcb *pcb; // current pcb (protocol control block)
struct pbuf *p; // current receiving or transmission pbuf
};
#ifdef __cplusplus
extern "C" {
#endif
void tcp_echoserver_connect(void);
void tcp_echoserver_close(void);
int16_t TcpProcessTransmission(uint8_t *pData, uint16_t Size);
#ifdef __cplusplus
}
#endif
#endif /* __TCP_ECHOSERVER */
/******************* (C) COPYRIGHT 2015-2020 ӲʯǶÈëʽ¿ª·¢ÍÅ¶Ó *****END OF FILE****/
tcp_echoserver.c
這裏只講一下TcpProcessTransmission這個函數,這個是我自己寫的,可以在程序的任意地方任何時候調用,用來發送數據的函數。
重點要注意的是, 在tcp_echoserver_recv中,有兩個地方我調用了tcp_recved函數。
/* °üº¬Í·Îļþ ----------------------------------------------------------------*/
#include "tcp_echoserver.h"
#if LWIP_TCP
// private type def --------------------------------------------------------------
struct tcp_pcb *tcp_echoserver_pcb = NULL;
struct tcp_echoserver_struct *tcp_echoserver_es = NULL;
// private macro ----------------------------------------------------------------
// private varaible--------------------------------------------------------------
uint8_t ServerIp[4];
uint8_t tcp_server_recvbuf[TCP_SERVER_RX_BUFSIZE];
// PRIVATE FUNCTIONS-------------------------------------------------------------
static err_t tcp_echoserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err);
static err_t tcp_echoserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
static void tcp_echoserver_error(void *arg, err_t err);
static err_t tcp_echoserver_poll(void *arg, struct tcp_pcb *tpcb);
static err_t tcp_echoserver_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
static void tcp_echoserver_send(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es);
static void tcp_echoserver_connection_close(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es);
// --------------------------------------------------------------------
/**
* º¯Êý¹¦ÄÜ: TCP·þÎñÆ÷²âÊÔ
* ÊäÈë²ÎÊý: ÎÞ
* ·µ »Ø Öµ: ÎÞ
* ˵ Ã÷: ÎÞ
*/
void tcp_echoserver_connect(void)
{
main_flag &= ~((uint16_t)EMF_TCP_CONNECTED);
tcp_echoserver_pcb = tcp_new();
if (tcp_echoserver_pcb != NULL) {
// printf("create a new pcb\n");
err_t err;
// bind local IP to designated port (TCP_SERVER_PORT)
err = tcp_bind(tcp_echoserver_pcb, IP_ADDR_ANY, TCP_SERVER_PORT);
if (err == ERR_OK){
//printf(" binding pcb successfully\n");
tcp_echoserver_pcb = tcp_listen(tcp_echoserver_pcb); // tcp pcb listening / monitoring
tcp_accept(tcp_echoserver_pcb, tcp_echoserver_accept);// Intialize LwIP tcp_accept callback
main_flag |= EMF_TCP_CONNECTED;
}
else {
memp_free(MEMP_TCP_PCB, tcp_echoserver_pcb);
// printf("Binding pcb failed\n");
}
}
else{
// printf("create new pcb failed.\n");
}
}
/**
* brief: ¹Ø±ÕTCPÁ¬½Ó
*/
void tcp_echoserver_close(void)
{
tcp_echoserver_connection_close(tcp_echoserver_pcb, tcp_echoserver_es);
//printf("¹Ø±Õtcp server\n");
}
/**
* brief: LwIP callback of accept, recognizing link establishment!
* tcp_input --> tcp_process(pcb) --> TCP_EVENT_ACCEPT,
* NOTE: tcp_accept_pcb may not be the tcp_active_pcbs (here it is from tcp_active_pcbs)
*/
static err_t tcp_echoserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
{
err_t ret_err;
struct tcp_echoserver_struct *es;
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(err);
// set new pcb priority
tcp_setprio(newpcb, TCP_PRIO_MIN);
// IMPORTANT NOTE: allocation struct mem for pcb information control
es = (struct tcp_echoserver_struct *)mem_malloc(sizeof(struct tcp_echoserver_struct));
tcp_echoserver_es = es;
if (es != NULL)
{
es->state = ES_ACCEPTED; // rcv established
es->pcb = newpcb; // this is the established pcb!!! (pcb->state == ESTABLISHED)
es->retries = 0;
es->p = NULL;
tcp_arg(newpcb, es); // es is now the new pcb parameters
tcp_recv(newpcb, tcp_echoserver_recv); // init tcp_recv() callback
tcp_err(newpcb, tcp_echoserver_error); // init tcp_err() callback
tcp_poll(newpcb, tcp_echoserver_poll, 1); // init tcp_poll callback
ServerIp[0] = newpcb->remote_ip.addr & 0xff; //IADDR4
ServerIp[1] = (newpcb->remote_ip.addr>>8) & 0xff; //IADDR3
ServerIp[2] = (newpcb->remote_ip.addr>>16)& 0xff; //IADDR2
ServerIp[3] = (newpcb->remote_ip.addr>>24)& 0xff; //IADDR1
//printf("Á¬½ÓµÄµçÄÔ¶ËIPΪ£º%d %d %d %d\n",ServerIp[0],ServerIp[1],ServerIp[2],ServerIp[3]);
ret_err = ERR_OK;
}
else
{
// close TCP link
tcp_echoserver_connection_close(newpcb, es);
// return the error code
ret_err = ERR_MEM;
}
return ret_err;
}
/**
* brief: TCP callback of receiving
*/
static err_t tcp_echoserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
char *recdata=0;
struct tcp_echoserver_struct *es;
err_t ret_err;
LWIP_ASSERT("arg != NULL",arg != NULL);
es = (struct tcp_echoserver_struct *)arg;
// if we receive an empty tcp frame from client => close connection
if (p == NULL){
// remote host closed connection
es->state = ES_CLOSING;
if(es->p == NULL){
tcp_echoserver_connection_close(tpcb, es); // we're done sending, close connection
}
else
{
tcp_sent(tpcb, tcp_echoserver_sent); // we're not done yet, acknowledge received packet
tcp_echoserver_send(tpcb, es); // send remaining data
}
ret_err = ERR_OK;
}
// else : a non empty frame was received from client but for some reason err != ERR_OK
else if(err != ERR_OK)
{
// free received pbuf
if (p != NULL)
{
es->p = NULL;
pbuf_free(p);
}
ret_err = err;
}
else if(es->state == ES_ACCEPTED)
{
// first data chunk in p->payload
es->state = ES_RECEIVED;
// store reference to incoming pbuf (chain)
es->p = p;
// initialize LwIP tcp_sent callback function
tcp_sent(tpcb, tcp_echoserver_sent);
recdata=(char *)malloc(p->len*sizeof(char));
if(recdata!=NULL)
{
memcpy(recdata, p->payload, p->len);
print_msg("TCP_Server_Rec:%s\n", recdata);
}
free(recdata); // printf send out already....
//-- commented out bymc
// tcp_echoserver_send(tpcb, es); // send back the received data (echo)
tcp_recved(tpcb, p->tot_len); // added bymc
pbuf_free(p); // added bymc
es->p = NULL; // added bymc
ret_err = ERR_OK;
}
else if (es->state == ES_RECEIVED)
{
// more data received from client and previous data has been already sent
if(es->p == NULL)
{
es->p = p;
recdata=(char *)malloc(p->len*sizeof(char)+1);
if(recdata!=NULL)
{
memcpy(recdata, p->payload, p->len);
recdata[p->len] = 0x0;
print_msg("TCP_Server_Rec:%s\n",recdata);
}
free(recdata);
//-- commented out bymc
//tcp_echoserver_send(tpcb, es); // send back received data
tcp_recved(tpcb, p->tot_len); // added bymc
pbuf_free(p); // added bymc
es->p = NULL; // added bymc
}
else
{
struct pbuf *ptr;
// chain pbufs to the end of what we recv'ed previously
ptr = es->p;
pbuf_chain(ptr, p);
}
ret_err = ERR_OK;
}
else if(es->state == ES_CLOSING)
{
// odd case, remote side closing twice, trash data
tcp_recved(tpcb, p->tot_len);
es->p = NULL;
pbuf_free(p);
ret_err = ERR_OK;
}
else
{
// unkown es->state, trash data
tcp_recved(tpcb, p->tot_len);
es->p = NULL;
pbuf_free(p);
ret_err = ERR_OK;
}
return ret_err;
}
/**
* brief: TCP´íÎó»Øµ÷º¯Êý
*/
static void tcp_echoserver_error(void *arg, err_t err)
{
struct tcp_echoserver_struct *es;
LWIP_UNUSED_ARG(err);
es = (struct tcp_echoserver_struct *)arg;
if (es != NULL)
{
/* free es structure */
mem_free(es);
}
}
/**
* brief: TCP_poll»Øµ÷º¯Êý
*/
static err_t tcp_echoserver_poll(void *arg, struct tcp_pcb *tpcb)
{
err_t ret_err;
struct tcp_echoserver_struct * es;
es = (struct tcp_echoserver_struct *)arg;
if (es != NULL)
{
if (es->p != NULL)
{
tcp_sent(tpcb, tcp_echoserver_sent);
// there is a remaining pbuf (chain) , try to send data
tcp_echoserver_send(tpcb, es);
}
else
{
//* no remaining pbuf (chain)
if(es->state == ES_CLOSING)
{
// close tcp connection
tcp_echoserver_connection_close(tpcb, es);
}
}
ret_err = ERR_OK;
}
else
{
// nothing to be done
tcp_abort(tpcb);
ret_err = ERR_ABRT;
}
return ret_err;
}
/**
* brief: TCP·¢Ëͻص÷º¯Êý
*/
static err_t tcp_echoserver_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
{
struct tcp_echoserver_struct *es;
LWIP_UNUSED_ARG(len);
es = (struct tcp_echoserver_struct *)arg;
es->retries = 0;
if(es->p != NULL)
{
// still got pbufs to send
tcp_sent(tpcb, tcp_echoserver_sent);
tcp_echoserver_send(tpcb, es);
}
else
{
// if no more data to send and client closed connection
if(es->state == ES_CLOSING)
tcp_echoserver_connection_close(tpcb, es);
}
return ERR_OK;
}
/**
* brief: TCP·¢ËÍÊý¾Ýº¯Êý
*/
static void tcp_echoserver_send(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es)
{
struct pbuf *ptr;
err_t wr_err = ERR_OK;
while ((wr_err == ERR_OK) &&
(es->p != NULL) &&
(es->p->len <= tcp_sndbuf(tpcb)))
{
// get pointer on pbuf from es structure
ptr = es->p;
// enqueue data for transmission
wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);
if (wr_err == ERR_OK)
{
u16_t plen;
u8_t freed;
plen = ptr->len;
// continue with next pbuf in chain (if any)
es->p = ptr->next;
if(es->p != NULL){
// increment reference count for es->p
pbuf_ref(es->p);
}
// chop first pbuf from chain
do
{
// try hard to free pbuf
freed = pbuf_free(ptr);
} while(freed == 0);
// we can read more data now
tcp_recved(tpcb, plen);
}
else if(wr_err == ERR_MEM)
{
// we are low on memory, try later / harder, defer to poll
es->p = ptr;
tcp_output(tpcb);
}
else
{
// other problem ??
}
}
}
/**
* brief: ¹Ø±ÕTCPÁ¬½Óº¯Êý
*/
static void tcp_echoserver_connection_close(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es)
{
/* remove all callbacks */
tcp_arg(tpcb, NULL);
tcp_sent(tpcb, NULL);
tcp_recv(tpcb, NULL);
tcp_err(tpcb, NULL);
tcp_poll(tpcb, NULL, 0);
/* delete es structure */
if (es != NULL)
{
mem_free(es);
}
/* close tcp connection */
tcp_close(tpcb);
main_flag &= ~((uint16_t)EMF_TCP_CONNECTED);
}
int16_t TcpProcessTransmission(uint8_t *pData, uint16_t Len){
err_t wr_err = ERR_OK;
struct tcp_pcb * pcb = NULL;
if(tcp_echoserver_es){
pcb = tcp_echoserver_es->pcb;
}
if(pcb && (main_flag & EMF_TCP_CONNECTED)){
wr_err = tcp_write(pcb, pData, Len, 1);
if (wr_err == ERR_OK)
{
// we can read more data now
// tcp_recved(pcb, Len);
}
else if(wr_err == ERR_MEM)
{
// we are low on memory, try later / harder, defer to poll
tcp_output(pcb);
}
else
{
// other problem ??
}
return Len;
}
return 0;
}
#endif /* LWIP_TCP */
app_ethernet.h
#ifndef __APP_ETHERNET_H
#define __APP_ETHERNET_H
/* °üº¬Í·Îļþ ----------------------------------------------------------------*/
#include "lwip/netif.h"
#include "tcp_def.h"
/* ÀàÐͶ¨Òå ------------------------------------------------------------------*/
/* ºê¶¨Òå --------------------------------------------------------------------*/
#define DHCP_OFF (uint8_t) 0
#define DHCP_START (uint8_t) 1
#define DHCP_WAIT_ADDRESS (uint8_t) 2
#define DHCP_ADDRESS_ASSIGNED (uint8_t) 3
#define DHCP_TIMEOUT (uint8_t) 4
#define DHCP_LINK_DOWN (uint8_t) 5
/* À©Õ¹±äÁ¿ ------------------------------------------------------------------*/
/* º¯ÊýÉùÃ÷ ------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
void User_notification(struct netif *netif);
#ifdef USE_DHCP
void DHCP_Process(struct netif *netif);
void DHCP_Periodic_Handle(struct netif *netif);
#endif
#ifdef __cplusplus
}
#endif
#endif /* __APP_ETHERNET_H */
/******************* (C) COPYRIGHT 2015-2020 ӲʯǶÈëʽ¿ª·¢ÍÅ¶Ó *****END OF FILE****/
app_ethernet.c
/* °üº¬Í·Îļþ ----------------------------------------------------------------*/
#include <string.h>
#include "stm32f4xx_hal.h"
#include "lwip/dhcp.h"
#include "app_ethernet.h"
#ifdef USE_DHCP
#define MAX_DHCP_TRIES 4
extern uint32_t DHCPfineTimer; // = 0;
__IO uint8_t DHCP_state = DHCP_OFF;
__IO uint8_t DHCP_flag=0;
#endif
/**
* brief: test tcp server. semd IP address info on netif-up
*/
void User_notification(struct netif *netif)
{
if (netif_is_up(netif)){
#ifdef USE_DHCP
DHCP_state = DHCP_START; // Update DHCP state machine
print_msg("IP address: %s\n", ip4addr_ntoa((const ip4_addr_t *)&netif->ip_addr));
#else
uint8_t iptxt[20];
sprintf((char *)iptxt, "%s", ip4addr_ntoa((const ip4_addr_t *)&netif->ip_addr));
printf ("Static IP address: %s\n", iptxt);
#endif // USE_DHCP
}
else{
#ifdef USE_DHCP
DHCP_state = DHCP_LINK_DOWN; // Update DHCP state machine
#endif // USE_DHCP
print_msg("The network cable is not connected \n");
}
}
/**
* º¯Êý¹¦ÄÜ: ¶ÔÁ´½Ó״̬½øÐÐ֪ͨ
* ÊäÈë²ÎÊý: ÎÞ
* ·µ »Ø Öµ: ÎÞ
* ˵ Ã÷: ÎÞ
*/
void ethernetif_notify_conn_changed(struct netif *netif)
{
#ifndef USE_DHCP
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gw;
#endif
if(netif_is_link_up(netif))
{
print_msg("The network cable is now connected \n");
#ifdef USE_DHCP
DHCP_state = DHCP_START; // Update DHCP state machine
#else
IP_ADDR4(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
IP_ADDR4(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3);
IP_ADDR4(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
netif_set_addr(netif, &ipaddr , &netmask, &gw);
uint8_t iptxt[20];
sprintf((char *)iptxt, "%s", ip4addr_ntoa((const ip4_addr_t *)&netif->ip_addr));
printf ("Static IP address: %s\n", iptxt);
#endif // USE_DHCP
netif_set_up(netif); // When the netif is fully configured this function must be called.
print_msg("IP address: %s\n", ip4addr_ntoa((const ip4_addr_t *)&netif->ip_addr));
}
else
{
#ifdef USE_DHCP
DHCP_state = DHCP_LINK_DOWN; // Update DHCP state machine
#endif // USE_DHCP
netif_set_down(netif); // When the netif link is down this function must be called.
print_msg ("The network cable is not connected.\n");
}
}
#ifdef USE_DHCP
/**
*brief: retrieve DHCP
*/
void DHCP_Process(struct netif *netif)
{
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gw;
struct dhcp *dhcp;
switch (DHCP_state)
{
case DHCP_START:
{
ip_addr_set_zero_ip4(&netif->ip_addr);
ip_addr_set_zero_ip4(&netif->netmask);
ip_addr_set_zero_ip4(&netif->gw);
DHCP_state = DHCP_WAIT_ADDRESS;
dhcp_start(netif);
print_msg("State: Looking for DHCP server ...\n");
break;
}
case DHCP_WAIT_ADDRESS:
{
if (dhcp_supplied_address(netif))
{
DHCP_state = DHCP_ADDRESS_ASSIGNED;
print_msg("IP address assigned by a DHCP server: %s\n", ip4addr_ntoa((const ip4_addr_t *)&netif->ip_addr));
DHCP_flag=1;
}
else
{
dhcp = (struct dhcp *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);
// DHCP timeout
if (dhcp->tries > MAX_DHCP_TRIES)
{
DHCP_state = DHCP_TIMEOUT;
// Stop DHCP
dhcp_stop(netif);
// Static address used
IP_ADDR4(&ipaddr, IP_ADDR0 ,IP_ADDR1 , IP_ADDR2 , IP_ADDR3 );
IP_ADDR4(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
IP_ADDR4(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
netif_set_addr(netif, &ipaddr, &netmask, &gw);
print_msg("DHCP Timeout !! \n");
print_msg("Static IP address: %s\n", ip4addr_ntoa((const ip4_addr_t *)&netif->ip_addr));
}
}
break;
}
case DHCP_LINK_DOWN:
{
// Stop DHCP
dhcp_stop(netif);
DHCP_state = DHCP_OFF;
break;
}
default: break;
}
}
/**
* º¯Êý¹¦ÄÜ: DHCPÂÖѯ
* ÊäÈë²ÎÊý: ÎÞ
* ·µ »Ø Öµ: ÎÞ
* ˵ Ã÷: ÎÞ
*/
void DHCP_Periodic_Handle(struct netif *netif)
{
// Fine DHCP periodic process every 500ms
if (HAL_GetTick() - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS)
{
DHCPfineTimer = HAL_GetTick();
DHCP_Process(netif); // process DHCP state machine
}
}
#endif