Skip to content
Go DevBJ
Go back

[STM32] LWIP TCP/IP 스택 구현 가이드: 임베디드 네트워크 통합

Edit page

임베디드 시스템에서 네트워크 기능은 필수적인 요소가 되었다. 특히 IoT 기기나 산업 자동화 분야에서 원격 제어, 데이터 모니터링, 펌웨어 업데이트 등의 기능을 구현하기 위해 TCP/IP 통신 스택의 사용이 요구된다. 본 포스트에서는 STM32 마이크로컨트롤러에 경량 TCP/IP 스택인 LWIP(LightWeight IP)를 구현하여 네트워크 기능을 통합하는 과정을 상세히 다루었다.

1. LWIP 스택 소개 및 STM32 통합의 필요성

LWIP는 임베디드 시스템과 같이 제한된 자원을 가진 환경에서 동작하도록 설계된 TCP/IP 스택이다. 작은 메모리 footprint와 높은 효율성을 특징으로 하며, STM32와 같은 ARM Cortex-M 기반 MCU에서 널리 사용된다. STM32CubeMX 및 STM32CubeIDE를 활용하면 LWIP 스택을 쉽게 프로젝트에 통합할 수 있다.

STM32에 LWIP를 통합하는 것은 다음과 같은 이점을 제공한다.

2. STM32CubeMX를 이용한 프로젝트 설정

LWIP 스택을 STM32 프로젝트에 통합하기 위해 STM32CubeMX를 사용했다. 다음은 주요 설정 단계이다.

2.1. 프로젝트 생성 및 MCU 선택

STM32CubeMX를 실행하고 New Project를 선택한 후, 사용할 STM32 마이크로컨트롤러(예: STM32F407ZG)를 선택한다.

2.2. 클록 구성

System Core > RCC에서 HSE(High Speed External)를 Crystal/Ceramic Resonator로 설정했다. 이후 Clock Configuration 탭에서 HCLK를 최대 주파수(예: 168MHz)로 설정하여 시스템 성능을 최적화했다.

2.3. 이더넷 MAC (Ethernet MAC) 설정

Connectivity > ETH를 선택하여 이더넷 인터페이스를 활성화한다.

2.4. LWIP 스택 설정

Middleware > LWIP를 선택하여 LWIP 스택을 활성화한다.

2.5. FreeRTOS (선택 사항) 설정

Middleware > FreeRTOS를 선택하여 RTOS를 활성화했다. LWIP가 FreeRTOS 태스크로 동작하므로 안정적인 동작을 위해 필요하다.

2.6. GPIO 설정

이더넷 PHY 칩의 리셋 핀이나 전원 제어 핀이 있다면, 해당 GPIO를 GPIO_Output으로 설정하고 초기 상태를 지정한다.

설정 완료 후 GENERATE CODE 버튼을 클릭하여 프로젝트를 생성했다.

3. LWIP 코드 구현 및 테스트

STM32CubeIDE에서 생성된 프로젝트를 열고 LWIP 기능을 활용하는 코드를 구현한다.

3.1. LWIP 초기화 및 네트워크 인터페이스 설정

main.c 파일에서 MX_LWIP_Init() 함수가 호출되어 LWIP 스택이 초기화된다. 이 함수 내부에서 DHCP 클라이언트 시작 또는 정적 IP 설정이 이루어진다.

void MX_LWIP_Init(void)
{
  /* IP addresses initialization */
  ip4_addr_t ipaddr;
  ip4_addr_t netmask;
  ip4_addr_t gw;

  /* Initilialize the LwIP stack without RTOS if you want if you have chosen standalone mode. */
  /* If you want to use RTOS, the initilization for the LwIP stack is done in the default task. */

#if LWIP_DHCP == 0
  /* IP addresses setting */
  IP4_ADDR(&ipaddr, 192, 168, 1, 10); // 정적 IP 주소
  IP4_ADDR(&netmask, 255, 255, 255, 0); // 서브넷 마스크
  IP4_ADDR(&gw, 192, 168, 1, 1);     // 게이트웨이 주소
#endif

  /* Initilise the LwIP stack */
  lwip_init();

  /* Add the network interface (Ethernet) */
  netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &netif_input);

  /* Set as default network interface */
  netif_set_default(&gnetif);

  if (netif_is_link_up(&gnetif))
  {
    /* Set the link up */
    netif_set_up(&gnetif);
  }
  else
  {
    /* Set the link down */
    netif_set_down(&gnetif);
  }

#if LWIP_DHCP
  /* Start DHCP client if activated */
  dhcp_start(&gnetif);
#endif
}

### 3.2. 간단한 TCP Echo 서버 구현 (FreeRTOS 환경)

FreeRTOS를 사용하는 경우, TCP 서버를 위한 태스크를 생성하여 이더넷 이벤트와 애플리케이션 로직을 분리하는 것이 좋다.

// main.c 또는 별도의 tcp_server.c 파일
#include "lwip/opt.h"
#include "lwip/arch.h"
#include "lwip/api.h"
#include "lwip/inet.h"

#define TCP_SERVER_PORT 7000

static void tcp_server_thread(void *arg)
{
  struct netconn *conn, *newconn;
  err_t err, accept_err;

  LWIP_UNUSED_ARG(arg);

  /* Create a new connection identifier. */
  conn = netconn_new(NETCONN_TCP);

  if (conn != NULL)
  {
    /* Bind connection to well known port number. */
    err = netconn_bind(conn, IP_ADDR_ANY, TCP_SERVER_PORT);

    if (err == ERR_OK)
    {
      /* Tell connection to go into listening mode. */
      netconn_listen(conn);

      while (1)
      {
        /* Grab new connection. */
        accept_err = netconn_accept(conn, &newconn);

        /* Process the new connection. */
        if (accept_err == ERR_OK)
        {
          struct netbuf *buf;
          void *data;
          u16_t len;

          while ((err = netconn_recv(newconn, &buf)) == ERR_OK)
          {
            do
            {
              netbuf_data(buf, &data, &len);
              netconn_write(newconn, data, len, NETCONN_COPY); // Echo back
            } while (netbuf_next(buf) >= 0);
            netbuf_delete(buf);
          }

          /* Close connection and discard connection identifier. */
          netconn_close(newconn);
          netconn_delete(newconn);
        }
      }
    }
    else
    {
      netconn_delete(conn);
      // 오류 처리
    }
  }
  // 오류 처리
}

/* FreeRTOS Default Task에서 호출 */
void StartDefaultTask(void *argument)
{
  /* init code for LWIP */
  MX_LWIP_Init();

  /* Create the TCP server thread */
  sys_thread_new("tcp_server_thread", tcp_server_thread, NULL, 512, osPriorityNormal);

  /* Infinite loop */
  for (;;)
  {
    osDelay(1);
  }
}

StartDefaultTask 함수는 FreeRTOS에서 자동으로 생성되는 태스크이다. 이 안에서 MX_LWIP_Init()를 호출하여 LWIP를 초기화하고, tcp_server_thread를 별도의 태스크로 생성하여 TCP 서버를 실행했다.

3.3. 컴파일 및 펌웨어 다운로드

코드를 컴파일하고 STM32 개발 보드에 펌웨어를 다운로드한다.

3.4. 네트워크 테스트

펌웨어 다운로드 후, 개발 보드를 이더넷 케이블로 PC 또는 네트워크 스위치에 연결한다.

4. 결론

본 포스트에서는 STM32 마이크로컨트롤러에 LWIP TCP/IP 스택을 구현하여 임베디드 시스템에 네트워크 기능을 통합하는 과정을 다루었다. STM32CubeMX를 이용한 설정부터 FreeRTOS 기반의 간단한 TCP Echo 서버 구현 및 테스트까지 진행했다. LWIP는 제한된 자원 환경에서 효율적인 네트워크 통신을 가능하게 하며, 이를 통해 임베디드 시스템의 활용 범위를 크게 확장할 수 있었다. 이 기본적인 구현을 바탕으로 HTTP 서버, MQTT 클라이언트 등 다양한 네트워크 애플리케이션을 개발할 수 있을 것이다.


DevBJ | No Bio, Just Log
기술 삽질로그


Edit page
Share this post on:

Previous Post
Google AI Studio와 Python SDK: AI 모델 탐색 및 활용 예제
Next Post
최신 토렌트 사이트 순위 2026-03-28 확인