主页 > 游戏开发  > 

STM32H743ZIT6FreeRTOSCMSIS_V2LwipDP83848/LAN8720最新HALV1.

STM32H743ZIT6FreeRTOSCMSIS_V2LwipDP83848/LAN8720最新HALV1.

HAL库版本:V1.12.1 最新版

这版CUBEmx生成的LAN8742 的驱动文件有问题,无法正常初始化,导致无法PING通。 lwip 内存池 不需要手动指定0x30040200区域,lwipopts.h已作配置

开启DCACH 和ICACH 和 D2域SRAM3 时钟 /** * @brief The application entry point. * @retval int */ int main(void) { /* Initialize debug print for JlinkView */ debug_print_init(); /* MPU Configuration--------------------------------------------------------*/ MPU_Config(); debug_print("-----------------------------\r\n"); debug_print("mpu config...\r\n"); /* Enable the CPU Cache */ /* Enable I-Cache---------------------------------------------------------*/ SCB_EnableICache(); /* Enable D-Cache---------------------------------------------------------*/ SCB_EnableDCache(); debug_print("cpu cache enable...\r\n"); /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); debug_print("clock config...\r\n"); /* Initialize all configured peripherals */ MX_GPIO_Init(); /* Read Board id */ uint8_t id = read_board_id(); debug_print("this board id:%d \r\n",id); /* LM75B init */ lm75b_hw_init(); /* W25Q128 init */ w25q128.init(); /* Init scheduler */ osKernelInitialize(); /* Call init function for freertos objects (in cmsis_os2.c) */ freertos_init(); /* Start scheduler */ osKernelStart(); /* We should never get here as control is now taken by the scheduler */ /* Infinite loop */ while (1) { } } MPU 配置 static void MPU_Config(void) { MPU_Region_InitTypeDef MPU_InitStruct; /* Disable the MPU */ HAL_MPU_Disable(); /* Configure the MPU attributes as Device not cacheable for ETH DMA descriptors */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x30040000; MPU_InitStruct.Size = MPU_REGION_SIZE_256B; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER0; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /* Configure the MPU attributes as Normal Non Cacheable for LwIP RAM heap which contains the Tx buffers */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x30044000; MPU_InitStruct.Size = MPU_REGION_SIZE_16KB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER1; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /* Enable the MPU */ HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); } SCT 链接文件 ; ************************************************************* ; *** Scatter-Loading Description File generated by uVision *** ; ************************************************************* LR_IROM1 0x08000000 0x00100000 { ; load region size_region ER_IROM1 0x08000000 0x00100000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) .ANY (+XO) } RW_IRAM2 0x24000000 0x00080000 { ; RW data .ANY (+RW +ZI) } RW_DMARxDscrTab 0x30040000 0x60 { *(.RxDecripSection) } RW_DMATxDscrTab 0x30040060 0x60 { *(.TxDecripSection) } } SCT文件的使用

1、 2 、

LAN8742/DP83848 Init函数 /** * @brief Initialize the lan8742 and configure the needed hardware resources * @param pObj: device object LAN8742_Object_t. * @retval LAN8742_STATUS_OK if OK * LAN8742_STATUS_ADDRESS_ERROR if cannot find device address * LAN8742_STATUS_READ_ERROR if cannot read register */ int32_t LAN8742_Init(lan8742_Object_t *pObj) { uint32_t tickstart = 0, regvalue = 0, addr = 0; int32_t status = LAN8742_STATUS_OK; if(pObj->Is_Initialized == 0) { if(pObj->IO.Init != 0) { /* GPIO and Clocks initialization */ pObj->IO.Init(); } /* for later check */ pObj->DevAddr = LAN8742_MAX_DEV_ADDR + 1; /* Get the device address from special mode register */ for(addr = 0; addr <= LAN8742_MAX_DEV_ADDR; addr ++) { if(pObj->IO.ReadReg(addr, LAN8742_SMR, &regvalue) < 0) { status = LAN8742_STATUS_READ_ERROR; /* Can't read from this device address continue with next address */ continue; } if((regvalue & LAN8742_SMR_PHY_ADDR) == addr) { pObj->DevAddr = addr; status = LAN8742_STATUS_OK; break; } } if(pObj->DevAddr > LAN8742_MAX_DEV_ADDR) { status = LAN8742_STATUS_ADDRESS_ERROR; } /* if device address is matched */ if(status == LAN8742_STATUS_OK) { /* set a software reset */ if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, LAN8742_BCR_SOFT_RESET) >= 0) { /* get software reset status */ if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &regvalue) >= 0) { tickstart = pObj->IO.GetTick(); /* wait until software reset is done or timeout occured */ while(regvalue & LAN8742_BCR_SOFT_RESET) { if((pObj->IO.GetTick() - tickstart) <= (uint32_t)500U) { if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &regvalue) < 0) { status = LAN8742_STATUS_READ_ERROR; break; } } else { status = LAN8742_STATUS_RESET_TIMEOUT; break; } } } else { status = LAN8742_STATUS_READ_ERROR; } } else { status = LAN8742_STATUS_WRITE_ERROR; } } } if(status == LAN8742_STATUS_OK) { tickstart = pObj->IO.GetTick(); /* Wait for 2s to perform initialization */ while((pObj->IO.GetTick() - tickstart) <= (uint32_t)2000U) { } pObj->Is_Initialized = 1; } return status; } LAN8742 / DP83848 寄存器 #define LAN8742_BCR ((uint16_t)0x0000U) #define LAN8742_BSR ((uint16_t)0x0001U) #define LAN8742_PHYI1R ((uint16_t)0x0002U) #define LAN8742_PHYI2R ((uint16_t)0x0003U) #define LAN8742_ANAR ((uint16_t)0x0004U) #define LAN8742_ANLPAR ((uint16_t)0x0005U) #define LAN8742_ANER ((uint16_t)0x0006U) #define LAN8742_ANNPTR ((uint16_t)0x0007U) #define LAN8742_ANNPRR ((uint16_t)0x0008U) #define LAN8742_MMDACR ((uint16_t)0x000DU) #define LAN8742_MMDAADR ((uint16_t)0x000EU) #define LAN8742_ENCTR ((uint16_t)0x0010U) #define LAN8742_MCSR ((uint16_t)0x0011U) #define LAN8742_SMR ((uint16_t)0x0019U) /* LAN8742 为 0x0012U,我用的83848*/ #define LAN8742_TPDCR ((uint16_t)0x0018U) #define LAN8742_TCSR ((uint16_t)0x0019U) #define LAN8742_SECR ((uint16_t)0x001AU) #define LAN8742_SCSIR ((uint16_t)0x001BU) #define LAN8742_CLR ((uint16_t)0x001CU) #define LAN8742_ISFR ((uint16_t)0x001DU) #define LAN8742_IMR ((uint16_t)0x001EU) #define LAN8742_PHYSCSR ((uint16_t)0x001FU) ethernetif.c文件 /* USER CODE BEGIN Header */ /** ****************************************************************************** * File Name : ethernetif.c * Description : This file provides code for the configuration * of the ethernetif.c MiddleWare. ****************************************************************************** * @attention * * Copyright (c) 2024 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "lwip/opt.h" #include "lwip/timeouts.h" #include "netif/ethernet.h" #include "netif/etharp.h" #include "lwip/ethip6.h" #include "ethernetif.h" #include "lan8742.h" #include <string.h> #include "cmsis_os.h" #include "lwip/tcpip.h" /* Within 'USER CODE' section, code will be kept by default at each generation */ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /* Private define ------------------------------------------------------------*/ /* The time to block waiting for input. */ #define TIME_WAITING_FOR_INPUT ( portMAX_DELAY ) /* USER CODE BEGIN OS_THREAD_STACK_SIZE_WITH_RTOS */ /* Stack size of the interface thread */ #define INTERFACE_THREAD_STACK_SIZE ( 350 ) /* USER CODE END OS_THREAD_STACK_SIZE_WITH_RTOS */ /* Network interface name */ #define IFNAME0 's' #define IFNAME1 't' /* ETH Setting */ #define ETH_DMA_TRANSMIT_TIMEOUT ( 20U ) #define ETH_TX_BUFFER_MAX ((ETH_TX_DESC_CNT) * 2U) /* ETH_RX_BUFFER_SIZE parameter is defined in lwipopts.h */ /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* Private variables ---------------------------------------------------------*/ /* @Note: This interface is implemented to operate in zero-copy mode only: - Rx buffers will be allocated from LwIP stack memory heap, then passed to ETH HAL driver. - Tx buffers will be allocated from LwIP stack memory heap, then passed to ETH HAL driver. @Notes: 1.a. ETH DMA Rx descriptors must be contiguous, the default count is 4, to customize it please redefine ETH_RX_DESC_CNT in ETH GUI (Rx Descriptor Length) so that updated value will be generated in stm32xxxx_hal_conf.h 1.b. ETH DMA Tx descriptors must be contiguous, the default count is 4, to customize it please redefine ETH_TX_DESC_CNT in ETH GUI (Tx Descriptor Length) so that updated value will be generated in stm32xxxx_hal_conf.h 2.a. Rx Buffers number must be between ETH_RX_DESC_CNT and 2*ETH_RX_DESC_CNT 2.b. Rx Buffers must have the same size: ETH_RX_BUFFER_SIZE, this value must passed to ETH DMA in the init field (heth.Init.RxBuffLen) 2.c The RX Ruffers addresses and sizes must be properly defined to be aligned to L1-CACHE line size (32 bytes). */ /* Data Type Definitions */ typedef enum { RX_ALLOC_OK = 0x00, RX_ALLOC_ERROR = 0x01 } RxAllocStatusTypeDef; typedef struct { struct pbuf_custom pbuf_custom; uint8_t buff[(ETH_RX_BUFFER_SIZE + 31) & ~31] __ALIGNED(32); } RxBuff_t; /* Memory Pool Declaration */ #define ETH_RX_BUFFER_CNT 12U LWIP_MEMPOOL_DECLARE(RX_POOL, ETH_RX_BUFFER_CNT, sizeof(RxBuff_t), "Zero-copy RX PBUF pool"); /* Variable Definitions */ static uint8_t RxAllocStatus; #if defined ( __ICCARM__ ) /*!< IAR Compiler */ #pragma location=0x30040000 ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */ #pragma location=0x30040060 ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */ #elif defined ( __CC_ARM ) /* MDK ARM Compiler */ __attribute__((at(0x30040000))) ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */ __attribute__((at(0x30040060))) ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */ #elif defined ( __GNUC__ ) /* GNU Compiler */ ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */ ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */ #endif /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ osSemaphoreId RxPktSemaphore = NULL; /* Semaphore to signal incoming packets */ osSemaphoreId TxPktSemaphore = NULL; /* Semaphore to signal transmit packet complete */ /* Global Ethernet handle */ ETH_HandleTypeDef heth; ETH_TxPacketConfig TxConfig; /* Private function prototypes -----------------------------------------------*/ int32_t ETH_PHY_IO_Init(void); int32_t ETH_PHY_IO_DeInit (void); int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal); int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal); int32_t ETH_PHY_IO_GetTick(void); lan8742_Object_t LAN8742; lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init, ETH_PHY_IO_DeInit, ETH_PHY_IO_WriteReg, ETH_PHY_IO_ReadReg, ETH_PHY_IO_GetTick}; /* USER CODE BEGIN 3 */ /* USER CODE END 3 */ /* Private functions ---------------------------------------------------------*/ void pbuf_free_custom(struct pbuf *p); /** * @brief Ethernet Rx Transfer completed callback * @param handlerEth: ETH handler * @retval None */ void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *handlerEth) { osSemaphoreRelease(RxPktSemaphore); } /** * @brief Ethernet Tx Transfer completed callback * @param handlerEth: ETH handler * @retval None */ void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *handlerEth) { osSemaphoreRelease(TxPktSemaphore); } /** * @brief Ethernet DMA transfer error callback * @param handlerEth: ETH handler * @retval None */ void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *handlerEth) { if((HAL_ETH_GetDMAError(handlerEth) & ETH_DMACSR_RBU) == ETH_DMACSR_RBU) { osSemaphoreRelease(RxPktSemaphore); } } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /******************************************************************************* LL Driver Interface ( LwIP stack --> ETH) *******************************************************************************/ /** * @brief In this function, the hardware should be initialized. * Called from ethernetif_init(). * * @param netif the already initialized lwip network interface structure * for this ethernetif */ static void low_level_init(struct netif *netif) { HAL_StatusTypeDef hal_eth_init_status = HAL_OK; /* USER CODE BEGIN OS_THREAD_ATTR_CMSIS_RTOS_V2 */ osThreadAttr_t attributes; /* USER CODE END OS_THREAD_ATTR_CMSIS_RTOS_V2 */ uint32_t duplex, speed = 0; int32_t PHYLinkState = 0; ETH_MACConfigTypeDef MACConf = {0}; /* Start ETH HAL Init */ uint8_t MACAddr[6] ; heth.Instance = ETH; 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.MediaInterface = HAL_ETH_RMII_MODE; heth.Init.TxDesc = DMATxDscrTab; heth.Init.RxDesc = DMARxDscrTab; heth.Init.RxBuffLen = 1536; /* USER CODE BEGIN MACADDRESS */ /* USER CODE END MACADDRESS */ hal_eth_init_status = HAL_ETH_Init(&heth); memset(&TxConfig, 0 , sizeof(ETH_TxPacketConfig)); TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD; TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT; /* End ETH HAL Init */ /* Initialize the RX POOL */ LWIP_MEMPOOL_INIT(RX_POOL); #if LWIP_ARP || LWIP_ETHERNET /* set MAC hardware address length */ netif->hwaddr_len = ETH_HWADDR_LEN; /* set MAC hardware address */ 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]; /* maximum transfer unit */ netif->mtu = ETH_MAX_PAYLOAD; /* Accept broadcast address and ARP traffic */ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ #if LWIP_ARP netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; #else netif->flags |= NETIF_FLAG_BROADCAST; #endif /* LWIP_ARP */ /* create a binary semaphore used for informing ethernetif of frame reception */ RxPktSemaphore = osSemaphoreNew(1, 0, NULL); /* create a binary semaphore used for informing ethernetif of frame transmission */ TxPktSemaphore = osSemaphoreNew(1, 0, NULL); /* create the task that handles the ETH_MAC */ /* USER CODE BEGIN OS_THREAD_NEW_CMSIS_RTOS_V2 */ memset(&attributes, 0x0, sizeof(osThreadAttr_t)); attributes.name = "EthIf"; attributes.stack_size = INTERFACE_THREAD_STACK_SIZE; attributes.priority = osPriorityRealtime; osThreadNew(ethernetif_input, netif, &attributes); /* USER CODE END OS_THREAD_NEW_CMSIS_RTOS_V2 */ /* USER CODE BEGIN PHY_PRE_CONFIG */ /* USER CODE END PHY_PRE_CONFIG */ /* Set PHY IO functions */ LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx); /* Initialize the LAN8742 ETH PHY */ LAN8742_Init(&LAN8742); if (hal_eth_init_status == HAL_OK) { PHYLinkState = LAN8742_GetLinkState(&LAN8742); /* Get link state */ if(PHYLinkState <= LAN8742_STATUS_LINK_DOWN) { netif_set_link_down(netif); netif_set_down(netif); } else { switch (PHYLinkState) { case LAN8742_STATUS_100MBITS_FULLDUPLEX: duplex = ETH_FULLDUPLEX_MODE; speed = ETH_SPEED_100M; break; case LAN8742_STATUS_100MBITS_HALFDUPLEX: duplex = ETH_HALFDUPLEX_MODE; speed = ETH_SPEED_100M; break; case LAN8742_STATUS_10MBITS_FULLDUPLEX: duplex = ETH_FULLDUPLEX_MODE; speed = ETH_SPEED_10M; break; case LAN8742_STATUS_10MBITS_HALFDUPLEX: duplex = ETH_HALFDUPLEX_MODE; speed = ETH_SPEED_10M; break; default: duplex = ETH_FULLDUPLEX_MODE; speed = ETH_SPEED_100M; break; } /* Get MAC Config MAC */ HAL_ETH_GetMACConfig(&heth, &MACConf); MACConf.DuplexMode = duplex; MACConf.Speed = speed; HAL_ETH_SetMACConfig(&heth, &MACConf); HAL_ETH_Start_IT(&heth); netif_set_up(netif); netif_set_link_up(netif); /* USER CODE BEGIN PHY_POST_CONFIG */ /* USER CODE END PHY_POST_CONFIG */ } } else { Error_Handler(); } #endif /* LWIP_ARP || LWIP_ETHERNET */ /* USER CODE BEGIN LOW_LEVEL_INIT */ debug_print("ethernetif phy link state:%d\r\n",PHYLinkState); /* USER CODE END LOW_LEVEL_INIT */ } /** * @brief This function should do the actual transmission of the packet. The packet is * contained in the pbuf that is passed to the function. This pbuf * might be chained. * * @param netif the lwip network interface structure for this ethernetif * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) * @return ERR_OK if the packet could be sent * an err_t value if the packet couldn't be sent * * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to * strange results. You might consider waiting for space in the DMA queue * to become available since the stack doesn't retry to send a packet * dropped because of memory failure (except for the TCP timers). */ static err_t low_level_output(struct netif *netif, struct pbuf *p) { uint32_t i = 0U; struct pbuf *q = NULL; err_t errval = ERR_OK; ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT] = {0}; memset(Txbuffer, 0 , ETH_TX_DESC_CNT*sizeof(ETH_BufferTypeDef)); for(q = p; q != NULL; q = q->next) { if(i >= ETH_TX_DESC_CNT) return ERR_IF; Txbuffer[i].buffer = q->payload; Txbuffer[i].len = q->len; if(i>0) { Txbuffer[i-1].next = &Txbuffer[i]; } if(q->next == NULL) { Txbuffer[i].next = NULL; } i++; } TxConfig.Length = p->tot_len; TxConfig.TxBuffer = Txbuffer; TxConfig.pData = p; pbuf_ref(p); if (HAL_ETH_Transmit_IT(&heth, &TxConfig) == HAL_OK) { while(osSemaphoreAcquire(TxPktSemaphore, TIME_WAITING_FOR_INPUT)!=osOK) { } HAL_ETH_ReleaseTxPacket(&heth); } else { pbuf_free(p); } return errval; } /** * @brief Should allocate a pbuf and transfer the bytes of the incoming * packet from the interface into the pbuf. * * @param netif the lwip network interface structure for this ethernetif * @return a pbuf filled with the received packet (including MAC header) * NULL on memory error */ static struct pbuf * low_level_input(struct netif *netif) { struct pbuf *p = NULL; if(RxAllocStatus == RX_ALLOC_OK) { HAL_ETH_ReadData(&heth, (void **)&p); } return p; } /** * @brief This function should be called when a packet is ready to be read * from the interface. It uses the function low_level_input() that * should handle the actual reception of bytes from the network * interface. Then the type of the received packet is determined and * the appropriate input function is called. * * @param netif the lwip network interface structure for this ethernetif */ void ethernetif_input(void* argument) { struct pbuf *p = NULL; struct netif *netif = (struct netif *) argument; for( ;; ) { if (osSemaphoreAcquire(RxPktSemaphore, 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); } } } #if !LWIP_ARP /** * This function has to be completed by user in case of ARP OFF. * * @param netif the lwip network interface structure for this ethernetif * @return ERR_OK if ... */ static err_t low_level_output_arp_off(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) { err_t errval; errval = ERR_OK; /* USER CODE BEGIN 5 */ /* USER CODE END 5 */ return errval; } #endif /* LWIP_ARP */ /** * @brief Should be called at the beginning of the program to set up the * network interface. It calls the function low_level_init() to do the * actual setup of the hardware. * * This function should be passed as a parameter to netif_add(). * * @param netif the lwip network interface structure for this ethernetif * @return ERR_OK if the loopif is initialized * ERR_MEM if private data couldn't be allocated * any other err_t on error */ err_t ethernetif_init(struct netif *netif) { LWIP_ASSERT("netif != NULL", (netif != NULL)); #if LWIP_NETIF_HOSTNAME /* Initialize interface hostname */ netif->hostname = "lwip"; #endif /* LWIP_NETIF_HOSTNAME */ /* * Initialize the snmp variables and counters inside the struct netif. * The last argument should be replaced with your link speed, in units * of bits per second. */ // MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); netif->name[0] = IFNAME0; netif->name[1] = IFNAME1; /* We directly use etharp_output() here to save a function call. * You can instead declare your own function an call etharp_output() * from it if you have to do some checks before sending (e.g. if link * is available...) */ #if LWIP_IPV4 #if LWIP_ARP || LWIP_ETHERNET #if LWIP_ARP netif->output = etharp_output; #else /* The user should write its own code in low_level_output_arp_off function */ netif->output = low_level_output_arp_off; #endif /* LWIP_ARP */ #endif /* LWIP_ARP || LWIP_ETHERNET */ #endif /* LWIP_IPV4 */ #if LWIP_IPV6 netif->output_ip6 = ethip6_output; #endif /* LWIP_IPV6 */ netif->linkoutput = low_level_output; /* initialize the hardware */ low_level_init(netif); return ERR_OK; } /** * @brief Custom Rx pbuf free callback * @param pbuf: pbuf to be freed * @retval None */ void pbuf_free_custom(struct pbuf *p) { struct pbuf_custom* custom_pbuf = (struct pbuf_custom*)p; LWIP_MEMPOOL_FREE(RX_POOL, custom_pbuf); /* If the Rx Buffer Pool was exhausted, signal the ethernetif_input task to * call HAL_ETH_GetRxDataBuffer to rebuild the Rx descriptors. */ if (RxAllocStatus == RX_ALLOC_ERROR) { RxAllocStatus = RX_ALLOC_OK; osSemaphoreRelease(RxPktSemaphore); } } /* USER CODE BEGIN 6 */ /** * @brief Returns the current time in milliseconds * when LWIP_TIMERS == 1 and NO_SYS == 1 * @param None * @retval Current Time value */ u32_t sys_now(void) { return HAL_GetTick(); } /* USER CODE END 6 */ /** * @brief Initializes the ETH MSP. * @param ethHandle: ETH handle * @retval None */ void HAL_ETH_MspInit(ETH_HandleTypeDef* ethHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(ethHandle->Instance==ETH) { /* USER CODE BEGIN ETH_MspInit 0 */ /* USER CODE END ETH_MspInit 0 */ /* Enable Peripheral clock */ __HAL_RCC_ETH1MAC_CLK_ENABLE(); __HAL_RCC_ETH1TX_CLK_ENABLE(); __HAL_RCC_ETH1RX_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /**ETH GPIO Configuration PC1 ------> ETH_MDC PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO PA7 ------> ETH_CRS_DV PC4 ------> ETH_RXD0 PC5 ------> ETH_RXD1 PB11 ------> ETH_TX_EN PB12 ------> ETH_TXD0 PB13 ------> ETH_TXD1 */ GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF11_ETH; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF11_ETH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF11_ETH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* Peripheral interrupt init */ HAL_NVIC_SetPriority(ETH_IRQn, 6, 0); HAL_NVIC_EnableIRQ(ETH_IRQn); /* USER CODE BEGIN ETH_MspInit 1 */ /* USER CODE END ETH_MspInit 1 */ } } void HAL_ETH_MspDeInit(ETH_HandleTypeDef* ethHandle) { if(ethHandle->Instance==ETH) { /* USER CODE BEGIN ETH_MspDeInit 0 */ /* USER CODE END ETH_MspDeInit 0 */ /* Disable Peripheral clock */ __HAL_RCC_ETH1MAC_CLK_DISABLE(); __HAL_RCC_ETH1TX_CLK_DISABLE(); __HAL_RCC_ETH1RX_CLK_DISABLE(); /**ETH GPIO Configuration PC1 ------> ETH_MDC PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO PA7 ------> ETH_CRS_DV PC4 ------> ETH_RXD0 PC5 ------> ETH_RXD1 PB11 ------> ETH_TX_EN PB12 ------> ETH_TXD0 PB13 ------> ETH_TXD1 */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5); HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7); HAL_GPIO_DeInit(GPIOB, GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13); /* Peripheral interrupt Deinit*/ HAL_NVIC_DisableIRQ(ETH_IRQn); /* USER CODE BEGIN ETH_MspDeInit 1 */ /* USER CODE END ETH_MspDeInit 1 */ } } /******************************************************************************* PHI IO Functions *******************************************************************************/ /** * @brief Initializes the MDIO interface GPIO and clocks. * @param None * @retval 0 if OK, -1 if ERROR */ int32_t ETH_PHY_IO_Init(void) { /* We assume that MDIO GPIO configuration is already done in the ETH_MspInit() else it should be done here */ /* Configure the MDIO Clock */ HAL_ETH_SetMDIOClockRange(&heth); return 0; } /** * @brief De-Initializes the MDIO interface . * @param None * @retval 0 if OK, -1 if ERROR */ int32_t ETH_PHY_IO_DeInit (void) { return 0; } /** * @brief Read a PHY register through the MDIO interface. * @param DevAddr: PHY port address * @param RegAddr: PHY register address * @param pRegVal: pointer to hold the register value * @retval 0 if OK -1 if Error */ int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal) { if(HAL_ETH_ReadPHYRegister(&heth, DevAddr, RegAddr, pRegVal) != HAL_OK) { return -1; } return 0; } /** * @brief Write a value to a PHY register through the MDIO interface. * @param DevAddr: PHY port address * @param RegAddr: PHY register address * @param RegVal: Value to be written * @retval 0 if OK -1 if Error */ int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal) { if(HAL_ETH_WritePHYRegister(&heth, DevAddr, RegAddr, RegVal) != HAL_OK) { return -1; } return 0; } /** * @brief Get the time in millisecons used for internal PHY driver process. * @retval Time value */ int32_t ETH_PHY_IO_GetTick(void) { return HAL_GetTick(); } /** * @brief Check the ETH link state then update ETH driver and netif link accordingly. * @retval None */ void ethernet_link_thread(void* argument) { ETH_MACConfigTypeDef MACConf = {0}; int32_t PHYLinkState = 0; uint32_t linkchanged = 0U, speed = 0U, duplex = 0U; struct netif *netif = (struct netif *) argument; /* USER CODE BEGIN ETH link init */ /* USER CODE END ETH link init */ for(;;) { PHYLinkState = LAN8742_GetLinkState(&LAN8742); if(netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN)) { HAL_ETH_Stop_IT(&heth); netif_set_down(netif); netif_set_link_down(netif); } else if(!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN)) { switch (PHYLinkState) { case LAN8742_STATUS_100MBITS_FULLDUPLEX: duplex = ETH_FULLDUPLEX_MODE; speed = ETH_SPEED_100M; linkchanged = 1; break; case LAN8742_STATUS_100MBITS_HALFDUPLEX: duplex = ETH_HALFDUPLEX_MODE; speed = ETH_SPEED_100M; linkchanged = 1; break; case LAN8742_STATUS_10MBITS_FULLDUPLEX: duplex = ETH_FULLDUPLEX_MODE; speed = ETH_SPEED_10M; linkchanged = 1; break; case LAN8742_STATUS_10MBITS_HALFDUPLEX: duplex = ETH_HALFDUPLEX_MODE; speed = ETH_SPEED_10M; linkchanged = 1; break; default: break; } if(linkchanged) { /* Get MAC Config MAC */ HAL_ETH_GetMACConfig(&heth, &MACConf); MACConf.DuplexMode = duplex; MACConf.Speed = speed; HAL_ETH_SetMACConfig(&heth, &MACConf); HAL_ETH_Start_IT(&heth); netif_set_up(netif); netif_set_link_up(netif); } } /* USER CODE BEGIN ETH link Thread core code for User BSP */ /* USER CODE END ETH link Thread core code for User BSP */ osDelay(100); } } void HAL_ETH_RxAllocateCallback(uint8_t **buff) { /* USER CODE BEGIN HAL ETH RxAllocateCallback */ struct pbuf_custom *p = LWIP_MEMPOOL_ALLOC(RX_POOL); if (p) { /* Get the buff from the struct pbuf address. */ *buff = (uint8_t *)p + offsetof(RxBuff_t, buff); p->custom_free_function = pbuf_free_custom; /* Initialize the struct pbuf. * This must be performed whenever a buffer's allocated because it may be * changed by lwIP or the app, e.g., pbuf_free decrements ref. */ pbuf_alloced_custom(PBUF_RAW, 0, PBUF_REF, p, *buff, ETH_RX_BUFFER_SIZE); } else { RxAllocStatus = RX_ALLOC_ERROR; *buff = NULL; } /* USER CODE END HAL ETH RxAllocateCallback */ } void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length) { /* USER CODE BEGIN HAL ETH RxLinkCallback */ struct pbuf **ppStart = (struct pbuf **)pStart; struct pbuf **ppEnd = (struct pbuf **)pEnd; struct pbuf *p = NULL; /* Get the struct pbuf from the buff address. */ p = (struct pbuf *)(buff - offsetof(RxBuff_t, buff)); p->next = NULL; p->tot_len = 0; p->len = Length; /* Chain the buffer. */ if (!*ppStart) { /* The first buffer of the packet. */ *ppStart = p; } else { /* Chain the buffer to the end of the packet. */ (*ppEnd)->next = p; } *ppEnd = p; /* Update the total length of all the buffers of the chain. Each pbuf in the chain should have its tot_len * set to its own length, plus the length of all the following pbufs in the chain. */ for (p = *ppStart; p != NULL; p = p->next) { p->tot_len += Length; } /* Invalidate data cache because Rx DMA's writing to physical memory makes it stale. */ SCB_InvalidateDCache_by_Addr((uint32_t *)buff, Length); /* USER CODE END HAL ETH RxLinkCallback */ } void HAL_ETH_TxFreeCallback(uint32_t * buff) { /* USER CODE BEGIN HAL ETH TxFreeCallback */ pbuf_free((struct pbuf *)buff); /* USER CODE END HAL ETH TxFreeCallback */ } /* USER CODE BEGIN 8 */ /* USER CODE END 8 */ PING 截图

标签:

STM32H743ZIT6FreeRTOSCMSIS_V2LwipDP83848/LAN8720最新HALV1.由讯客互联游戏开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“STM32H743ZIT6FreeRTOSCMSIS_V2LwipDP83848/LAN8720最新HALV1.