From 73a5d28cfbeac87da5a4df36a2dae44e3d364f98 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Sat, 15 Mar 2025 21:09:46 -0700 Subject: [PATCH 1/9] lwip wifi --- firmware/console/console.mk | 1 - firmware/console/wifi_console.cpp | 106 ------ .../ethernet_console/ethernet_console.cpp | 4 +- firmware/ext/atwinc1500/atwinc1500.mk | 2 +- firmware/hw_layer/ports/rusefi_halconf.h | 2 +- firmware/net/lwipopts.h | 27 +- firmware/net/wifi_socket.cpp | 311 +++++++++--------- firmware/net/wifi_socket.h | 68 ++-- firmware/rusefi.cpp | 2 +- 9 files changed, 205 insertions(+), 318 deletions(-) delete mode 100644 firmware/console/wifi_console.cpp diff --git a/firmware/console/console.mk b/firmware/console/console.mk index a700a4fc0f..2db34b37f4 100644 --- a/firmware/console/console.mk +++ b/firmware/console/console.mk @@ -9,7 +9,6 @@ CONSOLE_SRC_CPP = $(CONSOLE_COMMON_SRC_CPP) \ $(PROJECT_DIR)/console/connector_uart_dma.cpp \ $(PROJECT_DIR)/console/binary_log/binary_logging.cpp \ $(PROJECT_DIR)/console/binary_log/usb_console.cpp \ - $(PROJECT_DIR)/console/wifi_console.cpp \ CONSOLE_INC=\ diff --git a/firmware/console/wifi_console.cpp b/firmware/console/wifi_console.cpp deleted file mode 100644 index 6567f329c9..0000000000 --- a/firmware/console/wifi_console.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include "pch.h" - -#if EFI_WIFI - -#include "wifi_socket.h" - -#include "socket/include/socket.h" - -#include "tunerstudio.h" - -class WifiChannel final : public TsChannelBase { -public: - WifiChannel(ServerSocket& server) - : TsChannelBase("WiFi") - , m_server(server) - { - } - - bool isReady() const override { - return m_server.hasConnectedSocket(); - } - - void write(const uint8_t* buffer, size_t size, bool /*isEndOfPacket*/) final override { - while (size) { - size_t chunkSize = writeChunk(buffer, size); - - buffer += chunkSize; - size -= chunkSize; - } - } - - void flush() final override { - if (m_writeSize == 0) { - // spurious flush, ignore - return; - } - - m_server.send(m_writeBuffer, m_writeSize); - - m_writeSize = 0; - } - - size_t readTimeout(uint8_t* buffer, size_t size, int timeout) override { - return m_server.recvTimeout(buffer, size, timeout); - } - -private: - ServerSocket& m_server; - - size_t writeChunk(const uint8_t* buffer, size_t size) { - // Maximum we can fit in the buffer before a flush - size_t available = SOCKET_BUFFER_MAX_LENGTH - m_writeSize; - - // Size we will write to the buffer in this chunk - size_t chunkSize = std::min(size, available); - - // Perform the write! - memcpy(&m_writeBuffer[m_writeSize], buffer, chunkSize); - m_writeSize += chunkSize; - - // This write filled the buffer, flush it - if (m_writeSize == SOCKET_BUFFER_MAX_LENGTH) { - flush(); - } - - return chunkSize; - } - - uint8_t m_writeBuffer[SOCKET_BUFFER_MAX_LENGTH]; - size_t m_writeSize = 0; -}; - -static NO_CACHE ServerSocket tsServer; -static NO_CACHE WifiChannel wifiChannel(tsServer); - -static void startTsListening() { - // Start listening on the socket - sockaddr_in address; - address.sin_family = AF_INET; - address.sin_port = _htons(29000); - address.sin_addr.s_addr = 0; - - tsServer.startListening(address); -} - -struct WifiConsoleThread : public TunerstudioThread { - WifiConsoleThread() : TunerstudioThread("WiFi Console") { } - - TsChannelBase* setupChannel() override { - waitForWifiInit(); - - startTsListening(); - - return &wifiChannel; - } -}; - -static NO_CACHE WifiConsoleThread wifiThread; - -void startWifiConsole() { - initWifi(); - - wifiThread.start(); -} - -#endif // EFI_WIFI diff --git a/firmware/controllers/modules/ethernet_console/ethernet_console.cpp b/firmware/controllers/modules/ethernet_console/ethernet_console.cpp index 53f4313fba..f54f52caf8 100644 --- a/firmware/controllers/modules/ethernet_console/ethernet_console.cpp +++ b/firmware/controllers/modules/ethernet_console/ethernet_console.cpp @@ -2,6 +2,8 @@ #include "lwipthread.h" +#include "wifi_socket.h" + #include "lwip/sockets.h" #include "thread_controller.h" @@ -73,7 +75,7 @@ struct EthernetThread : public TunerstudioThread { EthernetThread() : TunerstudioThread("Ethernet Console") { } TsChannelBase* setupChannel() override { - lwipInit(nullptr); + waitForWifiInit(); sockaddr_in address; address.sin_family = AF_INET; diff --git a/firmware/ext/atwinc1500/atwinc1500.mk b/firmware/ext/atwinc1500/atwinc1500.mk index 5d38fc08ae..dcb58ce6bf 100644 --- a/firmware/ext/atwinc1500/atwinc1500.mk +++ b/firmware/ext/atwinc1500/atwinc1500.mk @@ -24,8 +24,8 @@ ALLCPPSRC += \ $(ATWINC_DIR)/driver/source/nmi2c.cpp \ $(ATWINC_DIR)/driver/source/nmspi.cpp \ $(ATWINC_DIR)/driver/source/nmuart.cpp \ - $(ATWINC_DIR)/socket/source/socket.cpp \ $(ATWINC_DIR)/spi_flash/source/spi_flash.cpp \ + #$(ATWINC_DIR)/socket/source/socket.cpp \ #$(ATWINC_DIR)/driver/source/m2m_ssl.c diff --git a/firmware/hw_layer/ports/rusefi_halconf.h b/firmware/hw_layer/ports/rusefi_halconf.h index e4ceaf37e7..e0aca3a749 100644 --- a/firmware/hw_layer/ports/rusefi_halconf.h +++ b/firmware/hw_layer/ports/rusefi_halconf.h @@ -41,7 +41,7 @@ #define USB_USE_WAIT (EFI_FILE_LOGGING && EFI_USB_SERIAL) // Ethernet -#define HAL_USE_MAC MODULE_ETHERNET_CONSOLE +#define HAL_USE_MAC FALSE /*===========================================================================*/ /* Required rusEFI settings */ diff --git a/firmware/net/lwipopts.h b/firmware/net/lwipopts.h index 09d7ca8f5b..b5172fddae 100644 --- a/firmware/net/lwipopts.h +++ b/firmware/net/lwipopts.h @@ -43,7 +43,7 @@ #define TCPIP_MBOX_SIZE MEMP_NUM_PBUF #endif #if !defined(TCPIP_THREAD_STACKSIZE) -#define TCPIP_THREAD_STACKSIZE 1024 +#define TCPIP_THREAD_STACKSIZE 4096 #endif #define LWIP_LINK_POLL_INTERVAL TIME_S2I(1) @@ -52,26 +52,31 @@ #define LWIP_COMPAT_SOCKETS 0 -#define LWIP_RAW 0 -#define LWIP_TCP 1 +#define LWIP_RAW 4 +#define LWIP_TCP 4 #define LWIP_UDP 0 #define LWIP_STATS 0 // In theory we're only talking to a single PC, so we don't need a big ARP table -#define ARP_TABLE_SIZE 4 +#define ARP_TABLE_SIZE 16 // ascii `rus` -#define LWIP_ETHADDR_0 0x72 -#define LWIP_ETHADDR_1 0x75 -#define LWIP_ETHADDR_2 0x73 -#define LWIP_ETHADDR_3 0x12 -#define LWIP_ETHADDR_4 0x34 -#define LWIP_ETHADDR_5 0x56 +#define LWIP_ETHADDR_0 0xf8 +#define LWIP_ETHADDR_1 0xf0 +#define LWIP_ETHADDR_2 0x05 +#define LWIP_ETHADDR_3 0xa3 +#define LWIP_ETHADDR_4 0x19 +#define LWIP_ETHADDR_5 0xc2 #include "rusefi_generated.h" // Ensure that one TCP segment can always fit an entire response to TS - we never need to split a TS packet across multiple frames. -#define TCP_MSS (BLOCKING_FACTOR + 10) +#define TCP_MSS 8192 + +#define MEM_SIZE 65536 + +#define LWIP_TCP_SACK_OUT 1 +#define LWIP_TCP_MAX_SACK_NUM 8 // Enable the socket recv timeout (and it uses a nonstandard option of int, rather than timeval) #define LWIP_SO_SNDRCVTIMEO_NONSTANDARD 1 diff --git a/firmware/net/wifi_socket.cpp b/firmware/net/wifi_socket.cpp index 2af91c651e..f93a8e659e 100644 --- a/firmware/net/wifi_socket.cpp +++ b/firmware/net/wifi_socket.cpp @@ -3,211 +3,188 @@ #include "thread_controller.h" #include "driver/include/m2m_wifi.h" -#include "socket/include/socket.h" -static chibios_rt::BinarySemaphore isrSemaphore(/* taken =*/ true); +#include "lwipthread.h" -/*static*/ ServerSocket* ServerSocket::s_serverList = nullptr; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -ServerSocket::ServerSocket() { - // Add server to linked list - m_nextServer = s_serverList; - s_serverList = this; +static chibios_rt::BinarySemaphore isrSemaphore(/* taken =*/ true); +static chibios_rt::BinarySemaphore sendDoneSemaphore{/* taken =*/ true}; - // Set up queue - iqObjectInit(&m_recvQueue, m_recvQueueBuffer, sizeof(m_recvQueueBuffer), nullptr, nullptr); +void os_hook_isr() { + isrSemaphore.signalI(); } -void ServerSocket::startListening(const sockaddr_in& addr) { - m_listenerSocket = socket(AF_INET, SOCK_STREAM, SOCKET_CONFIG_SSL_OFF); - bind(m_listenerSocket, (sockaddr*)&addr, sizeof(addr)); +static void wifiCallback(uint8 u8MsgType, void* pvMsg) { + switch (u8MsgType) { + case M2M_WIFI_REQ_DHCP_CONF: { + auto& dhcpInfo = *reinterpret_cast(pvMsg); + uint8_t* addr = reinterpret_cast(&dhcpInfo.u32StaticIP); + efiPrintf("WiFi client connected DHCP IP is %d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); + } break; + default: + efiPrintf("WifiCallback: %d", (int)u8MsgType); + break; + } } -void ServerSocket::onAccept(int connectedSocket) { - m_connectedSocket = connectedSocket; +static netif thisif; - recv(m_connectedSocket, &m_recvBuf, 1, 0); -} +void ethernetCallback(uint8 u8MsgType, void * pvMsg,void * pvCtrlBuf) { + switch (u8MsgType) { + case M2M_WIFI_RESP_ETHERNET_RX_PACKET: + auto frame = reinterpret_cast(pvMsg); + auto ctrlBuf = reinterpret_cast(pvCtrlBuf); -void ServerSocket::onClose() { - close(m_connectedSocket); + size_t len = ctrlBuf->u16DataSize; - m_connectedSocket = -1; + #if ETH_PAD_SIZE + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ + #endif - { - chibios_rt::CriticalSectionLocker csl; - iqResetI(&m_recvQueue); - } -} + pbuf* p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); -void ServerSocket::onRecv(uint8_t* buffer, size_t recvSize, size_t remaining) { - { - chibios_rt::CriticalSectionLocker csl; + if (!p) { + // couldn't allocate, drop the frame + return; + } - for (size_t i = 0; i < recvSize; i++) { - iqPutI(&m_recvQueue, buffer[i]); + #if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ + #endif + + // copy the frame in to the pbuf + pbuf_take(p, frame, len); + + #if ETH_PAD_SIZE + pbuf_header(*p, ETH_PAD_SIZE); /* reclaim the padding word */ + #endif + + auto ethhdr = reinterpret_cast(p->payload); + switch (htons(ethhdr->type)) { + /* IP or ARP packet? */ + case ETHTYPE_IP: + case ETHTYPE_ARP: + /* full packet send to tcpip_thread to process */ + if (thisif.input(p, &thisif) == ERR_OK) + break; + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + /* Falls through */ + default: + pbuf_free(p); } - } - size_t nextRecv; - if (remaining < 1) { - // Always try to read at least 1 byte - nextRecv = 1; - } else if (remaining > sizeof(m_recvBuf)) { - // Remaining is too big for the buffer, so just read one buffer worth - nextRecv = sizeof(m_recvBuf); - } else { - // The full thing will fit, try to read it - nextRecv = remaining; + break; } - - // start the next recv - recv(m_connectedSocket, &m_recvBuf, nextRecv, 0); -} - -bool ServerSocket::hasConnectedSocket() const { - return m_connectedSocket != -1; } -/*static*/ bool ServerSocket::checkSend() { - bool result = false; - - auto current = s_serverList; +static pbuf* outgoing_pbuf = nullptr; - while (current) { - result |= current->trySendImpl(); - current = current->m_nextServer; - } +void checkOutgoingPbuf() { + if (outgoing_pbuf) { + #if ETH_PAD_SIZE + // drop the padding word + pbuf_header(outgoing_pbuf, -ETH_PAD_SIZE); + #endif - return result; -} + static NO_CACHE uint8_t ethernetTxBuffer[1600]; -void ServerSocket::send(uint8_t* buffer, size_t size) { - m_sendBuffer = buffer; - m_sendSize = size; - m_sendRequest = true; + // copy pbuf -> tx buffer + pbuf_copy_partial(outgoing_pbuf, ethernetTxBuffer, outgoing_pbuf->tot_len, 0); - // Wake the driver to perform the actual send - isrSemaphore.signal(); + // transmit the frame + m2m_wifi_send_ethernet_pkt(ethernetTxBuffer, outgoing_pbuf->tot_len); - // Wait for this chunk to complete - m_sendDoneSemaphore.wait(); + outgoing_pbuf = nullptr; + sendDoneSemaphore.signal(); + } } -void ServerSocket::onSendDone() { - // Send completed, notify caller! - chibios_rt::CriticalSectionLocker csl; - m_sendDoneSemaphore.signalI(); -} +static thread_t* wifiThreadRef = nullptr; -size_t ServerSocket::recvTimeout(uint8_t* buffer, size_t size, int timeout) { - return iqReadTimeout(&m_recvQueue, buffer, size, timeout); -} +static err_t low_level_output(struct netif *netif, struct pbuf *p) { + if (netif != &thisif) { + return ERR_IF; + } -/*static*/ ServerSocket* ServerSocket::findListener(int sock) { - auto current = s_serverList; + #if ETH_PAD_SIZE + // drop the padding word + pbuf_header(p, -ETH_PAD_SIZE); + #endif - while (current) { - if (current->m_listenerSocket == sock) { - break; - } + outgoing_pbuf = p; - current = current->m_nextServer; + if (wifiThreadRef == chThdGetSelfX()) { + checkOutgoingPbuf(); + } else { + isrSemaphore.signal(); } - return current; -} + sendDoneSemaphore.wait(); -/*static*/ ServerSocket* ServerSocket::findConnected(int sock) { - auto current = s_serverList; + #if ETH_PAD_SIZE + // reclaim the padding word + pbuf_header(p, ETH_PAD_SIZE); + #endif - while (current) { - if (current->m_connectedSocket == sock) { - break; - } - - current = current->m_nextServer; - } + // isrSemaphore.signal(); - return current; + return ERR_OK; } -bool ServerSocket::trySendImpl() { - if ((m_connectedSocket != -1) && m_sendRequest) { - ::send(m_connectedSocket, (void*)m_sendBuffer, m_sendSize, 0); - m_sendRequest = false; +static err_t ethernetif_init(struct netif *netif) { + netif->linkoutput = low_level_output; + netif->output = etharp_output; + netif->mtu = LWIP_NETIF_MTU; + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an Ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; - return true; - } + netif->name[0] = 'w'; + netif->name[1] = '0'; - return false; -} + netif->hwaddr_len = ETHARP_HWADDR_LEN; -void os_hook_isr() { - isrSemaphore.signalI(); -} + netif->state = NULL; -static void wifiCallback(uint8 u8MsgType, void* pvMsg) { - switch (u8MsgType) { - case M2M_WIFI_REQ_DHCP_CONF: { - auto& dhcpInfo = *reinterpret_cast(pvMsg); - uint8_t* addr = reinterpret_cast(&dhcpInfo.u32StaticIP); - efiPrintf("WiFi client connected DHCP IP is %d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); - } break; - default: - efiPrintf("WifiCallback: %d", (int)u8MsgType); - break; - } + return ERR_OK; } -static void socketCallback(SOCKET sock, uint8_t u8Msg, void* pvMsg) { - switch (u8Msg) { - case SOCKET_MSG_BIND: { - auto bindMsg = reinterpret_cast(pvMsg); - if (bindMsg && bindMsg->status == 0) { - // Socket bind complete, now listen! - listen(sock, 1); - } - } break; - case SOCKET_MSG_LISTEN: { - auto listenMsg = reinterpret_cast(pvMsg); - if (listenMsg && listenMsg->status == 0) { - // Listening, now accept a connection - accept(sock, nullptr, nullptr); - } - } break; - case SOCKET_MSG_ACCEPT: { - auto acceptMsg = reinterpret_cast(pvMsg); - if (acceptMsg && (acceptMsg->sock >= 0)) { - if (auto server = ServerSocket::findListener(sock)) { - server->onAccept(acceptMsg->sock); - } - } - } break; - case SOCKET_MSG_RECV: { - auto recvMsg = reinterpret_cast(pvMsg); - if (recvMsg && (recvMsg->s16BufferSize > 0)) { - if (auto server = ServerSocket::findConnected(sock)) { - server->onRecv(recvMsg->pu8Buffer, recvMsg->s16BufferSize, recvMsg->u16RemainingSize); - } - } else { - if (auto server = ServerSocket::findConnected(sock)) { - server->onClose(); - } - } - } break; - case SOCKET_MSG_SEND: { - if (auto server = ServerSocket::findConnected(sock)) { - server->onSendDone(); - } - } break; +bool setupLwip() { + tcpip_init(NULL, NULL); + + ip4_addr_t ip, gateway, netmask; + LWIP_IPADDR(&ip); + LWIP_GATEWAY(&gateway); + LWIP_NETMASK(&netmask); + + auto result = netifapi_netif_add(&thisif, &ip, &netmask, &gateway, NULL, ethernetif_init, tcpip_input); + if (result != ERR_OK) { + return false; } + + netifapi_netif_set_default(&thisif); + netifapi_netif_set_up(&thisif); + netifapi_netif_set_link_up(&thisif); + + return true; } class WifiHelperThread : public ThreadController<4096> { public: WifiHelperThread() : ThreadController("WiFi", WIFI_THREAD_PRIORITY) {} void ThreadTask() override { + wifiThreadRef = chThdGetSelfX(); + if (!initWifi()) { return; } @@ -216,11 +193,12 @@ class WifiHelperThread : public ThreadController<4096> { while (true) { + // check for outgoing frame + checkOutgoingPbuf(); + m2m_wifi_handle_events(nullptr); - if (!ServerSocket::checkSend()) { - isrSemaphore.wait(TIME_MS2I(1)); - } + isrSemaphore.wait(TIME_MS2I(1)); } } @@ -233,6 +211,14 @@ class WifiHelperThread : public ThreadController<4096> { // Initialize the WiFi module static tstrWifiInitParam param; param.pfAppWifiCb = wifiCallback; + + // Ethernet options + static NO_CACHE uint8_t ethernetRxBuffer[1600]; + param.strEthInitParam.pfAppEthCb = ethernetCallback; + param.strEthInitParam.au8ethRcvBuf = ethernetRxBuffer; + param.strEthInitParam.u16ethRcvBufSize = sizeof(ethernetRxBuffer); + param.strEthInitParam.u8EthernetEnable = M2M_WIFI_MODE_ETHERNET; + if (auto ret = m2m_wifi_init(¶m); M2M_SUCCESS != ret) { efiPrintf("Wifi init failed with: %d", ret); return false; @@ -263,11 +249,12 @@ class WifiHelperThread : public ThreadController<4096> { return false; } - // Set up the socket APIs - socketInit(); - registerSocketCallback(socketCallback, nullptr); + // Set the real WiFi chipset's MAC address on the lwip interface + if (M2M_SUCCESS != m2m_wifi_get_mac_address(thisif.hwaddr)) { + return false; + } - return true; + return setupLwip(); } bool m_initDone = false; diff --git a/firmware/net/wifi_socket.h b/firmware/net/wifi_socket.h index e774f1b334..fc8d263104 100644 --- a/firmware/net/wifi_socket.h +++ b/firmware/net/wifi_socket.h @@ -3,48 +3,48 @@ void initWifi(); void waitForWifiInit(); -struct sockaddr_in; +// struct sockaddr_in; -class ServerSocket { -public: - ServerSocket(); +// class ServerSocket { +// public: +// ServerSocket(); - // User functions: listen, recv, send - void startListening(const sockaddr_in& addr); - size_t recvTimeout(uint8_t* buffer, size_t size, int timeout); - void send(uint8_t* buffer, size_t size); +// // User functions: listen, recv, send +// void startListening(const sockaddr_in& addr); +// size_t recvTimeout(uint8_t* buffer, size_t size, int timeout); +// void send(uint8_t* buffer, size_t size); - // Calls up from the driver to notify of a change - void onAccept(int connectedSocket); - void onClose(); - void onRecv(uint8_t* buffer, size_t recvSize, size_t remaining); - void onSendDone(); - static bool checkSend(); +// // Calls up from the driver to notify of a change +// void onAccept(int connectedSocket); +// void onClose(); +// void onRecv(uint8_t* buffer, size_t recvSize, size_t remaining); +// void onSendDone(); +// static bool checkSend(); - bool hasConnectedSocket() const; +// bool hasConnectedSocket() const; - static ServerSocket* findListener(int sock); - static ServerSocket* findConnected(int sock); +// static ServerSocket* findListener(int sock); +// static ServerSocket* findConnected(int sock); -private: - bool trySendImpl(); +// private: +// bool trySendImpl(); - int m_listenerSocket = -1; - int m_connectedSocket = -1; +// int m_listenerSocket = -1; +// int m_connectedSocket = -1; - // TX helper data - const uint8_t* m_sendBuffer; - size_t m_sendSize; - bool m_sendRequest = false; - chibios_rt::BinarySemaphore m_sendDoneSemaphore{/* taken =*/ true}; +// // TX helper data +// const uint8_t* m_sendBuffer; +// size_t m_sendSize; +// bool m_sendRequest = false; +// chibios_rt::BinarySemaphore m_sendDoneSemaphore{/* taken =*/ true}; - // RX data - uint8_t m_recvBuf[512]; +// // RX data +// uint8_t m_recvBuf[512]; - uint8_t m_recvQueueBuffer[512]; - input_queue_t m_recvQueue; +// uint8_t m_recvQueueBuffer[512]; +// input_queue_t m_recvQueue; - // Linked list of all server sockets - static ServerSocket* s_serverList; - ServerSocket* m_nextServer = nullptr; -}; +// // Linked list of all server sockets +// static ServerSocket* s_serverList; +// ServerSocket* m_nextServer = nullptr; +// }; diff --git a/firmware/rusefi.cpp b/firmware/rusefi.cpp index e1b3c3e923..3e173452d2 100644 --- a/firmware/rusefi.cpp +++ b/firmware/rusefi.cpp @@ -258,7 +258,7 @@ void runRusEfiWithConfig() { initHardware(); #if EFI_WIFI - startWifiConsole(); + initWifi(); #endif #if EFI_FILE_LOGGING From 05ef81d0d3d188013624c7038c7a4aff7318e8a4 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Sat, 15 Mar 2025 21:18:05 -0700 Subject: [PATCH 2/9] remove semaphore in favor of mutex (saves a context switch!) --- firmware/net/wifi_socket.cpp | 55 ++++++++++++------------------------ 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/firmware/net/wifi_socket.cpp b/firmware/net/wifi_socket.cpp index f93a8e659e..2d7ab7fc71 100644 --- a/firmware/net/wifi_socket.cpp +++ b/firmware/net/wifi_socket.cpp @@ -18,7 +18,6 @@ #include static chibios_rt::BinarySemaphore isrSemaphore(/* taken =*/ true); -static chibios_rt::BinarySemaphore sendDoneSemaphore{/* taken =*/ true}; void os_hook_isr() { isrSemaphore.signalI(); @@ -87,29 +86,7 @@ void ethernetCallback(uint8 u8MsgType, void * pvMsg,void * pvCtrlBuf) { } } -static pbuf* outgoing_pbuf = nullptr; - -void checkOutgoingPbuf() { - if (outgoing_pbuf) { - #if ETH_PAD_SIZE - // drop the padding word - pbuf_header(outgoing_pbuf, -ETH_PAD_SIZE); - #endif - - static NO_CACHE uint8_t ethernetTxBuffer[1600]; - - // copy pbuf -> tx buffer - pbuf_copy_partial(outgoing_pbuf, ethernetTxBuffer, outgoing_pbuf->tot_len, 0); - - // transmit the frame - m2m_wifi_send_ethernet_pkt(ethernetTxBuffer, outgoing_pbuf->tot_len); - - outgoing_pbuf = nullptr; - sendDoneSemaphore.signal(); - } -} - -static thread_t* wifiThreadRef = nullptr; +static chibios_rt::Mutex wifiAccessMutex; static err_t low_level_output(struct netif *netif, struct pbuf *p) { if (netif != &thisif) { @@ -121,15 +98,21 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p) { pbuf_header(p, -ETH_PAD_SIZE); #endif - outgoing_pbuf = p; + #if ETH_PAD_SIZE + // drop the padding word + pbuf_header(p, -ETH_PAD_SIZE); + #endif - if (wifiThreadRef == chThdGetSelfX()) { - checkOutgoingPbuf(); - } else { - isrSemaphore.signal(); - } + static NO_CACHE uint8_t ethernetTxBuffer[1600]; - sendDoneSemaphore.wait(); + // copy pbuf -> tx buffer + pbuf_copy_partial(p, ethernetTxBuffer, p->tot_len, 0); + + { + // transmit the frame + chibios_rt::MutexLocker lock(wifiAccessMutex); + m2m_wifi_send_ethernet_pkt(ethernetTxBuffer, p->tot_len); + } #if ETH_PAD_SIZE // reclaim the padding word @@ -183,8 +166,6 @@ class WifiHelperThread : public ThreadController<4096> { public: WifiHelperThread() : ThreadController("WiFi", WIFI_THREAD_PRIORITY) {} void ThreadTask() override { - wifiThreadRef = chThdGetSelfX(); - if (!initWifi()) { return; } @@ -193,10 +174,10 @@ class WifiHelperThread : public ThreadController<4096> { while (true) { - // check for outgoing frame - checkOutgoingPbuf(); - - m2m_wifi_handle_events(nullptr); + { + chibios_rt::MutexLocker lock(wifiAccessMutex); + m2m_wifi_handle_events(nullptr); + } isrSemaphore.wait(TIME_MS2I(1)); } From 791ccaf9ca22c4c50325cf66a1ef6eaccd695d7e Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Sat, 15 Mar 2025 21:43:07 -0700 Subject: [PATCH 3/9] move ethernet buffers to global scope --- firmware/net/wifi_socket.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/firmware/net/wifi_socket.cpp b/firmware/net/wifi_socket.cpp index 2d7ab7fc71..aa981c3805 100644 --- a/firmware/net/wifi_socket.cpp +++ b/firmware/net/wifi_socket.cpp @@ -86,6 +86,8 @@ void ethernetCallback(uint8 u8MsgType, void * pvMsg,void * pvCtrlBuf) { } } +static NO_CACHE uint8_t ethernetTxBuffer[1600]; +static NO_CACHE uint8_t ethernetRxBuffer[1600]; static chibios_rt::Mutex wifiAccessMutex; static err_t low_level_output(struct netif *netif, struct pbuf *p) { @@ -103,8 +105,6 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p) { pbuf_header(p, -ETH_PAD_SIZE); #endif - static NO_CACHE uint8_t ethernetTxBuffer[1600]; - // copy pbuf -> tx buffer pbuf_copy_partial(p, ethernetTxBuffer, p->tot_len, 0); @@ -194,7 +194,6 @@ class WifiHelperThread : public ThreadController<4096> { param.pfAppWifiCb = wifiCallback; // Ethernet options - static NO_CACHE uint8_t ethernetRxBuffer[1600]; param.strEthInitParam.pfAppEthCb = ethernetCallback; param.strEthInitParam.au8ethRcvBuf = ethernetRxBuffer; param.strEthInitParam.u16ethRcvBufSize = sizeof(ethernetRxBuffer); From 3b9d110e0939eccdadd6608a2cbc38953eec1edd Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Sat, 15 Mar 2025 21:59:37 -0700 Subject: [PATCH 4/9] share a single ethernet buffer --- firmware/net/wifi_socket.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/firmware/net/wifi_socket.cpp b/firmware/net/wifi_socket.cpp index aa981c3805..e19551f9a2 100644 --- a/firmware/net/wifi_socket.cpp +++ b/firmware/net/wifi_socket.cpp @@ -86,8 +86,7 @@ void ethernetCallback(uint8 u8MsgType, void * pvMsg,void * pvCtrlBuf) { } } -static NO_CACHE uint8_t ethernetTxBuffer[1600]; -static NO_CACHE uint8_t ethernetRxBuffer[1600]; +static NO_CACHE uint8_t ethernetBuffer[1600]; static chibios_rt::Mutex wifiAccessMutex; static err_t low_level_output(struct netif *netif, struct pbuf *p) { @@ -105,13 +104,14 @@ static err_t low_level_output(struct netif *netif, struct pbuf *p) { pbuf_header(p, -ETH_PAD_SIZE); #endif - // copy pbuf -> tx buffer - pbuf_copy_partial(p, ethernetTxBuffer, p->tot_len, 0); - { - // transmit the frame chibios_rt::MutexLocker lock(wifiAccessMutex); - m2m_wifi_send_ethernet_pkt(ethernetTxBuffer, p->tot_len); + + // copy pbuf -> tx buffer + pbuf_copy_partial(p, ethernetBuffer, p->tot_len, 0); + + // transmit the frame + m2m_wifi_send_ethernet_pkt(ethernetBuffer, p->tot_len); } #if ETH_PAD_SIZE @@ -195,8 +195,8 @@ class WifiHelperThread : public ThreadController<4096> { // Ethernet options param.strEthInitParam.pfAppEthCb = ethernetCallback; - param.strEthInitParam.au8ethRcvBuf = ethernetRxBuffer; - param.strEthInitParam.u16ethRcvBufSize = sizeof(ethernetRxBuffer); + param.strEthInitParam.au8ethRcvBuf = ethernetBuffer; + param.strEthInitParam.u16ethRcvBufSize = sizeof(ethernetBuffer); param.strEthInitParam.u8EthernetEnable = M2M_WIFI_MODE_ETHERNET; if (auto ret = m2m_wifi_init(¶m); M2M_SUCCESS != ret) { From 6ded31974d0226f6fef0d512ca8ff2a962ab50fb Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Sat, 15 Mar 2025 22:00:04 -0700 Subject: [PATCH 5/9] s --- firmware/config/boards/atlas/board.mk | 2 ++ firmware/rusefi.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/firmware/config/boards/atlas/board.mk b/firmware/config/boards/atlas/board.mk index 8c67b44a09..fd0be08d2d 100644 --- a/firmware/config/boards/atlas/board.mk +++ b/firmware/config/boards/atlas/board.mk @@ -21,6 +21,8 @@ DDEFS += -DSTM32_LSE_BYPASS # We are running on Atlas hardware! DDEFS += -DHW_ATLAS=1 +include $(PROJECT_DIR)/controllers/modules/ethernet_console/ethernet_console.mk + # Atlas has WiFi USE_WIFI = yes diff --git a/firmware/rusefi.cpp b/firmware/rusefi.cpp index 3e173452d2..7fc9732c1a 100644 --- a/firmware/rusefi.cpp +++ b/firmware/rusefi.cpp @@ -133,6 +133,7 @@ #include "mass_storage_init.h" #include "trigger_emulator_algo.h" #include "rusefi_lua.h" +#include "wifi_socket.h" #include From e96e70cff78d42ee67705ce869c24e17a3e5b847 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Sun, 16 Mar 2025 00:23:44 -0700 Subject: [PATCH 6/9] faster tcp timer interval --- firmware/net/lwipopts.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/firmware/net/lwipopts.h b/firmware/net/lwipopts.h index b5172fddae..4e81afa2e8 100644 --- a/firmware/net/lwipopts.h +++ b/firmware/net/lwipopts.h @@ -78,6 +78,12 @@ #define LWIP_TCP_SACK_OUT 1 #define LWIP_TCP_MAX_SACK_NUM 8 +// Crank the TCP timer interval down to 10ms (down from 250ms default) +// As this sets the lower limit on retransmissions +// We want retransmissions to be super snappy in case of a dropped frame +#define TCP_TMR_INTERVAL 10 +#define LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT 5000 + // Enable the socket recv timeout (and it uses a nonstandard option of int, rather than timeval) #define LWIP_SO_SNDRCVTIMEO_NONSTANDARD 1 #define LWIP_SO_RCVTIMEO 1 From 5472644b2b18ac1b6e8071299a324102eacf6e89 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Sun, 16 Mar 2025 00:43:45 -0700 Subject: [PATCH 7/9] lwip tuning --- firmware/net/lwipopts.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/firmware/net/lwipopts.h b/firmware/net/lwipopts.h index 4e81afa2e8..5152ef5d1f 100644 --- a/firmware/net/lwipopts.h +++ b/firmware/net/lwipopts.h @@ -71,13 +71,10 @@ #include "rusefi_generated.h" // Ensure that one TCP segment can always fit an entire response to TS - we never need to split a TS packet across multiple frames. -#define TCP_MSS 8192 +#define TCP_MSS (BLOCKING_FACTOR + 10) #define MEM_SIZE 65536 -#define LWIP_TCP_SACK_OUT 1 -#define LWIP_TCP_MAX_SACK_NUM 8 - // Crank the TCP timer interval down to 10ms (down from 250ms default) // As this sets the lower limit on retransmissions // We want retransmissions to be super snappy in case of a dropped frame From fd02923a9e2ff0fa008863b57f72e9dd1291ed1c Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Sun, 16 Mar 2025 00:47:12 -0700 Subject: [PATCH 8/9] lwip options tuning --- firmware/net/lwipopts.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/net/lwipopts.h b/firmware/net/lwipopts.h index 5152ef5d1f..1235dac058 100644 --- a/firmware/net/lwipopts.h +++ b/firmware/net/lwipopts.h @@ -52,8 +52,8 @@ #define LWIP_COMPAT_SOCKETS 0 -#define LWIP_RAW 4 -#define LWIP_TCP 4 +#define LWIP_RAW 0 +#define LWIP_TCP 1 #define LWIP_UDP 0 #define LWIP_STATS 0 From 953ede0aa63e6f78a84d3b319aa6838f70d93e3a Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Sun, 16 Mar 2025 00:47:25 -0700 Subject: [PATCH 9/9] lwip options --- firmware/net/lwipopts.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/net/lwipopts.h b/firmware/net/lwipopts.h index 1235dac058..94b9228b6c 100644 --- a/firmware/net/lwipopts.h +++ b/firmware/net/lwipopts.h @@ -43,7 +43,7 @@ #define TCPIP_MBOX_SIZE MEMP_NUM_PBUF #endif #if !defined(TCPIP_THREAD_STACKSIZE) -#define TCPIP_THREAD_STACKSIZE 4096 +#define TCPIP_THREAD_STACKSIZE 1024 #endif #define LWIP_LINK_POLL_INTERVAL TIME_S2I(1)