Skip to content

Commit a993582

Browse files
committed
Resolve M487 EMAC bus error by bus reset
1 parent e4b81f6 commit a993582

File tree

3 files changed

+53
-9
lines changed

3 files changed

+53
-9
lines changed

features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/TARGET_M480/m480_eth.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,27 @@
1818
*/
1919
#include "m480_eth.h"
2020
#include "mbed_toolchain.h"
21+
#define NU_TRACE
2122
#include "numaker_eth_hal.h"
2223

2324
#define ETH_TRIGGER_RX() do{EMAC->RXST = 0;}while(0)
2425
#define ETH_TRIGGER_TX() do{EMAC->TXST = 0;}while(0)
2526
#define ETH_ENABLE_TX() do{EMAC->CTL |= EMAC_CTL_TXON;}while(0)
26-
#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON;}while(0)
27+
#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON_Msk;}while(0)
2728
#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0)
28-
#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON;}while(0)
29+
#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON_Msk;}while(0)
2930

31+
#define EMAC_ENABLE_INT(emac, u32eIntSel) ((emac)->INTEN |= (u32eIntSel))
32+
#define EMAC_DISABLE_INT(emac, u32eIntSel) ((emac)->INTEN &= ~ (u32eIntSel))
3033

3134
MBED_ALIGN(4) struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];
3235
MBED_ALIGN(4) struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];
3336

3437
struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr;
3538

39+
__attribute__ ((section("EMAC_RAM")))
3640
MBED_ALIGN(4) uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
41+
__attribute__ ((section("EMAC_RAM")))
3742
MBED_ALIGN(4) uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
3843

3944
eth_callback_t nu_eth_txrx_cb = NULL;
@@ -162,7 +167,7 @@ static void init_rx_desc(void)
162167
rx_desc[i].status1 = OWNERSHIP_EMAC;
163168
rx_desc[i].buf = &rx_buf[i][0];
164169
rx_desc[i].status2 = 0;
165-
rx_desc[i].next = &rx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
170+
rx_desc[i].next = &rx_desc[(i + 1) % RX_DESCRIPTOR_NUM];
166171
}
167172
EMAC->RXDSA = (unsigned int)&rx_desc[0];
168173
return;
@@ -261,6 +266,11 @@ void numaker_eth_init(uint8_t *mac_addr)
261266
EMAC_CAMCTL_AMP_Msk |
262267
EMAC_CAMCTL_ABP_Msk;
263268
EMAC->CAMEN = 1; // Enable CAM entry 0
269+
/* Limit the max receive frame length to 1514 + 4 */
270+
EMAC->MRFL = 1518;
271+
272+
/* Set RX FIFO threshold as 8 words */
273+
EMAC->FIFOCTL = 0x00200100;
264274

265275
reset_phy();
266276

@@ -281,20 +291,22 @@ unsigned int m_status;
281291

282292
void EMAC_RX_IRQHandler(void)
283293
{
284-
// NU_DEBUGF(("%s ... nu_eth_txrx_cb=0x%x\r\n", __FUNCTION__, nu_eth_txrx_cb));
285294
m_status = EMAC->INTSTS & 0xFFFF;
286295
EMAC->INTSTS = m_status;
287296
if (m_status & EMAC_INTSTS_RXBEIF_Msk) {
288297
// Shouldn't goes here, unless descriptor corrupted
289-
NU_DEBUGF(("RX descriptor corrupted \r\n"));
290-
//return;
298+
mbed_error_printf("### RX Bus error [0x%x]\r\n", m_status);
299+
if (nu_eth_txrx_cb != NULL) nu_eth_txrx_cb('B', nu_userData);
300+
return;
291301
}
302+
EMAC_DISABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk));
292303
if (nu_eth_txrx_cb != NULL) nu_eth_txrx_cb('R', nu_userData);
293304
}
294305

295306

296307
void numaker_eth_trigger_rx(void)
297308
{
309+
EMAC_ENABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk));
298310
ETH_TRIGGER_RX();
299311
}
300312

@@ -313,6 +325,12 @@ int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf)
313325
if (status & RXFD_RXGD) {
314326
*buf = cur_rx_desc_ptr->buf;
315327
*len = status & 0xFFFF;
328+
if( *len > 1514 ) {
329+
NU_DEBUGF(("%s... unexpected long packet length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf));
330+
331+
*len = 0; // Skip this unexpected long packet
332+
}
333+
if( *len == 1514 ) NU_DEBUGF(("%s... length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf));
316334
}
317335
return 0;
318336
}
@@ -331,6 +349,8 @@ void EMAC_TX_IRQHandler(void)
331349
EMAC->INTSTS = status;
332350
if(status & EMAC_INTSTS_TXBEIF_Msk) {
333351
// Shouldn't goes here, unless descriptor corrupted
352+
mbed_error_printf("### TX Bus error [0x%x]\r\n", status);
353+
if (nu_eth_txrx_cb != NULL) nu_eth_txrx_cb('B', nu_userData);
334354
return;
335355
}
336356

features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/numaker_emac.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ extern "C" void numaker_eth_rx_next(void);
4848
/* \brief Flags for worker thread */
4949
#define FLAG_TX 1
5050
#define FLAG_RX 2
51+
#define FLAG_BUS_RESET 4
5152

5253
/** \brief Driver thread priority */
5354
#define THREAD_PRIORITY (osPriorityNormal)
@@ -82,6 +83,13 @@ void NUMAKER_EMAC::rx_isr()
8283
}
8384
}
8485

86+
void NUMAKER_EMAC::bus_isr()
87+
{
88+
if (thread) {
89+
osThreadFlagsSet(thread, FLAG_BUS_RESET);
90+
}
91+
}
92+
8593
void NUMAKER_EMAC::tx_isr()
8694
{
8795
/* No-op at this stage */
@@ -98,6 +106,8 @@ void NUMAKER_EMAC::ethernet_callback(char event, void *param)
98106
case 'T': //For TX event
99107
enet->tx_isr();
100108
break;
109+
case 'B': // For BUS event
110+
enet->bus_isr();
101111
default:
102112
break;
103113
}
@@ -172,10 +182,13 @@ void NUMAKER_EMAC::thread_function(void* pvParameters)
172182
static struct NUMAKER_EMAC *nu_enet = static_cast<NUMAKER_EMAC *>(pvParameters);
173183

174184
for (;;) {
175-
uint32_t flags = osThreadFlagsWait(FLAG_RX, osFlagsWaitAny, osWaitForever);
185+
uint32_t flags = osThreadFlagsWait(FLAG_RX | FLAG_BUS_RESET, osFlagsWaitAny, osWaitForever);
176186

177187
if (flags & FLAG_RX) {
178188
nu_enet->packet_rx();
189+
} else if (flags & FLAG_BUS_RESET) {
190+
NU_DEBUGF(("RX BUS error and reset bus\r\n"));
191+
nu_enet->bus_reset();
179192
}
180193
}
181194
}
@@ -304,7 +317,7 @@ bool NUMAKER_EMAC::power_up()
304317
return false;
305318

306319
/* Worker thread */
307-
thread = create_new_thread("numaker_emac_thread", &NUMAKER_EMAC::thread_function, this, THREAD_STACKSIZE, THREAD_PRIORITY, &thread_cb);
320+
thread = create_new_thread("numaker_emac_thread", &NUMAKER_EMAC::thread_function, this, THREAD_STACKSIZE * 2, THREAD_PRIORITY, &thread_cb);
308321

309322
/* PHY monitoring task */
310323
phy_state = PHY_UNLINKED_STATE;
@@ -317,6 +330,15 @@ bool NUMAKER_EMAC::power_up()
317330
return true;
318331
}
319332

333+
bool NUMAKER_EMAC::bus_reset()
334+
{
335+
/* Initialize the hardware */
336+
if (!low_level_init_successful())
337+
return false;
338+
numaker_eth_enable_interrupts();
339+
return true;
340+
}
341+
320342

321343
uint32_t NUMAKER_EMAC::get_mtu_size() const
322344
{

features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/numaker_emac.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,11 @@ class NUMAKER_EMAC : public EMAC {
151151
bool low_level_init_successful();
152152
void tx_isr();
153153
void rx_isr();
154+
void bus_isr();
154155
void packet_rx();
156+
bool bus_reset();
155157
int low_level_input(emac_mem_buf_t **buf);
156-
static void thread_function(void* pvParameters);
158+
static void thread_function(void *pvParameters);
157159
void phy_task();
158160
static void ethernet_callback(char event, void *param);
159161

0 commit comments

Comments
 (0)