-
Notifications
You must be signed in to change notification settings - Fork 143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
First implementation of Ethernet for STM32F7 (and later STM32F4). #466
Merged
+2,170
−12
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* | ||
* Copyright (c) 2016-2017, Niklas Hauser | ||
* | ||
* This file is part of the modm project. | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
// ---------------------------------------------------------------------------- | ||
|
||
#include <modm/board.hpp> | ||
|
||
using namespace Board; | ||
|
||
int | ||
main() | ||
{ | ||
Board::initialize(); | ||
Leds::setOutput(); | ||
|
||
// Use the logging streams to print some messages. | ||
// Change MODM_LOG_LEVEL above to enable or disable these messages | ||
MODM_LOG_DEBUG << "debug" << modm::endl; | ||
MODM_LOG_INFO << "info" << modm::endl; | ||
MODM_LOG_WARNING << "warning" << modm::endl; | ||
MODM_LOG_ERROR << "error" << modm::endl; | ||
|
||
uint32_t counter(0); | ||
|
||
while (true) | ||
{ | ||
Leds::write(1 << (counter % (Leds::width+1) )); | ||
modm::delay(Button::read() ? 100ms : 500ms); | ||
|
||
MODM_LOG_INFO << "loop: " << counter++ << modm::endl; | ||
} | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<library> | ||
<extends>modm:nucleo-f767zi</extends> | ||
<options> | ||
<option name="modm:build:build.path">../../../build/nucleo_f767zi/blink</option> | ||
</options> | ||
<modules> | ||
<module>modm:build:scons</module> | ||
</modules> | ||
</library> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,256 @@ | ||
/* | ||
* Copyright (c) 2020, Mike Wolfram | ||
* | ||
* This file is part of the modm project. | ||
* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
// ---------------------------------------------------------------------------- | ||
|
||
#include <modm/board.hpp> | ||
#include <modm/driver/ethernet/lan8720a.hpp> | ||
#include <modm/processing/rtos.hpp> | ||
#include <FreeRTOS_IP.h> | ||
#include <FreeRTOS_Sockets.h> | ||
|
||
using namespace Board; | ||
|
||
namespace Ethernet | ||
{ | ||
using RMII_Ref_Clk = GpioInputA1; | ||
using RMII_Mdio = GpioA2; | ||
using RMII_Crs_Dv = GpioInputA7; | ||
using RMII_Tx_En = GpioOutputG11; | ||
using RMII_Tx_D0 = GpioOutputG13; | ||
using RMII_Tx_D1 = GpioOutputB13; | ||
using RMII_Mdc = GpioOutputC1; | ||
using RMII_Rx_D0 = GpioInputC4; | ||
using RMII_Rx_D1 = GpioInputC5; | ||
using Port = Eth<modm::Lan8720a>; | ||
} | ||
|
||
UBaseType_t ulNextRand; | ||
|
||
void vApplicationIPNetworkEventHook(eIPCallbackEvent_t eNetworkEvent); | ||
|
||
class NetworkInitTask : modm::rtos::Thread | ||
{ | ||
public: | ||
NetworkInitTask() | ||
: Thread(5, 2048, "network_init") | ||
{} | ||
|
||
void | ||
run() | ||
{ | ||
uint8_t ipAddress[4] { 192, 168, 1, 1 }; | ||
uint8_t netmask[4] { 255, 255, 255, 0 }; | ||
uint8_t gatewayAddress[4] { 0, 0, 0, 0 }; | ||
uint8_t dnsAddress[4] { 0, 0, 0, 0 }; | ||
|
||
// local MAC address | ||
uint8_t macAddress[] { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
|
||
// A real MAC address can be retrieved from the Microchip 24AA02E48 | ||
// I2C EEPROM, which is locaed at address 0xFA. | ||
|
||
// initialize random numbers | ||
time_t now; | ||
time(&now); | ||
ulNextRand = uint32_t(now); | ||
|
||
FreeRTOS_IPInit(ipAddress, | ||
netmask, | ||
gatewayAddress, | ||
dnsAddress, | ||
&macAddress[0]); | ||
|
||
vTaskDelete(0); | ||
} | ||
}; | ||
|
||
class HttpConnection | ||
{ | ||
static constexpr TickType_t shutdownTimeout { pdMS_TO_TICKS(5000) }; | ||
static constexpr TickType_t receiveTimeout { pdMS_TO_TICKS(5000) }; | ||
static constexpr TickType_t sendTimeout { pdMS_TO_TICKS(5000) }; | ||
|
||
public: | ||
static constexpr char name[] { "HTTPConnection" }; | ||
static constexpr uint8_t httpText[] = { | ||
"HTTP/1.1 200 OK \r\n" | ||
"Content-Type: text/html\r\n" | ||
"Connection: keep-alive\r\n" | ||
"\r\n" | ||
"<html><body><h1>Hello from your STM32!</h1></body></html>" | ||
}; | ||
|
||
enum class | ||
ResponseStatus : uint16_t { | ||
Ok = 200, | ||
BadRequest = 400, | ||
NotFound = 404, | ||
}; | ||
|
||
static void | ||
run(void *parameter) | ||
{ | ||
Socket_t connectedSocket = reinterpret_cast<Socket_t>(parameter); | ||
uint8_t *buffer = reinterpret_cast<uint8_t *>(pvPortMalloc(ipconfigTCP_MSS)); | ||
|
||
if (buffer) { | ||
FreeRTOS_setsockopt(connectedSocket, 0, FREERTOS_SO_RCVTIMEO, &receiveTimeout, | ||
sizeof(receiveTimeout)); | ||
FreeRTOS_setsockopt(connectedSocket, 0, FREERTOS_SO_SNDTIMEO, &sendTimeout, | ||
sizeof(sendTimeout)); | ||
|
||
while (true) { | ||
std::memset(buffer, 0, ipconfigTCP_MSS); | ||
int32_t bytes = FreeRTOS_recv(connectedSocket, buffer, ipconfigTCP_MSS, 0); | ||
if (bytes <= 0) | ||
break; | ||
if (FreeRTOS_send(connectedSocket, httpText, sizeof(httpText) - 1, 0) < 0) | ||
break; | ||
} | ||
} | ||
|
||
FreeRTOS_shutdown(connectedSocket, FREERTOS_SHUT_RDWR); | ||
TickType_t shutdownTime { xTaskGetTickCount() }; | ||
do { | ||
if (FreeRTOS_recv(connectedSocket, buffer, ipconfigTCP_MSS, 0) < 0) | ||
break; | ||
} while ((xTaskGetTickCount() - shutdownTime) < shutdownTimeout); | ||
|
||
vPortFree(buffer); | ||
FreeRTOS_closesocket(connectedSocket); | ||
vTaskDelete(0); | ||
|
||
} | ||
}; | ||
|
||
class HttpServerListener | ||
{ | ||
static constexpr TickType_t receiveTimeout { portMAX_DELAY }; | ||
static constexpr BaseType_t backlog { 20 }; | ||
|
||
public: | ||
static constexpr char name[] { "HTTPListener" }; | ||
|
||
static void | ||
run(void *) | ||
{ | ||
Socket_t listeningSocket; | ||
Socket_t connectedSocket; | ||
|
||
listeningSocket = FreeRTOS_socket(FREERTOS_AF_INET, | ||
FREERTOS_SOCK_STREAM, | ||
FREERTOS_IPPROTO_TCP); | ||
FreeRTOS_setsockopt(listeningSocket, 0, FREERTOS_SO_RCVTIMEO, &receiveTimeout, | ||
sizeof(receiveTimeout)); | ||
|
||
#if ipconfigUSE_TCP_WIN == 1 | ||
WinProperties_t winProps { | ||
.lTxBufSize = ipconfigTCP_TX_BUFFER_LENGTH, | ||
.lTxWinSize = 2, | ||
.lRxBufSize = ipconfigTCP_RX_BUFFER_LENGTH, | ||
.lRxWinSize = 2, | ||
}; | ||
FreeRTOS_setsockopt(listeningSocket, 0, FREERTOS_SO_WIN_PROPERTIES, | ||
reinterpret_cast<void *>(&winProps), sizeof(winProps)); | ||
#endif | ||
|
||
struct freertos_sockaddr bindAddress { | ||
.sin_port = FreeRTOS_htons(80), | ||
}; | ||
FreeRTOS_bind(listeningSocket, &bindAddress, sizeof(bindAddress)); | ||
FreeRTOS_listen(listeningSocket, backlog); | ||
|
||
struct freertos_sockaddr clientAddress; | ||
|
||
while (true) { | ||
connectedSocket = FreeRTOS_accept(listeningSocket, &clientAddress, 0); | ||
char buffer[16]; | ||
FreeRTOS_inet_ntoa(clientAddress.sin_addr, buffer); | ||
xTaskCreate(HttpConnection::run, HttpConnection::name, configMINIMAL_STACK_SIZE * 5, | ||
reinterpret_cast<void *>(connectedSocket), configMAX_PRIORITIES, 0); | ||
} | ||
} | ||
}; | ||
|
||
NetworkInitTask networkInit; | ||
|
||
int | ||
main() | ||
{ | ||
Board::initialize(); | ||
Leds::setOutput(); | ||
MODM_LOG_INFO << "\n\nReboot: Ethernet Example" << modm::endl; | ||
|
||
Ethernet::Port::connect<Ethernet::RMII_Ref_Clk::Refclk, | ||
Ethernet::RMII_Mdc::Mdc, | ||
Ethernet::RMII_Mdio::Mdio, | ||
Ethernet::RMII_Crs_Dv::Rcccrsdv, | ||
Ethernet::RMII_Tx_En::Txen, | ||
Ethernet::RMII_Tx_D0::Txd0, | ||
Ethernet::RMII_Tx_D1::Txd1, | ||
Ethernet::RMII_Rx_D0::Rxd0, | ||
Ethernet::RMII_Rx_D1::Rxd1>(); | ||
|
||
modm::rtos::Scheduler::schedule(); | ||
|
||
// we should never get here | ||
return 0; | ||
} | ||
|
||
void vApplicationIPNetworkEventHook(eIPCallbackEvent_t eNetworkEvent) | ||
{ | ||
static bool taskCreated = false; | ||
|
||
if (eNetworkEvent != eNetworkUp) | ||
return; | ||
|
||
if (not taskCreated) { | ||
xTaskCreate(HttpServerListener::run, HttpServerListener::name, configMINIMAL_STACK_SIZE * 2, 0, configMAX_PRIORITIES + 1, 0); | ||
taskCreated = true; | ||
} | ||
|
||
uint32_t ipAddress; | ||
uint32_t netmask; | ||
uint32_t gateway; | ||
uint32_t dns; | ||
char buffer[16]; | ||
|
||
FreeRTOS_GetAddressConfiguration(&ipAddress, &netmask, &gateway, &dns); | ||
FreeRTOS_inet_ntoa(ipAddress, buffer); | ||
MODM_LOG_DEBUG << "IP address: " << buffer << modm::endl; | ||
FreeRTOS_inet_ntoa(netmask, buffer); | ||
MODM_LOG_DEBUG << "Netmask : " << buffer << modm::endl; | ||
FreeRTOS_inet_ntoa(gateway, buffer); | ||
MODM_LOG_DEBUG << "Gateway : " << buffer << modm::endl; | ||
FreeRTOS_inet_ntoa(dns, buffer); | ||
MODM_LOG_DEBUG << "DNS : " << buffer << modm::endl; | ||
} | ||
|
||
UBaseType_t uxRand( void ) | ||
{ | ||
static constexpr uint32_t ulMultiplier = 0x015a4e35UL; | ||
static constexpr uint32_t ulIncrement = 1UL; | ||
|
||
/* Utility function to generate a pseudo random number. */ | ||
|
||
ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement; | ||
return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL ); | ||
} | ||
|
||
BaseType_t xApplicationGetRandomNumber(uint32_t* pulNumber) | ||
{ | ||
*(pulNumber) = uxRand(); | ||
return pdTRUE; | ||
} | ||
|
||
uint32_t ulApplicationGetNextSequenceNumber(uint32_t, uint16_t, uint32_t, uint16_t) | ||
{ | ||
return uxRand(); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could have used real random numbers here...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, and as a fallback you can seed srand with the device's UID.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also
time()
is not implemented. We could perhaps wire it tomodm::Clock
, but it's not done yet.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if this is a good idea or a serious security flaw...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, you need to collect entropy somehow. There are a bunch more hardware calibration registers that provide entropy within some bounds. It's a somewhat good idea since the values will be different for every device (assuming a good hash function), however, only if the attacker cannot read them out remotely. However, security is definitely beyond the scope of modm and too much work to implement yourself. We'd have to integrate some embedded TLS library for encryption.