В настоящее время я использую 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).
Я был в этом в течение дня, и у меня действительно не осталось идей.