fix: stop network tasks cleanly on restart
This commit is contained in:
@@ -28,6 +28,14 @@ extern volatile int32_t g_netif_set_up_err;
|
|||||||
extern volatile int32_t g_netif_init_ok;
|
extern volatile int32_t g_netif_init_ok;
|
||||||
|
|
||||||
void app_start_network_tasks(void);
|
void app_start_network_tasks(void);
|
||||||
|
void app_request_network_task_stop(void);
|
||||||
|
void app_clear_network_task_stop(void);
|
||||||
|
BaseType_t app_network_task_stop_requested(void);
|
||||||
|
BaseType_t app_network_tasks_are_stopped(void);
|
||||||
|
void app_on_network_task_exit(TaskHandle_t task_handle);
|
||||||
|
void app_request_network_restart(void);
|
||||||
|
void app_clear_network_restart_request(void);
|
||||||
|
BaseType_t app_network_restart_requested(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
+71
-7
@@ -14,7 +14,31 @@
|
|||||||
#include "ethernetif.h"
|
#include "ethernetif.h"
|
||||||
#include "route_msg.h"
|
#include "route_msg.h"
|
||||||
|
|
||||||
#define TCP_CLIENT_CONNECT_TIMEOUT_MS 5000
|
#define TCP_CLIENT_CONNECT_TIMEOUT_MS 500
|
||||||
|
#define TCP_CLIENT_STOP_POLL_MS 50u
|
||||||
|
|
||||||
|
static BaseType_t tcp_client_stop_requested(void)
|
||||||
|
{
|
||||||
|
return (app_network_task_stop_requested() != pdFALSE) ? pdTRUE : pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BaseType_t tcp_client_delay_with_stop(uint32_t delay_ms)
|
||||||
|
{
|
||||||
|
uint32_t remaining_ms = delay_ms;
|
||||||
|
|
||||||
|
while (remaining_ms > 0u) {
|
||||||
|
uint32_t slice_ms = (remaining_ms > TCP_CLIENT_STOP_POLL_MS) ? TCP_CLIENT_STOP_POLL_MS : remaining_ms;
|
||||||
|
|
||||||
|
if (tcp_client_stop_requested() != pdFALSE) {
|
||||||
|
return pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(slice_ms));
|
||||||
|
remaining_ms -= slice_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (tcp_client_stop_requested() == pdFALSE) ? pdTRUE : pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void tcp_client_abort_and_delete(struct netconn *conn, uint8_t link_index)
|
static void tcp_client_abort_and_delete(struct netconn *conn, uint8_t link_index)
|
||||||
{
|
{
|
||||||
@@ -53,6 +77,10 @@ static err_t tcp_client_worker(struct netconn *conn, uint8_t link_index)
|
|||||||
netconn_set_recvtimeout(conn, 10);
|
netconn_set_recvtimeout(conn, 10);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
if (tcp_client_stop_requested() != pdFALSE) {
|
||||||
|
return ERR_CLSD;
|
||||||
|
}
|
||||||
|
|
||||||
err = netconn_recv(conn, &buf);
|
err = netconn_recv(conn, &buf);
|
||||||
if (err == ERR_OK) {
|
if (err == ERR_OK) {
|
||||||
do {
|
do {
|
||||||
@@ -76,11 +104,19 @@ static err_t tcp_client_worker(struct netconn *conn, uint8_t link_index)
|
|||||||
}
|
}
|
||||||
} while (netbuf_next(buf) >= 0);
|
} while (netbuf_next(buf) >= 0);
|
||||||
netbuf_delete(buf);
|
netbuf_delete(buf);
|
||||||
} else if (err != ERR_TIMEOUT) {
|
} else if (err == ERR_TIMEOUT) {
|
||||||
|
if (tcp_client_stop_requested() != pdFALSE) {
|
||||||
|
return ERR_CLSD;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (xQueueReceive(xLinkTxQueues[link_index], &tx_msg, 0) == pdPASS) {
|
while (xQueueReceive(xLinkTxQueues[link_index], &tx_msg, 0) == pdPASS) {
|
||||||
|
if (tcp_client_stop_requested() != pdFALSE) {
|
||||||
|
route_msg_free(tx_msg);
|
||||||
|
return ERR_CLSD;
|
||||||
|
}
|
||||||
err = netconn_write(conn, tx_msg->data, tx_msg->len, NETCONN_COPY);
|
err = netconn_write(conn, tx_msg->data, tx_msg->len, NETCONN_COPY);
|
||||||
route_msg_free(tx_msg);
|
route_msg_free(tx_msg);
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
@@ -104,13 +140,25 @@ static void tcp_client_task(uint8_t link_index)
|
|||||||
first_connect_deferred = (link_index == CONFIG_LINK_C1) ? 1u : 0u;
|
first_connect_deferred = (link_index == CONFIG_LINK_C1) ? 1u : 0u;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
if (tcp_client_stop_requested() != pdFALSE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
while ((g_netif_ready == pdFALSE) || (ethernetif_link_is_up() == 0u)) {
|
while ((g_netif_ready == pdFALSE) || (ethernetif_link_is_up() == 0u)) {
|
||||||
|
if (tcp_client_stop_requested() != pdFALSE) {
|
||||||
|
goto exit_task;
|
||||||
|
}
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg = config_get();
|
cfg = config_get();
|
||||||
if (cfg->links[link_index].enabled == 0u) {
|
if (cfg->links[link_index].enabled == 0u) {
|
||||||
vTaskDelay(pdMS_TO_TICKS(500));
|
if (tcp_client_stop_requested() != pdFALSE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (tcp_client_delay_with_stop(500u) == pdFALSE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,13 +167,17 @@ static void tcp_client_task(uint8_t link_index)
|
|||||||
if (first_connect_deferred != 0u) {
|
if (first_connect_deferred != 0u) {
|
||||||
first_connect_deferred = 0u;
|
first_connect_deferred = 0u;
|
||||||
debug_log_write("[CLI] C1 first-connect defer\r\n");
|
debug_log_write("[CLI] C1 first-connect defer\r\n");
|
||||||
vTaskDelay(pdMS_TO_TICKS(delay_ms));
|
if (tcp_client_delay_with_stop(delay_ms) == pdFALSE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn = netconn_new(NETCONN_TCP);
|
conn = netconn_new(NETCONN_TCP);
|
||||||
if (conn == NULL) {
|
if (conn == NULL) {
|
||||||
vTaskDelay(pdMS_TO_TICKS(delay_ms));
|
if (tcp_client_delay_with_stop(delay_ms) == pdFALSE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +189,9 @@ static void tcp_client_task(uint8_t link_index)
|
|||||||
(int)err,
|
(int)err,
|
||||||
(unsigned int)cfg->links[link_index].local_port);
|
(unsigned int)cfg->links[link_index].local_port);
|
||||||
netconn_delete(conn);
|
netconn_delete(conn);
|
||||||
vTaskDelay(pdMS_TO_TICKS(delay_ms));
|
if (tcp_client_delay_with_stop(delay_ms) == pdFALSE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,8 +230,18 @@ static void tcp_client_task(uint8_t link_index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tcp_client_abort_and_delete(conn, link_index);
|
tcp_client_abort_and_delete(conn, link_index);
|
||||||
vTaskDelay(pdMS_TO_TICKS(delay_ms));
|
if (tcp_client_stop_requested() != pdFALSE) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if (tcp_client_delay_with_stop(delay_ms) == pdFALSE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_task:
|
||||||
|
netconn_thread_cleanup();
|
||||||
|
app_on_network_task_exit(xTaskGetCurrentTaskHandle());
|
||||||
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TcpCliTask_C1(void *argument)
|
void TcpCliTask_C1(void *argument)
|
||||||
|
|||||||
+66
-5
@@ -11,6 +11,32 @@
|
|||||||
#include "debug_log.h"
|
#include "debug_log.h"
|
||||||
#include "route_msg.h"
|
#include "route_msg.h"
|
||||||
|
|
||||||
|
#define TCP_SERVER_ACCEPT_TIMEOUT_MS 100
|
||||||
|
#define TCP_SERVER_STOP_POLL_MS 50u
|
||||||
|
|
||||||
|
static BaseType_t tcp_server_stop_requested(void)
|
||||||
|
{
|
||||||
|
return (app_network_task_stop_requested() != pdFALSE) ? pdTRUE : pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BaseType_t tcp_server_delay_with_stop(uint32_t delay_ms)
|
||||||
|
{
|
||||||
|
uint32_t remaining_ms = delay_ms;
|
||||||
|
|
||||||
|
while (remaining_ms > 0u) {
|
||||||
|
uint32_t slice_ms = (remaining_ms > TCP_SERVER_STOP_POLL_MS) ? TCP_SERVER_STOP_POLL_MS : remaining_ms;
|
||||||
|
|
||||||
|
if (tcp_server_stop_requested() != pdFALSE) {
|
||||||
|
return pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(slice_ms));
|
||||||
|
remaining_ms -= slice_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (tcp_server_stop_requested() == pdFALSE) ? pdTRUE : pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static err_t tcp_server_worker(struct netconn *conn, uint8_t link_index)
|
static err_t tcp_server_worker(struct netconn *conn, uint8_t link_index)
|
||||||
{
|
{
|
||||||
struct netbuf *buf;
|
struct netbuf *buf;
|
||||||
@@ -24,6 +50,10 @@ static err_t tcp_server_worker(struct netconn *conn, uint8_t link_index)
|
|||||||
netconn_set_recvtimeout(conn, 10);
|
netconn_set_recvtimeout(conn, 10);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
if (tcp_server_stop_requested() != pdFALSE) {
|
||||||
|
return ERR_CLSD;
|
||||||
|
}
|
||||||
|
|
||||||
err = netconn_recv(conn, &buf);
|
err = netconn_recv(conn, &buf);
|
||||||
if (err == ERR_OK) {
|
if (err == ERR_OK) {
|
||||||
do {
|
do {
|
||||||
@@ -47,11 +77,19 @@ static err_t tcp_server_worker(struct netconn *conn, uint8_t link_index)
|
|||||||
}
|
}
|
||||||
} while (netbuf_next(buf) >= 0);
|
} while (netbuf_next(buf) >= 0);
|
||||||
netbuf_delete(buf);
|
netbuf_delete(buf);
|
||||||
} else if (err != ERR_TIMEOUT) {
|
} else if (err == ERR_TIMEOUT) {
|
||||||
|
if (tcp_server_stop_requested() != pdFALSE) {
|
||||||
|
return ERR_CLSD;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (xQueueReceive(xLinkTxQueues[link_index], &tx_msg, 0) == pdPASS) {
|
while (xQueueReceive(xLinkTxQueues[link_index], &tx_msg, 0) == pdPASS) {
|
||||||
|
if (tcp_server_stop_requested() != pdFALSE) {
|
||||||
|
route_msg_free(tx_msg);
|
||||||
|
return ERR_CLSD;
|
||||||
|
}
|
||||||
err = netconn_write(conn, tx_msg->data, tx_msg->len, NETCONN_COPY);
|
err = netconn_write(conn, tx_msg->data, tx_msg->len, NETCONN_COPY);
|
||||||
route_msg_free(tx_msg);
|
route_msg_free(tx_msg);
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
@@ -72,31 +110,49 @@ static void tcp_server_task(uint8_t link_index)
|
|||||||
netconn_thread_init();
|
netconn_thread_init();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
if (tcp_server_stop_requested() != pdFALSE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
while (g_netif_ready == pdFALSE) {
|
while (g_netif_ready == pdFALSE) {
|
||||||
|
if (tcp_server_stop_requested() != pdFALSE) {
|
||||||
|
goto exit_task;
|
||||||
|
}
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg = config_get();
|
cfg = config_get();
|
||||||
if (cfg->links[link_index].enabled == 0u) {
|
if (cfg->links[link_index].enabled == 0u) {
|
||||||
vTaskDelay(pdMS_TO_TICKS(500));
|
if (tcp_server_stop_requested() != pdFALSE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (tcp_server_delay_with_stop(500u) == pdFALSE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
listener = netconn_new(NETCONN_TCP);
|
listener = netconn_new(NETCONN_TCP);
|
||||||
if (listener == NULL) {
|
if (listener == NULL) {
|
||||||
vTaskDelay(pdMS_TO_TICKS(500));
|
if (tcp_server_delay_with_stop(500u) == pdFALSE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
netconn_set_recvtimeout(listener, TCP_SERVER_ACCEPT_TIMEOUT_MS);
|
||||||
|
|
||||||
if (netconn_bind(listener, IP_ADDR_ANY, cfg->links[link_index].local_port) != ERR_OK ||
|
if (netconn_bind(listener, IP_ADDR_ANY, cfg->links[link_index].local_port) != ERR_OK ||
|
||||||
netconn_listen(listener) != ERR_OK) {
|
netconn_listen(listener) != ERR_OK) {
|
||||||
netconn_delete(listener);
|
netconn_delete(listener);
|
||||||
vTaskDelay(pdMS_TO_TICKS(500));
|
if (tcp_server_delay_with_stop(500u) == pdFALSE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (cfg->links[link_index].enabled == 0u) {
|
if (tcp_server_stop_requested() != pdFALSE || cfg->links[link_index].enabled == 0u) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (netconn_accept(listener, &newconn) == ERR_OK) {
|
if (netconn_accept(listener, &newconn) == ERR_OK) {
|
||||||
@@ -109,6 +165,11 @@ static void tcp_server_task(uint8_t link_index)
|
|||||||
netconn_close(listener);
|
netconn_close(listener);
|
||||||
netconn_delete(listener);
|
netconn_delete(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit_task:
|
||||||
|
netconn_thread_cleanup();
|
||||||
|
app_on_network_task_exit(xTaskGetCurrentTaskHandle());
|
||||||
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TcpSrvTask_S1(void *argument)
|
void TcpSrvTask_S1(void *argument)
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ static TaskHandle_t xTcpCliTaskC1Handle = NULL;
|
|||||||
static TaskHandle_t xTcpCliTaskC2Handle = NULL;
|
static TaskHandle_t xTcpCliTaskC2Handle = NULL;
|
||||||
static TaskHandle_t xDefaultTaskHandle = NULL;
|
static TaskHandle_t xDefaultTaskHandle = NULL;
|
||||||
static BaseType_t xNetworkTasksStarted = pdFALSE;
|
static BaseType_t xNetworkTasksStarted = pdFALSE;
|
||||||
|
static volatile BaseType_t xNetworkTaskStopRequested = pdFALSE;
|
||||||
|
static volatile BaseType_t xNetworkRestartRequested = pdFALSE;
|
||||||
|
|
||||||
void app_start_network_tasks(void)
|
void app_start_network_tasks(void)
|
||||||
{
|
{
|
||||||
@@ -49,6 +51,11 @@ void app_start_network_tasks(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (xNetworkTaskStopRequested != pdFALSE) {
|
||||||
|
debug_log_write("[NET] start-network-tasks stop-pending\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cfg = config_get();
|
cfg = config_get();
|
||||||
|
|
||||||
debug_log_printf("[NET] start-network-tasks enter free=%lu min=%lu\r\n",
|
debug_log_printf("[NET] start-network-tasks enter free=%lu min=%lu\r\n",
|
||||||
@@ -107,6 +114,68 @@ void app_start_network_tasks(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void app_request_network_task_stop(void)
|
||||||
|
{
|
||||||
|
xNetworkTaskStopRequested = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_clear_network_task_stop(void)
|
||||||
|
{
|
||||||
|
xNetworkTaskStopRequested = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseType_t app_network_task_stop_requested(void)
|
||||||
|
{
|
||||||
|
return xNetworkTaskStopRequested;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseType_t app_network_tasks_are_stopped(void)
|
||||||
|
{
|
||||||
|
return (xTcpSrvTaskS1Handle == NULL &&
|
||||||
|
xTcpSrvTaskS2Handle == NULL &&
|
||||||
|
xTcpCliTaskC1Handle == NULL &&
|
||||||
|
xTcpCliTaskC2Handle == NULL) ? pdTRUE : pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_on_network_task_exit(TaskHandle_t task_handle)
|
||||||
|
{
|
||||||
|
taskENTER_CRITICAL();
|
||||||
|
|
||||||
|
if (task_handle == xTcpSrvTaskS1Handle) {
|
||||||
|
xTcpSrvTaskS1Handle = NULL;
|
||||||
|
} else if (task_handle == xTcpSrvTaskS2Handle) {
|
||||||
|
xTcpSrvTaskS2Handle = NULL;
|
||||||
|
} else if (task_handle == xTcpCliTaskC1Handle) {
|
||||||
|
xTcpCliTaskC1Handle = NULL;
|
||||||
|
} else if (task_handle == xTcpCliTaskC2Handle) {
|
||||||
|
xTcpCliTaskC2Handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xTcpSrvTaskS1Handle == NULL &&
|
||||||
|
xTcpSrvTaskS2Handle == NULL &&
|
||||||
|
xTcpCliTaskC1Handle == NULL &&
|
||||||
|
xTcpCliTaskC2Handle == NULL) {
|
||||||
|
xNetworkTasksStarted = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_request_network_restart(void)
|
||||||
|
{
|
||||||
|
xNetworkRestartRequested = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_clear_network_restart_request(void)
|
||||||
|
{
|
||||||
|
xNetworkRestartRequested = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseType_t app_network_restart_requested(void)
|
||||||
|
{
|
||||||
|
return xNetworkRestartRequested;
|
||||||
|
}
|
||||||
|
|
||||||
static void StartDefaultTask(void *argument)
|
static void StartDefaultTask(void *argument)
|
||||||
{
|
{
|
||||||
BaseType_t iwdg_ready = pdFALSE;
|
BaseType_t iwdg_ready = pdFALSE;
|
||||||
|
|||||||
Reference in New Issue
Block a user