W5500으로 이더넷 구현하기 (W5500 드라이버 포팅)

W5500으로 이더넷 구현하기

목차

  1. 개발 환경 구축

    • LPCXpresso 설치
    • Flash Magic 설치
    • 신규 프로젝트 생성 방법
  2. W5500 드라이버 포팅

    • W5500-EVB W5500 Interface (SPI)
    • W5500 Driver Import
    • 초기화 함수 구현
      • W5500 초기화 Flow
      • MCU Interface 초기화 함수
      • Call Back 함수 구현
      • W5500 Chip 초기화 함수
      • Network 설정 함수
    • Main 함수 구현
    • Firmware 적용 및 테스트
  3. Echo-Server 구현

    • Echo-Server 구현

W5500 드라이버 포팅

W5500-EVB W5500 Interface (SPI)

W5500-EVB는 NXP LPC11E36 MCU를 사용하며, W5500과 SPI를 통하여 인터페이스 되어 있다. LPC11E36 MCU는 2개 채널의 SPI를 지원하는데 W5500과는 SPI0를 통해서 인터페이스 되어 있다. W5500-EVB에 대한 자세한 내용은 WIZnet wiki 사이트에서 참조하기 바란다.
http://wizwiki.net/wiki/doku.php?id=products:w5500:w5500_evb

아래의 그림은 W5500-EVB Schematic에서 W5500 인터페이스를 보여준다.

  • CS : PIO0_2 / SSEL0
  • SCLK : PIO0_6 / SCLK0
  • MISO : PIO0_8 / MISO0
  • MOSI : PIO0_9 / MOSI0
  • W5500_RST : PIO0_3

141029_w5500_interface1 141029_w5500_interface2

W5500 Driver Import

이전 강의록 “개발 환경 구축” 편을 참조하여 새로운 프로젝트를 생성한다.
W5500으로 이더넷 구현하기 (개발 환경 구축)
※ 프로젝트명을 W5500-EVB로 생성함

아래의 사이트에서 W5500 Driver 소스 코드를 다운로드 받는다.
http://wizwiki.net/wiki/doku.php?id=products:w5500:driver

141029_wizwiki_hompage

소스 코드는 zip으로 압축된 형태로 배포된다. 압축을 풀면 Ethernet이라는 디렉토리가 생기며, 이 디렉토리 내에 W5500 Driver 소스 코드들이 존재한다. Ethernet 디렉토리를 새로 생성한 프로젝트의 src 디렉토리로 복사한다.

src 디렉토리
141029_porting1

LPCXpresso Project Explorer에서 생성한 프로젝트를 선택한 후 “F5″를 눌러 refresh를 하면, 복사한 Ethernet 디렉토리를 Project Explorer에서 확인 할 수 있다.
141029_porting2

복사한 Ethernet 디렉토리의 Include Path를 위해 다음 과정을 수행한다.
Project Explorer에서 W5500-EVB를 선택한 후, LPCXpresso 메뉴 Project->Properties를 클릭한다. 클릭하면 새로운 팝업 창이 뜨며, 오른쪽 메뉴의 C/C++ Build->Settings를 선택한다.
141029_porting3

Tool Settings 탭에서 MCU C Compiler -> Includes 항목을 선택한 후, 새로운 include 경로를 추가하기 위해 “+”로 표시된 아이콘을 클릭한다.
141029_porting4

“+”로 표시된 아이콘을 클릭하면 다음 창이 뜨며, Workspace…를 클릭한 후 W5500-EVB 프로젝트 내의 src 디렉토리를 선택하여 추가한다.
141029_porting5 141029_porting6

동일한 방법으로 Ethernet 디렉토리도 추가한다. 최종적으로 추가가 왼료되면 다음과 같이 나타난다.
141029_porting7

빌드하여 생성된 Firmware를 Flash Magic으로 보드에 적용하기 위해서는 Firmware가 Hex 파일 형태가 되어야 한다. Hex 파일 형태의 Firmware를 생성하기 위해서 다음의 과정을 수행한다.
Build steps 탭에서 Post-build steps -> Command 창의 Edit… 버튼을 누르면, 다음의 창이 뜨며 아래의 내용을 추가한다.

arm-none-eabi-objcopy -O ihex "${BuildArtifactFileBaseName}.axf" "${BuildArtifactFileBaseName}.hex"

141029_porting8

추가한 후 “OK” 버튼을 누르면 다음 창이 뜨며, “OK” 버튼을 눌러 다음 단계로 진행한다.
141029_porting9

표준 입출력 함수를 사용하기 위해 다음의 설정을 변경한다.
Tool Settings 탭에서 MCU Linker -> Managed Linker Script 항목을 선택한 후, Library 항목을 “Redlib(nohost)”로 변경한다.
141029_porting10

W5500 Driver 소스 Ethernet/W5500/w5500.h 파일에 다음 코드를 추가한다.
추가할 위치는 1176줄 “#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit()” 위에 추가한다.

#ifdef _exit
#undef _exit
#endif

141029_porting11

이 과정을 마친 후 빌드하면 정상적으로 빌드되는 것을 볼 수 있다.
141029_porting12

초기화 함수 구현

W5500 초기화 Flow

W5500을 사용하기 위해서는 다음의 초기화 과정이 필요하다.

  1. MCU Interface 초기화
    • SPI 관련 초기화
    • Reset Pin 관련 초기화
  2. Call back 함수 구현
    • Chip Select Functions
    • SPI Read/Write Functions
  3. W5500 Chip 초기화
    • H/W reset
    • Register Call Back Functions
    • Initializes to W5500 with SOCKET buffer size
  4. Network Information 초기화
MCU Interface 초기화 함수

MCU Inteface 초기화 함수에서는 SPI Inteface 관련 초기화 루틴과 Reset Pin 관련 초기화 루틴이 포함되어야 한다.

src 디렉토리에 spi_handler.h 파일을 생성한 후 Pin 관련 정보들을 정의한다.

#ifndef __SSP_H__
#define __SSP_H__

#define GPIO_SPI0_PORT      0
#define GPIO_W5500_RST_PORT 0

#define GPIO_SPI0_CS        2
#define GPIO_SPI0_CLK       6       
#define GPIO_SPI0_MISO      8
#define GPIO_SPI0_MOSI      9
#define GPIO_W5500_RST      3

void SPI_Init();

#endif

src 디렉토리에 spi_handler.c 파일을 생성한 후 다음의 초기화 루틴들을 구현한다.
헤더 파일 include

#include "board.h"
#include "spi_handler.h"

PIN Mux 설정 함수 구현

static void Init_SSP_PinMux(void)
{
    /* Configure SPI Pin */
    Chip_IOCON_PinMuxSet(LPC_IOCON, GPIO_SPI0_PORT, GPIO_SPI0_CLK, 
                    (IOCON_FUNC2 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
    Chip_IOCON_PinMuxSet(LPC_IOCON, GPIO_SPI0_PORT, GPIO_SPI0_MISO, 
                    (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
    Chip_IOCON_PinMuxSet(LPC_IOCON, GPIO_SPI0_PORT, GPIO_SPI0_MOSI, 
                    (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
    Chip_IOCON_PinMuxSet(LPC_IOCON, GPIO_SPI0_PORT, GPIO_SPI0_CS, 
                    (IOCON_FUNC0 | IOCON_MODE_PULLUP));
    Chip_GPIO_SetPinDIROutput(LPC_GPIO, GPIO_SPI0_PORT, GPIO_SPI0_CS);
    Chip_GPIO_SetPinState(LPC_GPIO, GPIO_SPI0_PORT, GPIO_SPI0_CS, true);

    /* Configure W5500 RESET Pin */
    Chip_GPIO_SetPinDIROutput(LPC_GPIO, GPIO_W5500_RST_PORT, GPIO_W5500_RST);
    Chip_GPIO_SetPinState(LPC_GPIO, GPIO_W5500_RST_PORT, GPIO_W5500_RST, true);
}

SPI 초기화 함수 (SPI Mode0 / SPI Clock 10MHz)

void SPI_Init()
{
    /* SSP initialization */
    Init_SSP_PinMux();
    Chip_SSP_Init(LPC_SSP0);

    Chip_SSP_SetFormat(LPC_SSP0, SSP_BITS_8, SSP_FRAMEFORMAT_SPI, SSP_CLOCK_MODE0);
    Chip_SSP_SetMaster(LPC_SSP0, true);
    Chip_SSP_SetBitRate(LPC_SSP0, 12000000);    // 12MHz
    Chip_SSP_Enable(LPC_SSP0);
}
Call Back 함수 구현

W5500에서 Host MCU의 SPI Interface 사용을 위한 Call Back Function들을 구현한다.

src 디렉토리에 w5500_init.c 파일에 SPI Call back function을 구현한다.

/* W5500 Call Back Functions */
static void  wizchip_select(void)
{
    Chip_GPIO_SetPinState(LPC_GPIO, GPIO_SPI0_PORT, GPIO_SPI0_CS, false);  // SSEL(CS)
}

static void  wizchip_deselect(void)
{
    Chip_GPIO_SetPinState(LPC_GPIO, GPIO_SPI0_PORT, GPIO_SPI0_CS, true);   // SSEL(CS)
}

static uint8_t wizchip_read()
{
    uint8_t rb;
    Chip_SSP_ReadFrames_Blocking(LPC_SSP0, &rb, 1);
    return rb;
}

static void  wizchip_write(uint8_t wb)
{
    Chip_SSP_WriteFrames_Blocking(LPC_SSP0, &wb, 1);
}

Call Back Function을 등록하기 위해 W5500_Init 함수 “Register Call back function” 주석 밑에 다음 코드를 추가한다.

/* Register Call back function */
reg_wizchip_cs_cbfunc(wizchip_select, wizchip_deselect);
reg_wizchip_spi_cbfunc(wizchip_read, wizchip_write);
W5500 Chip 초기화 함수

W5500 Chip 초기화 함수를 구현한다. 초기화 과정은 다음과 같다.

  • W5500 Chip Reset
  • Register SPI Call back Functions
  • W5500 Chip Initialization (Socket Buffer Size)

W5500 Chip Reset 방법은 Reset 핀을 High 상태에서 Low 상태로 바꾼 뒤 일정 시간 유지한 후, 다시 Reset 핀을 High 상태로 바꿔주면 된다.

src 디렉토리에 w5500_init.h 파일을 생성한 후, 다음을 정의 한다.

#ifndef __W5500_INIT_H__
#define __W5500_INIT_H__

void delay_cnt(volatile unsigned int nCount);
void display_net_info();
void Net_Conf();
void W5500_Init();

#endif

src 디렉토리에 w5500_init.c 파일을 생성한 후, 칩 초기화 루틴을 구현한다. (Call back 함수 등록은 Call Back 함수 부분에서 설명하겠다.)

헤더 파일 include

#include <stdio.h>
#include "board.h"
#include "spi_handler.h"
#include "wizchip_conf.h"
#include "socket.h"

Delay 함수

void delay_cnt(volatile unsigned int nCount)
{
    for(; nCount!= 0;nCount--);
}

W5500 Chip 초기화 함수

void W5500_Init()
{
    uint8_t memsize[2][8] = { { 2, 2, 2, 2, 2, 2, 2, 2 }, { 2, 2, 2, 2, 2, 2, 2, 2 } };

    /* W5500 Chip Reset */
    Chip_GPIO_SetPinState(LPC_GPIO, GPIO_W5500_RST_PORT, GPIO_W5500_RST, false);
    delay_cnt(5000);
    Chip_GPIO_SetPinState(LPC_GPIO, GPIO_W5500_RST_PORT, GPIO_W5500_RST, true);
    delay_cnt(10000);

    /* Register Call back function */
    reg_wizchip_cs_cbfunc(wizchip_select, wizchip_deselect);
    reg_wizchip_spi_cbfunc(wizchip_read, wizchip_write);

    /* W5500 Chip Initialization */
    if (ctlwizchip(CW_INIT_WIZCHIP, (void*) memsize) == -1) {
        printf("WIZCHIP Initialized fail.\r\n");
        while (1);
    }  
}
Network 설정 함수

Network 정보들을 설정하기 위한 함수이다. 설정하는 정보들은 다음과 같다.

  • mac address
  • ip address
  • gateway
  • subnet mask
  • dns server

src 디렉토리에 w5500_init.c 파일에 다음의 함수를 구현한다.

void display_net_info()
{
    wiz_NetInfo gWIZNETINFO;

    ctlnetwork(CN_GET_NETINFO, (void*) &gWIZNETINFO);
    printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n", gWIZNETINFO.mac[0], gWIZNETINFO.mac[1], gWIZNETINFO.mac[2], gWIZNETINFO.mac[3], gWIZNETINFO.mac[4], gWIZNETINFO.mac[5]);
    printf("IP: %d.%d.%d.%d\r\n", gWIZNETINFO.ip[0], gWIZNETINFO.ip[1], gWIZNETINFO.ip[2], gWIZNETINFO.ip[3]);
    printf("GW: %d.%d.%d.%d\r\n", gWIZNETINFO.gw[0], gWIZNETINFO.gw[1], gWIZNETINFO.gw[2], gWIZNETINFO.gw[3]);
    printf("SN: %d.%d.%d.%d\r\n", gWIZNETINFO.sn[0], gWIZNETINFO.sn[1], gWIZNETINFO.sn[2], gWIZNETINFO.sn[3]);
    printf("DNS: %d.%d.%d.%d\r\n", gWIZNETINFO.dns[0], gWIZNETINFO.dns[1], gWIZNETINFO.dns[2], gWIZNETINFO.dns[3]);
}

void Net_Conf()
{
    wiz_NetInfo gWIZNETINFO = {
        { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 },    // Mac address
        { 192, 168, 1, 100 },                       // IP address
        { 192, 168, 1, 1},                          // Gateway
        { 255, 255, 255, 0},                        // Subnet mask
        { 8, 8, 8, 8},                              // DNS Server
    };

    ctlnetwork(CN_SET_NETINFO, (void*) &gWIZNETINFO);

    display_net_info();
}

Main 함수 구현

W5500-EVB.c 파일내의 main 함수를 다음과 같이 구현한다.

int main(void) {

#if defined (__USE_LPCOPEN)
#if !defined(NO_BOARD_LIB)
    // Read clock settings and update SystemCoreClock variable
    SystemCoreClockUpdate();
    // Set up and initialize all required blocks and
    // functions related to the board hardware
    Board_Init();
    // Set the LED to the state of "On"
    Board_LED_Set(0, true);
#endif
#endif
    SPI_Init();
    W5500_Init();
    Net_Conf();

    while(1) {
    }   
    return 0;
}

W5500-EVB.c 파일에 헤더 파일 include 루틴을 추가한다.

#include "spi_handler.h"
#include "w5500_init.h"

Firmware 적용 및 테스트

※ W5500-EVB 연결 후 RS232 Driver를 설치해야 Serial 기능을 사용할 수 있다. RS232 Driver는 다음 링크에서 다운받을 수 있다.
다운로드

먼저 W5500-EVB를 ISP 모드로 동작시키기 위해서 ISP 버튼을 누른 상태에서 Reset 버튼을 누른다.
141029_w5500-evb_isp

Flash Magic 프로그램을 실행시킨다.
먼저 Step1 설정을 진행한다. Chip은 “LPC11E36/501″을 선택하며, 시리얼 설정은 각자 자신의 환경에 맞게 설정한다.
141029_firm_test1

Step2에 “Erase all Flash+Code Rd Prot” 부분을 체크한다.
141029_firm_test2

Step3에 앞의 과정에서 생성한 Firmware Hex 파일을 지정한다. Firmware 파일은 프로젝트 내의 Debug 디렉토리 내에 존재한다.
141029_firm_test3

Start 버튼을 누르면 Firmware 이미지가 보드에 적용된다.
141029_firm_test4

시리얼 터미널 프로그램을 실행시킨 후, 보드 Reset 버튼을 누르면 다음과 같은 Network 설정 메시지들을 볼 수 있다. 동일 네트워크 상에서 보드에 설정된 “192.168.1.100”으로 ping을 보내면 정상 동작하는 것을 볼 수 있을 것이다.
141029_firm_test5 141029_firm_test6

소스 파일 : 다운로드 프로젝트 파일 : 다운로드

W5500으로 이더넷 구현하기 (W5500 드라이버 포팅)”에 대한 2개의 생각

  1. 안녕하세요.
    님의 글을 보고 시험해 볼려고 하고 있는데 Flash magic으로 Write를 못하고 있습니다.
    Flash magic쪽은 글과 같이 설정하였는데 보드쪽에서 처리를 해줘야 하는게 있는지요?
    LPC계열은 처음이라 뭔지를 모르겠네요. 관련 자료도 찾을수가 없네요.
    스위치나 이런것을 순차적으로 눌러줘야 하는것이라면 순서를 좀 알려 주시면 좋겠습니다.

    응답
    1. damduc 글쓴이

      Flash Magic으로 Write를 하려면 하드웨어가 ISP 모드로 설정되어 있어야 합니다. 그 부분을 확인해 보세요.

      응답

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

This site uses Akismet to reduce spam. Learn how your comment data is processed.