The FreeRTOS coding style follows a naming convention to indicate the return type. You can read more about this here. You can also inspect the code freely on Github to verify any functions you like - for example pvPortMalloc. In this case the pv prefix signifies a void pointer is returned.
For memcpy I suggest online documentation for the standard library functions, for example this site.
A pointer to void is a special “code” in C that it is a pointer that might point to anything, which could be a string. C will freely convert any other type of pointer to object to a pointer to void, or a pointer to void to any other type of pointer to object.
So idx and the pointer schould be global variables ??
or schould the code be like this ?
// make room on the heap for the message
void * ptr = pvPortMalloc(idx * sizeof(char));
// Place the message on the heap
memcpy(ptr, buff, idx);
// set the flag
messageFlag = true;
idx = 0 ;
memset(buff, 0, 20);
It is not required to ptr to be global or something special. But it should be able to be passed to next code which will use a string from a heap and, finally, will free a heap when data are processed or are transferred.
For example, you may pass ptr as an argument for a function which will use the data you’ve placed in a heap. Or you may make ptr global to use it as is. Also for next string processing, you may cast ptr to a string of chars (char*)ptr to be precise and to ensure your data are handled as a string.
Most important part here: don’t forget to free() the space you got from a heap. Else way a memory leak will occur.
The problem with the code you shared previously is that you set idx to zero and use it to calculate the number of bytes (idx * sizeof(char)) that need to be allocated via pvPortMalloc, which is zero.
Calling pvPortMalloc, to allocate zero bytes results in implementation-defined behavior; it can either return NULL or undefined behavior depending upon the implementation.
// my solution to lesson 4
// Learned so far
// - writing task
// - task scheduling
// - memory managament
// Challenge
// Write 2 tasks.
// task 1 : get input from serial monitor
// after getting a enter , put it into heap memory
// signal to task2 that there is something on the heap
// task2 : read input from the heap if the task 1 signal that there is a message
// display it on the serial monitor
// free the memory
#if CONFIG_FREERTOS_UNICORE
static const BaseType_t app_cpu = 0 ;
#else
static const BaseType_t app_cpu = 1;
#endif
// Pins
static const int led_pin = 2;
bool messageFlag = false;
char * message_ptr;
// Our task is to read in a message
void readMessageFromMonitor(void * parameter) {
char ch;
char buff[40];
int idx = 0;
memset(buff, 0, 20);
while (1) {
if (Serial.available() > 0) {
ch = Serial.read();
if (ch == '\n') {
// clear buffer
// make room on the heap for the message
message_ptr = (char *) pvPortMalloc(idx * sizeof(char));
// Place the message on the heap
memcpy(message_ptr, buff, idx);
// set the flag
messageFlag = true;
idx = 0 ;
memset(buff, 0, 20);
} else {
if (idx < 39) {
buff[idx] = ch;
idx++;
}
}
}
}
}
void setup() {
pinMode(led_pin, OUTPUT);
Serial.begin(9600);
Serial.println("RW");
// Task to run forever
xTaskCreatePinnedToCore(
readMessageFromMonitor, // Function to be called
"Read Message", // name of the function
1024, // stack size
NULL, // parameter to pass to the function
1, // priority
NULL, // task handle
app_cpu
);
}
void loop() {
}
The size of buff is 40 but the parameter to memset call is 20.
You want to add a check when \n is the first character (and therefore, idx is zero):
if ( (ch == '\n') && ( idx != 0 ) ) {
As others have pointed out, you are not freeing the memory you are allocating. You are probably yet to implement the second task described in comments:
// task2 : read input from the heap if the task 1 signal that there is a message
// display it on the serial monitor
// free the memory
// my solution to lesson 4
// Learned so far
// - writing task
// - task scheduling
// - memory managament
// Challenge
// Write 2 tasks.
// task 1 : get input from serial monitor
// after getting a enter , put it into heap memory
// signal to task2 that there is something on the heap
// task2 : read input from the heap if the task 1 signal that there is a message
// display it on the serial monitor
// free the memory
#if CONFIG_FREERTOS_UNICORE
static const BaseType_t app_cpu = 0 ;
#else
static const BaseType_t app_cpu = 1;
#endif
// Pins
static const int led_pin = 2;
bool messageFlag = false;
char * message_ptr;
// Our task is to read in a message
void readMessageFromMonitor(void * parameter) {
char ch;
char buff[40];
int idx = 0;
memset(buff, 0, 20);
while (1) {
if (Serial.available() > 0) {
ch = Serial.read();
if (ch == '\n') {
if(idx != 0 )
{ // clear buffer
// make room on the heap for the message
message_ptr = (char *) pvPortMalloc(idx * sizeof(char));
// Place the message on the heap
memcpy(message_ptr, buff, idx);
// set the flag
messageFlag = true;
idx = 0 ;
memset(buff, 0, 20);
}
else
{
/* Ignore the empty buffer. */
}
} else {
if (idx < 39) {
buff[idx] = ch;
idx++;
}
}
}
}
}
void displayMessage() {
if (messageFlag) {
Serial.print("Task2 reads :")
Serial.println(message_ptr);
vPortFree(message_ptr);
messageFlag = false ;
}
}
void setup() {
pinMode(led_pin, OUTPUT);
Serial.begin(9600);
Serial.println("RW");
// Task to run forever
xTaskCreatePinnedToCore(
readMessageFromMonitor, // Function to be called
"Read Message", // name of the function
1024, // stack size
NULL, // parameter to pass to the function
1, // priority
NULL, // task handle
app_cpu
);
xTaskCreatePinnedToCore(
displayMessage, // Function to be called
"Display Message", // name of the function
1024, // stack size
NULL, // parameter to pass to the function
1, // priority
NULL, // task handle
app_cpu
);
}
void loop() {
}
I cannot test it because I use wokike and that is one the whole day very very busy
RW
Task2 reads :Dit is een testxVº?
E (1678) FreeRTOS: FreeRTOS Task "Display Message" should not return, Aborting now!
Guru Me
tbortn Errorcalled a0 PC 0x400 (c6f on core 1nel
exception).
0x40
22fc:0x3fe: 440 0891088219f0x6ffb 46-CORR0PTEc
:0x3ffb
B80 tra0e: 06f00x32f99503
`` `
can anyone help me figure out why ?
One further observation - Task readMessageFromMonitor does not yield properly. This will result in task displayMessage never executing. The simplest (but not optimal) way to switch switch between the tasks would be to add a simple taskYIELD call to both tasks. This would look like the following:
// Our task is to read in a message
void readMessageFromMonitor(void * parameter) {
char ch;
char buff[40];
int idx = 0;
memset(buff, 0, 20);
while (1) {
if (Serial.available() > 0) {
ch = Serial.read();
if (ch == '\n') {
if(idx != 0 )
{ // clear buffer
buff[idx] = '\0';
// make room on the heap for the message
message_ptr = (char *) pvPortMalloc(idx * sizeof(char));
// Place the message on the heap
memcpy(message_ptr, buff, idx);
// set the flag
messageFlag = true;
idx = 0 ;
memset(buff, 0, 20);
taskYIELD(); // Yield so that the message can be displayed by the other task
}
else
{
/* Ignore the empty buffer. */
}
} else {
if (idx < 39) {
buff[idx] = ch;
idx++;
}
}
}
}
}
void displayMessage(void * parameter) {
while(1) {
if (messageFlag) {
Serial.print("Task2 reads :");
Serial.println(message_ptr);
vPortFree(message_ptr);
messageFlag = false ;
taskYIELD(); //Yield now that the message has been displayed
}}
}