LwIP网卡设计与实现上
netif相关结构体
netif flag
#define NETIF_FLAG_UP 0x01U
#define NETIF_FLAG_BROADCAST 0x02U
#define NETIF_FLAG_LINK_UP 0x04U
#define NETIF_FLAG_ETHARP 0x08U
#define NETIF_FLAG_ETHERNET 0x10U
netif结构体
struct netif {
struct netif *next;
#if LWIP_IPV4
ip_addr_t ip_addr;
ip_addr_t netmask;
ip_addr_t gw;
#endif
netif_input_fn input;
#if LWIP_IPV4
netif_output_fn output;
#endif
netif_linkoutput_fn linkoutput;
#if LWIP_NETIF_STATUS_CALLBACK
netif_status_callback_fn status_callback;
#endif
#if LWIP_NETIF_LINK_CALLBACK
netif_status_callback_fn link_callback;
#endif
#if LWIP_NETIF_REMOVE_CALLBACK
netif_status_callback_fn remove_callback;
#endif
void *state;
#if LWIP_NETIF_HOSTNAME
const char* hostname;
#endif
#if LWIP_CHECKSUM_CTRL_PER_NETIF
u16_t chksum_flags;
#endif
u16_t mtu;
u8_t hwaddr_len;
u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
u8_t flags;
char name[2];
u8_t num;
#if LWIP_IPV4 && LWIP_IGMP
netif_igmp_mac_filter_fn igmp_mac_filter;
#endif
};
netif API
netif_add
struct netif *netif_add(struct netif *netif,const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,void *state, netif_init_fn init, netif_input_fn input);
netif_set_default
void netif_set_default(struct netif *netif);
netif_set_up&netif_set_down
void netif_set_up(struct netif *netif);
void netif_set_down(struct netif *netif);
callback
#if LWIP_NETIF_LINK_CALLBACK
void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback);
#endif
netif 底层接口(跟硬件打交道的)
ethernetif_init
err_t ethernetif_init(struct netif *netif);
ethernetif_input
void ethernetif_input(void const * argument);
low_level_init
static void low_level_init(struct netif *netif);
low_level_output
static err_t low_level_output(struct netif *netif, struct pbuf *p);
low_level_input
static struct pbuf * low_level_input(struct netif *netif);
lwIP网卡设计与实现下
tcpip_init
void tcpip_init(tcpip_init_done_fn initfunc, void *arg)
{
lwip_init();
tcpip_init_done = initfunc;
tcpip_init_done_arg = arg;
if (sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
}
#if LWIP_TCPIP_CORE_LOCKING
if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
LWIP_ASSERT("failed to create lock_tcpip_core", 0);
}
#endif
sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
}
lwip_init
void lwip_init(void)
{
stats_init();
#if !NO_SYS
sys_init();
#endif
mem_init();
memp_init();
pbuf_init();
netif_init();
#if LWIP_IPV4
ip_init();
#if LWIP_ARP
etharp_init();
#endif
#endif
#if LWIP_RAW
raw_init();
#endif
#if LWIP_UDP
udp_init();
#endif
#if LWIP_TCP
tcp_init();
#endif
#if LWIP_IGMP
igmp_init();
#endif
#if LWIP_DNS
dns_init();
#endif
#if PPP_SUPPORT
ppp_init();
#endif
#if LWIP_TIMERS
sys_timeouts_init();
#endif
}
MX_LWIP_Init
void MX_LWIP_Init(void)
{
IP_ADDRESS[0] = 192;
IP_ADDRESS[1] = 168;
IP_ADDRESS[2] = 1;
IP_ADDRESS[3] = 10;
NETMASK_ADDRESS[0] = 255;
NETMASK_ADDRESS[1] = 255;
NETMASK_ADDRESS[2] = 255;
NETMASK_ADDRESS[3] = 0;
GATEWAY_ADDRESS[0] = 192;
GATEWAY_ADDRESS[1] = 168;
GATEWAY_ADDRESS[2] = 1;
GATEWAY_ADDRESS[3] = 1;
tcpip_init( NULL, NULL );
IP4_ADDR(&ipaddr, IP_ADDRESS[0], IP_ADDRESS[1], IP_ADDRESS[2], IP_ADDRESS[3]);
IP4_ADDR(&netmask, NETMASK_ADDRESS[0], NETMASK_ADDRESS[1] , NETMASK_ADDRESS[2], NETMASK_ADDRESS[3]);
IP4_ADDR(&gw, GATEWAY_ADDRESS[0], GATEWAY_ADDRESS[1], GATEWAY_ADDRESS[2], GATEWAY_ADDRESS[3]);
netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input);
netif_set_default(&gnetif);
if (netif_is_link_up(&gnetif))
{
netif_set_up(&gnetif);
}
else
{
netif_set_down(&gnetif);
}
}
ethernetif_init
err_t ethernetif_init(struct netif *netif)
{
#if LWIP_IPV4
#if LWIP_ARP || LWIP_ETHERNET
#if LWIP_ARP
netif->output = etharp_output;
#else
netif->output = low_level_output_arp_off;
#endif
#endif
#endif
netif->linkoutput = low_level_output;
low_level_init(netif);
return ERR_OK;
}
low_level_init
static void low_level_init(struct netif *netif)
{
uint32_t regvalue = 0;
HAL_StatusTypeDef hal_eth_init_status;
uint8_t MACAddr[6] ;
heth.Instance = ETH;
heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
heth.Init.PhyAddress = DP83848_PHY_ADDRESS;
MACAddr[0] = 0x00;
MACAddr[1] = 0x80;
MACAddr[2] = 0xE1;
MACAddr[3] = 0x00;
MACAddr[4] = 0x00;
MACAddr[5] = 0x00;
heth.Init.MACAddr = &MACAddr[0];
heth.Init.RxMode = ETH_RXINTERRUPT_MODE;
heth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
heth.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
hal_eth_init_status = HAL_ETH_Init(&heth);
if (hal_eth_init_status == HAL_OK)
{
netif->flags |= NETIF_FLAG_LINK_UP;
}
HAL_ETH_DMATxDescListInit(&heth, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
HAL_ETH_DMARxDescListInit(&heth, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
#if LWIP_ARP || LWIP_ETHERNET
netif->hwaddr_len = ETH_HWADDR_LEN;
netif->hwaddr[0] = heth.Init.MACAddr[0];
netif->hwaddr[1] = heth.Init.MACAddr[1];
netif->hwaddr[2] = heth.Init.MACAddr[2];
netif->hwaddr[3] = heth.Init.MACAddr[3];
netif->hwaddr[4] = heth.Init.MACAddr[4];
netif->hwaddr[5] = heth.Init.MACAddr[5];
netif->mtu = 1500;
#if LWIP_ARP
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
#else
netif->flags |= NETIF_FLAG_BROADCAST;
#endif
osSemaphoreDef(SEM);
s_xSemaphore = osSemaphoreCreate(osSemaphore(SEM), 1);
osThreadDef(EthIf, ethernetif_input, osPriorityRealtime, 0, INTERFACE_THREAD_STACK_SIZE);
osThreadCreate (osThread(EthIf), netif);
HAL_ETH_Start(&heth);
HAL_ETH_ReadPHYRegister(&heth, PHY_MICR, ®value);
regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE);
HAL_ETH_WritePHYRegister(&heth, PHY_MICR, regvalue );
HAL_ETH_ReadPHYRegister(&heth, PHY_MISR, ®value);
regvalue |= PHY_MISR_LINK_INT_EN;
HAL_ETH_WritePHYRegister(&heth, PHY_MISR, regvalue);
#endif
}
底层数据收发
HAL_ETH_RxCpltCallback
void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
{
osSemaphoreRelease(s_xSemaphore);
}
ethernetif_input
void ethernetif_input(void const * argument)
{
struct pbuf *p;
struct netif *netif = (struct netif *) argument;
for( ;; )
{
if (osSemaphoreWait(s_xSemaphore, TIME_WAITING_FOR_INPUT) == osOK)
{
do
{
p = low_level_input( netif );
if (p != NULL)
{
if (netif->input( p, netif) != ERR_OK )
{
pbuf_free(p);
}
}
} while(p!=NULL);
}
}
}
low_level_input
/**
*/
static struct pbuf * low_level_input(struct netif *netif)
{
struct pbuf *p = NULL;
struct pbuf *q = NULL;
uint16_t len = 0;
uint8_t *buffer;
__IO ETH_DMADescTypeDef *dmarxdesc;
uint32_t bufferoffset = 0;
uint32_t payloadoffset = 0;
uint32_t byteslefttocopy = 0;
uint32_t i=0;
/*
通过HAL库,获取网卡帧数据
*/
if (HAL_ETH_GetReceivedFrame_IT(&heth) != HAL_OK)
return NULL;
/*
获取网卡数据超度,及内存地址
*/
len = heth.RxFrameInfos.length;
buffer = (uint8_t *)heth.RxFrameInfos.buffer;
//网卡中数据有效
if (len > 0)
{
/*
网卡数据不能大于1500
属于原始层接口
*/
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
}
//如果pbuf创建成功,则从ETH中拷贝数据到pbuf里,最终把pbuf返回给上层应用
if (p != NULL)
{
dmarxdesc = heth.RxFrameInfos.FSRxDesc;
bufferoffset = 0;
for(q = p; q != NULL; q = q->next)
{
byteslefttocopy = q->len;
payloadoffset = 0;
/* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
while( (byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE )
{
/* Copy data to pbuf */
memcpy( (uint8_t*)((uint8_t*)q->payload + payloadoffset), (uint8_t*)((uint8_t*)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset));
/* Point to next descriptor */
dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
buffer = (uint8_t *)(dmarxdesc->Buffer1Addr);
byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset);
payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset);
bufferoffset = 0;
}
/* Copy remaining data in pbuf */
memcpy( (uint8_t*)((uint8_t*)q->payload + payloadoffset), (uint8_t*)((uint8_t*)buffer + bufferoffset), byteslefttocopy);
bufferoffset = bufferoffset + byteslefttocopy;
}
}
/* Release descriptors to DMA */
/* Point to first descriptor */
dmarxdesc = heth.RxFrameInfos.FSRxDesc;
/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
for (i=0; i< heth.RxFrameInfos.SegCount; i++)
{
dmarxdesc->Status |= ETH_DMARXDESC_OWN;
dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
}
/* Clear Segment_Count */
heth.RxFrameInfos.SegCount =0;
/* When Rx Buffer unavailable flag is set: clear it and resume reception */
if ((heth.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET)
{
/* Clear RBUS ETHERNET DMA flag */
heth.Instance->DMASR = ETH_DMASR_RBUS;
/* Resume DMA reception */
heth.Instance->DMARPDR = 0;
}
return p;
}
low_level_output
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
err_t errval;
struct pbuf *q;
uint8_t *buffer = (uint8_t *)(heth.TxDesc->Buffer1Addr);
__IO ETH_DMADescTypeDef *DmaTxDesc;
uint32_t framelength = 0;
uint32_t bufferoffset = 0;
uint32_t byteslefttocopy = 0;
uint32_t payloadoffset = 0;
DmaTxDesc = heth.TxDesc;
bufferoffset = 0;
for(q = p; q != NULL; q = q->next)
{
if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
{
errval = ERR_USE;
goto error;
}
byteslefttocopy = q->len;
payloadoffset = 0;
while( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE )
{
memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset) );
DmaTxDesc = (ETH_DMADescTypeDef *)(DmaTxDesc->Buffer2NextDescAddr);
if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
{
errval = ERR_USE;
goto error;
}
buffer = (uint8_t *)(DmaTxDesc->Buffer1Addr);
byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset);
payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset);
framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset);
bufferoffset = 0;
}
memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), byteslefttocopy );
bufferoffset = bufferoffset + byteslefttocopy;
framelength = framelength + byteslefttocopy;
}
HAL_ETH_TransmitFrame(&heth, framelength);
errval = ERR_OK;
error:
if ((heth.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET)
{
heth.Instance->DMASR = ETH_DMASR_TUS;
heth.Instance->DMATPDR = 0;
}
return errval;
}