Here is a FreeRTOS example

Last night, I was looking for an example of how to use FreeRTOS in a Mongoose app but didn’t find a complete one. So I wrote one, which I’ll paste below in case anyone else is interested.

main.c:

#include "mgos_app.h"
#include "mgos_gpio.h"

/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"


const uint8_t LED13 = 13;
const uint8_t LED15 = 15;

typedef struct params_s
{
  uint16_t ticks;
  uint8_t led;
} params_t, *p_params_t;

static void vLEDTask(void* pvParameters)
{
    p_params_t pParams = (p_params_t) pvParameters;

    bool on = true;
    TickType_t xLastWakeTime;
    const TickType_t xFrequency = pParams->ticks / portTICK_PERIOD_MS;

     // Initialise the xLastWakeTime variable with the current time.
     xLastWakeTime = xTaskGetTickCount();

     for(;;)
     {
       on = !on;
       mgos_gpio_write(pParams->led, on);

       vTaskDelayUntil(&xLastWakeTime, xFrequency);
     }
}


// Entry point to app
enum mgos_app_init_result mgos_app_init(void)
{
  mgos_gpio_set_mode(LED13, MGOS_GPIO_MODE_OUTPUT);
  mgos_gpio_set_mode(LED15, MGOS_GPIO_MODE_OUTPUT);

  p_params_t pParams1 = (p_params_t) malloc(sizeof(params_t));
  pParams1->led = LED13;
  pParams1->ticks = 1000;

  xTaskCreate(vLEDTask, "LED13", 500, pParams1, 1, NULL );

  p_params_t pParams2 = (p_params_t) malloc(sizeof(params_t));
  pParams2->led = LED15;
  pParams2->ticks = 250;

  xTaskCreate(vLEDTask, "LED15", 500, pParams2, 1, NULL );

  return MGOS_APP_INIT_SUCCESS;
}

mos.yml:

author: Jim
description: Simple app to demonstrate FreeRTOS
version: 1.0

platform: esp32

libs_version: ${mos.version}
modules_version: ${mos.version}
mongoose_os_version: ${mos.version}

# Optional. List of tags for online search.
tags:
  - c

# List of files / directories with C sources. No slashes at the end of dir names.
sources:
  - src

# List of dirs. Files from these dirs will be copied to the device filesystem
filesystem:
  - fs

# Custom configuration entries, settable via "device configuration"
# Below is a custom firmware configuration example.
# Uncomment and modify according to your needs:

# config_schema:
#  - ["my_app", "o", {title: "My app custom settings"}]
#  - ["my_app.bool_value", "b", false, {title: "Some boolean value"}]
#  - ["my_app.string_value", "s", "", {title: "Some string value"}]
#  - ["my_app.int_value", "i", 123, {title: "Some integer value"}]

# These settings get compiled into the C structure, and can be accessed
# from the C code this way:
#
# printf("Hello from %s!\n", mgos_sys_config_get_device_id());
#
# Settings are cool: can be modified remotely without full firmware upgrade!
#
# To see all available compiled settings, buid the firmware and open
# build/gen/mgos_config.h file.
#
# Also, in this config_schema section, you can override existing
# settings that has been created by other libraries. For example, debug log
# level is 2 by default. For this firmware we can override it to 3:
#
config_schema:
 - ["debug.level", 3]


# List of libraries used by this app, in order of initialisation
libs:
  - origin: https://github.com/mongoose-os-libs/ca-bundle

  - origin: https://github.com/mongoose-os-libs/rpc-service-config
  - origin: https://github.com/mongoose-os-libs/rpc-service-fs
  - origin: https://github.com/mongoose-os-libs/rpc-service-ota
  - origin: https://github.com/mongoose-os-libs/rpc-uart
  - origin: https://github.com/mongoose-os-libs/rpc-ws

  - origin: https://github.com/mongoose-os-libs/wifi
  - origin: https://github.com/mongoose-os-libs/sntp
  - origin: https://github.com/mongoose-os-libs/ota-http-server
  - origin: https://github.com/mongoose-os-libs/dash

  - origin: https://github.com/mongoose-os-libs/i2c
  - origin: https://github.com/mongoose-os-libs/spi
6 Likes

Wow. I literally came here to complain how hard it was to blink a LED on ESP32 and found that.

I’m guessing the secret is p_params_t pParams1 = (p_params_t) malloc(sizeof(params_t)); as that creates a param that can be read by the task when the task stack is created (which can be after init_result or another one of your functions/timers/etc finishes).

I’ve been extending the mgos_pwm_rgb_led library to handle fading. In typical fashion the esp32 idf fade end interrupt doesn’t do what you think it’d do, but sends events constantly and the brave people who have tried to dive into it gave up and used xtaskcreate.

My situation is slightly more complicated with RGB LEDs so it’ll need to use pwm. I think I’ll use the RGB library to create my values, then bundle them across to xtaskcreate following your pattern as the color doesn’t change while it’s blinking.

ps, we would have roughly started on the same problem at the same time. I’ve tried all kinds of approaches with fade interrupt, timers (which are best effort at best so the blinking pattern isn’t steady) and xtaskcreate.

Actually my goal was not to blink LEDs, although this does that. I was seeking to learn how to use FreeRTOS to spawn multiple tasks. Ultimately these tasks will do much more than blink LEDs, I was just looking for easy conformation that the tasks are running.

1 Like