ENC28J60 прекращает прием

В настоящее время я использую stm32f405 и ENC28J60 и lwip в качестве стека tcp/ip. При запуске все работает нормально, но примерно через минуту или около того ENC перестает получать пакеты. Передача продолжает работать нормально. Я пробовал как опрашивать, так и использовать прерывания.

Я использую https://github.com/wolfgangr/enc28j60 для связи с ENC. А это код, который обрабатывает входящие пакеты:

while (true) {

eventmask_t mask = chEvtWaitAnyTimeout(ALL_EVENTS, LWIP_PACKET_POLL_INTERVAL);

if(mask & ENC_INTERRUPT_ID)
{
  /* Handle ENC28J60 interrupt */
  ENC_IRQHandler(&encHandle);
  /* Reenable interrupts */
  ENC_EnableInterrupts(EIE_INTIE);
}

if (mask & PERIODIC_LINK_TIMER_ID)
{
  bool current_link_status = ((encHandle.LinkStatus) & PHSTAT2_LSTAT) != 0;

  if (current_link_status != prev_link_status) {
    if (current_link_status) {
      dhcp_start(&thisif);
    }
    else {
      dhcp_stop(&thisif);
    }
  }
  prev_link_status = current_link_status;
}

/* Check if new frames where received */
struct pbuf *p;

while ((p = low_level_input(&thisif)) != NULL) {

  struct eth_hdr *ethhdr = p->payload;
  switch (htons(ethhdr->type)) {
  /* IP or ARP packet? */
  case ETHTYPE_IP:
  case ETHTYPE_ARP:

    /* full packet send to tcpip_thread to process */
    if (tcpip_input(p, &thisif) == ERR_OK)
      break;
    LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
  default:
    pbuf_free(p);
  }
}
}

Функция low_level_input:

static struct pbuf *low_level_input(struct netif *netif) {
struct pbuf *p = NULL;
struct pbuf *q;
uint16_t len;
uint8_t *buffer;
uint32_t bufferoffset = 0;

if (!ENC_GetReceivedFrame(&encHandle)) {
  return NULL;
}

/* Obtain the size of the packet and put it into the "len" variable. */
len = encHandle.RxFrameInfos.length;
buffer = (uint8_t *)encHandle.RxFrameInfos.buffer;

if (len > 0)
{
  /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
  p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
}

if (p != NULL)
{
  bufferoffset = 0;

  for(q = p; q != NULL; q = q->next)
  {
    /* Copy data in pbuf */
    memcpy( (uint8_t*)((uint8_t*)q->payload), (uint8_t*)((uint8_t*)buffer + bufferoffset), q->len);
    bufferoffset = bufferoffset + q->len;
  }
}

return p;
}

Через некоторое время функция ENC_GetReceivedFrame продолжает возвращать false, даже если я точно знаю, что некоторые пакеты должны были быть получены. Я отладил функцию (найденную в enc28j60.c) и эту строку:

pktcnt = enc_rdbreg(handle, ENC_EPKTCNT);

pktcnt всегда равен 0. Я проверил шину SPI с помощью логического анализатора, и ENC действительно дает 0. Шина SPI работает нормально.

Непосредственно перед этим принимаются некоторые пакеты, которые не помечены как RXSTAT_OK (см. строку 1259 в enc28j60.c).

Я был в этом в течение дня, и у меня действительно не осталось идей.


person rmmed    schedule 26.05.2017    source источник


Ответы (1)


Я столкнулся с похожей проблемой. Регистр EPKTCNT время от времени уменьшался без причины (без установки бита ECON2_PKTDEC). Я заметил, что это произошло после установки бита ECON2_AUTOINC. Не каждый раз, когда ECON2_AUTOINC был установлен, но часто.

Я просто установил ECON2_AUTOINC при инициализации ENC28J60, не более во время процесса чтения. Так как EPKTCNT перестал снижаться без причины.

Надеюсь, это может помочь

person Jean-Henri Delmotte    schedule 25.06.2018