add generated demo

This commit is contained in:
Alwin Berger 2024-03-25 08:00:13 +01:00
parent 8ae2900833
commit 20248a1413
5 changed files with 387 additions and 2 deletions

View File

@ -51,7 +51,7 @@ extern void vAssertCalled( void );
#define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 1
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
#define configCPU_CLOCK_HZ ( ( unsigned long ) 6250000 ) // icount shift 4 // modified
#define configCPU_CLOCK_HZ ( ( unsigned long ) 62500000 ) // icount shift 4 = 62.5 Mips ~= 1/16 GHz
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 2000 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 900 ) )

View File

@ -123,6 +123,11 @@ ifeq ($(MINIMAL_DEMO), 1)
SOURCE_FILES += main_minimal.c
CFLAGS := -DmainCREATE_MINIMAL_DEMO=1
else
ifdef GEN_DEMO
SOURCE_FILES += gen_$(GEN_DEMO).c
CFLAGS := -DmainCREATE_GEN_DEMO=1
else
SOURCE_FILES += main_blinky.c
@ -141,6 +146,7 @@ endif
endif
endif
endif
endif
ifeq ($(INTERRUPT_ACTIVATION), 1)
CFLAGS += -D INTERRUPT_ACTIVATION=1

View File

@ -3,13 +3,15 @@
// Time wasters =====
volatile long _NONSENSE_VAR = 0;
#define NS_PER_INS (1000000000 / configCPU_CLOCK_HZ) // 20MHz
#define NS_PER_INS (1000000000 / configCPU_CLOCK_HZ)
#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
#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_USEC(X) for (int i=0; i<=((X*1000*GLOBAL_WCET_MULT)/(NS_PER_INS*INS_PER_LOOP)); i++) {_NONSENSE_VAR+=i;}
#define WASTE_MSEC(X) for (int i=0; i<=((X*1000000*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) WASTE_TIME(X)

View File

@ -0,0 +1,373 @@
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/*
Goal: 500ms
exec period
feeder > m1 < input 15ms 250ms
machine_1 > shm, sem1 < feeder 30ms 150ms
machine_2 > shm, sem2 < input 30ms 150ms
quality_control > supervisor < sem2 10ms 250ms
supervisor < qc 10ms 250ms
conveyor_belt < sem1, sem2 05ms 150ms
inventory_control > feeder 10ms 50ms
maintenance 10ms 300ms
user_interface 05ms 100ms
system_monitor 10ms 100ms
target utilization ~95%
*/
// Task priorities
#define low_TASK_PRIO ( tskIDLE_PRIORITY + 1 )
#define feeder_TASK_PRIO ( tskIDLE_PRIORITY + 2 )
#define machine_1_TASK_PRIO ( tskIDLE_PRIORITY + 2 )
#define machine_2_TASK_PRIO ( tskIDLE_PRIORITY + 3 )
#define quality_control_TASK_PRIO ( tskIDLE_PRIORITY + 5 )
#define supervisor_TASK_PRIO ( tskIDLE_PRIORITY + 6 )
#define conveyor_belt_TASK_PRIO ( tskIDLE_PRIORITY + 7 )
#define inventory_control_TASK_PRIO ( tskIDLE_PRIORITY + 8 )
#define maintenance_TASK_PRIO ( tskIDLE_PRIORITY + 9 )
#define user_interface_TASK_PRIO ( tskIDLE_PRIORITY + 10 )
#define system_monitor_TASK_PRIO ( tskIDLE_PRIORITY + 11 )
// Task handles
TaskHandle_t feeder_task_handle = NULL;
TaskHandle_t machine_1_task_handle = NULL;
TaskHandle_t machine_2_task_handle = NULL;
TaskHandle_t quality_control_task_handle = NULL;
TaskHandle_t supervisor_task_handle = NULL;
TaskHandle_t conveyor_belt_task_handle = NULL;
TaskHandle_t inventory_control_task_handle = NULL;
TaskHandle_t maintenance_task_handle = NULL;
TaskHandle_t user_interface_task_handle = NULL;
TaskHandle_t system_monitor_task_handle = NULL;
// Semaphores and other synchronization objects
SemaphoreHandle_t machine_1_completion_sem;
SemaphoreHandle_t machine_2_completion_sem;
SemaphoreHandle_t shared_resource_mutex;
static int shared_resource = 0;
#include <stdio.h>
#include "arbitrary_loads.c"
__attribute__((noinline)) static void trigger_Qemu_break( void )
{
puts("Trigger");
while (1) {
}
}
// Input Stuff
volatile unsigned int FUZZ_INPUT[2048] = {0xa,0xb,0xc,0xd};
volatile uint32_t FUZZ_LENGTH = 4;
volatile uint32_t FUZZ_POINTER = 0;
// Read the Byte of Input, if the Input is exausted trigger the breakpoint instead
static unsigned int fuzz_int_next(void) {
// printf("Get next Input from %lx \n",FUZZ_INPUT);
if (FUZZ_POINTER < FUZZ_LENGTH) {
FUZZ_POINTER++;
return FUZZ_INPUT[FUZZ_POINTER-1];
} else {
// Exausted inputs early
trigger_Qemu_break();
}
}
// Worst in 2^24: 15733191 with 704 steps
int collatz(int i) {
int in = i;
int steps = 0;
while (in != 1) {
if (i & 1) {i=i*3+1;}
else {i>=1;}
steps++;
}
return steps;
}
void feeder_task(void *params) {
TickType_t xLastWakeTime = xTaskGetTickCount();
while (1) {
// Perform some work here, such as adding materials to the conveyor belt
int input = fuzz_int_next() & 0xFFFFFF;
int steps = collatz(input);
WASTE_USEC(steps*21); // 701*21 ~= 15ms
// Put something on the conveyor belt
xTaskNotify(machine_1_task_handle, steps, eSetValueWithOverwrite);
// Wait for the next activation period
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(250));
}
}
int SORT_FIELD[4096] = {0};
int bubbleSort(int arr[], int n) {
int swaps = 0;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
// Swap arr[j] and arr[j+1]
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swaps++;
}
}
}
return swaps;
}
void fill_field_rng(int bound) {
SORT_FIELD[0] = RNG_FROM(bound);
for (int i=1; i<bound; i++) {
SORT_FIELD[i]=RNG_FROM(SORT_FIELD[i-1]);
}
}
int big_increase_fast(int value) {
WASTE_TIME(value);
value += value * 10;
return value;
}
int small_increase_slow(int value) {
WASTE_TIME(500+2*value);
value += value/2;
return value;
}
void machine_1_task(void *params) {
TickType_t xLastWakeTime = xTaskGetTickCount();
while (1) {
// Perform some work here, such as processing materials from the conveyor belt
int val = ulTaskNotifyTake(pdTRUE,portMAX_DELAY); // max 701
fill_field_rng(val);
int swaps = bubbleSort(SORT_FIELD, val); // max swaps ~= 701 * 701/2 = 245700
WASTE_TIME(swaps*100); // ~ up to 25ms
// Signal completion using a binary semaphore
xSemaphoreGive(machine_1_completion_sem);
// Wait for access to a shared resource using a mutex
xSemaphoreTake(shared_resource_mutex, portMAX_DELAY);
// Perform some more work here
shared_resource = big_increase_fast(shared_resource);
// Release the mutex
xSemaphoreGive(shared_resource_mutex);
// Wait for the next activation period
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(150));
}
}
#include <stdint.h>
uint32_t popcount(uint32_t x) {
uint32_t count = 0;
while (x != 0) {
count += (x & 1);
x >>= 1;
}
return count;
}
int complex_function(int input1) {
int result = 0;
for (int i = 0; i < input1; i++) {
if (i % 2 == 0) {
for (int j = 0; j < i*5; j++) {
if (j % 3 == 0) {
for (int k = 0; k < 2*j; k++) {
if (k % 5 == 0) {
int r = RNG_FROM(i ^ j ^ k );
if ((popcount(r)) > 16) {
result += r;
}
}
}
}
}
}
}
return result;
}
static int m2_out = 0;
void machine_2_task(void *params) {
TickType_t xLastWakeTime = xTaskGetTickCount();
while (1) {
// Perform some work here, such as processing materials from machine_1_task
int input = fuzz_int_next();
int out = complex_function(input);
out = collatz(out & 0xFFFFFF);
WASTE_USEC(out*100);
m2_out = out;
// Signal completion using a binary semaphore
xSemaphoreGive(machine_2_completion_sem);
// Wait for access to a shared resource using a mutex
xSemaphoreTake(shared_resource_mutex, portMAX_DELAY);
// Perform some more work here
shared_resource = small_increase_slow(shared_resource);
// Release the mutex
xSemaphoreGive(shared_resource_mutex);
// Wait for the next activation period
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(150));
}
}
void quality_control_task(void *params) {
TickType_t xLastWakeTime = xTaskGetTickCount();
while (1) {
// Perform some work here, such as checking the quality of materials from machine_2_task
int waited = xSemaphoreTake(machine_2_completion_sem, 3);
if (waited == pdFALSE) {
WASTE_MSEC(10);
} else {
WASTE_MSEC(5);
if (m2_out & 1) { /* defect detected */
// Send a notification to the supervisor task
xTaskNotifyFromISR(supervisor_task_handle, 0, eNoAction, NULL);
}
xSemaphoreGive(machine_2_completion_sem);
}
// Wait for the next activation period
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(250));
}
}
void supervisor_task(void *params) {
TickType_t xLastWakeTime = xTaskGetTickCount();
while (1) {
// Perform some work here, such as monitoring the status of all machines
// Wait for notifications from other tasks
int result = ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(50));
// Take corrective action if any issues are detected
if (result == pdTRUE) {
WASTE_MSEC(10);
} else {
WASTE_MSEC(5);
}
// Wait for the next activation period
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(250));
}
}
void conveyor_belt_task(void *params) {
TickType_t xLastWakeTime = xTaskGetTickCount();
while (1) {
// Perform some work here, such as controlling the movement of materials through the assembly line
// Wait for signals from other tasks using binary semaphores
xSemaphoreTake(machine_1_completion_sem, portMAX_DELAY);
xSemaphoreTake(machine_2_completion_sem, portMAX_DELAY);
// Adjust speed based on the signals received
WASTE_MSEC(5);
// Wait for the next activation period
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(100));
}
}
void inventory_control_task(void *params) {
TickType_t xLastWakeTime = xTaskGetTickCount();
while (1) {
// Perform some work here, such as keeping track of inventory levels
if (1) { /* more materials needed */
// Send a notification to the feeder task
WASTE_MSEC(10);
xTaskNotifyFromISR(feeder_task_handle, 0, eNoAction, NULL);
}
// Wait for the next activation period
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(50));
}
}
void maintenance_task(void *params) {
TickType_t xLastWakeTime = xTaskGetTickCount();
while (1) {
// Perform some work here, such as performing periodic maintenance operations on the machines
WASTE_MSEC(10);
// Wait for the next activation period
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(300));
}
}
void user_interface_task(void *params) {
TickType_t xLastWakeTime = xTaskGetTickCount();
while (1) {
// Perform some work here, such as providing a user interface for controlling the system and displaying status information
// Wait for updates from other tasks using binary semaphores or task notifications
// Update the UI with new data
WASTE_MSEC(5);
// Wait for the next activation period
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(100));
}
}
void system_monitor_task(void *params) {
TickType_t xLastWakeTime = xTaskGetTickCount();
while (1) {
// Perform some work here, such as monitoring the health of the system and sending notifications if any issues are detected
WASTE_MSEC(10);
// Wait for the next activation period
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(100));
}
}
void main_gen(void) {
// Initialize synchronization objects
machine_1_completion_sem = xSemaphoreCreateBinary();
machine_2_completion_sem = xSemaphoreCreateBinary();
shared_resource_mutex = xSemaphoreCreateMutex();
// Create tasks
xTaskCreate(feeder_task, "feeder", configMINIMAL_STACK_SIZE, NULL, feeder_TASK_PRIO, &feeder_task_handle);
xTaskCreate(machine_1_task, "machine_1", configMINIMAL_STACK_SIZE, NULL, machine_1_TASK_PRIO, &machine_1_task_handle);
xTaskCreate(machine_2_task, "machine_2", configMINIMAL_STACK_SIZE, NULL, machine_2_TASK_PRIO, &machine_2_task_handle);
xTaskCreate(quality_control_task, "quality_control", configMINIMAL_STACK_SIZE, NULL, quality_control_TASK_PRIO, &quality_control_task_handle);
xTaskCreate(supervisor_task, "supervisor", configMINIMAL_STACK_SIZE, NULL, supervisor_TASK_PRIO, &supervisor_task_handle);
xTaskCreate(conveyor_belt_task, "conveyor_belt", configMINIMAL_STACK_SIZE, NULL, conveyor_belt_TASK_PRIO, &conveyor_belt_task_handle);
xTaskCreate(inventory_control_task, "inventory_control", configMINIMAL_STACK_SIZE, NULL, inventory_control_TASK_PRIO, &inventory_control_task_handle);
xTaskCreate(maintenance_task, "maintenance", configMINIMAL_STACK_SIZE, NULL, maintenance_TASK_PRIO, &maintenance_task_handle);
xTaskCreate(user_interface_task, "user_interface", configMINIMAL_STACK_SIZE, NULL, user_interface_TASK_PRIO, &user_interface_task_handle);
xTaskCreate(system_monitor_task, "system_monitor", configMINIMAL_STACK_SIZE, NULL, system_monitor_TASK_PRIO, &system_monitor_task_handle);
vTaskStartScheduler();
trigger_Qemu_break();
}
void isr_starter( void )
{
}

View File

@ -107,6 +107,10 @@ int main()
{
main_minimal();
}
#elif ( mainCREATE_GEN_DEMO == 1 )
{
main_gen();
}
#else
{