1

I want to create a task with push button and the task sends a string to a queue and creates another task (this can also be separate task with lower priority) which reads the queue and blink led if its variable is same with the string in the queue. Otherwise system should stay in the idle mode. Im quite new with freertos and Led doesnot blink with below codes eventhough there is no compilation error. I also want to replace the datatype from char to string if it is possible. (select and zyRxBuff come from different sources, it is written as below for simplicity)

#include "main.h"
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "queue.h"
    
void SystemClock_Config(void);
static void MX_GPIO_Init(void);

The handlers ;

QueueHandle_t myQueue = NULL;
TaskHandle_t QTASK1 = NULL;
TaskHandle_t QTASK2 = NULL;

Prototypes ;

void Qsender(void* p);
void Qreceiver(void* p);

Main block;

int main(void)
{

 HAL_Init();
 SystemClock_Config();
 MX_GPIO_Init();

if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_SET)
{
     xTaskCreate(Qsender, "SendingTask", 200, NULL, 1, &QTASK1);
     vTaskStartScheduler();
}
 while (1) {};
}

Sender Function;

void Qsender(void* p)
{
  char select[10]= "BlinkLed";
    myQueue = xQueueCreate(1, sizeof(select));
    xQueueSend(myQueue, (void*) &select, (TickType_t)10);

    if (myQueue != 0)
    {
        xTaskCreate(Qreceiver, "ReceivingTask", 200, NULL, 1, &QTASK2);
    }

}

Receiver Function;

void Qreceiver(void* p)
{
    char myRxBuff[10];
    char zyRxBuff[10]="BlinkLed";
    xQueueReceive(myQueue, &myRxBuff, (TickType_t)50);

    if ( myRxBuff == zyRxBuff)
    {
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
            HAL_Delay(500);
    }
}

Idle function;

void vApplicationIdleHook(void){__WFI();};
lsn
  • 33
  • 10
  • 1
    What are you using, `C` or `C++`. Edit post to keep only the tag you are using. And have you compiled and seen warnings or errors? If so, post them showing where in code they appeared. – ryyker Nov 06 '20 at 13:16

1 Answers1

0

Nothing is happening because the program is likely executing too quickly for things to work. When your program starts it initializes everything in a fraction of a second, and if the button is not pressed then nothing happens. Then your main loop does nothing. At a minimum, you should put the button watching in a task, and that task should have a while or for loop that doesn't end.

Create a more simple system first - like, two tasks, a button-reader, and a light-emitter. The button-reader task simply checks if the button is pressed and inserts an item into the queue. The light-emitter check if there is something in the queue.

It should also be noted, that all RTOS really don't like creating and ending tasks all the time. If you're going to do so, you should read up on how tasks are created and destroyed. (https://www.freertos.org/a00125.html) Letting a task go out of context doesn't automatically clean it up, you need to use vTaskDelete - With your current functions, you'll need to clean up the QReceiver with your QSender task, which is a violation of the SOLID principals. Additionally, your QReceiver will need to send a message back that it's done. If you can get them statically working first, it will be a lot easier to get them dynamically working later.

I also noticed that you're comparing strings by address and not by content. Qsender is sending BlinkLed

void Qsender(void* p){
    char select[10]= "BlinkLed";
    myQueue = xQueueCreate(1, sizeof(select));
    xQueueSend(myQueue, (void*) &select, (TickType_t)10);

    if (myQueue){
        xTaskCreate(Qreceiver, "ReceivingTask", 200, NULL, 1, &QTASK2);
    }
}

However in Qreceiver you're comparing the address of myRxBuff and zyRxBuff, when you should be doing a string-compare

void Qreceiver(void* p){
    char myRxBuff[10];
    char zyRxBuff[10]="BlinkLed";
    xQueueReceive(myQueue, &myRxBuff, (TickType_t)50);
    if ( myRxBuff == zyRxBuff){ // Offending Line
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
            HAL_Delay(500);
    }
}

void Qreceiver(void* p){
    char myRxBuff[10];
    char zyRxBuff[10]="BlinkLed";
    xQueueReceive(myQueue, &myRxBuff, (TickType_t)50);
    if ( strcmp(myRxBuff, zyRxBuff) == 0){ // Should compare content now
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
            HAL_Delay(500);
    }
}
Alex Shirley
  • 385
  • 4
  • 11
  • "Nothing is happening because the program is likely executing too quickly for things to work. When your program starts it initializes everything in a fraction of a second, and if the button is not pressed then nothing happens " normally this is what I want. Those two task should do their tasks and then system return to idle mode. Their execution time will change but they will not be in infinite loop. Maybe I can create a new task which control those two task as its subtasks in a while loop. – lsn Nov 07 '20 at 07:48
  • When I debug the current code, I saw that two task is created but it doesnot go in to the if statement, it seems like an error in xQueueReceive as misuse of pointer / address appointments. – lsn Nov 07 '20 at 07:48
  • To your first point - unless you are holding the button when the board powers on, the if-statement will not occur, and the first task will not be created. To your second point - try using `strcmp(a,b)=0` instead of `==` in `QReceiver`. You're comparing the address of two strings instead of the actual content of two strings. – Alex Shirley Nov 07 '20 at 08:08
  • yep, it is blinking :) – lsn Nov 07 '20 at 08:49