FreeRTOS

Working libraries, libraries being ported and related hardware
User avatar
Pito
Posts: 984
Joined: Sat Mar 26, 2016 3:26 pm
Location: Rapa Nui

Re: FreeRTOS

Postby Pito » Thu Aug 04, 2016 9:34 pm

It draws a small single cube sometimes after a reset, but it stops afterwards.. So the SPI2 works somehow, but there must be an issue probably with DMA (SPI2 uses DMA imho) vs. FreeRtos.
Ok, with larger Cube_stack_sizes (ie. 512bytes, the default configMINIMAL_STACK_SIZE is 120 shorts) it works now with SPI2 as well:

Code: Select all

..
  xTaskCreate(vCube1LoopTask,
              "Cube1",
              512,
              NULL,
              tskIDLE_PRIORITY + 2,
              NULL);
  xTaskCreate(vCube2LoopTask,
              "Cube2",
              512,
              NULL,
              tskIDLE_PRIORITY + 1,
              NULL);
              ..
Pukao Hats Cleaning Services Ltd.

User avatar
Pito
Posts: 984
Joined: Sat Mar 26, 2016 3:26 pm
Location: Rapa Nui

Re: FreeRTOS

Postby Pito » Fri Aug 05, 2016 9:46 am

And the Maple Mini version (incl. some mods) with the display at SPI2:

Code: Select all

// Cube FreeRtos Demo
// for Maple Mini and SPI2 display
// uses "SPI2" ILI9341 library
// uses UART at 115k2
// ide 1.6.10
// mods 8/2016 by Pito

#include <MapleFreeRTOS821.h>
#include <SPI.h>
#include <Adafruit_GFX_AS.h>    // Core graphics library, with extra fonts.
#include <Adafruit_ILI9341_STM_SPI2.h>  // SPI2 DMA Hardware-specific library

// Maple Mini with SPI2
#define TFT_CS         PA8                 
#define TFT_DC         PA13   

Adafruit_ILI9341_STM tft = Adafruit_ILI9341_STM(TFT_CS, TFT_DC); // Use hardware SPI

xSemaphoreHandle xDisplayFree;

#define BOARD_LED_PIN PB1

const float sin_d[] = {
  0, 0.17, 0.34, 0.5, 0.64, 0.77, 0.87, 0.94, 0.98, 1, 0.98, 0.94,
  0.87, 0.77, 0.64, 0.5, 0.34, 0.17, 0, -0.17, -0.34, -0.5, -0.64,
  -0.77, -0.87, -0.94, -0.98, -1, -0.98, -0.94, -0.87, -0.77,
  -0.64, -0.5, -0.34, -0.17
};
const float cos_d[] = {
  1, 0.98, 0.94, 0.87, 0.77, 0.64, 0.5, 0.34, 0.17, 0, -0.17, -0.34,
  -0.5, -0.64, -0.77, -0.87, -0.94, -0.98, -1, -0.98, -0.94, -0.87,
  -0.77, -0.64, -0.5, -0.34, -0.17, 0, 0.17, 0.34, 0.5, 0.64, 0.77,
  0.87, 0.94, 0.98
};
const float d = 5;
float cube1_px[] = {
  -d,  d,  d, -d, -d,  d,  d, -d
};
float cube1_py[] = {
  -d, -d,  d,  d, -d, -d,  d,  d
};
float cube1_pz[] = {
  -d, -d, -d, -d,  d,  d,  d,  d
};

float cube1_p2x[] = {
  0, 0, 0, 0, 0, 0, 0, 0
};
float cube1_p2y[] = {
  0, 0, 0, 0, 0, 0, 0, 0
};

int cube1_r[] = {
  0, 0, 0
};
const float d2 = 10;
float cube2_px[] = {
  -d2,  d2,  d2, -d2, -d2,  d2,  d2, -d2
};
float cube2_py[] = {
  -d2, -d2,  d2,  d2, -d2, -d2,  d2,  d2
};
float cube2_pz[] = {
  -d2, -d2, -d2, -d2,  d2,  d2,  d2,  d2
};

float cube2_p2x[] = {
  0, 0, 0, 0, 0, 0, 0, 0
};
float cube2_p2y[] = {
  0, 0, 0, 0, 0, 0, 0, 0
};

int cube2_r[] = {
  0, 0, 0
};

uint16 cube1_x, cube1_y, cube2_x, cube2_y, cube1_color, cube2_color;

 // Perform an LED blink every 1000msecs
 static void vLEDFlashTask( void * pvParameters )
 {
 portTickType xLastWakeTime;
 const portTickType xPeriod = 1000; // =1second with 1ms Tick
     // Initialise the xLastWakeTime variable with the current time.
     xLastWakeTime = xTaskGetTickCount();
     for( ;; )
     {
         // Wait for the next blink cycle.
         vTaskDelayUntil( &xLastWakeTime, xPeriod );
         // Perform the LED blink
         digitalWrite(BOARD_LED_PIN, HIGH);
         vTaskDelay(50); // 50msec blink
         digitalWrite(BOARD_LED_PIN, LOW);
     }
 }

static void vCube1LoopTask(void *pvParameters) {
  while (1) {
    if ( xSemaphoreTake( xDisplayFree, ( portTickType ) 10 ) == pdTRUE )
    {
      cube(cube1_px, cube1_py, cube1_pz, cube1_p2x, cube1_p2y, cube1_r, &cube1_x, &cube1_y, &cube1_color);
      xSemaphoreGive( xDisplayFree );
        vTaskDelay(50);
    }
  }
}

static void vCube2LoopTask(void *pvParameters) {
  while (1) {
    if ( xSemaphoreTake( xDisplayFree, ( portTickType ) 10 ) == pdTRUE )
    {
      cube(cube2_px, cube2_py, cube2_pz, cube2_p2x, cube2_p2y, cube2_r, &cube2_x, &cube2_y, &cube2_color);
      xSemaphoreGive( xDisplayFree );
        vTaskDelay(40);
    }
  }
}


void cube(float *px, float *py, float *pz, float *p2x, float *p2y, int *r, uint16 *x, uint16 *y, uint16 *color) {

  for (int i = 0; i < 3; i++) {
    tft.drawLine(p2x[i], p2y[i], p2x[i + 1], p2y[i + 1], ILI9341_WHITE);
    tft.drawLine(p2x[i + 4], p2y[i + 4], p2x[i + 5], p2y[i + 5], ILI9341_WHITE);
    tft.drawLine(p2x[i], p2y[i], p2x[i + 4], p2y[i + 4], ILI9341_WHITE);
  }
  tft.drawLine(p2x[3], p2y[3], p2x[0], p2y[0], ILI9341_WHITE);
  tft.drawLine(p2x[7], p2y[7], p2x[4], p2y[4], ILI9341_WHITE);
  tft.drawLine(p2x[3], p2y[3], p2x[7], p2y[7], ILI9341_WHITE);

  r[0] = r[0] + 1;
  r[1] = r[1] + 1;
  if (r[0] == 36) r[0] = 0;
  if (r[1] == 36) r[1] = 0;
  if (r[2] == 36) r[2] = 0;
  for (int i = 0; i < 8; i++)
  {
    float px2 = px[i];
    float py2 = cos_d[r[0]] * py[i] - sin_d[r[0]] * pz[i];
    float pz2 = sin_d[r[0]] * py[i] + cos_d[r[0]] * pz[i];

    float px3 = cos_d[r[1]] * px2 + sin_d[r[1]] * pz2;
    float py3 = py2;
    float pz3 = -sin_d[r[1]] * px2 + cos_d[r[1]] * pz2;

    float ax = cos_d[r[2]] * px3 - sin_d[r[2]] * py3;
    float ay = sin_d[r[2]] * px3 + cos_d[r[2]] * py3;
    float az = pz3 - 190;

    p2x[i] = *x + ax * 500 / az;
    p2y[i] = *y + ay * 500 / az;
  }

  for (int i = 0; i < 3; i++) {
    tft.drawLine(p2x[i], p2y[i], p2x[i + 1], p2y[i + 1], *color);
    tft.drawLine(p2x[i + 4], p2y[i + 4], p2x[i + 5], p2y[i + 5], *color);
    tft.drawLine(p2x[i], p2y[i], p2x[i + 4], p2y[i + 4], *color);
  }
  tft.drawLine(p2x[3], p2y[3], p2x[0], p2y[0], *color);
  tft.drawLine(p2x[7], p2y[7], p2x[4], p2y[4], *color);
  tft.drawLine(p2x[3], p2y[3], p2x[7], p2y[7], *color);
}

static void vSqrtTask(void *pvParameters) {
  while (1){
  Serial1.println (F("Starting Sqrt calculations..."));
  uint32 x = 0;
  uint32 Ns = 100000; // number of sqrt calcs
  // Library Sqrt
  uint32_t t0 = millis();
  for (uint32_t n = 1 ; n < Ns ; n++) {
    x = sqrt (247400000 + n);
  }
  uint32_t t1 = millis() - t0;
  Serial1.print (F("100k Sqrt calculations took (ms): "));
  Serial1.println (t1);
  vTaskDelay (70);
  }
}

void setup() {
  // initialize the digital pin as an output:
  Serial1.begin(115200);
  delay (1000);
  Serial1.println (F("Running..."));
  pinMode(BOARD_LED_PIN, OUTPUT);
  tft.begin();
  tft.fillScreen(ILI9341_WHITE);
  cube1_x = ((tft.width()) / 4);
  cube1_y = ((tft.height()) / 4);
  cube2_x = ((tft.width()) / 2);
  cube2_y = ((tft.height()) / 2);
  cube1_color = ILI9341_BLACK;
  cube2_color = ILI9341_RED;
  vSemaphoreCreateBinary(xDisplayFree);
  xTaskCreate(vLEDFlashTask,
              "Task1",
              configMINIMAL_STACK_SIZE,
              NULL,
              tskIDLE_PRIORITY + 3,
              NULL);
  xTaskCreate(vCube1LoopTask,
              "Cube1",
              configMINIMAL_STACK_SIZE + 200,
              NULL,
              tskIDLE_PRIORITY + 2,
              NULL);
  xTaskCreate(vCube2LoopTask,
              "Cube2",
              configMINIMAL_STACK_SIZE + 200,
              NULL,
              tskIDLE_PRIORITY + 1,
              NULL);
  xTaskCreate(vSqrtTask,
              "Sqrt",
              configMINIMAL_STACK_SIZE,
              NULL,
              tskIDLE_PRIORITY,
              NULL);
  vTaskStartScheduler();
 
   Serial.println(F("Insufficient RAM"));
   while(1);
}

void loop() {
  // Do not write any code here, it would not execute.
}

Code: Select all

Starting Sqrt calculations...
100k Sqrt calculations took (ms): 3620
Starting Sqrt calculations...
100k Sqrt calculations took (ms): 3642
Pukao Hats Cleaning Services Ltd.

priyank_bolia
Posts: 1
Joined: Wed Oct 12, 2016 5:14 pm

Re: FreeRTOS

Postby priyank_bolia » Wed Oct 12, 2016 5:23 pm

Did anyone has success in using timers in FreeRTOS on STM32Duino. I tried to compile, it compiled, but did nothing. the timer function was never called. Does anyone has a working example of timers.

michael_l
Posts: 318
Joined: Mon Aug 24, 2015 6:11 pm

Re: FreeRTOS

Postby michael_l » Wed Nov 02, 2016 10:42 am

priyank_bolia wrote:Did anyone has success in using timers in FreeRTOS on STM32Duino. I tried to compile, it compiled, but did nothing. the timer function was never called. Does anyone has a working example of timers.


Hi, did you get this solved ? Could we see your sketch ?

michael_l
Posts: 318
Joined: Mon Aug 24, 2015 6:11 pm

Re: FreeRTOS

Postby michael_l » Wed Nov 02, 2016 10:45 am

This must sound like a simple question but does using 'Serial.println' etc. functions need guarding with mutexes in this FreeRtos made for Maple and BluePill in STM32Duino ?

User avatar
Pito
Posts: 984
Joined: Sat Mar 26, 2016 3:26 pm
Location: Rapa Nui

Re: FreeRTOS

Postby Pito » Wed Nov 02, 2016 5:31 pm

I would recommend to use mutexes for any resources which could be called/requested out of several tasks.
The Serial usually address a single device (terminal) so not using a mutex around Serial must not necessarily crash the code (but mess the input/output), however resources like SPI and I2C when be called out of various tasks and address various task-related devices can crash, thus a mutex here is required, afaik.
Pukao Hats Cleaning Services Ltd.

Ollie
Posts: 149
Joined: Thu Feb 25, 2016 7:27 pm

Re: FreeRTOS

Postby Ollie » Wed Nov 02, 2016 6:29 pm

For SPI and I2C, I have used a queuing model where one or multiple threads/tasks can post the request without any blocking. Those requests are stored in a FIFO and processed one at time. When the response from remote device is available, a callback mechanism is used to communicate with the original thread/task.

In that model, not mutex is required.

Cheers, Ollie

michael_l
Posts: 318
Joined: Mon Aug 24, 2015 6:11 pm

Re: FreeRTOS

Postby michael_l » Thu Nov 03, 2016 8:34 am

Thanks Pito and Ollie. I tested with several tasks writing to Serial and at some point it got messed but not crashed. Good to know. I'm using SPI1 and SPI2 with Adafrut_ILI9143_STM library and there I have to use mutexes.

Some other question related to memory handling. I've programmed in multithread environments for many years but with PC's mostly. Embedded stuff is so different as we all know.

I found that FreeRTOS has own memory model where you define in the config file how much memory (heap) it can use. Where is this defined? From build log I can see that 8kB is allocated so I'm guessing 8kB is the amount defined. Also is the 8kB heap available globally for use within all tasks ?

Second question:

In one of my tasks I added some my code and when I start it it hangs. Is there any methods in FreeRTOS available to trace if for example stack is out of memory, can i get some callback function or such ? if there is fault at processor level can this be traced or found out also ?

Thanks.

User avatar
Pito
Posts: 984
Joined: Sat Mar 26, 2016 3:26 pm
Location: Rapa Nui

Re: FreeRTOS

Postby Pito » Thu Nov 03, 2016 9:57 am

..\hardware\Arduino_STM32\STM32F1\libraries\FreeRTOS821\utility\MemMang\heap_1.c
There are several heap models there..

Maybe:
http://www.freertos.org/uxTaskGetStackH ... rMark.html
Pukao Hats Cleaning Services Ltd.

michael_l
Posts: 318
Joined: Mon Aug 24, 2015 6:11 pm

Re: FreeRTOS

Postby michael_l » Thu Nov 03, 2016 6:41 pm

Thanks. And here's also one way to check:

http://www.freertos.org/Stacks-and-stac ... cking.html


Return to “Libraries & Hardware”

Who is online

Users browsing this forum: No registered users and 2 guests