xref: /FreeRTOS-Plus-TCP-v4.0.0/source/portable/NetworkInterface/Zynq/x_emacpsif_hw.c (revision 2d3f4daa567ffe71aeda2e0f6d0bc02850db0627)
1 /*
2  * Copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.
3  *
4  * Xilinx, Inc.
5  * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
6  * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
7  * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
8  * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
9  * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
10  * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
11  * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
12  * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
13  * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
14  * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  */
18 
19 
20 /* Standard includes. */
21 #include <stdint.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 
25 /* FreeRTOS includes. */
26 #include "FreeRTOS.h"
27 #include "task.h"
28 #include "queue.h"
29 
30 /* FreeRTOS+TCP includes. */
31 #include "FreeRTOS_IP.h"
32 #include "FreeRTOS_Sockets.h"
33 #include "FreeRTOS_IP_Private.h"
34 #include "FreeRTOS_Routing.h"
35 #include "NetworkBufferManagement.h"
36 #include "NetworkInterface.h"
37 
38 #include "Zynq/x_emacpsif.h"
39 
40 extern TaskHandle_t xEMACTaskHandles[ XPAR_XEMACPS_NUM_INSTANCES ];
41 
42 /*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
43  *** to run it on a PEEP board
44  ***/
45 
setup_isr(xemacpsif_s * xemacpsif)46 void setup_isr( xemacpsif_s * xemacpsif )
47 {
48     /*
49      * Setup callbacks
50      */
51     XEmacPs_SetHandler( &xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
52                         ( void * ) emacps_send_handler,
53                         ( void * ) xemacpsif );
54 
55     XEmacPs_SetHandler( &xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
56                         ( void * ) emacps_recv_handler,
57                         ( void * ) xemacpsif );
58 
59     XEmacPs_SetHandler( &xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
60                         ( void * ) emacps_error_handler,
61                         ( void * ) xemacpsif );
62 }
63 
start_emacps(xemacpsif_s * xemacps)64 void start_emacps( xemacpsif_s * xemacps )
65 {
66     /* start the temac */
67     XEmacPs_Start( &xemacps->emacps );
68 }
69 
70 
71 volatile int error_msg_count = 0;
72 volatile const char * last_err_msg = "";
73 
74 struct xERROR_MSG
75 {
76     void * arg;
77     u8 Direction;
78     u32 ErrorWord;
79 };
80 
81 static struct xERROR_MSG xErrorList[ 8 ];
82 static BaseType_t xErrorHead, xErrorTail;
83 
emacps_error_handler(void * arg,u8 Direction,u32 ErrorWord)84 void emacps_error_handler( void * arg,
85                            u8 Direction,
86                            u32 ErrorWord )
87 {
88     BaseType_t xHigherPriorityTaskWoken = pdFALSE;
89     xemacpsif_s * xemacpsif;
90     BaseType_t xNextHead = xErrorHead;
91     BaseType_t xEMACIndex;
92 
93     xemacpsif = ( xemacpsif_s * ) ( arg );
94     xEMACIndex = xemacpsif->emacps.Config.DeviceId;
95 
96     if( ( Direction != XEMACPS_SEND ) || ( ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) )
97     {
98         if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) )
99         {
100             xNextHead = 0;
101         }
102 
103         if( xNextHead != xErrorTail )
104         {
105             xErrorList[ xErrorHead ].arg = arg;
106             xErrorList[ xErrorHead ].Direction = Direction;
107             xErrorList[ xErrorHead ].ErrorWord = ErrorWord;
108 
109             xErrorHead = xNextHead;
110 
111             xemacpsif = ( xemacpsif_s * ) ( arg );
112             xemacpsif->isr_events |= EMAC_IF_ERR_EVENT;
113         }
114 
115         if( xEMACTaskHandles[ xEMACIndex ] != NULL )
116         {
117             vTaskNotifyGiveFromISR( xEMACTaskHandles[ xEMACIndex ], &xHigherPriorityTaskWoken );
118         }
119     }
120 
121     portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
122 }
123 
124 static void emacps_handle_error( void * arg,
125                                  u8 Direction,
126                                  u32 ErrorWord );
127 
emacps_check_errors(xemacpsif_s * xemacps)128 int emacps_check_errors( xemacpsif_s * xemacps )
129 {
130     int xResult;
131 
132     ( void ) xemacps;
133 
134     if( xErrorHead == xErrorTail )
135     {
136         xResult = 0;
137     }
138     else
139     {
140         xResult = 1;
141         emacps_handle_error(
142             xErrorList[ xErrorTail ].arg,
143             xErrorList[ xErrorTail ].Direction,
144             xErrorList[ xErrorTail ].ErrorWord );
145     }
146 
147     return xResult;
148 }
149 
emacps_handle_error(void * arg,u8 Direction,u32 ErrorWord)150 static void emacps_handle_error( void * arg,
151                                  u8 Direction,
152                                  u32 ErrorWord )
153 {
154     xemacpsif_s * xemacpsif;
155     XEmacPs * xemacps;
156     BaseType_t xEMACIndex;
157 
158     xemacpsif = ( xemacpsif_s * ) ( arg );
159 
160     xemacps = &xemacpsif->emacps;
161     xEMACIndex = xemacps->Config.DeviceId;
162 
163     last_err_msg = NULL;
164 
165     if( ErrorWord != 0 )
166     {
167         switch( Direction )
168         {
169             case XEMACPS_RECV:
170 
171                 if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 )
172                 {
173                     last_err_msg = "Receive DMA error";
174                     vInitialiseOnIndex( xEMACIndex );
175                 }
176 
177                 if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 )
178                 {
179                     last_err_msg = "Receive over run";
180                     emacps_recv_handler( arg );
181                 }
182 
183                 if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 )
184                 {
185                     last_err_msg = "Receive buffer not available";
186                     emacps_recv_handler( arg );
187                 }
188 
189                 break;
190 
191             case XEMACPS_SEND:
192 
193                 if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 )
194                 {
195                     last_err_msg = "Transmit DMA error";
196                     vInitialiseOnIndex( xEMACIndex );
197                 }
198 
199                 if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 )
200                 {
201                     last_err_msg = "Transmit under run";
202                     HandleTxErrors( xemacpsif );
203                 }
204 
205                 if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 )
206                 {
207                     last_err_msg = "Transmit buffer exhausted";
208                     HandleTxErrors( xemacpsif );
209                 }
210 
211                 if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 )
212                 {
213                     last_err_msg = "Transmit retry excessed limits";
214                     HandleTxErrors( xemacpsif );
215                 }
216 
217                 if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 )
218                 {
219                     last_err_msg = "Transmit collision";
220                     emacps_check_tx( xemacpsif );
221                 }
222 
223                 break;
224         }
225     }
226 
227     /* Break on this statement and inspect error_msg if you like */
228     if( last_err_msg != NULL )
229     {
230         error_msg_count++;
231         FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) );
232     }
233 }
234 
HandleTxErrors(xemacpsif_s * xemacpsif)235 void HandleTxErrors( xemacpsif_s * xemacpsif )
236 {
237     u32 netctrlreg;
238 
239     /*taskENTER_CRITICAL() */
240     {
241         netctrlreg = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress,
242                                       XEMACPS_NWCTRL_OFFSET );
243         netctrlreg = netctrlreg & ( ~XEMACPS_NWCTRL_TXEN_MASK );
244         XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress,
245                           XEMACPS_NWCTRL_OFFSET, netctrlreg );
246 
247         clean_dma_txdescs( xemacpsif );
248         netctrlreg = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress,
249                                       XEMACPS_NWCTRL_OFFSET );
250         netctrlreg = netctrlreg | ( XEMACPS_NWCTRL_TXEN_MASK );
251         XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress,
252                           XEMACPS_NWCTRL_OFFSET, netctrlreg );
253     }
254     /*taskEXIT_CRITICAL( ); */
255 }
256