W5100 TCP 통신 중 간헐적으로 이전 데이터가 써지는 문제

안녕하세요.

DSP28335 와 WIZ811MJ 모듈을 가지고 개발하는 개발자입니다.

소켓 0 를 통해 2048byte를 dSP28335 에서 PC로 데이터를 송신하는 펌웨어를 구성하였습니다.

보내고자 하는 데이터가 16bit 데이터를 송신하는데 간헐적으로 데이터가 송신이 안되는 경우가 발생을 합니다.

데이터 패킷 상위 8bit 하위 8bit 이렇게 송신을 합니다.

예를 들면

DSP 송신 :

0x01 0xAB 0x01 0xAB 0x01 0xAB 0x01 0xAB 0x01 0xAB 0x01 0xAB 0x01 0xAB : 2048 바이트

PC 수신 :

0x01 0xAB 0x01 0xAB 0x01 0xAB 0x01 0xAB 0xAB 0xAB 0x01 0xAB 0x01 0xAB : 2048 바이트

PC 측 수신에서 0x01 0xAB 값이 수신이 되다가 0xAB 0XAB 이값이 수신이 됩니다.

매번 생기는 증상은 아니고, 간헐적으로 생기고, 한번 생기기 시작하면 2048 중에서 특정한 위치에서 동일하게 발생 합니다.

PC 수신측은 작성한 프로그램으로 받아도 동일한 증상이고, wire shark 프로그램으로 받아도 동일한 증상입니다.

제가 구현한 소스는 W5100_ATMega_WEBSERV-master 프로그램을 수정하였습니다.

하드웨어 환경은 SPI 클럭 10Mhz 입니다.

TCP sever 함수는 아래와 같습니다.

void W5100_TCP_SOCKET_Flow(void)
{
    mysocketstate = W51_read(sockaddr+W5100_SR_OFFSET);
    switch  (mysocketstate)        // based on current status of socket...
    {
    case  W5100_SKT_SR_CLOSED:                      // if socket is closed...
        if (OpenSocket(mysocket, W5100_SKT_MR_TCP, HTTP_PORT) == mysocket)      // if successful opening a socket...
        {
            socketreconnectcounter++;
            Listen(mysocket);
            DELAY_US(1000);
        }
    break;
    case  W5100_SKT_SR_ESTABLISHED:                 // if socket connection is established...
        if(RECT.DMADataSendFlag)
        {
            if(DMAFlagCount > 4)
            {
                DMAFlagCountdisplay = DMAFlagCount;
                DMAFlagCount = 0;
                switch(DMASendFlag)
                {
                case SENDPING:

                    DMASendFlag = SENDSTOP;
                    datasendstate = Send16(mysocket, ADC_RESULT, sizeof(ADC_RESULT));

                    break;
                case SENDPONG:
                    DMASendFlag = SENDSTOP;
                    datasendstate = Send16(mysocket, ADC_RESULT_BUFF, sizeof(ADC_RESULT_BUFF));
                    break;
                case SENDSTOP:
                    break;
                default :
                    break;
                }
            }

        }
        else
        {
            DMASendFlag = SENDSTOP;
        }
    break;
    case  W5100_SKT_SR_FIN_WAIT:
    case  W5100_SKT_SR_CLOSING:
    case  W5100_SKT_SR_TIME_WAIT:
    case  W5100_SKT_SR_CLOSE_WAIT:
    case  W5100_SKT_SR_LAST_ACK:
        DisconnectSocket(mysocket);
        CloseSocket(mysocket);
    break;
    }
}

send 구현 함수는 아래와 같습니다.

Uint8 Send16(Uint8  sock, const Uint16  *buf, Uint16  buflen)
{
    Uint16  ptr;
    Uint16  offaddr;
    Uint16  realaddr;
    Uint16  txsize;
    Uint16  timeout;
    Uint16  sockaddr;
//    GPIO0_ON;
//    Uint16  DMASendFlagState;
    // ----------------------(1)   1msec -------------------------------------------------------------------
    if (buflen == 0 || sock >= W5100_NUM_SOCKETS)  return  W5100_FAIL;      // ignore illegal requests
    sockaddr = W5100_SKT_BASE(sock);                                        // calc base addr for this socket
    // Make sure the TX Free Size Register is available
    txsize = W51_read(sockaddr+W5100_TX_FSR_OFFSET);                        // make sure the TX free-size reg is available
    txsize = (((txsize & 0x00FF) << 8 ) + W51_read(sockaddr+W5100_TX_FSR_OFFSET + 1));

    timeout = 0;
    while (txsize < buflen)
    {
//        DELAY_US(10);
        txsize = W51_read(sockaddr+W5100_TX_FSR_OFFSET);        // make sure the TX free-size reg is available
        txsize = (((txsize & 0x00FF) << 8 ) + W51_read(sockaddr+W5100_TX_FSR_OFFSET + 1));
        if (timeout++ > 1000)                       // if max delay has passed...
        {
            DisconnectSocket(sock);                 // can't connect, close it down
            return  W5100_FAIL;                     // show failure
        }
    }
   // Read the Tx Write Pointer
    ptr = W51_read(sockaddr+W5100_TX_WR_OFFSET);
    offaddr = (((ptr & 0x00FF) << 8 ) + W51_read(sockaddr+W5100_TX_WR_OFFSET + 1));
    //------------------(1) 1msec end ------------------------------------------------------------------------
    while (buflen)
    {
        buflen--;
        realaddr = W5100_TXBUFADDR + (offaddr & W5100_TX_BUF_MASK);     // calc W5100 physical buffer addr for this socket

        static Uint8 tmp;
        tmp = *buf & 0x00FF;
        W51_write(realaddr, tmp);                  // send a upper byte of application data to TX buffer
        offaddr++;                                  // next TX buffer addr
        tmp = ((*buf) >> 8)&0x00FF;
        W51_write(realaddr+1, tmp);                  // send a lower byte of application data to TX buffer
        offaddr++;                                  // next TX buffer addr
        buf++;                                      // next input buffer addr
        if(DMASendFlag)
        {
//            return DMA_OVERFLOW;
        }
    }

    W51_write(sockaddr+W5100_TX_WR_OFFSET, (offaddr & 0xFF00) >> 8);    // send MSB of new write-pointer addr
    W51_write(sockaddr+W5100_TX_WR_OFFSET + 1, (offaddr & 0x00FF));     // send LSB

    W51_write(sockaddr+W5100_CR_OFFSET, W5100_SKT_CR_SEND); // start the send on its way
    while (W51_read(sockaddr+W5100_CR_OFFSET))  ;   // loop until socket starts the send (blocks!!)
//    GPIO0_OFF;
    return  W5100_OK;
}

검토 의견 부탁드립니다.

다른 데이터를 쓰더라도 전혀 다른 데이터를 송신하는 것이아니라 이전 데이터를 송신합니다.

즉 0x01 0x34 이렇게 송신하면 수신측에서 간헐적으로 0x34 0x34 이렇게 수신합니다.

DSP28335에서 주는 데이터를 ADC_RESULT의 buf에 저장해서 Send동작을 할때 WIZ811mj로 보내지는 것으로 보입니다.

ADC_RESULT에 제대로된 값이 저장되었는지, SEND16을 했을때, TX buffer addr와 정확한 값이 전송되는지 확인해야할것 같습니다.

ADC_RESULT의 내용이 정상이라면, SEND16을 이용했을때 TX buffer addr 값이 이상하지 않았나 생각이 듭니다.

한번확인해보시고 알려주세요.