硬件连线就是将dp83848的INT脚连到STM32的某个中断脚上,这里是PB14
PB14的中断处理函数中,会释放一个信号量,这里只是发生链路状态改变中断(网线插上或拔下)
1 void EXTI15_10_IRQHandler(void) 2 { 3 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; 4 5 if(EXTI_GetITStatus(ETH_LINK_EXTI_LINE) != RESET) 6 { 7 /* Give the semaphore to wakeup LwIP task */ 8 xSemaphoreGiveFromISR( ETH_link_xSemaphore, &xHigherPriorityTaskWoken ); 9 } 10 /* Clear interrupt pending bit */ 11 EXTI_ClearITPendingBit(ETH_LINK_EXTI_LINE); 12 13 /* Switch tasks if necessary. */ 14 if( xHigherPriorityTaskWoken != pdFALSE ) 15 { 16 portEND_SWITCHING_ISR( xHigherPriorityTaskWoken ); 17 } 18 }
该信号量在eth_bsp.c中定义,在ETH_BSP_Config中创建,同时,启动一个Eth_Link_IT_task任务,阻塞在信号量上,侦听链路状态,
1 xSemaphoreHandle ETH_link_xSemaphore = NULL; 2 3 void ETH_BSP_Config(void) 4 { 5 6 if (ETH_link_xSemaphore == NULL) 7 { 8 /* create binary semaphore used for ETH_link handling */ 9 vSemaphoreCreateBinary( ETH_link_xSemaphore ); 10 } 11 12 /* create the task that handles the ETH_link */ 13 xTaskCreate(Eth_Link_IT_task, (signed char*) "E_link", ETH_LINK_TASK_STACK_SIZE, (void *)DP83848_PHY_ADDRESS, 14 ETH_LINK_TASK_PRIORITY,NULL); 15 }
在Eth_Link_IT_task任务中,会读取以太网寄存器,进一步判断链路状态变化的类型,是通还是断,网线插上了还是拔下了,
然后,将网络接口的链路状态设置为up或down。此处,在eth_bsp中引用xnetif有点别扭。。。由于需要读取PHY寄存器,所以,放在这儿了,是不是可以封装一下,由上面调用。。。
1 void Eth_Link_IT_task( void * pvParameters ) 2 { 3 uint32_t pcPHYAddress; 4 5 pcPHYAddress = ( uint32_t ) pvParameters; 6 7 for(;;) 8 { 9 if (xSemaphoreTake( ETH_link_xSemaphore, emacBLOCK_TIME_WAITING_ETH_LINK_IT)==pdTRUE) 10 { 11 /* Check whether the link interrupt has occurred or not */ 12 if(((ETH_ReadPHYRegister((uint16_t) pcPHYAddress, PHY_MISR)) & PHY_LINK_STATUS) != 0) 13 { 14 if((ETH_ReadPHYRegister((uint16_t) pcPHYAddress, PHY_SR) & 1)) 15 { 16 netif_set_link_up(&xnetif); 17 } 18 else 19 { 20 netif_set_link_down(&xnetif); 21 } 22 } 23 } 24 } 25 }
之后,netif_set_link_up里会调用用户挂接的link up down回调函数,该函数也在eth_bsp中,是ETH_link_callback,挂接是在netconf中创建xnetif的时候。
在ETH_link_callback中,
如果是up,会启动MAC(不知道启动的什么?),设置netif up(是接口up,不是link up);
如果是down,会停止MAC,设置netif down。
1 void ETH_link_callback(struct netif *netif) 2 { 6 if(netif_is_link_up(netif)) 7 { 8 /* Restart MAC interface */ 9 ETH_Start(); 10 11 /* When the netif is fully configured this function must be called.*/ 12 netif_set_up(&xnetif); 15 } 16 else 17 { 18 ETH_Stop(); 19 20 /* When the netif link is down this function must be called.*/ 21 netif_set_down(&xnetif);24 } 25 }
上面的注释提到,link up down之后,netif up down必须调用,
因为,有些协议,比如arp和nd6,都是在netif down之后,清理arp缓存,nd的前缀、邻居信息的。