add micro bench for interrupt times
This commit is contained in:
parent
99fc3ddfd2
commit
1e37657385
@ -98,6 +98,11 @@ ifeq ($(BRANCHLESS_DEMO), 1)
|
|||||||
SOURCE_FILES += main_micro_branchless.c
|
SOURCE_FILES += main_micro_branchless.c
|
||||||
|
|
||||||
CFLAGS := -DmainCREATE_BRANCHLESS_DEMO=1
|
CFLAGS := -DmainCREATE_BRANCHLESS_DEMO=1
|
||||||
|
else
|
||||||
|
ifeq ($(INT_DEMO), 1)
|
||||||
|
SOURCE_FILES += main_micro_int.c
|
||||||
|
|
||||||
|
CFLAGS := -DmainCREATE_INT_DEMO=1
|
||||||
else
|
else
|
||||||
SOURCE_FILES += main_blinky.c
|
SOURCE_FILES += main_blinky.c
|
||||||
|
|
||||||
@ -111,6 +116,7 @@ endif
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
DEFINES := -DQEMU_SOC_MPS2 -DHEAP3
|
DEFINES := -DQEMU_SOC_MPS2 -DHEAP3
|
||||||
|
|
||||||
|
@ -6,7 +6,9 @@ volatile long _NONSENSE_VAR = 0;
|
|||||||
#define NS_PER_INS (1000000000 / configCPU_CLOCK_HZ) // 20MHz
|
#define NS_PER_INS (1000000000 / configCPU_CLOCK_HZ) // 20MHz
|
||||||
#define INS_PER_LOOP 5 // got this multiplier by testing with the goal of getting a 100 ms or 100 tick period
|
#define INS_PER_LOOP 5 // got this multiplier by testing with the goal of getting a 100 ms or 100 tick period
|
||||||
#define INS_PER_PRINT 117 // got this multiplier by testing with the goal of getting a 100 ms or 100 tick period, 2 digits
|
#define INS_PER_PRINT 117 // got this multiplier by testing with the goal of getting a 100 ms or 100 tick period, 2 digits
|
||||||
#define GLOBAL_WCET_MULT 16 // Multiplier to increase all waiting periods to make the schedule more tight an force preemptions
|
#ifndef GLOBAL_WCET_MULT
|
||||||
|
#define GLOBAL_WCET_MULT 1 // Multiplier to increase all waiting periods to make the schedule more tight an force preemptions
|
||||||
|
#endif
|
||||||
#define WASTE_TIME(X) for (int i=0; i<=((X*GLOBAL_WCET_MULT)/(NS_PER_INS*INS_PER_LOOP)); i++) {_NONSENSE_VAR+=i;}
|
#define WASTE_TIME(X) for (int i=0; i<=((X*GLOBAL_WCET_MULT)/(NS_PER_INS*INS_PER_LOOP)); i++) {_NONSENSE_VAR+=i;}
|
||||||
#define PRINT_TIME(X,Y) for (int i=0; i<=((X*GLOBAL_WCET_MULT)/((NS_PER_INS*INS_PER_PRINT))); i++) {puts(Y);}
|
#define PRINT_TIME(X,Y) for (int i=0; i<=((X*GLOBAL_WCET_MULT)/((NS_PER_INS*INS_PER_PRINT))); i++) {puts(Y);}
|
||||||
// #define PRINT_TIME(X,Y) WASTE_TIME(X)
|
// #define PRINT_TIME(X,Y) WASTE_TIME(X)
|
||||||
|
@ -95,6 +95,10 @@ int main()
|
|||||||
{
|
{
|
||||||
main_branchless();
|
main_branchless();
|
||||||
}
|
}
|
||||||
|
#elif ( mainCREATE_INT_DEMO == 1 )
|
||||||
|
{
|
||||||
|
main_micro_int();
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
{
|
{
|
||||||
|
207
FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_micro_int.c
Normal file
207
FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_micro_int.c
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
#include <semphr.h>
|
||||||
|
#include "arbitrary_loads.c"
|
||||||
|
/*
|
||||||
|
Interrupt Demo without priority inheritance
|
||||||
|
Async | I
|
||||||
|
A | RxxP xxxVD
|
||||||
|
B | RxxxD
|
||||||
|
C RxxxPx xx xxxV xxxD
|
||||||
|
*/
|
||||||
|
// #undef PRINT_TIME
|
||||||
|
// #define PRINT_TIME(X,Y) WASTE_TIME(X)
|
||||||
|
#define WCET_CLAMP(X, LB, UB, LABEL) PRINT_TIME(UB,LABEL)
|
||||||
|
|
||||||
|
__attribute__((noinline)) static void trigger_Qemu_break( void )
|
||||||
|
{
|
||||||
|
puts("Trigger");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin Input Stuff
|
||||||
|
volatile unsigned char FUZZ_INPUT[4096] = {0xa,0xb,0xc,0xd,0xe,0xf};
|
||||||
|
volatile uint32_t FUZZ_LENGTH = 32;
|
||||||
|
volatile uint32_t FUZZ_POINTER = 0;
|
||||||
|
|
||||||
|
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 prvReplicaA( void * pvParameters );
|
||||||
|
static void prvReplicaB( void * pvParameters );
|
||||||
|
static void prvReplicaC( void * pvParameters );
|
||||||
|
static void prvSpor( void * pvParameters );
|
||||||
|
|
||||||
|
#define mainREPLICA_SPOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 6 )
|
||||||
|
#define mainREPLICA_A_TASK_PRIORITY ( tskIDLE_PRIORITY + 5 )
|
||||||
|
#define mainREPLICA_B_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
|
||||||
|
#define mainREPLICA_C_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||||
|
|
||||||
|
// Handles for direct messages
|
||||||
|
static TaskHandle_t xReplA = NULL;
|
||||||
|
static TaskHandle_t xReplB = NULL;
|
||||||
|
static TaskHandle_t xReplC = NULL;
|
||||||
|
|
||||||
|
static SemaphoreHandle_t xSemaphoreAC;
|
||||||
|
|
||||||
|
void main_micro_int( void )
|
||||||
|
{
|
||||||
|
xSemaphoreAC = xSemaphoreCreateBinary();
|
||||||
|
xSemaphoreGive(xSemaphoreAC);
|
||||||
|
|
||||||
|
if( xSemaphoreAC != NULL )
|
||||||
|
{
|
||||||
|
/* Start the two tasks as described in the comments at the top of this
|
||||||
|
* file. */
|
||||||
|
xTaskCreate( prvReplicaA, /* The function that implements the task. */
|
||||||
|
"ReplA", /* 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. */
|
||||||
|
mainREPLICA_A_TASK_PRIORITY, /* The priority assigned to the task. */
|
||||||
|
&xReplA ); /* The task handle is not required, so NULL is passed. */
|
||||||
|
|
||||||
|
xTaskCreate( prvReplicaB, /* The function that implements the task. */
|
||||||
|
"ReplB", /* 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. */
|
||||||
|
mainREPLICA_B_TASK_PRIORITY, /* The priority assigned to the task. */
|
||||||
|
&xReplB ); /* The task handle is not required, so NULL is passed. */
|
||||||
|
|
||||||
|
xTaskCreate( prvReplicaC, /* The function that implements the task. */
|
||||||
|
"ReplC", /* 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. */
|
||||||
|
mainREPLICA_C_TASK_PRIORITY, /* The priority assigned to the task. */
|
||||||
|
&xReplC ); /* The task handle is not required, so NULL is passed. */
|
||||||
|
|
||||||
|
xTaskCreate( prvSpor, /* The function that implements the task. */
|
||||||
|
"Spor", /* 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. */
|
||||||
|
mainREPLICA_SPOR_TASK_PRIORITY, /* The priority assigned to the task. */
|
||||||
|
NULL ); /* The task handle is not required, so NULL is passed. */
|
||||||
|
|
||||||
|
/* Start the tasks and timer running. */
|
||||||
|
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 prvReplicaA( void * pvParameters )
|
||||||
|
{
|
||||||
|
TickType_t xLastWakeTime = xTaskGetTickCount();
|
||||||
|
vTaskDelayUntil( &xLastWakeTime, 5 / portTICK_PERIOD_MS );
|
||||||
|
puts("A Ready");
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
xSemaphoreTake(xSemaphoreAC, portMAX_DELAY);
|
||||||
|
uint32_t x = fuzz_long_next();
|
||||||
|
WCET_CLAMP(x>>5,0, 5 * 1000 * 1000, "A ")
|
||||||
|
xSemaphoreGive(xSemaphoreAC);
|
||||||
|
trigger_Qemu_break();
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void prvReplicaB( void * pvParameters )
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
ulTaskNotifyTake(pdTRUE,portMAX_DELAY);
|
||||||
|
uint32_t x = fuzz_long_next();
|
||||||
|
WCET_CLAMP(x>>5,0, 5 * 1000 * 1000, "B ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void prvReplicaC( void * pvParameters )
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
xSemaphoreTake(xSemaphoreAC, portMAX_DELAY);
|
||||||
|
uint32_t x = fuzz_long_next();
|
||||||
|
WCET_CLAMP(x>>5, 6 * 1000 * 1000, 10 * 1000 * 1000, "C ")
|
||||||
|
xSemaphoreGive(xSemaphoreAC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void prvSpor( void * pvParameters )
|
||||||
|
{
|
||||||
|
TickType_t xLastWakeTime = xTaskGetTickCount();
|
||||||
|
const TickType_t xFrequency = 7 / portTICK_PERIOD_MS;
|
||||||
|
vTaskDelayUntil( &xLastWakeTime, xFrequency );
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
puts("Fire");
|
||||||
|
xTaskNotifyGive(xReplB);
|
||||||
|
vTaskDelayUntil( &xLastWakeTime, xFrequency * 10000 );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void isr_starter( void )
|
||||||
|
{
|
||||||
|
puts("Fire");
|
||||||
|
xTaskNotifyGive(xReplB);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
@ -41,8 +41,8 @@ prvVoterTask will wait on ReplicateA&B
|
|||||||
If they disagree ReplicateC will be started by mutex.
|
If they disagree ReplicateC will be started by mutex.
|
||||||
If all the Replicates disagree now the sampler will be engaged once more
|
If all the Replicates disagree now the sampler will be engaged once more
|
||||||
*/
|
*/
|
||||||
// include tacle benches
|
|
||||||
|
|
||||||
|
#define GLOBAL_WCET_MULT 16 // Multiplier to increase all waiting periods to make the schedule more tight an force preemptions
|
||||||
#include "arbitrary_loads.c"
|
#include "arbitrary_loads.c"
|
||||||
|
|
||||||
__attribute__((noinline)) static void trigger_Qemu_break( void )
|
__attribute__((noinline)) static void trigger_Qemu_break( void )
|
||||||
@ -439,18 +439,21 @@ static void prvTask1129( void * pvParameters ) {
|
|||||||
for( ;; ){
|
for( ;; ){
|
||||||
// if (--period_counter==0) {puts("End");}
|
// if (--period_counter==0) {puts("End");}
|
||||||
// Actions --------------------------------------
|
// Actions --------------------------------------
|
||||||
// Exectime: f(x,y) = if !y ? 80000+x : x (<40k)
|
// Exectime: f(x,y) = if y && rng(x) ? c1+x : c2+x
|
||||||
// Output: g(x) = x % 4
|
// Output: g(x) = y && rng(x)
|
||||||
|
// longmax - shortmax: 69505
|
||||||
|
// most likely long case, which causes a short case in next task
|
||||||
uint32_t x = (uint32_t)fuzz_short_next();
|
uint32_t x = (uint32_t)fuzz_short_next();
|
||||||
int y = ulTaskNotifyTake(pdFALSE, 0);
|
int y = ulTaskNotifyTake(pdFALSE, 0);
|
||||||
|
int do_short_run = y && CHANCE_1_IN_POWOF2(x, 3);
|
||||||
int torun = 0;
|
int torun = 0;
|
||||||
if (!y) {
|
if (do_short_run) {
|
||||||
torun = 80000 + x;
|
torun = 10000 + x;
|
||||||
} else {
|
} else {
|
||||||
torun = x;
|
torun = 80000 + x;
|
||||||
}
|
}
|
||||||
WCET_CLAMP(torun, 0, 145040, TASK_1129_MESSAGE)
|
WCET_CLAMP(torun, 0, 145040, TASK_1129_MESSAGE)
|
||||||
xTaskNotify(xTask416, x % 4, eSetValueWithOverwrite);
|
xTaskNotify(xTask416, do_short_run, eSetValueWithOverwrite);
|
||||||
// ---------------------------------------------
|
// ---------------------------------------------
|
||||||
vTaskDelayUntil( &xLastWakeTime, xFrequency );}
|
vTaskDelayUntil( &xLastWakeTime, xFrequency );}
|
||||||
}
|
}
|
||||||
@ -461,16 +464,17 @@ static void prvTask416( void * pvParameters ) {
|
|||||||
const TickType_t xFrequency = 10 / portTICK_PERIOD_MS;
|
const TickType_t xFrequency = 10 / portTICK_PERIOD_MS;
|
||||||
for( ;; ){
|
for( ;; ){
|
||||||
// Actions --------------------------------------
|
// Actions --------------------------------------
|
||||||
// Exectime: f(x,y) = if y == 3 ? c-x : c+x
|
// Exectime: f(x,y) = if y ? c1+2*x : c2-x
|
||||||
|
// longmax - shortmax: 86955
|
||||||
uint32_t x = (uint32_t)fuzz_short_next();
|
uint32_t x = (uint32_t)fuzz_short_next();
|
||||||
int y = ulTaskNotifyTake(pdFALSE, 0);
|
int y = ulTaskNotifyTake(pdFALSE, 0);
|
||||||
int torun = 0;
|
int torun = 0;
|
||||||
if (y==3) {
|
if (y) {
|
||||||
torun = 70000 + x;
|
torun = x*3;
|
||||||
} else {
|
} else {
|
||||||
torun = 70000 - x;
|
torun = 40000 - CLAMP_CEILING(x, 40000);
|
||||||
}
|
}
|
||||||
PRINT_TIME(126955, TASK_416_MESSAGE)
|
WCET_CLAMP(torun, 10000, 126955, TASK_416_MESSAGE)
|
||||||
// ---------------------------------------------
|
// ---------------------------------------------
|
||||||
vTaskDelayUntil( &xLastWakeTime, xFrequency );}
|
vTaskDelayUntil( &xLastWakeTime, xFrequency );}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user