Lav et Ethernet loopback med FreeRtos ogLWIP

Vores produkt har et Ethernet interface, og vi har et ønske om at kunne lave en selftest af dette interface ved, at lave et loopback i PHY’en, så sende en pakke på interfacet, og checke at vi modtager den samme pakke.

Vi bruger LWIP og FreeRtos, og nedenstående kode viser hvordan en sådan selftest kan laves.

static const char loopbackFrame[] = "Sending loopback test frame";
static const uint16_t frameSize = sizeof(loopbackFrame);
static testResult_e ethernetSelfTestLastResult = FAILED;

// Call whenever a frame is received according to the bind in ethernetSelftest()
static void checkLoopbackFrameRecv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr,  u16_t port) {
    if (memcmp  (loopbackFrame, p->payload, frameSize) == 0) {
        ethernetSelfTestLastResult = PASSED;
    } else {
         ethernetSelfTestLastResult = FAILED;
    }
}

static void bindLoopBackFrame(struct udp_pcb *rxPcb) {
     udp_recv(rxPcb, checkLoopbackFrameRecv, NULL);
     udp_bind(rxPcb, IP_ADDR_ANY, 9090);
}

static void sendLoopbackFrame(struct udp_pcb* txPcb) {
    struct pbuf* b = pbuf_alloc(PBUF_TRANSPORT, frameSize, PBUF_RAM);
    memcpy(b->payload, loopbackFrame, frameSize);
    err_t err = udp_sendto(txPcb, b, IP_ADDR_BROADCAST, 9090);
    pbuf_free(b);
    vTaskDelay(100); // Make sure that frame is transmitted before continuing the test
    TRACE("ethernet", T_E, "Frame Tx - err:%d, Result:%d", err, ethernetSelfTestLastResult);
}

testResult_e ethernetSelftest() {
    struct udp_pcb *rxPcb = udp_new();
    struct udp_pcb *txPcb = udp_new();

    if (rxPcb == NULL || txPcb == NULL) {
        return FAILED;
    }

    bindLoopBackFrame(rxPcb);
    loopback(true);
    sendLoopbackFrame(txPcb);
    loopback(false);

    udp_remove(txPcb);
    udp_remove(rxPcb);

    return ethernetSelfTestLastResult;
}

 
 Og loopback functionen lagt i ethernetif.c filen

void loopback(bool enable) {
   // Must clear PHY_AUTONEGOTIATION before setting LOOPBACK, see datasheet (dp83848c.pdf) section 6.3.4
   HAL_ETH_WritePHYRegister(&heth, PHY_BCR, 0);
   if (enable) {
       HAL_ETH_WritePHYRegister(&heth, PHY_BCR, PHY_LOOPBACK);
    } else {
        HAL_ETH_WritePHYRegister(&heth, PHY_BCR, PHY_AUTONEGOTIATION);
    }
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *