본문 바로가기

RaspberryPi/RP2350

[RP2350-W6300 SSM] W6300 웹서버 테스트

 

[RP2350-W6300 SSM] 보드를 이용하여 웹서버 테스트를 해보자.

[RP2350 SM] W6300 개발환경 설정 코드에서 웹서버 코드를 추가 할수 있다.

https://nexp.tistory.com/4185

 

[RP2350 SM] W6300 테스트 개발환경 설정

RP2350을 이용하여 W6300을 테스트 해보자먼저 하드웨어 적으로 QSPI로 연결한다. [W6300 SSM] 보드는 표준 핀맵의 SPI로 할당되어 있고 나머지 핀에 QSPI 핀이 할당되어 있다. RP2350은 QSPI 하드웨어 블록은

nexp.tistory.com

 

웹서버를 구현하려면 ioLibrary_Driver 에서 제공하는 httpServer 코드를 복사한다.

https://github.com/Wiznet/ioLibrary_Driver/tree/927c017c5b207414882a38b854ebaef905aa0515/Internet/httpServer

 

 

Cmakelist 파일에 추가된 파일을 업데이트 한다.

add_executable(rp2350_w6300_test rp2350_w6300_test.c 
        Ethernet/socket.c
        Ethernet/wizchip_conf.c
        Ethernet/w6300/wizchip_spi.c  
        Ethernet/w6300/w6300.c 
        Ethernet/w6300/wizchip_qspi_pio.c
        Ethernet/w6300/wizchip_gpio_irq.c

        Ethernet/Internet/httpServer/httpParser.c
        Ethernet/Internet/httpServer/httpServer.c
        Ethernet/Internet/httpServer/httpUtil.c        
)

# Add the standard include files to the build
target_include_directories(rp2350_w6300_test PRIVATE
        ${CMAKE_CURRENT_LIST_DIR}
        ${CMAKE_CURRENT_LIST_DIR}/Ethernet
        ${CMAKE_CURRENT_LIST_DIR}/Ethernet/w6300
        ${CMAKE_CURRENT_LIST_DIR}/Ethernet/Internet/httpServer
)

 

 

 

W6300 웹서버 테스트 기본 코드

#define index_html  "<!DOCTYPE html>\
<html>\
<head>\
  <title> remote control</title>\
	<style>\
	.container {margin: 0 auto; text-align: center; margin-top: 80px; }\
	button {color: white; width: 150px; height: 100px;\
	border-radius: 20%; margin: 5px; border: none; font-size: 40px; outline: none; transition: all 0.2s;}\
	.red{background-color: rgb(196, 39, 39);}\
	.green{background-color: rgb(39, 121, 39);}\
	.blue {background-color: rgb(5, 87, 180);}\
	.off{background-color: grey;}\
	button:hover{cursor: pointer; opacity: 0.7;}\
	</style>\
</head>\
<body>\
	<div class='container'>\
	<h1>W6300 LED Control</h1>\
	<button class='red' type='submit' onclick='location.href=\"/led_on\"'>ON</button>\
	<button class='off' type='submit' onmousedown='location.href=\"/led_off\"'>OFF</button><br>\
	</div>\
</body>\
</html>"


/* Ethernet 통신용 버퍼 최대 크기 (송수신 각각 2KB) */
#define ETHERNET_BUF_MAX_SIZE (1024 * 2)

/* 동시에 사용할 수 있는 HTTP 소켓의 최대 개수 */
#define HTTP_SOCKET_MAX_NUM 4


/* HTTP 송신 버퍼 (2KB) */
static uint8_t g_http_send_buf[ETHERNET_BUF_MAX_SIZE] = {0};
/* HTTP 수신 버퍼 (2KB) */
static uint8_t g_http_recv_buf[ETHERNET_BUF_MAX_SIZE] = {0};
/* 사용할 소켓 번호 리스트 (0~3) */
static uint8_t g_http_socket_num_list[HTTP_SOCKET_MAX_NUM] = {0, 1, 2, 3};

int main()
{
    /* 시스템 클럭 설정 */
    set_clock_khz();

    /* 표준 입출력 초기화 (USB-CDC / UART 디버그 출력) */
    stdio_init_all();
    sleep_ms(3000);   // 초기 안정화 대기 (3초)

    /* 빌드 시각 출력 */
    printf("==========================================================\n");
    printf("Compiled @ %s, %s\n", __DATE__, __TIME__);
    printf("==========================================================\n");

    /* WIZnet 이더넷 칩 초기화 과정 */
    wizchip_spi_initialize();   // SPI 인터페이스 초기화
    wizchip_cris_initialize();  // CRIS (Critical Section) 초기화
    wizchip_reset();            // WIZnet 칩 하드웨어 리셋
    wizchip_initialize();       // 내부 레지스터 및 메모리 초기화
    wizchip_check();            // 칩 동작 확인

    /* 네트워크 환경 설정 (IP, Gateway, Subnet 등) */
    network_initialize(g_net_info);

    /* 현재 네트워크 정보 출력 */
    print_network_information(g_net_info);

    // HTTP 서버 초기화 
    httpServer_init(g_http_send_buf, g_http_recv_buf, HTTP_SOCKET_MAX_NUM, g_http_socket_num_list);

    /* 웹 서버에 페이지 등록
       - "index.html" 요청 시 index_html 배열을 응답
       - "led_on", "led_off" 요청도 동일하게 index_html 반환 */
    reg_httpServer_webContent("index.html", index_html);
    reg_httpServer_webContent((uint8_t *)"led_on", (uint8_t *)index_html);
    reg_httpServer_webContent((uint8_t *)"led_off", (uint8_t *)index_html);
    
    /* 메인 루프: HTTP 서버 실행 */
    while (true) {
        /* 등록된 소켓들(0~3)에 대해 HTTP 서버 동작 */
        for (int i = 0; i < HTTP_SOCKET_MAX_NUM; i++) {
            httpServer_run(i);
        }
    }
}

 

 

컴파일 후 실행하고 보드의 IP로 접속하면 index_html 페이지가 출력되는 것을 확인 할 수 있다.

 

 

이번에는 on/off 에 따른 페이지 요청에 대한 처리를 해주는 코드를 작성하자. 

httpServer.c 파일에서 http_process_handler 함수를 수정해서 페이지 요청에 따른 콜백 함수를 처리 할수 있도로 한다.

static void http_process_handler(uint8_t s, st_http_request * p_http_request)
{
	uint8_t * uri_name;
	uint32_t content_addr = 0;
	uint16_t content_num = 0;
	uint32_t file_len = 0;

	uint8_t uri_buf[MAX_URI_SIZE]={0x00, };

	uint16_t http_status;
	int8_t get_seqnum;
	uint8_t content_found;

	if((get_seqnum = getHTTPSequenceNum(s)) == -1) return; // exception handling; invalid number

	http_status = 0;
	http_response = pHTTP_RX;
	file_len = 0;

	//method Analyze
	switch (p_http_request->METHOD)
	{
		case METHOD_ERR :
			http_status = STATUS_BAD_REQ;
			send_http_response_header(s, 0, 0, http_status);
			break;

		case METHOD_HEAD :
		case METHOD_GET :
			get_http_uri_name(p_http_request->URI, uri_buf);
			uri_name = uri_buf;

			if (!strcmp((char *)uri_name, "/")) strcpy((char *)uri_name, INITIAL_WEBPAGE);	// If URI is "/", respond by index.html
			if (!strcmp((char *)uri_name, "m")) strcpy((char *)uri_name, M_INITIAL_WEBPAGE);
			if (!strcmp((char *)uri_name, "mobile")) strcpy((char *)uri_name, MOBILE_INITIAL_WEBPAGE);
			find_http_uri_type(&p_http_request->TYPE, uri_name);	// Checking requested file types (HTML, TEXT, GIF, JPEG and Etc. are included)

#ifdef _HTTPSERVER_DEBUG_
			printf("\r\n> HTTPSocket[%d] : HTTP Method GET\r\n", s);
			printf("> HTTPSocket[%d] : Request Type = %d\r\n", s, p_http_request->TYPE);
			printf("> HTTPSocket[%d] : Request URI = %s\r\n", s, uri_name);
#endif

			if(ProcessUserPageCb(uri_name, p_http_request) == 1)
			{

				if(find_userReg_webContent(uri_buf, &content_num, &file_len))
				{
					content_found = 1; // Web content found in code flash memory
					content_addr = (uint32_t)content_num;
					HTTPSock_Status[get_seqnum].storage_type = CODEFLASH;
				}

				if(!content_found)
				{
#ifdef _HTTPSERVER_DEBUG_
					printf("> HTTPSocket[%d] : Unknown Page Request\r\n", s);
#endif
					http_status = STATUS_NOT_FOUND;
				}
				else
				{
#ifdef _HTTPSERVER_DEBUG_
					printf("> HTTPSocket[%d] : Find Content [%s] ok - Start [%ld] len [ %ld ]byte\r\n", s, uri_name, content_addr, file_len);
#endif
					http_status = STATUS_OK;
				}

				// Send HTTP header
				if(http_status)
				{
					//send_http_response_header(s, p_http_request->TYPE, file_len, http_status);
				}

				// Send HTTP body (content)
				if(http_status == STATUS_OK)
				{
					send_http_response_body(s, uri_name, http_response, content_addr, file_len);
				}			

				break;	
			}

 

 

메인함수에 콜백함수 ProcessUserPageCb 를 등록하고 페이지 요청에 따를 처르를 해 주면 된다.

unsigned int ProcessUserPageCb(uint8_t *uri_name, st_http_request * p_http_request)
{
	if(strstr(p_http_request->URI, "led_off"))
	{
		Led1Off();

		printf("LED ->%s\r\n", uri_name);
        return 1;
	}
	else if(strstr(p_http_request->URI, "led_on"))
	{
		Led1On();
		printf("LED ->%s\r\n", uri_name);
        return 1;
	}

	return 0;
}

 

 


좀더 복잡한 웹페이지를 표현하기 위해 바이너리 파일을 처리 할 수 있는 코드가 있으면 좋을것 같다. 그림파일이나 자바 복잡한 자바 스크립트 파일등은 바이너리로 저장해서 처리 하도록 하면 편리하다.

void reg_httpServer_webContentB(uint8_t * content_name, const uint8_t * content, unsigned int size)
{
	uint16_t name_len;
	uint32_t content_len;

	if(content_name == NULL || content == NULL)
	{
		return;
	}
	else if(total_content_cnt >= MAX_CONTENT_CALLBACK)
	{
		return;
	}

	name_len = strlen((char *)content_name);
	content_len = size;

	web_content[total_content_cnt].content_name = malloc(name_len+1);
	strcpy((char *)web_content[total_content_cnt].content_name, (const char *)content_name);
	web_content[total_content_cnt].content_len = content_len;
	web_content[total_content_cnt].content = content;

	total_content_cnt++;
}

 

 

바이너리 처리 함수를 추가해서 웹페이지를 등록

    /* Register web page */
    reg_httpServer_webContentB("index.html", index_html, 4594);
    reg_httpServer_webContentB("basic.ccs", basic_ccs, 2408);
    reg_httpServer_webContentB("javascript.js", myjava_lib, 10763);
    reg_httpServer_webContent((uint8_t *)"led_on", (uint8_t *)index_html);
    reg_httpServer_webContent((uint8_t *)"led_off", (uint8_t *)index_html);

 

 

이렇게해서 좀더 복잡한 웹페이지도 쉽게 처리 할 수 있게 되었다. W6300의 네트웍 전송속도가 빠르기 때문에 복잡한 웹페이지도 부드럽게 잘 치리 되는것 같다.

 

 

반응형