Использование RTOS SDK - сбой при добавлении другой задачи
(Я надеюсь, что это правильное место, чтобы задать вопросы о ESP8266_RTOS_SDK)
У меня есть программа, которую я взял из каталога samples (protocols/tcp_client) в RTOS SDK и добавил код из образца uart только для того, чтобы я мог использовать клавиатуру, чтобы сказать клиенту, когда начать. Задача tcp_client просто отправляет сокет на & recv с сервера (простой сервер сокетов, работающий на рабочем столе linux). Он отлично работает, пока я не попытался добавить еще один пример задачи:
static void test_task(void *pvParameters)
{
vTaskDelay(MYDELAY2);
ESP_LOGI(TAG, "asdf 123");
}
А затем в app_main () я создаю задачу:
xTaskCreate(test_task, "test", 2048, NULL, 10, NULL);
Я пытаюсь запустить его, и он либо блокируется, а затем выходит из строя, либо просто выходит из строя, как только подключается к серверу. Обычно он выходит из строя сразу после того, как распечатает сообщение в test_task.
#include <string.h>
#include <sys/param.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "protocol_examples_common.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>
#include "freertos/queue.h"
#include "driver/uart.h"
#define HOST_IP_ADDR CONFIG_EXAMPLE_IPV4_ADDR
#define MYDELAY1 (75 / portTICK_PERIOD_MS)
#define MYDELAY2 (125 / portTICK_PERIOD_MS)
#define MYDELAY3 (250 / portTICK_PERIOD_MS)
#define MYDELAY4 (500 / portTICK_PERIOD_MS)
#define MYDELAY5 (1000 / portTICK_PERIOD_MS)
#define MYDELAY6 (2000 / portTICK_PERIOD_MS)
#define MYDELAY7 (5000 / portTICK_PERIOD_MS)
#define PORT CONFIG_EXAMPLE_PORT
static const char *TAG = "example";
#define EX_UART_NUM UART_NUM_0
#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)
static QueueHandle_t uart0_queue;
unsigned char state;
int sock;
static void test_task(void *pvParameters)
{
vTaskDelay(MYDELAY2);
ESP_LOGI(TAG, "asdf 123");
}
static void tcp_client_task(void *pvParameters)
{
char rx_buffer[128];
char send_buff[100];
char addr_str[128];
int addr_family;
int ip_protocol;
int i = 0;
char xbyte = 0x21;
int len, err;
struct sockaddr_in destAddr;
// destAddr.sin_addr.s_addr = inet_addr(HOST_IP_ADDR);
// can set ip address either explicitly or using 'make menuconfig' and go to 'example configuration'
destAddr.sin_addr.s_addr = inet_addr("192.168.88.103");
inet_ntoa_r(((struct sockaddr_in *)&destAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
ESP_LOGI(TAG, "address : %s", addr_str);
destAddr.sin_family = AF_INET;
destAddr.sin_port = htons(PORT);
addr_family = AF_INET;
ip_protocol = IPPROTO_IP;
inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1);
sock = socket(addr_family, SOCK_STREAM, ip_protocol);
if (sock < 0)
{
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
state = 51;
}
ESP_LOGI(TAG, "Socket created %d",sock);
memset(send_buff,0,sizeof(send_buff));
for(i = 0;i < 99;i++)
{
send_buff[i] = xbyte;
if(++xbyte > 0x7e)
xbyte = 0x21;
}
send_buff[99] = 0;
ESP_LOGI(TAG,"press '1' to connect, then press '2' to start client, '3' to shutdown");
while (1)
{
switch(state)
{
case 0:
vTaskDelay(MYDELAY3);
break;
case 49:
err = connect(sock, (struct sockaddr *)&destAddr, sizeof(destAddr));
if (err != 0)
{
ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
close(sock);
vTaskDelay(MYDELAY1);
state = 0;
}
ESP_LOGI(TAG, "Successfully connected %d",err);
state = 0;
break;
case 50:
//ESP_LOGI(TAG, "starting...");
err = send(sock, send_buff, 80, 0);
if (err < 0)
{
ESP_LOGE(TAG, "Error occured during sending: errno %d", errno);
state = 0;
break;
}
//ESP_LOGI(TAG,"send returned: %d",err);
vTaskDelay(MYDELAY1);
len = recv(sock, rx_buffer, 80, 0);
// Error occured during receiving
if (len < 0)
{
ESP_LOGE(TAG, "recv failed: errno %d", errno);
state = 0;
break;
}
else
{
rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
//ESP_LOGI(TAG, "Received %d bytes from %s:", len, addr_str);
ESP_LOGI(TAG, "%s", rx_buffer);
}
vTaskDelay(MYDELAY1);
if (sock == -1)
{
ESP_LOGE(TAG, "Shutting down socket, press '1' to restart...");
shutdown(sock, 0);
close(sock);
state = 0;
}
break;
case 51:
ESP_ERROR_CHECK(example_disconnect());
break;
case 52:
shutdown(sock,0);
close(sock);
ESP_LOGI(TAG,"shutdown - deleting task");
vTaskDelete(NULL);
break;
default:
ESP_LOGI(TAG,"press '1' to connect, then press '2' to start client %d",state);
vTaskDelay(MYDELAY3);
state = 0;
break;
}
}
}
//#if 0
static void uart_event_task(void *pvParameters)
{
uart_event_t event;
int i;
uint8_t *dtmp = (uint8_t *) malloc(RD_BUF_SIZE);
for (;;) {
// Waiting for UART event.
if (xQueueReceive(uart0_queue, (void *)&event, (portTickType)portMAX_DELAY)) {
bzero(dtmp, RD_BUF_SIZE);
//ESP_LOGI(TAG, "uart[%d] event:", EX_UART_NUM);
switch (event.type) {
// Event of UART receving data
// We'd better handler data event fast, there would be much more data events than
// other types of events. If we take too much time on data event, the queue might be full.
case UART_DATA:
ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY);
state = dtmp[0];
ESP_LOGI(TAG,"state: %d",state);
// uart_write_bytes(EX_UART_NUM, (const char *) dtmp, event.size);
break;
// Event of HW FIFO overflow detected
case UART_FIFO_OVF:
ESP_LOGI(TAG, "hw fifo overflow");
// If fifo overflow happened, you should consider adding flow control for your application.
// The ISR has already reset the rx FIFO,
// As an example, we directly flush the rx buffer here in order to read more data.
uart_flush_input(EX_UART_NUM);
xQueueReset(uart0_queue);
break;
// Event of UART ring buffer full
case UART_BUFFER_FULL:
ESP_LOGI(TAG, "ring buffer full");
// If buffer full happened, you should consider encreasing your buffer size
// As an example, we directly flush the rx buffer here in order to read more data.
uart_flush_input(EX_UART_NUM);
xQueueReset(uart0_queue);
break;
case UART_PARITY_ERR:
ESP_LOGI(TAG, "uart parity error");
break;
// Event of UART frame error
case UART_FRAME_ERR:
ESP_LOGI(TAG, "uart frame error");
break;
// Others
default:
ESP_LOGI(TAG, "uart event type: %d", event.type);
break;
}
}
}
free(dtmp);
dtmp = NULL;
vTaskDelete(NULL);
}
//#endif
void app_main()
{
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
ESP_ERROR_CHECK(example_connect());
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(EX_UART_NUM, &uart_config);
// Install UART driver, and get the queue.
uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 100, &uart0_queue, 0);
xTaskCreate(test_task, "test", 2048, NULL, 10, NULL);
xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, 12, NULL);
xTaskCreate(tcp_client_task, "tcp_client", 2048, NULL, 5, NULL);
}
Когда я добавил задачу для uart, она работает, но когда я добавляю задачу для печати тестового сообщения и делаю временную задержку, она выходит из строя.
@SpaceCowboy, 👍1
1 ответ
У меня не было задачи в виде бесконечного цикла. Это должно быть:
static void test_task(void *pvParameters)
{
while(1)
{
vTaskDelay(MYDELAY6);
ESP_LOGI(TAG, "test 123");
}
}