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()â?
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âŠ
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.
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:
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);
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.
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.
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.
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.
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.
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.
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.