diff --git a/images/ESP8266_TCP_Client_VET6.png b/images/ESP8266_TCP_Client_VET6.png index 9383c43..af87385 100644 Binary files a/images/ESP8266_TCP_Client_VET6.png and b/images/ESP8266_TCP_Client_VET6.png differ diff --git a/workspace/ESP8266_AT_CMD_VET6/Core/Inc/wifi_passthrough.h b/workspace/ESP8266_AT_CMD_VET6/Core/Inc/wifi_passthrough.h index 8793dc4..8044c08 100644 --- a/workspace/ESP8266_AT_CMD_VET6/Core/Inc/wifi_passthrough.h +++ b/workspace/ESP8266_AT_CMD_VET6/Core/Inc/wifi_passthrough.h @@ -9,15 +9,15 @@ extern "C" { #endif // Replace these values for the Wi-Fi network and TCP server used for testing -#define WIFI_PASSTHROUGH_SSID "HC_HOME" -#define WIFI_PASSTHROUGH_PASSWORD "$Bb1988121!" -#define WIFI_PASSTHROUGH_SERVER_IP "192.168.1.176" +#define WIFI_PASSTHROUGH_SSID "WIFI_SSID" +#define WIFI_PASSTHROUGH_PASSWORD "WIFI_PASSWORD" +#define WIFI_PASSTHROUGH_SERVER_IP "SERVER_IP" #define WIFI_PASSTHROUGH_SERVER_PORT 8000U // Set to 0 to disable generated traffic and use only the USART1 bridge #define WIFI_PASSTHROUGH_ENABLE_TEST_PAYLOAD 1U -#define WIFI_PASSTHROUGH_TEST_INTERVAL_MS 1000U -#define WIFI_PASSTHROUGH_TEST_LINE_REPEAT 40U +#define WIFI_PASSTHROUGH_TEST_INTERVAL_MS 2000U +#define WIFI_PASSTHROUGH_TEST_LINE_REPEAT 2U void WiFiPassthrough_Run(UART_HandleTypeDef *console_uart, ringBuffer_t *console_rx_buffer); diff --git a/workspace/ESP8266_AT_CMD_VET6/Core/Src/wifi_passthrough.c b/workspace/ESP8266_AT_CMD_VET6/Core/Src/wifi_passthrough.c index 3546681..bb48447 100644 --- a/workspace/ESP8266_AT_CMD_VET6/Core/Src/wifi_passthrough.c +++ b/workspace/ESP8266_AT_CMD_VET6/Core/Src/wifi_passthrough.c @@ -4,8 +4,18 @@ #include "stm32f407xx_esp8266.h" #include "wifi_passthrough.h" +/* Maximum bytes transferred per loop iteration in either direction: + * UART1 console <-> UART3 ESP8266/TCP. */ #define WIFI_BRIDGE_CHUNK_SIZE 64U +#if (WIFI_BRIDGE_CHUNK_SIZE == 0U) || \ + (WIFI_BRIDGE_CHUNK_SIZE >= RING_BUFFER_SIZE) +#error "WIFI_BRIDGE_CHUNK_SIZE must be between 1 and RING_BUFFER_SIZE - 1" +#endif + +/* Configure the ESP8266, open the TCP connection, and leave the module in + * transparent mode. Once this succeeds, bytes written to the ESP8266 UART + * are TCP payload rather than AT commands. */ static HAL_StatusTypeDef WiFiPassthrough_Connect(void) { HAL_StatusTypeDef status; @@ -68,6 +78,8 @@ static bool WiFiPassthrough_UpdateClosedState(uint8_t data) { return false; } +/* Move all currently queued console bytes (up to one chunk) to the TCP connection. + * HAL_OK with an empty console buffer is normal, not an error. */ static HAL_StatusTypeDef WiFiPassthrough_ForwardConsole( ringBuffer_t *console_rx_buffer) { uint8_t data[WIFI_BRIDGE_CHUNK_SIZE]; @@ -89,6 +101,9 @@ static HAL_StatusTypeDef WiFiPassthrough_ForwardConsole( return ESP8266_Transmit(data, length, 1000U); } +/* Move all currently queued ESP8266 bytes (up to one chunk) to the console. + * The bytes are also inspected for the asynchronous "CLOSED" notification. + * Returning true tells the caller to reset and reconnect the module. */ static bool WiFiPassthrough_ForwardNetwork(UART_HandleTypeDef *console_uart) { uint8_t data[WIFI_BRIDGE_CHUNK_SIZE]; uint16_t length = 0U; @@ -120,6 +135,8 @@ static HAL_StatusTypeDef WiFiPassthrough_SendTestPayload(void) { return status; } } + static const uint8_t end_line[] = "\r\n"; + ESP8266_Transmit(end_line, (uint16_t) (sizeof(end_line) - 1U), 1000U); return HAL_OK; } @@ -130,6 +147,8 @@ void WiFiPassthrough_Run(UART_HandleTypeDef *console_uart, uint32_t next_test_tick = 0U; bool connection_closed = false; + /* Initial connection failures are retried forever because this function is + * the application's long-running bridge task. */ while (WiFiPassthrough_Connect() != HAL_OK) { printf("ESP8266: Connection failed; resetting and retrying\r\n"); ESP8266_Reset(); @@ -139,10 +158,13 @@ void WiFiPassthrough_Run(UART_HandleTypeDef *console_uart, next_test_tick = HAL_GetTick(); for (;;) { + /* A UART transmit failure is treated as loss of the ESP8266 data path. + * This is the first path that can set connection_closed. */ if (WiFiPassthrough_ForwardConsole(console_rx_buffer) != HAL_OK) { connection_closed = true; } - + /* A "CLOSED" notification received from the ESP8266 is the second + * path that can set connection_closed. */ if (WiFiPassthrough_ForwardNetwork(console_uart)) { connection_closed = true; } diff --git a/workspace/ESP8266_TCP_Client_VET6/Core/Inc/wifi_passthrough.h b/workspace/ESP8266_TCP_Client_VET6/Core/Inc/wifi_passthrough.h index 8793dc4..8044c08 100644 --- a/workspace/ESP8266_TCP_Client_VET6/Core/Inc/wifi_passthrough.h +++ b/workspace/ESP8266_TCP_Client_VET6/Core/Inc/wifi_passthrough.h @@ -9,15 +9,15 @@ extern "C" { #endif // Replace these values for the Wi-Fi network and TCP server used for testing -#define WIFI_PASSTHROUGH_SSID "HC_HOME" -#define WIFI_PASSTHROUGH_PASSWORD "$Bb1988121!" -#define WIFI_PASSTHROUGH_SERVER_IP "192.168.1.176" +#define WIFI_PASSTHROUGH_SSID "WIFI_SSID" +#define WIFI_PASSTHROUGH_PASSWORD "WIFI_PASSWORD" +#define WIFI_PASSTHROUGH_SERVER_IP "SERVER_IP" #define WIFI_PASSTHROUGH_SERVER_PORT 8000U // Set to 0 to disable generated traffic and use only the USART1 bridge #define WIFI_PASSTHROUGH_ENABLE_TEST_PAYLOAD 1U -#define WIFI_PASSTHROUGH_TEST_INTERVAL_MS 1000U -#define WIFI_PASSTHROUGH_TEST_LINE_REPEAT 40U +#define WIFI_PASSTHROUGH_TEST_INTERVAL_MS 2000U +#define WIFI_PASSTHROUGH_TEST_LINE_REPEAT 2U void WiFiPassthrough_Run(UART_HandleTypeDef *console_uart, ringBuffer_t *console_rx_buffer); diff --git a/workspace/ESP8266_TCP_Client_VET6/Core/Src/wifi_passthrough.c b/workspace/ESP8266_TCP_Client_VET6/Core/Src/wifi_passthrough.c index 3546681..bb48447 100644 --- a/workspace/ESP8266_TCP_Client_VET6/Core/Src/wifi_passthrough.c +++ b/workspace/ESP8266_TCP_Client_VET6/Core/Src/wifi_passthrough.c @@ -4,8 +4,18 @@ #include "stm32f407xx_esp8266.h" #include "wifi_passthrough.h" +/* Maximum bytes transferred per loop iteration in either direction: + * UART1 console <-> UART3 ESP8266/TCP. */ #define WIFI_BRIDGE_CHUNK_SIZE 64U +#if (WIFI_BRIDGE_CHUNK_SIZE == 0U) || \ + (WIFI_BRIDGE_CHUNK_SIZE >= RING_BUFFER_SIZE) +#error "WIFI_BRIDGE_CHUNK_SIZE must be between 1 and RING_BUFFER_SIZE - 1" +#endif + +/* Configure the ESP8266, open the TCP connection, and leave the module in + * transparent mode. Once this succeeds, bytes written to the ESP8266 UART + * are TCP payload rather than AT commands. */ static HAL_StatusTypeDef WiFiPassthrough_Connect(void) { HAL_StatusTypeDef status; @@ -68,6 +78,8 @@ static bool WiFiPassthrough_UpdateClosedState(uint8_t data) { return false; } +/* Move all currently queued console bytes (up to one chunk) to the TCP connection. + * HAL_OK with an empty console buffer is normal, not an error. */ static HAL_StatusTypeDef WiFiPassthrough_ForwardConsole( ringBuffer_t *console_rx_buffer) { uint8_t data[WIFI_BRIDGE_CHUNK_SIZE]; @@ -89,6 +101,9 @@ static HAL_StatusTypeDef WiFiPassthrough_ForwardConsole( return ESP8266_Transmit(data, length, 1000U); } +/* Move all currently queued ESP8266 bytes (up to one chunk) to the console. + * The bytes are also inspected for the asynchronous "CLOSED" notification. + * Returning true tells the caller to reset and reconnect the module. */ static bool WiFiPassthrough_ForwardNetwork(UART_HandleTypeDef *console_uart) { uint8_t data[WIFI_BRIDGE_CHUNK_SIZE]; uint16_t length = 0U; @@ -120,6 +135,8 @@ static HAL_StatusTypeDef WiFiPassthrough_SendTestPayload(void) { return status; } } + static const uint8_t end_line[] = "\r\n"; + ESP8266_Transmit(end_line, (uint16_t) (sizeof(end_line) - 1U), 1000U); return HAL_OK; } @@ -130,6 +147,8 @@ void WiFiPassthrough_Run(UART_HandleTypeDef *console_uart, uint32_t next_test_tick = 0U; bool connection_closed = false; + /* Initial connection failures are retried forever because this function is + * the application's long-running bridge task. */ while (WiFiPassthrough_Connect() != HAL_OK) { printf("ESP8266: Connection failed; resetting and retrying\r\n"); ESP8266_Reset(); @@ -139,10 +158,13 @@ void WiFiPassthrough_Run(UART_HandleTypeDef *console_uart, next_test_tick = HAL_GetTick(); for (;;) { + /* A UART transmit failure is treated as loss of the ESP8266 data path. + * This is the first path that can set connection_closed. */ if (WiFiPassthrough_ForwardConsole(console_rx_buffer) != HAL_OK) { connection_closed = true; } - + /* A "CLOSED" notification received from the ESP8266 is the second + * path that can set connection_closed. */ if (WiFiPassthrough_ForwardNetwork(console_uart)) { connection_closed = true; }