main #2

Merged
eyck merged 2 commits from Airbus/ADS-VP-Demo-FW:main into main 2026-02-08 07:57:28 +00:00
3 changed files with 136 additions and 178 deletions

View File

@@ -1,15 +1,14 @@
/***************************************************************************
* Copyright (c) 2024 Microsoft Corporation
* Copyright (c) 2024 Microsoft Corporation
* Copyright (c) 2025-present Eclipse ThreadX Contributors
*
*
* This program and the accompanying materials are made available under the
* terms of the MIT License which is available at
* https://opensource.org/licenses/MIT.
*
*
* SPDX-License-Identifier: MIT
**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
@@ -20,11 +19,11 @@
/**************************************************************************/
/**************************************************************************/
/* Include necessary system files. */
#include "gen/ethmac.h"
#include "nx_api.h"
#include "nx_user.h"
#include "platform.h"
#include "tx_port.h"
#include <string.h>
@@ -71,14 +70,13 @@ const ULONG mnrs_mac_address_msw = 0x0200;
const ULONG mnrs_mac_address_lsw = 0x00334450;
/* Define driver prototypes. */
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_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);
VOID _nx_mnrs_eth_recv_packet(UINT id, volatile ethmac_t* ethmac);
VOID _nx_mnrs_eth_recv_packet_eth0(VOID);
VOID _nx_mnrs_eth_recv_packet_eth1(VOID);
VOID nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr);
static void _nx_mnrs_network_driver_output(NX_PACKET* packet_ptr, UINT interface_instance_id);
static void _nx_mnrs_network_driver_receive(NX_IP* ip_ptr, NX_PACKET* packet_ptr, UINT interface_instance_id);
static UINT _nx_mnrs_eth_send_packet(NX_PACKET* packet_ptr, volatile ethmac_t* ethmac);
static VOID _nx_mnrs_eth_recv_packet(UINT i);
static VOID _nx_mnrs_eth_recv_packet_eth0(VOID);
static VOID _nx_mnrs_eth_recv_packet_eth1(VOID);
#define NX_MNRS_DRIVER_MAX_MCAST_ADDRESSES 3
typedef struct MAC_ADDRESS_STRUCT
@@ -87,7 +85,6 @@ typedef struct MAC_ADDRESS_STRUCT
ULONG nx_mac_address_lsw;
} MAC_ADDRESS;
/* Define an application-specific data structure that holds internal
data (such as the state information) of a device driver.
@@ -98,26 +95,24 @@ typedef struct _nx_mnrs_network_driver_instance_type
{
UINT nx_mnrs_network_driver_in_use;
UINT nx_mnrs_network_driver_id;
UINT nx_mnrs_network_driver_id;
NX_INTERFACE *nx_mnrs_driver_interface_ptr;
NX_INTERFACE* nx_mnrs_driver_interface_ptr;
NX_IP *nx_mnrs_driver_ip_ptr;
NX_IP* nx_mnrs_driver_ip_ptr;
MAC_ADDRESS nx_mnrs_driver_mac_address;
MAC_ADDRESS nx_mnrs_driver_mac_address;
MAC_ADDRESS nx_mnrs_driver_mcast_address[NX_MNRS_DRIVER_MAX_MCAST_ADDRESSES];
MAC_ADDRESS nx_mnrs_driver_mcast_address[NX_MNRS_DRIVER_MAX_MCAST_ADDRESSES];
volatile ethmac_t* ethmac;
volatile ethmac_t* ethmac;
} _nx_mnrs_network_driver_instance_type;
/* 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
the interface information of each driver. */
static _nx_mnrs_network_driver_instance_type nx_mnrs_driver[NX_MAX_PHYSICAL_INTERFACES];
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
@@ -169,7 +164,7 @@ static _nx_mnrs_network_driver_instance_type nx_mnrs_driver[NX_MAX_PHYSICAL_INTE
/* resulting in version 6.4.0 */
/* */
/**************************************************************************/
VOID _nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr)
VOID nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr)
{
UINT i = 0;
NX_IP* ip_ptr;
@@ -178,13 +173,13 @@ VOID _nx_mnrs_network_driver(NX_IP_DRIVER* driver_req_ptr)
UINT interface_index;
USHORT ether_type;
#ifndef NX_ENABLE_VLAN
ULONG *ethernet_frame_ptr;
ULONG* ethernet_frame_ptr;
#endif /* NX_ENABLE_VLAN */
/* Setup the IP pointer from the driver request. */
ip_ptr = driver_req_ptr -> nx_ip_driver_ptr;
ip_ptr = driver_req_ptr->nx_ip_driver_ptr;
/* Default to successful return. */
driver_req_ptr -> nx_ip_driver_status = NX_SUCCESS;
driver_req_ptr->nx_ip_driver_status = NX_SUCCESS;
#ifdef NX_ENABLE_VLAN
/* Let link layer to preprocess the driver request and return actual interface. */
if (nx_link_driver_request_preprocess(driver_req_ptr, &interface_ptr) != NX_SUCCESS)
@@ -193,23 +188,15 @@ ULONG *ethernet_frame_ptr;
}
#else
/* Setup interface pointer. */
interface_ptr = driver_req_ptr -> nx_ip_driver_interface;
interface_ptr = driver_req_ptr->nx_ip_driver_interface;
#endif /* NX_ENABLE_VLAN */
/* Obtain the index number of the network interface. */
interface_index = interface_ptr -> nx_interface_index;
interface_index = interface_ptr->nx_interface_index;
/* Find out the driver interface if the driver command is not ATTACH. */
if (driver_req_ptr->nx_ip_driver_command != NX_LINK_INTERFACE_ATTACH)
{
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)
{
break;
@@ -221,6 +208,7 @@ ULONG *ethernet_frame_ptr;
return;
}
}
/* Process according to the driver request type in the IP control
block. */
switch (driver_req_ptr->nx_ip_driver_command)
@@ -559,26 +547,15 @@ ULONG *ethernet_frame_ptr;
case NX_LINK_GET_INTERFACE_TYPE:
{
/* 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;
}
case NX_LINK_DEFERRED_PROCESSING:
{
/* Driver defined deferred processing. This is typically used to defer interrupt
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.
*/
/* The MNRS ETH driver doesn't require a deferred process so it breaks out of
the switch case. */
_nx_mnrs_eth_recv_packet(i);
break;
}
case NX_LINK_SET_PHYSICAL_ADDRESS:
@@ -686,10 +663,10 @@ void _nx_mnrs_network_driver_output(NX_PACKET* packet_ptr, UINT interface_instan
UINT old_threshold = 0;
#ifdef NX_DEBUG_PACKET
UCHAR *ptr;
UINT i, j;
UCHAR* ptr;
UINT i, j;
ptr = packet_ptr -> nx_packet_prepend_ptr;
ptr = packet_ptr->nx_packet_prepend_ptr;
printf("Ethernet Packet: ");
for (j = 0; j < 6; j++)
{
@@ -719,9 +696,9 @@ UINT i, j;
/* Disable preemption. */
tx_thread_preemption_change(tx_thread_identify(), 0, &old_threshold);
_nx_mnrs_eth_send_packet(packet_ptr, nx_mnrs_driver[interface_instance_id].ethmac);
_nx_mnrs_eth_send_packet(packet_ptr, nx_mnrs_driver[interface_instance_id].ethmac);
#ifdef NX_ENABLE_VLAN
/* Release the packet. */
/* Release the packet. */
nx_link_packet_transmitted(nx_mnrs_driver[interface_instance_id].nx_mnrs_driver_ip_ptr,
nx_mnrs_driver[interface_instance_id].nx_mnrs_driver_interface_ptr->nx_interface_index,
packet_ptr,
@@ -729,9 +706,9 @@ UINT i, j;
#else
/* Remove the Ethernet header. In real hardware environments, this is typically
done after a transmit complete interrupt. */
packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
packet_ptr->nx_packet_prepend_ptr = packet_ptr->nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
/* Adjust the packet length. */
packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE;
packet_ptr->nx_packet_length = packet_ptr->nx_packet_length - NX_ETHERNET_SIZE;
/* Now that the Ethernet frame has been removed, release the packet. */
nx_packet_transmit_release(packet_ptr);
#endif /* NX_ENABLE_VLAN */
@@ -739,7 +716,6 @@ UINT i, j;
tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold);
}
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
@@ -819,41 +795,37 @@ void _nx_mnrs_network_driver_receive(NX_IP* ip_ptr, NX_PACKET* packet_ptr, UINT
the first 32-bit word). */
/* Clean off the Ethernet header. */
packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
packet_ptr->nx_packet_prepend_ptr = packet_ptr->nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
/* Adjust the packet length. */
packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE;
packet_ptr->nx_packet_length = packet_ptr->nx_packet_length - NX_ETHERNET_SIZE;
/* Route to the ip receive function. */
#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
#ifdef NX_DIRECT_ISR_CALL
_nx_ip_packet_receive(ip_ptr, packet_ptr);
#else
_nx_ip_packet_deferred_receive(ip_ptr, packet_ptr);
#endif
}
#ifndef NX_DISABLE_IPV4
else if (packet_type == NX_ETHERNET_ARP)
{
/* Clean off the Ethernet header. */
packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
packet_ptr->nx_packet_prepend_ptr = packet_ptr->nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
/* Adjust the packet length. */
packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE;
packet_ptr->nx_packet_length = packet_ptr->nx_packet_length - NX_ETHERNET_SIZE;
/* Route to the ARP receive function. */
#ifdef NX_DEBUG
printf("NetX MNRS ETH Driver ARP Receive - %s\n", ip_ptr -> nx_ip_name);
printf("NetX MNRS ETH Driver ARP Receive - %s\n", ip_ptr->nx_ip_name);
#endif
_nx_arp_packet_deferred_receive(ip_ptr, packet_ptr);
}
else if (packet_type == NX_ETHERNET_RARP)
{
/* Clean off the Ethernet header. */
packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
packet_ptr->nx_packet_prepend_ptr = packet_ptr->nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
/* Adjust the packet length. */
packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE;
packet_ptr->nx_packet_length = packet_ptr->nx_packet_length - NX_ETHERNET_SIZE;
/* Route to the RARP receive function. */
#ifdef NX_DEBUG
printf("NetX MNRS ETH Driver RARP Receive - %s\n", ip_ptr -> nx_ip_name);
printf("NetX MNRS ETH Driver RARP Receive - %s\n", ip_ptr->nx_ip_name);
#endif
_nx_rarp_packet_deferred_receive(ip_ptr, packet_ptr);
}
@@ -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;
size = packet_ptr->nx_packet_length;
words = (size + 3) / 4;
/* wait until ethmac is ready to receive packets */
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);
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);
}
else
{
memcpy(&buffer, data + i, size - i);
}
memcpy(&buffer, data + i, 4);
while (!get_ethmac_mac_ctrl_tx_ready(ethmac))
;
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;
}
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];
VOID _nx_mnrs_eth_recv_packet(UINT id, volatile ethmac_t* ethmac)
VOID _nx_mnrs_eth_recv_packet(UINT i)
{
UINT bits_received;
UINT words_to_read;
UINT i, j;
UINT j;
UINT word;
UINT status;
NX_PACKET* packet_ptr;
@@ -946,96 +894,110 @@ VOID _nx_mnrs_eth_recv_packet(UINT id, volatile ethmac_t* ethmac)
UINT address_len;
UINT packet_type;
set_ethmac_mac_intr_rx_data_avail_intr_enable(ethmac, 0);
bits_received = get_ethmac_mac_rx(ethmac);
/* read the number of bits in the frame and convert it into number of words to read */
bits_received = get_ethmac_mac_rx(nx_mnrs_driver[i].ethmac);
words_to_read = (bits_received + 31) / 32;
if (words_to_read < 4)
{
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
word = get_ethmac_mac_rx(ethmac);
word = get_ethmac_mac_rx(nx_mnrs_driver[i].ethmac);
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;
}
// find the diver instance belonging to our ethmac
for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; ++i)
// get the IP diver instance belonging to our ethmac
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);
if (status)
{
if (nx_mnrs_driver[i].ethmac == ethmac)
packet_ptr = NX_NULL;
data = nx_mnrs_receive_buffer;
}
else if (ip_ptr->nx_ip_default_packet_pool->nx_packet_pool_payload_size >= (NX_LINK_MTU + 2))
{
data = packet_ptr->nx_packet_prepend_ptr + 2;
}
else
{
data = nx_mnrs_receive_buffer;
}
/* now get the remaining bytes from the ethmac peripheral */
for (j = 0; j < words_to_read; j++)
{
while (!get_ethmac_mac_ctrl_rx_pending(nx_mnrs_driver[i].ethmac))
;
// be carefull of unaligned accesses since data is 2byte aligned
word = get_ethmac_mac_rx(nx_mnrs_driver[i].ethmac);
memcpy(data + j * sizeof(UINT), &word, sizeof(UINT));
}
if (packet_ptr == NX_NULL)
{
/* No packet available. Drop it and continue. */
return;
}
/* Make sure IP header is 4-byte aligned. */
packet_ptr->nx_packet_prepend_ptr += 2;
packet_ptr->nx_packet_append_ptr += 2;
if (data == nx_mnrs_receive_buffer)
{
/* Copy data into packet. */
status = nx_packet_data_append(
packet_ptr, (VOID*)data, bytes_received, ip_ptr->nx_ip_default_packet_pool, NX_NO_WAIT);
if (status)
{
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);
if (status)
{
packet_ptr = NX_NULL;
data = nx_mnrs_receive_buffer;
}
else if (ip_ptr->nx_ip_default_packet_pool->nx_packet_pool_payload_size >= (NX_LINK_MTU + 2))
{
data = packet_ptr->nx_packet_prepend_ptr + 2;
}
else
{
data = nx_mnrs_receive_buffer;
}
/* now get the remaining bytes from the ethmac peripheral */
for (j = 0; j < words_to_read; j++)
{
while (!get_ethmac_mac_ctrl_rx_pending(ethmac))
;
// be carefull of unaligned accesses since data is 2byte aligned
word = get_ethmac_mac_rx(ethmac);
memcpy(data + j * sizeof(UINT), &word, sizeof(UINT));
}
if (packet_ptr == NX_NULL)
{
/* No packet available. Drop it and continue. */
return;
}
/* Make sure IP header is 4-byte aligned. */
packet_ptr->nx_packet_prepend_ptr += 2;
packet_ptr->nx_packet_append_ptr += 2;
if (data == nx_mnrs_receive_buffer)
{
/* Copy data into packet. */
status = nx_packet_data_append(
packet_ptr, (VOID*)data, bytes_received, ip_ptr->nx_ip_default_packet_pool, NX_NO_WAIT);
if (status)
{
nx_packet_release(packet_ptr);
return;
}
}
else
{
packet_ptr->nx_packet_length = (ULONG)bytes_received;
packet_ptr->nx_packet_append_ptr += (ULONG)bytes_received;
}
_nx_mnrs_network_driver_receive(ip_ptr, packet_ptr, i);
break;
nx_packet_release(packet_ptr);
return;
}
}
set_ethmac_mac_intr_rx_data_avail_intr_enable(ethmac, 1);
else
{
packet_ptr->nx_packet_length = (ULONG)bytes_received;
packet_ptr->nx_packet_append_ptr += (ULONG)bytes_received;
}
_nx_mnrs_network_driver_receive(ip_ptr, packet_ptr, i);
set_ethmac_mac_intr_rx_data_avail_intr_enable(nx_mnrs_driver[i].ethmac, 1);
}
VOID _nx_mnrs_eth_recv_packet_eth0(VOID)
{
ULONG old_threshold;
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)
{
ULONG old_threshold;
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.
* Only 16 and 32 are supported. */
#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
here by commenting or un-commenting the conditional compilation defined OR supply the defines
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
packet on the IP instance and have the driver's real processing routine called from the NetX internal
IP helper thread. */
/*
#define NX_DRIVER_DEFERRED_PROCESSING
*/
/* Defined, the source address of incoming packet is checked. The default is disabled. */
/*

View File

@@ -36,9 +36,8 @@ void thread_1_entry(ULONG thread_input);
void thread_1_connect_received(NX_TCP_SOCKET* server_socket, UINT port);
void thread_1_disconnect_received(NX_TCP_SOCKET* server_socket);
void _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT* driver_req);
void _nx_mnrs_network_driver(struct NX_IP_DRIVER_STRUCT* driver_req);
#define NETWORK_DRIVER _nx_mnrs_network_driver
void nx_mnrs_network_driver(struct NX_IP_DRIVER_STRUCT* driver_req);
#define NETWORK_DRIVER nx_mnrs_network_driver
// alternative the ram driver can be used
// #define NETWORK_DRIVER _nx_ram_network_driver