adds deferred processing capability to mnrs network driver

This commit is contained in:
2026-02-08 08:38:04 +01:00
parent 47588180b9
commit 889470ed04
2 changed files with 133 additions and 174 deletions

View File

@@ -9,7 +9,6 @@
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
**************************************************************************/ **************************************************************************/
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
/** */ /** */
@@ -20,11 +19,11 @@
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
/* Include necessary system files. */ /* Include necessary system files. */
#include "gen/ethmac.h" #include "gen/ethmac.h"
#include "nx_api.h" #include "nx_api.h"
#include "nx_user.h"
#include "platform.h" #include "platform.h"
#include "tx_port.h" #include "tx_port.h"
#include <string.h> #include <string.h>
@@ -71,12 +70,11 @@ const ULONG mnrs_mac_address_msw = 0x0200;
const ULONG mnrs_mac_address_lsw = 0x00334450; const ULONG mnrs_mac_address_lsw = 0x00334450;
/* Define driver prototypes. */ /* Define driver prototypes. */
VOID _nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr); VOID _nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr);
void _nx_mnrs_network_driver_output(NX_PACKET* packet_ptr, UINT interface_instance_id); void _nx_mnrs_network_driver_output(NX_PACKET* packet_ptr, UINT interface_instance_id);
void _nx_mnrs_network_driver_receive(NX_IP* ip_ptr, NX_PACKET* packet_ptr, UINT interface_instance_id); void _nx_mnrs_network_driver_receive(NX_IP* ip_ptr, NX_PACKET* packet_ptr, UINT interface_instance_id);
UINT _nx_mnrs_eth_send_packet(NX_PACKET* packet_ptr, volatile ethmac_t* ethmac); UINT _nx_mnrs_eth_send_packet(NX_PACKET* packet_ptr, volatile ethmac_t* ethmac);
VOID _nx_mnrs_eth_recv_packet(UINT id, volatile ethmac_t* ethmac); VOID _nx_mnrs_eth_recv_packet(UINT i);
VOID _nx_mnrs_eth_recv_packet_eth0(VOID); VOID _nx_mnrs_eth_recv_packet_eth0(VOID);
VOID _nx_mnrs_eth_recv_packet_eth1(VOID); VOID _nx_mnrs_eth_recv_packet_eth1(VOID);
@@ -87,7 +85,6 @@ typedef struct MAC_ADDRESS_STRUCT
ULONG nx_mac_address_lsw; ULONG nx_mac_address_lsw;
} MAC_ADDRESS; } MAC_ADDRESS;
/* Define an application-specific data structure that holds internal /* Define an application-specific data structure that holds internal
data (such as the state information) of a device driver. data (such as the state information) of a device driver.
@@ -111,13 +108,11 @@ typedef struct _nx_mnrs_network_driver_instance_type
volatile ethmac_t* ethmac; volatile ethmac_t* ethmac;
} _nx_mnrs_network_driver_instance_type; } _nx_mnrs_network_driver_instance_type;
/* In this example, there are four instances of the MNRS ETH driver. /* In this example, there are four instances of the MNRS ETH driver.
Therefore an array of four driver instances are created to keep track of Therefore an array of four driver instances are created to keep track of
the interface information of each driver. */ the interface information of each driver. */
static _nx_mnrs_network_driver_instance_type nx_mnrs_driver[NX_MAX_PHYSICAL_INTERFACES]; static _nx_mnrs_network_driver_instance_type nx_mnrs_driver[NX_MAX_PHYSICAL_INTERFACES];
/**************************************************************************/ /**************************************************************************/
/* */ /* */
/* FUNCTION RELEASE */ /* FUNCTION RELEASE */
@@ -202,14 +197,6 @@ ULONG *ethernet_frame_ptr;
{ {
for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++) for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
{ {
if (nx_mnrs_driver[i].nx_mnrs_network_driver_in_use == 0)
{
continue;
}
if (nx_mnrs_driver[i].nx_mnrs_driver_ip_ptr != ip_ptr)
{
continue;
}
if (nx_mnrs_driver[i].nx_mnrs_driver_interface_ptr == interface_ptr) if (nx_mnrs_driver[i].nx_mnrs_driver_interface_ptr == interface_ptr)
{ {
break; break;
@@ -221,6 +208,7 @@ ULONG *ethernet_frame_ptr;
return; return;
} }
} }
/* Process according to the driver request type in the IP control /* Process according to the driver request type in the IP control
block. */ block. */
switch (driver_req_ptr->nx_ip_driver_command) switch (driver_req_ptr->nx_ip_driver_command)
@@ -559,26 +547,15 @@ ULONG *ethernet_frame_ptr;
case NX_LINK_GET_INTERFACE_TYPE: case NX_LINK_GET_INTERFACE_TYPE:
{ {
/* Return the link's interface type in the supplied return pointer. Unsupported feature. */ /* Return the link's interface type in the supplied return pointer. Unsupported feature. */
*(driver_req_ptr->nx_ip_driver_return_ptr) = NX_INTERFACE_TYPE_UNKNOWN; *(driver_req_ptr->nx_ip_driver_return_ptr) = NX_INTERFACE_TYPE_ETHERNET;
break; break;
} }
case NX_LINK_DEFERRED_PROCESSING: case NX_LINK_DEFERRED_PROCESSING:
{ {
/* Driver defined deferred processing. This is typically used to defer interrupt /* Driver defined deferred processing. This is typically used to defer interrupt
processing to the thread level. processing to the thread level.
A typical use case of this command is:
On receiving an Ethernet frame, the RX ISR does not process the received frame,
but instead records such an event in its internal data structure, and issues
a notification to the IP stack (the driver sends the notification to the IP
helping thread by calling "_nx_ip_driver_deferred_processing()". When the IP stack
gets a notification of a pending driver deferred process, it calls the
driver with the NX_LINK_DEFERRED_PROCESSING command. The driver shall complete
the pending receive process.
*/ */
_nx_mnrs_eth_recv_packet(i);
/* The MNRS ETH driver doesn't require a deferred process so it breaks out of
the switch case. */
break; break;
} }
case NX_LINK_SET_PHYSICAL_ADDRESS: case NX_LINK_SET_PHYSICAL_ADDRESS:
@@ -739,7 +716,6 @@ UINT i, j;
tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold); tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold);
} }
/**************************************************************************/ /**************************************************************************/
/* */ /* */
/* FUNCTION RELEASE */ /* FUNCTION RELEASE */
@@ -826,11 +802,7 @@ void _nx_mnrs_network_driver_receive(NX_IP* ip_ptr, NX_PACKET* packet_ptr, UINT
#ifdef NX_DEBUG_PACKET #ifdef NX_DEBUG_PACKET
printf("NetX MNRS ETH Driver IP Packet Receive - %s\n", ip_ptr->nx_ip_name); printf("NetX MNRS ETH Driver IP Packet Receive - %s\n", ip_ptr->nx_ip_name);
#endif #endif
#ifdef NX_DIRECT_ISR_CALL
_nx_ip_packet_receive(ip_ptr, packet_ptr);
#else
_nx_ip_packet_deferred_receive(ip_ptr, packet_ptr); _nx_ip_packet_deferred_receive(ip_ptr, packet_ptr);
#endif
} }
#ifndef NX_DISABLE_IPV4 #ifndef NX_DISABLE_IPV4
else if (packet_type == NX_ETHERNET_ARP) else if (packet_type == NX_ETHERNET_ARP)
@@ -883,60 +855,36 @@ UINT _nx_mnrs_eth_send_packet(NX_PACKET* packet_ptr, volatile ethmac_t* ethmac)
data = packet_ptr->nx_packet_prepend_ptr; data = packet_ptr->nx_packet_prepend_ptr;
size = packet_ptr->nx_packet_length; size = packet_ptr->nx_packet_length;
words = (size + 3) / 4; words = (size + 3) / 4;
/* wait until ethmac is ready to receive packets */
while (get_ethmac_mac_ctrl_tx_ready(ethmac) == 0) while (get_ethmac_mac_ctrl_tx_ready(ethmac) == 0)
; ;
/* write the length of the frame in bits into ethmac fifo*/
set_ethmac_mac_tx(ethmac, size * 8); set_ethmac_mac_tx(ethmac, size * 8);
for (i = 0; i < size; i += 4) /* process buffer in word size and write into ethmac tx fifo*/
{ for (i = 0; i + 3 < size; i += 4)
if (i < size - 3)
{ {
memcpy(&buffer, data + i, 4); memcpy(&buffer, data + i, 4);
}
else
{
memcpy(&buffer, data + i, size - i);
}
while (!get_ethmac_mac_ctrl_tx_ready(ethmac)) while (!get_ethmac_mac_ctrl_tx_ready(ethmac))
; ;
set_ethmac_mac_tx(ethmac, buffer); set_ethmac_mac_tx(ethmac, buffer);
}
/* process remaining bytes */
if (i < size)
{
memcpy(&buffer, data + i, size - i);
while (!get_ethmac_mac_ctrl_tx_ready(ethmac))
;
set_ethmac_mac_tx(ethmac, buffer);
} }
return NX_SUCCESS; return NX_SUCCESS;
} }
UINT mac_addr_hit(UINT i, MAC_ADDRESS* mac_addr)
{
UINT mcast_index;
if (nx_mnrs_driver[i].nx_mnrs_driver_mac_address.nx_mac_address_msw == mac_addr->nx_mac_address_msw &&
nx_mnrs_driver[i].nx_mnrs_driver_mac_address.nx_mac_address_lsw == mac_addr->nx_mac_address_lsw)
{
return 1;
}
return 0;
}
UINT mcast_mac_addr_hit_idx(UINT i, MAC_ADDRESS* mac_addr)
{
UINT mcast_index;
for (mcast_index = 0; mcast_index < NX_MNRS_DRIVER_MAX_MCAST_ADDRESSES; mcast_index++)
{
if (nx_mnrs_driver[i].nx_mnrs_driver_mcast_address[mcast_index].nx_mac_address_msw ==
mac_addr->nx_mac_address_msw &&
nx_mnrs_driver[i].nx_mnrs_driver_mcast_address[mcast_index].nx_mac_address_lsw ==
mac_addr->nx_mac_address_lsw)
{
return i;
}
}
return -1;
}
static UCHAR nx_mnrs_receive_buffer[NX_MAX_PACKET_SIZE]; static UCHAR nx_mnrs_receive_buffer[NX_MAX_PACKET_SIZE];
VOID _nx_mnrs_eth_recv_packet(UINT id, volatile ethmac_t* ethmac) VOID _nx_mnrs_eth_recv_packet(UINT i)
{ {
UINT bits_received; UINT bits_received;
UINT words_to_read; UINT words_to_read;
UINT i, j; UINT j;
UINT word; UINT word;
UINT status; UINT status;
NX_PACKET* packet_ptr; NX_PACKET* packet_ptr;
@@ -946,27 +894,23 @@ VOID _nx_mnrs_eth_recv_packet(UINT id, volatile ethmac_t* ethmac)
UINT address_len; UINT address_len;
UINT packet_type; UINT packet_type;
set_ethmac_mac_intr_rx_data_avail_intr_enable(ethmac, 0); /* read the number of bits in the frame and convert it into number of words to read */
bits_received = get_ethmac_mac_rx(ethmac); bits_received = get_ethmac_mac_rx(nx_mnrs_driver[i].ethmac);
words_to_read = (bits_received + 31) / 32; words_to_read = (bits_received + 31) / 32;
if (words_to_read < 4) if (words_to_read < 4)
{ {
for (j = 0; j < words_to_read; j++) for (j = 0; j < words_to_read; j++)
{ {
while (!get_ethmac_mac_ctrl_rx_pending(ethmac)) while (!get_ethmac_mac_ctrl_rx_pending(nx_mnrs_driver[i].ethmac))
; ;
// be carefull of unaligned accesses since data is 2byte aligned // be carefull of unaligned accesses since data is 2byte aligned
word = get_ethmac_mac_rx(ethmac); word = get_ethmac_mac_rx(nx_mnrs_driver[i].ethmac);
memcpy(data + j * sizeof(UINT), &word, sizeof(UINT)); memcpy(data + j * sizeof(UINT), &word, sizeof(UINT));
} }
set_ethmac_mac_intr_rx_data_avail_intr_enable(ethmac, 1); set_ethmac_mac_intr_rx_data_avail_intr_enable(nx_mnrs_driver[i].ethmac, 1);
return; return;
} }
// find the diver instance belonging to our ethmac // get the IP diver instance belonging to our ethmac
for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; ++i)
{
if (nx_mnrs_driver[i].ethmac == ethmac)
{
ip_ptr = nx_mnrs_driver[i].nx_mnrs_driver_ip_ptr; ip_ptr = nx_mnrs_driver[i].nx_mnrs_driver_ip_ptr;
status = nx_packet_allocate(ip_ptr->nx_ip_default_packet_pool, &packet_ptr, NX_RECEIVE_PACKET, NX_NO_WAIT); status = nx_packet_allocate(ip_ptr->nx_ip_default_packet_pool, &packet_ptr, NX_RECEIVE_PACKET, NX_NO_WAIT);
if (status) if (status)
@@ -985,10 +929,10 @@ VOID _nx_mnrs_eth_recv_packet(UINT id, volatile ethmac_t* ethmac)
/* now get the remaining bytes from the ethmac peripheral */ /* now get the remaining bytes from the ethmac peripheral */
for (j = 0; j < words_to_read; j++) for (j = 0; j < words_to_read; j++)
{ {
while (!get_ethmac_mac_ctrl_rx_pending(ethmac)) while (!get_ethmac_mac_ctrl_rx_pending(nx_mnrs_driver[i].ethmac))
; ;
// be carefull of unaligned accesses since data is 2byte aligned // be carefull of unaligned accesses since data is 2byte aligned
word = get_ethmac_mac_rx(ethmac); word = get_ethmac_mac_rx(nx_mnrs_driver[i].ethmac);
memcpy(data + j * sizeof(UINT), &word, sizeof(UINT)); memcpy(data + j * sizeof(UINT), &word, sizeof(UINT));
} }
if (packet_ptr == NX_NULL) if (packet_ptr == NX_NULL)
@@ -1017,25 +961,43 @@ VOID _nx_mnrs_eth_recv_packet(UINT id, volatile ethmac_t* ethmac)
} }
_nx_mnrs_network_driver_receive(ip_ptr, packet_ptr, i); _nx_mnrs_network_driver_receive(ip_ptr, packet_ptr, i);
break; set_ethmac_mac_intr_rx_data_avail_intr_enable(nx_mnrs_driver[i].ethmac, 1);
}
}
set_ethmac_mac_intr_rx_data_avail_intr_enable(ethmac, 1);
} }
VOID _nx_mnrs_eth_recv_packet_eth0(VOID) VOID _nx_mnrs_eth_recv_packet_eth0(VOID)
{ {
ULONG old_threshold;
if (get_ethmac_mac_ctrl_rx_pending(ethmac0)) if (get_ethmac_mac_ctrl_rx_pending(ethmac0))
{ {
_nx_mnrs_eth_recv_packet(0, ethmac0); set_ethmac_mac_intr_rx_data_avail_intr_enable(ethmac0, 0);
#ifndef NX_DRIVER_DEFERRED_PROCESSING
/* Disable preemption. */
tx_thread_preemption_change(tx_thread_identify(), 0, &old_threshold);
_nx_mnrs_eth_recv_packet(0);
/* Restore preemption. */
tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold);
#else
_nx_ip_driver_deferred_processing(nx_mnrs_driver[0].nx_mnrs_driver_ip_ptr);
#endif
} }
} }
VOID _nx_mnrs_eth_recv_packet_eth1(VOID) VOID _nx_mnrs_eth_recv_packet_eth1(VOID)
{ {
ULONG old_threshold;
if (get_ethmac_mac_ctrl_rx_pending(ethmac1)) if (get_ethmac_mac_ctrl_rx_pending(ethmac1))
{ {
_nx_mnrs_eth_recv_packet(1, ethmac1); set_ethmac_mac_intr_rx_data_avail_intr_enable(ethmac1, 0);
#ifndef NX_DRIVER_DEFERRED_PROCESSING
/* Disable preemption. */
tx_thread_preemption_change(tx_thread_identify(), 0, &old_threshold);
_nx_mnrs_eth_recv_packet(1);
/* Restore preemption. */
tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold);
#else
_nx_ip_driver_deferred_processing(nx_mnrs_driver[1].nx_mnrs_driver_ip_ptr);
#endif
} }
} }

View File

@@ -62,7 +62,6 @@
/* Define the base exponent of 2 for huge number. /* Define the base exponent of 2 for huge number.
* Only 16 and 32 are supported. */ * Only 16 and 32 are supported. */
#define NX_CRYPTO_HUGE_NUMBER_BITS 32 #define NX_CRYPTO_HUGE_NUMBER_BITS 32
#define NX_DIRECT_ISR_CALL 1
/* Define various build options for the NetX Duo port. The application should either make changes /* Define various build options for the NetX Duo port. The application should either make changes
here by commenting or un-commenting the conditional compilation defined OR supply the defines here by commenting or un-commenting the conditional compilation defined OR supply the defines
though the compiler's equivalent of the -D option. */ though the compiler's equivalent of the -D option. */
@@ -706,9 +705,7 @@
/* Defined, this option enables deferred driver packet handling. This allows the driver to place a raw /* Defined, this option enables deferred driver packet handling. This allows the driver to place a raw
packet on the IP instance and have the driver's real processing routine called from the NetX internal packet on the IP instance and have the driver's real processing routine called from the NetX internal
IP helper thread. */ IP helper thread. */
/*
#define NX_DRIVER_DEFERRED_PROCESSING #define NX_DRIVER_DEFERRED_PROCESSING
*/
/* Defined, the source address of incoming packet is checked. The default is disabled. */ /* Defined, the source address of incoming packet is checked. The default is disabled. */
/* /*