@@ -52,24 +52,32 @@ extern void k66f_init_eth_hardware(void);
52
52
/* K64F EMAC driver data structure */
53
53
struct k64f_enetdata {
54
54
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 */
57
56
sys_mutex_t TXLockMutex ; /**< TX critical section mutex */
58
57
sys_sem_t xTXDCountSem ; /**< TX free buffer counting semaphore */
59
58
uint8_t tx_consume_index , tx_produce_index ; /**< TX buffers ring */
60
59
};
61
60
62
61
static struct k64f_enetdata k64f_enetdata ;
63
62
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
73
81
74
82
/********************************************************************************
75
83
* Buffer management
@@ -132,12 +140,12 @@ static void k64f_tx_reclaim(struct k64f_enetdata *k64f_enet)
132
140
*/
133
141
void enet_mac_rx_isr ()
134
142
{
135
- sys_sem_signal ( & k64f_enetdata .RxReadySem );
143
+ osThreadFlagsSet ( k64f_enetdata .thread , FLAG_RX );
136
144
}
137
145
138
146
void enet_mac_tx_isr ()
139
147
{
140
- sys_sem_signal ( & k64f_enetdata .TxCleanSem );
148
+ osThreadFlagsSet ( k64f_enetdata .thread , FLAG_TX );
141
149
}
142
150
143
151
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)
461
469
}
462
470
}
463
471
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
+
464
507
/** \brief Packet reception task
465
508
*
466
509
* This task is called when a packet is received. It will
467
510
* pass the packet to the LWIP core.
468
511
*
469
- * \param[in] pvParameters pointer to the interface data
512
+ * \param[in] k64f_enet pointer to the interface data
470
513
*/
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 ;
478
517
479
518
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 ;
482
521
}
483
- }
484
522
}
485
523
486
524
/** \brief Transmit cleanup task
@@ -489,16 +527,11 @@ static void packet_rx(void* pvParameters) {
489
527
* reclaims the pbuf and descriptor used for the packet once
490
528
* the packet has been transferred.
491
529
*
492
- * \param[in] pvParameters pointer to the interface data
530
+ * \param[in] k64f_enet pointer to the interface data
493
531
*/
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
+ {
500
534
k64f_tx_reclaim (k64f_enet );
501
- }
502
535
}
503
536
504
537
/** \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)
569
602
* PHY task: monitor link
570
603
*******************************************************************************/
571
604
572
- #define PHY_TASK_PERIOD_MS 200
573
605
#define STATE_UNKNOWN (-1)
574
606
575
607
typedef struct {
@@ -578,48 +610,48 @@ typedef struct {
578
610
phy_duplex_t duplex ;
579
611
} PHY_STATE ;
580
612
581
- int phy_link_status () {
613
+ int phy_link_status (void ) {
582
614
bool connection_status ;
583
615
uint32_t phyAddr = 0 ;
584
616
585
617
PHY_GetLinkStatus (ENET , phyAddr , & connection_status );
586
618
return (int )connection_status ;
587
619
}
588
620
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 ;
596
628
597
- prev_state = crt_state ;
598
- while (true) {
599
629
// Get current status
630
+ PHY_STATE crt_state ;
631
+ bool connection_status ;
600
632
PHY_GetLinkStatus (ENET , phyAddr , & connection_status );
601
- crt_state .connected = connection_status ? 1 : 0 ;
633
+ crt_state .connected = connection_status ;
602
634
// Get the actual PHY link speed
603
635
PHY_GetLinkSpeedDuplex (ENET , phyAddr , & crt_state .speed , & crt_state .duplex );
604
636
605
637
// Compare with previous state
606
638
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
+ }
611
645
}
612
646
613
647
if (crt_state .speed != prev_state .speed ) {
614
- rcr = ENET -> RCR ;
648
+ uint32_t rcr = ENET -> RCR ;
615
649
rcr &= ~ENET_RCR_RMII_10T_MASK ;
616
650
rcr |= ENET_RCR_RMII_10T (!crt_state .speed );
617
651
ENET -> RCR = rcr ;
618
652
}
619
653
620
654
prev_state = crt_state ;
621
- osDelay (PHY_TASK_PERIOD_MS );
622
- }
623
655
}
624
656
625
657
/**
@@ -707,27 +739,13 @@ err_t eth_arch_enetif_init(struct netif *netif)
707
739
err = sys_mutex_new (& k64f_enetdata .TXLockMutex );
708
740
LWIP_ASSERT ("TXLockMutex creation error" , (err == ERR_OK ));
709
741
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
-
728
742
/* 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 );
729
744
osDelay (10 );
730
745
746
+ /* Worker thread */
747
+ k64f_enetdata .thread = sys_thread_new ("k64f_emac_thread" , emac_thread , netif -> state , THREAD_STACKSIZE , THREAD_PRIORITY )-> id ;
748
+
731
749
return ERR_OK ;
732
750
}
733
751
0 commit comments