From d1fca2842eda8bf28efe17cd7505dddec69ff321 Mon Sep 17 00:00:00 2001 From: Alwin Berger Date: Tue, 10 Sep 2024 15:08:57 +0200 Subject: [PATCH] partitioned inputs, hyhperperiod limits, link markers, new example --- .../Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile | 21 ++ FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main.c | 4 + .../CORTEX_M3_MPS2_QEMU_GCC/main_release.c | 329 ++++++++++++++++++ .../CORTEX_M3_MPS2_QEMU_GCC/main_waters.c | 136 +++++--- .../CORTEX_M3_MPS2_QEMU_GCC/main_watersv2.c | 141 +++++--- .../scripts/mps2_m3.ld | 12 +- 6 files changed, 559 insertions(+), 84 deletions(-) create mode 100644 FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_release.c diff --git a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile index 36098ae8..f98cbed3 100644 --- a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile +++ b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/Makefile @@ -94,11 +94,21 @@ ifeq ($(WATERS_DEMO), 1) CFLAGS := -DmainCREATE_WATERS_DEMO=1 else +ifeq ($(WATERSPART_DEMO), 1) + SOURCE_FILES += main_waterspart.c + + CFLAGS := -DmainCREATE_WATERS_DEMO=1 +else ifeq ($(WATERSV2_DEMO), 1) SOURCE_FILES += main_watersv2.c CFLAGS := -DmainCREATE_WATERS_DEMO=1 else +ifeq ($(WATERSPARTV2_DEMO), 1) + SOURCE_FILES += main_waterspartv2.c + + CFLAGS := -DmainCREATE_WATERS_DEMO=1 +else ifeq ($(MAN_DEMO), 1) SOURCE_FILES += main_manual.c @@ -133,6 +143,11 @@ ifdef GEN_DEMO SOURCE_FILES += main_gen_$(GEN_DEMO).c CFLAGS := -DmainCREATE_GEN_DEMO=1 +else +ifeq ($(RELEASE_DEMO), 1) + SOURCE_FILES += main_release.c + + CFLAGS := -DmainCREATE_RELEASE_DEMO=1 else SOURCE_FILES += main_blinky.c @@ -153,10 +168,16 @@ endif endif endif endif +endif +endif +endif ifeq ($(INTERRUPT_ACTIVATION), 1) CFLAGS += -D INTERRUPT_ACTIVATION=1 endif +ifeq ($(PARTITION_INPUT), 1) + CFLAGS += -D PARTITION_INPUT=1 +endif DEFINES := -DQEMU_SOC_MPS2 -DHEAP3 diff --git a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main.c b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main.c index af2d04aa..53331ce6 100644 --- a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main.c +++ b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main.c @@ -115,6 +115,10 @@ int main() { main_interact(); } + #elif ( mainCREATE_RELEASE_DEMO == 1 ) + { + main_release(); + } #else { diff --git a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_release.c b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_release.c new file mode 100644 index 00000000..1436a05c --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_release.c @@ -0,0 +1,329 @@ +/* + * 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 +#include +#include +#include +#include +/* +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 20 // 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) { + } +} + +__attribute__((noinline)) static void trigger_job_done( void ) +{ + puts("Job Done"); + // trigger_Qemu_break(); +} +// 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} + +#define DO_TIME(X, Y) WASTE_USEC((X)) + +#ifdef DEBUG_WCET + #define DEBUG_VAL(X,D) (D) + #define WCET_CLAMP(X, LB, UB, LABEL) WASTE_NSEC(CLAMP(X,LB,UB),LABEL) +#else + #define DEBUG_VAL(X,D) (X) + #define WCET_CLAMP(X, LB, UB, LABEL) DO_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 (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 prvTask1( void * pvParameters ); +static void prvTask2( void * pvParameters ); +static void prvTask3( void * pvParameters ); +static void prvTask4( void * pvParameters ); +static void prvTask5( 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_1_PRIO ( tskIDLE_PRIORITY + 1 ) +#define mainTASK_2_PRIO ( tskIDLE_PRIORITY + 2 ) +#define mainTASK_3_PRIO ( tskIDLE_PRIORITY + 3 ) +#define mainTASK_4_PRIO ( tskIDLE_PRIORITY + 4 ) +#define mainTASK_5_PRIO ( tskIDLE_PRIORITY + 5 ) + +#define TASK_1_MESSAGE "01" +#define TASK_2_MESSAGE "02" +#define TASK_3_MESSAGE "03" +#define TASK_4_MESSAGE "04" +#define TASK_5_MESSAGE "05" + +// Handles for direct messages +static TaskHandle_t xTask1 = NULL; +static TaskHandle_t xTask2 = NULL; +static TaskHandle_t xTask3 = NULL; +static TaskHandle_t xTask4 = NULL; +static TaskHandle_t xTask5 = NULL; + +static TickType_t initial_release_time = 0; + +static SemaphoreHandle_t xMutex; + +void main_release( void ) +{ + xMutex = xSemaphoreCreateBinary(); + xSemaphoreGive(xMutex); + // puts("Main function"); + /* Start the two tasks as described in the comments at the top of this + * file. */ + xTaskCreate( prvTask1, /* The function that implements the task. */ + "T1", /* 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_1_PRIO, /* The priority assigned to the task. */ + &xTask1 ); /* The task handle is not required, so NULL is passed. */ + + xTaskCreate( prvTask2, /* The function that implements the task. */ + "T2", /* 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_2_PRIO, /* The priority assigned to the task. */ + &xTask2 ); /* The task handle is not required, so NULL is passed. */ + + // This task is supposed to be sporadic + xTaskCreate( prvTask3, + "T3", + configMINIMAL_STACK_SIZE, + NULL, + mainTASK_3_PRIO, + &xTask3 ); + + xTaskCreate( prvTask4, + "T4", + configMINIMAL_STACK_SIZE, + NULL, + mainTASK_4_PRIO, + &xTask4 ); + + // This task is supposed to be sporadic + xTaskCreate( prvTask5, + "T5", + configMINIMAL_STACK_SIZE, + NULL, + mainTASK_5_PRIO, + &xTask5 ); + + /* 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( ; ; ) + { + } +} + +static void prvTask1( void * pvParameters ) { + TickType_t xLastWakeTime = initial_release_time; + const TickType_t xFrequency = 100 / portTICK_PERIOD_MS; + for( ;; ){ + // Actions -------------------------------------- + volatile uint16_t x = fuzz_short_next(); + WCET_CLAMP(x, 8000, 10000, TASK_1_MESSAGE) + xTaskNotify(xTask2, DEBUG_VAL(x % 2, 1), eSetValueWithOverwrite); + // --------------------------------------------- + trigger_job_done(); + trigger_Qemu_break(); + xTaskDelayUntil( &xLastWakeTime, xFrequency );}// Wait for the next cycle. +} + +static void prvTask2( void * pvParameters ) { + TickType_t xLastWakeTime = initial_release_time; + const TickType_t xFrequency = 50 / portTICK_PERIOD_MS; + for( ;; ){ + // Actions -------------------------------------- + uint16_t x = fuzz_short_next(); + DO_TIME(1000, TASK_2_MESSAGE) + xSemaphoreTake(xMutex, portMAX_DELAY); + volatile int torun = 2000; + if (DEBUG_VAL(CHANCE_1_IN_POWOF2(x, 5), 1)) { + torun += 2000; + } + int y = ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + xSemaphoreGive(xMutex); + // --------------------------------------------- + trigger_job_done(); + xTaskDelayUntil( &xLastWakeTime, xFrequency );} +} + +static void prvTask3( void * pvParameters ) { + TickType_t xLastWakeTime = initial_release_time; + const TickType_t xFrequency = 25 / portTICK_PERIOD_MS; + trigger_job_done(); // The first job instance just waits for an activation + for( ;; ){ + // Actions -------------------------------------- + int y = ulTaskNotifyTake(pdTRUE, portMAX_DELAY); // sporadic + xSemaphoreTake(xMutex, portMAX_DELAY); + volatile uint16_t x = fuzz_short_next(); + int torun = 0; + if (y) { + torun = CLAMP(x, 5000, 8000); + } else { + torun = CLAMP(x, 0, 12000); + } + DO_TIME(torun, TASK_3_MESSAGE) + xSemaphoreGive(xMutex); + // --------------------------------------------- + trigger_job_done(); + trigger_Qemu_break(); + // xTaskDelayUntil( &xLastWakeTime, xFrequency ); + } +} + +static void prvTask4( void * pvParameters ) { + initial_release_time = xTaskGetTickCount(); // The highest priority task sets the initial time + TickType_t xLastWakeTime = initial_release_time; + const TickType_t xFrequency = 10 / portTICK_PERIOD_MS; + for( ;; ){ + // Actions -------------------------------------- + volatile uint16_t x = fuzz_short_next(); + WCET_CLAMP(x, 1000, 2000, TASK_4_MESSAGE) + // --------------------------------------------- + trigger_job_done(); + xTaskDelayUntil( &xLastWakeTime, xFrequency );} +} + +static void prvTask5( void * pvParameters ) { + TickType_t xLastWakeTime = 0; + const TickType_t xFrequency = 5 / portTICK_PERIOD_MS; + trigger_job_done(); // The first job instance just waits for an activation + for( ;; ){ + // Actions -------------------------------------- + int y = ulTaskNotifyTake(pdTRUE, portMAX_DELAY); // sporadic + int succ = xSemaphoreTake(xMutex, 0); // try to take the mutex + if (succ == pdTRUE) { + // volatile uint16_t x = fuzz_short_next(); + uint16_t x = 2000; + int torun = 0; + torun = CLAMP(x, 0, 2000); + DO_TIME(torun, TASK_5_MESSAGE) + xSemaphoreGive(xMutex); + } else { + DO_TIME(50, TASK_5_MESSAGE) + } + // xTaskDelayUntil( &xLastWakeTime, xFrequency ); // enforce a minimum inter-arrival time + // --------------------------------------------- + trigger_job_done(); + // xTaskDelayUntil( &xLastWakeTime, portMAX_DELAY ); // enforce a minimum inter-arrival time + } +} + + +void vWatersIdleFunction() { + for (int i; i<1000; i++) { + puts("0 "); + } +} + +void ISR_0_Handler( void ) +{ + puts("Interrupt"); + if (xTask3) { + vTaskNotifyGiveFromISR(xTask3, NULL); + } +} + +void ISR_1_Handler( void ) +{ + puts("Interrupt"); + if (xTask5) { + vTaskNotifyGiveFromISR(xTask5, NULL); + } +} + +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_waters.c b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_waters.c index 781f654d..c56fe155 100644 --- a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_waters.c +++ b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_waters.c @@ -51,6 +51,12 @@ __attribute__((noinline)) static void trigger_Qemu_break( void ) while (1) { } } + +__attribute__((noinline)) static void trigger_job_done( void ) +{ + puts("Job Done"); + // trigger_Qemu_break(); +} // if this macro is set, the code will be modified to produce the worst case // #define DEBUG_WCET(A) {A} @@ -69,35 +75,48 @@ __attribute__((noinline)) static void trigger_Qemu_break( void ) #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; +#define PARTITION_INPUT +#define NUM_TASKS 10 +#define MAX_INPUT_BYTES 4096 +volatile unsigned char FUZZ_INPUT[MAX_INPUT_BYTES] = {}; +volatile int INPUT_POINTERS[NUM_TASKS] = {}; +volatile uint32_t FUZZ_LENGTH = MAX_INPUT_BYTES;// ignored // Read the Byte of Input, if the Input is exausted trigger the breakpoint instead -static unsigned char fuzz_char_next(void) { +static unsigned char fuzz_char_next(int tasknum) { +#ifdef PARTITION_INPUT + if (INPUT_POINTERS[tasknum] == 0) { + INPUT_POINTERS[tasknum] = tasknum * (MAX_INPUT_BYTES / NUM_TASKS); + } + if (INPUT_POINTERS[tasknum] >= (tasknum+1) * (MAX_INPUT_BYTES / NUM_TASKS)) { + trigger_Qemu_break(); + } + FUZZ_INPUT[INPUT_POINTERS[tasknum]++]; +#else // printf("Get next Input from %lx \n",FUZZ_INPUT); - if (FUZZ_POINTER < FUZZ_LENGTH) { - FUZZ_POINTER++; + if (INPUT_POINTERS[0] < FUZZ_LENGTH) { + INPUT_POINTERS[0]++; // printf("Input no. %d %x\n",FUZZ_POINTER-1,FUZZ_INPUT[FUZZ_POINTER-1]); - return FUZZ_INPUT[FUZZ_POINTER-1]; + return FUZZ_INPUT[INPUT_POINTERS[0]-1]; } else { // puts("End of Input"); // Exausted inputs early trigger_Qemu_break(); } +#endif } -static uint16_t fuzz_short_next(void) { +static uint16_t fuzz_short_next(int tasknum) { unsigned char field[2]; - field[0]=fuzz_char_next(); - field[1]=fuzz_char_next(); + field[0]=fuzz_char_next(tasknum); + field[1]=fuzz_char_next(tasknum); uint16_t* sf = (uint16_t*) field; return *sf; } -static uint32_t fuzz_long_next(void) { +static uint32_t fuzz_long_next(int tasknum) { unsigned char field[4]; - field[0]=fuzz_char_next(); - field[1]=fuzz_char_next(); - field[2]=fuzz_char_next(); - field[3]=fuzz_char_next(); + field[0]=fuzz_char_next(tasknum); + field[1]=fuzz_char_next(tasknum); + field[2]=fuzz_char_next(tasknum); + field[3]=fuzz_char_next(tasknum); uint32_t* sf = (uint32_t*) field; return *sf; } @@ -182,6 +201,22 @@ static TaskHandle_t xTask1009 = NULL; static TaskHandle_t xTask1107 = NULL; static TaskHandle_t xTask1129 = NULL; +static TickType_t initial_release_time = 0; + +#define HYPER_PERIOD 50 +#define SIMULATE_PERIODS 2 +static TaskHandle_t xTaskTimeSupervisor = NULL; +static void timing_supervisor_task( void * pvParameters ) { + initial_release_time = xTaskGetTickCount(); // The highest priority task sets the initial time + TickType_t xLastWakeTime = initial_release_time; + const TickType_t xFrequency = (SIMULATE_PERIODS * HYPER_PERIOD) / portTICK_PERIOD_MS; + trigger_job_done(); + xTaskDelayUntil( &xLastWakeTime, xFrequency ); + trigger_job_done(); + trigger_Qemu_break(); + for( ;; ){} +} + void main_waters( void ) { // puts("Main function"); @@ -258,6 +293,13 @@ void main_waters( void ) mainTASK_1129_PRIO, &xTask1129 ); + xTaskCreate( timing_supervisor_task, + "supervisor", + configMINIMAL_STACK_SIZE, + NULL, + configMAX_PRIORITIES - 1, + &xTaskTimeSupervisor ); + /* Start the tasks and timer running. */ // puts("Start scheduler"); @@ -276,7 +318,7 @@ void main_waters( void ) // Chain2: 31 -> 78 -> 400 static void prvTask31( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; const TickType_t xFrequency = 100 / portTICK_PERIOD_MS; int period_counter = 2; for( ;; ){ @@ -284,10 +326,11 @@ static void prvTask31( void * pvParameters ) { // Actions -------------------------------------- // Exectime: f(x) = x // Output: g(x) = x % 2 - volatile uint16_t x = fuzz_short_next(); + volatile uint16_t x = fuzz_short_next(0); DEBUG_WCET(x=48940;) WCET_CLAMP(x, 0, 48940, TASK_31_MESSAGE) - WCET_END({trigger_Qemu_break();}) + trigger_job_done(); + // WCET_END({trigger_Qemu_break();}) xTaskNotify(xTask78, DEBUG_VAL(x % 2, 1), eSetValueWithOverwrite); // --------------------------------------------- xTaskDelayUntil( &xLastWakeTime, xFrequency );}// Wait for the next cycle. @@ -295,13 +338,13 @@ static void prvTask31( void * pvParameters ) { // Chain2: 31 -> 78 -> 400 static void prvTask78( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; 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(); + uint16_t x = fuzz_short_next(1); int y = ulTaskNotifyTake(pdTRUE, 0); volatile int torun = 6035; if (y > 0) { @@ -313,17 +356,18 @@ static void prvTask78( void * pvParameters ) { WCET_CLAMP(torun, 0, 76035, TASK_78_MESSAGE) xTaskNotify(xTask400, DEBUG_VAL(y * (x % 4), 2), eSetValueWithOverwrite); // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } // Chain2: 31 -> 78 -> 400 static void prvTask400( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; 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(); + uint32_t x = fuzz_long_next(2); int y = ulTaskNotifyTake(pdTRUE, 0); volatile int torun = 0; if (y == 2 && DEBUG_VAL(CHANCE_1_IN_POWOF2(x, 2), 1)) { @@ -334,6 +378,7 @@ static void prvTask400( void * pvParameters ) { } WCET_CLAMP(torun, 0, 1765, TASK_400_MESSAGE) // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } @@ -341,17 +386,19 @@ static void prvTask400( void * pvParameters ) { // Chain3: 397 -> 90 -> 1107 static void prvTask397( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; const TickType_t xFrequency = 1 / portTICK_PERIOD_MS; for( ;; ){ - // Exectime: f(x) = x + // Exectime: f(x) = 20*x // Output: g(x) = x % 2 - volatile uint16_t x = fuzz_short_next(); + volatile uint16_t x = fuzz_char_next(3); + x *= 32; DEBUG_WCET(x=5830;) WCET_CLAMP(x, 0, 5830, TASK_397_MESSAGE); - xTaskNotify(xTask90, DEBUG_VAL(x & 0x1, 0), eSetValueWithOverwrite); + xTaskNotify(xTask90, DEBUG_VAL((x/32) & 0x1, 0), eSetValueWithOverwrite); // 3 different activation strategies ------------- // activate sporadically from interrupts + trigger_job_done(); #ifdef INTERRUPT_ACTIVATION ulTaskNotifyTake(pdTRUE,portMAX_DELAY); #else @@ -365,14 +412,15 @@ static void prvTask397( void * pvParameters ) { // Chain3: 397 -> 90 -> 1107 static void prvTask90( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; const TickType_t xFrequency = 2 / portTICK_PERIOD_MS; for( ;; ){ // Actions -------------------------------------- - // Exectime: f(x) = c + x + // Exectime: f(x) = c + 100*x // Output: g(x) = x % 4 int y = ulTaskNotifyTake(pdTRUE, 0); - volatile uint16_t x = fuzz_short_next(); + volatile uint16_t x = fuzz_char_next(4); + x *= 100; DEBUG_WCET(x=20048;) int torun = 0; if (y) { @@ -381,24 +429,26 @@ static void prvTask90( void * pvParameters ) { torun = CLAMP(x, 0, 20045); } WCET_CLAMP(torun, 0, 20045, TASK_90_MESSAGE) - xTaskNotify(xTask1107, DEBUG_VAL(x % 4, 0), eSetValueWithOverwrite); + xTaskNotify(xTask1107, DEBUG_VAL((x/100) % 4, 0), eSetValueWithOverwrite); // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } // Chain3: 397 -> 90 -> 1107 static void prvTask1107( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; const TickType_t xFrequency = 50 / portTICK_PERIOD_MS; for( ;; ){ // Actions -------------------------------------- // Exectime: f(x) = c - x*y - volatile uint16_t x = fuzz_short_next(); + volatile uint16_t x = fuzz_short_next(5); DEBUG_WCET(x=0;) int y = ulTaskNotifyTake(pdTRUE, 0); int torun = 76865-((int)x)*y; WCET_CLAMP(torun, 10000, 76865, TASK_1107_MESSAGE) // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } @@ -407,31 +457,32 @@ static void prvTask1107( void * pvParameters ) { // Chain1: 579 -> 1009 -> 1129 -> 416 static void prvTask579( void * pvParameters ) { // int period = 5; - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; 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(); + uint32_t x = fuzz_long_next(6); volatile int torun = (x>>8) & 0x0fff; DEBUG_WCET(torun = 0x0fff;) WCET_CLAMP(torun, 500, 2460, TASK_579_MESSAGE) xTaskNotify(xTask1009, DEBUG_VAL(x % 8, 0), eSetValueWithOverwrite); // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } // Chain1: 579 -> 1009 -> 1129 -> 416 static void prvTask1009( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; 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(); + uint16_t x = fuzz_short_next(7); int y = ulTaskNotifyTake(pdTRUE, 0); volatile int torun = 0; if (x % 8 == y) { @@ -443,13 +494,14 @@ static void prvTask1009( void * pvParameters ) { WCET_CLAMP(torun, 0, 51485, TASK_1009_MESSAGE) xTaskNotify(xTask1129, DEBUG_VAL(x % 8 == y, 1), eSetValueWithOverwrite); // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } // Chain1: 579 -> 1009 -> 1129 -> 416 static void prvTask1129( void * pvParameters ) { int period_counter = 2; - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; const TickType_t xFrequency = 10 / portTICK_PERIOD_MS; for( ;; ){ // if (--period_counter==0) {puts("End");} @@ -458,7 +510,7 @@ static void prvTask1129( void * pvParameters ) { // 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(); + volatile uint32_t x = (uint32_t)fuzz_short_next(8); int y = ulTaskNotifyTake(pdTRUE, 0); DEBUG_WCET( static char flag=0; @@ -475,18 +527,19 @@ static void prvTask1129( void * pvParameters ) { WCET_CLAMP(torun, 0, 145040, TASK_1129_MESSAGE) xTaskNotify(xTask416, do_short_run, eSetValueWithOverwrite); // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } // Chain1: 579 -> 1009 -> 1129 -> 416 static void prvTask416( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; 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(); + volatile uint32_t x = (uint32_t)fuzz_short_next(9); int y = ulTaskNotifyTake(pdTRUE, 0); volatile int torun = 0; if (y) { @@ -498,6 +551,7 @@ static void prvTask416( void * pvParameters ) { } WCET_CLAMP(torun, 10000, 126955, TASK_416_MESSAGE) // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } @@ -507,7 +561,7 @@ void vWatersIdleFunction() { } } -void isr_starter( void ) +void ISR_0_Handler( void ) { puts("Interrupt"); if (xTask397) { diff --git a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_watersv2.c b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_watersv2.c index 88786b16..1d31eb81 100644 --- a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_watersv2.c +++ b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_watersv2.c @@ -43,7 +43,7 @@ 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 25 // Multiplier to increase all waiting periods to make the schedule more tight an force preemptions +#define GLOBAL_WCET_MULT 15 // 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 ) @@ -52,6 +52,12 @@ __attribute__((noinline)) static void trigger_Qemu_break( void ) while (1) { } } + +__attribute__((noinline)) static void trigger_job_done( void ) +{ + puts("Job Done"); + // trigger_Qemu_break(); +} // if this macro is set, the code will be modified to produce the worst case // #define DEBUG_WCET(A) {A} @@ -72,35 +78,48 @@ __attribute__((noinline)) static void trigger_Qemu_break( void ) // #define INTERRUPT_ACTIVATION 1 // 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; +#define PARTITION_INPUT +#define NUM_TASKS 10 +#define MAX_INPUT_BYTES 4096 +volatile unsigned char FUZZ_INPUT[MAX_INPUT_BYTES] = {}; +volatile int INPUT_POINTERS[NUM_TASKS] = {}; +volatile uint32_t FUZZ_LENGTH = MAX_INPUT_BYTES;// ignored // Read the Byte of Input, if the Input is exausted trigger the breakpoint instead -static unsigned char fuzz_char_next(void) { +static unsigned char fuzz_char_next(int tasknum) { +#ifdef PARTITION_INPUT + if (INPUT_POINTERS[tasknum] == 0) { + INPUT_POINTERS[tasknum] = tasknum * (MAX_INPUT_BYTES / NUM_TASKS); + } + if (INPUT_POINTERS[tasknum] >= (tasknum+1) * (MAX_INPUT_BYTES / NUM_TASKS)) { + trigger_Qemu_break(); + } + FUZZ_INPUT[INPUT_POINTERS[tasknum]++]; +#else // printf("Get next Input from %lx \n",FUZZ_INPUT); - if (FUZZ_POINTER < FUZZ_LENGTH) { - FUZZ_POINTER++; + if (INPUT_POINTERS[0] < FUZZ_LENGTH) { + INPUT_POINTERS[0]++; // printf("Input no. %d %x\n",FUZZ_POINTER-1,FUZZ_INPUT[FUZZ_POINTER-1]); - return FUZZ_INPUT[FUZZ_POINTER-1]; + return FUZZ_INPUT[INPUT_POINTERS[0]-1]; } else { // puts("End of Input"); // Exausted inputs early trigger_Qemu_break(); } +#endif } -static uint16_t fuzz_short_next(void) { +static uint16_t fuzz_short_next(int tasknum) { unsigned char field[2]; - field[0]=fuzz_char_next(); - field[1]=fuzz_char_next(); + field[0]=fuzz_char_next(tasknum); + field[1]=fuzz_char_next(tasknum); uint16_t* sf = (uint16_t*) field; return *sf; } -static uint32_t fuzz_long_next(void) { +static uint32_t fuzz_long_next(int tasknum) { unsigned char field[4]; - field[0]=fuzz_char_next(); - field[1]=fuzz_char_next(); - field[2]=fuzz_char_next(); - field[3]=fuzz_char_next(); + field[0]=fuzz_char_next(tasknum); + field[1]=fuzz_char_next(tasknum); + field[2]=fuzz_char_next(tasknum); + field[3]=fuzz_char_next(tasknum); uint32_t* sf = (uint32_t*) field; return *sf; } @@ -187,6 +206,22 @@ static TaskHandle_t xTask1129 = NULL; static SemaphoreHandle_t xSemaphoreSpor; +static TickType_t initial_release_time = 0; + +#define HYPER_PERIOD 50 +#define SIMULATE_PERIODS 2 +static TaskHandle_t xTaskTimeSupervisor = NULL; +static void timing_supervisor_task( void * pvParameters ) { + initial_release_time = xTaskGetTickCount(); // The highest priority task sets the initial time + TickType_t xLastWakeTime = initial_release_time; + const TickType_t xFrequency = (SIMULATE_PERIODS * HYPER_PERIOD) / portTICK_PERIOD_MS; + trigger_job_done(); + xTaskDelayUntil( &xLastWakeTime, xFrequency ); + trigger_job_done(); + trigger_Qemu_break(); + for( ;; ){} +} + void main_waters( void ) { xSemaphoreSpor = xSemaphoreCreateBinary(); @@ -265,6 +300,14 @@ void main_waters( void ) mainTASK_1129_PRIO, &xTask1129 ); + xTaskCreate( timing_supervisor_task, + "supervisor", + configMINIMAL_STACK_SIZE, + NULL, + configMAX_PRIORITIES - 1, + &xTaskTimeSupervisor ); + + /* Start the tasks and timer running. */ // puts("Start scheduler"); @@ -283,7 +326,7 @@ void main_waters( void ) // Chain2: 31 -> 78 -> 400 static void prvTask31( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; const TickType_t xFrequency = 100 / portTICK_PERIOD_MS; // int period_counter = 2; for( ;; ){ @@ -291,10 +334,12 @@ static void prvTask31( void * pvParameters ) { // Actions -------------------------------------- // Exectime: f(x) = x // Output: g(x) = x % 2 - volatile uint16_t x = fuzz_short_next(); + volatile uint16_t x = fuzz_short_next(0); DEBUG_WCET(x=48940;) WCET_CLAMP(x, 0, 48940, TASK_31_MESSAGE) - WCET_END({trigger_Qemu_break();}) + trigger_job_done(); + // trigger_Qemu_break(); + // WCET_END({trigger_Qemu_break();}) xTaskNotify(xTask78, DEBUG_VAL(1 + x % 2, 1+1), eSetValueWithOverwrite); // --------------------------------------------- xTaskDelayUntil( &xLastWakeTime, xFrequency );}// Wait for the next cycle. @@ -302,13 +347,13 @@ static void prvTask31( void * pvParameters ) { // Chain2: 31 -> 78 -> 400 static void prvTask78( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; 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(); + uint16_t x = fuzz_short_next(1); int y = ulTaskNotifyTake(pdTRUE, 0); volatile int torun = 6035; if (y > 1) { @@ -322,17 +367,18 @@ static void prvTask78( void * pvParameters ) { xTaskNotify(xTask400, DEBUG_VAL(1 + y * (x % 4), 1+2), eSetValueWithOverwrite); } // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } // Chain2: 31 -> 78 -> 400 static void prvTask400( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; 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(); + uint32_t x = fuzz_char_next(2); int y = ulTaskNotifyTake(pdTRUE, 0); volatile int torun = 0; if (y == 3 && DEBUG_VAL(CHANCE_1_IN_POWOF2(x, 2), 1)) { @@ -342,10 +388,11 @@ static void prvTask400( void * pvParameters ) { DEBUG_WCET(torun=999;) } WCET_CLAMP(torun, 0, 1765, TASK_400_MESSAGE) - if (y) { - WCET_END({trigger_Qemu_break();}) - } + // if (y) { + // WCET_END({trigger_Qemu_break();}) + // } // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } @@ -353,11 +400,13 @@ static void prvTask400( void * pvParameters ) { // Chain3: 397 -> 90 -> 1107 static void prvTask397( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + // initial_release_time = xTaskGetTickCount(); // The highest priority task sets the initial time + TickType_t xLastWakeTime = initial_release_time; const TickType_t xFrequency = 1 / portTICK_PERIOD_MS; for( ;; ){ // 3 different activation strategies ------------- // activate sporadically from interrupts + trigger_job_done(); #ifdef INTERRUPT_ACTIVATION ulTaskNotifyTake(pdTRUE,portMAX_DELAY); #else @@ -369,7 +418,8 @@ static void prvTask397( void * pvParameters ) { // ----------------------------------------------- // Exectime: f(x) = x // Output: g(x) = x % 2 - volatile uint16_t x = fuzz_short_next(); + volatile uint16_t x = fuzz_char_next(3); + x *= 20; DEBUG_WCET(x=5830;) WCET_CLAMP(x, 0, 5830, TASK_397_MESSAGE); if (CHANCE_1_IN_POWOF2(x, 2)) { @@ -378,21 +428,22 @@ static void prvTask397( void * pvParameters ) { xSemaphoreGive(xSemaphoreSpor); } } else { - xTaskNotify(xTask90, DEBUG_VAL(1 + x & 0x1, 1), eSetValueWithOverwrite); + xTaskNotify(xTask90, DEBUG_VAL(1 + (x/20) & 0x1, 1), eSetValueWithOverwrite); } } } // Chain3: 397 -> 90 -> 1107 static void prvTask90( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; const TickType_t xFrequency = 2 / portTICK_PERIOD_MS; for( ;; ){ // Actions -------------------------------------- // Exectime: f(x) = c + x // Output: g(x) = x % 4 int y = ulTaskNotifyTake(pdTRUE, 0); - volatile uint16_t x = fuzz_short_next(); + volatile uint16_t x = fuzz_char_next(4); + x *= 100; DEBUG_WCET(x=20048;) int torun = 0; if (y == 2) { @@ -402,25 +453,27 @@ static void prvTask90( void * pvParameters ) { } WCET_CLAMP(torun, 0, 20045, TASK_90_MESSAGE) if (y) { - xTaskNotify(xTask1107, DEBUG_VAL(x % 4, 0), eSetValueWithOverwrite); + xTaskNotify(xTask1107, DEBUG_VAL((x/100) % 4, 0), eSetValueWithOverwrite); } // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } // Chain3: 397 -> 90 -> 1107 static void prvTask1107( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; const TickType_t xFrequency = 50 / portTICK_PERIOD_MS; for( ;; ){ // Actions -------------------------------------- // Exectime: f(x) = c - x*y - volatile uint16_t x = fuzz_short_next(); + volatile uint16_t x = fuzz_short_next(5); DEBUG_WCET(x=0;) int y = ulTaskNotifyTake(pdTRUE, 0); int torun = 76865-((int)x)*y; WCET_CLAMP(torun, 10000, 76865, TASK_1107_MESSAGE) // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } @@ -430,7 +483,7 @@ static int sem_at_579 = 0; // Chain1: 579 -> 1009 -> 1129 -> 416 static void prvTask579( void * pvParameters ) { // int period = 5; - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; const TickType_t xFrequency = 10 / portTICK_PERIOD_MS; for( ;; ){ // if (--period==0) {puts("End");} // Debugging Marker @@ -441,7 +494,7 @@ static void prvTask579( void * pvParameters ) { if (y && !sem_at_579) { sem_at_579 = xSemaphoreTake(xSemaphoreSpor, portMAX_DELAY); } - uint32_t x = fuzz_long_next(); + uint32_t x = fuzz_long_next(6); volatile int torun = (x>>8) & 0x0fff; DEBUG_WCET(torun = 0x0fff;) WCET_CLAMP(torun, 500, 2460, TASK_579_MESSAGE) @@ -455,18 +508,19 @@ static void prvTask579( void * pvParameters ) { } } // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } // Chain1: 579 -> 1009 -> 1129 -> 416 static void prvTask1009( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; 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(); + uint16_t x = fuzz_short_next(7); int y = ulTaskNotifyTake(pdTRUE, 0); volatile int torun = 0; if (x % 8 == (y-1)) { @@ -480,13 +534,14 @@ static void prvTask1009( void * pvParameters ) { xTaskNotify(xTask1129, DEBUG_VAL(1 + x % 8 == y, 2), eSetValueWithOverwrite); } // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } // Chain1: 579 -> 1009 -> 1129 -> 416 static void prvTask1129( void * pvParameters ) { int period_counter = 2; - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; const TickType_t xFrequency = 10 / portTICK_PERIOD_MS; for( ;; ){ // if (--period_counter==0) {puts("End");} @@ -495,7 +550,7 @@ static void prvTask1129( void * pvParameters ) { // 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(); + volatile uint32_t x = (uint32_t)fuzz_short_next(8); int y = ulTaskNotifyTake(pdTRUE, 0); DEBUG_WCET( static char flag=0; @@ -514,18 +569,19 @@ static void prvTask1129( void * pvParameters ) { xTaskNotify(xTask416, do_short_run, eSetValueWithOverwrite); } // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } // Chain1: 579 -> 1009 -> 1129 -> 416 static void prvTask416( void * pvParameters ) { - TickType_t xLastWakeTime = xTaskGetTickCount(); + TickType_t xLastWakeTime = initial_release_time; 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(); + volatile uint32_t x = (uint32_t)fuzz_short_next(9); int y = ulTaskNotifyTake(pdTRUE, 0); volatile int torun = 0; if (y-1) { @@ -540,6 +596,7 @@ static void prvTask416( void * pvParameters ) { xTaskNotifyIndexed(xTask579, 1, 1337, eSetValueWithOverwrite); } // --------------------------------------------- + trigger_job_done(); xTaskDelayUntil( &xLastWakeTime, xFrequency );} } diff --git a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/scripts/mps2_m3.ld b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/scripts/mps2_m3.ld index 1915a200..84ec2e86 100644 --- a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/scripts/mps2_m3.ld +++ b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/scripts/mps2_m3.ld @@ -51,7 +51,17 @@ SECTIONS __APP_CODE_START__ = .; *main_*.o(.text*) __APP_CODE_END__ = .; - *(EXCLUDE_FILE (*main_*.o) .text*) + __API_CODE_START__ = .; + *startup.o(.text*) + *port.o(.text*) + *tasks.o(.text*) + *list.o(.text*) + *queue.o(.text*) + *timers.o(.text*) + *event_groups.o(.text*) + *heap_3.o(.text*) + __API_CODE_END__ = .; + *(EXCLUDE_FILE (*main_*.o *startup.o *port.o *tasks.o *list.o *queue.o *timers.o *event_groups.o *heap_3.o) .text*) KEEP (*(.init)) KEEP (*(.fini)) KEEP(*(.eh_frame))