xref: /FreeRTOS-Plus-TCP-v4.0.0/source/portable/NetworkInterface/ThirdParty/MSP432/NetworkMiddleware.c (revision 1ab6eb88857cf1011bf1f8349b43a1c34c7ced0f)
1 /*
2  * FreeRTOS+TCP <DEVELOPMENT BRANCH>
3  * Copyright (C) 2022 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Driver code:
8  * Copyright (C) Nicholas J. Kinar <n.kinar@usask.ca>, Centre for Hydrology, University of Saskatchewan
9  *
10  * MSP432 Driverlib (C) 2017-2019 Texas Instruments Incorporated <https://www.ti.com/>
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy of
13  * this software and associated documentation files (the "Software"), to deal in
14  * the Software without restriction, including without limitation the rights to
15  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
16  * the Software, and to permit persons to whom the Software is furnished to do so,
17  * subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in all
20  * copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
25  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
26  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28  *
29  * http://aws.amazon.com/freertos
30  * http://www.FreeRTOS.org
31  */
32 
33 #include <stdint.h>
34 
35 #include "FreeRTOS.h"
36 #include "FreeRTOS_IP.h"
37 #include "FreeRTOS_IP_private.h"
38 #include "FreeRTOS_Sockets.h"
39 
40 #include "NetworkMiddleware.h"
41 #include "NetworkInterface.h"
42 
43 /* Waiting time between network EMAC hardware up and down */
44 #define TIME_TO_WAIT_BETWEEN_NETUP_DOWN    2000
45 
46 /* Stack for up and down thread */
47 #define NETWORK_TASK_MIDDLEWARE_STACK      1000
48 
49 /* Holds the device name used for LLMNR */
50 static char DEV_NAME[ MAX_NAME_LLMNR ];
51 
52 /* This function is provided by external code to obtain a random number */
53 extern uint32_t obtain_rand32();
54 
55 static SemaphoreHandle_t xSemaphore = NULL;
56 static TaskHandle_t xTaskToNotifyReset = NULL;
57 static uint32_t xDelay;
58 
59 static void prvNetworkResetTask( void * pvParameters );
60 
61 
62 /*  Call this function before starting the scheduler and after the MAC address and device name has been loaded.
63  *  The function can only be called once to set up the tasks. */
vPublicSetupFreeRTOSTasks(const struct InternalNetworkMiddlewareData data)64 void vPublicSetupFreeRTOSTasks( const struct InternalNetworkMiddlewareData data )
65 {
66     /* setup a device name */
67     vPublicSetupDeviceName( data.deviceName );
68 
69     /* get the MAC address from the driver code (assuming this is also set up) */
70     uint8_t uc8MACAddr[ ipMAC_ADDRESS_LENGTH_BYTES ];
71     vPublicGetMACAddr( uc8MACAddr );
72 
73     /* set up the task to reset the network every so often */
74     if( data.resetNetworkTaskRunning == pdTRUE )
75     {
76         xDelay = data.resetNetworkTaskEveryXSeconds;
77         xSemaphore = xSemaphoreCreateMutex();
78         xTaskCreate( prvNetworkResetTask,
79                      "resetNet",
80                      NETWORK_TASK_MIDDLEWARE_STACK,
81                      NULL,
82                      tskIDLE_PRIORITY,
83                      &xTaskToNotifyReset );
84     }
85 
86     /* init the network stack */
87     FreeRTOS_IPInit( data.ucIPAddress,
88                      data.ucNetMask,
89                      data.ucGatewayAddress,
90                      data.ucDNSServerAddress,
91                      uc8MACAddr );
92 }
93 
94 
95 /* Helper function to assign bytes to an array used to indicate the IP address */
vConvertOctetsToAddr(uint8_t arr[ipIP_ADDRESS_LENGTH_BYTES],uint8_t b0,uint8_t b1,uint8_t b2,uint8_t b3)96 void vConvertOctetsToAddr( uint8_t arr[ ipIP_ADDRESS_LENGTH_BYTES ],
97                            uint8_t b0,
98                            uint8_t b1,
99                            uint8_t b2,
100                            uint8_t b3 )
101 {
102     arr[ 0 ] = b0;
103     arr[ 1 ] = b1;
104     arr[ 2 ] = b2;
105     arr[ 3 ] = b3;
106 } /* end */
107 
108 
109 /* Task that resets the network every so often */
prvNetworkResetTask(void * pvParameters)110 void prvNetworkResetTask( void * pvParameters )
111 {
112     uint32_t cnt;
113 
114     cnt = 0;
115 
116     for( ; ; )
117     {
118         vTaskDelay( pdMS_TO_TICKS( 1000 ) );
119         cnt++;
120 
121         if( cnt > xDelay )
122         {
123             cnt = 0;
124 
125             if( xSemaphoreTake( xSemaphore, 0 ) == pdTRUE )
126             {
127                 FreeRTOS_NetworkDown();
128                 xSemaphoreGive( xSemaphore );
129             }
130         }
131     }
132 }
133 
134 
135 /* Call this function from a task to prevent a network reset during a critical section of the code */
publicPreventNetworkReset(const BaseType_t preventReset,const uint32_t waitTime)136 BaseType_t publicPreventNetworkReset( const BaseType_t preventReset,
137                                       const uint32_t waitTime )
138 {
139     if( preventReset == pdTRUE )
140     {
141         if( xSemaphoreTake( xSemaphore, pdMS_TO_TICKS( waitTime ) ) == pdTRUE )
142         {
143             return pdTRUE;
144         }
145         else
146         {
147             return pdFALSE;
148         }
149     }
150     else /* do not prevent reset */
151     {
152         xSemaphoreGive( xSemaphore );
153     }
154 
155     return pdTRUE;
156 }
157 
158 
159 /*  CALLED BY FREERTOS
160  *  Function that sets pulNumber to a random number, and then returns pdTRUE.
161  *  If the random number could not be obtained, then the function will return pdFALSE. */
xApplicationGetRandomNumber(uint32_t * pulNumber)162 BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber )
163 {
164     *pulNumber = 0;
165     uint32_t num = obtain_rand32();
166 
167     if( num == 0 )
168     {
169         return pdFALSE;
170     }
171 
172     *pulNumber = num;
173     return pdTRUE;
174 }
175 
176 /*  CALLED BY FREERTOS
177  *  Function that returns a random number for TCP.  This is taken to be a random number. */
ulApplicationGetNextSequenceNumber(uint32_t ulSourceAddress,uint16_t usSourcePort,uint32_t ulDestinationAddress,uint16_t usDestinationPort)178 uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,
179                                              uint16_t usSourcePort,
180                                              uint32_t ulDestinationAddress,
181                                              uint16_t usDestinationPort )
182 {
183     uint32_t pulNumber = 0;
184 
185     xApplicationGetRandomNumber( &pulNumber );
186     return pulNumber;
187 }
188 
189 
190 /*  CALLED BY FREERTOS
191  *  Function to obtain random number */
uxRand()192 UBaseType_t uxRand()
193 {
194     uint32_t num = obtain_rand32();
195 
196     return num;
197 }
198 
199 
200 /*  CALLED BY FREERTOS
201  *   Function called when the network connects or disconnects */
vApplicationIPNetworkEventHook(eIPCallbackEvent_t eNetworkEvent)202 void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
203 {
204     uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSServerAddress;
205     static BaseType_t xNetworkTasksAlreadyCreated = pdFALSE;
206     char cBuffer[ 16 ];
207 
208     if( eNetworkEvent == eNetworkUp )
209     {
210         if( xNetworkTasksAlreadyCreated == pdFALSE )
211         {
212             /*  Unblock any necessary tasks here when the network is up
213              *  Set a flag to indicate that the tasks do not need to be created again */
214             xNetworkTasksAlreadyCreated = pdTRUE;
215         }
216 
217         FreeRTOS_GetAddressConfiguration( &ulIPAddress,
218                                           &ulNetMask,
219                                           &ulGatewayAddress,
220                                           &ulDNSServerAddress );
221 
222         FreeRTOS_inet_ntoa( ulIPAddress, cBuffer );
223         vLoggingPrintf( "IP Address: %s\r\n", cBuffer );
224 
225         FreeRTOS_inet_ntoa( ulNetMask, cBuffer );
226         vLoggingPrintf( "Subnet Mask: %s\r\n", cBuffer );
227 
228         FreeRTOS_inet_ntoa( ulGatewayAddress, cBuffer );
229         vLoggingPrintf( "Gateway IP Address: %s\r\n", cBuffer );
230 
231         FreeRTOS_inet_ntoa( ulDNSServerAddress, cBuffer );
232         vLoggingPrintf( "DNS server IP Address: %s\r\n", cBuffer );
233     } /* end if */
234     else if( eNetworkEvent == eNetworkDown )
235     {
236         xNetworkTasksAlreadyCreated = pdFALSE; /* clear a flag to indicate that the tasks needs to be created again */
237         /* Stop or block any running tasks here */
238     } /* end if */
239 } /* end */
240 
241 
242 /*  CALLED BY FREERTOS
243  *  Function that indicates there is a ping response
244  *  Called from IPTraceMacroDefaults.h
245  *  NOTE: This function can cause the stack to slow down, so it should
246  *  only be used for debugging. */
247 
248 /*
249  #ifndef iptraceSENDING_PING_REPLY
250  *  extern void pingReply( uint32_t ulIPAddress );
251  #define iptraceSENDING_PING_REPLY( ulIPAddress )  pingReply(ulIPAddress )
252  #endif
253  */
pingReply(uint32_t ulIPAddress)254 void pingReply( uint32_t ulIPAddress )
255 {
256     #ifdef SEND_PING_PRINT_REPLY
257         char cBuffer[ 16 ];
258         FreeRTOS_inet_ntoa( ulIPAddress, cBuffer );
259         vLoggingPrintf( "Ping response to: %s\r\n", cBuffer );
260     #endif
261 }
262 
263 
264 /*  CALLED BY FREERTOS when conducting a DNS query
265  *  Function that returns pdTRUE if the pcName matches the LLMNR node name */
xApplicationDNSQueryHook(const char * pcName)266 BaseType_t xApplicationDNSQueryHook( const char * pcName )
267 {
268     if( strcmp( pcName, DEV_NAME ) )
269     {
270         return pdTRUE;
271     }
272 
273     return pdFALSE;
274 }
275 
276 
277 /*  CALLED BY FREERTOS
278  *  Hook to return a human-readable name */
pcApplicationHostnameHook(void)279 const char * pcApplicationHostnameHook( void )
280 {
281     const char * name;
282 
283     name = DEV_NAME;
284     return name;
285 }
286 
287 
288 /* Call this function to assign a device name before the stack is up */
vPublicSetupDeviceName(const char * deviceName)289 void vPublicSetupDeviceName( const char * deviceName )
290 {
291     memset( DEV_NAME, 0, sizeof( DEV_NAME ) );
292     strncpy( DEV_NAME, deviceName, MAX_NAME_LLMNR - 1 );
293 }
294