./../
  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(메모리 보호 유닛) 비캐시 설정, 링커 스크립트 매핑 버그 패치, 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 (수신 캐리어 감지) | | **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 비캐시 RAM 매핑 버그 - **문제점**: `ethernetif.c`에서는 DMA 디스크립터 섹션을 `.RxDescripSection`, `.TxDescripSection`으로 선언했으나, ST CubeMX 생성 링커 스크립트의 오타 및 잘못된 `RAM_D1` 매핑으로 인해 디스크립터가 캐시가 켜진 일반 AXI SRAM(`0x24000000`)에 배치됨. 이로 인해 CPU의 전송 요청(`OWN=1`)을 DMA가 읽지 못해 무한 `BUSY` 및 멈춤 발생. - **해결책**: 링커 스크립트의 `.lwip_sec` 섹션을 `RAM_D2 (0x30040000, SRAM3)`에 고정 배치하고 스펠링 오타 방어 코드 적용. #### ② MPU (Memory Protection Unit) 비캐시 및 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 캐시 내용을 물리 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 684910
xxx [공지]자료실 다운로드 오류 처리 2017-12-01 30807
xxx [공지]비난, 광고 게시물을 신고, 차단, 삭제됩니다. 2005-06-26 26622
256 [C#]  asp.net .net core connectionString Encryption 표준 암호화 방법 2026-09-24(목) 6
255 [CPP]  MS Windows 64bit Time Converter 2026-09-23(수) 9
254 [M D] > STM32H747I-DISCO 이더넷(RMII) 및 LwIP 완벽 구현 및 트러블슈팅 가이드 < 2026-09-17(목) 33
253 [일반]  .net core Web 생성하면 나오는 구조 2026-09-12(토) 55
252 [M D]  STM32 개발 때 다양한 USB CDCs 사용CDC, CP210x, FTDI, CH34x, PL2303) 2026-09-11(금) 58
251 [M D]  STM32H747I-DISCO CP2102 USB Host 트러블슈팅 종합 보고서 2026-09-11(금) 53
250 [일반]  STM32H747I-DISCO에서 STM32CubeMX 템플릿때문에 USB OTG 문제 발생할때 2026-09-10(목) 61
249 [M D]  TouchGFX에서 버튼같은거 삭제 했을때 make: *** No rule to make target.. 오류 2026-08-20(목) 117
248 [M D]  STM TouchGFX설계할때 main에서 View에 접근하는 순서 2026-08-16(일) 93
247 [M D]  STM TouchGFX설계할때 View가 main에 접근하는 순서 2026-08-16(일) 140
246 [M D]  MCU Task관리할때 필요한 세마포어(Semaphore)와 뮤텍스(Mutex) 2026-08-09(일) 131
245 [M D]  STM32F 마이컴 공부할때 RAM에 올려서 시험하기.(속도 빠름) 2026-08-08(토) 128
244 [일반]  STM32F767과 FreeRTOS를 이용해 설계할때 Time base Source는? 2026-08-08(토) 125
243 [일반]  VSCode로 STM32 개발할때 printf에서 실수 출력 안되면 2026-07-16(목) 985
242 [일반]  VisualStudio으로 만든 프로그램 .net 버전 올리기 위해 2026-07-02(목) 1207
241 [C#]  c# winform에서 URL QR생성 2026-06-30(화) 1050
240 [일반]  VC 컴파일할때 솔류션 폴더에 컴파일된 파일이 생성될때 2026-06-29(월) 440
239 [XML]  IIS 8.0 이상 IP 차단 web.config 설정 2026-06-13(토) 159
238 [일반]  C#.net 6이상 빌트할때 TargetFramework 폴더 생기는거 없애기 2026-04-16(목) 465
237 [일반]  windows의 각종 에디터에서 한글 입력시에 완성되야 표기되는 문제 2026-04-10(금) 465
검색 :
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