(3)W5500-EVB Chat_Adder_Ringbuffer

안녕하세요.
Edward입니다.

저번 링버퍼 설명에 추가하여 링버퍼 구현 코드를 올리겠습니다.

코드는 아래와 같습니다.


/*
===============================================================================
 Name : W5500-EVB.c
 Author : $(author)
 Version :
 Copyright : $(copyright)
 Description : main definition
===============================================================================
*/

#if defined (__USE_LPCOPEN)
#if defined(NO_BOARD_LIB)
#include <chip.h>
#else
#include <board.h>
#endif
#endif

#include "cr_section_macros.h"
#include "socket.h"
#include"spi_handler.h"
#include "w5500_init.h"

// TODO: insert other include files here

// TODO: insert other definitions and declarations here
#define SOCK_TCPS0 0
#define DATA_BUF_SIZE 2048
#define SERIAL_BUF_SIZE 2048
uint8_t gDATABUF[DATA_BUF_SIZE];
uint8_t SERIAL_BUF[SERIAL_BUF_SIZE];
uint8_t SERIAL_SIZE = 0;

typedef struct {
	int head;
	int tail;
	char data[SERIAL_BUF_SIZE];
} t_rb;

t_rb ringbuffer = {0, 0, }; // used to t_rb struct to creation ringbuffer variable to head = 0; , tail = 0;
uint8_t AutoSend_flag=0; // global variable

int rb_put( t_rb *rb , char d ) // push -> read UART
{
	int nhead = (rb->head+1) % (SERIAL_BUF_SIZE+1); // adder tail
	if (rb->tail == nhead) {	// full
		return 0;
	}
	rb->data[rb->head] = d;
	rb->head = nhead;
	return 1; // return rb_put -> continue the function -> until the tail output
}

/*push -> serial data write , pop -> read the data to send*/
char rb_get( t_rb *rb, int *err ) // pop -> send Ethernet
{
	char d;
	int ntail = (rb->tail+1) % (SERIAL_BUF_SIZE+1);
	if (rb->tail == rb->head) {	// empty
		*err = 0;
		return 0;
	}
	d = rb->data[rb->tail];
	rb->tail = ntail;
	*err = 1;
	return d; // return d
}

int finder ( t_rb *rb, char ch )
{
	int i;
	int cnt;

	if(rb->head > rb->tail){
		for(i=rb->tail; i<rb->head; i++){
			if(rb->data[i] == ch){
				return i;
			}
		}
	}
	else{
		for(i=rb->tail; i < SERIAL_BUF_SIZE; i++){
			if(rb->data[i] == ch){
				return i;
			}
		}
		cnt = i;
		for(i=0; i < rb->tail; i++){
			if(rb->data[i] == ch){
				return (cnt +i);
			}
		}
	}
	return 0;
}

int EtherToSerial(uint8_t* buf,uint16_t size)
{
	uint8_t i;
	for(i=0 ; i < size ; i++){
		putchar(buf[i]);
	}
	return 0 ;
}

int SerialToEther(uint8_t sn)
{
	int len = finder(&ringbuffer, '\n');
	int err;
	int i;

	if(len > 0)
	{
		for(i=0; i<len; i++){
			SERIAL_BUF[i] = rb_get(&ringbuffer, &err);
		}
		send(sn, SERIAL_BUF, len);
		return len;
	}
	else if(AutoSend_flag == 1)
	{
		for(i=0; i<SERIAL_BUF_SIZE; i++){
			SERIAL_BUF[i] = rb_get(&ringbuffer, &err);
		}
		send(sn, SERIAL_BUF, SERIAL_BUF_SIZE);
		AutoSend_flag = 0;
		return SERIAL_BUF_SIZE;
		}
	return 0;
}

void UART_IRQHandler(void)
{
	if((Chip_UART_ReadLineStatus(LPC_USART) & UART_LSR_RDR) == 1){
		if(rb_put(&ringbuffer, Chip_UART_ReadByte(LPC_USART)) != 1){
			AutoSend_flag = 1;
		}

	}
}

int main(void) {

	//uint8_t ip[4]={192,168,0,45};
	uint16_t port=23;
	uint8_t sn=SOCK_TCPS0;
	uint16_t size=0;

	#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();

	Chip_UART_IntEnable(LPC_USART, (UART_IER_RBRINT | UART_IER_RLSINT)); //uart enable

	/* Enable UART 0 interrupt */
	NVIC_EnableIRQ(UART0_IRQn);



	//printf("%d:Connecting, ip[%d.%d.%d.%d] port [%d]\r\n", sn, ip[0], ip[1], ip[2], ip[3], port);

	while(1) {
		switch(getSn_SR(sn)) { // Sn_SR(sn) check if) listen state? goto ESTABLISHED
		case SOCK_CLOSED:
			if(socket(sn, Sn_MR_TCP, port, 0x00)==sn){ // socket create
				printf("%d:Socket Opened\r\n",sn);
			}
			else{
				printf("%d:Socket Error\r\n",sn);
				while(1); // end to error
			}

			break;
		case SOCK_INIT:
			//printf("%d:Connecting, ip[%d.%d.%d.%d] port [%d]\r\", sn, ip[0], ip[1], ip[2], ip[3], port);
			/*
 	 	 	 if(connect(sn,ip,port)==SOCK_OK);
 	 	 	 else {
 	 	 	 	 printf("%d:Connect Error\r\n",sn);
 	 	 	 	 while(1);
 	 	 	 	 }
			*/
			if(listen(sn) == SOCK_OK){ // listen state
				printf("%d:listen\r\n",sn);
			}
			else{
				printf("%d:listen error\r\n",sn);
				while(1);
			}

			break;
		case SOCK_LISTEN:
			/* TCP Server Mode */

			break;
		case SOCK_ESTABLISHED:
			/* TCP ESTABLISHED */
			//Connect Interrupt Check
			if(getSn_IR(sn) & Sn_IR_CON) {
				printf("%d:Connected\r\n",sn);
				setSn_IR(sn,Sn_IR_CON);
				Board_LED_Set(0, false);
				Board_LED_Set(1, true);
			}
			//Receive Data Check
			if((size = getSn_RX_RSR(sn)) > 0) {
				if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
				recv(sn,gDATABUF,size);
				EtherToSerial(gDATABUF, size);
			}
			SerialToEther(sn);
			break;

		case SOCK_CLOSE_WAIT:
			if(disconnect(sn) == SOCK_OK){
				printf("%d:disconnect OK\r\n",sn);
			}
			else{
				printf("%d:diconnect Error\r\n",sn);
			}

			break;
		}
		//NVIC_DisableIRQ(UART0_IRQn);
		//Chip_UART_DeInit(LPC_USART);
	}
	return 0 ;
}

* 설명!


typedef struct { // Creation buffer(링버퍼)
	int head;
	int tail;
	char data[SERIAL_BUF_SIZE];
} t_rb;

t_rb ringbuffer = {0, 0, }; // head, tail 0 초기화
uint8_t AutoSend_flag=0; // 자동전송 flag & 플래그 1될 때 강제전송
/*여기서! return1일 때 Data Write하고 return0일 때는 Data Write안되요*/
int rb_put( t_rb *rb , char d ) // push -> read UART
{
	int nhead = (rb->head+1) % (SERIAL_BUF_SIZE+1); // 나머지 연산
	if (rb->tail == nhead) {	// full
		return 0;
	}
	rb->data[rb->head] = d; // 위 조건식이 아닐경우 데이터 배열로 Write
	rb->head = nhead; // Write 포인터 증가
	return 1; // return rb_put;
}

/*마찬가지로 return d일 때 read 포인터에서 data 뽑아서 출력*/
/*push -> serial data write , pop -> read the data to send*/
char rb_get( t_rb *rb, int *err ) // pop -> send Ethernet
{
	char d;
	int ntail = (rb->tail+1) % (SERIAL_BUF_SIZE+1); // 나머지 연산
	if (rb->tail == rb->head) {	// empty
		*err = 0;
		return 0;
	}
	d = rb->data[rb->tail]; // Read 포인터
	rb->tail = ntail; // Read 포인터 감소(data 뽑아냈으니깐.)
	*err = 1;
	return d; // return d
}


int finder ( t_rb *rb, char ch ) // \n 개행문자 입력 시 Data 전송 되도록 구현
{
	int i;
	int cnt;

	if(rb->head > rb->tail){ // head가 tail보다 작으면
		for(i=rb->tail; i<rb->head; i++){ // tail부터 head범위까지
			if(rb->data[i] == ch){ // 찾기
				return i;
			}
		}
	}
	else{
		for(i=rb->tail; i < SERIAL_BUF_SIZE; i++){ //tail부터 size까지
			if(rb->data[i] == ch){ // 찾기
				return i;
			}
		}
		cnt = i;
		for(i=0; i < rb->tail; i++){ // 0부터 tail까지
			if(rb->data[i] == ch){ // 찾기
				return (cnt +i);
			}
		}
	}
	return 0;
}

int EtherToSerial(uint8_t* buf,uint16_t size) // Client로 부터 Data 받음.
{
	uint8_t i;
	for(i=0 ; i < size ; i++){
		putchar(buf[i]);
	}
	return 0 ;
}
/*수신버퍼와 SERIAL_BUF랑은 다른거에요!*/
/*저렇게 버퍼에 있는걸 버퍼로 넣어서 한번에 전송시키는게 속도가 빠른 것으로 알고있어요.*/
int SerialToEther(uint8_t sn) // Client로 data 출력
{
	int len = finder(&ringbuffer, '\n');
	int err;
	int i;

	if(len > 0)
	{
		for(i=0; i<len; i++){
			SERIAL_BUF[i] = rb_get(&ringbuffer, &err); // UART data를 Serial buffer에 담음.
		}
		send(sn, SERIAL_BUF, len); // Serial 버퍼에 있는 Data 전송
		return len; // len 범위까지
	}
	else if(AutoSend_flag == 1) // 자동전송
	{
		for(i=0; i<SERIAL_BUF_SIZE; i++){
			SERIAL_BUF[i] = rb_get(&ringbuffer, &err);
		}
		send(sn, SERIAL_BUF, SERIAL_BUF_SIZE);
		AutoSend_flag = 0;
		return SERIAL_BUF_SIZE; // 전체 전송
		}
	return 0;
}

void UART_IRQHandler(void)
{
	if((Chip_UART_ReadLineStatus(LPC_USART) & UART_LSR_RDR) == 1){
		if(rb_put(&ringbuffer, Chip_UART_ReadByte(LPC_USART)) != 1){ // UART 1byte씩 Read. 
			AutoSend_flag = 1; // if문 조건식이 1과 같지 않으면 참으로 인식 -> 자동 전송함.
		}

	}
}

!!! 여기에서 문제점..

버그가 발견되었습니다.

UART에서 Data를 읽어와서 Ethernet으로 전송해야하는데, Firmware 적으로 뻗어버립니다.

자동전송까지는 구현이 되었는데, 개행문자를 사용해서 보내버리면 Firmware가 먹통이 되어버려서 다음시간에는 Debugging하여 포스팅 하겠습니다.

Advertisements

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

%s에 연결하는 중