Solved! Go to Solution.
Hi Richard,
To receive Ethernet frames with a specific Ether Type you have to register this protocol type on an Ethernet channel using the ENET_open function. Example:
if ((ENET_open((RTCS_get_enet_handle (MQX1588_ihandle)), 0x88F7, MQX1588_Recv_L2_1588, MQX1588_ihandle)) != ENET_OK)
{
TGT_printf("Registering an EtherType value for IEEE 1588 (0x88 0xF7) protocol failed.\n");
}
--------------------------------------------------
MQX1588_Recv_L2_1588 function then handles all received Eth. frames with 0x88F7 type.
As for sending, you have to create the frame (DST_MAC, SRC_MAC, EthType, Data) first, then create the pcb and finally use ENET_send_raw function for sending the packet. Example:
typedef struct {
uint_8 DST[6];
uint_8 SRC[6];
uint_8 ETHTYPE[2];
uint_8 DATA[50];
} FRAME, * FRAME_PTR;
--------------------------------------
PCB_PTR pcb_ptr;
uchar_ptr mem_ptr;
FRAME_PTR packet_ptr;
mem_ptr = _mem_alloc_zero(sizeof(PCB)+sizeof(PCB_FRAGMENT)+sizeof(FRAME));
if (mem_ptr==NULL) {
return FALSE;
}
pcb_ptr = (PCB_PTR) mem_ptr;
packet_ptr = (FRAME_PTR)&mem_ptr[sizeof(PCB)+sizeof(PCB_FRAGMENT)];
memcpy( phy_packet_ptr->DST [0], MY_FRAME, sizeof(MY_FRAME));
pcb_ptr->FREE = free_pcb;
pcb_ptr->FRAG[0].LENGTH = sizeof(FRAME);
pcb_ptr->FRAG[0].FRAGMENT = (uchar_ptr)packet_ptr;
if((ENET_send_raw(RTCS_get_enet_handle (ipcfg_get_ihandle(portHandle->device_number)), pcb_ptr)) == ENET_OK)
return TRUE;
else
return FALSE;
------------------------------------------
Regards
MichalP
Doing the ENET_join() should eliminate the need to use the "#define RTCSCFG_IP_DISABLE_DIRECTED_BROADCAST 0".
This worked with MQX 4.2 on a Kinetis K64. For more information read about the following registers in the K64:
ENET_RCR bits PROM (promiscuous) and BC_REJ (broadcast), and ENET_GAUR, ENET_GALR.
I have found that I also need to call ENET_join() after the ENET_open().
// destination MAC address
unsigned char aucDestMac[6] = {0x01,0x02,0x03,0x00,0x00,0x00};
ENET_join((RTCS_get_enet_handle(ipcfg_get_ihandle(BSP_DEFAULT_ENET_DEVICE))),
0x88F7, // EtherType, ethernet type
aucDestMac);
I registered the function with ethertype 0x88f7 after I open a http server and now I sent a broadcast frame in another machine with these ethertype but the callback function never was called:
if (ENET_open(RTCS_get_enet_handle(ipcfg_get_ihandle(BSP_DEFAULT_ENET_DEVICE)),
0x88f7, recv_ethtype, ipcfg_get_ihandle(BSP_DEFAULT_ENET_DEVICE)) != MQX_OK)
return 1;
void recv_ethtype
(
PCB_PTR pcb,
/* [IN] the received packet */
void *handle
/* [IN] the IP interface structure */
)
{
printf("\nreceived enet 0x88f7 frame\n");
}
I'm using the new MQX 4.1.1 and I can't see any error to register the ethertype but I never receive any frame.
Does anybody tested this code? Is it work?
I solved my problem enabling broadcasting setting 0 to RTCSCFG_IP_DISABLE_DIRECTED_BROADCAST on user_config.h:
#define RTCSCFG_IP_DISABLE_DIRECTED_BROADCAST 0
Hi Richard,
To receive Ethernet frames with a specific Ether Type you have to register this protocol type on an Ethernet channel using the ENET_open function. Example:
if ((ENET_open((RTCS_get_enet_handle (MQX1588_ihandle)), 0x88F7, MQX1588_Recv_L2_1588, MQX1588_ihandle)) != ENET_OK)
{
TGT_printf("Registering an EtherType value for IEEE 1588 (0x88 0xF7) protocol failed.\n");
}
--------------------------------------------------
MQX1588_Recv_L2_1588 function then handles all received Eth. frames with 0x88F7 type.
As for sending, you have to create the frame (DST_MAC, SRC_MAC, EthType, Data) first, then create the pcb and finally use ENET_send_raw function for sending the packet. Example:
typedef struct {
uint_8 DST[6];
uint_8 SRC[6];
uint_8 ETHTYPE[2];
uint_8 DATA[50];
} FRAME, * FRAME_PTR;
--------------------------------------
PCB_PTR pcb_ptr;
uchar_ptr mem_ptr;
FRAME_PTR packet_ptr;
mem_ptr = _mem_alloc_zero(sizeof(PCB)+sizeof(PCB_FRAGMENT)+sizeof(FRAME));
if (mem_ptr==NULL) {
return FALSE;
}
pcb_ptr = (PCB_PTR) mem_ptr;
packet_ptr = (FRAME_PTR)&mem_ptr[sizeof(PCB)+sizeof(PCB_FRAGMENT)];
memcpy( phy_packet_ptr->DST [0], MY_FRAME, sizeof(MY_FRAME));
pcb_ptr->FREE = free_pcb;
pcb_ptr->FRAG[0].LENGTH = sizeof(FRAME);
pcb_ptr->FRAG[0].FRAGMENT = (uchar_ptr)packet_ptr;
if((ENET_send_raw(RTCS_get_enet_handle (ipcfg_get_ihandle(portHandle->device_number)), pcb_ptr)) == ENET_OK)
return TRUE;
else
return FALSE;
------------------------------------------
Regards
MichalP
Hi Michal:
I'm trying to debug this code at the TWR MCF51CN128 KIT, but codewarrior don't recognize the functions and parameters like RTCS_get_enet_handle and MQX1588_ihandle, I don't know if I'm missing something.
Thanks,
Daniel.
Hello Daniel,
RTCS_get_enet_handle should be accessible from the application, do not forget to include path to the compiled RTCS library (<MQX installation folder>\lib\<board>\<target>\rtcs\rtcs.a) and to include the "rtcs.h" into you code. As for the MQX1588_ihandle variable this is just an example from an application. You can get the ihandle by calling ipcfg_get_ihandle(ENET_DEVICE) so for registering the protocol type you can call:
if ((ENET_open((RTCS_get_enet_handle (ipcfg_get_ihandle(ENET_DEVICE))), 0x88F7, MQX1588_Recv_L2_1588, NULL)) != ENET_OK)
{
printf("Registering an EtherType value for IEEE 1588 (0x88 0xF7) protocol failed.\n");
}
see <MQX installation folder>\mqx\source\io\enet\enopen.c for description of ENET_open function and it's parameters.
Regards
MichalP
Hi Michal:
I have done what you adviced me to "see <MQX installation folder>\mqx\source\io\enet\enopen.c for description of ENET_open function and it's parameters."
I know that “ENET_open” Registers a protocol type on an Ethernet channel.
and the structure is like this:
uint_32 ENET_open
(
/* [IN] the Ethernet state structure */
_enet_handle handle,
/* [IN] the protocol */
uint_16 type,
/* [IN] the callback function */
void (_CODE_PTR_ service)(PCB_PTR, pointer),
/* [IN] private data for the callback */
pointer private
)
I don´t know how to use the callback function and also the private data for the callback??
I also found this function ENET_send for send a packet and this is the structure of it:
uint_32 ENET_send
(
/* [IN] the Ethernet state structure */
_enet_handle handle,
/* [IN] the packet to send */
PCB_PTR packet,
/* [IN] the protocol */
uint_16 type,
/* [IN] the destination Ethernet address */
_enet_address dest,
/* [IN] optional flags, zero = default */
uint_32 flags
)
I don´t know if this is the same function that you use call "ENET_send_raw"?
Im still having troubles trying to understand this functions…
Thanks,
Hello Daniel,
let's consider we have registered 0x88F7 protocol type on an Ethernet channel by:
ENET_open((RTCS_get_enet_handle (ipcfg_get_ihandle(ENET_DEVICE))), 0x88F7, MQX1588_Recv_L2_1588, enet_ptr)
where enet_ptr of ENET_CONTEXT_STRUCT_PTR type is the requested private data to be passsed to the MQX1588_Recv_L2_1588 callback function.
Then the callback function should look like this:
void MQX1588_Recv_L2_1588
(
PCB_PTR pcb, /* [IN] the received packet */
pointer private /* [IN] pointer to private data */
)
{
ENET_CONTEXT_STRUCT_PTR enet_ptr = (ENET_CONTEXT_STRUCT_PTR) private;
MACNET_CONTEXT_STRUCT_PTR macnet_context_ptr = (MACNET_CONTEXT_STRUCT_PTR)enet_ptr->MAC_CONTEXT_PTR;
/* Now you have the pointer to the Ethernet packet in pcb->FRAG[0].FRAGMENT
and the buffer length in pcb->FRAG[0].LENGTH) */
/* Do not forget to free the memory after the packet payload is read or passed to another user buffer */
PCB_free(pcb);
}
As for functions for sending, use the ENET_send_raw function for sending data from one device to another device using just their MAC addresses - that's what's discuseed in this thread. You can find how to do it from previous items of this thread.
Regards
MichalP
Hello Michal,
I am using your code above to send an Ethernet frame but I get an error on the line: pcb_ptr->FREE = free_pcb; (undefined indentifier free_pcb). When I remove this line I am able to send the frame but after that the program stops after printing
pNET
Here is my actual code:
mem_ptr = _mem_alloc_zero(sizeof(PCB)+sizeof(PCB_FRAGMENT)+sizeof(FRAME));
pcb_ptr = (PCB_PTR) mem_ptr;
packet_ptr = (FRAME_PTR) & mem_ptr[sizeof(PCB)+sizeof(PCB_FRAGMENT)];
memcpy( packet_ptr, gs_buf, sizeof(gs_buf));
pcb_ptr->FREE = free_pcb;
pcb_ptr->FRAG[0].LENGTH = sizeof(FRAME);
pcb_ptr->FRAG[0].FRAGMENT = (uchar_ptr)packet_ptr;
if((ENET_send_raw(RTCS_get_enet_handle (ipcfg_get_ihandle(ENET_DEVICE)), pcb_ptr)) != ENET_OK)
printf("ENET Error\n");
else
printf("pNET Sent\n");
I am working with MQX 3.8.1 and CW10.3 and I can not identify the name of the function I need to use in pcb_ptr->FREE =
Could you please point out to the right function
Thank you, Kroum
free_pcb it is a function which frees the memory after the packet is sent by ENET, something like this:
void free_pcb
(
/* [IN] the PCB to enqueue */
PCB_PTR pcb_ptr
)
{
_mem_free(pcb_ptr);
}
Thank you, Fire Brizz! I got it working.
Kroum
Did you get this working? I have having the same problem.