1 /***********************************************************************************************************************
2 * DISCLAIMER
3 * This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No
4 * other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all
5 * applicable laws, including copyright laws.
6 * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
7 * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,
8 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM
9 * EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES
10 * SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS
11 * SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
12 * Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of
13 * this software. By using this software, you agree to the additional terms and conditions found by accessing the
14 * following link:
15 * http://www.renesas.com/disclaimer
16 *
17 * Copyright (C) 2020 Renesas Electronics Corporation. All rights reserved.
18 ***********************************************************************************************************************/
19 
20 /***********************************************************************************************************************
21 * File Name    : NetworkInterface.c
22 * Device(s)    : RX
23 * Description  : Interfaces FreeRTOS TCP/IP stack to RX Ethernet driver.
24 ***********************************************************************************************************************/
25 
26 /***********************************************************************************************************************
27 * History : DD.MM.YYYY Version  Description
28 *         : 07.03.2018 0.1     Development
29 ***********************************************************************************************************************/
30 
31 /***********************************************************************************************************************
32 *  Includes   <System Includes> , "Project Includes"
33 ***********************************************************************************************************************/
34 #include <stdint.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 
39 /* FreeRTOS includes. */
40 #include "FreeRTOS.h"
41 #include "task.h"
42 #include "FreeRTOS_IP.h"
43 #include "FreeRTOS_IP_Private.h"
44 /*#include "FreeRTOS_DNS.h" */
45 #include "NetworkBufferManagement.h"
46 #include "NetworkInterface.h"
47 
48 #include "r_ether_rx_if.h"
49 #include "r_pinset.h"
50 
51 /***********************************************************************************************************************
52  * Macro definitions
53  **********************************************************************************************************************/
54 #define ETHER_BUFSIZE_MIN    60
55 
56 #if defined( BSP_MCU_RX65N ) || defined( BSP_MCU_RX64M ) || defined( BSP_MCU_RX71M ) || defined( BSP_MCU_RX72M ) || defined( BSP_MCU_RX72N )
57     #if ETHER_CFG_MODE_SEL == 0
58         #define R_ETHER_PinSet_CHANNEL_0()    R_ETHER_PinSet_ETHERC0_MII()
59     #elif ETHER_CFG_MODE_SEL == 1
60         #define R_ETHER_PinSet_CHANNEL_0()    R_ETHER_PinSet_ETHERC0_RMII()
61     #endif
62 #elif defined( BSP_MCU_RX63N )
63     #if ETHER_CFG_MODE_SEL == 0
64         #define R_ETHER_PinSet_CHANNEL_0()    R_ETHER_PinSet_ETHERC_MII()
65     #elif ETHER_CFG_MODE_SEL == 1
66         #define R_ETHER_PinSet_CHANNEL_0()    R_ETHER_PinSet_ETHERC_RMII()
67     #endif
68 #endif /* if defined( BSP_MCU_RX65N ) || defined( BSP_MCU_RX64M ) || defined( BSP_MCU_RX71M ) */
69 
70 #if defined( PHY_LS_HIGH_CHECK_TIME_MS ) || defined( PHY_LS_LOW_CHECK_TIME_MS )
71     #error please use the new defines with 'ipconfig' prefix
72 #endif
73 
74 #ifndef ipconfigPHY_LS_HIGH_CHECK_TIME_MS
75 
76 /* Check if the LinkStatus in the PHY is still high after 2 seconds of not
77  * receiving packets. */
78     #define ipconfigPHY_LS_HIGH_CHECK_TIME_MS    2000U
79 #endif
80 
81 #ifndef ipconfigPHY_LS_LOW_CHECK_TIME_MS
82     /* Check if the LinkStatus in the PHY is still low every second. */
83     #define ipconfigPHY_LS_LOW_CHECK_TIME_MS    1000U
84 #endif
85 
86 
87 /***********************************************************************************************************************
88  * Private global variables and functions
89  **********************************************************************************************************************/
90 typedef enum
91 {
92     eMACInit,   /* Must initialise MAC. */
93     eMACPass,   /* Initialisation was successful. */
94     eMACFailed, /* Initialisation failed. */
95 } eMAC_INIT_STATUS_TYPE;
96 
97 static TaskHandle_t ether_receive_check_task_handle = NULL;
98 static TaskHandle_t xTaskToNotify = NULL;
99 static BaseType_t xPHYLinkStatus;
100 static BaseType_t xReportedStatus;
101 static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;
102 
103 /* Pointer to the interface object of this NIC */
104 static NetworkInterface_t * pxMyInterface = NULL;
105 
106 static int16_t SendData( uint8_t * pucBuffer,
107                          size_t length );
108 static int InitializeNetwork( void );
109 static void prvEMACDeferredInterruptHandlerTask( void * pvParameters );
110 static void clear_all_ether_rx_discriptors( uint32_t event );
111 
112 int32_t callback_ether_regist( void );
113 void EINT_Trig_isr( void * );
114 void get_random_number( uint8_t * data,
115                         uint32_t len );
116 
117 void prvLinkStatusChange( BaseType_t xStatus );
118 
119 /*-----------------------------------------------------------*/
120 
121 NetworkInterface_t * pxRX_FillInterfaceDescriptor( BaseType_t xEMACIndex,
122                                                    NetworkInterface_t * pxInterface );
123 
124 /* Function to initialise the network interface */
125 BaseType_t xRX_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface );
126 
127 BaseType_t xRX_NetworkInterfaceOutput( NetworkInterface_t * pxInterface,
128                                        NetworkBufferDescriptor_t * const pxDescriptor,
129                                        BaseType_t bReleaseAfterSend );
130 
131 static inline BaseType_t xRX_PHYGetLinkStatus( NetworkInterface_t * pxInterface );
132 
pxRX_FillInterfaceDescriptor(BaseType_t xEMACIndex,NetworkInterface_t * pxInterface)133 NetworkInterface_t * pxRX_FillInterfaceDescriptor( BaseType_t xEMACIndex,
134                                                    NetworkInterface_t * pxInterface )
135 {
136     static char pcName[ 17 ];
137 
138     /* This function pxRX_FillInterfaceDescriptor() adds a network-interface.
139      * Make sure that the object pointed to by 'pxInterface'
140      * is declared static or global, and that it will remain to exist. */
141 
142     snprintf( pcName, sizeof( pcName ), "eth%u", ( unsigned ) xEMACIndex );
143 
144     memset( pxInterface, '\0', sizeof( *pxInterface ) );
145     pxInterface->pcName = pcName;                    /* Just for logging, debugging. */
146     pxInterface->pvArgument = ( void * ) xEMACIndex; /* Has only meaning for the driver functions. */
147     pxInterface->pfInitialise = xRX_NetworkInterfaceInitialise;
148     pxInterface->pfOutput = xRX_NetworkInterfaceOutput;
149     pxInterface->pfGetPhyLinkStatus = xRX_PHYGetLinkStatus;
150 
151     FreeRTOS_AddNetworkInterface( pxInterface );
152 
153     return pxInterface;
154 }
155 
156 /***********************************************************************************************************************
157  * Function Name: xRX_NetworkInterfaceInitialise ()
158  * Description  : Initialization of Ethernet driver.
159  * Arguments    : Pointer to the interface desc
160  * Return Value : pdPASS, pdFAIL
161  **********************************************************************************************************************/
xRX_NetworkInterfaceInitialise(NetworkInterface_t * pxInterface)162 BaseType_t xRX_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface )
163 {
164     BaseType_t xReturn;
165 
166     if( xMacInitStatus == eMACInit )
167     {
168         pxMyInterface = pxInterface;
169 
170         /*
171          * Perform the hardware specific network initialization here using the Ethernet driver library to initialize the
172          * Ethernet hardware, initialize DMA descriptors, and perform a PHY auto-negotiation to obtain a network link.
173          *
174          * InitialiseNetwork() uses Ethernet peripheral driver library function, and returns 0 if the initialization fails.
175          */
176         if( InitializeNetwork() == pdFALSE )
177         {
178             xMacInitStatus = eMACFailed;
179         }
180         else
181         {
182             /* Indicate that the MAC initialisation succeeded. */
183             xMacInitStatus = eMACPass;
184         }
185 
186         FreeRTOS_printf( ( "InitializeNetwork returns %s\n", ( xMacInitStatus == eMACPass ) ? "OK" : " Fail" ) );
187     }
188 
189     if( xMacInitStatus == eMACPass )
190     {
191         xReturn = xPHYLinkStatus;
192     }
193     else
194     {
195         xReturn = pdFAIL;
196     }
197 
198     FreeRTOS_printf( ( "xNetworkInterfaceInitialise returns %d\n", xReturn ) );
199 
200     return xReturn;
201 } /* End of function xNetworkInterfaceInitialise() */
202 
203 
204 /***********************************************************************************************************************
205  * Function Name: xRX_NetworkInterfaceOutput ()
206  * Description  : Simple network output interface.
207  * Arguments    : pxInterface, pxDescriptor, xReleaseAfterSend
208  * Return Value : pdTRUE, pdFALSE
209  **********************************************************************************************************************/
xRX_NetworkInterfaceOutput(NetworkInterface_t * pxInterface,NetworkBufferDescriptor_t * const pxDescriptor,BaseType_t xReleaseAfterSend)210 BaseType_t xRX_NetworkInterfaceOutput( NetworkInterface_t * pxInterface,
211                                        NetworkBufferDescriptor_t * const pxDescriptor,
212                                        BaseType_t xReleaseAfterSend )
213 {
214     BaseType_t xReturn = pdFALSE;
215 
216     /* As there is only a single instance of the EMAC, there is only one pxInterface object. */
217     ( void ) pxInterface;
218 
219     /* Simple network interfaces (as opposed to more efficient zero copy network
220      * interfaces) just use Ethernet peripheral driver library functions to copy
221      * data from the FreeRTOS+TCP buffer into the peripheral driver's own buffer.
222      * This example assumes SendData() is a peripheral driver library function that
223      * takes a pointer to the start of the data to be sent and the length of the
224      * data to be sent as two separate parameters.  The start of the data is located
225      * by pxDescriptor->pucEthernetBuffer.  The length of the data is located
226      * by pxDescriptor->xDataLength. */
227     if( xPHYLinkStatus != 0 )
228     {
229         if( SendData( pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength ) >= 0 )
230         {
231             xReturn = pdTRUE;
232             /* Call the standard trace macro to log the send event. */
233             iptraceNETWORK_INTERFACE_TRANSMIT();
234         }
235     }
236     else
237     {
238         /* As the PHY Link Status is low, it makes no sense trying to deliver a packet. */
239     }
240 
241     if( xReleaseAfterSend != pdFALSE )
242     {
243         /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet
244          * buffer.  The Ethernet buffer is therefore no longer needed, and must be
245          * freed for re-use. */
246         vReleaseNetworkBufferAndDescriptor( pxDescriptor );
247     }
248 
249     return xReturn;
250 } /* End of function xNetworkInterfaceOutput() */
251 
252 
253 /***********************************************************************************************************************
254  * Function Name: prvEMACDeferredInterruptHandlerTask ()
255  * Description  : The deferred interrupt handler is a standard RTOS task.
256  * Arguments    : pvParameters
257  * Return Value : none
258  **********************************************************************************************************************/
prvEMACDeferredInterruptHandlerTask(void * pvParameters)259 static void prvEMACDeferredInterruptHandlerTask( void * pvParameters )
260 {
261     NetworkBufferDescriptor_t * pxBufferDescriptor;
262     int32_t xBytesReceived = 0;
263 
264     /* Avoid compiler warning about unreferenced parameter. */
265     ( void ) pvParameters;
266 
267     /* Used to indicate that xSendEventStructToIPTask() is being called because
268      * of an Ethernet receive event. */
269     IPStackEvent_t xRxEvent;
270 
271     uint8_t * buffer_pointer;
272 
273     /* Some variables related to monitoring the PHY. */
274     TimeOut_t xPhyTime;
275     TickType_t xPhyRemTime;
276     const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
277 
278     vTaskSetTimeOutState( &xPhyTime );
279     xPhyRemTime = pdMS_TO_TICKS( ipconfigPHY_LS_LOW_CHECK_TIME_MS );
280 
281     FreeRTOS_printf( ( "Deferred Interrupt Handler Task started\n" ) );
282     xTaskToNotify = ether_receive_check_task_handle;
283 
284     for( ; ; )
285     {
286         #if ( ipconfigHAS_PRINTF != 0 )
287             {
288                 /* Call a function that monitors resources: the amount of free network
289                  * buffers and the amount of free space on the heap.  See FreeRTOS_IP.c
290                  * for more detailed comments. */
291                 vPrintResourceStats();
292             }
293         #endif /* ( ipconfigHAS_PRINTF != 0 ) */
294 
295         /* Wait for the Ethernet MAC interrupt to indicate that another packet
296          * has been received.  */
297         if( xBytesReceived <= 0 )
298         {
299             ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
300         }
301 
302         /* See how much data was received.  */
303         xBytesReceived = R_ETHER_Read_ZC2( ETHER_CHANNEL_0, ( void ** ) &buffer_pointer );
304 
305         if( xBytesReceived < 0 )
306         {
307             /* This is an error. Logged. */
308             FreeRTOS_debug_printf( ( "R_ETHER_Read_ZC2: rc = %d\n", xBytesReceived ) );
309         }
310         else if( xBytesReceived > 0 )
311         {
312             /* Allocate a network buffer descriptor that points to a buffer
313              * large enough to hold the received frame.  As this is the simple
314              * rather than efficient example the received data will just be copied
315              * into this buffer. */
316             pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( ( size_t ) xBytesReceived, 0 );
317 
318             if( pxBufferDescriptor != NULL )
319             {
320                 /* pxBufferDescriptor->pucEthernetBuffer now points to an Ethernet
321                  * buffer large enough to hold the received data.  Copy the
322                  * received data into pcNetworkBuffer->pucEthernetBuffer.  Here it
323                  * is assumed ReceiveData() is a peripheral driver function that
324                  * copies the received data into a buffer passed in as the function's
325                  * parameter.  Remember! While is is a simple robust technique -
326                  * it is not efficient.  An example that uses a zero copy technique
327                  * is provided further down this page. */
328                 memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer_pointer, ( size_t ) xBytesReceived );
329                 /*ReceiveData( pxBufferDescriptor->pucEthernetBuffer ); */
330 
331                 /* Set the actual packet length, in case a larger buffer was returned. */
332                 pxBufferDescriptor->xDataLength = ( size_t ) xBytesReceived;
333                 pxBufferDescriptor->pxInterface = pxMyInterface;
334                 pxBufferDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pxBufferDescriptor->pucEthernetBuffer );
335 
336                 R_ETHER_Read_ZC2_BufRelease( ETHER_CHANNEL_0 );
337 
338                 /* See if the data contained in the received Ethernet frame needs
339                 * to be processed.  NOTE! It is preferable to do this in
340                 * the interrupt service routine itself, which would remove the need
341                 * to unblock this task for packets that don't need processing. */
342                 if( ( eConsiderFrameForProcessing( pxBufferDescriptor->pucEthernetBuffer ) == eProcessBuffer ) && ( pxBufferDescriptor->pxEndPoint != NULL ) )
343                 {
344                     /* The event about to be sent to the TCP/IP is an Rx event. */
345                     xRxEvent.eEventType = eNetworkRxEvent;
346 
347                     /* pvData is used to point to the network buffer descriptor that
348                      * now references the received data. */
349                     xRxEvent.pvData = ( void * ) pxBufferDescriptor;
350 
351                     /* Send the data to the TCP/IP stack. */
352                     if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
353                     {
354                         /* The buffer could not be sent to the IP task so the buffer must be released. */
355                         vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
356 
357                         /* Make a call to the standard trace macro to log the occurrence. */
358                         iptraceETHERNET_RX_EVENT_LOST();
359                         clear_all_ether_rx_discriptors( 0 );
360                     }
361                     else
362                     {
363                         /* The message was successfully sent to the TCP/IP stack.
364                         * Call the standard trace macro to log the occurrence. */
365                         iptraceNETWORK_INTERFACE_RECEIVE();
366                         R_BSP_NOP();
367                     }
368                 }
369                 else
370                 {
371                     /* The Ethernet frame can be dropped, but the Ethernet buffer must be released. */
372                     vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
373                 }
374             }
375             else
376             {
377                 /* The event was lost because a network buffer was not available.
378                  * Call the standard trace macro to log the occurrence. */
379                 iptraceETHERNET_RX_EVENT_LOST();
380                 clear_all_ether_rx_discriptors( 1 );
381                 FreeRTOS_printf( ( "R_ETHER_Read_ZC2: Cleared descriptors\n" ) );
382             }
383         }
384 
385         if( xBytesReceived > 0 )
386         {
387             /* A packet was received. No need to check for the PHY status now,
388              * but set a timer to check it later on. */
389             vTaskSetTimeOutState( &xPhyTime );
390             xPhyRemTime = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
391 
392             /* Indicate that the Link Status is high, so that
393              * xNetworkInterfaceOutput() can send packets. */
394             if( xPHYLinkStatus == 0 )
395             {
396                 xPHYLinkStatus = 1;
397                 FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS assume %d\n", xPHYLinkStatus ) );
398             }
399         }
400         else if( ( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) || ( FreeRTOS_IsNetworkUp() == pdFALSE ) )
401         {
402             R_ETHER_LinkProcess( ETHER_CHANNEL_0 );
403 
404             if( xPHYLinkStatus != xReportedStatus )
405             {
406                 xPHYLinkStatus = xReportedStatus;
407                 FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", xPHYLinkStatus ) );
408             }
409 
410             vTaskSetTimeOutState( &xPhyTime );
411 
412             if( xPHYLinkStatus != 0 )
413             {
414                 xPhyRemTime = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
415             }
416             else
417             {
418                 xPhyRemTime = pdMS_TO_TICKS( ipconfigPHY_LS_LOW_CHECK_TIME_MS );
419             }
420         }
421     }
422 } /* End of function prvEMACDeferredInterruptHandlerTask() */
423 
424 
425 /***********************************************************************************************************************
426  * Function Name: vNetworkInterfaceAllocateRAMToBuffers ()
427  * Description  : .
428  * Arguments    : pxNetworkBuffers
429  * Return Value : none
430  **********************************************************************************************************************/
431 
vNetworkInterfaceAllocateRAMToBuffers(NetworkBufferDescriptor_t pxNetworkBuffers[ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS])432 void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
433 {
434     uint32_t ul;
435     uint8_t * buffer_address;
436     portPOINTER_SIZE_TYPE uxStartAddress;
437 
438     static uint8_t ETH_BUFFERS[ ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * ETHER_CFG_BUFSIZE ) + portBYTE_ALIGNMENT ];
439 
440     /* Align the buffer start address to portBYTE_ALIGNMENT bytes */
441     uxStartAddress = ( portPOINTER_SIZE_TYPE ) & ETH_BUFFERS[ 0 ];
442     uxStartAddress += portBYTE_ALIGNMENT;
443     uxStartAddress &= ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK );
444 
445     buffer_address = ( uint8_t * ) uxStartAddress;
446 
447     for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
448     {
449         pxNetworkBuffers[ ul ].pucEthernetBuffer = buffer_address + ipBUFFER_PADDING;
450         *( ( unsigned * ) buffer_address ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
451         buffer_address += ETHER_CFG_BUFSIZE;
452     }
453 } /* End of function vNetworkInterfaceAllocateRAMToBuffers() */
454 
455 /***********************************************************************************************************************
456  * Function Name: prvLinkStatusChange ()
457  * Description  : Function will be called when the Link Status of the phy has changed ( see ether_callback.c )
458  * Arguments    : xStatus : true when status has become high
459  * Return Value : void
460  **********************************************************************************************************************/
prvLinkStatusChange(BaseType_t xStatus)461 void prvLinkStatusChange( BaseType_t xStatus )
462 {
463     if( xReportedStatus != xStatus )
464     {
465         FreeRTOS_printf( ( "prvLinkStatusChange( %d )\n", xStatus ) );
466         xReportedStatus = xStatus;
467     }
468 }
469 
470 /***********************************************************************************************************************
471  * Function Name: InitializeNetwork ()
472  * Description  :
473  * Arguments    : none
474  * Return Value : pdTRUE, pdFALSE
475  **********************************************************************************************************************/
InitializeNetwork(void)476 static int InitializeNetwork( void )
477 {
478     ether_return_t eth_ret;
479     BaseType_t return_code = pdFALSE;
480     ether_param_t param;
481 
482     /* Read the mac address after it has been initilized by the FreeRTOS IP Stack, rather than from defines
483      * as the mac address is usually read from the EEPROM, and it might be different to the mac address in
484      * the defines, especially in production environments
485      */
486     configASSERT( pxMyInterface );
487     const uint8_t * myethaddr = &pxMyInterface->pxEndPoint->xMACAddress.ucBytes[ 0 ];
488 
489     R_ETHER_PinSet_CHANNEL_0();
490     R_ETHER_Initial();
491     callback_ether_regist();
492 
493     param.channel = ETHER_CHANNEL_0;
494     eth_ret = R_ETHER_Control( CONTROL_POWER_ON, param ); /* PHY mode settings, module stop cancellation */
495 
496     if( ETHER_SUCCESS != eth_ret )
497     {
498         return pdFALSE;
499     }
500 
501     eth_ret = R_ETHER_Open_ZC2( ETHER_CHANNEL_0, myethaddr, ETHER_FLAG_OFF );
502 
503     if( ETHER_SUCCESS != eth_ret )
504     {
505         return pdFALSE;
506     }
507 
508     if( ether_receive_check_task_handle == NULL )
509     {
510         return_code = xTaskCreate( prvEMACDeferredInterruptHandlerTask,
511                                    "ETHER_RECEIVE_CHECK_TASK",
512                                    512u,
513                                    0,
514                                    configMAX_PRIORITIES - 1,
515                                    &ether_receive_check_task_handle );
516     }
517     else
518     {
519         return_code = pdTRUE;
520     }
521 
522     if( pdFALSE == return_code )
523     {
524         return pdFALSE;
525     }
526 
527     return pdTRUE;
528 } /* End of function InitializeNetwork() */
529 
530 
531 /***********************************************************************************************************************
532  * Function Name: SendData ()
533  * Description  :
534  * Arguments    : pucBuffer, length
535  * Return Value : 0 success, negative fail
536  **********************************************************************************************************************/
SendData(uint8_t * pucBuffer,size_t length)537 static int16_t SendData( uint8_t * pucBuffer,
538                          size_t length ) /*TODO complete stub function */
539 {
540     ether_return_t ret;
541     uint8_t * pwrite_buffer;
542     uint16_t write_buf_size;
543 
544     /* (1) Retrieve the transmit buffer location controlled by the  descriptor. */
545     ret = R_ETHER_Write_ZC2_GetBuf( ETHER_CHANNEL_0, ( void ** ) &pwrite_buffer, &write_buf_size );
546 
547     if( ETHER_SUCCESS == ret )
548     {
549         if( write_buf_size >= length )
550         {
551             memcpy( pwrite_buffer, pucBuffer, length );
552         }
553 
554         if( length < ETHER_BUFSIZE_MIN )                                             /*under minimum*/
555         {
556             memset( ( pwrite_buffer + length ), 0, ( ETHER_BUFSIZE_MIN - length ) ); /*padding*/
557             length = ETHER_BUFSIZE_MIN;                                              /*resize*/
558         }
559 
560         ret = R_ETHER_Write_ZC2_SetBuf( ETHER_CHANNEL_0, ( uint16_t ) length );
561         ret = R_ETHER_CheckWrite( ETHER_CHANNEL_0 );
562     }
563 
564     if( ETHER_SUCCESS != ret )
565     {
566         return -5; /* XXX return meaningful value */
567     }
568     else
569     {
570         return 0;
571     }
572 } /* End of function SendData() */
573 
574 
575 /***********************************************************************************************************************
576 * Function Name: EINT_Trig_isr
577 * Description  : Standard frame received interrupt handler
578 * Arguments    : ectrl - EDMAC and ETHERC control structure
579 * Return Value : None
580 * Note         : This callback function is executed when EINT0 interrupt occurred.
581 ***********************************************************************************************************************/
EINT_Trig_isr(void * ectrl)582 void EINT_Trig_isr( void * ectrl )
583 {
584     ether_cb_arg_t * pdecode;
585     BaseType_t xHigherPriorityTaskWoken = pdFALSE;
586 
587     pdecode = ( ether_cb_arg_t * ) ectrl;
588 
589     if( pdecode->status_eesr & 0x00040000 ) /* EDMAC FR (Frame Receive Event) interrupt */
590     {
591         if( xTaskToNotify != NULL )
592         {
593             vTaskNotifyGiveFromISR( ether_receive_check_task_handle, &xHigherPriorityTaskWoken );
594         }
595 
596         /* If xHigherPriorityTaskWoken is now set to pdTRUE then a context switch
597          * should be performed to ensure the interrupt returns directly to the highest
598          * priority task.  The macro used for this purpose is dependent on the port in
599          * use and may be called portEND_SWITCHING_ISR(). */
600         portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
601         /*TODO complete interrupt handler for other events. */
602     }
603 } /* End of function EINT_Trig_isr() */
604 
605 
clear_all_ether_rx_discriptors(uint32_t event)606 static void clear_all_ether_rx_discriptors( uint32_t event )
607 {
608     int32_t xBytesReceived;
609     uint8_t * buffer_pointer;
610 
611     /* Avoid compiler warning about unreferenced parameter. */
612     ( void ) event;
613 
614     while( 1 )
615     {
616         /* See how much data was received.  */
617         xBytesReceived = R_ETHER_Read_ZC2( ETHER_CHANNEL_0, ( void ** ) &buffer_pointer );
618 
619         if( 0 > xBytesReceived )
620         {
621             /* This is an error. Ignored. */
622         }
623         else if( 0 < xBytesReceived )
624         {
625             R_ETHER_Read_ZC2_BufRelease( ETHER_CHANNEL_0 );
626             iptraceETHERNET_RX_EVENT_LOST();
627         }
628         else
629         {
630             break;
631         }
632     }
633 }
634 
xRX_PHYGetLinkStatus(NetworkInterface_t * pxInterface)635 static inline BaseType_t xRX_PHYGetLinkStatus( NetworkInterface_t * pxInterface )
636 {
637     ( void ) pxInterface;
638     return( xPHYLinkStatus != 0 );
639 }
640 
641 
642 /***********************************************************************************************************************
643  * End of file "NetworkInterface.c"
644  **********************************************************************************************************************/
645