init new demo

This commit is contained in:
Alwin Berger 2023-10-05 16:12:46 +02:00
parent 95bb6f0bd0
commit 3c5043df42
2 changed files with 530 additions and 0 deletions

View File

@ -99,6 +99,11 @@ ifeq ($(WATERSV2_DEMO), 1)
CFLAGS := -DmainCREATE_WATERS_DEMO=1
else
ifeq ($(MAN_DEMO), 1)
SOURCE_FILES += main_manual.c
CFLAGS := -DmainCREATE_WATERS_DEMO=1
else
ifeq ($(BRANCHLESS_DEMO), 1)
SOURCE_FILES += main_micro_branchless.c
@ -129,6 +134,7 @@ endif
endif
endif
endif
endif
ifeq ($(INTERRUPT_ACTIVATION), 1)
CFLAGS += -D INTERRUPT_ACTIVATION=1

View File

@ -0,0 +1,524 @@
/*
* FreeRTOS V202111.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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include <stdio.h>
/*
TMR Demo with retry
prvSamplerTask will read 4 Bytes of Input into a buffer, unlocks xMutexInput
prvReplicateA and prvReplicateB wait on xMutexInput to average the Inputs and
sum up all numbers up to the Input.
ReplicateA will fail if mod 11 = 0, but only once
ReplicateB will fail if mod 12 = 0
ReplicateC also exists and will never fail, does not run by default
Each Replicate outputs to it's own queue
prvVoterTask will wait on ReplicateA&B
If they disagree ReplicateC will be started by mutex.
If all the Replicates disagree now the sampler will be engaged once more
*/
#define GLOBAL_WCET_MULT 16 // Multiplier to increase all waiting periods to make the schedule more tight an force preemptions
#include "arbitrary_loads.c"
__attribute__((noinline)) static void trigger_Qemu_break( void )
{
puts("Trigger");
while (1) {
}
}
// if this macro is set, the code will be modified to produce the worst case
// #define DEBUG_WCET(A) {A}
// #define WCET_END(A)
#define WCET_END(A) {A}
#ifdef DEBUG_WCET
#define DEBUG_VAL(X,D) (D)
// #define WCET_CLAMP(X, LB, UB, LABEL) PRINT_TIME(UB,LABEL)
#define WCET_CLAMP(X, LB, UB, LABEL) PRINT_TIME(CLAMP(X,LB,UB),LABEL)
#else
#define DEBUG_VAL(X,D) (X)
#define WCET_CLAMP(X, LB, UB, LABEL) PRINT_TIME(CLAMP(X,LB,UB),LABEL)
#define DEBUG_WCET(A)
#endif
// Begin Input Stuff
volatile unsigned char FUZZ_INPUT[4096] = {0xa,0xb,0xc,0xd,0xe,0xf};
volatile uint32_t FUZZ_LENGTH = 4096;
volatile uint32_t FUZZ_POINTER = 0;
// Read the Byte of Input, if the Input is exausted trigger the breakpoint instead
static unsigned char fuzz_char_next(void) {
// printf("Get next Input from %lx \n",FUZZ_INPUT);
if (1 || FUZZ_POINTER < FUZZ_LENGTH) {
FUZZ_POINTER++;
// printf("Input no. %d %x\n",FUZZ_POINTER-1,FUZZ_INPUT[FUZZ_POINTER-1]);
return FUZZ_INPUT[FUZZ_POINTER-1];
} else {
// puts("End of Input");
// Exausted inputs early
trigger_Qemu_break();
}
}
static uint16_t fuzz_short_next(void) {
unsigned char field[2];
field[0]=fuzz_char_next();
field[1]=fuzz_char_next();
uint16_t* sf = (uint16_t*) field;
return *sf;
}
static uint32_t fuzz_long_next(void) {
unsigned char field[4];
field[0]=fuzz_char_next();
field[1]=fuzz_char_next();
field[2]=fuzz_char_next();
field[3]=fuzz_char_next();
uint32_t* sf = (uint32_t*) field;
return *sf;
}
// End Input Stuff
static void prvC1T1( void * pvParameters );
static void prvC1T2( void * pvParameters );
static void prvC1T3( void * pvParameters );
static void prvC1T4( void * pvParameters );
static void prvC2T1( void * pvParameters );
static void prvC2T2( void * pvParameters );
static void prvC2T3( void * pvParameters );
static void prvC3T1( void * pvParameters );
static void prvC3T2( void * pvParameters );
static void prvC3T3( void * pvParameters );
// Priorities using rate-monotonic scheduling
// ties are decided favoring short wcets
// Chain1: 579 -> 1009 -> 1129 -> 416
// 10ms 10ms 10ms 10ms
// Chain2: 31 -> 78 -> 400
// 100ms 10ms 2ms
// Chain3: 397 -> 90 -> 1107
// spor 2ms 50ms
// cross-chain effect ideas:
// RM + sort by chains
#define mainTASK_C1T1_PRIO ( tskIDLE_PRIORITY + 5 )
#define mainTASK_C1T2_PRIO ( tskIDLE_PRIORITY + 5 )
#define mainTASK_C1T3_PRIO ( tskIDLE_PRIORITY + 5 )
#define mainTASK_C1T4_PRIO ( tskIDLE_PRIORITY + 5 )
#define mainTASK_C2T1_PRIO ( tskIDLE_PRIORITY + 1 )
#define mainTASK_C2T2_PRIO ( tskIDLE_PRIORITY + 5 )
#define mainTASK_C2T3_PRIO ( tskIDLE_PRIORITY + 9 )
#define mainTASK_C3T1_PRIO ( tskIDLE_PRIORITY + 10 )
#define mainTASK_C3T2_PRIO ( tskIDLE_PRIORITY + 8 )
#define mainTASK_C3T3_PRIO ( tskIDLE_PRIORITY + 2 )
// RM with pref for short
// #define mainTASK_C2T1_PRIO ( tskIDLE_PRIORITY + 1 )
// #define mainTASK_C2T2_PRIO ( tskIDLE_PRIORITY + 5 )
// #define mainTASK_C3T2_PRIO ( tskIDLE_PRIORITY + 8 )
// #define mainTASK_C3T1_PRIO ( tskIDLE_PRIORITY + 10 )
// #define mainTASK_C2T3_PRIO ( tskIDLE_PRIORITY + 9 )
// #define mainTASK_C1T4_PRIO ( tskIDLE_PRIORITY + 4 )
// #define mainTASK_C1T1_PRIO ( tskIDLE_PRIORITY + 7 )
// #define mainTASK_C1T2_PRIO ( tskIDLE_PRIORITY + 6 )
// #define mainTASK_C3T3_PRIO ( tskIDLE_PRIORITY + 2 )
// #define mainTASK_C1T3_PRIO ( tskIDLE_PRIORITY + 3 )
// Same Prio
// #define mainTASK_C2T1_PRIO ( tskIDLE_PRIORITY + 1 )
// #define mainTASK_C2T2_PRIO ( tskIDLE_PRIORITY + 7 )
// #define mainTASK_C3T2_PRIO ( tskIDLE_PRIORITY + 8 )
// #define mainTASK_C3T1_PRIO ( tskIDLE_PRIORITY + 10 )
// #define mainTASK_C2T3_PRIO ( tskIDLE_PRIORITY + 9 )
// #define mainTASK_C1T4_PRIO ( tskIDLE_PRIORITY + 7 )
// #define mainTASK_C1T1_PRIO ( tskIDLE_PRIORITY + 7 )
// #define mainTASK_C1T2_PRIO ( tskIDLE_PRIORITY + 7 )
// #define mainTASK_C3T3_PRIO ( tskIDLE_PRIORITY + 2 )
// #define mainTASK_C1T3_PRIO ( tskIDLE_PRIORITY + 7 )
#define TASK_C1T1_MESSAGE "11"
#define TASK_C1T2_MESSAGE "12"
#define TASK_C1T3_MESSAGE "13"
#define TASK_C1T4_MESSAGE "14"
#define TASK_C2T1_MESSAGE "21"
#define TASK_C2T2_MESSAGE "22"
#define TASK_C2T3_MESSAGE "23"
#define TASK_C3T1_MESSAGE "31"
#define TASK_C3T2_MESSAGE "32"
#define TASK_C3T3_MESSAGE "33"
// Handles for direct messages
static TaskHandle_t xC2T1 = NULL;
static TaskHandle_t xC2T2 = NULL;
static TaskHandle_t xC3T2 = NULL;
static TaskHandle_t xC3T1 = NULL;
static TaskHandle_t xC2T3 = NULL;
static TaskHandle_t xC1T4 = NULL;
static TaskHandle_t xC1T1 = NULL;
static TaskHandle_t xC1T2 = NULL;
static TaskHandle_t xC3T3 = NULL;
static TaskHandle_t xC1T3 = NULL;
void main_waters( void )
{
// puts("Main function");
/* Start the two tasks as described in the comments at the top of this
* file. */
xTaskCreate( prvC2T1, /* The function that implements the task. */
"2-1", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
NULL, /* The parameter passed to the task - not used in this case. */
mainTASK_C2T1_PRIO, /* The priority assigned to the task. */
&xC2T1 ); /* The task handle is not required, so NULL is passed. */
xTaskCreate( prvC2T2, /* The function that implements the task. */
"2-2", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
NULL, /* The parameter passed to the task - not used in this case. */
mainTASK_C2T2_PRIO, /* The priority assigned to the task. */
&xC2T2 ); /* The task handle is not required, so NULL is passed. */
xTaskCreate( prvC3T2,
"3-2",
configMINIMAL_STACK_SIZE,
NULL,
mainTASK_C3T2_PRIO,
&xC3T2 );
// This task is supposed to be sporadic
xTaskCreate( prvC3T1,
"async_3-1",
configMINIMAL_STACK_SIZE,
NULL,
mainTASK_C3T1_PRIO,
&xC3T1 );
xTaskCreate( prvC2T3,
"2-3",
configMINIMAL_STACK_SIZE,
NULL,
mainTASK_C2T3_PRIO,
&xC2T3 );
xTaskCreate( prvC1T4,
"1-4",
configMINIMAL_STACK_SIZE,
NULL,
mainTASK_C1T4_PRIO,
&xC1T4 );
xTaskCreate( prvC1T1,
"1-1",
configMINIMAL_STACK_SIZE,
NULL,
mainTASK_C1T1_PRIO,
&xC1T1 );
xTaskCreate( prvC1T2,
"1-2",
configMINIMAL_STACK_SIZE,
NULL,
mainTASK_C1T2_PRIO,
&xC1T2 );
xTaskCreate( prvC3T3,
"3-3",
configMINIMAL_STACK_SIZE,
NULL,
mainTASK_C3T3_PRIO,
&xC3T3 );
xTaskCreate( prvC1T3,
"1-3",
configMINIMAL_STACK_SIZE,
NULL,
mainTASK_C1T3_PRIO,
&xC1T3 );
/* Start the tasks and timer running. */
// puts("Start scheduler");
vTaskStartScheduler();
/* If all is well, the scheduler will now be running, and the following
* line will never be reached. If the following line does execute, then
* there was insufficient FreeRTOS heap memory available for the Idle and/or
* timer tasks to be created. See the memory management section on the
* FreeRTOS web site for more details on the FreeRTOS heap
* http://www.freertos.org/a00111.html. */
for( ; ; )
{
}
}
// Chain2: 31 -> 78 -> 400
static void prvC2T1( void * pvParameters ) {
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = 100 / portTICK_PERIOD_MS;
int period_counter = 2;
for( ;; ){
WCET_END({if (--period_counter==0) {puts("End");}}) // Debugging
// Actions --------------------------------------
// Exectime: f(x) = x
// Output: g(x) = x % 2
volatile uint16_t x = fuzz_short_next();
DEBUG_WCET(x=48940;)
WCET_CLAMP(x, 0, 48940, TASK_C2T1_MESSAGE)
WCET_END({trigger_Qemu_break();})
xTaskNotify(xC2T2, DEBUG_VAL(x % 2, 1), eSetValueWithOverwrite);
// ---------------------------------------------
vTaskDelayUntil( &xLastWakeTime, xFrequency );}// Wait for the next cycle.
}
// Chain2: 31 -> 78 -> 400
static void prvC2T2( void * pvParameters ) {
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = 10 / portTICK_PERIOD_MS;
for( ;; ){
// Actions --------------------------------------
// Exectime: f(x,y) = c + y*20000 + rng(x)*50000
// Output: g(x,y) = y * (x % 4)
uint16_t x = fuzz_short_next();
int y = ulTaskNotifyTake(pdTRUE, 0);
volatile int torun = 6035;
if (y > 0) {
torun += 20000;
}
if (DEBUG_VAL(CHANCE_1_IN_POWOF2(x, 5), 1)) {
torun += 50000;
}
WCET_CLAMP(torun, 0, 76035, TASK_C2T2_MESSAGE)
xTaskNotify(xC2T3, DEBUG_VAL(y * (x % 4), 2), eSetValueWithOverwrite);
// ---------------------------------------------
vTaskDelayUntil( &xLastWakeTime, xFrequency );}
}
// Chain2: 31 -> 78 -> 400
static void prvC2T3( void * pvParameters ) {
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = 2 / portTICK_PERIOD_MS;
for( ;; ){
// Actions --------------------------------------
// Exectime: f(x,y) = rng(x)*y*c or (rng(x) % 1000)
uint32_t x = fuzz_long_next();
int y = ulTaskNotifyTake(pdTRUE, 0);
volatile int torun = 0;
if (y == 2 && DEBUG_VAL(CHANCE_1_IN_POWOF2(x, 2), 1)) {
torun = 1765;
} else {
torun = RNG_FROM(x) % 1000;
DEBUG_WCET(torun=999;)
}
WCET_CLAMP(torun, 0, 1765, TASK_C2T3_MESSAGE)
// ---------------------------------------------
vTaskDelayUntil( &xLastWakeTime, xFrequency );}
}
//==================================================================
// Chain3: 397 -> 90 -> 1107
static void prvC3T1( void * pvParameters ) {
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = 1 / portTICK_PERIOD_MS;
for( ;; ){
// Exectime: f(x) = x
// Output: g(x) = x % 2
volatile uint16_t x = fuzz_short_next();
DEBUG_WCET(x=5830;)
WCET_CLAMP(x, 0, 5830, TASK_C3T1_MESSAGE);
xTaskNotify(xC3T2, DEBUG_VAL(x & 0x1, 0), eSetValueWithOverwrite);
// 3 different activation strategies -------------
// activate sporadically from interrupts
#ifdef INTERRUPT_ACTIVATION
ulTaskNotifyTake(pdTRUE,portMAX_DELAY);
#else
// activate with worst possible frequency (700us, but tick resolution is too low)
vTaskDelayUntil( &xLastWakeTime, xFrequency );
#endif
// wait pseudo random many ticks
// vTaskDelayUntil( &xLastWakeTime, CLAMP(RNG, 1, 100) / portTICK_PERIOD_MS );
}
}
// Chain3: 397 -> 90 -> 1107
static void prvC3T2( void * pvParameters ) {
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = 2 / portTICK_PERIOD_MS;
for( ;; ){
// char buf[400];
// vTaskList(buf);
// puts(buf);
// Actions --------------------------------------
// Exectime: f(x) = c + x
// Output: g(x) = x % 4
int y = ulTaskNotifyTake(pdTRUE, 0);
volatile uint16_t x = fuzz_short_next();
DEBUG_WCET(x=20048;)
int torun = 0;
if (y) {
torun = CLAMP(x, 5000, 10000);
} else {
torun = CLAMP(x, 0, 20045);
}
WCET_CLAMP(torun, 0, 20045, TASK_C3T2_MESSAGE)
xTaskNotify(xC3T3, DEBUG_VAL(x % 4, 0), eSetValueWithOverwrite);
// ---------------------------------------------
vTaskDelayUntil( &xLastWakeTime, xFrequency );}
}
// Chain3: 397 -> 90 -> 1107
static void prvC3T3( void * pvParameters ) {
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = 50 / portTICK_PERIOD_MS;
for( ;; ){
// Actions --------------------------------------
// Exectime: f(x) = c - x*y
volatile uint16_t x = fuzz_short_next();
DEBUG_WCET(x=0;)
int y = ulTaskNotifyTake(pdTRUE, 0);
int torun = 76865-((int)x)*y;
WCET_CLAMP(torun, 10000, 76865, TASK_C3T3_MESSAGE)
// ---------------------------------------------
vTaskDelayUntil( &xLastWakeTime, xFrequency );}
}
//==================================================================
// Chain1: 579 -> 1009 -> 1129 -> 416
static void prvC1T1( void * pvParameters ) {
// int period = 5;
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = 10 / portTICK_PERIOD_MS;
for( ;; ){
// if (--period==0) {puts("End");} // Debugging Marker
// Actions --------------------------------------
// Exectime: f(x) = x>>8 & 0x0fff
// Output: g(x) = x % 8
uint32_t x = fuzz_long_next();
volatile int torun = (x>>8) & 0x0fff;
DEBUG_WCET(torun = 0x0fff;)
WCET_CLAMP(torun, 500, 2460, TASK_C1T1_MESSAGE)
xTaskNotify(xC1T2, DEBUG_VAL(x % 8, 0), eSetValueWithOverwrite);
// ---------------------------------------------
vTaskDelayUntil( &xLastWakeTime, xFrequency );}
}
// Chain1: 579 -> 1009 -> 1129 -> 416
static void prvC1T2( void * pvParameters ) {
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = 10 / portTICK_PERIOD_MS;
for( ;; ){
// Actions --------------------------------------
// Exectime: f(x,y) = if x%8 == y ? 40000+x : x (<40k)
// Output: g(x) = x % 8 == y
uint16_t x = fuzz_short_next();
int y = ulTaskNotifyTake(pdTRUE, 0);
volatile int torun = 0;
if (x % 8 == y) {
torun = 40000 + x;
} else {
torun = CLAMP(x, 0, 40000);
}
DEBUG_WCET(torun = 51485;)
WCET_CLAMP(torun, 0, 51485, TASK_C1T2_MESSAGE)
xTaskNotify(xC1T3, DEBUG_VAL(x % 8 == y, 1), eSetValueWithOverwrite);
// ---------------------------------------------
vTaskDelayUntil( &xLastWakeTime, xFrequency );}
}
// Chain1: 579 -> 1009 -> 1129 -> 416
static void prvC1T3( void * pvParameters ) {
int period_counter = 2;
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = 10 / portTICK_PERIOD_MS;
for( ;; ){
// if (--period_counter==0) {puts("End");}
// Actions --------------------------------------
// Exectime: f(x,y) = if y && rng(x) ? c1+x : c2+x
// Output: g(x) = y && rng(x)
// longmax - shortmax: 39505
// most likely long case, which causes a short case in next task
volatile uint32_t x = (uint32_t)fuzz_short_next();
int y = ulTaskNotifyTake(pdTRUE, 0);
DEBUG_WCET(
static char flag=0;
if (flag++ == 0 | flag == 5 | flag == 8 | flag == 9) {x = 65529;}
else {x = 0xffff;}
)
volatile int do_short_run = (y + CHANCE_1_IN_POWOF2(x, 5)) == 1; // XOR
int torun = 0;
if (do_short_run > 0) {
torun = 40000 + x;
} else {
torun = 80000 + x;
}
WCET_CLAMP(torun, 0, 145040, TASK_C1T3_MESSAGE)
xTaskNotify(xC1T4, do_short_run, eSetValueWithOverwrite);
// ---------------------------------------------
vTaskDelayUntil( &xLastWakeTime, xFrequency );}
}
// Chain1: 579 -> 1009 -> 1129 -> 416
static void prvC1T4( void * pvParameters ) {
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = 10 / portTICK_PERIOD_MS;
for( ;; ){
// Actions --------------------------------------
// Exectime: f(x,y) = if y ? c1+2*x : c2-x
// longmax - shortmax: 76955
volatile uint32_t x = (uint32_t)fuzz_short_next();
int y = ulTaskNotifyTake(pdTRUE, 0);
volatile int torun = 0;
if (y) {
DEBUG_WCET(x=0xffff;)
torun = x*3;
} else {
DEBUG_WCET(x=0;)
torun = 50000 - CLAMP_CEILING(x, 50000);
}
WCET_CLAMP(torun, 10000, 126955, TASK_C1T4_MESSAGE)
// ---------------------------------------------
vTaskDelayUntil( &xLastWakeTime, xFrequency );}
}
void vWatersIdleFunction() {
for (int i; i<1000; i++) {
puts("0 ");
}
}
void isr_starter( void )
{
puts("Interrupt");
if (prvC3T1) {
vTaskNotifyGiveFromISR(xC3T1, NULL);
}
}
/*-----------------------------------------------------------*/