Skip to content

Commit 857819f

Browse files
Merge pull request #4996 from kjbracey-arm/k64f_emac_1thread
Reduce K64F Ethernet driver to 1 thread
2 parents 34d41c5 + 65639e8 commit 857819f

File tree

1 file changed

+87
-69
lines changed
  • features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale

1 file changed

+87
-69
lines changed

features/FEATURE_LWIP/lwip-interface/lwip-eth/arch/TARGET_Freescale/k64f_emac.c

Lines changed: 87 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -52,24 +52,32 @@ extern void k66f_init_eth_hardware(void);
5252
/* K64F EMAC driver data structure */
5353
struct k64f_enetdata {
5454
struct netif *netif; /**< Reference back to LWIP parent netif */
55-
sys_sem_t RxReadySem; /**< RX packet ready semaphore */
56-
sys_sem_t TxCleanSem; /**< TX cleanup thread wakeup semaphore */
55+
osThreadId_t thread; /**< Processing thread */
5756
sys_mutex_t TXLockMutex; /**< TX critical section mutex */
5857
sys_sem_t xTXDCountSem; /**< TX free buffer counting semaphore */
5958
uint8_t tx_consume_index, tx_produce_index; /**< TX buffers ring */
6059
};
6160

6261
static struct k64f_enetdata k64f_enetdata;
6362

64-
/** \brief Driver transmit and receive thread priorities
65-
*
66-
* Thread priorities for receive thread and TX cleanup thread. Alter
67-
* to prioritize receive or transmit bandwidth. In a heavily loaded
68-
* system or with LEIP_DEBUG enabled, the priorities might be better
69-
* the same. */
70-
#define RX_PRIORITY (osPriorityNormal)
71-
#define TX_PRIORITY (osPriorityNormal)
72-
#define PHY_PRIORITY (osPriorityNormal)
63+
/* \brief Flags for worker thread */
64+
#define FLAG_TX 1
65+
#define FLAG_RX 2
66+
67+
/** \brief Driver thread priority */
68+
#define THREAD_PRIORITY (osPriorityNormal)
69+
70+
#ifdef LWIP_DEBUG
71+
#define THREAD_STACKSIZE (DEFAULT_THREAD_STACKSIZE * 5)
72+
#else
73+
#define THREAD_STACKSIZE DEFAULT_THREAD_STACKSIZE
74+
#endif
75+
76+
static void k64f_phy_task(void *data);
77+
static void packet_rx(struct k64f_enetdata *k64f_enet);
78+
static void packet_tx(struct k64f_enetdata *k64f_enet);
79+
80+
#define PHY_TASK_PERIOD_MS 200
7381

7482
/********************************************************************************
7583
* Buffer management
@@ -132,12 +140,12 @@ static void k64f_tx_reclaim(struct k64f_enetdata *k64f_enet)
132140
*/
133141
void enet_mac_rx_isr()
134142
{
135-
sys_sem_signal(&k64f_enetdata.RxReadySem);
143+
osThreadFlagsSet(k64f_enetdata.thread, FLAG_RX);
136144
}
137145

138146
void enet_mac_tx_isr()
139147
{
140-
sys_sem_signal(&k64f_enetdata.TxCleanSem);
148+
osThreadFlagsSet(k64f_enetdata.thread, FLAG_TX);
141149
}
142150

143151
void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param)
@@ -461,26 +469,56 @@ void k64f_enetif_input(struct netif *netif, int idx)
461469
}
462470
}
463471

472+
/** \brief Worker thread.
473+
*
474+
* Woken by thread flags to receive packets or clean up transmit
475+
*
476+
* \param[in] pvParameters pointer to the interface data
477+
*/
478+
static void emac_thread(void* pvParameters)
479+
{
480+
struct k64f_enetdata *k64f_enet = pvParameters;
481+
482+
for (;;) {
483+
uint32_t flags = osThreadFlagsWait(FLAG_RX|FLAG_TX, osFlagsWaitAny, PHY_TASK_PERIOD_MS);
484+
if (flags == osFlagsErrorTimeout) {
485+
// Rather than calling strictly every period, we call when idle
486+
// for that period - hopefully good enough. We run this task
487+
// from lwIP's thread rather than our RX/TX thread, as PHY reads can
488+
// be slow, and we don't want them to interfere with data pumping.
489+
// This is analogous to the way the PHY polling works in the Nanostack
490+
// version of the driver
491+
tcpip_callback_with_block(k64f_phy_task, k64f_enet->netif, 0);
492+
continue;
493+
}
494+
495+
LWIP_ASSERT("osThreadFlagsWait error", !(flags & osFlagsError));
496+
497+
if (flags & FLAG_RX) {
498+
packet_rx(k64f_enet);
499+
}
500+
501+
if (flags & FLAG_TX) {
502+
packet_tx(k64f_enet);
503+
}
504+
}
505+
}
506+
464507
/** \brief Packet reception task
465508
*
466509
* This task is called when a packet is received. It will
467510
* pass the packet to the LWIP core.
468511
*
469-
* \param[in] pvParameters pointer to the interface data
512+
* \param[in] k64f_enet pointer to the interface data
470513
*/
471-
static void packet_rx(void* pvParameters) {
472-
struct k64f_enetdata *k64f_enet = pvParameters;
473-
int idx = 0;
474-
475-
while (1) {
476-
/* Wait for receive task to wakeup */
477-
sys_arch_sem_wait(&k64f_enet->RxReadySem, 0);
514+
static void packet_rx(struct k64f_enetdata *k64f_enet)
515+
{
516+
static int idx = 0;
478517

479518
while ((g_handle.rxBdCurrent->control & ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK) == 0) {
480-
k64f_enetif_input(k64f_enet->netif, idx);
481-
idx = (idx + 1) % ENET_RX_RING_LEN;
519+
k64f_enetif_input(k64f_enet->netif, idx);
520+
idx = (idx + 1) % ENET_RX_RING_LEN;
482521
}
483-
}
484522
}
485523

486524
/** \brief Transmit cleanup task
@@ -489,16 +527,11 @@ static void packet_rx(void* pvParameters) {
489527
* reclaims the pbuf and descriptor used for the packet once
490528
* the packet has been transferred.
491529
*
492-
* \param[in] pvParameters pointer to the interface data
530+
* \param[in] k64f_enet pointer to the interface data
493531
*/
494-
static void packet_tx(void* pvParameters) {
495-
struct k64f_enetdata *k64f_enet = pvParameters;
496-
497-
while (1) {
498-
/* Wait for transmit cleanup task to wakeup */
499-
sys_arch_sem_wait(&k64f_enet->TxCleanSem, 0);
532+
static void packet_tx(struct k64f_enetdata *k64f_enet)
533+
{
500534
k64f_tx_reclaim(k64f_enet);
501-
}
502535
}
503536

504537
/** \brief Low level output of a packet. Never call this from an
@@ -569,7 +602,6 @@ static err_t k64f_low_level_output(struct netif *netif, struct pbuf *p)
569602
* PHY task: monitor link
570603
*******************************************************************************/
571604

572-
#define PHY_TASK_PERIOD_MS 200
573605
#define STATE_UNKNOWN (-1)
574606

575607
typedef struct {
@@ -578,48 +610,48 @@ typedef struct {
578610
phy_duplex_t duplex;
579611
} PHY_STATE;
580612

581-
int phy_link_status() {
613+
int phy_link_status(void) {
582614
bool connection_status;
583615
uint32_t phyAddr = 0;
584616

585617
PHY_GetLinkStatus(ENET, phyAddr, &connection_status);
586618
return (int)connection_status;
587619
}
588620

589-
static void k64f_phy_task(void *data) {
590-
struct netif *netif = (struct netif*)data;
591-
bool connection_status;
592-
PHY_STATE crt_state = {STATE_UNKNOWN, (phy_speed_t)STATE_UNKNOWN, (phy_duplex_t)STATE_UNKNOWN};
593-
PHY_STATE prev_state;
594-
uint32_t phyAddr = 0;
595-
uint32_t rcr = 0;
621+
static void k64f_phy_task(void *data)
622+
{
623+
struct netif *netif = data;
624+
625+
static PHY_STATE prev_state = {STATE_UNKNOWN, (phy_speed_t)STATE_UNKNOWN, (phy_duplex_t)STATE_UNKNOWN};
626+
627+
uint32_t phyAddr = 0;
596628

597-
prev_state = crt_state;
598-
while (true) {
599629
// Get current status
630+
PHY_STATE crt_state;
631+
bool connection_status;
600632
PHY_GetLinkStatus(ENET, phyAddr, &connection_status);
601-
crt_state.connected = connection_status ? 1 : 0;
633+
crt_state.connected = connection_status;
602634
// Get the actual PHY link speed
603635
PHY_GetLinkSpeedDuplex(ENET, phyAddr, &crt_state.speed, &crt_state.duplex);
604636

605637
// Compare with previous state
606638
if (crt_state.connected != prev_state.connected) {
607-
if (crt_state.connected)
608-
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, (void*) netif, 1);
609-
else
610-
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1);
639+
// We're called from lwIP's tcpip thread, so can call link functions directly
640+
if (crt_state.connected) {
641+
netif_set_link_up(netif);
642+
} else {
643+
netif_set_link_down(netif);
644+
}
611645
}
612646

613647
if (crt_state.speed != prev_state.speed) {
614-
rcr = ENET->RCR;
648+
uint32_t rcr = ENET->RCR;
615649
rcr &= ~ENET_RCR_RMII_10T_MASK;
616650
rcr |= ENET_RCR_RMII_10T(!crt_state.speed);
617651
ENET->RCR = rcr;
618652
}
619653

620654
prev_state = crt_state;
621-
osDelay(PHY_TASK_PERIOD_MS);
622-
}
623655
}
624656

625657
/**
@@ -707,27 +739,13 @@ err_t eth_arch_enetif_init(struct netif *netif)
707739
err = sys_mutex_new(&k64f_enetdata.TXLockMutex);
708740
LWIP_ASSERT("TXLockMutex creation error", (err == ERR_OK));
709741

710-
/* Packet receive task */
711-
err = sys_sem_new(&k64f_enetdata.RxReadySem, 0);
712-
LWIP_ASSERT("RxReadySem creation error", (err == ERR_OK));
713-
714-
#ifdef LWIP_DEBUG
715-
sys_thread_new("k64f_emac_rx_thread", packet_rx, netif->state, DEFAULT_THREAD_STACKSIZE*5, RX_PRIORITY);
716-
#else
717-
sys_thread_new("k64f_emac_thread", packet_rx, netif->state, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY);
718-
#endif
719-
720-
/* Transmit cleanup task */
721-
err = sys_sem_new(&k64f_enetdata.TxCleanSem, 0);
722-
LWIP_ASSERT("TxCleanSem creation error", (err == ERR_OK));
723-
sys_thread_new("k64f_emac_txclean_thread", packet_tx, netif->state, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY);
724-
725-
/* PHY monitoring task */
726-
sys_thread_new("k64f_emac_phy_thread", k64f_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_PRIORITY);
727-
728742
/* Allow the PHY task to detect the initial link state and set up the proper flags */
743+
tcpip_callback_with_block(k64f_phy_task, netif, 1);
729744
osDelay(10);
730745

746+
/* Worker thread */
747+
k64f_enetdata.thread = sys_thread_new("k64f_emac_thread", emac_thread, netif->state, THREAD_STACKSIZE, THREAD_PRIORITY)->id;
748+
731749
return ERR_OK;
732750
}
733751

0 commit comments

Comments
 (0)