Hardware/STM32

[STM32F746G-DISCO] HTTP server 테스트

rudals.kim 2024. 7. 22. 17:51
반응형
아래 테스트는 STM32CubeIDE 1.7.0/STM32Cube_FW_F7_V1.16.1를 사용하여 테스트 되었습니다.


STM32F746G-DISCO 보드용으로 제공되는 lwIP 예제가 적어서 STM32756G_EVAL에서 제공되는 예제를 살펴보니 다양한 lwIP 예제가 제공되고 있었고 이를 참고하여 HTTP server 테스트를 해 보았습니다.
(참고 예제 : TM32Cube_FW_F7_V1.16.1/Projects/STM32756G_EVAL/Applications/LwIP/LwIP_HTTP_Server_Netconn_RTOS)

새 프로젝트를 생성 후 DMA2D/ETH/FMC/FREERTOS/GPIO/LTDC/LWIP/NVIC/RCC/SYS/USART1을 설정하였습니다.

이더넷은 STM32의 이전게시물에서 사용된 것과 동일하게 설정을 하였습니다.

HTTP 서버로 동작되기 위해 lwip의 HTTPD 설정을 enable 시켰습니다.

제공되는 예제를 참고하여 새 프로젝트를 작성합니다.

저는 HTTP 서버 테스트를 위해 간단한 데모 웹페이지에 2개의 버튼을 생성 후 각 각의 버튼을 클릭 시 해당 이벤트를 STM32F746G-DISCO 보드에서 수신하여 개별 처리되는 테스트를 해 보려고 합니다.

테스트에 사용될 데모 웹페이지인 index.html을 아래와 같이 작성하였습니다.

<!DOCTYPE html>
<html>

<head>
    <title>STM32F746G-DISCO LWIP 테스트</title>
    <meta charset="utf-8" />
    <style>
        html body {
            font-family:Verdana,sans-serif;
            font-size:15px
        }

        .center {
            margin: auto;
            width: 50%;
            border: 1px solid green;
            padding: 10px;
        }

        .title {
            background-color: #b2fd9f;
            width: 450px;
            padding: 20px 30px;
            text-align: center;
        }

        .main {
            background-color: #a6f5e5;
            width: 450px;
            padding: 20px 30px;
            text-align: center;
        }

        .button {
            border: none;
            color: white;
            padding: 15px 32px;
            text-align: center;
            text-decoration: none;
            display: inline-block;
            font-size: 16px;
            margin: 4px 2px;
            cursor: pointer;
            width: 130px;
            border-radius: 5px;
        }

        .button1 {
            background-color: #065fa8;
        }
    </style>
</head>

<body>
    <h1 class="title center">LWIP를 사용한 HTTP 테스트</h1>
    <br/>
    <div class="main center">
        <form method="GET">
            <h2>LED ON/OFF 테스트</h2>
            <input class="button button1" type="submit" name="led" value="OFF" />
            <input class="button button1" type="submit" name="led" value="ON" />
        </form>
    </div>
</body>

</html>


위 HTML 소스코드는 바로 사용하지 못하고 아래 perl 스크립트 소스를 사용하여 예제 디렉터리에 있는 fsdata_custom.c 파일과 같이 변환해 주는 작업이 필요합니다. 아래 스크립트 소스를 makefsdata로 저장합니다.

#!/usr/bin/perl

open(OUTPUT, "> fsdata.c");

chdir("fs");
open(FILES, "find . -type f |");

while($file = <FILES>) {

    # Do not include files in CVS directories nor backup files.
    if($file =~ /(CVS|~)/) {
    	next;
    }
    
    chop($file);
    
    open(HEADER, "> /tmp/header") || die $!;
    if($file =~ /404/) {
	print(HEADER "HTTP/1.0 404 File not found\r\n");
    } else {
	print(HEADER "HTTP/1.0 200 OK\r\n");
    }
    print(HEADER "Server: lwIP/pre-0.6 (http://www.sics.se/~adam/lwip/)\r\n");
    if($file =~ /\.html$/) {
	print(HEADER "Content-type: text/html\r\n");
    } elsif($file =~ /\.gif$/) {
	print(HEADER "Content-type: image/gif\r\n");
    } elsif($file =~ /\.png$/) {
	print(HEADER "Content-type: image/png\r\n");
    } elsif($file =~ /\.jpg$/) {
	print(HEADER "Content-type: image/jpeg\r\n");
    } elsif($file =~ /\.class$/) {
	print(HEADER "Content-type: application/octet-stream\r\n");
    } elsif($file =~ /\.ram$/) {
	print(HEADER "Content-type: audio/x-pn-realaudio\r\n");    
    } else {
	print(HEADER "Content-type: text/plain\r\n");
    }
    print(HEADER "\r\n");
    close(HEADER);

    unless($file =~ /\.plain$/ || $file =~ /cgi/) {
	system("cat /tmp/header $file > /tmp/file");
    } else {
	system("cp $file /tmp/file");
    }
    
    open(FILE, "/tmp/file");
    unlink("/tmp/file");
    unlink("/tmp/header");

    $file =~ s/\.//;
    $fvar = $file;
    $fvar =~ s-/-_-g;
    $fvar =~ s-\.-_-g;
    print(OUTPUT "static const unsigned char data".$fvar."[] = {\n");
    print(OUTPUT "\t/* $file */\n\t");
    for($j = 0; $j < length($file); $j++) {
	printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1)));
    }
    printf(OUTPUT "0,\n");
    
    
    $i = 0;
    while(read(FILE, $data, 1)) {
        if($i == 0) {
            print(OUTPUT "\t");
        }
        printf(OUTPUT "%#02x, ", unpack("C", $data));
        $i++;
        if($i == 10) {
            print(OUTPUT "\n");
            $i = 0;
        }
    }
    print(OUTPUT "};\n\n");
    close(FILE);
    push(@fvars, $fvar);
    push(@files, $file);
}

for($i = 0; $i < @fvars; $i++) {
    $file = $files[$i];
    $fvar = $fvars[$i];

    if($i == 0) {
        $prevfile = "NULL";
    } else {
        $prevfile = "file" . $fvars[$i - 1];
    }
    print(OUTPUT "const struct fsdata_file file".$fvar."[] = {{$prevfile, data$fvar, ");
    print(OUTPUT "data$fvar + ". (length($file) + 1) .", ");
    print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) ."}};\n\n");
}

print(OUTPUT "#define FS_ROOT file$fvars[$i - 1]\n\n");
print(OUTPUT "#define FS_NUMFILES $i\n");


위 perl 스크립트를 저장한 디렉토리에 fs 디렉터리를 생성합니다.

예제 프로젝트의 fs 디렉터리의 404.html 파일과 위에서 작성한 index.html 파일을 새로 생성한 fs 디렉터리로 복사해 넣습니다. 위 perl 스크립트 파일이 리눅스 명령어가 사용되어 윈도우 PC 사용자인 경우 cygwin이나 msys 환경에서 실행해야 합니다.


리눅스 환경에서 ./makefsdata 명령어로 실행시키면 같은 디렉터리에 fsdata.c 파일이 생성됩니다.
이 파일의 내용이 예제 프로젝트의 fsdata_custom.c 파일과 동일한 구조로 변경된 파일입니다.
이 파일을 새 프로젝트에 추가하여 적용시키면 됩니다.

데모 웹페이지의 버튼 클릭 시 해당 이벤트를 처리하기 위해 httpserver-netconn.c의 http_server_serve 함수를 아래와 같이 수정하였습니다.

if((strncmp(buf, "GET /index.html", 15) == 0)||(strncmp(buf, "GET / ", 6) == 0)) {
  /* Load STM32F7xx page */
  fs_open(&file, "/index.html");
  netconn_write(conn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY);
  fs_close(&file);
}else if((strncmp(buf, "GET /?led=OFF", 13) == 0)||(strncmp(buf, "GET / ", 6) == 0)) {
  printf("--> led off\r\n");
  fs_open(&file, "/index.html");
  netconn_write(conn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY);
  fs_close(&file);
}else if((strncmp(buf, "GET /?led=ON", 12) == 0)||(strncmp(buf, "GET / ", 6) == 0)) {
  printf("===> led on\r\n");
  fs_open(&file, "/index.html");
  netconn_write(conn, (const unsigned char*)(file.data), (size_t)file.len, NETCONN_NOCOPY);
  fs_close(&file);
}


프로젝트를 빌드 후 실행시켜 보면 아래와 같은 화면이 나옵니다.

PC의 웹브라우저를 사용하여 데모 보드의 IP로 접속해 봅니다. 위 index.html 파일이 정상적으로 보입니다.

OFF/ON 버튼을 클릭해 봅니다. led의 파라미터 값이 변경되어 각 각 전송됩니다.

STM32F746G-DISCO 보드에서 해당 이벤트를 수신하여 ON/OFF를 로그를 보여줍니다.

로그를 처리하는 부분에서 다른 센서나 모터등의 주변장치를 제어하는 기능을 추가하여 기능을 확장시킬 수 있을것으로 보입니다. 인터넷으로 데모 보드에 접속하여 사용자 이벤트를 수신하는 기본 테스트를 해 보았습니다.

반응형