Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
FreeRTOSTCP.cxx
Go to the documentation of this file.
1
35#include <new>
36#include <stdio.h>
37
38// FreeRTOS
39#include "FreeRTOS.h"
40#include "task.h"
41#include "queue.h"
42
43// FreeRTOSTCP includes
44#include "FreeRTOS_IP.h"
45#include "FreeRTOS_Sockets.h"
46
47#include "FreeRTOSTCP.hxx"
48#include "FreeRTOSTCPSocket.hxx"
49
50static SocketSet_t socket_set = NULL;
51
52static QueueHandle_t close_queue = NULL;
53
55bool network_layer_preinit(void);
56
59extern "C" void vApplicationIPNetworkEventHook(
60 eIPCallbackEvent_t eNetworkEvent);
61
62/*
63 * FreeRTOSTCP::FreeRTOSTCP()
64 */
66 : ipAddress(0)
67 , wakeup(NULL)
68{
69}
70
71/*
72 * FreeRTOSTCP::start()
73 */
75{
77 os_thread_create(NULL, "FreeRTOSTCP Task", configMAX_PRIORITIES - 1, 2048,
78 net_task_entry, NULL);
79}
80
81/*
82 * FreeRTOSTCP::net_task()
83 */
85{
86 int sel_result, result, tries;
87 struct freertos_sockaddr address;
88
89 socket_set = FreeRTOS_CreateSocketSet();
90 HASSERT(socket_set != NULL);
91
92 close_queue = xQueueCreate(10, sizeof(Socket_t));
93 HASSERT(close_queue != 0);
94
95 tries = 0;
96 wakeup = FREERTOS_INVALID_SOCKET;
97 while ((++tries <= 5) && (wakeup == FREERTOS_INVALID_SOCKET))
98 {
99 wakeup = FreeRTOS_socket(
100 FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP);
101 if (wakeup == FREERTOS_INVALID_SOCKET)
102 {
103 // no memory or networking stack not fully operational
104 if (++tries < 5)
105 sleep(1);
106 }
107 }
108 HASSERT(wakeup != FREERTOS_INVALID_SOCKET);
109
110 address.sin_port = FreeRTOS_htons(8000);
111 address.sin_addr = FreeRTOS_htonl(0); // INADDR_ANY;
112 result = FreeRTOS_bind(wakeup, &address, sizeof(address));
113 HASSERT(result >= 0);
114
115 FreeRTOS_FD_SET(wakeup, socket_set, eSELECT_READ | eSELECT_INTR);
116
117 for (; /* forever */;)
118 {
119 const TickType_t timeout = pdMS_TO_TICKS(30000);
120
121 sel_result = FreeRTOS_select(socket_set, timeout);
122
123 if (sel_result < 0)
124 {
125 continue;
126 }
127
128 if (sel_result & eSELECT_INTR)
129 {
130 // wakeup: process close_queue entries
131 Socket_t sd;
132
133 while (xQueueReceive(close_queue, &sd, 0) == pdTRUE)
134 {
135 portENTER_CRITICAL();
136 FreeRTOS_FD_CLR(sd, socket_set,
137 eSELECT_READ | eSELECT_WRITE | eSELECT_EXCEPT);
140 portEXIT_CRITICAL();
141 FreeRTOS_shutdown(sd, FREERTOS_SHUT_RDWR);
142 FreeRTOS_closesocket(sd);
143 }
144 }
145
146 // there should be a better to way to go about determining which sockets
147 // are
148 // in the socketset used for the call in select
149 for (int i = MAX_SOCKETS - 1; i >= 0; --i)
150 {
151 FreeRTOSTCPSocket *s = nullptr;
152 Socket_t sd;
153 BaseType_t evt;
154 sd = wakeup;
155
156 if (i == 0)
157 {
158 s = nullptr;
159 sd = wakeup;
160 }
161 else
162 {
164 if (s == nullptr)
165 {
166 continue;
167 }
168 sd = s->sd;
169 }
170
171 /* obtain event mask in evt */
172 evt = FreeRTOS_FD_ISSET(sd, socket_set);
173 if (evt == 0)
174 {
175 continue;
176 }
177
178 if (evt & eSELECT_READ)
179 {
180 if (sd == wakeup)
181 {
182 /* this is the socket we use as a signal, so discard any
183 * data received */
184 char data[4];
185 FreeRTOS_recvfrom(
186 wakeup, data, sizeof(data), 0, nullptr, nullptr);
187 }
188 else
189 {
190 // have something to read
191 FreeRTOS_FD_CLR(sd, socket_set, eSELECT_READ);
192 s->readActive = true;
193 s->select_wakeup(&s->selInfoRd);
194 }
195 }
196
197 if (evt & eSELECT_WRITE)
198 {
199 if (sd == wakeup)
200 {
201 FreeRTOS_FD_CLR(sd, socket_set, eSELECT_WRITE);
202 continue;
203 }
204 // was the test for the write fdset
205 FreeRTOS_FD_CLR(sd, socket_set, eSELECT_WRITE);
206 s->writeActive = false;
207 s->select_wakeup(&s->selInfoWr);
208 }
209 if (evt & eSELECT_EXCEPT)
210 {
211 // was the test for the except fdset
212 FreeRTOS_FD_CLR(sd, socket_set, eSELECT_EXCEPT);
213 /* currently we don't handle any errors */
214 ;
215 }
216 }
217 }
218}
219
220/*
221 * FreeRTOSTCP::select_wakeup()
222 */
224{
225 HASSERT(wakeup >= 0);
226
227#if ipconfigSUPPORT_SIGNALS == 1
228 // needs FreeRTOSIPConfig to include SUPPORT_SIGNALS = 1
229 if (data != nullptr)
230 {
231 // place request in wake_queue
232 xQueueSend(close_queue, &data, 0);
233 }
234 FreeRTOS_SignalSocket(wakeup);
235#else
236#error "FreeRTOSIPConfig.h must include ipconfigSUPPORT_SIGNALS = 1"
237#endif
238}
239
240/*
241 * FreeRTOSTCP::fd_set_read()
242 */
244{
245 FreeRTOS_FD_SET(socket, socket_set, eSELECT_READ);
247}
248
249/*
250 * FreeRTOSTCP::fd_set_write()
251 */
253{
254 FreeRTOS_FD_SET(socket, socket_set, eSELECT_WRITE);
256}
257
258extern "C" void vApplicationIPNetworkEventHook(eIPCallbackEvent_t eNetworkEvent)
259{
260 return;
261}
void vApplicationIPNetworkEventHook(eIPCallbackEvent_t eNetworkEvent)
Callback from FreeRTOS network event handler.
bool network_layer_preinit(void)
Called before the TCP stack is initialized in FreeRTOS.
void * Socket_t
local declaraction of Socket_t to avoid dependency on FreeRTOSTCP headers
static OSEvent wakeup
event used to wakeup select calls
Definition Select.cxx:40
int socket(int domain, int type, int protocol)
Create an unbound socket in a communications domain.
Definition Socket.cxx:144
bool writeActive
indicates our "best guess" at current socket's write active status
static FreeRTOSTCPSocket * get_sd_by_index(int inx)
Get the socket descriptor assoicated with socket index.
static void remove_instance_from_sd(Socket_t sd)
Remove the FreeRTOSTCP instance from the active FreeRTOSTCP list.
bool readActive
indicates our "best guess" at current socket's read active status
static FreeRTOSTCPSocket * get_instance_from_sd(Socket_t sd)
Get the FreeRTOSTCP instance given a specific socket descriptor.
Socket_t sd
FreeRTOS socket descriptor.
Socket_t wakeup
signal socket to wakeup select()
FreeRTOSTCP()
Constructor.
void net_task()
Thread that will manage the net connection inside object context.
void start()
Startup the networking processes.
void fd_set_read(Socket_t socket)
Add socket to the read fd set.
static void * net_task_entry(void *context)
Thread that will manage the network connection.
void select_wakeup(Socket_t data=nullptr)
Asynchronously wakeup the select call.
void fd_set_write(Socket_t socket)
Add socket to the write fd set.
SelectInfo selInfoRd
select wakeup metadata for read active
Definition Socket.hxx:79
SelectInfo selInfoWr
select wakeup metadata for write active
Definition Socket.hxx:80
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
int os_thread_create(os_thread_t *thread, const char *name, int priority, size_t stack_size, void *(*start_routine)(void *), void *arg)
Create a thread.
Definition os.c:450
static void select_wakeup(SelectInfo *info)
Wakeup the list of clients needing woken.
Definition Select.cxx:210