self made protocol

박진은·2022년 5월 5일
0

컴퓨터 네트워크

목록 보기
1/12

TX 설명

  1. src 노드의 ID가 1이고 dest 노드의 ID가 2이고 src에서 dest노들로 “hello” 라는 메세지를 보내는 경우의 모든 코드 동작을 설명하시오

메인함수가 실행되어서 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이 반환된다.

  • memcpy()함수에 대한 설명: void memcpy (void dest, const void source, size_t num), 첫번째 인자 void dest= 복사 받을 메모리를 가리키는 포인터, 두번째 인자 const void* source= 복사할 메모리를 가리키고 있는 포인터, 세번째 인자 size_t num= 복사할 데이터(값)의 길이(바이트 단위) 배열에 저장된 메모리가 복사되어서 저장된다.

이후 이 함수가 실행되면서 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실습결과 사진

fig. 1. TX실습결과 사진

실습결과 pdu를 전송하는 과정에서 데이터의 sequenceNum이 -1인 것을 알 수 있다.

RX설명

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. 실습결과 사진

fig. 2. 실습결과 사진

위의 실습결과에서 수신한 HELLO가 pdu의 길이와 함께 출력된 것을 알 수 있다.

profile
코딩

0개의 댓글