ethernetif.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143
  1. /* USER CODE BEGIN Header */
  2. /**
  3. ******************************************************************************
  4. * File Name : ethernetif.c
  5. * Description : This file provides code for the configuration
  6. * of the ethernetif.c MiddleWare.
  7. ******************************************************************************
  8. * @attention
  9. *
  10. * Copyright (c) 2022 STMicroelectronics.
  11. * All rights reserved.
  12. *
  13. * This software is licensed under terms that can be found in the LICENSE file
  14. * in the root directory of this software component.
  15. * If no LICENSE file comes with this software, it is provided AS-IS.
  16. *
  17. ******************************************************************************
  18. */
  19. /* USER CODE END Header */
  20. /* Includes ------------------------------------------------------------------*/
  21. #include "main.h"
  22. #include "lwip/opt.h"
  23. #include "lwip/timeouts.h"
  24. #include "netif/ethernet.h"
  25. #include "netif/etharp.h"
  26. #include "lwip/ethip6.h"
  27. #include "ethernetif.h"
  28. #include "lan8742.h"
  29. #include <string.h>
  30. #include "cmsis_os.h"
  31. #include "lwip/tcpip.h"
  32. /* Within 'USER CODE' section, code will be kept by default at each generation */
  33. /* USER CODE BEGIN 0 */
  34. /* USER CODE END 0 */
  35. /* Private define ------------------------------------------------------------*/
  36. /* The time to block waiting for input. */
  37. #define TIME_WAITING_FOR_INPUT ( portMAX_DELAY )
  38. /* USER CODE BEGIN OS_THREAD_STACK_SIZE_WITH_RTOS */
  39. /* ETH_CODE: increase stack size, otherwise there
  40. * might be overflow in more advanced applications.
  41. * Lower optimization can increase the stack usage
  42. * and cause stack overflows in some cases.
  43. */
  44. /* Stack size of the interface thread */
  45. #define INTERFACE_THREAD_STACK_SIZE ( 1024 )
  46. /* USER CODE END OS_THREAD_STACK_SIZE_WITH_RTOS */
  47. /* Network interface name */
  48. #define IFNAME0 's'
  49. #define IFNAME1 't'
  50. /* ETH Setting */
  51. #define ETH_DMA_TRANSMIT_TIMEOUT ( 20U )
  52. #define ETH_TX_BUFFER_MAX ((ETH_TX_DESC_CNT) * 2U)
  53. /* ETH_RX_BUFFER_SIZE parameter is defined in lwipopts.h */
  54. /* USER CODE BEGIN 1 */
  55. #if USE_DHCP
  56. #define MAX_DHCP_TRIES 4
  57. enum dhcp_states {
  58. DHCP_OFF = 0,
  59. DHCP_START,
  60. DHCP_WAIT_ADDRESS,
  61. DHCP_ADDRESS_ASSIGNED,
  62. DHCP_TIMEOUT,
  63. DHCP_LINKD_DOWN,
  64. DHCP_LAST
  65. } ;
  66. #endif
  67. /* USER CODE END 1 */
  68. /* Private variables ---------------------------------------------------------*/
  69. /*
  70. @Note: This interface is implemented to operate in zero-copy mode only:
  71. - Rx buffers are allocated statically and passed directly to the LwIP stack
  72. they will return back to ETH DMA after been processed by the stack.
  73. - Tx Buffers will be allocated from LwIP stack memory heap,
  74. then passed to ETH HAL driver.
  75. @Notes:
  76. 1.a. ETH DMA Rx descriptors must be contiguous, the default count is 4,
  77. to customize it please redefine ETH_RX_DESC_CNT in ETH GUI (Rx Descriptor Length)
  78. so that updated value will be generated in stm32xxxx_hal_conf.h
  79. 1.b. ETH DMA Tx descriptors must be contiguous, the default count is 4,
  80. to customize it please redefine ETH_TX_DESC_CNT in ETH GUI (Tx Descriptor Length)
  81. so that updated value will be generated in stm32xxxx_hal_conf.h
  82. 2.a. Rx Buffers number must be between ETH_RX_DESC_CNT and 2*ETH_RX_DESC_CNT
  83. 2.b. Rx Buffers must have the same size: ETH_RX_BUFFER_SIZE, this value must
  84. passed to ETH DMA in the init field (heth.Init.RxBuffLen)
  85. 2.c The RX Ruffers addresses and sizes must be properly defined to be aligned
  86. to L1-CACHE line size (32 bytes).
  87. */
  88. /* Data Type Definitions */
  89. typedef enum
  90. {
  91. RX_ALLOC_OK = 0x00,
  92. RX_ALLOC_ERROR = 0x01
  93. } RxAllocStatusTypeDef;
  94. typedef struct
  95. {
  96. struct pbuf_custom pbuf_custom;
  97. uint8_t buff[(ETH_RX_BUFFER_SIZE + 31) & ~31] __ALIGNED(32);
  98. } RxBuff_t;
  99. /* Memory Pool Declaration */
  100. #define ETH_RX_BUFFER_CNT 12U
  101. LWIP_MEMPOOL_DECLARE(RX_POOL, ETH_RX_BUFFER_CNT, sizeof(RxBuff_t), "Zero-copy RX PBUF pool");
  102. /* Variable Definitions */
  103. static uint8_t RxAllocStatus;
  104. __IO uint32_t TxPkt = 0;
  105. __IO uint32_t RxPkt = 0;
  106. #if defined ( __ICCARM__ ) /*!< IAR Compiler */
  107. #pragma location=0x30000000
  108. ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
  109. #pragma location=0x30000100
  110. ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
  111. #elif defined ( __CC_ARM ) /* MDK ARM Compiler */
  112. __attribute__((at(0x30000000))) ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
  113. __attribute__((at(0x30000100))) ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
  114. #elif defined ( __GNUC__ ) /* GNU Compiler */
  115. ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
  116. ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */
  117. #endif
  118. /* USER CODE BEGIN 2 */
  119. /* ETH_CODE: placement of RX_POOL
  120. * Please note this was tested only for GCC compiler.
  121. * Additional code needed in linkerscript for GCC.
  122. *
  123. * Also this buffer can be placed in D1 SRAM
  124. * if there is not sufficient space in D2.
  125. * This can be case of STM32H72x/H73x devices.
  126. * However the 32-byte alignment should be forced.
  127. * Below is example of placement into BSS section
  128. *
  129. * . = ALIGN(32);
  130. * *(.Rx_PoolSection)
  131. * . = ALIGN(4);
  132. * _ebss = .;
  133. * __bss_end__ = _ebss;
  134. * } >RAM_D1
  135. */
  136. #if defined ( __ICCARM__ ) /*!< IAR Compiler */
  137. #pragma location = 0x30040200
  138. extern u8_t memp_memory_RX_POOL_base[];
  139. #elif defined ( __CC_ARM ) /* MDK ARM Compiler */
  140. __attribute__((at(0x30040200)) extern u8_t memp_memory_RX_POOL_base[];
  141. #elif defined ( __GNUC__ ) /* GNU Compiler */
  142. __attribute__((section(".Rx_PoolSection"))) extern u8_t memp_memory_RX_POOL_base[];
  143. #endif
  144. /* USER CODE END 2 */
  145. osSemaphoreId RxPktSemaphore = NULL; /* Semaphore to signal incoming packets */
  146. osSemaphoreId TxPktSemaphore = NULL; /* Semaphore to signal transmit packet complete */
  147. /* Global Ethernet handle */
  148. ETH_HandleTypeDef heth;
  149. ETH_TxPacketConfig TxConfig;
  150. /* Private function prototypes -----------------------------------------------*/
  151. int32_t ETH_PHY_IO_Init(void);
  152. int32_t ETH_PHY_IO_DeInit (void);
  153. int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal);
  154. int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal);
  155. int32_t ETH_PHY_IO_GetTick(void);
  156. lan8742_Object_t LAN8742;
  157. lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init,
  158. ETH_PHY_IO_DeInit,
  159. ETH_PHY_IO_WriteReg,
  160. ETH_PHY_IO_ReadReg,
  161. ETH_PHY_IO_GetTick};
  162. /* USER CODE BEGIN 3 */
  163. #if USE_DHCP
  164. void dhcp_sm(struct netif *netif, enum dhcp_states *state);
  165. #endif
  166. /* USER CODE END 3 */
  167. /* Private functions ---------------------------------------------------------*/
  168. void pbuf_free_custom(struct pbuf *p);
  169. /**
  170. * @brief Ethernet Rx Transfer completed callback
  171. * @param handlerEth: ETH handler
  172. * @retval None
  173. */
  174. void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *handlerEth)
  175. {
  176. osSemaphoreRelease(RxPktSemaphore);
  177. }
  178. /**
  179. * @brief Ethernet Tx Transfer completed callback
  180. * @param handlerEth: ETH handler
  181. * @retval None
  182. */
  183. void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *handlerEth)
  184. {
  185. osSemaphoreRelease(TxPktSemaphore);
  186. }
  187. /**
  188. * @brief Ethernet DMA transfer error callback
  189. * @param handlerEth: ETH handler
  190. * @retval None
  191. */
  192. void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *handlerEth)
  193. {
  194. if((HAL_ETH_GetDMAError(handlerEth) & ETH_DMACSR_RBU) == ETH_DMACSR_RBU)
  195. {
  196. osSemaphoreRelease(RxPktSemaphore);
  197. }
  198. }
  199. /* USER CODE BEGIN 4 */
  200. /* USER CODE END 4 */
  201. /*******************************************************************************
  202. LL Driver Interface ( LwIP stack --> ETH)
  203. *******************************************************************************/
  204. /**
  205. * @brief In this function, the hardware should be initialized.
  206. * Called from ethernetif_init().
  207. *
  208. * @param netif the already initialized lwip network interface structure
  209. * for this ethernetif
  210. */
  211. static void low_level_init(struct netif *netif)
  212. {
  213. HAL_StatusTypeDef hal_eth_init_status = HAL_OK;
  214. /* USER CODE BEGIN OS_THREAD_ATTR_CMSIS_RTOS_V2 */
  215. osThreadAttr_t attributes;
  216. /* USER CODE END OS_THREAD_ATTR_CMSIS_RTOS_V2 */
  217. uint32_t duplex, speed = 0;
  218. int32_t PHYLinkState = 0;
  219. ETH_MACConfigTypeDef MACConf = {0};
  220. /* Start ETH HAL Init */
  221. uint8_t MACAddr[6] ;
  222. heth.Instance = ETH;
  223. // MACAddr[0] = 0x00;
  224. // MACAddr[1] = 0x80;
  225. // MACAddr[2] = 0xE1;
  226. // MACAddr[3] = 0x00;
  227. // MACAddr[4] = 0x00;
  228. // MACAddr[5] = 0x00;
  229. MACAddr[0] = 0x7C;
  230. MACAddr[1] = 0xF6;
  231. MACAddr[2] = 0x66;
  232. MACAddr[3] = 0xE4;
  233. MACAddr[4] = 0xB5;
  234. MACAddr[5] = 0x41;
  235. heth.Init.MACAddr = &MACAddr[0];
  236. heth.Init.MediaInterface = HAL_ETH_MII_MODE;
  237. heth.Init.TxDesc = DMATxDscrTab;
  238. heth.Init.RxDesc = DMARxDscrTab;
  239. heth.Init.RxBuffLen = 1536;
  240. /* USER CODE BEGIN MACADDRESS */
  241. /* USER CODE END MACADDRESS */
  242. hal_eth_init_status = HAL_ETH_Init(&heth);
  243. memset(&TxConfig, 0 , sizeof(ETH_TxPacketConfig));
  244. TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
  245. TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
  246. TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
  247. /* End ETH HAL Init */
  248. /* Initialize the RX POOL */
  249. LWIP_MEMPOOL_INIT(RX_POOL);
  250. #if LWIP_ARP || LWIP_ETHERNET
  251. /* set MAC hardware address length */
  252. netif->hwaddr_len = ETH_HWADDR_LEN;
  253. /* set MAC hardware address */
  254. netif->hwaddr[0] = heth.Init.MACAddr[0];
  255. netif->hwaddr[1] = heth.Init.MACAddr[1];
  256. netif->hwaddr[2] = heth.Init.MACAddr[2];
  257. netif->hwaddr[3] = heth.Init.MACAddr[3];
  258. netif->hwaddr[4] = heth.Init.MACAddr[4];
  259. netif->hwaddr[5] = heth.Init.MACAddr[5];
  260. /* maximum transfer unit */
  261. netif->mtu = ETH_MAX_PAYLOAD;
  262. /* Accept broadcast address and ARP traffic */
  263. /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
  264. #if LWIP_ARP
  265. netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
  266. #else
  267. netif->flags |= NETIF_FLAG_BROADCAST;
  268. #endif /* LWIP_ARP */
  269. /* create a binary semaphore used for informing ethernetif of frame reception */
  270. RxPktSemaphore = osSemaphoreNew(1, 1, NULL);
  271. /* create a binary semaphore used for informing ethernetif of frame transmission */
  272. TxPktSemaphore = osSemaphoreNew(1, 1, NULL);
  273. /* create the task that handles the ETH_MAC */
  274. /* USER CODE BEGIN OS_THREAD_NEW_CMSIS_RTOS_V2 */
  275. memset(&attributes, 0x0, sizeof(osThreadAttr_t));
  276. attributes.name = "EthIf";
  277. attributes.stack_size = INTERFACE_THREAD_STACK_SIZE;
  278. attributes.priority = osPriorityRealtime;
  279. osThreadNew(ethernetif_input, netif, &attributes);
  280. /* USER CODE END OS_THREAD_NEW_CMSIS_RTOS_V2 */
  281. /* USER CODE BEGIN PHY_PRE_CONFIG */
  282. /* USER CODE END PHY_PRE_CONFIG */
  283. /* Set PHY IO functions */
  284. LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx);
  285. /* Initialize the LAN8742 ETH PHY */
  286. LAN8742_Init(&LAN8742);
  287. if (hal_eth_init_status == HAL_OK)
  288. {
  289. PHYLinkState = LAN8742_GetLinkState(&LAN8742);
  290. /* Get link state */
  291. if(PHYLinkState <= LAN8742_STATUS_LINK_DOWN)
  292. {
  293. netif_set_link_down(netif);
  294. netif_set_down(netif);
  295. }
  296. else
  297. {
  298. switch (PHYLinkState)
  299. {
  300. case LAN8742_STATUS_100MBITS_FULLDUPLEX:
  301. duplex = ETH_FULLDUPLEX_MODE;
  302. speed = ETH_SPEED_100M;
  303. break;
  304. case LAN8742_STATUS_100MBITS_HALFDUPLEX:
  305. duplex = ETH_HALFDUPLEX_MODE;
  306. speed = ETH_SPEED_100M;
  307. break;
  308. case LAN8742_STATUS_10MBITS_FULLDUPLEX:
  309. duplex = ETH_FULLDUPLEX_MODE;
  310. speed = ETH_SPEED_10M;
  311. break;
  312. case LAN8742_STATUS_10MBITS_HALFDUPLEX:
  313. duplex = ETH_HALFDUPLEX_MODE;
  314. speed = ETH_SPEED_10M;
  315. break;
  316. default:
  317. duplex = ETH_FULLDUPLEX_MODE;
  318. speed = ETH_SPEED_100M;
  319. break;
  320. }
  321. /* Get MAC Config MAC */
  322. HAL_ETH_GetMACConfig(&heth, &MACConf);
  323. MACConf.DuplexMode = duplex;
  324. MACConf.Speed = speed;
  325. HAL_ETH_SetMACConfig(&heth, &MACConf);
  326. HAL_ETH_Start_IT(&heth);
  327. netif_set_up(netif);
  328. netif_set_link_up(netif);
  329. /* USER CODE BEGIN PHY_POST_CONFIG */
  330. ethernetif_notify_conn_changed(netif);
  331. /* USER CODE END PHY_POST_CONFIG */
  332. }
  333. }
  334. else
  335. {
  336. Error_Handler();
  337. }
  338. #endif /* LWIP_ARP || LWIP_ETHERNET */
  339. /* USER CODE BEGIN LOW_LEVEL_INIT */
  340. /* USER CODE END LOW_LEVEL_INIT */
  341. }
  342. /**
  343. * This function should do the actual transmission of the packet. The packet is
  344. * contained in the pbuf that is passed to the function. This pbuf
  345. * might be chained.
  346. *
  347. * @param netif the lwip network interface structure for this ethernetif
  348. * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
  349. * @return ERR_OK if the packet could be sent
  350. * an err_t value if the packet couldn't be sent
  351. *
  352. * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
  353. * strange results. You might consider waiting for space in the DMA queue
  354. * to become available since the stack doesn't retry to send a packet
  355. * dropped because of memory failure (except for the TCP timers).
  356. */
  357. static err_t low_level_output(struct netif *netif, struct pbuf *p)
  358. {
  359. uint32_t i = 0U;
  360. struct pbuf *q = NULL;
  361. err_t errval = ERR_OK;
  362. ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT];
  363. memset(Txbuffer, 0 , ETH_TX_DESC_CNT*sizeof(ETH_BufferTypeDef));
  364. for(q = p; q != NULL; q = q->next)
  365. {
  366. if(i >= ETH_TX_DESC_CNT)
  367. return ERR_IF;
  368. Txbuffer[i].buffer = q->payload;
  369. Txbuffer[i].len = q->len;
  370. if(i>0)
  371. {
  372. Txbuffer[i-1].next = &Txbuffer[i];
  373. }
  374. if(q->next == NULL)
  375. {
  376. Txbuffer[i].next = NULL;
  377. }
  378. i++;
  379. }
  380. TxConfig.Length = p->tot_len;
  381. TxConfig.TxBuffer = Txbuffer;
  382. TxConfig.pData = p;
  383. pbuf_ref(p);
  384. HAL_ETH_Transmit_IT(&heth, &TxConfig);
  385. // while(osSemaphoreAcquire(TxPktSemaphore, TIME_WAITING_FOR_INPUT)!=osOK)
  386. // while(osSemaphoreAcquire(TxPktSemaphore, pdMS_TO_TICKS(1000))!=osOK)
  387. // {
  388. // }
  389. osSemaphoreAcquire(TxPktSemaphore, pdMS_TO_TICKS(1000));
  390. HAL_ETH_ReleaseTxPacket(&heth);
  391. return errval;
  392. }
  393. /**
  394. * Should allocate a pbuf and transfer the bytes of the incoming
  395. * packet from the interface into the pbuf.
  396. *
  397. * @param netif the lwip network interface structure for this ethernetif
  398. * @return a pbuf filled with the received packet (including MAC header)
  399. * NULL on memory error
  400. */
  401. static struct pbuf * low_level_input(struct netif *netif)
  402. {
  403. struct pbuf *p = NULL;
  404. if(RxAllocStatus == RX_ALLOC_OK)
  405. {
  406. HAL_ETH_ReadData(&heth, (void **)&p);
  407. }
  408. return p;
  409. }
  410. /**
  411. * This function should be called when a packet is ready to be read
  412. * from the interface. It uses the function low_level_input() that
  413. * should handle the actual reception of bytes from the network
  414. * interface. Then the type of the received packet is determined and
  415. * the appropriate input function is called.
  416. *
  417. * @param netif the lwip network interface structure for this ethernetif
  418. */
  419. void ethernetif_input(void* argument)
  420. {
  421. struct pbuf *p = NULL;
  422. struct netif *netif = (struct netif *) argument;
  423. for( ;; )
  424. {
  425. if (osSemaphoreAcquire(RxPktSemaphore, TIME_WAITING_FOR_INPUT) == osOK)
  426. {
  427. do
  428. {
  429. p = low_level_input( netif );
  430. if (p != NULL)
  431. {
  432. if (netif->input( p, netif) != ERR_OK )
  433. {
  434. pbuf_free(p);
  435. }
  436. }
  437. } while(p!=NULL);
  438. }
  439. }
  440. }
  441. #if !LWIP_ARP
  442. /**
  443. * This function has to be completed by user in case of ARP OFF.
  444. *
  445. * @param netif the lwip network interface structure for this ethernetif
  446. * @return ERR_OK if ...
  447. */
  448. static err_t low_level_output_arp_off(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
  449. {
  450. err_t errval;
  451. errval = ERR_OK;
  452. /* USER CODE BEGIN 5 */
  453. /* USER CODE END 5 */
  454. return errval;
  455. }
  456. #endif /* LWIP_ARP */
  457. /**
  458. * Should be called at the beginning of the program to set up the
  459. * network interface. It calls the function low_level_init() to do the
  460. * actual setup of the hardware.
  461. *
  462. * This function should be passed as a parameter to netif_add().
  463. *
  464. * @param netif the lwip network interface structure for this ethernetif
  465. * @return ERR_OK if the loopif is initialized
  466. * ERR_MEM if private data couldn't be allocated
  467. * any other err_t on error
  468. */
  469. err_t ethernetif_init(struct netif *netif)
  470. {
  471. LWIP_ASSERT("netif != NULL", (netif != NULL));
  472. #if LWIP_NETIF_HOSTNAME
  473. /* Initialize interface hostname */
  474. netif->hostname = "lwip";
  475. #endif /* LWIP_NETIF_HOSTNAME */
  476. /*
  477. * Initialize the snmp variables and counters inside the struct netif.
  478. * The last argument should be replaced with your link speed, in units
  479. * of bits per second.
  480. */
  481. // MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
  482. netif->name[0] = IFNAME0;
  483. netif->name[1] = IFNAME1;
  484. /* We directly use etharp_output() here to save a function call.
  485. * You can instead declare your own function an call etharp_output()
  486. * from it if you have to do some checks before sending (e.g. if link
  487. * is available...) */
  488. #if LWIP_IPV4
  489. #if LWIP_ARP || LWIP_ETHERNET
  490. #if LWIP_ARP
  491. netif->output = etharp_output;
  492. #else
  493. /* The user should write its own code in low_level_output_arp_off function */
  494. netif->output = low_level_output_arp_off;
  495. #endif /* LWIP_ARP */
  496. #endif /* LWIP_ARP || LWIP_ETHERNET */
  497. #endif /* LWIP_IPV4 */
  498. #if LWIP_IPV6
  499. netif->output_ip6 = ethip6_output;
  500. #endif /* LWIP_IPV6 */
  501. netif->linkoutput = low_level_output;
  502. /* initialize the hardware */
  503. low_level_init(netif);
  504. return ERR_OK;
  505. }
  506. /**
  507. * @brief Custom Rx pbuf free callback
  508. * @param pbuf: pbuf to be freed
  509. * @retval None
  510. */
  511. void pbuf_free_custom(struct pbuf *p)
  512. {
  513. struct pbuf_custom* custom_pbuf = (struct pbuf_custom*)p;
  514. LWIP_MEMPOOL_FREE(RX_POOL, custom_pbuf);
  515. /* If the Rx Buffer Pool was exhausted, signal the ethernetif_input task to
  516. * call HAL_ETH_GetRxDataBuffer to rebuild the Rx descriptors. */
  517. if (RxAllocStatus == RX_ALLOC_ERROR)
  518. {
  519. RxAllocStatus = RX_ALLOC_OK;
  520. osSemaphoreRelease(RxPktSemaphore);
  521. }
  522. }
  523. /* USER CODE BEGIN 6 */
  524. /**
  525. * @brief Returns the current time in milliseconds
  526. * when LWIP_TIMERS == 1 and NO_SYS == 1
  527. * @param None
  528. * @retval Current Time value
  529. */
  530. u32_t sys_now(void)
  531. {
  532. return HAL_GetTick();
  533. }
  534. /* USER CODE END 6 */
  535. void HAL_ETH_MspInit(ETH_HandleTypeDef* ethHandle)
  536. {
  537. GPIO_InitTypeDef GPIO_InitStruct = {0};
  538. if(ethHandle->Instance==ETH)
  539. {
  540. /* USER CODE BEGIN ETH_MspInit 0 */
  541. /* USER CODE END ETH_MspInit 0 */
  542. /* Enable Peripheral clock */
  543. __HAL_RCC_ETH1MAC_CLK_ENABLE();
  544. __HAL_RCC_ETH1TX_CLK_ENABLE();
  545. __HAL_RCC_ETH1RX_CLK_ENABLE();
  546. __HAL_RCC_GPIOG_CLK_ENABLE();
  547. __HAL_RCC_GPIOE_CLK_ENABLE();
  548. __HAL_RCC_GPIOI_CLK_ENABLE();
  549. __HAL_RCC_GPIOC_CLK_ENABLE();
  550. __HAL_RCC_GPIOA_CLK_ENABLE();
  551. __HAL_RCC_GPIOB_CLK_ENABLE();
  552. /**ETH GPIO Configuration
  553. PG11 ------> ETH_TX_EN
  554. PE2 ------> ETH_TXD3
  555. PG12 ------> ETH_TXD1
  556. PG13 ------> ETH_TXD0
  557. PI10 ------> ETH_RX_ER
  558. PC1 ------> ETH_MDC
  559. PC2 ------> ETH_TXD2
  560. PC3 ------> ETH_TX_CLK
  561. PA2 ------> ETH_MDIO
  562. PA1 ------> ETH_RX_CLK
  563. PA0 ------> ETH_CRS
  564. PA7 ------> ETH_RX_DV
  565. PC4 ------> ETH_RXD0
  566. PB1 ------> ETH_RXD3
  567. PA3 ------> ETH_COL
  568. PC5 ------> ETH_RXD1
  569. PB0 ------> ETH_RXD2
  570. */
  571. GPIO_InitStruct.Pin = MII_TX_EN_Pin|MII_TXD1_Pin|MII_TXD0_Pin;
  572. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  573. GPIO_InitStruct.Pull = GPIO_NOPULL;
  574. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  575. GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  576. HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
  577. GPIO_InitStruct.Pin = MII_TXD3_Pin;
  578. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  579. GPIO_InitStruct.Pull = GPIO_NOPULL;
  580. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  581. GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  582. HAL_GPIO_Init(MII_TXD3_GPIO_Port, &GPIO_InitStruct);
  583. GPIO_InitStruct.Pin = MII_RX_ER_Pin;
  584. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  585. GPIO_InitStruct.Pull = GPIO_NOPULL;
  586. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  587. GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  588. HAL_GPIO_Init(MII_RX_ER_GPIO_Port, &GPIO_InitStruct);
  589. GPIO_InitStruct.Pin = MII_MDC_Pin|MII_TXD2_Pin|MII_TX_CLK_Pin|MII_RXD0_Pin
  590. |MII_RXD1_Pin;
  591. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  592. GPIO_InitStruct.Pull = GPIO_NOPULL;
  593. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  594. GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  595. HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  596. GPIO_InitStruct.Pin = MII_MDIO_Pin|GPIO_PIN_1|MII_CRS_Pin|GPIO_PIN_7
  597. |MII_COL_Pin;
  598. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  599. GPIO_InitStruct.Pull = GPIO_NOPULL;
  600. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  601. GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  602. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  603. GPIO_InitStruct.Pin = MII_RXD3_Pin|MII_RXD2_Pin;
  604. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  605. GPIO_InitStruct.Pull = GPIO_NOPULL;
  606. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  607. GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  608. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  609. /* Peripheral interrupt init */
  610. HAL_NVIC_SetPriority(ETH_IRQn, 5, 0);
  611. HAL_NVIC_EnableIRQ(ETH_IRQn);
  612. /* USER CODE BEGIN ETH_MspInit 1 */
  613. /* USER CODE END ETH_MspInit 1 */
  614. }
  615. }
  616. void HAL_ETH_MspDeInit(ETH_HandleTypeDef* ethHandle)
  617. {
  618. if(ethHandle->Instance==ETH)
  619. {
  620. /* USER CODE BEGIN ETH_MspDeInit 0 */
  621. /* USER CODE END ETH_MspDeInit 0 */
  622. /* Disable Peripheral clock */
  623. __HAL_RCC_ETH1MAC_CLK_DISABLE();
  624. __HAL_RCC_ETH1TX_CLK_DISABLE();
  625. __HAL_RCC_ETH1RX_CLK_DISABLE();
  626. /**ETH GPIO Configuration
  627. PG11 ------> ETH_TX_EN
  628. PE2 ------> ETH_TXD3
  629. PG12 ------> ETH_TXD1
  630. PG13 ------> ETH_TXD0
  631. PI10 ------> ETH_RX_ER
  632. PC1 ------> ETH_MDC
  633. PC2 ------> ETH_TXD2
  634. PC3 ------> ETH_TX_CLK
  635. PA2 ------> ETH_MDIO
  636. PA1 ------> ETH_RX_CLK
  637. PA0 ------> ETH_CRS
  638. PA7 ------> ETH_RX_DV
  639. PC4 ------> ETH_RXD0
  640. PB1 ------> ETH_RXD3
  641. PA3 ------> ETH_COL
  642. PC5 ------> ETH_RXD1
  643. PB0 ------> ETH_RXD2
  644. */
  645. HAL_GPIO_DeInit(GPIOG, MII_TX_EN_Pin|MII_TXD1_Pin|MII_TXD0_Pin);
  646. HAL_GPIO_DeInit(MII_TXD3_GPIO_Port, MII_TXD3_Pin);
  647. HAL_GPIO_DeInit(MII_RX_ER_GPIO_Port, MII_RX_ER_Pin);
  648. HAL_GPIO_DeInit(GPIOC, MII_MDC_Pin|MII_TXD2_Pin|MII_TX_CLK_Pin|MII_RXD0_Pin
  649. |MII_RXD1_Pin);
  650. HAL_GPIO_DeInit(GPIOA, MII_MDIO_Pin|GPIO_PIN_1|MII_CRS_Pin|GPIO_PIN_7
  651. |MII_COL_Pin);
  652. HAL_GPIO_DeInit(GPIOB, MII_RXD3_Pin|MII_RXD2_Pin);
  653. /* Peripheral interrupt Deinit*/
  654. HAL_NVIC_DisableIRQ(ETH_IRQn);
  655. /* USER CODE BEGIN ETH_MspDeInit 1 */
  656. /* USER CODE END ETH_MspDeInit 1 */
  657. }
  658. }
  659. /*******************************************************************************
  660. PHI IO Functions
  661. *******************************************************************************/
  662. /**
  663. * @brief Initializes the MDIO interface GPIO and clocks.
  664. * @param None
  665. * @retval 0 if OK, -1 if ERROR
  666. */
  667. int32_t ETH_PHY_IO_Init(void)
  668. {
  669. /* We assume that MDIO GPIO configuration is already done
  670. in the ETH_MspInit() else it should be done here
  671. */
  672. /* Configure the MDIO Clock */
  673. HAL_ETH_SetMDIOClockRange(&heth);
  674. return 0;
  675. }
  676. /**
  677. * @brief De-Initializes the MDIO interface .
  678. * @param None
  679. * @retval 0 if OK, -1 if ERROR
  680. */
  681. int32_t ETH_PHY_IO_DeInit (void)
  682. {
  683. return 0;
  684. }
  685. /**
  686. * @brief Read a PHY register through the MDIO interface.
  687. * @param DevAddr: PHY port address
  688. * @param RegAddr: PHY register address
  689. * @param pRegVal: pointer to hold the register value
  690. * @retval 0 if OK -1 if Error
  691. */
  692. int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal)
  693. {
  694. if(HAL_ETH_ReadPHYRegister(&heth, DevAddr, RegAddr, pRegVal) != HAL_OK)
  695. {
  696. return -1;
  697. }
  698. return 0;
  699. }
  700. /**
  701. * @brief Write a value to a PHY register through the MDIO interface.
  702. * @param DevAddr: PHY port address
  703. * @param RegAddr: PHY register address
  704. * @param RegVal: Value to be written
  705. * @retval 0 if OK -1 if Error
  706. */
  707. int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal)
  708. {
  709. if(HAL_ETH_WritePHYRegister(&heth, DevAddr, RegAddr, RegVal) != HAL_OK)
  710. {
  711. return -1;
  712. }
  713. return 0;
  714. }
  715. /**
  716. * @brief Get the time in millisecons used for internal PHY driver process.
  717. * @retval Time value
  718. */
  719. int32_t ETH_PHY_IO_GetTick(void)
  720. {
  721. return HAL_GetTick();
  722. }
  723. /**
  724. * @brief Check the ETH link state then update ETH driver and netif link accordingly.
  725. * @param argument: netif
  726. * @retval None
  727. */
  728. void ethernet_link_thread(void* argument)
  729. {
  730. ETH_MACConfigTypeDef MACConf = {0};
  731. int32_t PHYLinkState = 0;
  732. uint32_t linkchanged = 0U, speed = 0U, duplex = 0U;
  733. struct netif *netif = (struct netif *) argument;
  734. /* USER CODE BEGIN ETH link init */
  735. #if USE_DHCP
  736. enum dhcp_states DHCP_state = DHCP_START;
  737. #endif
  738. /* ETH_CODE: call HAL_ETH_Start_IT instead of HAL_ETH_Start
  739. * This is required for operation with RTOS.
  740. * This trick allows to keep this change through
  741. * code re-generation by STM32CubeMX
  742. */
  743. #define HAL_ETH_Start HAL_ETH_Start_IT
  744. /* ETH_CODE: workaround to call LOCK_TCPIP_CORE when accessing netif link functions*/
  745. // LOCK_TCPIP_CORE();
  746. /* USER CODE END ETH link init */
  747. for(;;)
  748. {
  749. PHYLinkState = LAN8742_GetLinkState(&LAN8742);
  750. if(netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN))
  751. {
  752. HAL_ETH_Stop_IT(&heth);
  753. LOCK_TCPIP_CORE();
  754. netif_set_down(netif);
  755. netif_set_link_down(netif);
  756. UNLOCK_TCPIP_CORE();
  757. printf("Link down...\r\n");
  758. }
  759. else if(!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN))
  760. {
  761. switch (PHYLinkState)
  762. {
  763. case LAN8742_STATUS_100MBITS_FULLDUPLEX:
  764. duplex = ETH_FULLDUPLEX_MODE;
  765. speed = ETH_SPEED_100M;
  766. linkchanged = 1;
  767. break;
  768. case LAN8742_STATUS_100MBITS_HALFDUPLEX:
  769. duplex = ETH_HALFDUPLEX_MODE;
  770. speed = ETH_SPEED_100M;
  771. linkchanged = 1;
  772. break;
  773. case LAN8742_STATUS_10MBITS_FULLDUPLEX:
  774. duplex = ETH_FULLDUPLEX_MODE;
  775. speed = ETH_SPEED_10M;
  776. linkchanged = 1;
  777. break;
  778. case LAN8742_STATUS_10MBITS_HALFDUPLEX:
  779. duplex = ETH_HALFDUPLEX_MODE;
  780. speed = ETH_SPEED_10M;
  781. linkchanged = 1;
  782. break;
  783. default:
  784. break;
  785. }
  786. if(linkchanged)
  787. {
  788. /* Get MAC Config MAC */
  789. HAL_ETH_GetMACConfig(&heth, &MACConf);
  790. MACConf.DuplexMode = duplex;
  791. MACConf.Speed = speed;
  792. HAL_ETH_SetMACConfig(&heth, &MACConf);
  793. HAL_ETH_Start(&heth);
  794. LOCK_TCPIP_CORE();
  795. netif_set_up(netif);
  796. netif_set_link_up(netif);
  797. UNLOCK_TCPIP_CORE();
  798. printf("Link up...\r\n");
  799. }
  800. }
  801. /* USER CODE BEGIN ETH link Thread core code for User BSP */
  802. #if USE_DHCP
  803. dhcp_sm(netif, &DHCP_state);
  804. #endif
  805. /* ETH_CODE: workaround to call LOCK_TCPIP_CORE when accessing netif link functions*/
  806. // UNLOCK_TCPIP_CORE();
  807. osDelay(pdMS_TO_TICKS(500));
  808. // LOCK_TCPIP_CORE();
  809. continue; /* skip next osDelay */
  810. /* USER CODE END ETH link Thread core code for User BSP */
  811. osDelay(100);
  812. }
  813. }
  814. /**
  815. * @brief This function notify user about link status changement.
  816. * @param netif: the network interface
  817. * @retval None
  818. */
  819. __weak void ethernetif_notify_conn_changed(struct netif *netif)
  820. {
  821. /* NOTE : This is function could be implemented in user file
  822. when the callback is needed,
  823. */
  824. }
  825. void HAL_ETH_RxAllocateCallback(uint8_t **buff)
  826. {
  827. /* USER CODE BEGIN HAL ETH RxAllocateCallback */
  828. struct pbuf_custom *p = LWIP_MEMPOOL_ALLOC(RX_POOL);
  829. if (p)
  830. {
  831. /* Get the buff from the struct pbuf address. */
  832. *buff = (uint8_t *)p + offsetof(RxBuff_t, buff);
  833. p->custom_free_function = pbuf_free_custom;
  834. /* Initialize the struct pbuf.
  835. * This must be performed whenever a buffer's allocated because it may be
  836. * changed by lwIP or the app, e.g., pbuf_free decrements ref. */
  837. pbuf_alloced_custom(PBUF_RAW, 0, PBUF_REF, p, *buff, ETH_RX_BUFFER_SIZE);
  838. }
  839. else
  840. {
  841. RxAllocStatus = RX_ALLOC_ERROR;
  842. *buff = NULL;
  843. }
  844. /* USER CODE END HAL ETH RxAllocateCallback */
  845. }
  846. void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length)
  847. {
  848. /* USER CODE BEGIN HAL ETH RxLinkCallback */
  849. struct pbuf **ppStart = (struct pbuf **)pStart;
  850. struct pbuf **ppEnd = (struct pbuf **)pEnd;
  851. struct pbuf *p = NULL;
  852. /* Get the struct pbuf from the buff address. */
  853. p = (struct pbuf *)(buff - offsetof(RxBuff_t, buff));
  854. p->next = NULL;
  855. p->tot_len = 0;
  856. p->len = Length;
  857. /* Chain the buffer. */
  858. if (!*ppStart)
  859. {
  860. /* The first buffer of the packet. */
  861. *ppStart = p;
  862. }
  863. else
  864. {
  865. /* Chain the buffer to the end of the packet. */
  866. (*ppEnd)->next = p;
  867. }
  868. *ppEnd = p;
  869. /* Update the total length of all the buffers of the chain. Each pbuf in the chain should have its tot_len
  870. * set to its own length, plus the length of all the following pbufs in the chain. */
  871. for (p = *ppStart; p != NULL; p = p->next)
  872. {
  873. p->tot_len += Length;
  874. }
  875. /* Invalidate data cache because Rx DMA's writing to physical memory makes it stale. */
  876. SCB_InvalidateDCache_by_Addr((uint32_t *)buff, Length);
  877. /* USER CODE END HAL ETH RxLinkCallback */
  878. }
  879. void HAL_ETH_TxFreeCallback(uint32_t * buff)
  880. {
  881. /* USER CODE BEGIN HAL ETH TxFreeCallback */
  882. pbuf_free((struct pbuf *)buff);
  883. /* USER CODE END HAL ETH TxFreeCallback */
  884. }
  885. /* USER CODE BEGIN 8 */
  886. /* ETH_CODE: add functions needed for proper multithreading support and check */
  887. static osThreadId_t lwip_core_lock_holder_thread_id;
  888. static osThreadId_t lwip_tcpip_thread_id;
  889. void sys_lock_tcpip_core(void){
  890. sys_mutex_lock(&lock_tcpip_core);
  891. lwip_core_lock_holder_thread_id = osThreadGetId();
  892. }
  893. void sys_unlock_tcpip_core(void){
  894. lwip_core_lock_holder_thread_id = 0;
  895. sys_mutex_unlock(&lock_tcpip_core);
  896. }
  897. void sys_check_core_locking(void){
  898. /* Embedded systems should check we are NOT in an interrupt context here */
  899. LWIP_ASSERT("Function called from interrupt context", (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) == 0);
  900. if (lwip_tcpip_thread_id != 0) {
  901. osThreadId_t current_thread_id = osThreadGetId();
  902. #if LWIP_TCPIP_CORE_LOCKING
  903. LWIP_ASSERT("Function called without core lock", current_thread_id == lwip_core_lock_holder_thread_id);
  904. /* ETH_CODE: to easily check that example has correct handling of core lock
  905. * This will trigger breakpoint (__BKPT)
  906. */
  907. #warning Below check should be removed in production code
  908. if(current_thread_id != lwip_core_lock_holder_thread_id) __BKPT(0);
  909. #else /* LWIP_TCPIP_CORE_LOCKING */
  910. LWIP_ASSERT("Function called from wrong thread", current_thread_id == lwip_tcpip_thread_id);
  911. #endif /* LWIP_TCPIP_CORE_LOCKING */
  912. LWIP_UNUSED_ARG(current_thread_id); /* for LWIP_NOASSERT */
  913. }
  914. }
  915. void sys_mark_tcpip_thread(void){
  916. lwip_tcpip_thread_id = osThreadGetId();
  917. }
  918. void dhcp_sm(struct netif *netif, enum dhcp_states *state)
  919. {
  920. struct dhcp *dhcp;
  921. ip_addr_t ipaddr;
  922. ip_addr_t netmask;
  923. ip_addr_t gw;
  924. #ifdef DHCP_USER_LOGS
  925. uint8_t iptxt[20];
  926. #endif
  927. switch(*state)
  928. {
  929. case DHCP_START:
  930. *state = DHCP_WAIT_ADDRESS;
  931. #ifdef DHCP_USER_LOGS
  932. printf(" State: Looking for DHCP server ...\n");
  933. #endif
  934. break;
  935. case DHCP_WAIT_ADDRESS:
  936. if (dhcp_supplied_address(netif))
  937. {
  938. *state = DHCP_ADDRESS_ASSIGNED;
  939. #ifdef DHCP_USER_LOGS
  940. sprintf((char *)iptxt, "%s", ip4addr_ntoa((const ip4_addr_t *)&netif->ip_addr));
  941. printf("IP address assigned by a DHCP server: %s\n", iptxt);
  942. #endif
  943. }
  944. else
  945. {
  946. dhcp = (struct dhcp *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);
  947. /* DHCP timeout */
  948. if (dhcp->tries > MAX_DHCP_TRIES)
  949. {
  950. *state = DHCP_TIMEOUT;
  951. /* Stop DHCP */
  952. LOCK_TCPIP_CORE();
  953. dhcp_stop(netif);
  954. UNLOCK_TCPIP_CORE();
  955. /* Static address used */
  956. ipaddr_aton(STATIC_IP, &ipaddr);
  957. ipaddr_aton(STATIC_MASK, &netmask);
  958. ipaddr_aton(STATIC_GW, &gw);
  959. LOCK_TCPIP_CORE();
  960. netif_set_addr(netif, ip_2_ip4(&ipaddr), ip_2_ip4(&netmask), ip_2_ip4(&gw));
  961. UNLOCK_TCPIP_CORE();
  962. #ifdef DHCP_USER_LOGS
  963. sprintf((char *)iptxt, "%s", ip4addr_ntoa((const ip4_addr_t *)&netif->ip_addr));
  964. printf("DHCP Timeout !! \n");
  965. printf("Static IP address: %s\n", iptxt);
  966. #endif
  967. }
  968. }
  969. break;
  970. case DHCP_ADDRESS_ASSIGNED:
  971. dhcp = (struct dhcp *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);
  972. if(dhcp->state == 3)
  973. {
  974. *state = DHCP_START;
  975. }
  976. break;
  977. default:
  978. break;
  979. }
  980. }
  981. /* USER CODE END 8 */