This is the main.c file:
/*
* FreeRTOS V202212.00
* Copyright (C) 2020 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.
*
* 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.
*
*
*/
/******************************************************************************
* This project provides two demo applications. A simple blinky style project,
* and a more comprehensive test and demo application. The
* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting (defined in this file) is used to
* select between the two. The simply blinky demo is implemented and described
* in main_blinky.c. The more comprehensive test and demo application is
* implemented and described in main_full.c.
*
* This file implements the code that is not demo specific, including the
* hardware setup and FreeRTOS hook functions.
*
*/
/* Standard includes. */
#include <stdio.h>
#include <ioport.h>
#include <ioport_pio.h>
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"
#include "portmacro.h"
#include "event_groups.h"
#include "uart_dma.h"
#include "conf_board.h"
#include "rb_uint8_256.h"
#include "usart.h"
#include "rb_tx_dbg_uart.h"
#include "power.h"
#include "core_cm4.h"
#include "wdt.h"
#include "string.h"
#include "compiler.h"
#include <pio/pio.h>
#include <pio_handler.h>
#define POWER_BUTTON MCU_PB_PWR_MASK
#define TRIGGER_BUTTON MCU_PB_USR_MASK
#define PWR_BUT_INT_PRESS PIO_IT_RISE_EDGE
#define PWR_BUT_INT_REAL PIO_IT_FALL_EDGE
#define TRI_BUT_INT_PRESS PIO_IT_FALL_EDGE
#define TRI_BUT_INT_REAL PIO_IT_RISE_EDGE
#define BIT_0 (1 << 0)
#define BIT_1 (1 << 1)
#define mainREAD_ONLY_ALIGN_SIZE 512
/* Declare a variable to hold the handle of the created event group. */
EventGroupHandle_t xEventGroupHandle;
/* Declare a variable to hold the data associated with the created
event group. */
StaticEventGroup_t xCreatedEventGroup;
SemaphoreHandle_t xSemaphore = NULL;
StaticSemaphore_t xSemaphoreBuffer;
static const uart_dma_t uart_dma = UART_DMA__UART2;
static void tx_callback_from_IRQ(void);
static rb_tx_dbg_uart_t tx_ring_buffer = {};
// ------------------ TX -------------------
static void try_to_pop_ring_buffer_to_uart_dma(void) {
// can be call from IRQ or main context -> must be protected with ctritical section
cpu_irq_enter_critical(); //-------------------------
uart_dma_frame_t* tx_frame = uart_dma_tx_get_frame_buffer(uart_dma);
if (tx_frame != NULL) {
// pop from ring buffer to tx frame
const uint32_t nb_popped = rb_tx_dbg_uart_pop_multi(&tx_ring_buffer, &tx_frame->data[tx_frame->len], tx_frame->max_len - tx_frame->len);
tx_frame->len += nb_popped;
uart_dma_tx_send_frame(uart_dma);
}
cpu_irq_leave_critical(); //-------------------------
}
// call when uart_dma has finished to send a frame
static void tx_callback_from_IRQ(void) {
try_to_pop_ring_buffer_to_uart_dma();
}
#if 0
TaskHandle_t xTaskTestOverflow;
void fun(int x);
void fun (int x){
UBaseType_t uxHighWaterMark;
char ch[4];
if (x==1){
uart_dma_write(uart_dma, "Fin de l'exécution", sizeof(char)*19);
}
else {
//uart_dma_write(uart_dma, "Exécution en cours", sizeof(char)*19);
x=6;
/* Inspect our own high water mark on entering the task. */
uxHighWaterMark = uxTaskGetStackHighWaterMark(xTaskTestOverflow);
sprintf(ch, "%lu", uxHighWaterMark);
while (uart_dma_tx_get_frame_buffer(uart_dma)==NULL) {
vTaskDelay(1000/portTICK_PERIOD_MS);
}
uart_dma_write(uart_dma, ch, sizeof(char)*4);
fun(x);
}
}
static void taskTestOverflow( void * pvParameters) {
UNUSED(pvParameters);
int x = 5;
for (;;)
{
fun(x);
}
}
#endif
StaticTask_t xTaskBufferuart;
TaskHandle_t xTaskuart;
static void taskuart( void * pvParameters) {
UNUSED(pvParameters);
portTickType xLastWakeTime;
xLastWakeTime = xTaskGetTickCount();
vTaskDelayUntil(&xLastWakeTime, 100/portTICK_PERIOD_MS);
char p[9] ="Bonjour ";
for (;;)
{
while (uart_dma_tx_get_frame_buffer(uart_dma)==NULL) {
vTaskDelay(1000/portTICK_PERIOD_MS);
}
uart_dma_write(uart_dma, p, sizeof(char)*9);
vTaskSuspend(NULL);
//vTaskDelayUntil(&xLastWakeTime, 9000); //correspond à une périodicité de 9s
}
}
#if 0
TaskHandle_t xTaskCStack;
static void taskCStack( void * pvParameters) {
UNUSED(pvParameters);
UBaseType_t uxHighWaterMark;
char ch[4];
for (;;)
{
/* Inspect our own high water mark on entering the task. */
uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);
sprintf(ch, "%lu", uxHighWaterMark);
while (uart_dma_tx_get_frame_buffer(uart_dma)==NULL) {
vTaskDelay(1000/portTICK_PERIOD_MS);
}
//strcat(ch, " ");
//vTaskDelay(3000/portTICK_PERIOD_MS);
uart_dma_write(uart_dma, ch, sizeof(char)*4);
//vTaskDelay(3000/portTICK_PERIOD_MS); //correspond à une périodicité de 3s
}
}
#endif
StaticTask_t xTaskBuffer1;
TaskHandle_t xTask1;
static void task1( void * pvParameters ){
UNUSED(pvParameters);
portTickType xLastWakeTime;
#if 0
uint8_t buf = 49;
#endif
UBaseType_t uxHighWaterMark;
char ch[3];
//Allume led camera en rouge
ioport_pin_t led_pin = 23;
arch_ioport_set_pin_dir(led_pin, IOPORT_DIR_OUTPUT);
xLastWakeTime =xTaskGetTickCount();
vTaskDelayUntil(&xLastWakeTime, 100/portTICK_PERIOD_MS);
/* Worker task Loop. */
for(;;)
{
/*for (uint32_t i =0; i<100; i++){
buf = buf +i;
}*/
arch_ioport_set_pin_level(led_pin, true);
vTaskDelay(1000/portTICK_PERIOD_MS);
//uart_dma_write(uart_dma, &buf, sizeof(uint8_t));
//printf("%u", buf);
while (uart_dma_tx_get_frame_buffer(uart_dma)==NULL) {
vTaskDelay(1000/portTICK_PERIOD_MS);
}
uart_dma_write(uart_dma, "Tache 1 ", sizeof(char)*9);
arch_ioport_set_pin_level(led_pin, false);
//vTaskDelay(2000/portTICK_PERIOD_MS);
//vTaskDelay(1000/portTICK_PERIOD_MS);
/* Inspect our own high water mark on entering the task. */
uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);
sprintf(ch, "%lu", uxHighWaterMark);
while (uart_dma_tx_get_frame_buffer(uart_dma)==NULL) {
vTaskDelay(1000/portTICK_PERIOD_MS);
}
//vTaskDelay(3000/portTICK_PERIOD_MS);
uart_dma_write(uart_dma, ch, sizeof(char)*3);
/*Calling the function will have used some stack space, we would therefore now expect uxTaskGetStackHighWaterMark()
to return a value lower than when it was called on entering the task. */
vTaskSuspend(NULL);
//vTaskDelayUntil(&xLastWakeTime, 9000/portTICK_PERIOD_MS); //correspond à une périodicité de 9s
}
}
StaticTask_t xTaskBuffer2;
TaskHandle_t xTask2;
static void task2( void * pvParameters ){
UNUSED(pvParameters);
portTickType xLastWakeTime;
UBaseType_t uxHighWaterMark;
char ch[3];
//Allume led camera en vert
ioport_pin_t led_pin = 21;
arch_ioport_set_pin_dir(led_pin, IOPORT_DIR_OUTPUT);
xLastWakeTime =xTaskGetTickCount();
vTaskDelayUntil(&xLastWakeTime, 100/portTICK_PERIOD_MS);
/* Worker task Loop. */
for(;;)
{
arch_ioport_set_pin_level(led_pin, true);
vTaskDelay(1000/portTICK_PERIOD_MS);
while (uart_dma_tx_get_frame_buffer(uart_dma)==NULL) {
vTaskDelay(1000/portTICK_PERIOD_MS);
}
uart_dma_write(uart_dma, "Tache 2 ", sizeof(char)*9);
arch_ioport_set_pin_level(led_pin, false);
uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);
uxHighWaterMark = 160 - uxHighWaterMark;
sprintf(ch, "%lu", uxHighWaterMark);
while (uart_dma_tx_get_frame_buffer(uart_dma)==NULL) {
vTaskDelay(1000/portTICK_PERIOD_MS);
}
uart_dma_write(uart_dma, ch, sizeof(char)*3);
vTaskSuspend(NULL);
//vTaskDelayUntil(&xLastWakeTime, 4000/portTICK_PERIOD_MS);
}
}
TaskHandle_t xTaskSender;
static void taskSender(void *pvParameters){
UNUSED(pvParameters);
for (;;)
{
vTaskDelay(pdMS_TO_TICKS(1000));
xEventGroupSetBits(xEventGroupHandle, BIT_0);
//printf("Event BIT_0 sent\n");
while (uart_dma_tx_get_frame_buffer(uart_dma)==NULL) {
vTaskDelay(1000/portTICK_PERIOD_MS);
}
uart_dma_write(uart_dma, "BIT_0 sent ", sizeof(char)*11);
vTaskDelay(pdMS_TO_TICKS(2000));
xEventGroupSetBits(xEventGroupHandle, BIT_1);
while (uart_dma_tx_get_frame_buffer(uart_dma)==NULL) {
vTaskDelay(1000/portTICK_PERIOD_MS);
}
uart_dma_write(uart_dma, "BIT_1 sent ", sizeof(char)*11);
}
}
TaskHandle_t xTaskReceiver;
static void taskReceiver(void *pvParameters)
{
UNUSED(pvParameters);
EventBits_t uxBits;
//Allume led camera en bleu
ioport_pin_t led_pin_0 = 22;
ioport_pin_t led_pin_cam = 23;
//Allume led power en rouge
ioport_pin_t led_pin_1 = 0;
ioport_pin_t led_pin_pow = 21;
arch_ioport_set_pin_dir(led_pin_0, IOPORT_DIR_OUTPUT);
arch_ioport_set_pin_dir(led_pin_1, IOPORT_DIR_OUTPUT);
for (;;)
{
uxBits = xEventGroupWaitBits(
xEventGroupHandle, // Le groupe d'événements à surveiller
BIT_0 | BIT_1, // Les bits à surveiller
pdTRUE, // Effacer les bits après réception
pdFALSE, // Attendre tous les bits ou n'importe lequel
portMAX_DELAY // Attendre indéfiniment
);
if ((uxBits & BIT_0) != 0)
{
//arch_ioport_set_pin_level(led_pin_cam, false);
arch_ioport_set_pin_level(led_pin_0, true);
vTaskDelay(1000/portTICK_PERIOD_MS);
arch_ioport_set_pin_level(led_pin_0, false);
//printf("Received BIT_0\n");
while (uart_dma_tx_get_frame_buffer(uart_dma)==NULL) {
vTaskDelay(1000/portTICK_PERIOD_MS);
}
uart_dma_write(uart_dma, "BIT_0 receive ", sizeof(char)*14);
}
if ((uxBits & BIT_1) != 0)
{
//arch_ioport_set_pin_level(led_pin_pow, false);
arch_ioport_set_pin_level(led_pin_1, true);
vTaskDelay(1000/portTICK_PERIOD_MS);
arch_ioport_set_pin_level(led_pin_1, false);
while (uart_dma_tx_get_frame_buffer(uart_dma)==NULL) {
vTaskDelay(1000/portTICK_PERIOD_MS);
}
uart_dma_write(uart_dma, "BIT_1 receive ", sizeof(char)*14);
//printf("Received BIT_1\n");
}
//vTaskResume(xTaskSender);
}
}
StaticTimer_t xTimerBuffer;
TimerHandle_t Timer_id;
static void TimerCallback ( TimerHandle_t pxtimer){
UNUSED(pxtimer);
#if 0
uart_dma_write(uart_dma, "I am the timer ", sizeof(char)*16);
#endif
vTaskResume(xTaskuart);
vTaskResume(xTask1);
vTaskResume(xTask2);
}
StaticTimer_t xTimerBufferwdt;
TimerHandle_t Timer_idwdt;
static void TimerCallbackwdt ( TimerHandle_t pxtimer){
/* Reload watchdog */
UNUSED(pxtimer);
uart_dma_write(uart_dma, "Watchdog reset ", sizeof(char)*16);
WDT->WDT_CR = WDT_CR_KEY_PASSWD | WDT_CR_WDRSTT;
}
extern const char _sfixed[];
static uint8_t tx_buffer[128] = {};
const uart_dma_config_t config = {
.baudrate = 115200,
.handshaking = false,
.rx_callback_from_IRQ = NULL,
.tx_end_callback_from_IRQ = tx_callback_from_IRQ,
.tx_buffer = tx_buffer,
.tx_buffer_size = sizeof(tx_buffer),
};
StaticTask_t xTaskBufferled;
TaskHandle_t xStartLedTask;
static void StartLedTask(void *pvParameters)
{
uint32_t ulNotifiedValue;
//Allume led power en rouge
ioport_pin_t led_pin_1 = 0;
arch_ioport_set_pin_dir(led_pin_1, IOPORT_DIR_OUTPUT);
xSemaphore = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer);
UNUSED(pvParameters);
for(;;)
{
//ulNotifiedValue = ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
if(xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE)
{
arch_ioport_set_pin_level(led_pin_1, true);
vTaskDelay(1000/portTICK_PERIOD_MS);
arch_ioport_set_pin_level(led_pin_1, false);
uart_dma_write(uart_dma, "success\n", sizeof(char)*8);
}
else
{
uart_dma_write(uart_dma, "failure ", sizeof(char)*8);
}
}
}
void userButtonPressedHandler( uint32_t ul_id, uint32_t ul_mask) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
//vTaskNotifyGiveFromISR(xStartLedTask, &xHigherPriorityTaskWoken);
xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);
/* portYIELD_FROM_ISR() will request a context switch if executing this
interrupt handler caused a task to leave the blocked state, and the task
that left the blocked state has a higher priority than the currently running
task (the task this interrupt interrupted).*/
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
//Paramètres de création de la tâche 1
/* Declare the stack that will be used by the task. The stack alignment must
match its size and be a power of 2, so if 128 words are reserved for the stack
then it must be aligned to ( 128 * 4 ) bytes. This example used GCC syntax. */
static portSTACK_TYPE xTaskStack1[ 256 ] __attribute__((aligned(256*4)));
/* Declare an array that will be accessed by the task. The task should only
be able to read from the array, and not write to it. */
char cReadOnlyArray1[ 512 ] __attribute__((aligned(512)));
/* Fill in a TaskParameters_t structure to define the task - this is the
structure passed to the xTaskCreateRestricted() function. */
static const TaskParameters_t xTaskDefinition1 =
{
task1, /* pvTaskCode */
"Task 1", /* pcName */
140, /* usStackDepth - defined in words, not bytes. */
NULL, /* pvParameters */
5, /* uxPriority - priority 1, start in User mode. */
xTaskStack1, /* puxStackBuffer - the array to use as the task stack. */
/* xRegions - In this case only one of the three user definable regions is
actually used. The parameters are used to set the region to read only. */
{
/* Base address Length Parameters */
{ cReadOnlyArray1, mainREAD_ONLY_ALIGN_SIZE, portMPU_REGION_READ_ONLY },
{ 0, 0, 0 },
{ 0, 0, 0 },
},
&xTaskBuffer1
};
//Paramètres de création de la tâche 2
/* Declare the stack that will be used by the task. The stack alignment must
match its size and be a power of 2, so if 128 words are reserved for the stack
then it must be aligned to ( 128 * 4 ) bytes. This example used GCC syntax. */
static portSTACK_TYPE xTaskStack2[ 256 ] __attribute__((aligned(256*4)));
/* Declare an array that will be accessed by the task. The task should only
be able to read from the array, and not write to it. */
char cReadOnlyArray2[ 512 ] __attribute__((aligned(512)));
/* Fill in a TaskParameters_t structure to define the task - this is the
structure passed to the xTaskCreateRestricted() function. */
static const TaskParameters_t xTaskDefinition2 =
{
task2, /* pvTaskCode */
"Task 2", /* pcName */
140, /* usStackDepth - defined in words, not bytes. */
NULL, /* pvParameters */
4, /* uxPriority - priority 1, start in User mode. */
xTaskStack2, /* puxStackBuffer - the array to use as the task stack. */
/* xRegions - In this case only one of the three user definable regions is
actually used. The parameters are used to set the region to read only. */
{
/* Base address Length Parameters */
{ cReadOnlyArray2, mainREAD_ONLY_ALIGN_SIZE, portMPU_REGION_READ_ONLY },
{ 0, 0, 0 },
{ 0, 0, 0 },
},
&xTaskBuffer2
};
//Paramètres de création de la tâche Uart
/* Declare the stack that will be used by the task. The stack alignment must
match its size and be a power of 2, so if 128 words are reserved for the stack
then it must be aligned to ( 128 * 4 ) bytes. This example used GCC syntax. */
static portSTACK_TYPE xTaskStackUart[ 128 ] __attribute__((aligned(128*4)));
/* Declare an array that will be accessed by the task. The task should only
be able to read from the array, and not write to it. */
char cReadOnlyArrayUart[ 512 ] __attribute__((aligned(512)));
/* Fill in a TaskParameters_t structure to define the task - this is the
structure passed to the xTaskCreateRestricted() function. */
static const TaskParameters_t xTaskDefinitionUart =
{
taskuart, /* pvTaskCode */
"Task Uart", /* pcName */
128, /* usStackDepth - defined in words, not bytes. */
NULL, /* pvParameters */
2, /* uxPriority - priority 1, start in User mode. */
xTaskStackUart, /* puxStackBuffer - the array to use as the task stack. */
/* xRegions - In this case only one of the three user definable regions is
actually used. The parameters are used to set the region to read only. */
{
/* Base address Length Parameters */
{ cReadOnlyArrayUart, mainREAD_ONLY_ALIGN_SIZE, portMPU_REGION_READ_ONLY },
{ 0, 0, 0 },
{ 0, 0, 0 },
},
&xTaskBufferuart
};
//Paramètres de création de la tâche Led
/* Declare the stack that will be used by the task. The stack alignment must
match its size and be a power of 2, so if 128 words are reserved for the stack
then it must be aligned to ( 128 * 4 ) bytes. This example used GCC syntax. */
static portSTACK_TYPE xTaskStackled[ 128 ] __attribute__((aligned(128*4)));
/* Declare an array that will be accessed by the task. The task should only
be able to read from the array, and not write to it. */
char cReadOnlyArrayled[ 512 ] __attribute__((aligned(512)));
/* Fill in a TaskParameters_t structure to define the task - this is the
structure passed to the xTaskCreateRestricted() function. */
static const TaskParameters_t xTaskDefinitionled =
{
StartLedTask, /* pvTaskCode */
"Task interrupt handler", /* pcName */
128, /* usStackDepth - defined in words, not bytes. */
NULL, /* pvParameters */
4, /* uxPriority - priority 1, start in User mode. */
xTaskStackled, /* puxStackBuffer - the array to use as the task stack. */
/* xRegions - In this case only one of the three user definable regions is
actually used. The parameters are used to set the region to read only. */
{
/* Base address Length Parameters */
{ cReadOnlyArrayled, mainREAD_ONLY_ALIGN_SIZE, portMPU_REGION_READ_ONLY },
{ 0, 0, 0 },
{ 0, 0, 0 },
},
&xTaskBufferled
};
int main( void )
{
SCB->VTOR = (unsigned long)_sfixed;
sysclk_init();
BRD_clk_init();
BRD_default_io_init();
BRD_init_bus_ios_DBG_UART();
uart_dma_init(uart_dma, config);
PW_enable_maintain_power();
//ioport_set_pin_peripheral_mode(PIO_PA5_IDX, IOPORT_MODE_MUX_A); // DEBUG_UART_RXD
ioport_set_pin_mode(PIO_PA5_IDX, IOPORT_MODE_MUX_A);
ioport_disable_pin(PIO_PA5_IDX);
//ioport_set_pin_peripheral_mode(PIO_PA6_IDX, IOPORT_MODE_MUX_A); // DEBUG_UART_TXD
ioport_set_pin_mode(PIO_PA6_IDX, IOPORT_MODE_MUX_A);
ioport_disable_pin(PIO_PA6_IDX);
arch_ioport_init();
/* Set input OPEN_DRAIN */
pio_set_input(PB_PIN_PIO, POWER_BUTTON, PIO_OPENDRAIN | PIO_DEBOUNCE);
//pio_set_input(PB_PIN_PIO, TRIGGER_BUTTON, PIO_OPENDRAIN | PIO_DEBOUNCE);
/* Set GPIOs interruption */
pio_handler_set(PB_PIN_PIO, PB_PIN_ID, POWER_BUTTON, PIO_OPENDRAIN | PWR_BUT_INT_PRESS, userButtonPressedHandler);
//pio_handler_set(PB_PIN_PIO, PB_PIN_ID, TRIGGER_BUTTON, PIO_OPENDRAIN | TRI_BUT_INT_PRESS, BUT_trigger_press);
//portENABLE_INTERRUPTS();
/* Configure & Enable PIO line interrupts. */
pio_enable_interrupt(PB_PIN_PIO, POWER_BUTTON);
//pio_enable_interrupt(PB_PIN_PIO, TRIGGER_BUTTON);
//Les priorités autorisés sont définies dans FreeRTOSConfig.h et vont de 10 à 15
NVIC_SetPriority((IRQn_Type)PB_PIN_ID, 15);
/* Enable PIO controller IRQs. */
NVIC_EnableIRQ((IRQn_Type)PB_PIN_ID);
uart_dma_tx_blocking_flush(uart_dma);
xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup);
if( xEventGroupHandle == NULL ){
uart_dma_write(uart_dma, "Echec Creation Groupe S ", sizeof(char)*24);
}
else {
uart_dma_write(uart_dma, "Succes creation groupe S ", sizeof(char)*25);
}
/*Création des tâches*/
/* Create the task defined by xTaskDefinition. NULL is used as the second
parameter as a task handle is not required. */
xTaskCreateRestrictedStatic( &xTaskDefinition1, &xTask1 );
xTaskCreateRestrictedStatic( &xTaskDefinition2, &xTask2 );
xTaskCreateRestrictedStatic( &xTaskDefinitionUart, &xTaskuart );
xTaskCreateRestrictedStatic( &xTaskDefinitionled, &xStartLedTask );
Timer_idwdt = xTimerCreateStatic("Timer watchdog", (11000/portTICK_PERIOD_MS), pdTRUE, NULL, TimerCallbackwdt, &xTimerBufferwdt );
Timer_id = xTimerCreateStatic("Timer",(8000/portTICK_PERIOD_MS), pdTRUE, NULL, TimerCallback, &xTimerBuffer);
/*Timer_idwdt = xTimerCreate("Timer", (11000/portTICK_PERIOD_MS), pdTRUE, NULL, TimerCallbackwdt);
Timer_id = xTimerCreate("Timer", (8000/portTICK_PERIOD_MS), pdTRUE, NULL, TimerCallback);*/
xTimerStart (Timer_id, 0);
xTimerStart (Timer_idwdt, 0);
//xTaskCreate( taskuart, "Task Uart", configMINIMAL_STACK_SIZE, NULL, 4, &xTaskuart);
/*if( Timer_id == NULL )
{
uart_dma_write(uart_dma, "Timer null ", sizeof(char)*12);
}
vTimerSetTimerID( Timer_id, ( void * ) 0 );
/* Start the scheduler itself. */
vTaskStartScheduler();
return 0;
}
/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
used by the Idle task. */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
configSTACK_DEPTH_TYPE *puxIdleTaskStackSize )
{
/* If the buffers to be provided to the Idle task are declared inside this
function then they must be declared static - otherwise they will be allocated on
the stack and so not exists after this function exits. */
static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
/* Pass out a pointer to the StaticTask_t structure in which the Idle task's
state will be stored. */
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
/* Pass out the array that will be used as the Idle task's stack. */
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*puxIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
/*-----------------------------------------------------------*/
/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
application must provide an implementation of vApplicationGetTimerTaskMemory()
to provide the memory that is used by the Timer service task. */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
configSTACK_DEPTH_TYPE *puxTimerTaskStackSize )
{
/* If the buffers to be provided to the Timer task are declared inside this
function then they must be declared static - otherwise they will be allocated on
the stack and so not exists after this function exits. */
static StaticTask_t xTimerTaskTCB;
static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
/* Pass out a pointer to the StaticTask_t structure in which the Timer
task's state will be stored. */
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
/* Pass out the array that will be used as the Timer task's stack. */
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
*puxTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
void vApplicationMallocFailedHook( void )
{
/* vApplicationMallocFailedHook() will only be called if
configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
function that will get called if a call to pvPortMalloc() fails.
pvPortMalloc() is called internally by the kernel whenever a task, queue,
timer or semaphore is created. It is also called by various parts of the
demo application. If heap_1.c or heap_2.c are used, then the size of the
heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
to query the size of free heap space that remains (although it does not
provide information on how the remaining heap might be fragmented). */
taskDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
void vApplicationIdleHook( void )
{
/* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
task. It is essential that code added to this hook function never attempts
to block in any way (for example, call xQueueReceive() with a block time
specified, or call vTaskDelay()). If the application makes use of the
vTaskDelete() API function (as this demo application does) then it is also
important that vApplicationIdleHook() is permitted to return to its calling
function, because it is the responsibility of the idle task to clean up
memory allocated by the kernel to any task that has since been deleted. */
//uart_dma_write(uart_dma, "I am the idle ", sizeof(char)*15);
}
/*-----------------------------------------------------------*/
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
{
( void ) pcTaskName;
( void ) pxTask;
while (uart_dma_tx_get_frame_buffer(uart_dma)==NULL) {
vTaskDelay(1000/portTICK_PERIOD_MS);
}
uart_dma_write(uart_dma, "Stack overflow détecté ", sizeof(char)*26);
/* Run time stack overflow checking is performed if
configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
function is called if a stack overflow is detected. */
taskDISABLE_INTERRUPTS();
vApplicationIdleHook();
for( ;; );
}
/*-----------------------------------------------------------*/
void vApplicationTickHook( void )
{
/* This function will be called by each tick interrupt if
configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be
added here, but the tick hook is called from an interrupt context, so
code must not attempt to block, and only the interrupt safe FreeRTOS API
functions can be used (those that end in FromISR()). */
}
/*-----------------------------------------------------------*/
//=============== syscall redirection =============//
// STDOUT/STDERR are linked to DEBUG_UART
extern int _write(int file, const char* ptr, int len);
extern int _write(int file, const char* ptr, int len) {
if ((file != 1) && (file != 2) && (file != 3)) {
return -1;
}
// copy input buffer to tx ring buffer
//! use critical section to keep message sentence ordered (not fragmented) when 'log' called from IRQ
cpu_irq_enter_critical(); //-------------------------
for (int i = 0; i < len; i++) {
uint8_t c = ptr[i];
const bool pushed = rb_tx_dbg_uart_push(&tx_ring_buffer, &c);
if (false == pushed) {
// ring buffer full -> do not push end buffer -> bytes are 'lost'
break;
}
}
cpu_irq_leave_critical(); //-------------------------
try_to_pop_ring_buffer_to_uart_dma();
#if 0 // 1 : flush mode -> wait dma and ring buffer are sent // for used for debug
uart_dma_tx_blocking_flush(uart_dma);
#endif
return len;
}
//=============== syscall redirection =============//
extern int _read(int file, char* ptr, int len);
extern int _read(int file, char* ptr, int len) {
(void)file;
(void)ptr;
(void)len;
return 0;
}