1.) I want to make a freertos task to monitor incoming serial input, preferably the task should only run when a user is starting to enter input into the serial monitor, how can i realise this, for now i just added a vtaskdelay to keep checking for input, is there a more direct or better approach?
2.) I have a second task that requests some user input through that initial freertos serial monitor task, then the serial monitor task needs to forward the input to the User_Cmd1 task, there will be multiple tasks that will request this type of info from the serial terminal monitoring task. Is my approach(Messagebuffer) and execution(use of) correct and desirable as is?
3.) How do i detect wether the user pressed the backspace button? right now the backspace is counted as a char input, wich is not desirable.
4.) What is the correct way to call forth a task to execute only once when called upon? fe see the User_Cmd1 task.
- By including and enabling a bool to indicate the task may run else vtaskdelay it untill the bool is true, after execution set it back to false?
- Or by deleting the task and recalling xTaskCreatePinnedToCore for the task and delete it again after it ran?
- or by a different method?
5.) After we recieved our user input in the User_Cmd1 task, I delete the buffer but the handle to the buffer is not set to NULL so i manually set it to NULL but after that the rest of the function does not execute, i assume that is because i call vTaskDelete before any other message is printed, i guess vTaskDelete removes the entire task without first completing it, vTaskDelete is also not setting my handle to 0 so that i'm not able to restart the task for another go(in the app_main infinite loop), how can i delete a task and set its handle to NULL to indicate the task is not running and i can check for that in my code to see wether or not i should start that task again?
The code:
Code: Select all
#include "Arduino.h"
#include "HardwareSerial.h"
#include "esp32-hal.h"
#include "esp_log.h"
#include "freertos/idf_additions.h"
#include "freertos/projdefs.h"
#include "nvs_flash.h"
#include "portmacro.h"
#include "freertos/message_buffer.h"
#include <cstddef>
#include <cstring>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#define Max_Msg_Len 256
static const char tag[] = "Testertje";
MessageBufferHandle_t xMsg1Buffer;
MessageBufferHandle_t xMsg2Buffer;
static TaskHandle_t hUser_Cmd1 = NULL;
extern "C"
{
void app_main(void);
}
static void User_Cmd1(void *arg)
{
/* What is the correct way to call forth a task to execute only once when called upon?
By including and enabling a bool to indicate the task may run else vtaskdelay it untill the bool is true, after execution set it back to false
Or by deleting the task and recalling xTaskCreatePinnedToCore for the task and delete it again after it ran?
*/
char *Msg = (char*)calloc(1, sizeof(char)*Max_Msg_Len);
uint16_t rx_Length = 0;
ESP_LOGI(tag, "User_Cmd1 task succesfully created");
printf("\t\tGetting ready to write some stuff.. ");
xMsg1Buffer = xMessageBufferCreate(Max_Msg_Len);
if( xMsg1Buffer == NULL )
{
ESP_LOGE(tag, "There was not enough heap memory space available to create the message buffer. (user_cmd1)");
} else {
ESP_LOGI(tag, "Successfully created our MSG Buffer");
rx_Length = xMessageBufferReceive(xMsg1Buffer,Msg, Max_Msg_Len, portMAX_DELAY);
if( rx_Length > 0 )
{
ESP_LOGI(tag, "User_Cmd1 successfully recieved a message from the buffer, we recieved %i bytes\n ", rx_Length);
printf("\tThe recieved message:\n\t");
printf("%s\n", Msg);
} else ESP_LOGE(tag, "Did not recieve any bytes from our message buffer!");
vMessageBufferDelete(xMsg1Buffer);
ESP_LOGI(tag, "deleted the messagebuffer");
if(xMsg1Buffer == NULL) ESP_LOGI(tag, "Successfully deleted our message buffer");
else {
ESP_LOGE(tag, "Deleted MessageBuffer but handle is not NULL..");
xMsg1Buffer = NULL;
ESP_LOGI(tag, "Buffer handle is now: %p", xMsg1Buffer);
}
}
free(Msg);
vTaskDelete(hUser_Cmd1);
hUser_Cmd1 = NULL;
ESP_LOGI(tag, "Task should be deleted");
ESP_LOGI(tag, "handle is set to %s (%p)", hUser_Cmd1==NULL?"NULL":"Not NULL", hUser_Cmd1);
}
static void Monitor_serial(void *arg)
{
ESP_LOGI(tag, "Monitor serial task succesfully created");
char Input;
static uint16_t Length = 0;
static uint16_t LengthSent = 0;
static char Cmd[Max_Msg_Len];
//bool Quit = false;
// Whats the proper way to ignore this task and only come here as soon as something is being entered in the serial terminal? So that this task runs on the best efficiency?
while(true) {
if(Serial.available())
{
Input = Serial.read();
/*
How do i detect when the user used the backspace to delete a char? right now, when we press backspace this action is counted as a char input
*/
if(Input == '\n' || Input == '\r' || Length == Max_Msg_Len) // end of message
{
if(Input == '\n') ESP_LOGI(tag, "Cmd end was init by char: /n");
if(Input == '\r') ESP_LOGI(tag, "Cmd end was init by char: /r");
if(Input != '\n' && Input != '\r') ESP_LOGI(tag, "Cmd end was init by Full Buffer(255)");
Cmd[Length] = '\0';
printf("\n");
//Cmd[Length+1] = '\0';
ESP_LOGI(tag, "total length of the cmd: %i, Entered Command:\t%s", Length, Cmd);
if( strcmp(Cmd, "quit") == 0)
{
// Results in a reboot; console log: "abort() was called at PC 0x400877d3 on core 0"
// break; results in the task not responding anymore but does not continue after breaking out the while loop so the message: Leaving infite loop never shows up
ESP_LOGI(tag, "Entered quit, trying to break free out of the task..");
return;
}
// Check if we have a pending request for a message
if( xMsg1Buffer != NULL )
{
if( xMessageBufferIsEmpty(xMsg1Buffer) == pdFALSE )
{
// For some reason the buffer is not empty, lets clear it first
if( xMessageBufferReset(xMsg1Buffer) == pdFAIL )ESP_LOGE(tag, "Could not empty MessageBuffer (user_cmd1)");
}
if( xMessageBufferSpaceAvailable(xMsg1Buffer) < Length ) ESP_LOGE(tag, "Not enough space in Message Buffer to fit our message");
else {
LengthSent = xMessageBufferSend(xMsg1Buffer, &Cmd, Length, 0);
if(LengthSent != Length) ESP_LOGE(tag, "Did not send the full message for some reason, msg length: %i, length sent: %i", Length, LengthSent);
else ESP_LOGI(tag, "Successfully sent the complete Cmd to User_Cmd1 task, Msg Length: %i", Length);
}
} else if( xMsg2Buffer != NULL) {}
Length = 0;
LengthSent = 0;
Cmd[Length] = '\0';
} else { // fill buffer, msg ongoing, add null terminator for string print
printf("%c", Input);
Cmd[Length] = Input;
Length++;
}
//vTaskDelay(50/portTICK_PERIOD_MS);
} else vTaskDelay(500 / portTICK_PERIOD_MS);
}
printf("Leaving infite loop for created task Monitor_serial, deleting..");
vTaskDelete(NULL);
}
void app_main(void)
{
esp_err_t err = nvs_flash_init();
if(err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
{
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
if(err != ESP_OK)
{
ESP_LOGD(tag, "Error (%s) while initializing memory, can not proceed", esp_err_to_name(err));
}
err = esp_timer_early_init();
if(err != ESP_OK) ESP_LOGE(tag, "Could not early initiate timer.h library (%i).", err);
initArduino();
Serial.begin(115200);
BaseType_t result = pdFAIL;
result = xTaskCreatePinnedToCore(Monitor_serial, "Comm-Check", 4096, NULL, 10, NULL, tskNO_AFFINITY);
if(result != pdPASS) ESP_LOGE(tag, "Failed to create the serial monitor task");
result = xTaskCreatePinnedToCore(User_Cmd1, "usrinput1", 4096, NULL, 10, &hUser_Cmd1, tskNO_AFFINITY);
if(result != pdPASS) ESP_LOGE(tag, "Failed to create the sUser_Cmd1 task");
printf("Hello from app_main!\nEnter something:");
while (true) {
if( hUser_Cmd1 == NULL )
{
ESP_LOGI(tag, "User_Cmd1 task finished, recalling in 2 seconds..");
vTaskDelay(2000/portTICK_PERIOD_MS);
result = xTaskCreatePinnedToCore(User_Cmd1, "User input menu1", 4096, NULL, 10, &hUser_Cmd1, tskNO_AFFINITY);
if(result != pdPASS) ESP_LOGE(tag, "Failed to create the sUser_Cmd1 task");
}
vTaskDelay(2000/portTICK_PERIOD_MS);
}
}
Code: Select all
//console output:
I (276) heap_init: Initializing. RAM available for dynamic allocation:
I (283) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (289) heap_init: At 3FFB3310 len 0002CCF0 (179 KiB): DRAM
I (295) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (301) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (308) heap_init: At 4008EB24 len 000114DC (69 KiB): IRAM
I (316) spi_flash: detected chip: generic
I (319) spi_flash: flash io: dio
W (323) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (337) main_task: Started on CPU0
I (340) main_task: Calling app_main()
W (354) �ysI (357) Testertje: Monitor serial task succesfully created
I (358) Testertje: User_Cmd1 task succesfully created
Getting ready to write some stuff.. I (358) Testertje: Successfully created our MSG Buffer
Hello from app_main!
Enter something:qsdI (49858) Testertje: Cmd end was init by char: /r
I (49858) Testertje: total length of the cmd: 3, Entered Command: qsd
I (49861) Testertje: Successfully sent the complete Cmd to User_Cmd1 task, Msg Length: 3
I (49861) Testertje: User_Cmd1 successfully recieved a message from the buffer, we recieved 3 bytes
The recieved message:
qsd
I (49882) Testertje: deleted the messagebuffer
E (49887) Testertje: Deleted MessageBuffer but handle is not NULL..
I (3894) Testertje: Buffer handle is now: 0x0
brokeI (60870) Testertje: Cmd end was init by char: /r
I (60870) Testertje: total length of the cmd: 5, Entered Command: broke
10 backspacesI (82372) Testertje: Cmd end was init by char: /r
I (82372) Testertje: total length of the cmd: 24, Entered Com10 backspaces
5backspacesI (121877) Testertje: Cmd end was init by char: /r
I (121877) Testertje: total length of the cmd: 16, Entered Command:5backspaces
10backspacesI (138381) Testertje: Cmd end was init by char: /r
I (138381) Testertje: total length of the cmd: 22, Entered Com10backspaces
10 BackspacesI (155886) Testertje: Cmd end was init by char: /r
I (155886) Testertje: total length of the cmd: 23, Entered Com10 Backspaces
What is happening here??!I (175891) Testertje: Cmd end was init by char: /r
I (175891) Testertje: total length of the cmd: 25, Entered Command: What is happening here??!
// entering 256 backspaces..
I (220896) Testertje: Cmd end was init by Full Buffer(255)
I (220902) Testertje: total length of the cmd: 256, Entered Command: