./../
  I D :    ¾ÏÈ£ :    IDÀúÀå      ȸ¿ø°¡ÀÔ    ³×°Ô(ÁåÀå) ÂÊÁöº¸³»±â    ¸Þ¸ðÀå    °¢Á¾°è»ê±â    Ä÷¯ºü·¿    À̸ðƼÄÜ(ÇÁ·¹ÀÓ, »õâ)    º¸À¯Àåºñ
¸ñ·ÏÀ¸·Î °¡±â..
STM32H747I-DISCO ÀÌ´õ³Ý(RMII) ¹× LwIP ¿Ïº® ±¸Çö ¹× Æ®·¯ºí½´ÆÃ °¡ÀÌµå ±èÁ¾È£ | »èÁ¦Çϱâ

# STM32H747I-DISCO Ethernet (RMII) + LwIP Complete Implementation & Troubleshooting Guide # STM32H747I-DISCO ÀÌ´õ³Ý(RMII) ¹× LwIP ¿Ïº® ±¸Çö ¹× Æ®·¯ºí½´ÆÃ °¡À̵å --- ## 0. Introduction & Purpose / ¼­·Ð ¹× ¸ñÀû ### [KO] ¼­·Ð ¹× ¸ñÀû ÀÌ ¹®¼­´Â **STMicroelectronics STM32H747I-DISCO °³¹ß º¸µå**¿¡¼­ °í¼º´É µà¾ó ÄÚ¾î(Cortex-M7)¿Í LAN8742A ÀÌ´õ³Ý PHY ĨÀ» °áÇÕÇÏ¿©, **LwIP ³×Æ®¿öÅ© ½ºÅðú FreeRTOS ±â¹ÝÀÇ ¾ç¹æÇâ ÀÌ´õ³Ý Åë½Å(TX/RX, ICMP Ping, °í¼Ó UDP ¼Û¼ö½Å)**À» ¿Ïº®ÇÏ°Ô ±¸ÇöÇϱâ À§ÇÑ ½ÇÀü ±â¼ú °¡À̵åÀÔ´Ï´Ù. STM32H7 ½Ã¸®Áî´Â °í¼º´É Cortex-M7 ÄÚ¾îÀÇ Ãʰí¼Ó L1 µ¥ÀÌÅÍ Ä³½Ã(D-Cache)¿Í µ¶¸³µÈ µµ¸ÞÀκ° ¸Þ¸ð¸® ±¸Á¶(D1 AXI-SRAM, D2 SRAM1~3)¸¦ °®Ãß°í ÀÖ¾î, ÀÌÀü ¼¼´ë MCU(F4, F7)¿¡ ºñÇØ ÀÌ´õ³Ý DMA ±¸¼º ³­À̵µ°¡ ¸Å¿ì ³ô½À´Ï´Ù. ƯÈ÷ ST °ø½Ä ÅøÃ¼ÀÎ(STM32CubeMX)ÀÇ ÀÚµ¿ »ý¼º Äڵ忡 Á¸ÀçÇÏ´Â ¸µÄ¿ ½ºÅ©¸³Æ® ¿ÀŸ, D-Cache µ¥ÀÌÅÍ ºÒÀÏÄ¡(Coherency) ¹®Á¦, ±×¸®°í º¸µå ³» ¿Âº¸µå ȸ·Î(MEMS ¸¶ÀÌÅ©)¿ÍÀÇ ÇÉ Ãæµ¹ µîÀ¸·Î ÀÎÇØ ¸¹Àº °³¹ßÀÚµéÀÌ **"Ping ÀÀ´ä ½ÇÆÐ", "¹«ÇÑ TX BUSY Àá±è", "MISCOMPARE µ¥ÀÌÅÍ ºÒÀÏÄ¡ ¿À·ù"**¸¦ °Þ°Ô µË´Ï´Ù. **º» ¹®¼­ÀÇ ¸ñÀûÀº ´ÙÀ½°ú °°½À´Ï´Ù:** 1. **Çϵå¿þ¾î °³Á¶ Æ÷ÀÎÆ® ¸íȮȭ**: DISCO º¸µåÀÇ ±âº» ¿Âº¸µå Ãæµ¹ ȸ·Î¸¦ ¾ÈÀüÇÏ°Ô ºÐ¸®Çϰí ÀÌ´õ³Ý RMII ½ÅÈ£¼±À» 100% Ȱ¼ºÈ­ÇÏ´Â ¼Ö´õ ºê¸´Áö ³³¶« °³Á¶ Æ÷ÀÎÆ®¸¦ »ó¼¼È÷ Á¦½ÃÇÕ´Ï´Ù. 2. **¼ÒÇÁÆ®¿þ¾î ³­Á¦ÀÇ ±Ùº» ¿øÀÎ ±Ô¸í ¹× ÇØ°á**: MPU(¸Þ¸ð¸® º¸È£ À¯´Ö) ºñij½Ã ¼³Á¤, ¸µÄ¿ ½ºÅ©¸³Æ® ¸ÅÇÎ ¹ö±× ÆÐÄ¡, Cortex-M7 D-Cache Clean/InvalidateÀÇ ¿Ïº®ÇÑ Å¸Àְ̹ú ¼ø¼­¸¦ ¸íÄèÈ÷ ¼³¸íÇÕ´Ï´Ù. 3. **100% µ¿ÀÛ °ËÁõµÈ ¼Ò½º ÄÚµå Á¦°ø**: 1ms À̳»ÀÇ ¹«¼Õ½Ç Ping(ICMP) ÀÀ´ä°ú 100ms ÁÖ±âÀÇ °í¼Ó UDP Àü¼ÛÀÌ ¿Ïº®È÷ °ËÁõµÈ ½ÇÀü Äڵ带 °øÀ¯ÇÏ¿©, °³¹ßÀÚ°¡ ºÒÇÊ¿äÇÑ ½ÃÇàÂø¿À ¾øÀÌ Áï½Ã »ó¿ë ÀÓº£µðµå ÇÁ·ÎÁ§Æ®, ¼­º¸ ¸ðÅÍ Á¦¾î, »ê¾÷¿ë IoT ½Ã½ºÅÛ¿¡ Àû¿ëÇÒ ¼ö ÀÖµµ·Ï µ½½À´Ï´Ù. --- ### [EN] Introduction & Purpose This document serves as a comprehensive, step-by-step engineering and troubleshooting guide for establishing robust, bi-directional Ethernet communication (TX/RX, ICMP Echo Reply, high-speed UDP) on the **STMicroelectronics STM32H747I-DISCO** discovery kit using the **LAN8742A RMII PHY**, **FreeRTOS (CMSIS-RTOS V2)**, and the **LwIP 2.1.2** TCP/IP stack running on the high-performance ARM Cortex-M7 core. The STM32H7 family incorporates a high-performance L1 Data Cache (D-Cache), an AXI bus matrix, and segmented memory domains (D1 AXI-SRAM, D2 SRAM1–3). While this architecture delivers remarkable throughput, it introduces intricate challenges when synchronizing Ethernet DMA hardware with the CPU. Developers frequently encounter pervasive issues such as **perpetual `TX BUSY` lockups, packet loss, `MISCOMPARE at offset 28` errors during Ping requests**, and silent network freezes caused by CubeMX linker script bugs, MPU misconfigurations, and cache coherency hazards. **The primary purposes of this guide are:** 1. **Provide a Definitive Hardware Blueprint**: Detail the exact solder bridge rework required on the STM32H747I-DISCO to isolate onboard MEMS microphone conflicts and properly route all RMII interface signals. 2. **Resolve Fundamental Software & Cache Roadblocks**: Explain the correct setup for MPU non-cacheable descriptor regions, fix linker script section naming bugs, and demonstrate the precise placement of D-Cache `Clean` and `Invalidate` operations. 3. **Deliver a 100% Production-Verified Reference Codebase**: Supply fully verified, end-to-end source code achieving deterministic sub-millisecond (<1ms) Ping response times and continuous UDP transmission, empowering engineers to immediately integrate reliable networking into motor control, industrial IoT, and real-time embedded systems. --- ## 1. System Specifications / Çϵå¿þ¾î ¹× ½Ã½ºÅÛ »ç¾ç ### [KO] Çϵå¿þ¾î ¹× ¼ÒÇÁÆ®¿þ¾î »ç¾ç - **´ë»ó º¸µå**: STMicroelectronics **STM32H747I-DISCO** (Discovery Kit) - **¸ÞÀÎ MCU**: **STM32H747XIH6** Dual-core (ARM Cortex-M7 @ 400/480MHz + Cortex-M4 @ 200/240MHz) - **ÀÌ´õ³Ý PHY Ĩ**: Microchip / SMSC **LAN8742A** (10/100 Mbps RMII Physical Layer Transceiver) - **ÀÎÅÍÆäÀ̽º ¸ðµå**: RMII (Reduced Media Independent Interface, 50 MHz ±âÁØ Å¬·°) - **Ŭ·° ±¸Á¶**: - º¸µå ³»Àå 25 MHz Å©¸®½ºÅ»(X3) ¶Ç´Â MCU `PA8 (MCO1: 25MHz HSE)` $\rightarrow$ LAN8742A ³»ºÎ PLL·Î 50 MHz ü¹è $\rightarrow$ LAN8742A Pin 5(`CLKOUT`) $\rightarrow$ **SB17** $\rightarrow$ STM32 `PA1 (ETH_REF_CLK)` - **¿î¿µÃ¼Á¦ ¹× ½ºÅÃ**: FreeRTOS (CMSIS-RTOS V2) + LwIP 2.1.2 (ST HAL Driver) - **³×Æ®¿öÅ© ¼³Á¤**: °íÁ¤ IP `192.168.31.60` (¼­ºê³Ý `255.255.255.0`, °ÔÀÌÆ®¿þÀÌ `192.168.31.1`), PC IP: `192.168.31.58` ### [EN] Hardware & Software Specifications - **Target Board**: STMicroelectronics **STM32H747I-DISCO** (Discovery Kit) - **Main MCU**: **STM32H747XIH6** Dual-core (ARM Cortex-M7 @ 400/480MHz + Cortex-M4 @ 200/240MHz) - **Ethernet PHY Chip**: Microchip / SMSC **LAN8742A** (10/100 Mbps RMII Transceiver) - **Interface Mode**: RMII (50 MHz Reference Clock) - **Clock Architecture**: - Onboard 25 MHz Crystal (X3) or MCU `PA8 (MCO1: 25MHz HSE)` $\rightarrow$ LAN8742A internal PLL generates 50 MHz $\rightarrow$ LAN8742A Pin 5(`CLKOUT`) $\rightarrow$ **SB17** $\rightarrow$ STM32 `PA1 (ETH_REF_CLK)` - **OS & Network Stack**: FreeRTOS (CMSIS-RTOS V2) + LwIP 2.1.2 (ST HAL Driver) - **Network Configuration**: Static IP `192.168.31.60` (Subnet `255.255.255.0`, Gateway `192.168.31.1`), Target PC IP: `192.168.31.58` --- ## 2. Hardware Modifications: Solder Bridges / Çϵå¿þ¾î ¼Ö´õ ºê¸´Áö °³Á¶ STM32H747I-DISCO º¸µå´Â ±âº» °øÀå ÃâÇÏ ½Ã ÀϺΠÀÌ´õ³Ý ÇÉÀÌ ¿Âº¸µå MEMS ¸¶ÀÌÅ© ¹× ¿Àµð¿À ÄÚµ¦°ú ÇÉÀ» °øÀ¯ÇÕ´Ï´Ù. ÀÌ´õ³Ý RMII ±â´ÉÀ» ¿ÂÀüÈ÷ »ç¿ëÇÏ·Á¸é ¾Æ·¡¿Í °°ÀÌ ¼Ö´õ ºê¸´Áö(³³¶« Á¡ÆÛ)¸¦ °³Á¶ÇØ¾ß ÇÕ´Ï´Ù. On the STM32H747I-DISCO, certain Ethernet RMII pins are shared with onboard MEMS microphones and audio circuitry. To use Ethernet RMII, the following solder bridge modifications are required. | Signal / ½ÅÈ£ | STM32 Pin | Solder Bridge to OPEN (´Ü¼±) | Solder Bridge to CLOSE (¼îÆ®) | Description / ¼³¸í | | :--- | :--- | :--- | :--- | :--- | | **ETH_REF_CLK** | `PA1` | - | **SB17** | 50 MHz RMII Reference Clock from PHY / PHY Ŭ·° °ø±Þ | | **ETH_MDIO** | `PA2` | - | **SB8** | MDIO Management Data / PHY ·¹Áö½ºÅÍ µ¥ÀÌÅÍ Åë½Å | | **ETH_CRS_DV** | `PA7` | **SB45** (Disconnect Mic) | **SB44** | Carrier Sense / Data Valid (¼ö½Å ij¸®¾î °¨Áö) | | **ETH_MDC** | `PC1` | **R87** (Disconnect Mic) | **SB21** / Direct | Management Data Clock / PHY ·¹Áö½ºÅÍ Å¬·° | | **ETH_RXD0** | `PC4` | **SB21** (Disconnect Mic) | **SB22** | Receive Data Bit 0 / ¼ö½Å µ¥ÀÌÅÍ ºñÆ® 0 | | **ETH_RXD1** | `PC5` | - | **Direct** | Receive Data Bit 1 / ¼ö½Å µ¥ÀÌÅÍ ºñÆ® 1 | | **ETH_TX_EN** | `PG11` | - | **Direct** | Transmit Enable / ¼Û½Å Ȱ¼ºÈ­ | | **ETH_TXD1** | `PG12` | - | **Direct** | Transmit Data Bit 1 / ¼Û½Å µ¥ÀÌÅÍ ºñÆ® 1 | | **ETH_TXD0** | `PG13` | - | **Direct** | Transmit Data Bit 0 / ¼Û½Å µ¥ÀÌÅÍ ºñÆ® 0 | --- ## 3. Root Causes of Failure & Solutions / ÇÙ½É ¹®Á¦ ¿øÀÎ ¹× ÇØ°áÃ¥ ### [KO] 3´ë ÇÙ½É ³­Á¦ ¹× ¿Ïº® ÇØ°áÃ¥ #### ¨ç ¸µÄ¿ ½ºÅ©¸³Æ® ¿ÀŸ ¹× D2 ºñij½Ã RAM ¸ÅÇÎ ¹ö±× - **¹®Á¦Á¡**: `ethernetif.c`¿¡¼­´Â DMA µð½ºÅ©¸³ÅÍ ¼½¼ÇÀ» `.RxDescripSection`, `.TxDescripSection`À¸·Î ¼±¾ðÇßÀ¸³ª, ST CubeMX »ý¼º ¸µÄ¿ ½ºÅ©¸³Æ®ÀÇ ¿ÀŸ ¹× À߸øµÈ `RAM_D1` ¸ÅÇÎÀ¸·Î ÀÎÇØ µð½ºÅ©¸³ÅͰ¡ ij½Ã°¡ ÄÑÁø ÀÏ¹Ý AXI SRAM(`0x24000000`)¿¡ ¹èÄ¡µÊ. ÀÌ·Î ÀÎÇØ CPUÀÇ Àü¼Û ¿äû(`OWN=1`)À» DMA°¡ ÀÐÁö ¸øÇØ ¹«ÇÑ `BUSY` ¹× ¸ØÃ㠹߻ý. - **ÇØ°áÃ¥**: ¸µÄ¿ ½ºÅ©¸³Æ®ÀÇ `.lwip_sec` ¼½¼ÇÀ» `RAM_D2 (0x30040000, SRAM3)`¿¡ °íÁ¤ ¹èÄ¡ÇÏ°í ½ºÆç¸µ ¿ÀŸ ¹æ¾î ÄÚµå Àû¿ë. #### ¨è MPU (Memory Protection Unit) ºñij½Ã ¹× DMA °øÀ¯ ¼³Á¤ - **¹®Á¦Á¡**: Cortex-M7ÀÇ °í¼º´É D-Cache·Î ÀÎÇØ DMA¿Í CPU °£ µð½ºÅ©¸³ÅÍ Ç÷¡±×°¡ ºÒÀÏÄ¡µÊ. - **ÇØ°áÃ¥**: `MPU_Config()`¿¡¼­ `0x30040000` (SRAM3, 32KB) ¿µ¿ªÀ» `MPU_ACCESS_NOT_CACHEABLE`, `MPU_ACCESS_NOT_BUFFERABLE`, `MPU_ACCESS_SHAREABLE`, `MPU_TEX_LEVEL0` (Strongly-Ordered/Device ¼Ó¼º)À¸·Î ¼³Á¤. #### ¨é Cortex-M7 D-Cache Coherency (¼ö½Å Invalidate / ¼Û½Å Clean) - **¹®Á¦Á¡**: - ¼Û½Å ½Ã: CPU°¡ ÀÛ¼ºÇÑ Ping ÀÀ´ä ¹× UDP µ¥ÀÌÅͰ¡ D-Cache¿¡ ¸Ó¹°·¯ RAM¿¡ ¹Ý¿µµÇÁö ¾Ê¾Æ PC¿¡¼­ `MISCOMPARE at offset 28` ¿¡·¯ ¹ß»ý. - ¼ö½Å ½Ã: Invalidate ¸í·É¾î°¡ struct pbuf ¸ÞŸµ¥ÀÌÅÍ ÀÛ¼º µÚ¿¡ À§Ä¡ÇÏ¿© ÆÐŶ ±æÀÌ Á¤º¸°¡ ¼Ò½ÇµÊ. - **ÇØ°áÃ¥**: - `low_level_output`: ÆÐŶ ¼Û½Å Àü `SCB_CleanDCache_by_Addr`¸¦ È£ÃâÇÏ¿© CPU ij½Ã ³»¿ëÀ» ¹°¸® RAMÀ¸·Î Áï½Ã Flush. - `HAL_ETH_RxLinkCallback`: ¸ÞŸµ¥ÀÌÅ͸¦ ¾²±â Àü ¸Ç ù ÁÙ¿¡¼­ `SCB_InvalidateDCache_by_Addr`¸¦ È£ÃâÇÏ¿© ¹°¸® RAMÀÇ ¼ö½Å ÆÐŶÀ» ÃÖ½ÅÈ­. --- ### [EN] 3 Root Causes & Solutions #### ¨ç Linker Script Section Mismatch & D2 Non-Cacheable RAM Mapping - **Issue**: Descriptors declared in `ethernetif.c` were incorrectly placed into Cacheable `RAM_D1` due to CubeMX section naming mismatches. The Ethernet DMA was unable to see CPU descriptor updates (`OWN=1`), causing perpetual `BUSY` lockups. - **Solution**: Explicitly map `.lwip_sec` containing `.RxDescripSection`, `.TxDescripSection`, and `.Rx_PoolSection` into `RAM_D2 (0x30040000, SRAM3)`. #### ¨è MPU (Memory Protection Unit) Non-Cacheable & Shareable Configuration - **Issue**: Cache coherency mismatch between Ethernet DMA and Cortex-M7 CPU on descriptor ring buffers. - **Solution**: Configure `0x30040000` (SRAM3, 32KB) as Non-Cacheable, Non-Bufferable, and Shareable with `MPU_TEX_LEVEL0`. #### ¨é Cortex-M7 D-Cache Management (TX Clean / RX Invalidate) - **Issue**: - TX: CPU payload writes remained in D-Cache without being flushed to RAM, causing `MISCOMPARE at offset 28` on Ping replies. - RX: Invalidate was called after writing pbuf metadata, wiping out the received packet length. - **Solution**: - `low_level_output`: Call `SCB_CleanDCache_by_Addr` before triggering DMA transmission. - `HAL_ETH_RxLinkCallback`: Call `SCB_InvalidateDCache_by_Addr` on the raw payload buffer *before* writing pbuf metadata. --- ## 4. Complete Code Implementation / Àüü ÇÙ½É ÄÚµå ### 1) Linker Script (`stm32h747xx_flash_CM7.ld`) ```ld /* Specify memory areas */ MEMORY { RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 512K FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K RAM_D2 (xrw) : ORIGIN = 0x30040000, LENGTH = 32K /* SRAM3: Non-Cacheable Ethernet Area */ RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K SDRAM (xrw) : ORIGIN = 0xD0000000, LENGTH = 32M } SECTIONS { /* ... standard flash, text, data, bss sections ... */ /* Force Ethernet Descriptors and Buffers into SRAM3 (0x30040000) */ .lwip_sec (NOLOAD) : { . = ABSOLUTE(0x30040000); KEEP(*(.RxDescripSection)) KEEP(*(.RxDecripSection)) . = ABSOLUTE(0x300400A0); KEEP(*(.TxDescripSection)) KEEP(*(.TxDecripSection)) . = ABSOLUTE(0x30040140); KEEP(*(.Rx_PoolSection)) KEEP(*(.RxArraySection)) } >RAM_D2 } ``` --- ### 2) MPU Configuration (`main.c`) ```c void MPU_Config(void) { MPU_Region_InitTypeDef MPU_InitStruct = {0}; /* Disables the MPU */ HAL_MPU_Disable(); /** Configure Ethernet DMA Descriptors Region (SRAM3: 0x30040000, 32KB) */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER0; MPU_InitStruct.BaseAddress = 0x30040000; MPU_InitStruct.Size = MPU_REGION_SIZE_32KB; MPU_InitStruct.SubRegionDisable = 0x0; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; /* DMA Shareable */ MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; /* Non-Cacheable */ MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; /* Non-Bufferable */ HAL_MPU_ConfigRegion(&MPU_InitStruct); /* Enables the MPU */ HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); } ``` --- ### 3) Hardware MSP Initialization (`stm32h7xx_hal_msp.c`) ```c void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(heth->Instance == ETH) { /* 1. CRITICAL: Select RMII mode in SYSCFG BEFORE enabling Ethernet peripheral clocks */ __HAL_RCC_SYSCFG_CLK_ENABLE(); HAL_SYSCFG_ETHInterfaceSelect(SYSCFG_ETH_RMII); /* 2. Enable GPIO Clocks */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); /** ETH GPIO Configuration PA1 ------> ETH_REF_CLK PA2 ------> ETH_MDIO PA7 ------> ETH_CRS_DV PC1 ------> ETH_MDC PC4 ------> ETH_RXD0 PC5 ------> ETH_RXD1 PG11 ------> ETH_TX_EN PG12 ------> ETH_TXD1 PG13 ------> ETH_TXD0 */ GPIO_InitStruct.Pin = GPIO_PIN_1 | 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); /* MDIO requires Pull-Up */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 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_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(GPIOG, &GPIO_InitStruct); /* 3. Enable Ethernet Peripheral Clocks */ __HAL_RCC_ETH1MAC_CLK_ENABLE(); __HAL_RCC_ETH1TX_CLK_ENABLE(); __HAL_RCC_ETH1RX_CLK_ENABLE(); /* 4. Configure ETH Global Interrupt */ HAL_NVIC_SetPriority(ETH_IRQn, 5, 0); HAL_NVIC_EnableIRQ(ETH_IRQn); } } ``` --- ### 4) Low-Level Ethernet Driver (`ethernetif.c`) ```c extern volatile uint32_t eth_rx_packet_count; /** * @brief TX Output function: Transmits packet with D-Cache Clean */ 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}; ETH_TxPacketConfig tx_config; memset(Txbuffer, 0, ETH_TX_DESC_CNT * sizeof(ETH_BufferTypeDef)); memset(&tx_config, 0, sizeof(ETH_TxPacketConfig)); tx_config.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD; tx_config.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; tx_config.CRCPadCtrl = ETH_CRC_PAD_INSERT; 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; /* CRITICAL: Flush outgoing packet data from D-Cache to physical RAM */ SCB_CleanDCache_by_Addr((uint32_t *)q->payload, q->len); if(i > 0) { Txbuffer[i-1].next = &Txbuffer[i]; } if(q->next == NULL) { Txbuffer[i].next = NULL; } i++; } tx_config.Length = p->tot_len; tx_config.TxBuffer = Txbuffer; tx_config.pData = p; pbuf_ref(p); do { if(HAL_ETH_Transmit_IT(&heth, &tx_config) == HAL_OK) { errval = ERR_OK; } else { if(HAL_ETH_GetError(&heth) & HAL_ETH_ERROR_BUSY) { /* Wait for descriptors to become available */ osSemaphoreAcquire(TxPktSemaphore, ETHIF_TX_TIMEOUT); HAL_ETH_ReleaseTxPacket(&heth); errval = ERR_BUF; } else { errval = ERR_IF; } } } while(errval == ERR_BUF); return errval; } /** * @brief RX Link Callback: Invalidate D-Cache FIRST before writing metadata */ void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length) { /* 1. Invalidate cache on packet buffer FIRST before CPU writes pbuf metadata */ SCB_InvalidateDCache_by_Addr((uint32_t *)buff, Length); struct pbuf **ppStart = (struct pbuf **)pStart; struct pbuf **ppEnd = (struct pbuf **)pEnd; struct pbuf *p = NULL; /* Get struct pbuf from buff address */ p = (struct pbuf *)(buff - offsetof(RxBuff_t, buff)); p->next = NULL; p->tot_len = 0; p->len = Length; /* Chain buffer */ if (!*ppStart) { *ppStart = p; } else { (*ppEnd)->next = p; } *ppEnd = p; /* Update total length */ for (p = *ppStart; p != NULL; p = p->next) { p->tot_len += Length; } } /** * @brief RX Task thread: Receives packets and routes to LwIP Stack */ 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) { eth_rx_packet_count++; printf("[RX] Packet Received! len=%d (Total: %lu)\r\n", (int)p->tot_len, (unsigned long)eth_rx_packet_count); if (netif->input( p, netif) != ERR_OK ) { pbuf_free(p); } } } while(p != NULL); } } } ``` --- ### 5) Main Application Thread (`main.c`) ```c volatile uint32_t eth_rx_packet_count = 0; void myTaskFunc01(void *argument) { uint32_t cnt = 0; char txBuffer[64]; uint32_t last_tick = 0; uint32_t last_tx_tick = 0; extern USBH_HandleTypeDef hUsbHostHS; extern struct netif gnetif; static uint8_t ip_assigned = 0; printf("\r\n========================================\r\n"); printf("[ETH] Waiting for PHY Stabilization (500ms)...\r\n"); osDelay(500); printf("[ETH] Starting MX_LWIP_Init()...\r\n"); MX_LWIP_Init(); printf("[ETH] MX_LWIP_Init Completed!\r\n"); /* LwIP UDP PCB Creation (TX Dedicated) */ LOCK_TCPIP_CORE(); struct udp_pcb *tx_pcb = udp_new(); ip_addr_t dest_ip; IP4_ADDR(&dest_ip, 192, 168, 31, 58); /* Target PC IP */ UNLOCK_TCPIP_CORE(); printf("[ETH] UDP TX PCB Created! (Target: 192.168.31.58:5000)\r\n"); for (;;) { cnt = HAL_GetTick(); /* --- TX: Send UDP Packet every 100ms --- */ if (cnt - last_tx_tick >= 100) { last_tx_tick = cnt; LOCK_TCPIP_CORE(); struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 64, PBUF_RAM); if (p != NULL) { int plen = snprintf((char*)p->payload, 64, "TICK=%lu\r\n", cnt); p->len = plen; p->tot_len = plen; udp_sendto(tx_pcb, p, &dest_ip, 5000); pbuf_free(p); } UNLOCK_TCPIP_CORE(); } /* --- 1000ms Periodic Status Display (UART COM4) --- */ if (cnt - last_tick >= 1000) { last_tick = cnt; if (eth_rx_packet_count == 0) { printf("[RX] Waiting for Ping (0 pkts)... | [TX] UDP Sending... Tick=%lu\r\n", cnt); } else { printf("[RX] Received! Total: %lu pkts | [TX] UDP Sending... Tick=%lu\r\n", (unsigned long)eth_rx_packet_count, cnt); } } if (netif_is_link_up(&gnetif)) { if (ip_assigned == 0) { printf("[ETH] Link UP! Static IP: 192.168.31.60\r\n"); ip_assigned = 1; } } osDelay(1); } } ``` --- ## 5. Verification & Results / ÃÖÁ¾ °ËÁõ °á°ú ### 1) Ping Response Verification (ICMP) / Ping ÀÀ´ä °ËÁõ ```cmd C:\> ping 192.168.31.60 -t 192.168.31.60ÀÇ ÀÀ´ä: ¹ÙÀÌÆ®=32 ½Ã°£=1ms TTL=255 192.168.31.60ÀÇ ÀÀ´ä: ¹ÙÀÌÆ®=32 ½Ã°£=1ms TTL=255 192.168.31.60ÀÇ ÀÀ´ä: ¹ÙÀÌÆ®=32 ½Ã°£=1ms TTL=255 192.168.31.60ÀÇ ÀÀ´ä: ¹ÙÀÌÆ®=32 ½Ã°£=1ms TTL=255 ``` - **°á°ú / Result**: 0% Packet Loss, Steady 1ms latency, No payload corruption (MISCOMPARE resolved). ### 2) Serial Terminal Output (ST-Link VCP COM4 @ 115200 bps) ```text ======================================== [ETH] Waiting for PHY Stabilization (500ms)... [ETH] Starting MX_LWIP_Init()... [ETH] ethernet_link_thread started! [ETH] LAN8742 PHY detected at Address 0 (Reg1=0x782D) [ETH] Cable Connected (Link Up)! Static IP: 192.168.31.60 [ETH] MX_LWIP_Init Completed! [ETH] UDP TX PCB Created! (Target: 192.168.31.58:5000) [ETH] Link UP! Static IP: 192.168.31.60 [RX] Packet Received! len=60 (Total: 1) [RX] Packet Received! len=74 (Total: 2) [RX] Received! Total: 2 pkts | [TX] UDP Sending... Tick=3891 [RX] Received! Total: 3 pkts | [TX] UDP Sending... Tick=4895 ```

÷¾ð ´Þ±â
À̸§ : ¾ÏÈ£ :
¹øÈ£    Á¦¸ñ...(÷¾ð) ÀÛ¼ºÀÏ Á¢¼Ó
xxx [°øÁö]ÀÚÀ¯°Ö·¯¸® µî·Ï ¿À·ù ¼öÁ¤ ¿Ï·á 2017-12-22 684725
xxx [°øÁö]ÀÚ·á½Ç ´Ù¿î·Îµå ¿À·ù ó¸® 2017-12-01 30622
xxx [°øÁö]ºñ³­, ±¤°í °Ô½Ã¹°À» ½Å°í, Â÷´Ü, »èÁ¦µË´Ï´Ù. 2005-06-26 26459
254 [M D] > STM32H747I-DISCO ÀÌ´õ³Ý(RMII) ¹× LwIP ¿Ïº® ±¸Çö ¹× Æ®·¯ºí½´ÆÃ °¡À̵ånew < 2026-09-17(¸ñ) 2
253 [ÀϹÝ]  .net core Web »ý¼ºÇÏ¸é ³ª¿À´Â ±¸Á¶ 2026-09-12(Åä) 27
252 [M D]  STM32 °³¹ß ¶§ ´Ù¾çÇÑ USB CDCs »ç¿ëCDC, CP210x, FTDI, CH34x, PL2303) 2026-09-11(±Ý) 32
251 [M D]  STM32H747I-DISCO CP2102 USB Host Æ®·¯ºí½´ÆÃ Á¾ÇÕ º¸°í¼­ 2026-09-11(±Ý) 30
250 [ÀϹÝ]  STM32H747I-DISCO¿¡¼­ STM32CubeMX ÅÛÇø´¶§¹®¿¡ USB OTG ¹®Á¦ ¹ß»ýÇÒ¶§ 2026-09-10(¸ñ) 34
249 [M D]  TouchGFX¿¡¼­ ¹öư°°Àº°Å »èÁ¦ ÇßÀ»¶§ make: *** No rule to make target.. ¿À·ù 2026-08-20(¸ñ) 107
248 [M D]  STM TouchGFX¼³°èÇÒ¶§ main¿¡¼­ View¿¡ Á¢±ÙÇÏ´Â ¼ø¼­ 2026-08-16(ÀÏ) 81
247 [M D]  STM TouchGFX¼³°èÇÒ¶§ View°¡ main¿¡ Á¢±ÙÇÏ´Â ¼ø¼­ 2026-08-16(ÀÏ) 130
246 [M D]  MCU Task°ü¸®ÇÒ¶§ ÇÊ¿äÇÑ ¼¼¸¶Æ÷¾î(Semaphore)¿Í ¹ÂÅØ½º(Mutex) 2026-08-09(ÀÏ) 120
245 [M D]  STM32F ¸¶ÀÌÄÄ °øºÎÇÒ¶§ RAM¿¡ ¿Ã·Á¼­ ½ÃÇèÇϱâ.(¼Óµµ ºü¸§) 2026-08-08(Åä) 118
244 [ÀϹÝ]  STM32F767°ú FreeRTOS¸¦ ÀÌ¿ëÇØ ¼³°èÇÒ¶§ Time base Source´Â? 2026-08-08(Åä) 115
243 [ÀϹÝ]  VSCode·Î STM32 °³¹ßÇÒ¶§ printf¿¡¼­ ½Ç¼ö Ãâ·Â ¾ÈµÇ¸é 2026-07-16(¸ñ) 974
242 [ÀϹÝ]  VisualStudioÀ¸·Î ¸¸µç ÇÁ·Î±×·¥ .net ¹öÀü ¿Ã¸®±â À§ÇØ 2026-07-02(¸ñ) 1190
241 [C#]  c# winform¿¡¼­ URL QR»ý¼º 2026-06-30(È­) 1033
240 [ÀϹÝ]  VC ÄÄÆÄÀÏÇÒ¶§ ¼Ö·ù¼Ç Æú´õ¿¡ ÄÄÆÄÀÏµÈ ÆÄÀÏÀÌ »ý¼ºµÉ¶§ 2026-06-29(¿ù) 423
239 [XML]  IIS 8.0 ÀÌ»ó IP Â÷´Ü web.config ¼³Á¤ 2026-06-13(Åä) 147
238 [ÀϹÝ]  C#.net 6ÀÌ»ó ºôÆ®ÇÒ¶§ TargetFramework Æú´õ »ý±â´Â°Å ¾ø¾Ö±â 2026-04-16(¸ñ) 451
237 [ÀϹÝ]  windowsÀÇ °¢Á¾ ¿¡µðÅÍ¿¡¼­ ÇÑ±Û ÀԷ½ÿ¡ ¿Ï¼ºµÇ¾ß Ç¥±âµÇ´Â ¹®Á¦ 2026-04-10(±Ý) 443
236 [ÀϹÝ]  MPLab X 6.2¿¡¼­ ICD3 ¿¬°á ½ÇÆÐ°¡ ³ª¿Ã¶§ 2026-04-07(È­) 461
235 [ÀϹÝ]  Verolog HDL Operation (¿¬»êÀÚ) 2026-03-27(±Ý) 417
°Ë»ö :
Page : ÀÌÀü 1  2  3  4  5  6  7  8  9  10  11  12  13  ´ÙÀ½




Copyright 2003-2026 ¨Ï ±èÁ¾È£. All rights reserved. kimjongho.co.kr kimjongho.kr kimjongho.net kimjongho.com