Skip to content

Commit d8be0a2

Browse files
Mike Wolframrleh
authored andcommitted
[examples] Add FreeRTOS TCP Ethernet example
1 parent ddbd29f commit d8be0a2

File tree

2 files changed

+267
-0
lines changed

2 files changed

+267
-0
lines changed
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
/*
2+
* Copyright (c) 2020, Mike Wolfram
3+
*
4+
* This file is part of the modm project.
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
// ----------------------------------------------------------------------------
11+
12+
#include <modm/board.hpp>
13+
#include <modm/driver/ethernet/lan8720a.hpp>
14+
#include <modm/processing/rtos.hpp>
15+
#include <FreeRTOS_IP.h>
16+
#include <FreeRTOS_Sockets.h>
17+
18+
using namespace Board;
19+
20+
namespace Ethernet
21+
{
22+
using RMII_Ref_Clk = GpioInputA1;
23+
using RMII_Mdio = GpioA2;
24+
using RMII_Crs_Dv = GpioInputA7;
25+
using RMII_Tx_En = GpioOutputG11;
26+
using RMII_Tx_D0 = GpioOutputG13;
27+
using RMII_Tx_D1 = GpioOutputB13;
28+
using RMII_Mdc = GpioOutputC1;
29+
using RMII_Rx_D0 = GpioInputC4;
30+
using RMII_Rx_D1 = GpioInputC5;
31+
using Port = Eth<modm::Lan8720a>;
32+
}
33+
34+
UBaseType_t ulNextRand;
35+
36+
void vApplicationIPNetworkEventHook(eIPCallbackEvent_t eNetworkEvent);
37+
38+
class NetworkInitTask : modm::rtos::Thread
39+
{
40+
public:
41+
NetworkInitTask()
42+
: Thread(5, 2048, "network_init")
43+
{}
44+
45+
void
46+
run()
47+
{
48+
uint8_t ipAddress[4] { 192, 168, 1, 1 };
49+
uint8_t netmask[4] { 255, 255, 255, 0 };
50+
uint8_t gatewayAddress[4] { 0, 0, 0, 0 };
51+
uint8_t dnsAddress[4] { 0, 0, 0, 0 };
52+
53+
// local MAC address
54+
uint8_t macAddress[] { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
55+
56+
// A real MAC address can be retrieved from the Microchip 24AA02E48
57+
// I2C EEPROM, which is locaed at address 0xFA.
58+
59+
// initialize random numbers
60+
time_t now;
61+
time(&now);
62+
ulNextRand = uint32_t(now);
63+
64+
FreeRTOS_IPInit(ipAddress,
65+
netmask,
66+
gatewayAddress,
67+
dnsAddress,
68+
&macAddress[0]);
69+
70+
vTaskDelete(0);
71+
}
72+
};
73+
74+
class HttpConnection
75+
{
76+
static constexpr TickType_t shutdownTimeout { pdMS_TO_TICKS(5000) };
77+
static constexpr TickType_t receiveTimeout { pdMS_TO_TICKS(5000) };
78+
static constexpr TickType_t sendTimeout { pdMS_TO_TICKS(5000) };
79+
80+
public:
81+
static constexpr char name[] { "HTTPConnection" };
82+
static constexpr uint8_t httpText[] = {
83+
"HTTP/1.1 200 OK \r\n"
84+
"Content-Type: text/html\r\n"
85+
"Connection: keep-alive\r\n"
86+
"\r\n"
87+
"<html><body><h1>Hello from your STM32!</h1></body></html>"
88+
};
89+
90+
enum class
91+
ResponseStatus : uint16_t {
92+
Ok = 200,
93+
BadRequest = 400,
94+
NotFound = 404,
95+
};
96+
97+
static void
98+
run(void *parameter)
99+
{
100+
Socket_t connectedSocket = reinterpret_cast<Socket_t>(parameter);
101+
uint8_t *buffer = reinterpret_cast<uint8_t *>(pvPortMalloc(ipconfigTCP_MSS));
102+
103+
if (buffer) {
104+
FreeRTOS_setsockopt(connectedSocket, 0, FREERTOS_SO_RCVTIMEO, &receiveTimeout,
105+
sizeof(receiveTimeout));
106+
FreeRTOS_setsockopt(connectedSocket, 0, FREERTOS_SO_SNDTIMEO, &sendTimeout,
107+
sizeof(sendTimeout));
108+
109+
while (true) {
110+
std::memset(buffer, 0, ipconfigTCP_MSS);
111+
int32_t bytes = FreeRTOS_recv(connectedSocket, buffer, ipconfigTCP_MSS, 0);
112+
if (bytes <= 0)
113+
break;
114+
if (FreeRTOS_send(connectedSocket, httpText, sizeof(httpText) - 1, 0) < 0)
115+
break;
116+
}
117+
}
118+
119+
FreeRTOS_shutdown(connectedSocket, FREERTOS_SHUT_RDWR);
120+
TickType_t shutdownTime { xTaskGetTickCount() };
121+
do {
122+
if (FreeRTOS_recv(connectedSocket, buffer, ipconfigTCP_MSS, 0) < 0)
123+
break;
124+
} while ((xTaskGetTickCount() - shutdownTime) < shutdownTimeout);
125+
126+
vPortFree(buffer);
127+
FreeRTOS_closesocket(connectedSocket);
128+
vTaskDelete(0);
129+
130+
}
131+
};
132+
133+
class HttpServerListener
134+
{
135+
static constexpr TickType_t receiveTimeout { portMAX_DELAY };
136+
static constexpr BaseType_t backlog { 20 };
137+
138+
public:
139+
static constexpr char name[] { "HTTPListener" };
140+
141+
static void
142+
run(void *)
143+
{
144+
Socket_t listeningSocket;
145+
Socket_t connectedSocket;
146+
147+
listeningSocket = FreeRTOS_socket(FREERTOS_AF_INET,
148+
FREERTOS_SOCK_STREAM,
149+
FREERTOS_IPPROTO_TCP);
150+
FreeRTOS_setsockopt(listeningSocket, 0, FREERTOS_SO_RCVTIMEO, &receiveTimeout,
151+
sizeof(receiveTimeout));
152+
153+
#if ipconfigUSE_TCP_WIN == 1
154+
WinProperties_t winProps {
155+
.lTxBufSize = ipconfigTCP_TX_BUFFER_LENGTH,
156+
.lTxWinSize = 2,
157+
.lRxBufSize = ipconfigTCP_RX_BUFFER_LENGTH,
158+
.lRxWinSize = 2,
159+
};
160+
FreeRTOS_setsockopt(listeningSocket, 0, FREERTOS_SO_WIN_PROPERTIES,
161+
reinterpret_cast<void *>(&winProps), sizeof(winProps));
162+
#endif
163+
164+
struct freertos_sockaddr bindAddress {
165+
.sin_port = FreeRTOS_htons(80),
166+
};
167+
FreeRTOS_bind(listeningSocket, &bindAddress, sizeof(bindAddress));
168+
FreeRTOS_listen(listeningSocket, backlog);
169+
170+
struct freertos_sockaddr clientAddress;
171+
172+
while (true) {
173+
connectedSocket = FreeRTOS_accept(listeningSocket, &clientAddress, 0);
174+
char buffer[16];
175+
FreeRTOS_inet_ntoa(clientAddress.sin_addr, buffer);
176+
xTaskCreate(HttpConnection::run, HttpConnection::name, configMINIMAL_STACK_SIZE * 5,
177+
reinterpret_cast<void *>(connectedSocket), configMAX_PRIORITIES, 0);
178+
}
179+
}
180+
};
181+
182+
NetworkInitTask networkInit;
183+
184+
int
185+
main()
186+
{
187+
Board::initialize();
188+
Leds::setOutput();
189+
MODM_LOG_INFO << "\n\nReboot: Ethernet Example" << modm::endl;
190+
191+
Ethernet::Port::connect<Ethernet::RMII_Ref_Clk::Refclk,
192+
Ethernet::RMII_Mdc::Mdc,
193+
Ethernet::RMII_Mdio::Mdio,
194+
Ethernet::RMII_Crs_Dv::Rcccrsdv,
195+
Ethernet::RMII_Tx_En::Txen,
196+
Ethernet::RMII_Tx_D0::Txd0,
197+
Ethernet::RMII_Tx_D1::Txd1,
198+
Ethernet::RMII_Rx_D0::Rxd0,
199+
Ethernet::RMII_Rx_D1::Rxd1>();
200+
201+
modm::rtos::Scheduler::schedule();
202+
203+
// we should never get here
204+
return 0;
205+
}
206+
207+
void vApplicationIPNetworkEventHook(eIPCallbackEvent_t eNetworkEvent)
208+
{
209+
static bool taskCreated = false;
210+
211+
if (eNetworkEvent != eNetworkUp)
212+
return;
213+
214+
if (not taskCreated) {
215+
xTaskCreate(HttpServerListener::run, HttpServerListener::name, configMINIMAL_STACK_SIZE * 2, 0, configMAX_PRIORITIES + 1, 0);
216+
taskCreated = true;
217+
}
218+
219+
uint32_t ipAddress;
220+
uint32_t netmask;
221+
uint32_t gateway;
222+
uint32_t dns;
223+
char buffer[16];
224+
225+
FreeRTOS_GetAddressConfiguration(&ipAddress, &netmask, &gateway, &dns);
226+
FreeRTOS_inet_ntoa(ipAddress, buffer);
227+
MODM_LOG_DEBUG << "IP address: " << buffer << modm::endl;
228+
FreeRTOS_inet_ntoa(netmask, buffer);
229+
MODM_LOG_DEBUG << "Netmask : " << buffer << modm::endl;
230+
FreeRTOS_inet_ntoa(gateway, buffer);
231+
MODM_LOG_DEBUG << "Gateway : " << buffer << modm::endl;
232+
FreeRTOS_inet_ntoa(dns, buffer);
233+
MODM_LOG_DEBUG << "DNS : " << buffer << modm::endl;
234+
}
235+
236+
UBaseType_t uxRand( void )
237+
{
238+
static constexpr uint32_t ulMultiplier = 0x015a4e35UL;
239+
static constexpr uint32_t ulIncrement = 1UL;
240+
241+
/* Utility function to generate a pseudo random number. */
242+
243+
ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;
244+
return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL );
245+
}
246+
247+
BaseType_t xApplicationGetRandomNumber(uint32_t* pulNumber)
248+
{
249+
*(pulNumber) = uxRand();
250+
return pdTRUE;
251+
}
252+
253+
uint32_t ulApplicationGetNextSequenceNumber(uint32_t, uint16_t, uint32_t, uint16_t)
254+
{
255+
return uxRand();
256+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<library>
2+
<extends>modm:nucleo-f767zi</extends>
3+
<options>
4+
<option name="modm:build:build.path">../../../build/nucleo_f767zi/ethernet</option>
5+
</options>
6+
<modules>
7+
<module>modm:build:scons</module>
8+
<module>modm:freertos:tcp:lan8720a</module>
9+
<module>modm:processing:rtos</module>
10+
</modules>
11+
</library>

0 commit comments

Comments
 (0)