TIL-LwIP

치삼이·2022년 2월 14일
0
post-thumbnail

LwIP with STM32F4x7

1. LwIP

LwIP(Lightweight IP)는 스웨덴 컴퓨터 과학 연구소의 Adam Dunkels가 처음 만든 오픈소스(Modified BSD license) TCP/IP 프로토콜 스택이다. 이름 그대로 경량 인터넷 프로토콜으로 임베디드 시스템에 자주 사용된다. LwIP는 수십 Kbyte의 RAM과 코드를 위한 40Kbyte이상의 ROM이 있는 곳에서 사용할 수 있다.

LwIP의 latest version은 2.1.3이며 🔗 LwIP 공식 홈페이지 에서 다운로드 받을 수 있다. LwIP의 최신 버전은 2.3.1 이지만 STM32F407에 포팅된 LwIP 버전은 1.4.1 을 사용하고 있다. 포팅이된 예제 및 프로젝트는 🔗 ST 공식 홈페이지 에서 다운받을 수 있다. (STM32F4x7에 포팅된 버전을 기준으로 설명한다.)

1.1 LwIP Architecture Protocols and API's

LwIP Architecture는 TCP/IP 4계층을 따른다.

LwIP는 다음과 같은 프로토콜들을 지원한다.

  • IPv4 and IPv6 (Internet Protocol v4 and v6)
  • ICMP (Internet Control Message Protocol) for network maintenance and debugging
  • IGMP (Internet Group Management Protocol) for multicast traffic management
  • UDP (User Datagram Protocol)
  • TCP (Transmission Control Protocol)
  • DNS (Domain Name Server)
  • SNMP (Simple Network Management Protocol)
  • DHCP (Dynamic Host Configuration Protocol)
  • PPP (Point to Point Protocol)
  • ARP (Address Resolution Protocol)

LwIP를 이용하는 API는 총 3가지가 존재한다.

  • Raw API :

    가장 Low Level의 API로 이벤트와 콜백을 이용한 어플리케이션 제작이 가능하다. 가장 Low Level로써 최적의 코드사이즈 및 성능을 보여주지만, 사용하기에 다소 복잡하다.

  • Netconn API

    RTOS의 서비스를 필요로하는 API로 Raw API 보다 High Level의 API이다. Netconn API는 멀티쓰레드 동작이 가능하다.

  • BSD Socket API

    Netconn API를 이용해 만든 Socket API로 가장 High Level의 API다.

1.2 LwIP STM32F407 Directory Organization

STSW-STM32070의 압축을 풀어 /Utilities/Third_Party/LwIP-1.4.1 를 살펴보면 아래와 같은 트리구조를 볼 수 있다.

  • port/STM32F4x7: LwIP를 STM32F4x7 시리즈에 맞춰 구현한 파일들의 모음이다.
  • arch: 데이터 타입 등 STM32의 아키텍쳐 관련 파일
  • FreeRTOS: FreeRTOS를 이용하는 LwIP의 이더넷 인터페이스 및 시스템 아키텍쳐 소스 및 헤더파일
  • Standalone: Standalone mod의 LwIP의 이더넷 인터페이스 소스 및 헤더파일

1.3 LwIP API overview

위에 언급했듯 LwIP는 총 3가지의 API가 존재한다. API는 낮은 Level 순서로 Raw ➝ Netconn ➝ Socket 이 존재하며 Level이 낮을수록 사이즈 및 성능이 높아지지만 복잡해 진다.

  • RAW API TCP Summary

  • RAW API UDP Summary

  • Netconn API Summary

  • Socekt API Summary

1.4 LwIP buffer management

LwIP는 pbuf 라는 구조체로 버퍼를 관리한다. pbuf 는 구조체 멤버변수중 next 라는 변수가 있는데 이는 다음 pbuf 를 가르키는 포인터 변수다. pbuf 는 링크드리스트 형태로 버퍼를 관리하는것을 확인할 수 있다.

  • next : 다음 pbuf 구조체의 주소
  • payload : 패킷의 데이터 부분 주소
  • len : 패킷 데이터의 길이
  • tot_len: 링크드 리스트로 연결된 데이터의 길이
  • ref : 참조 카운터를 나타내는 지시자 ref 멤버 변수가 0이어야 메모리에서 해제할 수 있다.
  • flags : pbuf의 타입을 나타내는 변수

LwIP는 세가지 형태의 타입이 있는데 각각 메모리를 어떻게 할당받느냐에 따라 정의가 된다.

  • PBUF_POOL

    미리 확보해놓은 정적메모리에 pubf를 할당한다. 할당해야하는 데이터의 크기에 따라 pbuf의 갯수가 달라진다.

  • PBUF_RAM

    요청시 필요한 만큼 메모리를 할당해주는 동적 메모리 (heap)에 pbuf를 할당한다.

  • PBUF_ROM

    메모리에 충분한 공간이 없을때 데이터를 ROM에 할당한다.

패킷 수신시 가장 적절한 pbuf 타입은 가장신속하게 메모리 할당이 가능한 PBUF_POOL 타입이다. PBUF_RAM은 메모리(heap)에 동적할당하므로, 딜레이와 메모리 단편화가 일어날 수 있다.

  • Pbuf API's

2. Interfacing LwIP

2.1 Interfacing LwIP to STM32F4x7 Ethernet

STM32F4x7 시리즈에 LwIP 포팅하기위한 스택은 /port/STM32F4x7 에 정의되어 있다. 디렉토리엔 다음과 같은 두 가지 구현체가 있는다.

  • Implementation without RTOS (standalone)
  • Implementation with an RTOS using FreeRTOS

두 디렉토리 모두 ethernet_if.c 라는 파일이 존재하며, 이 파일 에서 LwIP 스택과 STM32F4x7 Ethernet Interface의 연결을 담당한다. RTOS 디렉토리에는 sys_arch.c 라는 파일도 존재하는데, 이 파일은 RTOS에서 제공하는 서비스를 담당한다.

  • ethernet_if.c functions description

2.2 DMA descriptor handling

이더넷 케이블을 통한 패킷이 메모리로 전달되기 위한 인터페이스는 DMA descriptor라는 자료구조를 이용한DMA 전송이다.

위의 그림에서 보듯 DMA descriptor는 두 가지의 포맷을 가질 수 있는데 하나는 링크드 리스트 형태의 버퍼이며 다른 하나는 버퍼를 두 개 사용하는 형태이다. STM32F4X7 Ethernet Driver에서는 옵션1의 형태를 채용하고있다. 옵션 1의 형태를 자세히 살펴보면 원형 링크드 리스트임을 확인할 수 있다.

ethernet_if.c 파일을 확인하면 외부 전역변수를 사용하는 것을 볼 수 있다. 이 변수들을 이용해 메모리에 전달된 패킷 데이터에 접근이 가능하다. 이 전역 변수는 stm32f4x7_eth.c 에 정의되어 있다.

/* Ethernet Rx & Tx DMA Descriptors */
extern ETH_DMADESCTypeDef  DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB];

/* Ethernet Driver Receive buffers  */
extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE]; 

/* Ethernet Driver Transmit buffers */
extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE]; 

/* Global pointers to track current transmit and receive descriptors */
extern ETH_DMADESCTypeDef  *DMATxDescToSet;
extern ETH_DMADESCTypeDef  *DMARxDescToGet;

배열 길이로 사용되는 ETH_RXBUFNB, ETH_RXBUFNB 등 은 stm32f4x7_eth.h 에서 변경이 가능하다.

0개의 댓글