When "vTaskStartScheduler()" is added, the firmware freezes

Good morning.

I am doing a basic exercise about how to handle a task, I mean create/delete.

The hardware is a RAKWireless solution RAK4631 (Nordic nRF52840 + Semtech LoRa radio+ Nordic BLE radio). When the behavior become normal, the evolution will be tasks to handle RAK1904(accelerometer sensor), RAK1906(environment sensor), RAK5801(current 4-29mA sensor) and RAK12500(GNSS sensor), one task for each sensor.

The code described below is working fine (vTaskStartScheduler() is commented by a //). The problem happens when I try do add the “vTaskStartScheduler()”, the firmware freezes.

Any ideas ? How the FreeRTOS will be behavior with the tasks with or without the “vTaskStartScheduler()”?

Regards,

Claudio


#include "Adafruit_TinyUSB.h"
#include <Arduino.h>
#include <stdint.h> // usa int sem sinal, por exemplo uint8_t, que ocupa apenas 1 byte 
#include <Wire.h> // todos os sensores se comunicam através do I2C

/*mapeamento de pinos*/ 
uint8_t countervTask1 = 0;
uint8_t countervTask2 = 0;

char ptrTaskList[250];

/* VariĂĄveis para armazenamento do handle das tasks*/
TaskHandle_t task1Handle = NULL;
TaskHandle_t task2Handle = NULL;

/*protĂ­tipos das Tasks*/
void vTask1(void *pvParameters);
void vTask2(void *pvParameters);

/*função setup*/
void setup() {
  Serial.begin(115200); //configura comunicação serial com baudrate de 9600 bps
  while (!Serial)
    {
      vTaskDelay(pdMS_TO_TICKS(3000)); //libera a CPU por 3 seg
    }
  Serial.printf("Porta USB iniciada com sucesso!!!! \n");
    vTaskDelay(pdMS_TO_TICKS(3000)); //libera a CPU por 3 seg

 

  xTaskCreate(vTask1,"TASK1",configMINIMAL_STACK_SIZE,NULL,1,&task1Handle);
  xTaskCreate(vTask2,"TASK2",configMINIMAL_STACK_SIZE,NULL,1,&task2Handle);
  //  vTaskStartScheduler();

    vTaskList(ptrTaskList);
		Serial.println("******************************************");
		Serial.println("******* Final da Tarefa Setup ************");
		Serial.println("******************************************");
		Serial.println("Task          State   Prio    Stack    Num"); 
		Serial.println("******************************************");
		Serial.print(ptrTaskList);
		Serial.println("******************************************");
  vTaskDelay(pdMS_TO_TICKS(3000));

}
/*função loop*/
void loop()
{
  Serial.printf("Apagando a tarefa loop \n");
  
  vTaskDelay(pdMS_TO_TICKS(1000));

  vTaskDelete(NULL);
  //  vTaskDelay(3000); //libera a CPU por 3 seg
}


void vTask1(void *pvParameters)
{
    while(countervTask1 <= 50)
    {
      countervTask1++;

      if (countervTask1 <= 50)
      {
        Serial.printf("vTask1 ocorrĂȘncia %d \n", countervTask1);
        vTaskDelay(pdMS_TO_TICKS(1000));
      } else {
              countervTask1 = 0;
              }
    }
}

/*
vTask2 
imprime valor da contagem e dela a task 1 e task 2
*/
void vTask2(void *pvParameters)
{  
  while (countervTask2 <= 60) {
      countervTask2++;
      Serial.printf("vTask2 ocorrĂȘncia %d \n", countervTask2);
      vTaskDelay(pdMS_TO_TICKS(500));
      if (countervTask2 > 50) {
          if (task1Handle != NULL) {
            vTaskList(ptrTaskList);
            Serial.println("******************************************");
            Serial.println("**** Finalizando da Tarefa vTask1 ********");
            Serial.println("******************************************");
            Serial.println("Task          State   Prio    Stack    Num"); 
            Serial.println("******************************************");
            Serial.print(ptrTaskList);
            Serial.println("******************************************");
            vTaskDelay(pdMS_TO_TICKS(3000));
            Serial.printf("Apagando vTask1 \n");
            vTaskDelete(task1Handle);
            task1Handle = NULL;
            vTaskList(ptrTaskList);
            Serial.println("******************************************");
            Serial.println("***** Finalizada a Tarefa vTask1 *********");
            Serial.println("******************************************");
            Serial.println("Task          State   Prio    Stack    Num"); 
            Serial.println("******************************************");
            Serial.print(ptrTaskList);
            Serial.println("******************************************");
            vTaskDelay(pdMS_TO_TICKS(3000));
            }
      }
    }
    vTaskList(ptrTaskList);
    Serial.println("******************************************");
    Serial.println("**** Finalizando da Tarefa vTask2 ********");
    Serial.println("******************************************");
    Serial.println("Task          State   Prio    Stack    Num"); 
    Serial.println("******************************************");
    Serial.print(ptrTaskList);
    Serial.println("******************************************");
    vTaskDelay(pdMS_TO_TICKS(3000));
    Serial.printf("Apagando vTask2 \n");
    vTaskDelay(pdMS_TO_TICKS(3000));
    vTaskDelete(NULL);
    task2Handle = NULL;
    vTaskList(ptrTaskList);
    Serial.println("******************************************");
    Serial.println("***** Finalizada a Tarefa vTask1 *********");
    Serial.println("******************************************");
    Serial.println("Task          State   Prio    Stack    Num"); 
    Serial.println("******************************************");
    Serial.print(ptrTaskList);
    Serial.println("******************************************");
    vTaskDelay(pdMS_TO_TICKS(3000));  
}

Are you really sure the configMINIMAL_STACK_SIZE is sufficient ?
I afraid it’s not since printf functions are used know to require quite a lot of stack.
Did you define configASSERT properly and enabled stack checking as recommended ?
Without starting the scheduler no task will run.
Or just try as a quick test a (much) larger stack size e.g. 1024.

I changed the original FreeRTOSConfig.h by the AWS FreeRTOSConfig.h customized for Nordic nRF52840-DK (this is the MCU that I am using in the RAK4631). Then, the value is 600 for the minimal: “#define configMINIMAL_STACK_SIZE ( 600 )”: Getting started with the Nordic nRF52840-DK - FreeRTOS

What do you think about the value 600? Is it enough?

Below you can see the FreeRTOSConfig.h that I am using:

/*
 * FreeRTOS Kernel V10.0.0
 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. If you wish to use our Amazon
 * FreeRTOS name, please do so in a fair use way that does not cause confusion.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * http://www.FreeRTOS.org
 * http://aws.amazon.com/freertos
 *
 * 1 tab == 4 spaces!
 */


#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

#ifdef SOFTDEVICE_PRESENT
#include "nrf_soc.h"
#endif

// This port of nrf52 use RTC for freeRTOS tick

/*-----------------------------------------------------------
 * Application specific definitions.
 *
 * These definitions should be adjusted for your particular hardware and
 * application requirements.
 *
 * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
 * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
 *
 * See http://www.freertos.org/a00110.html.
 *----------------------------------------------------------*/
#define configTICK_SOURCE                                                         FREERTOS_USE_RTC
#define configUSE_PREEMPTION                                                      1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION                                   0
#define configUSE_TICKLESS_IDLE                                                   0
#define configUSE_TICKLESS_IDLE_SIMPLE_DEBUG                                      1 /* See into vPortSuppressTicksAndSleep source code for explanation */
#define configCPU_CLOCK_HZ                                                        ( SystemCoreClock )
#define configTICK_RATE_HZ                                                        100
#define configMAX_PRIORITIES                                                      ( 15 )
#define configMINIMAL_STACK_SIZE                                                  ( 600 )
#define configTOTAL_HEAP_SIZE                                                     ( 175000 )
#define configMAX_TASK_NAME_LEN                                                   ( 15 )
#define configUSE_16_BIT_TICKS                                                    0
#define configIDLE_SHOULD_YIELD                                                   1
#define configUSE_MUTEXES                                                         1
#define configUSE_RECURSIVE_MUTEXES                                               1
#define configUSE_COUNTING_SEMAPHORES                                             1
#define configUSE_ALTERNATIVE_API                                                 0    /* Deprecated! */
#define configQUEUE_REGISTRY_SIZE                                                 2
#define configUSE_QUEUE_SETS                                                      0
#define configUSE_TIME_SLICING                                                    0
#define configUSE_NEWLIB_REENTRANT                                                0
#define configENABLE_BACKWARD_COMPATIBILITY                                       1

// Erro na compilaïżœïżœo #define configUSE_DAEMON_TASK_STARTUP_HOOK                       1
#define configSUPPORT_STATIC_ALLOCATION                          0
#define configUSE_APPLICATION_TASK_TAG                                            1
#define configUSE_POSIX_ERRNO                                                     1

#define configSUPPORT_DYNAMIC_ALLOCATION                         1

/* Hook function related definitions. */
#define configUSE_IDLE_HOOK                                      1
#define configUSE_TICK_HOOK                                      0
#define configCHECK_FOR_STACK_OVERFLOW                           1
#define configUSE_MALLOC_FAILED_HOOK                             0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS                            0
#if (CFG_DEBUG >= D_INFORMA)
#define configUSE_TRACE_FACILITY                                 1
#define configUSE_STATS_FORMATTING_FUNCTIONS                     1
#else 
#define configUSE_TRACE_FACILITY                                 0
#define configUSE_STATS_FORMATTING_FUNCTIONS                     0
#endif



/* Co-routine definitions. */
#define configUSE_CO_ROUTINES                                    0
#define configMAX_CO_ROUTINE_PRIORITIES                          ( 2 )

/* Software timer definitions. */
#define configUSE_TIMERS                                         1
#define configTIMER_TASK_PRIORITY                                ( 2 ) // Normal
#define configTIMER_QUEUE_LENGTH                                 32
#define configTIMER_TASK_STACK_DEPTH                             ( 256 )

/* Tickless Idle configuration. */
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP                    2

/* Tickless idle/low power functionality. */


/* Define to trap errors during development. */
#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER)
#define configASSERT( x )                                        ASSERT(x)
#endif

/* FreeRTOS MPU specific definitions. */
#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS   1

/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet                                 1
#define INCLUDE_uxTaskPriorityGet                                1
#define INCLUDE_vTaskDelete                                      1
#define INCLUDE_vTaskSuspend                                     1
#define INCLUDE_xResumeFromISR                                   1
#define INCLUDE_vTaskDelayUntil                                  1
#define INCLUDE_vTaskDelay                                       1
#define INCLUDE_xTaskGetSchedulerState                           1
#define INCLUDE_xTaskGetCurrentTaskHandle                        1
#define INCLUDE_uxTaskGetStackHighWaterMark                      1
#define INCLUDE_xTaskGetIdleTaskHandle                           1
#define INCLUDE_xTimerGetTimerDaemonTaskHandle                   1
#define INCLUDE_pcTaskGetTaskName                                1
#define INCLUDE_eTaskGetState                                    1
#define INCLUDE_xEventGroupSetBitFromISR                         1
#define INCLUDE_xTimerPendFunctionCall                           1

/* Code below should be only used by the compiler, and not the assembler. */
#if !(defined(__ASSEMBLY__) || defined(__ASSEMBLER__))
    #include "nrf.h"

    /* This part of definitions may be problematic in assembly - it uses definitions from files that are not assembly compatible. */
    /* Cortex-M specific definitions. */
    #ifdef __NVIC_PRIO_BITS
        /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
        #define configPRIO_BITS             __NVIC_PRIO_BITS
    #else
        #error "This port requires __NVIC_PRIO_BITS to be defined"
    #endif
#endif /* !assembler */

/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY                   ((1<<configPRIO_BITS) - 1)

/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */

/* SD priority
 * 0: SD timing critical
 * 1: SD memory protection
 * 2: App Highest
 * 3: App High
 * 4: SD non-time-critical
 * 5+ Remaining Application
 */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY             2

// Note: Nordic implement its own port (nrf52/port.c) that will shift the NVIC priority to to MSB
// Therefore configKERNEL_INTERRUPT_PRIORITY/configMAX_SYSCALL_INTERRUPT_PRIORITY shouldn't be shifted
// here as the standard port provided by freeRTOS for Cortex M

/* Interrupt priorities used by the kernel port layer itself.  These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY                          configLIBRARY_LOWEST_INTERRUPT_PRIORITY

/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY                     configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY

/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names - or at least those used in the unmodified vector table. */

#define vPortSVCHandler                                          SVC_Handler
#define xPortPendSVHandler                                       PendSV_Handler

/*-----------------------------------------------------------
 * Settings that are generated automatically
 * basing on the settings above
 */
#define configSYSTICK_CLOCK_HZ  ( 32768UL )
#define xPortSysTickHandler     RTC1_IRQHandler

/** Implementation note:  Use this with caution and set this to 1 ONLY for debugging
 * ----------------------------------------------------------
 * Set the value of configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG to below for enabling or disabling RTOS tick auto correction:
 * 0. This is default. If the RTC tick interrupt is masked for more than 1 tick by higher priority interrupts, then most likely
 *    one or more RTC ticks are lost. The tick interrupt inside RTOS will detect this and make a correction needed. This is needed
 *    for the RTOS internal timers to be more accurate.
 * 1. The auto correction for RTOS tick is disabled even though few RTC tick interrupts were lost. This feature is desirable when debugging
 *    the RTOS application and stepping though the code. After stepping when the application is continued in debug mode, the auto-corrections of
 *    RTOS tick might cause asserts. Setting configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG to 1 will make RTC and RTOS go out of sync but could be
 *    convenient for debugging.
 */
#define configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG     0

// Sysview is enabled by default at debug level 3
#if CFG_SYSVIEW
#include "sysview/SEGGER_SYSVIEW_FreeRTOS.h"
#endif

#endif /* FREERTOS_CONFIG_H */

One possible issue is that “arduino” doesn’t really fully support FreeRTOS and parts of the library do things in ways that can cause problems.

Also, if I remember right, the “loop” function is part of the idle hook, so not allowed to call vTaskDelay or to delete itself (I am not totally sure on that, I am just remembering problems from other people), which means that you code WILL crash FreeRTOS (or at least trigger an assert).

Well, as I wrote,.the code is already working with vTaskDelay, vTaskList, xTaskCreate, but when I try to add vTaskSchedule, It os freezeing, without any error messages


Claudio

Except that if you haven’t started the scheduler, the calls to vTaskDelay will just return, as the scheduler isn’t running to implement the delay. If the scheduler IS running, calling vTaskDelay from the idle task will crash the system.

your definition of configASSERT() doesn’t make sure that it is defined, and thus it appears that FreeRTOS’s checks are likely not being performed.

I suppose the question is does the Arduino IDE you are using talk about what you are supposed to be doing to use FreeRTOS? If they already call vTaskStartScheduler on the return from setup(), then perhaps you are breaking things by starting it too soon.

You are using things not under the control of the FreeRTOS team, and things known to streach the typical design rules.

Well, first let me show to you:

  1. I am using VSCode/Platformio with Arduino framework, that this framework contains FreeRTOS, maybe I am wrong, but I suppose that FreeRTOS version is Vanilla: Empowering Embedded Development: FreeRTOS with PlatformIO and Arduino Due

  1. the monitor serial output below: the messages are in portuguese because I came from Brazil, but the idea is show what is the behavior when the vTask1counter reach 50, vTask1 will be deleted by vTask2 and before and after the vTaskDelete is executed, I show the task list with the vTaskList:
 *  Executing task in folder RastAtivosRTOSBase: C:\Users\Claudio Rosa\.platformio\penv\Scripts\platformio.exe device monitor 

--- Terminal on COM8 | 115200 8-N-1
--- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at https://bit.ly/pio-monitor-filters
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
Porta USB iniciada com sucesso!!!! 
******************************************
******* Final da Tarefa Setup ************
******************************************
vTask2 ocorrĂȘncia 1 
vTask1 ocorrĂȘncia 1 
Task          State   Prio    Stack    Num
******************************************
TASK2           R       1       589     7
loop            X       1       862     1
TASK1           R       1       589     6
IDLE            R       0       580     3
Callback        B       2       729     2
usbd            B       3       124     5
Tmr Svc         B       2       219     4
******************************************
vTask2 ocorrĂȘncia 2 
vTask2 ocorrĂȘncia 3 
vTask1 ocorrĂȘncia 2 
vTask2 ocorrĂȘncia 4 
vTask1 ocorrĂȘncia 3 
vTask2 ocorrĂȘncia 5 
vTask2 ocorrĂȘncia 6 
Apagando a tarefa loop 
vTask1 ocorrĂȘncia 4 
vTask2 ocorrĂȘncia 7 
vTask2 ocorrĂȘncia 8 
vTask1 ocorrĂȘncia 5 
vTask2 ocorrĂȘncia 9 
vTask2 ocorrĂȘncia 10 
vTask1 ocorrĂȘncia 6
vTask2 ocorrĂȘncia 11
vTask2 ocorrĂȘncia 12 
vTask1 ocorrĂȘncia 7
vTask2 ocorrĂȘncia 13
vTask2 ocorrĂȘncia 14 
vTask1 ocorrĂȘncia 8
vTask2 ocorrĂȘncia 15
vTask2 ocorrĂȘncia 16 
vTask1 ocorrĂȘncia 9
vTask2 ocorrĂȘncia 17
vTask2 ocorrĂȘncia 18 
vTask1 ocorrĂȘncia 10
vTask2 ocorrĂȘncia 19
vTask2 ocorrĂȘncia 20 
vTask1 ocorrĂȘncia 11
vTask2 ocorrĂȘncia 21
vTask2 ocorrĂȘncia 22 
vTask1 ocorrĂȘncia 12
vTask2 ocorrĂȘncia 23
vTask2 ocorrĂȘncia 24 
vTask1 ocorrĂȘncia 13
vTask2 ocorrĂȘncia 25
vTask2 ocorrĂȘncia 26 
vTask1 ocorrĂȘncia 14
vTask2 ocorrĂȘncia 27
vTask2 ocorrĂȘncia 28 
vTask1 ocorrĂȘncia 15
vTask2 ocorrĂȘncia 29
vTask2 ocorrĂȘncia 30 
vTask1 ocorrĂȘncia 16
vTask2 ocorrĂȘncia 31
vTask2 ocorrĂȘncia 32 
vTask1 ocorrĂȘncia 17
vTask2 ocorrĂȘncia 33
vTask2 ocorrĂȘncia 34 
vTask1 ocorrĂȘncia 18
vTask2 ocorrĂȘncia 35
vTask2 ocorrĂȘncia 36 
vTask1 ocorrĂȘncia 19
vTask2 ocorrĂȘncia 37
vTask2 ocorrĂȘncia 38 
vTask1 ocorrĂȘncia 20
vTask2 ocorrĂȘncia 39
vTask2 ocorrĂȘncia 40 
vTask1 ocorrĂȘncia 21
vTask2 ocorrĂȘncia 41
vTask2 ocorrĂȘncia 42 
vTask1 ocorrĂȘncia 22
vTask2 ocorrĂȘncia 43
vTask2 ocorrĂȘncia 44 
vTask1 ocorrĂȘncia 23
vTask2 ocorrĂȘncia 45
vTask2 ocorrĂȘncia 46 
vTask1 ocorrĂȘncia 24
vTask2 ocorrĂȘncia 47
vTask2 ocorrĂȘncia 48 
vTask1 ocorrĂȘncia 25
vTask2 ocorrĂȘncia 49
vTask2 ocorrĂȘncia 50 
vTask1 ocorrĂȘncia 26
vTask2 ocorrĂȘncia 51
******************************************
**** Finalizando da Tarefa vTask1 ********
******************************************
Task          State   Prio    Stack    Num
******************************************
TASK2           X       1       418     7
IDLE            R       0       579     3
TASK1           B       1       422     6
usbd            B       3       124     5
Tmr Svc         B       2       219     4
Callback        B       2       729     2
******************************************
vTask1 ocorrĂȘncia 27 
vTask1 ocorrĂȘncia 28
vTask1 ocorrĂȘncia 29
Apagando vTask1 
******************************************
***** Finalizada a Tarefa vTask1 *********
******************************************
Task          State   Prio    Stack    Num
******************************************
TASK2           X       1       418     7
IDLE            R       0       579     3
usbd            B       3       124     5
Callback        B       2       729     2
Tmr Svc         B       2       219     4
******************************************
vTask2 ocorrĂȘncia 52 
vTask2 ocorrĂȘncia 53
vTask2 ocorrĂȘncia 54
vTask2 ocorrĂȘncia 55 
vTask2 ocorrĂȘncia 56
vTask2 ocorrĂȘncia 57
vTask2 ocorrĂȘncia 58 
vTask2 ocorrĂȘncia 59
vTask2 ocorrĂȘncia 60
vTask2 ocorrĂȘncia 61 
******************************************
**** Finalizando da Tarefa vTask2 ********
******************************************
Task          State   Prio    Stack    Num
******************************************
TASK2           X       1       418     7
IDLE            R       0       579     3
usbd            B       3       124     5
Tmr Svc         B       2       219     4
Callback        B       2       729     2
******************************************

I’m confused. If you have your tasks running, why do you want to start the scheduler again ?
Or what exactly is the problem you want to solve ?
I’d not propose to use vTaskDelete to kill (other) tasks without proper synchronization.
That causes problems pretty often.
Also in your vTask2 this sequence is probably not what you want:

   vTaskDelete(NULL);
    task2Handle = NULL;  <--- this can't be executed since you deleted the task before !
    vTaskList(ptrTaskList);

The stack size of 600 could be ok. But I’d set
#define configCHECK_FOR_STACK_OVERFLOW 2
for a better check. See FreeRTOS - stacks and stack overflow checking for the details.

I am confused too :slight_smile:

If I didn®t start the Scheduller, maybe is “something” starting the Scheduller, and I don®t know?

Claudio

My guess is that the system automatically starts the scheduler when the setup function returns, and starting it early means that some of the parts that they expect to be setup doesn’t happen, and causes issues.

That is one of the problems with systems like that which try to make it “easy” to use, is that they tend to just hide the complexity, but in doing so, you don’t know what is actually happening, so if you want to do something a bit different than the simple cases that were defined, there isn’t much help on what you need to do.

Thank you Richard by your support.

These concepts I knew in 1984 when I was working with IBM Mainframe environments. Now I am trying to make it happen with FreeRTOS in MCUs for Embedded Systems to monitor Trains for my client.

The super loop architecture version is ready, but now I am testing how to manage tasks in a Real Time Operational Systems, to make my code in a event-driven architecture. To do this, I need to be sure how to control tasks: create, suspend, block and delete.

This is the general idea
 Thank you any way.

ClĂĄudio

I’d like to add that suspend/resume tasks is somewhat special. I guess this feature is used only in rare cases and harder to get right than it seems at the 1st place.
If you have access to the sources of the Arduino SDK you might search for vTaskStartScheduler to see where it’s invoked by the framework or use a debugger and put a breakpoint at it.

One point is that once you add a “Framework”, even if it uses the stock system, is rarely used exactly as the stock system, as the framework provides its own rules. This leads to problems of figuring out if the issue is with the basic system, or the framework, and where should you look for to get support.

The FreeRTOS community will try to help, but without knowing what the Arduino framework is actually doing, it can be difficult to solve issues that can easily be actually problems or misuse of the framework.

As Hartmut says, “Suspend” in my experience is virtually NEVER needed, but should be done with some from of blocking, and deleting is a very rare, and somewhat specialized case.

I would say that virutally all of the code I have used has created all the tasks and related primitives before starting the scheduler, and then tasks block on the privatives waiting for work to perform. I rarely have an “event loop” handling anything other than a user interface, though sometimes it does make sense for a particular sub-system.

2 Likes

The project that I am developing it is based on Low Power WAN concept. This way, it will be a event-driven behavior, in other words, if the hardware is not doing a important task, it will go to sleep or deep sleep state to be able to save energy as much as possible. The power supply will be some 18650 LiFePO4 batteries and the target is to have battery charge for some years.

As tools to save energy, I am planning to measure power consumption using Nordic PPK II turn off (suspend/delete) everytime that it is possible. For example, in normal conditions, it is not necessary to read environment variable, like temperature, humidity and barometric pressure, in the period of time less than 15 minutes, probably between 30 minutes and 1 hour. Then why I would mantain all this sensors spending energy if it is not necessary? Then sleep or deep sleep is a better choice.

Is it more clear now?

ClĂĄudio

As I said to @hs2 , I have to think out of the box, Innovation means sometimes to optimize old things or a creation a new way. :slight_smile:

This is one of reasons that I think that the name IoT should be renamed for “Intellgence of the Things”, because Internet is not really new.

This is one of the reasons that with 60 years old I am still trying to create smart things :slight_smile:

I will give news about the project, as soon as possible

Thank you by your support

Claudio

Tbere is no need to “Suspend” a task before having the processor enter a low power mode. Having the tasks blocked on some object is just as good.

Deleting tasks, and then recreating them when you need them is almost certainly a waste of power, as it takes work to build up and tear down the structures for a task, while nothing to have it sit blocking for a request to do something.

The key point is that processor spend power when doing something, and tasks that are blocked aren’t doing anything, so spend no power.

I found where are the location where the FreeRTOS version that it comes with Platformio Arduino Framework, from Adafruit. Here it is: Adafruit_nRF52_Arduino/cores/nRF5/freertos at master · adafruit/Adafruit_nRF52_Arduino · GitHub

What I would like it is work with the VSCode/Platformio and FreeRTOS from FreeRTOS.org, but I couldnÂŽt find a way to do it.

Today I already part of the thing that I would like because all my sensors libraries are in my environment. I need to control when and how my task will run, this is the reason for FreeRTOS.

And about a waste of power, I will measure the consumption with the Nordic Power Profile Kit II. This way I will be sure about “what” are consuming “how much” :-). I will compare some ways to reach in a conclusion what will be the best choice.

main.cpp

And the question comes, what does the documentaition for that framework say to do. If it comes with FreeRTOS, they should have documentation on how to use FreeRTOS IN THAT FRAMEWORK.

As I mentioned earlier, when you use a framework, you FIRST need to look at what the framework tells you to do and how, not the library that the framework uses, as the framework may do some of the steps the library wants, and may have its own.needs.

The Arduino framework has a number of good features to make it easy for a hobbiest, but it also varies quite a bit in quality from platform to platform based on how well they were able to implement some of the low level libraries on that machine to fit into their structure. There are also at times “quirks” due to its history of how it grew up, so don’t be surprized if some things don’t go the way you expect.

I agree with you, and this is one of reasons that I am looking for a way to work in my IDE environment(VSCode/Platformio) with the FreeRTOS from FreeRTOS.org. Do you know if it is possible?

It sounds like “Platformio” is an Arduino style framework (that include using FreeRTOS), so you need to look at its documentation for how to use FreeRTOS in that framework.