Advertisement
Guest User

ethernetif.c

a guest
Apr 8th, 2015
678
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 21.19 KB | None | 0 0
  1. /**
  2.   ******************************************************************************
  3.   * @file    LwIP/LwIP_HTTP_Server_Socket_RTOS/Src/ethernetif.c
  4.   * @author  MCD Application Team
  5.   * @version V1.2.1
  6.   * @date    13-March-2015
  7.   * @brief   This file implements Ethernet network interface drivers for lwIP
  8.   ******************************************************************************
  9.   * @attention
  10.   *
  11.   * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
  12.   *
  13.   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  14.   * You may not use this file except in compliance with the License.
  15.   * You may obtain a copy of the License at:
  16.   *
  17.   *        http://www.st.com/software_license_agreement_liberty_v2
  18.   *
  19.   * Unless required by applicable law or agreed to in writing, software
  20.   * distributed under the License is distributed on an "AS IS" BASIS,
  21.   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22.   * See the License for the specific language governing permissions and
  23.   * limitations under the License.
  24.   *
  25.   ******************************************************************************
  26.   */
  27.  
  28. /* Includes ------------------------------------------------------------------*/
  29. #include "stm32f4xx_hal.h"
  30. #include "lwip/opt.h"
  31. #include "lwip/lwip_timers.h"
  32. #include "netif/etharp.h"
  33. #include "ethernetif.h"
  34. #include <string.h>
  35.  
  36. /* Private typedef -----------------------------------------------------------*/
  37. /* Private define ------------------------------------------------------------*/
  38. /* The time to block waiting for input. */
  39. #define TIME_WAITING_FOR_INPUT                 ( 100 )
  40. /* Stack size of the interface thread */
  41. #define INTERFACE_THREAD_STACK_SIZE            ( 350 )
  42.  
  43. /* Define those to better describe your network interface. */
  44. #define IFNAME0 's'
  45. #define IFNAME1 't'
  46.  
  47. /* Private macro -------------------------------------------------------------*/
  48. /* Private variables ---------------------------------------------------------*/
  49. #if defined ( __ICCARM__ ) /*!< IAR Compiler */
  50.   #pragma data_alignment=4  
  51. #endif
  52. __ALIGN_BEGIN ETH_DMADescTypeDef  DMARxDscrTab[ETH_RXBUFNB] __ALIGN_END;/* Ethernet Rx MA Descriptor */
  53.  
  54. #if defined ( __ICCARM__ ) /*!< IAR Compiler */
  55.   #pragma data_alignment=4  
  56. #endif
  57. __ALIGN_BEGIN ETH_DMADescTypeDef  DMATxDscrTab[ETH_TXBUFNB] __ALIGN_END;/* Ethernet Tx DMA Descriptor */
  58.  
  59. #if defined ( __ICCARM__ ) /*!< IAR Compiler */
  60.   #pragma data_alignment=4  
  61. #endif
  62. __ALIGN_BEGIN uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __ALIGN_END; /* Ethernet Receive Buffer */
  63.  
  64. #if defined ( __ICCARM__ ) /*!< IAR Compiler */
  65.   #pragma data_alignment=4  
  66. #endif
  67. __ALIGN_BEGIN uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __ALIGN_END; /* Ethernet Transmit Buffer */
  68.  
  69. /* Semaphore to signal incoming packets */
  70. osSemaphoreId s_xSemaphore = NULL;
  71.  
  72. /* Global Ethernet handle*/
  73. ETH_HandleTypeDef EthHandle;
  74.  
  75. /* Private function prototypes -----------------------------------------------*/
  76. static void ethernetif_input( void const * argument );
  77.  
  78. /* Private functions ---------------------------------------------------------*/
  79. /*******************************************************************************
  80.                        Ethernet MSP Routines
  81. *******************************************************************************/
  82. /**
  83.   * @brief  Initializes the ETH MSP.
  84.   * @param  heth: ETH handle
  85.   * @retval None
  86.   */
  87. void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
  88. {
  89.   GPIO_InitTypeDef GPIO_InitStructure;
  90.  
  91.     __HAL_RCC_ETHMAC_CLK_ENABLE();
  92.   __HAL_RCC_ETHMACTX_CLK_ENABLE();
  93.   __HAL_RCC_ETHMACRX_CLK_ENABLE();
  94.    
  95.   /* Enable GPIOs clocks */
  96.   __HAL_RCC_GPIOA_CLK_ENABLE();
  97.   __HAL_RCC_GPIOB_CLK_ENABLE();
  98.   __HAL_RCC_GPIOC_CLK_ENABLE();
  99.   __HAL_RCC_GPIOF_CLK_ENABLE();
  100.   __HAL_RCC_GPIOG_CLK_ENABLE();
  101.   __HAL_RCC_GPIOH_CLK_ENABLE();
  102.   __HAL_RCC_GPIOI_CLK_ENABLE();
  103.    
  104.     /* Ethernet pins configuration ************************************************/
  105.    /*
  106.  
  107.         RMII
  108.             ETH_MDIO --------------> PA2
  109.             ETH_MDC ---------------> PC1
  110.             ETH_RMII_REF_CLK-------> PA1
  111.             ETH_RMII_CRS_DV -------> PA7
  112.             ETH_RMII_RXD0   -------> PC4
  113.       ETH_RMII_RXD1   -------> PC5
  114.       ETH_RMII_TX_EN  -------> PB11
  115.       ETH_RMII_TXD0   -------> PB12
  116.       ETH_RMII_TXD1   -------> PB13
  117.       ETH_RST_PIN     -------> PE2
  118.            
  119.                                                  */
  120.  
  121.   /* Configure PA1, PA2 and PA7 */
  122.   GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
  123.   GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
  124.   GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
  125.   GPIO_InitStructure.Pull = GPIO_NOPULL;
  126.   GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
  127.   HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
  128.  
  129.   /* Configure PB11, PB12 and PB13 */
  130.   GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
  131.   HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
  132.  
  133.   /* Configure PC1, PC4 and PC5 */
  134.   GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
  135.   HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
  136.    
  137.     /* Configure PE2 */
  138.   GPIO_InitStructure.Pin = GPIO_PIN_2;
  139.     GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
  140.   GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
  141.     GPIO_InitStructure.Pull = GPIO_PULLUP;
  142.   HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
  143.  
  144.     HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_RESET);
  145.     osDelay(50);
  146.     HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_SET);
  147.     osDelay(50);
  148.  
  149.   /* Enable the Ethernet global Interrupt */
  150.   HAL_NVIC_SetPriority(ETH_IRQn, 12, 0);
  151.     HAL_NVIC_EnableIRQ(ETH_IRQn);
  152.  
  153.   /* Enable ETHERNET clock  */
  154.   __HAL_RCC_ETH_CLK_ENABLE();
  155.  
  156. }
  157.  
  158. /**
  159.   * @brief  Ethernet Rx Transfer completed callback
  160.   * @param  heth: ETH handle
  161.   * @retval None
  162.   */
  163. void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
  164. {
  165.   osSemaphoreRelease(s_xSemaphore);
  166. }
  167.  
  168. /**
  169.   * @brief  Ethernet IRQ Handler
  170.   * @param  None
  171.   * @retval None
  172.   */
  173. void ETHERNET_IRQHandler(void)
  174. {
  175.   HAL_ETH_IRQHandler(&EthHandle);
  176. }
  177.  
  178. /*******************************************************************************
  179.                        LL Driver Interface ( LwIP stack --> ETH)
  180. *******************************************************************************/
  181. /**
  182.   * @brief In this function, the hardware should be initialized.
  183.   * Called from ethernetif_init().
  184.   *
  185.   * @param netif the already initialized lwip network interface structure
  186.   *        for this ethernetif
  187.   */
  188. static void low_level_init(struct netif *netif)
  189. {
  190.   uint32_t regvalue = 0;
  191.   uint8_t macaddress[6]= { MAC_ADDR0, MAC_ADDR1, MAC_ADDR2, MAC_ADDR3, MAC_ADDR4, MAC_ADDR5 };
  192.  
  193.   EthHandle.Instance = ETH;  
  194.   EthHandle.Init.MACAddr = macaddress;
  195.   EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
  196.   EthHandle.Init.Speed = ETH_SPEED_100M;
  197.   EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
  198.   EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
  199.   EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE;
  200.   EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
  201.   EthHandle.Init.PhyAddress = LAN8720_PHY_ADDRESS;
  202.  
  203.   /* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
  204.   if (HAL_ETH_Init(&EthHandle) == HAL_OK)
  205.   {
  206.     /* Set netif link flag */
  207.     netif->flags |= NETIF_FLAG_LINK_UP;    
  208.   }
  209.  
  210.   /* Initialize Tx Descriptors list: Chain Mode */
  211.   HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
  212.      
  213.   /* Initialize Rx Descriptors list: Chain Mode  */
  214.   HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
  215.  
  216.   /* set netif MAC hardware address length */
  217.   netif->hwaddr_len = ETHARP_HWADDR_LEN;
  218.  
  219.   /* set netif MAC hardware address */
  220.   netif->hwaddr[0] =  MAC_ADDR0;
  221.   netif->hwaddr[1] =  MAC_ADDR1;
  222.   netif->hwaddr[2] =  MAC_ADDR2;
  223.   netif->hwaddr[3] =  MAC_ADDR3;
  224.   netif->hwaddr[4] =  MAC_ADDR4;
  225.   netif->hwaddr[5] =  MAC_ADDR5;
  226.  
  227.   /* set netif maximum transfer unit */
  228.   netif->mtu = 1500;
  229.  
  230.   /* Accept broadcast address and ARP traffic */
  231.   netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
  232.  
  233.   /* create a binary semaphore used for informing ethernetif of frame reception */
  234.   osSemaphoreDef(SEM);
  235.   s_xSemaphore = osSemaphoreCreate(osSemaphore(SEM) , 1 );
  236.  
  237.   /* create the task that handles the ETH_MAC */
  238.   osThreadDef(Eth_if, ethernetif_input, osPriorityRealtime, 0, INTERFACE_THREAD_STACK_SIZE);
  239.   osThreadCreate (osThread(Eth_if), netif);
  240.  
  241.   /* Enable MAC and DMA transmission and reception */
  242.   HAL_ETH_Start(&EthHandle);
  243.  
  244.   /**** Configure PHY to generate an interrupt when Eth Link state changes ****/
  245.   /* Read Register Configuration */
  246.   HAL_ETH_ReadPHYRegister(&EthHandle, PHY_MICR, &regvalue);
  247.  
  248.   regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE);
  249.  
  250.   /* Enable Interrupts */
  251.   HAL_ETH_WritePHYRegister(&EthHandle, PHY_MICR, regvalue );
  252.  
  253.   /* Read Register Configuration */
  254.   HAL_ETH_ReadPHYRegister(&EthHandle, PHY_MISR, &regvalue);
  255.  
  256.   regvalue |= PHY_MISR_LINK_INT_EN;
  257.    
  258.   /* Enable Interrupt on change of link status */
  259.   HAL_ETH_WritePHYRegister(&EthHandle, PHY_MISR, regvalue);  
  260. }
  261.  
  262. /**
  263.   * @brief This function should do the actual transmission of the packet. The packet is
  264.   * contained in the pbuf that is passed to the function. This pbuf
  265.   * might be chained.
  266.   *
  267.   * @param netif the lwip network interface structure for this ethernetif
  268.   * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
  269.   * @return ERR_OK if the packet could be sent
  270.   *         an err_t value if the packet couldn't be sent
  271.   *
  272.   * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
  273.   *       strange results. You might consider waiting for space in the DMA queue
  274.   *       to become available since the stack doesn't retry to send a packet
  275.   *       dropped because of memory failure (except for the TCP timers).
  276.   */
  277. static err_t low_level_output(struct netif *netif, struct pbuf *p)
  278. {
  279.   err_t errval;
  280.   struct pbuf *q;
  281.   uint8_t *buffer = (uint8_t *)(EthHandle.TxDesc->Buffer1Addr);
  282.   __IO ETH_DMADescTypeDef *DmaTxDesc;
  283.   uint32_t framelength = 0;
  284.   uint32_t bufferoffset = 0;
  285.   uint32_t byteslefttocopy = 0;
  286.   uint32_t payloadoffset = 0;
  287.  
  288.   DmaTxDesc = EthHandle.TxDesc;
  289.   bufferoffset = 0;
  290.  
  291.   /* copy frame from pbufs to driver buffers */
  292.   for(q = p; q != NULL; q = q->next)
  293.   {
  294.     /* Is this buffer available? If not, goto error */
  295.     if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
  296.     {
  297.       errval = ERR_USE;
  298.       goto error;
  299.     }
  300.    
  301.     /* Get bytes in current lwIP buffer */
  302.     byteslefttocopy = q->len;
  303.     payloadoffset = 0;
  304.    
  305.     /* Check if the length of data to copy is bigger than Tx buffer size*/
  306.     while( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE )
  307.     {
  308.       /* Copy data to Tx buffer*/
  309.       memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset) );
  310.      
  311.       /* Point to next descriptor */
  312.       DmaTxDesc = (ETH_DMADescTypeDef *)(DmaTxDesc->Buffer2NextDescAddr);
  313.      
  314.       /* Check if the buffer is available */
  315.       if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
  316.       {
  317.         errval = ERR_USE;
  318.         goto error;
  319.       }
  320.      
  321.       buffer = (uint8_t *)(DmaTxDesc->Buffer1Addr);
  322.      
  323.       byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset);
  324.       payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset);
  325.       framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset);
  326.       bufferoffset = 0;
  327.     }
  328.    
  329.     /* Copy the remaining bytes */
  330.     memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), byteslefttocopy );
  331.     bufferoffset = bufferoffset + byteslefttocopy;
  332.     framelength = framelength + byteslefttocopy;
  333.   }
  334.  
  335.   /* Prepare transmit descriptors to give to DMA */
  336.   HAL_ETH_TransmitFrame(&EthHandle, framelength);
  337.  
  338.   errval = ERR_OK;
  339.  
  340. error:
  341.  
  342.   /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
  343.   if ((EthHandle.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET)
  344.   {
  345.     /* Clear TUS ETHERNET DMA flag */
  346.     EthHandle.Instance->DMASR = ETH_DMASR_TUS;
  347.    
  348.     /* Resume DMA transmission*/
  349.     EthHandle.Instance->DMATPDR = 0;
  350.   }
  351.   return errval;
  352. }
  353.  
  354. /**
  355.   * @brief Should allocate a pbuf and transfer the bytes of the incoming
  356.   * packet from the interface into the pbuf.
  357.   *
  358.   * @param netif the lwip network interface structure for this ethernetif
  359.   * @return a pbuf filled with the received packet (including MAC header)
  360.   *         NULL on memory error
  361.   */
  362. static struct pbuf * low_level_input(struct netif *netif)
  363. {
  364.   struct pbuf *p = NULL, *q = NULL;
  365.   u16_t len = 0;
  366.   uint8_t *buffer;
  367.   __IO ETH_DMADescTypeDef *dmarxdesc;
  368.   uint32_t bufferoffset = 0;
  369.   uint32_t payloadoffset = 0;
  370.   uint32_t byteslefttocopy = 0;
  371.   uint32_t i=0;
  372.  
  373.   /* get received frame */
  374.   if(HAL_ETH_GetReceivedFrame_IT(&EthHandle) != HAL_OK)
  375.     return NULL;
  376.  
  377.   /* Obtain the size of the packet and put it into the "len" variable. */
  378.   len = EthHandle.RxFrameInfos.length;
  379.   buffer = (uint8_t *)EthHandle.RxFrameInfos.buffer;
  380.  
  381.   if (len > 0)
  382.   {
  383.     /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
  384.     p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
  385.   }
  386.  
  387.   if (p != NULL)
  388.   {
  389.     dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc;
  390.     bufferoffset = 0;
  391.    
  392.     for(q = p; q != NULL; q = q->next)
  393.     {
  394.       byteslefttocopy = q->len;
  395.       payloadoffset = 0;
  396.  
  397.       /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
  398.       while( (byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE )
  399.       {
  400.         /* Copy data to pbuf*/
  401.         memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset));
  402.  
  403.         /* Point to next descriptor */
  404.         dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
  405.         buffer = (unsigned char *)(dmarxdesc->Buffer1Addr);
  406.  
  407.         byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset);
  408.         payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset);
  409.         bufferoffset = 0;
  410.       }
  411.  
  412.       /* Copy remaining data in pbuf */
  413.       memcpy( (u8_t*)((u8_t*)q->payload + payloadoffset), (u8_t*)((u8_t*)buffer + bufferoffset), byteslefttocopy);
  414.       bufferoffset = bufferoffset + byteslefttocopy;
  415.   }
  416.  
  417.    /* Release descriptors to DMA */
  418.    dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc;
  419.  
  420.     /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
  421.     for (i=0; i< EthHandle.RxFrameInfos.SegCount; i++)
  422.     {  
  423.       dmarxdesc->Status |= ETH_DMARXDESC_OWN;
  424.       dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
  425.     }
  426.  
  427.     /* Clear Segment_Count */
  428.     EthHandle.RxFrameInfos.SegCount =0;
  429.   }
  430.  
  431.   /* When Rx Buffer unavailable flag is set: clear it and resume reception */
  432.   if ((EthHandle.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET)  
  433.   {
  434.     /* Clear RBUS ETHERNET DMA flag */
  435.     EthHandle.Instance->DMASR = ETH_DMASR_RBUS;
  436.     /* Resume DMA reception */
  437.     EthHandle.Instance->DMARPDR = 0;
  438.   }
  439.   return p;
  440. }
  441.  
  442.  
  443. /**
  444.   * @brief This function is the ethernetif_input task, it is processed when a packet
  445.   * is ready to be read from the interface. It uses the function low_level_input()
  446.   * that should handle the actual reception of bytes from the network
  447.   * interface. Then the type of the received packet is determined and
  448.   * the appropriate input function is called.
  449.   *
  450.   * @param netif the lwip network interface structure for this ethernetif
  451.   */
  452. void ethernetif_input( void const * argument )
  453. {
  454.   struct pbuf *p;
  455.   struct netif *netif = (struct netif *) argument;
  456.  
  457.   for( ;; )
  458.   {
  459.     if (osSemaphoreWait( s_xSemaphore, TIME_WAITING_FOR_INPUT)==osOK)
  460.     {
  461.       do
  462.       {
  463.         p = low_level_input( netif );
  464.         if (p != NULL)
  465.         {
  466.           if (netif->input( p, netif) != ERR_OK )
  467.           {
  468.             pbuf_free(p);
  469.           }
  470.         }
  471.       }while(p!=NULL);
  472.     }
  473.   }
  474. }
  475.  
  476. /**
  477.   * @brief Should be called at the beginning of the program to set up the
  478.   * network interface. It calls the function low_level_init() to do the
  479.   * actual setup of the hardware.
  480.   *
  481.   * This function should be passed as a parameter to netif_add().
  482.   *
  483.   * @param netif the lwip network interface structure for this ethernetif
  484.   * @return ERR_OK if the loopif is initialized
  485.   *         ERR_MEM if private data couldn't be allocated
  486.   *         any other err_t on error
  487.   */
  488. err_t ethernetif_init(struct netif *netif)
  489. {
  490.   LWIP_ASSERT("netif != NULL", (netif != NULL));
  491.  
  492. #if LWIP_NETIF_HOSTNAME
  493.   /* Initialize interface hostname */
  494.   netif->hostname = "lwip";
  495. #endif /* LWIP_NETIF_HOSTNAME */
  496.  
  497.   netif->name[0] = IFNAME0;
  498.   netif->name[1] = IFNAME1;
  499.  
  500.   netif->output = etharp_output;
  501.   netif->linkoutput = low_level_output;
  502.  
  503.   /* initialize the hardware */
  504.   low_level_init(netif);
  505.  
  506.   return ERR_OK;
  507. }
  508.  
  509. /**
  510.   * @brief  This function sets the netif link status.
  511.   * @param  netif: the network interface
  512.   * @retval None
  513.   */
  514. void ethernetif_set_link(void const *argument)
  515. {
  516.   uint32_t regvalue = 0;
  517.   struct link_str *link_arg = (struct link_str *)argument;
  518.  
  519.   for(;;)
  520.   {
  521.     if (osSemaphoreWait( link_arg->semaphore, 100)== osOK)
  522.     {
  523.       /* Read PHY_MISR*/
  524.       HAL_ETH_ReadPHYRegister(&EthHandle, PHY_MISR, &regvalue);
  525.      
  526.       /* Check whether the link interrupt has occurred or not */
  527.       if((regvalue & PHY_LINK_INTERRUPT) != (uint16_t)RESET)
  528.       {
  529.         /* Read PHY_SR*/
  530.         HAL_ETH_ReadPHYRegister(&EthHandle, PHY_SR, &regvalue);
  531.        
  532.         /* Check whether the link is up or down*/
  533.         if((regvalue & PHY_LINK_STATUS)!= (uint16_t)RESET)
  534.         {
  535.           netif_set_link_up(link_arg->netif);
  536.         }
  537.         else
  538.         {
  539.           netif_set_link_down(link_arg->netif);
  540.         }
  541.       }
  542.     }
  543.   }
  544. }
  545.  
  546. /**
  547.   * @brief  Link callback function, this function is called on change of link status
  548.   *         to update low level driver configuration.
  549.   * @param  netif: The network interface
  550.   * @retval None
  551.   */
  552. void ethernetif_update_config(struct netif *netif)
  553. {
  554.   __IO uint32_t tickstart = 0;
  555.   uint32_t regvalue = 0;
  556.  
  557.   if(netif_is_link_up(netif))
  558.   {
  559.     /* Restart the auto-negotiation */
  560.     if(EthHandle.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE)
  561.     {
  562.       /* Enable Auto-Negotiation */
  563.       HAL_ETH_WritePHYRegister(&EthHandle, PHY_BCR, PHY_AUTONEGOTIATION);
  564.      
  565.       /* Get tick */
  566.       tickstart = HAL_GetTick();
  567.      
  568.       /* Wait until the auto-negotiation will be completed */
  569.       do
  570.       {
  571.         HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, &regvalue);
  572.        
  573.         /* Check for the Timeout ( 1s ) */
  574.         if((HAL_GetTick() - tickstart ) > 1000)
  575.         {
  576.           /* In case of timeout */
  577.           goto error;
  578.         }
  579.        
  580.       } while (((regvalue & PHY_AUTONEGO_COMPLETE) != PHY_AUTONEGO_COMPLETE));
  581.      
  582.       /* Read the result of the auto-negotiation */
  583.       HAL_ETH_ReadPHYRegister(&EthHandle, PHY_SR, &regvalue);
  584.      
  585.       /* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */
  586.       if((regvalue & PHY_DUPLEX_STATUS) != (uint32_t)RESET)
  587.       {
  588.         /* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
  589.         EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;  
  590.       }
  591.       else
  592.       {
  593.         /* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */
  594.         EthHandle.Init.DuplexMode = ETH_MODE_HALFDUPLEX;          
  595.       }
  596.       /* Configure the MAC with the speed fixed by the auto-negotiation process */
  597.       if(regvalue & PHY_SPEED_STATUS)
  598.       {  
  599.         /* Set Ethernet speed to 10M following the auto-negotiation */
  600.         EthHandle.Init.Speed = ETH_SPEED_10M;
  601.       }
  602.       else
  603.       {  
  604.         /* Set Ethernet speed to 100M following the auto-negotiation */
  605.         EthHandle.Init.Speed = ETH_SPEED_100M;
  606.       }
  607.     }
  608.     else /* AutoNegotiation Disable */
  609.     {
  610.     error :
  611.       /* Check parameters */
  612.       assert_param(IS_ETH_SPEED(EthHandle.Init.Speed));
  613.       assert_param(IS_ETH_DUPLEX_MODE(EthHandle.Init.DuplexMode));
  614.      
  615.       /* Set MAC Speed and Duplex Mode to PHY */
  616.       HAL_ETH_WritePHYRegister(&EthHandle, PHY_BCR, ((uint16_t)(EthHandle.Init.DuplexMode >> 3) |
  617.                                                      (uint16_t)(EthHandle.Init.Speed >> 1)));
  618.     }
  619.  
  620.     /* ETHERNET MAC Re-Configuration */
  621.     HAL_ETH_ConfigMAC(&EthHandle, (ETH_MACInitTypeDef *) NULL);
  622.  
  623.     /* Restart MAC interface */
  624.     HAL_ETH_Start(&EthHandle);  
  625.   }
  626.   else
  627.   {
  628.     /* Stop MAC interface */
  629.     HAL_ETH_Stop(&EthHandle);
  630.   }
  631.  
  632.   ethernetif_notify_conn_changed(netif);
  633. }
  634.  
  635. /**
  636.   * @brief  This function notify user about link status changement.
  637.   * @param  netif: the network interface
  638.   * @retval None
  639.   */
  640. __weak void ethernetif_notify_conn_changed(struct netif *netif)
  641. {
  642.   /* NOTE : This is function could be implemented in user file
  643.             when the callback is needed,
  644.   */  
  645. }
  646. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement