diff --git a/README.md b/README.md index 41b3759..be202b9 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ original Arduino firmware repository. 1. [Download the ESP32 toolchain](https://docs.espressif.com/projects/esp-idf/en/v3.3.1/get-started/index.html#setup-toolchain) 1. Extract it and add it to your `PATH`: `export PATH=$PATH:/bin` -1. Clone **v3.3.1** of the IDF: `git clone --branch v3.3.1 --recursive https://github.com/espressif/esp-idf.git` +1. Clone **v5.5** of the IDF: `git clone --branch v5.5 --recursive https://github.com/espressif/esp-idf.git` 1. Set the `IDF_PATH` environment variable: `export IDF_PATH=` 1. `git submodule update --init` to fetch the `certificates` submodule. 1. Run `make firmware` to build the firmware (in the directory of this read me) diff --git a/main/CommandHandler.cpp b/main/CommandHandler.cpp index 7e9e708..a15a426 100644 --- a/main/CommandHandler.cpp +++ b/main/CommandHandler.cpp @@ -63,7 +63,7 @@ int errno; // Note: following version definition line is parsed by python script. Please don't change its format (space, indent) only update its version number. // ADAFRUIT-CHANGE: not fixed length -// The version number obeys semver rules. We suffix with "+adafruit" to distinguish from Arduino NINA-FW. +// The version number obeys semver rules. We suffix with "+adafruit" to distinguish from Arduino NINA-FW. const char FIRMWARE_VERSION[] = "3.0.0"; // ADAFRUIT-CHANGE: user-supplied cert and key @@ -81,6 +81,7 @@ uint32_t resolvedHostname; #define MAX_SOCKETS CONFIG_LWIP_MAX_SOCKETS uint8_t socketTypes[MAX_SOCKETS]; +SemaphoreHandle_t socketMutex[MAX_SOCKETS]; NetworkClient tcpClients[MAX_SOCKETS]; NetworkUDP udps[MAX_SOCKETS]; NetworkServer tcpServers[MAX_SOCKETS]; @@ -668,6 +669,7 @@ int startServerTcp(const uint8_t command[], uint8_t response[]) int getStateTcp(const uint8_t command[], uint8_t response[]) { uint8_t socket = command[4]; + xSemaphoreTake(socketMutex[socket], portMAX_DELAY); response[2] = 1; // number of parameters response[3] = 1; // parameter 1 length @@ -678,6 +680,8 @@ int getStateTcp(const uint8_t command[], uint8_t response[]) response[4] = 0; } + xSemaphoreGive(socketMutex[socket]); + return 6; } @@ -697,6 +701,8 @@ int availDataTcp(const uint8_t command[], uint8_t response[]) uint8_t socket = command[4]; uint16_t available = 0; + xSemaphoreTake(socketMutex[socket], portMAX_DELAY); + if (socketTypes[socket] == TCP_MODE) { if (tcpServers[socket]) { @@ -763,6 +769,8 @@ int availDataTcp(const uint8_t command[], uint8_t response[]) memcpy(&response[4], &available, sizeof(available)); + xSemaphoreGive(socketMutex[socket]); + return 7; } @@ -771,6 +779,8 @@ int getDataTcp(const uint8_t command[], uint8_t response[]) uint8_t socket = command[4]; uint8_t peek = command[6]; + xSemaphoreTake(socketMutex[socket], portMAX_DELAY); + response[2] = 1; // number of parameters response[3] = 1; // parameter 1 length @@ -794,6 +804,8 @@ int getDataTcp(const uint8_t command[], uint8_t response[]) } } + xSemaphoreGive(socketMutex[socket]); + return 6; } @@ -823,6 +835,8 @@ int startClientTcp(const uint8_t command[], uint8_t response[]) type = command[15 + command[3]]; } + xSemaphoreTake(socketMutex[socket], portMAX_DELAY); + if (type == TCP_MODE) { int result; @@ -832,6 +846,8 @@ int startClientTcp(const uint8_t command[], uint8_t response[]) result = tcpClients[socket].connect(ip, port); } + xSemaphoreGive(socketMutex[socket]); + if (result) { socketTypes[socket] = TCP_MODE; @@ -854,6 +870,8 @@ int startClientTcp(const uint8_t command[], uint8_t response[]) result = udps[socket].beginPacket(ip, port); } + xSemaphoreGive(socketMutex[socket]); + if (result == 1) { socketTypes[socket] = UDP_MODE; @@ -884,6 +902,8 @@ int startClientTcp(const uint8_t command[], uint8_t response[]) result = tlsClients[socket].connect(ip, port); } + xSemaphoreGive(socketMutex[socket]); + if (result) { socketTypes[socket] = TLS_MODE; @@ -907,6 +927,7 @@ int startClientTcp(const uint8_t command[], uint8_t response[]) int stopClientTcp(const uint8_t command[], uint8_t response[]) { uint8_t socket = command[4]; + xSemaphoreTake(socketMutex[socket], portMAX_DELAY); if (socketTypes[socket] == TCP_MODE) { tcpClients[socket].stop(); @@ -917,6 +938,8 @@ int stopClientTcp(const uint8_t command[], uint8_t response[]) } socketTypes[socket] = NO_MODE; + xSemaphoreGive(socketMutex[socket]); + response[2] = 1; // number of parameters response[3] = 1; // parameter 1 length response[4] = 1; @@ -927,6 +950,7 @@ int stopClientTcp(const uint8_t command[], uint8_t response[]) int getClientStateTcp(const uint8_t command[], uint8_t response[]) { uint8_t socket = command[4]; + xSemaphoreTake(socketMutex[socket], portMAX_DELAY); response[2] = 1; // number of parameters response[3] = 1; // parameter 1 length @@ -940,6 +964,8 @@ int getClientStateTcp(const uint8_t command[], uint8_t response[]) response[4] = 0; } + xSemaphoreGive(socketMutex[socket]); + return 6; } @@ -1032,6 +1058,7 @@ int getFwVersion(const uint8_t command[], uint8_t response[]) int sendUDPdata(const uint8_t command[], uint8_t response[]) { uint8_t socket = command[4]; + xSemaphoreTake(socketMutex[socket], portMAX_DELAY); response[2] = 1; // number of parameters response[3] = 1; // parameter 1 length @@ -1042,12 +1069,15 @@ int sendUDPdata(const uint8_t command[], uint8_t response[]) response[4] = 0; } + xSemaphoreGive(socketMutex[socket]); + return 6; } int getRemoteData(const uint8_t command[], uint8_t response[]) { uint8_t socket = command[4]; + xSemaphoreTake(socketMutex[socket], portMAX_DELAY); /*IPAddress*/uint32_t ip = /*IPAddress(0, 0, 0, 0)*/0; uint16_t port = 0; @@ -1063,6 +1093,8 @@ int getRemoteData(const uint8_t command[], uint8_t response[]) port = tlsClients[socket].remotePort(); } + xSemaphoreGive(socketMutex[socket]); + response[2] = 2; // number of parameters response[3] = 4; // parameter 1 length @@ -2420,6 +2452,43 @@ const CommandHandlerType commandHandlers[] = { }; #define NUM_COMMAND_HANDLERS (sizeof(commandHandlers) / sizeof(commandHandlers[0])) +#if defined(CMAKE_BUILD_TYPE_DEBUG) && 0 +const char* commandStrings[] = { + // 0x00 -> 0x0f + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // 0x10 -> 0x1f + "setNet", "setPassPhrase", "setKey", NULL, "setIPconfig", "setDNSconfig", "setHostname", "setPowerMode", "setApNet", "setApPassPhrase", "setDebug", "getTemperature", NULL, NULL, "getDNSconfig", "getReasonCode", + // 0x20 -> 0x2f + "getConnStatus", "getIPaddr", "getMACaddr", "getCurrSSID", "getCurrBSSID", "getCurrRSSI", "getCurrEnct", "scanNetworks", "startServerTcp", "getStateTcp", "dataSentTcp", "availDataTcp", "getDataTcp", "startClientTcp", "stopClientTcp", "getClientStateTcp", + // 0x30 -> 0x3f + "disconnect", NULL, "getIdxRSSI", "getIdxEnct", "reqHostByName", "getHostByName", "startScanNetworks", "getFwVersion", NULL, "sendUDPdata", "getRemoteData", "getTime", "getIdxBSSID", "getIdxChannel", "ping", "getSocket", + // 0x40 -> 0x4f + "setClientCert", "setCertKey", NULL, NULL, "sendDataTcp", "getDataBufTcp", "insertDataBuf", NULL, NULL, NULL, "wpa2EntSetIdentity", "wpa2EntSetUsername", "wpa2EntSetPassword", "wpa2EntSetCACert", "wpa2EntSetCertKey", "wpa2EntEnable", + // 0x50 -> 0x5f + "setPinMode", "setDigitalWrite", "setAnalogWrite", "getDigitalRead", "getAnalogRead", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // 0x60 -> 0x6f + "writeFile", "readFile", "deleteFile", "existsFile", "downloadFile", "applyOTA", "renameFile", "downloadOTA", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // Low-level BSD-like sockets functions. + // 0x70 -> 0x7f + "socket_socket", + "socket_close", + "socket_errno", + "socket_bind", + "socket_listen", + "socket_accept", + "socket_connect", + "socket_send", + "socket_recv", + "socket_sendto", + "socket_recvfrom", + "socket_ioctl", + "socket_poll", + "socket_setsockopt", + "socket_getsockopt", + "socket_getpeername" +}; +#endif + CommandHandlerClass::CommandHandlerClass() { } @@ -2436,12 +2505,13 @@ void CommandHandlerClass::begin() for (int i = 0; i < MAX_SOCKETS; i++) { socketTypes[i] = NO_MODE; + socketMutex[i] = xSemaphoreCreateMutex(); } _updateGpio0PinSemaphore = xSemaphoreCreateCounting(2, 0); // change priority to higher than loop task() to prevent socket connected() and available() race condition - xTaskCreatePinnedToCore(CommandHandlerClass::gpio0Updater, "gpio0Updater", 8192, NULL, 2, NULL, + xTaskCreatePinnedToCore(CommandHandlerClass::gpio0Updater, "gpio0Updater", 8192, NULL, 1, NULL, CONFIG_FREERTOS_NUMBER_OF_CORES-1); } @@ -2453,6 +2523,13 @@ int CommandHandlerClass::handle(const uint8_t command[], uint8_t response[]) int responseLength = 0; if (command[0] == START_CMD && command[1] < NUM_COMMAND_HANDLERS) { + #if defined(CMAKE_BUILD_TYPE_DEBUG) && 0 + const char* cmdStr = (command[1] < sizeof(commandStrings) / sizeof(commandStrings[0])) ? commandStrings[command[1]] : NULL; + if (cmdStr) { + ets_printf("Command %u: %s\r\n", command[1], cmdStr); + } + #endif + CommandHandlerType commandHandlerType = commandHandlers[command[1]]; if (commandHandlerType) { @@ -2489,8 +2566,12 @@ void CommandHandlerClass::updateGpio0Pin() xSemaphoreTake(_updateGpio0PinSemaphore, portMAX_DELAY); int available = 0; + int i; + for (i = 0; i < MAX_SOCKETS; i++) { + if (pdFALSE == xSemaphoreTake(socketMutex[i], 0)) { + continue; // skip if mutex is not available + } - for (int i = 0; i < MAX_SOCKETS; i++) { if (socketTypes[i] == TCP_MODE) { if (tcpServers[i] && (tcpServers[i].hasClient() || tcpServers[i].accept())) { available = 1; @@ -2511,15 +2592,17 @@ void CommandHandlerClass::updateGpio0Pin() break; } + xSemaphoreGive(socketMutex[i]); } if (available) { + xSemaphoreGive(socketMutex[i]); // break early, not giving back semaphore yet digitalWrite(GPIO_IRQ, HIGH); } else { digitalWrite(GPIO_IRQ, LOW); } - vTaskDelay(1); + // vTaskDelay(1); } void CommandHandlerClass::onWiFiReceive()