Skip to content

Commit f68f67e

Browse files
committed
freertos_demo: add A-extension AMO stress and validate in PASS path
- add two FreeRTOS atomic worker tasks that repeatedly execute `amoadd.w` - have workers notify consumer on completion - gate `<<PASS>>` on both queue checks and expected atomic final count - print atomic summary (`actual/expected`) in demo output - reduce atomic worker stack size to fit current FreeRTOS heap budget
1 parent 2c48311 commit f68f67e

File tree

1 file changed

+96
-11
lines changed

1 file changed

+96
-11
lines changed

sw/apps/freertos_demo/main.c

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,24 @@
3232
#include "uart.h"
3333

3434
#define TASK_STACK_SIZE (512)
35+
#define ATOMIC_TASK_STACK_SIZE (256)
3536
#define QUEUE_LENGTH (3)
3637
#define NUM_ITEMS (5)
38+
#define ATOMIC_WORKER_TASKS (2U)
39+
#define ATOMIC_ITERATIONS_PER_WORKER (4000U)
3740

3841
extern void freertos_risc_v_trap_handler(void);
3942

4043
/* Shared resources */
4144
static QueueHandle_t xDataQueue = NULL;
4245
static SemaphoreHandle_t xUartMutex = NULL;
46+
static TaskHandle_t xConsumerTaskHandle = NULL;
4347

4448
/* Counters for demonstration */
4549
static volatile uint32_t ulProducerCount = 0;
4650
static volatile uint32_t ulConsumerCount = 0;
51+
static volatile uint32_t ulAtomicCounter = 0;
52+
static const uint32_t ulAtomicWorkerIds[ATOMIC_WORKER_TASKS] = {1U, 2U};
4753

4854
/*-----------------------------------------------------------*/
4955
/* Safe UART output with mutex protection */
@@ -95,13 +101,50 @@ static void vProducerTask(void *pvParameters)
95101
vTaskDelete(NULL);
96102
}
97103

104+
/*-----------------------------------------------------------*/
105+
/* Atomic increment helper (A extension) */
106+
107+
static inline void atomic_inc_amo(volatile uint32_t *target)
108+
{
109+
uint32_t one = 1U;
110+
__asm volatile("amoadd.w zero, %1, (%0)" : : "r"(target), "r"(one) : "memory");
111+
}
112+
113+
/*-----------------------------------------------------------*/
114+
/* Atomic worker task - stress A extension under preemption */
115+
116+
static void vAtomicWorkerTask(void *pvParameters)
117+
{
118+
(void) pvParameters;
119+
uint32_t i;
120+
121+
for (i = 0; i < ATOMIC_ITERATIONS_PER_WORKER; i++) {
122+
atomic_inc_amo(&ulAtomicCounter);
123+
124+
/* Force frequent interleaving across tasks. */
125+
if ((i & 0x3FU) == 0U) {
126+
taskYIELD();
127+
}
128+
}
129+
130+
if (xConsumerTaskHandle != NULL) {
131+
xTaskNotifyGive(xConsumerTaskHandle);
132+
}
133+
134+
vTaskDelete(NULL);
135+
}
136+
98137
/*-----------------------------------------------------------*/
99138
/* Consumer Task - receives data from queue */
100139

101140
static void vConsumerTask(void *pvParameters)
102141
{
103142
(void) pvParameters;
104143
uint32_t ulReceived;
144+
uint32_t i;
145+
BaseType_t xQueueOk;
146+
BaseType_t xAtomicOk;
147+
const uint32_t ulAtomicExpected = ATOMIC_WORKER_TASKS * ATOMIC_ITERATIONS_PER_WORKER;
105148

106149
safe_print("[Consumer] Task started (higher priority)\r\n");
107150

@@ -121,19 +164,33 @@ static void vConsumerTask(void *pvParameters)
121164
}
122165
}
123166

167+
safe_print("[Consumer] Waiting for atomic worker completion...\r\n");
168+
for (i = 0; i < ATOMIC_WORKER_TASKS; i++) {
169+
(void) ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
170+
}
171+
172+
xQueueOk = (ulProducerCount == NUM_ITEMS) && (ulConsumerCount == NUM_ITEMS);
173+
xAtomicOk = (ulAtomicCounter == ulAtomicExpected);
174+
124175
/* Print summary */
125176
if (xSemaphoreTake(xUartMutex, portMAX_DELAY) == pdTRUE) {
126177
uart_puts("\r\n");
127178
uart_puts("=== Demo Complete ===\r\n");
128-
uart_puts("Producer sent: ");
129-
uart_putchar('0' + ulProducerCount);
130-
uart_puts(" items\r\n");
131-
uart_puts("Consumer received: ");
132-
uart_putchar('0' + ulConsumerCount);
133-
uart_puts(" items\r\n");
134-
uart_puts("Queue + Mutex + Preemption: Working!\r\n");
135-
uart_puts("\r\nPASS\r\n");
136-
uart_puts("<<PASS>>\r\n");
179+
uart_printf("Producer sent: %lu items\r\n", (unsigned long) ulProducerCount);
180+
uart_printf("Consumer received: %lu items\r\n", (unsigned long) ulConsumerCount);
181+
uart_printf("Atomic counter: %lu/%lu\r\n",
182+
(unsigned long) ulAtomicCounter,
183+
(unsigned long) ulAtomicExpected);
184+
uart_puts("Queue + Mutex + Preemption + A-extension stress: ");
185+
if (xQueueOk == pdTRUE && xAtomicOk == pdTRUE) {
186+
uart_puts("Working!\r\n");
187+
uart_puts("\r\nPASS\r\n");
188+
uart_puts("<<PASS>>\r\n");
189+
} else {
190+
uart_puts("FAILED\r\n");
191+
uart_puts("\r\nFAIL\r\n");
192+
uart_puts("<<FAIL>>\r\n");
193+
}
137194
xSemaphoreGive(xUartMutex);
138195
}
139196

@@ -198,14 +255,42 @@ int main(void)
198255
uart_puts("[Main] Created Producer task (priority 1)\r\n");
199256

200257
/* Create consumer task (priority 2 - higher, runs first when data available) */
201-
if (xTaskCreate(vConsumerTask, "Consumer", TASK_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL) !=
202-
pdPASS) {
258+
if (xTaskCreate(vConsumerTask,
259+
"Consumer",
260+
TASK_STACK_SIZE,
261+
NULL,
262+
tskIDLE_PRIORITY + 2,
263+
&xConsumerTaskHandle) != pdPASS) {
203264
uart_puts("[ERROR] Consumer task creation failed\r\n");
204265
for (;;)
205266
;
206267
}
207268
uart_puts("[Main] Created Consumer task (priority 2)\r\n");
208269

270+
/* Create atomic stress workers (priority 1) */
271+
if (xTaskCreate(vAtomicWorkerTask,
272+
"Atomic1",
273+
ATOMIC_TASK_STACK_SIZE,
274+
(void *) &ulAtomicWorkerIds[0],
275+
tskIDLE_PRIORITY + 1,
276+
NULL) != pdPASS) {
277+
uart_puts("[ERROR] Atomic1 task creation failed\r\n");
278+
for (;;)
279+
;
280+
}
281+
282+
if (xTaskCreate(vAtomicWorkerTask,
283+
"Atomic2",
284+
ATOMIC_TASK_STACK_SIZE,
285+
(void *) &ulAtomicWorkerIds[1],
286+
tskIDLE_PRIORITY + 1,
287+
NULL) != pdPASS) {
288+
uart_puts("[ERROR] Atomic2 task creation failed\r\n");
289+
for (;;)
290+
;
291+
}
292+
uart_puts("[Main] Created Atomic workers (priority 1)\r\n");
293+
209294
uart_puts("[Main] Starting scheduler...\r\n\r\n");
210295

211296
/* Start the scheduler - never returns */

0 commit comments

Comments
 (0)