메인함수가 실행되어서 src의 ID와 dest의 ID의 설정이 모두 완료되고나면 while문 안에서 반복문이 실행되어진다. 이때 주어진 상황은 srcID에 1 그리고 destID에 2가 저장된다.
arqLLI_initLowLayer(endNode_ID);//하위레이어로 전달 nodeID전달
pc.attach(&arqMain_processInputWord, Serial::RxIrq);
위 문장을 실행해서 하위 레이어에게 endNodeID를 제공해서 lowlayer를 초기화 한다. 이후 밑에 attch함수를 통해서 지속적으로 문자를 받아드리게 만들어준다.
int main(void){
while(1)
{
//debug message
if (prev_state != main_state)//위에서 메인함수 처음으로 실행할 때 prev_state를 0으로 초기화했고 위에서 main state도 0으로 초기화되어있음
{//prev_state와 mainstate가 다르다면
debug_if(DBGMSG_ARQ, "[ARQ] State transition from %i to %i\n", prev_state, main_state);//디버깅 문장을 추가 하고 다시 조건을 부여해서 디버깅한다,
prev_state = main_state;//둘의 상태를 같게 만들어줌
}
이후 메인함수 내부의 반복문이 실행이 되는데 내부에 제일 먼제 if의 기능은 FSM의 상태를 전 상태와 비교해서 같지 않은 경우에 디버깅 메세지와 함께 디버깅을 실행하고 이때 prev_state 와 main_state 를 같게 만들어준다.
이후 위의 if 문을 지나고 나면 switch문이 실행되며 mainstate에 따라서 반복문이 다르게 작동하게 되어있다.
switch (main_state)
{
case MAINSTATE_IDLE: //IDLE state description// main state가 IDLE 상태라면이고 수신대기중일때
if (arqEvent_checkEventFlag(arqEvent_dataRcvd)) //if data reception event happens 데이터 수신이 일어나면
{
//Retrieving data info.
uint8_t srcId = arqLLI_getSrcId();//수신한 src의 아이디를 반환하는 함수를 이용해서 scrId 변수에 저장한다.
uint8_t* dataPtr = arqLLI_getRcvdDataPtr();//수신한 data의 출력할 부분을 받는다.
uint8_t size = arqLLI_getSize();//입력받은 데이터의 크기를 반환한다.
pc.printf("\n -------------------------------------------------\nRCVD from %i : %s (length:%i, seq:%i)\n -------------------------------------------------\n",
srcId, arqMsg_getWord(dataPtr), size, arqMsg_getSeq(dataPtr));
main_state = MAINSTATE_IDLE;//다시 수신대기 상태로 만든다.
flag_needPrint = 1;//출력될 데이터가 있다는 의미인 변수를 1로 만들어 준다.
arqEvent_clearEventFlag(arqEvent_dataRcvd);//arqEvent_dataRcvd =3
}
else if (arqEvent_checkEventFlag(arqEvent_dataToSend)) //if data needs to be sent (keyboard input)
{// arqEvent_dataToSend = 4,
//msg header setting
pduSize = arqMsg_encodeData(arqPdu, originalWord, seqNum, wordLen);//생성되는 pdu의 사이즈를 반환한다.
arqLLI_sendData(arqPdu, pduSize, dest_ID);//pdu를 전송한다.
pc.printf("[MAIN] sending to %i (seq:%i)\n", dest_ID, (seqNum-1)%ARQMSSG_MAX_SEQNUM);//ARQMSSG_MAX_SEQNUM 로 모듈레이션 연산을 수행해준다.
main_state = MAINSTATE_TX;
flag_needPrint = 1;
wordLen = 0;
arqEvent_clearEventFlag(arqEvent_dataToSend);//eventFlag = 0 이 된다.
}
else if (flag_needPrint == 1)
{
pc.printf("Give a word to send : ");
flag_needPrint = 0;
}
break;
case MAINSTATE_TX: //IDLE state description
if (arqEvent_checkEventFlag(arqEvent_dataTxDone)) //data TX finished
{
main_state = MAINSTATE_IDLE;
arqEvent_clearEventFlag(arqEvent_dataTxDone);
}
break;
default :
break;
}
}
}
크게 두가지로 나누어서 switch 문이 실행되는데 첫번째는 main state가 idel 상태와 동일한 경우이다.
uint8_t main_state = MAINSTATE_IDLE; //protocol state
위 문장 때문에 제일 먼저 실행되는 switch문은 다음과 같다.
case MAINSTATE_IDLE: //IDLE state description// main state가 IDLE 상태라면이고 수신대기중일때
if (arqEvent_checkEventFlag(arqEvent_dataRcvd)) //if data reception event happens 데이터 수신이 일어나면
{
//Retrieving data info.
uint8_t srcId = arqLLI_getSrcId();//수신한 src의 아이디를 반환하는 함수를 이용해서 scrId 변수에 저장한다.
uint8_t* dataPtr = arqLLI_getRcvdDataPtr();//수신한 data의 출력할 부분을 받는다.
uint8_t size = arqLLI_getSize();//입력받은 데이터의 크기를 반환한다.
pc.printf("\n -------------------------------------------------\nRCVD from %i : %s (length:%i, seq:%i)\n -------------------------------------------------\n",
srcId, arqMsg_getWord(dataPtr), size, arqMsg_getSeq(dataPtr));
main_state = MAINSTATE_IDLE;//다시 수신대기 상태로 만든다.
flag_needPrint = 1;//출력될 데이터가 있다는 의미인 변수를 1로 만들어 준다.
arqEvent_clearEventFlag(arqEvent_dataRcvd);//arqEvent_dataRcvd =3 인데 이때 arqEvent_clearEventFlag 메서드 안에 들어있는
//비트 연산의 결과로 16진수 을 비트연산을 수행한과를 반환하는데
//eventFlag &= ~(0x01 << event); 근데 초기에 0으로 설정했기 때문에 다시 eventFlag변수에 0이 할당된다.
}
else if (arqEvent_checkEventFlag(arqEvent_dataToSend)) //if data needs to be sent (keyboard input)
{// arqEvent_dataToSend = 4,
//msg header setting
pduSize = arqMsg_encodeData(arqPdu, originalWord, seqNum, wordLen);//생성되는 pdu의 사이즈를 반환한다.
arqLLI_sendData(arqPdu, pduSize, dest_ID);
pc.printf("[MAIN] sending to %i (seq:%i)\n", dest_ID, (seqNum-1)%ARQMSSG_MAX_SEQNUM);//ARQMSSG_MAX_SEQNUM 로 모듈레이션 연산을 수행해준다.
main_state = MAINSTATE_TX;
flag_needPrint = 1;
wordLen = 0;
arqEvent_clearEventFlag(arqEvent_dataToSend);
}
else if (flag_needPrint == 1)
{
pc.printf("Give a word to send : ");
flag_needPrint = 0;
}
break;
if (arqEvent_checkEventFlag(arqEvent_dataRcvd))
위 문장에서 사용된 함수인 arqEvent_checkEventFlag()
의 경우 파라미터로 주어진 이벤트 상수값과 현재 이벤트 플래그에 저장된 값을 비교해서 정수 값을 반환하는 함수이고 이는 ARQ_FSMevent에 정의 되어 있다.
int arqEvent_checkEventFlag(arqEvent_e event)//현재발생하는 이벤트를 확인하는 함수
{
return (eventFlag & (0x01 << event));
}
위 함수는 파라미터로 주어진 이벤트를 비트 연산을 통해서 &연산을 적용해서 현재 이벤트를 저장하는 eventFlag 변수에 담겨있는 값과 비교를 수행한다.
이때 arqEvent_clearAllEventFlag();
함수를 호출해서 eventflag라는 변수에 0을 할당한다 main함수 초기 부분에 위 부분이 실행되어서
void arqEvent_clearAllEventFlag(void)//모든 이벤트 플레그를 0 으로 초기화하는 함수
{
eventFlag = 0;
}
eventFlag에 0을 저장한다.
따라서 제일 처음 if 문 if(arqEvent_checkEventFlag(arqEvent_dataRcvd))
문장이 실행된다면 내부에 eventFlag변수에 0이 저장되어 있으므로 0이 반환되어서(0은 불리언 타입의 거짓이므로) if 문이 실행되지 않는다. (arqEvent_dataRcvd = 3
) 이후의 두번째
else if(arqEvent_checkEventFlag(arqEvent_dataToSend))
문장도 첫번째와 동일한 이유로 실행되지 않는다 이후
else if (flag_needPrint == 1)
{
pc.printf("Give a word to send : ");
flag_needPrint = 0;
}
위 문장이 실행되는데 그 이유는 main 함수 내부의 선언 문이 다음과 같기 때문이다. uint8_t flag_needPrint=1;
이후 if문 내부의 출력에 따라서 “give a word to send”가 출력되에서 유저에게 보여지고 flag_needPrint = 0을 삽입한다. 이후 break 문을 나와서 switch문을 빠져나온다. 이후 사용자가 keyboard를 통해서 문자를 입력하면
void arqMain_processInputWord(void)
{
char c = pc.getc();//스트림에서 문자를 읽어옴.
if (main_state == MAINSTATE_IDLE &&
!arqEvent_checkEventFlag(arqEvent_dataToSend))//메인상태가 수신이 가능한 idel 이고, 보낼게 있다는 이벤트 플레그가 보낼게 있다는 것과 동일하지 않다면,
{
if (c == '\n' || c == '\r')//입력문자중에 엔터나 케리지 리턴 문자가 포함되어 있다면
{
originalWord[wordLen++] = '\0';//저장된 문자열 끝에 널문자를 삽입해서 문자열을 생성한다.
arqEvent_setEventFlag(arqEvent_dataToSend);//에벤트 플래그에 저장된 값을 바꾼다.
pc.printf("word is ready! ::: %s\n", originalWord);
}
else//엔터나 케리지 리턴 문자가 아니라면,
{
originalWord[wordLen++] = c;//문자를 오리지널 문자배열에 추가함,
if (wordLen >= ARQMSG_MAXDATASIZE-1)//전송하는 문자열의 길이가 최대 전송길이 보다 길다면,
{
originalWord[wordLen++] = '\0';//끝에 문자열을 널문자를 삽압해서 문자열을 완성하고
arqEvent_setEventFlag(arqEvent_dataToSend);//이벤트 플래그를 전송준비가 완료된것으로 변경한다.
pc.printf("\n max reached! word forced to be ready :::: %s\n", originalWord);//유저에게 길이를 넘어서 강제로 생성된 문자를 출력해서 알린다.
}
}
}
}
위 함수가 실행된다.
제일먼저 char c = pc.getc();//스트림에서 문자를 읽어옴.
를 통해서 스트림에서 문자하나를 읽어온다.
이후
if (main_state == MAINSTATE_IDLE &&
!arqEvent_checkEventFlag(arqEvent_dataToSend))//메인상태가 수신이 가능한 idel 이고,
int arqEvent_checkEventFlag(arqEvent_e event)//현재발생하는 이벤트를 확인하는 함수
{
return (eventFlag & (0x01 << event));
}
위 함수에 0을 대입하면 초기의 현재 저장되어있는 eventFlag값인 0과 arqEvent_dataToSend를 이용해서 다음 함수의 비트 연산을 적용하면 0이 반환된다 근데 위에 ‘!’ 연산자가 존재하기 때문에 if문의 조건은 참이 된다.
따라서 내부의 코드가 실행되면
if (c == '\n' || c == '\r')//입력문자중에 엔터나 케리지 리턴 문자가 포함되어 있다면
{
originalWord[wordLen++] = '\0';//저장된 문자열 끝에 널문자를 삽입해서 문자열을 생성한다.
arqEvent_setEventFlag(arqEvent_dataToSend);//에벤트 플래그에 저장된 값을 바꾼다.
pc.printf("word is ready! ::: %s\n", originalWord);
}
else//엔터나 케리지 리턴 문자가 아니라면,
{
originalWord[wordLen++] = c;//문자를 오리지널 문자배열에 추가함,
if (wordLen >= ARQMSG_MAXDATASIZE-1)//전송하는 문자열의 길이가 최대 전송길이 보다 길다면,
{
originalWord[wordLen++] = '\0';//끝에 문자열을 널문자를 삽압해서 문자열을 완성하고
arqEvent_setEventFlag(arqEvent_dataToSend);//이벤트 플래그를 전송준비가 완료된것으로 변경한다.
pc.printf("\n max reached! word forced to be ready :::: %s\n", originalWord);//유저에게 길이를 넘어서 강제로 생성된 문자를 출력해서 알린다.
}
사용자가 입력한 문자가 엔터나, 케리지 리턴 문자아 아닌 경우에는 uint8_t originalWord[200];
이 배열에 문자를 저장한다.
이후 사용자가 입력한 문장의 길이가 if (wordLen >= ARQMSG_MAXDATASIZE-1)
전송하는 문자열의 길이가 최대 전송길이 -1 보다 크거나 같다면, 즉 위 조건문을 만족한다면originalWord[wordLen++] = '\0';
끝에 문자열을 널문자를 삽압해서 문자열을 완성하고
arqEvent_setEventFlag(arqEvent_dataToSend);
eventFlag를 전송준비가 완료된것으로 변경한다.
pc.printf("\n max reached! word forced to be ready :::: %s\n", originalWord);
//유저에게 길이를 넘어서 강제로 생성된 문자를 출력해서 알린다.
그리고 함수의 로직에 의해서 사용자가 ‘enter’ 를 입력하거나 ‘케리지 리턴 문자’(\r)를 입력하거나 전송가능한 최대 문자길이를 입력하면 arqEvent_setEventFlag(*arqEvent_dataToSend*);//에벤트 플래그에 저장된 값을 바꾼다.
위 문장을 통해서 eventFlag에 저장된 값을 arqEvent_dataToSend= 4
를 인자로 전달해서 초기에 0이었던 eventFlag변수에 arqEvent_setEventFlag()
의 연산결과 16(이진수: 10000)을 저장한다.
이후 사용자에 의해서 “Hello”라는 문장을 만들었다고 가정하면 위 함수 실행의 결과 originalword[200]
배열에 “hello\0”이 한문자씩 저장되고 eventFlag에 16이 저장된다. 이후 pc.printf("word is ready! ::: %s\n", originalWord);
문장이 실행되먄서 사용자가 입력한 문장이 출력된다.
이후에 다시 반복문으로 돌아가면 evenFlag 변수에 16이 저장되어 있고 mainstate의 상태는 변화없이 idel 상태와 동일하다 이후 switch문에서 제일 처음 문장이 실행된다. 이때 if (arqEvent_checkEventFlag(arqEvent_dataRcvd))
이 문장의 내부 함수이 비트 연산 실행결과 0을 반환하므로 실행되지 않고 else if (arqEvent_checkEventFlag(arqEvent_dataToSend))
의 비트 연산결과 eventFlag 안에 저장되어있는 변수와 동일한 16이 반환되어서 else if 문장이 실행된다.
//msg header setting
pduSize = arqMsg_encodeData(arqPdu, originalWord, seqNum, wordLen);//생성되는 pdu의 사이즈를 반환한다.
arqLLI_sendData(arqPdu, pduSize, dest_ID);
pc.printf("[MAIN] sending to %i (seq:%i)\n", dest_ID, (seqNum-1)%ARQMSSG_MAX_SEQNUM);//ARQMSSG_MAX_SEQNUM 로 모듈레이션 연산을 수행해준다.
main_state = MAINSTATE_TX;//메인상태를 송신상태로 전환한다.
flag_needPrint = 1;//출력데이터를 표시하기 위해서 변수에 할당된 정수를 변환해 준다.
wordLen = 0;//단어의 길이를 0으로 젼환한다.메세지를 전성한 후에 배열을 초기화 하는 연산을 수행함
arqEvent_clearEventFlag(arqEvent_dataToSend);//
}
위의 문장이 실행되면
uint8_t arqMsg_encodeData(uint8_t* msg_data, uint8_t* data, int seq, int len)
{
msg_data[ARQMSG_OFFSET_TYPE] = ARQMSG_TYPE_DATA;
msg_data[ARQMSG_OFFSET_SEQ] = seq;
memcpy(&msg_data[ARQMSG_OFFSET_DATA], data, len*sizeof(uint8_t));
return len+ARQMSG_OFFSET_DATA;
}
전달된 파라미터에 따라서 위의 함수가 실행된다. arqMsg_encodeData(arqPdu, originalWord, seqNum, wordLen);
이 문장이 실행되면서 arqPdu, originalWord 의 배열의 주솟값이 전달되고 생성된 문자의 길이(wordLen)과 seqNum이 전달된다. 따라서 msg_data[ARQMSG_OFFSET_TYPE] = ARQMSG_TYPE_DATA;
의 실행결과 arqPdu
[0] = 0, arqPdu[1] = 0, memcpy()가 실행되면서 arqPdu에 originalWord 배열에 저장된 메모리가 복사된다. 위의 경우에는 arqPdu세번째 원소 부터 Hello가 저장된다. 띠라서 본 함수가 반환하는 정수는 “hello”를 전송하는 경우에는 ARQMSG_OFFSET_DATA = 2, wordLen = 6
이므로 따라서 8이 반환된다.
이후 이 함수가 실행되면서 arqLLI_sendData(arqPdu, pduSize, dest_ID);
void arqLLI_sendData(uint8_t* msg, uint8_t size, uint8_t dest)
{
phymac_dataReq(msg, size, dest);
txType = msg[ARQMSG_OFFSET_TYPE];//전송하는 데이터 타입을 지정해줌
}
파라마터로 전달된 arqPdu, pduSize = 8, dest_ID = 2
이므로
int phymac_dataReq(uint8_t* dataPtr, uint8_t size, uint8_t destId);
이 함수를 통해서 생성된 pdu배열의 전송을 LOWER LAYER에게 요청한다.
pc.printf("[MAIN] sending to %i (seq:%i)\n", dest_ID, (seqNum-1)%ARQMSSG_MAX_SEQNUM);//ARQMSSG_MAX_SEQNUM 로 모듈레이션 연산을 수행해준다.
main_state = MAINSTATE_TX;//메인상태를 송신으로 전환하는 것으 ㄹ실행한다
flag_needPrint = 1;//출력데이터를 표시하기 위해서 변수에 할당된 정수를 변환해 준다.
wordLen = 0;//단어의 길이를 0으로 젼환한다.메세지를 전성한 후에 배열을 초기화 하는 연산을 수행함
arqEvent_clearEventFlag(arqEvent_dataToSend);//
이후 유저에게 전송하는 메세지의 seqnum과 destID를 추력해주고 flag_needPrint = 1;
변수에 1을 할당한다. 이후 메세지를 전송했으므로 길이를 다시 wordLen = 0;
으로 바꾸어 준다. 또한 이 코드를 통해서 (main_state = MAINSTATE_TX;
)FSM을 바꾸어 준다. 이후 arqEvent_clearEventFlag(arqEvent_dataToSend);을 실행하면
void arqEvent_clearEventFlag(arqEvent_e event)//이벤트 플래그를 초기화하는 함수
{
eventFlag &= ~(0x01 << event);//eventFlag에 비트연산을 적용한 결과를 저장한다.
}
위의 비트연산이 실행되고 연산의 실행결과 전 과정에서 16이 eventFlag안에 저장되어 있었으므로 연산을 실행한 결과 0이 eventFlag에 저장되게 된다.
이후 데이터의 전송이 완료되면 아래의 함수가 실행된다
void arqLLI_dataCnfFunc(int err)
{
if (txType == ARQMSG_TYPE_DATA)//송신하는 측의 데이터 타입이 데이터일 경우에
{
arqEvent_setEventFlag(arqEvent_dataTxDone);//arqEvent_dataTxDone을 현제 이벤트로 설정함
}
else if (txType == ARQMSG_TYPE_ACK)//송신하는 측의 데이터가 아크일 경우에
{
arqEvent_setEventFlag(arqEvent_ackTxDone);
}
}
따라서 본 실습의 경우에는 ACK는 다루지 않는다 따라서 이에 따라서 첫번째 if 문이 실행이된다.
arqEvent_setEventFlag(arqEvent_dataTxDone);
이 함수가 실행이 되면 eventFlag가 1이 된다. 이후
``
case MAINSTATE_TX: //IDLE state description
if (arqEvent_checkEventFlag(arqEvent_dataTxDone)) //data TX finished
{
main_state = MAINSTATE_IDLE;
arqEvent_clearEventFlag(arqEvent_dataTxDone);
}
break;
이후에 반복문에 의해서 다시 switch 문이 실행되고 mainstate가 MAINSTATE_TX이므로 위의 case문장이 실행된다. 이후에 if 문이 실행되는데 이 때 전 반복문에서 eventFlag에 1이 저장 되어 있다. 따라서 이를 다시 if 조건문의 비트 연산을 실행하면 arqEvent_dataTxDone = 0 이므로 arqEvent_checkEventFlag(arqEvent_dataTxDone)
이 반환하는 값은 1이다 따라서 조건문이 실행이 일어나고
main_state = MAINSTATE_IDLE; arqEvent_clearEventFlag(arqEvent_dataTxDone);
이 실행이 되면 다시 수신가능한 상태로 전환된다.
typedef enum arqEvent
{
arqEvent_dataTxDone= 0,//데이터를 보냈다
arqEvent_ackTxDone= 1,//데이터를 보내고 아크를 받는 과정이 끝났다
arqEvent_ackRcvd= 2,//에크의 수신이 끝났다
arqEvent_dataRcvd= 3,//데이터를 받았다
arqEvent_dataToSend= 4,//데이터를 보낼것이 발생했을 때 발생하는 함수
arqEvent_arqTimeout= 5//아크를 받는 타이머가 시간이 지났을 때 발생하는 이벤트.
} arqEvent_e;
이벤트 플레그에 저장되어있는 데이터
fig. 1. TX실습결과 사진
실습결과 pdu를 전송하는 과정에서 데이터의 sequenceNum이 -1인 것을 알 수 있다.
Tx측과 마친가지로 nodeID, destID를 설정하고 나면 MAINSTATE_IDLE 상태가 되고 수신을 대기 하는 상태가 되는데 이때 초기 설정에 의해서 mainstate = 0, eventFlag = 0 이다 하지만 이 때 TX측에서 보낸 pdu가 수신되면
void arqLLI_dataIndFunc(uint8_t srcId, uint8_t* dataPtr, uint8_t size)
{
debug_if(DBGMSG_ARQ, "\n --> DATA IND : src:%i, size:%i\n", srcId, size);
memcpy(rcvdData, dataPtr, size*sizeof(uint8_t));
rcvdSrc = srcId;
rcvdSize = size;
//ready for ACK TX
if (arqMsg_checkIfData(dataPtr))
{
arqEvent_setEventFlag(arqEvent_dataRcvd);
}
else if (arqMsg_checkIfAck(dataPtr))
{
arqEvent_setEventFlag(arqEvent_ackRcvd);
}
}
이 함수가 실행이 되면서 pdu의 데이터를 읽는다 이때 이 함수는 파라미터로 전달받은 pdu를 저장하는 배열인 uint8_t* dataPtr
에 데이터를 저장한다. memcpy(rcvdData, dataPtr, size*sizeof(uint8_t)) ;
이 함수가 실행이되면 이는 배열의 저장된 메모리 값을 복사해서 저장하는 함수이다 따라서 rcvdData 배열에 수신받은 배열인 dataPtr의 메모리 값이 복사되어서 저장된다. size*sizeof(uint8_t)
이 파라미타는 배열에서 복사할 범위를 지정하기 위해서 사용한다. “Hello”를 수신한 경우에는 전송된 pdu의 길이가 8이므로 따라서 8개의 배열의 원소를 읽어오게 된다. 이후 전달받은 rcvdSrc = srcId; rcvdSize = size;
문장이 실행되면서 수시한 pdu의 id와 사이즈를 각각 변수에 저장한다.
이때 main 함수의 while문장에서 실행되는 case MAINSTATE_IDLE:
이 실행이되고 그중에서도
if (arqEvent_checkEventFlag(arqEvent_dataRcvd)) //if data reception event happens 데이터 수신이 일어나면
{
//Retrieving data info.
uint8_t srcId = arqLLI_getSrcId();//수신한 src의 아이디를 반환하는 함수를 이용해서 scrId 변수에 저장한다.
uint8_t* dataPtr = arqLLI_getRcvdDataPtr();//수신한 data의 출력할 부분을 받는다.
uint8_t size = arqLLI_getSize();//입력받은 데이터의 크기를 반환한다.
pc.printf("\n -------------------------------------------------\nRCVD from %i : %s (length:%i, seq:%i)\n -------------------------------------------------\n",
srcId, arqMsg_getWord(dataPtr), size, arqMsg_getSeq(dataPtr));
main_state = MAINSTATE_IDLE;//다시 수신대기 상태로 만든다.
flag_needPrint = 1;
arqEvent_clearEventFlag(arqEvent_dataRcvd);
}
위의 코드가 실행이 된다. 이후 각변수에 수신한 pdu의 정보가 저장된다.
uint8_t srcId = arqLLI_getSrcId();//수신한 src의 아이디를 반환하는 함수를 이용해서 scrId 변수에 저장한다.
uint8_t* dataPtr = arqLLI_getRcvdDataPtr();//수신한 data의 출력할 부분을 받는다.
uint8_t size = arqLLI_getSize();//입력받은 데이터의 크기를 반환한다.
각 함수에 반환값에 맞게 변수에 데이터가 저장되고
c.printf("\n -------------------------------------------------\nRCVD from %i : %s (length:%i, seq:%i)\n -------------------------------------------------\n",
srcId, arqMsg_getWord(dataPtr), size, arqMsg_getSeq(dataPtr));
사용자에게 전달받은 데이터의 길이와 내용을 출력한다 이후
main_state = MAINSTATE_IDLE;//다시 수신대기 상태로 만든다.
flag_needPrint = 1;//출력될 데이터가 있다는 의미인 변수를 1로 만들어 준다.
arqEvent_clearEventFlag(arqEvent_dataRcvd);
위의 문장이 실행이 되면서 수신대기 상태로 돌아간다.
arqEvent_clearEventFlag(arqEvent_dataRcvd);
또한 이 문장이 실행이 되면서 다시 eventFlag에 삽입이 된다. 이후에 반복문을 계속해서 실행된다.
fig. 2. 실습결과 사진
위의 실습결과에서 수신한 HELLO가 pdu의 길이와 함께 출력된 것을 알 수 있다.