-
Notifications
You must be signed in to change notification settings - Fork 1.3k
FreeRTOS posix port hangs when issuing interrupt-safe calls from an external thread #1073
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@doppioandante Consider using the event api defined in wait_for_event.c to simulate your interrupt. |
@doppioandante Please update your observations after using "wait_for_event.c". |
I'm not quite sure how I could use that API, it seems to me like an internal implementation detail of the POSIX port. |
What about using a signal handler for simulating interrupt? Something like the following - #define _GNU_SOURCE
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include <stdio.h>
#include <stdbool.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
static void init_globals();
static void init_tasks();
static void reader_task(void*);
static void periodic_task(void*);
static void* interrupt_simulator(void*);
static void send_int(int value);
static QueueHandle_t queue;
static pthread_t tid;
int main() {
init_globals();
init_tasks();
vTaskStartScheduler();
return 0;
}
void init_globals() {
queue = xQueueCreate(128, sizeof(int));
}
void sigusr1_handler(int sig) {
(void) sig;
static int val = 1;
BaseType_t waked = pdFALSE;
xQueueSendFromISR(queue, &val, &waked);
val += 1;
portYIELD_FROM_ISR(waked);
}
void init_tasks() {
xTaskCreate(reader_task, "ReaderTask", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
xTaskCreate(periodic_task, "PeriodicTask", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
sigset_t set;
pthread_attr_t attr;
struct sigaction sigusr;
sigfillset(&set);
sigdelset( &set, SIGUSR1 );
pthread_attr_init(&attr);
pthread_attr_setsigmask_np(&attr, &set);
sigusr.sa_flags = 0;
sigusr.sa_handler = sigusr1_handler;
sigfillset( &sigusr.sa_mask );
sigaction( SIGUSR1, &sigusr, NULL );
pthread_create(&tid, &attr, interrupt_simulator, NULL);
}
void reader_task(void* args) {
(void) args;
while (true) {
int val;
xQueueReceive(queue, &val, portMAX_DELAY);
send_int(val+1);
}
}
void periodic_task(void* args) {
(void) args;
TickType_t previousWakeTime = xTaskGetTickCount();
while (true) {
send_int(0);
xTaskDelayUntil(&previousWakeTime, pdMS_TO_TICKS(100));
}
}
static void send_int(int val)
{
taskENTER_CRITICAL();
printf("%d\n", val);
taskEXIT_CRITICAL();
}
static void* interrupt_simulator(void* args)
{
(void) args;
while (true) {
usleep(100000);
pthread_kill(tid, SIGUSR1);
}
return NULL;
} |
@doppioandante Did you get a chance to look at the above? |
From a quick glance, that won't cut it, but I'll have to think about it more thoroughly. I'll reach back when I have time to do that. In the meantime, I've changed the architecture of my application getting rid of freertos queues, and using a lockless ring buffer to send data from the interrupt to the task. This allowed me to run the same code on the MCU and on the posix layer, although a bit inconvenient. |
We have not tried that. If you decide to write one, feel free to upstream.
I am closing this issue. Feel free to reopen or create a new one whenever you need anything. |
Uh oh!
There was an error while loading. Please reload this page.
FreeRTOS: version: v11.1.0
FreeRTOS port: FreeRTOS Posix port
OS: Ubuntu 22.04
I'm using the freertos posix port to test a the firmware logic without the need for a hardware. The real hardware receives data via an interrupt, which is then pushed on a queue like:
On the simulator I'm using an external thread (pthread) not managed by FreeRTOS that wait for events on a local network interface; when an event comes, the same code is called, but I've found that it makes FreeRTOS hang or even assert often.
I also added the following assert to
vPortExitCritical
, and it somestimes get triggered, suggesting me that either there's something wrong in the port or, more probably, I'm invalidating the invariant by using the API incorrectly:(BTW, wouldn't a mutex or at least an atomic increment/decrement be needed for
uxCriticalNesting
?)I stripped down the pattern that makes my code crash down to:
freertos_posix_impl.c
FreeRTOSConfig.h
The text was updated successfully, but these errors were encountered: