Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stm32f4xx_hal.h>
- #include <string.h>
- #include "ethernetif.h"
- #include "NetworkDefaults.h"
- #include "lwip/init.h"
- #include "lwip/netif.h"
- #include "lwip/tcpip.h"
- #include "lwip/dhcp.h"
- #include "lwip/api.h"
- #include "lwip/opt.h"
- #include "lwip/timeouts.h"
- #include "netif/etharp.h"
- // TLK110 datasheet, page 5
- #define PHY_ADDR 0x01
- // TLK110 Registers
- #define PHY_MISR1 0x0012
- #define PHY_BMSR 0x0001
- // TLK110 bits
- #define PHY_LINK_STATUS (uint16_t)(1 << 2)
- static ETH_HandleTypeDef EthHandle;
- __ALIGN_BEGIN ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] __ALIGN_END; // Ethernet Rx MA Descriptor
- __ALIGN_BEGIN ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB] __ALIGN_END; // Ethernet Tx DMA Descriptor
- __ALIGN_BEGIN uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __ALIGN_END; // Ethernet RX buffer
- __ALIGN_BEGIN uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __ALIGN_END; // Ethernet TX buffer
- static err_t low_level_output(struct netif *netif, struct pbuf *p);
- static struct pbuf * low_level_input(struct netif *netif);
- static void InitPhyInterrupt(void);
- static uint8_t Tlk110EnableInterrupts(void);
- static void Tlk110TestRead(void);
- void low_level_init(struct netif *netif)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- uint8_t macaddress[6] = {MAC_ADDR0, MAC_ADDR1, MAC_ADDR2, MAC_ADDR3, MAC_ADDR4, MAC_ADDR5};
- // Enable clocks
- __HAL_RCC_ETH_CLK_ENABLE();
- __HAL_RCC_GPIOA_CLK_ENABLE();
- __HAL_RCC_GPIOB_CLK_ENABLE();
- __HAL_RCC_GPIOC_CLK_ENABLE();
- /*
- * TapBot ETH pins
- *
- RMII_REF_CLK ----------------------> PA1
- RMII_MDIO -------------------------> PA2
- RMII_MDC --------------------------> PC1
- RMII_MII_CRS_DV -------------------> PA7
- RMII_MII_RXD0 ---------------------> PC4
- RMII_MII_RXD1 ---------------------> PC5
- RMII_MII_TX_EN --------------------> PB11
- RMII_MII_TXD0 ---------------------> PB12
- RMII_MII_TXD1 ---------------------> PB13
- */
- // Common settings for RMII/MDC lines
- GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
- GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStructure.Pull = GPIO_NOPULL;
- GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
- // RMII_REF_CLK, RMII_MDIO, RMII_MII_CRS_DV
- GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
- // RMII_MII_TX_EN, RMII_MII_TXD0, RMII_MII_TXD1
- GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
- HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
- // RMII_MDC, RMII_MII_RXD0, RMII_MII_RXD1
- GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
- HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
- // Enable ethernet interrupts
- HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0);
- HAL_NVIC_EnableIRQ(ETH_IRQn);
- // Configure the Eth MAC hardware
- EthHandle.Instance = ETH;
- EthHandle.Init.MACAddr = macaddress;
- EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
- EthHandle.Init.Speed = ETH_SPEED_100M;
- EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
- EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
- EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE;
- EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
- EthHandle.Init.PhyAddress = PHY_ADDR;
- // Commit eth config
- if(HAL_ETH_Init(&EthHandle) == HAL_OK)
- {
- printf("Init OK!\r\n");
- }
- // Initialize Tx Descriptors list: Chain Mode
- HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
- // Initialize Rx Descriptors list: Chain Mode
- HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
- // Enable Eth MAC/DMA
- if(HAL_ETH_Start(&EthHandle) == HAL_OK)
- {
- printf("Link up!\r\n");
- netif_set_link_up(netif);
- }
- }
- void ethernetif_check_link_state(struct netif *netif)
- {
- uint32_t tmp;
- // Read back for verification
- if(HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BMSR, &tmp) != HAL_OK)
- {
- printf("Read fail!\r\n");
- return;
- }
- if (tmp & (1 << 2))
- {
- printf("Link up!!!!\r\n");
- netif_set_link_up(netif);
- }
- else
- {
- printf("Link down...\r\n");
- netif_set_link_down(netif);
- }
- }
- err_t ethernetif_init(struct netif *netif)
- {
- // MAC address length
- netif->hwaddr_len = ETHARP_HWADDR_LEN;
- // Copy MAC address
- netif->hwaddr[0] = MAC_ADDR0;
- netif->hwaddr[1] = MAC_ADDR1;
- netif->hwaddr[2] = MAC_ADDR2;
- netif->hwaddr[3] = MAC_ADDR3;
- netif->hwaddr[4] = MAC_ADDR4;
- netif->hwaddr[5] = MAC_ADDR5;
- // Interface name
- netif->name[0] = 's';
- netif->name[1] = 't';
- // Max transfer unit
- netif->mtu = 1500;
- // Accept broadcast address and ARP traffic
- netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
- // Link IO callbacks
- netif->output = etharp_output;
- netif->linkoutput = low_level_output;
- // Init hardware
- low_level_init(netif);
- printf("Low level init done!\r\n");
- return ERR_OK;
- }
- err_t ethernetif_input(struct netif *netif)
- {
- err_t err;
- struct pbuf *p;
- // Move received packet into a new pbuf
- p = low_level_input(netif);
- // No packet could be read, silently ignore this
- if (p == NULL)
- {
- return ERR_MEM;
- }
- // We do have a packet, give it to LwIP
- err = netif->input(p, netif);
- // If LwIP was able to process the packet, free the pbuf
- if (err != ERR_OK)
- {
- pbuf_free(p);
- p = NULL;
- }
- return err;
- }
- uint32_t sys_now(void)
- {
- return HAL_GetTick();
- }
- // Handle packet TX
- static err_t low_level_output(struct netif *netif, struct pbuf *p)
- {
- err_t errval;
- struct pbuf *q;
- uint8_t *buffer = (uint8_t *)(EthHandle.TxDesc->Buffer1Addr);
- __IO ETH_DMADescTypeDef *DmaTxDesc;
- uint32_t framelength = 0;
- uint32_t bufferoffset = 0;
- uint32_t byteslefttocopy = 0;
- uint32_t payloadoffset = 0;
- DmaTxDesc = EthHandle.TxDesc;
- bufferoffset = 0;
- printf("TX\r\n");
- /* copy frame from pbufs to driver buffers */
- for (q = p; q != NULL; q = q->next)
- {
- /* Is this buffer available? If not, goto error */
- if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
- {
- errval = ERR_USE;
- goto error;
- }
- /* Get bytes in current lwIP buffer */
- byteslefttocopy = q->len;
- payloadoffset = 0;
- /* Check if the length of data to copy is bigger than Tx buffer size*/
- while ((byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE)
- {
- /* Copy data to Tx buffer*/
- memcpy((uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset));
- /* Point to next descriptor */
- DmaTxDesc = (ETH_DMADescTypeDef *)(DmaTxDesc->Buffer2NextDescAddr);
- /* Check if the buffer is available */
- 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;
- }
- /* Copy the remaining bytes */
- memcpy((uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), byteslefttocopy);
- bufferoffset = bufferoffset + byteslefttocopy;
- framelength = framelength + byteslefttocopy;
- }
- /* Prepare transmit descriptors to give to DMA */
- HAL_ETH_TransmitFrame(&EthHandle, framelength);
- errval = ERR_OK;
- error:
- /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
- if ((EthHandle.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET)
- {
- /* Clear TUS ETHERNET DMA flag */
- EthHandle.Instance->DMASR = ETH_DMASR_TUS;
- /* Resume DMA transmission*/
- EthHandle.Instance->DMATPDR = 0;
- }
- return errval;
- }
- // Handle packet RX
- static struct pbuf* low_level_input(struct netif *netif)
- {
- struct pbuf *p = NULL, *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;
- /* get received frame */
- if (HAL_ETH_GetReceivedFrame(&EthHandle) != HAL_OK)
- {
- return NULL;
- }
- printf("RX\r\n");
- /* Obtain the size of the packet and put it into the "len" variable. */
- len = EthHandle.RxFrameInfos.length;
- buffer = (uint8_t *)EthHandle.RxFrameInfos.buffer;
- if (len > 0)
- {
- /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
- p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
- }
- if (p != NULL)
- {
- dmarxdesc = EthHandle.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 = EthHandle.RxFrameInfos.FSRxDesc;
- /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
- for (i = 0; i < EthHandle.RxFrameInfos.SegCount; i++)
- {
- dmarxdesc->Status |= ETH_DMARXDESC_OWN;
- dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
- }
- /* Clear Segment_Count */
- EthHandle.RxFrameInfos.SegCount = 0;
- /* When Rx Buffer unavailable flag is set: clear it and resume reception */
- if ((EthHandle.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET)
- {
- /* Clear RBUS ETHERNET DMA flag */
- EthHandle.Instance->DMASR = ETH_DMASR_RBUS;
- /* Resume DMA reception */
- EthHandle.Instance->DMARPDR = 0;
- }
- return p;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement