I have a question regarding scheduler implementation. I have tried to implement a scheduler according to my understanding.
In this example, i have taken advantage of the Systick handler provided by STM32, so my handler looks somewhat like this:
void SysTick_Handler(void)
{
HAL_IncTick();
HAL_SYSTICK_IRQHandler();
if(ticks_for_scheduler++==100)
ticks_for_scheduler=0;
}
I have a scheduler.h file which looks like this:
void (*task1)() = read_temp;
void (*task2)() = Display_temp_lcd;
and my scheduler.c looks like this:
extern uint16_t ticks_for_scheduler;
void sched_system()
{
if(ticks_for_scheduler==20)
(*task1)();
if(ticks_for_scheduler==40)
{
(*task2)();
}
}
The function sched_system is called in main(){while(1){sched_system();}My goal is to execute task1 every 20ms, and task2 every 40ms, but somehow I'm not able to get it right. I'm not sure what I'm doing wrong? I don't see the results on my LCD as expected.
Related
To clarify a question assume that we have:
Static Button object: static Button_T sButton = {0};
Function to get Button: void GetButton(Button_T * p_button); that is called from main loop context
ISR handler: void ButtonISRHandler(void);
Assumptions:
GetButton execution can be interrupted by any interrupt that does not execute ButtonISRHandler
ButtonISRHandler execution can be interrupted by other iterrupts
GetButton execution takes less time than the minimum time between two ButtonISRHandler interrupts call.
Button interrupt is a cyclic interrupt triggered for instance every 10 ms.
In ButtonISRHandler we have procedures like checking button PIN state or detecting if button is touched (in touch button case). If a given PIN state is stable in e.g. for 5 consequtive calls then sButton object state is updated.
Button_T is generic object - it could be classic tact switch or touch button etc.
ScanButtonAndUpdate could handle a list of Button_T objects but GetButton function operates only on the one button object.
The problem is: classic case when an interrupt can occur when program counter is inside GetButton
The question is: How to synchronize GetButton with ButtonISRHandler without disableing Interrupts?
My target processor is Cortex M0 without LDREX/STREX operation so I cannot use atomics from C11 that would be great solution in this case.
My Proposed Solution
Use Critical Section in GetButton.
If an interrupt occured when the program counter is inside Critical Section then do not handle ScanButtonAndUpdate in interrupt but handle it on ExitCriticalSection. Defer ScanButtonAndUpdate execution.
There is no possibility to call ScanButtonAndUpdate function from interrupt and main context in the same time - this behaviour is protected by semaphore
Implementation
#define SEMAPHORE_GIVEN 0
#define SEMAPHORE_TAKEN 1
typedef uint32_t BaseType_T;
typedef struct Button_T;
static volatile BaseType_T sSemaphore = SEMAPHORE_GIVEN;
static volatile bool sIsPendingISR = false;
static volatile Button_T sButton = {0};
void GetButton(Button_T * p_button)
{
EnterCriticalSection();
memcpy(p_button, &sButton, sizeof(Button_T))
/* Other procedures on sButton... */
ExitCriticalSection();
}
/* Cyclic executed handler */
void ButtonISRHandler(void)
{
if (!BinarySemaphoreTake()) {
SetISRPending();
}
else {
ScanButtonAndUpdate();
BinarySemaphoreGive();
}
}
void ScanButtonAndUpdate(void)
{
/* Scan for instance a current PIN state and update sButton object
if state is stable in next calls */
}
static void EnterCriticalSection(void)
{
while(false == BinarySemaphoreTake()) continue;
}
static void ExitCriticalSection(void)
{
BinarySemaphoreGive();
if (IsPendingISR()){
ScanButtonAndUpdate();
ResetISRPending();
}
}
static bool BinarySemaphoreTake(void)
{
if (SEMAPHORE_GIVEN == sSemaphore) {
/* Value Store operation is atomic on the architecture native type */
sSemaphore = SEMAPHORE_TAKEN;
return true;
}
else {
return false;
}
}
static void BinarySemaphoreGive(void)
{
sSemaphore = SEMAPHORE_GIVEN;
}
static void SetISRPending(void)
{
sIsPendingISR = true;
}
static void ResetISRPending(void)
{
sIsPendingISR = false;
}
static bool IsPendingISR(void)
{
return sIsPendingISR;
}
This solution was tested and works great without problems but I am not sure that this is the best solution without hidden bugs.
EDIT 1: Updated Assumptions and added missing ScanButtonAndUpdate function
There is a hidden synchronization which affects whether you have a race condition or not: what gates the Interrupt? The two most common scenarios are edge and level triggered; an edge trigger means that the interrupt will be inhibited until the device is cleared, whereas a level trigger means that the interrupt will repeatedly re-assert until the device is cleared.
If your code uses level triggered interrupts, then you have omitted this synchronization entirely, or you are pretending that sIsPendingISR is the mask & status flag. In that case, you look alright
If it is level triggered, then it can re-assert during /* Update sButton object */, causing the device handling code to be executing in two contexts (interrupt + normal). Most device code is not designed to do this.
Btw, there is a software protocol called “Dekkers Algorithm” which provides a general solution to mutual exclusion without hardware support. You have sort of integrated a version of it here.
I'm making a GTK+3 application in C and I want a spinner to show when the program is processing the data. Here's what I generally have:
main()
{
//Some statements
g_signal_connect(G_OBJECT(btnGenerate), "clicked", G_CALLBACK(Generate), &mainform);
}
void Generate(GtkWidget *btnGenerate, form_widgets *p_main_form)
{
gtk_spinner_start(GTK_SPINNER(p_main_form->spnProcessing));
Begin_Lengthy_Processing(Parameters, Galore, ...);
//gtk_spinner_stop(GTK_SPINNER(p_main_form->spnProcessing));
}
I have the stop function commented out so I can see the spinner spin even after the function has finished, but the spinner starts after the function is finished, and I suspect it turns on in the main loop.
I also found out that the entire interface freezes during the execution of the long going function.
Is there a way to get it to start and display inside the callback function? I found the same question, but it uses Python and threads. This is C, not Python, so I would assume things are different.
You need to run your lengthy computation in a separate thread, or break it up into chunks and run each of them separately as idle callbacks in the main thread.
If your lengthy computation takes a single set of inputs and doesn’t need any more inputs until it’s finished, then you should construct it as a GTask and use g_task_run_in_thread() to start the task. Its result will be delivered back to the main thread via the GTask’s GAsyncReadyCallback. There’s an example here.
If it takes more input as it progresses, you probably want to use a GAsyncQueue to feed it more inputs, and a GThreadPool to provide the threads (amortising the cost of creating threads over multiple calls to the lengthy function, and protecting against denial of service).
The GNOME developer docs give an overview of how to do threading.
This is what I got:
int main()
{
// Statements...
g_signal_connect(G_OBJECT(btnGenerate), "clicked", G_CALLBACK(Process), &mainform);
// More statements...
}
void Process(GtkWidget *btnGenerate, form_widgets *p_main_form)
{
GError *processing_error;
GThread *start_processing;
gtk_spinner_start(GTK_SPINNER(p_main_form->spnProcessing));
active = true;
if((start_processing = g_thread_try_new(NULL, (GThreadFunc)Generate, p_main_form, &processing_error)) == NULL)
{
printf("%s\n", processing_error->message);
printf("Error, cannot create thread!?!?\n\n");
exit(processing_error->code);
}
}
void Generate(form_widgets *p_main_form)
{
// Long process
active = false;
}
My program, once cleaned up and finished, as there are many other bugs in the program, will be put on GitHub.
Thank you all for your help. This answer comes from looking at all of your answers and comments as well as reading some more documentation, but mostly your comments and answers.
I did something similar in my gtk3 program. It's not that difficult. Here's how I would go about it.
/**
g_idle_add_full() expects a pointer to a function with the signature below:
(*GSourceFunc) (gpointer user_data).
So your function signature must adhere to that in order to be called.
But you might want to pass variables to the function.
If you don't want to have the variables in the global scope
then you can do this:
typedef struct myDataType {
char* name;
int age;
} myDataType;
myDataType person = {"Max", 25};
then when calling g_idle_add_full() you do it this way:
g_idle_add_full(G_PRIORITY_HIGH_IDLE, myFunction, person, NULL);
*/
int main()
{
// Assumming there exist a pointer called data
g_idle_add_full(G_PRIORITY_HIGH_IDLE, lengthyProcessCallBack, data, NULL);
// GTK & GDK event loop continues and window should be responsive while function runs in background
}
gboolean lengthyProcessCallBack(gpointer data)
{
myDataType person = (myDataType) *data;
// Doing lenghthy stuff
while(;;) {
sleep(3600); // hypothetical long process :D
}
return FALSE; // removed from event sources and won't be called again.
}
I am writing a linux kernel module which schedules a task using schedule_delayed_work at a particular time which in turn send a signal to a user space program to do some task.
What I did is manually given the time in milliseconds (say 5000ms) and changed it to jiffies using "msec to jiffies" function and tested it and worked.
My use case is that the user will give a time (say 5 pm) and the module has to schedule it to send the signal everyday at 5 pm to the user program. I am totally confused in how to calculate the milliseconds from the user given time for everyday basis.
I used workqueue to create a queue and then the task to accomplish and doing the scheduling.
My kernel module:
static void wq_handler_function(struct work_struct *work);
static unsigned long delay;
static struct workqueue_struct *my_wq; // my workqueue
static DECLARE_DELAYED_WORK(my_work, wq_handler_function); //my work/task
static void wq_handler_function(struct work_struct *work)
{
printk(KERN_DEBUG "handler function called\n");
if(my_wq)
{
/*Do some work like sending signal to user space*/
schedule_delayed_work(&my_work, delay); /*reschedule after the first scheduled time finished*/
}
}
int sig_init_module(void)
{
printk(KERN_DEBUG "signal module initiated\n");
delay = msecs_to_jiffies(5000); //Manually given 5000ms (5 sec) for scheuling
if(!my_wq)
my_wq = create_workqueue("my_queue");
if(my_wq)
{
schedule_delayed_work(&my_work, delay); /*schedule for the first time while module initiates*/
}
return 0;
}
void sig_cleanup_module(void)
{
flush_scheduled_work();
cancel_delayed_work_sync(&my_work);
flush_workqueue(my_wq);
destroy_workqueue(my_wq);
printk(KERN_DEBUG "signal module removed\n");
}
module_init(sig_init_module);
module_exit(sig_cleanup_module);
Kindly help me to have a solution for this. Thanks in advance!!!.
I don't understand why kernel modification would be desirable or necessary. If you want something periodically done (e.g. log rotation), add it to cron. Another option would be to use timerfd.
use mktime() function in kernel code which takes the wall time as arguments and directly returns the jiffies value.
For info about mktime, see this http://www.makelinux.net/ldd3/chp-7-sect-2
Attempting to use mbed OS scheduler for a small project.
As mbed os is Asynchronous I need to avoid blocking code.
However the library for my wireless receiver uses a blocking line of:
while (!(wireless.isRxData()));
Is there an alternative way to do this that won't block all the code until a message is received?
static void listen(void) {
wireless.quickRxSetup(channel, addr1);
sprintf(ackData,"Ack data \r\n");
wireless.acknowledgeData(ackData, strlen(ackData), 1);
while (!(wireless.isRxData()));
len = wireless.getRxData(msg);
}
static void motor(void) {
pc.printf("Motor\n");
m.speed(1);
n.speed(1);
led1 = 1;
wait(0.5);
m.speed(0);
n.speed(0);
}
static void sendData() {
wireless.quickTxSetup(channel, addr1);
strcpy(accelData, "Robot");
wireless.transmitData(accelData ,strlen(accelData));
}
void app_start(int, char**) {
minar::Scheduler::postCallback(listen).period(minar::milliseconds(500)).tolerance(minar::milliseconds(1000));
minar::Scheduler::postCallback(motor).period(minar::milliseconds(500));
minar::Scheduler::postCallback(sendData).period(minar::milliseconds(500)).delay(minar::milliseconds(3000));
}
You should remove the while (!(wireless.isRxData())); loop in your listen function. Replace it with:
if (wireless.isRxData()) {
len = wireless.getRxData(msg);
// Process data
}
Then, you can process your data in that if statement, or you can call postCallback on another function that will do your processing.
Instead of looping until data is available, you'll want to poll for data. If RX data is not available, exit the function and set a timer to go off after a short interval. When the timer goes off, check for data again. Repeat until data is available. I'm not familiar with your OS so I can't offer any specific code. This may be as simple as adding a short "sleep" call inside the while loop, or may involve creating another callback from the scheduler.
I have two modes that I want to switch between with an interrupt that is generated by a sliding switch. Initially I read the current position and choose a mode/function. I want to switch between the two right when the position of the switch is changed. I have an interrupt which occurs on both edges (whenever the position is changed). However since both functions run continuously in a while loop, I can't just call them in the interrupt. Basically I have something like this:
interrupt()
{
//not sure how to switch between modes here
}
main()
{
//choose mode on startup
if (switch_HIGH)
modeA();
else
modeB();
}
modeA()
{
while(1)
{
//do something
}
}
modeB()
{
while(1)
{
//do something
}
}
I don't know if it's a good idea to just leave a function where it is and just move to something else but I can't think of any other way to do it. I'd really appreciate it if someone could tell me how I can go about this.
The language I'm using is C and the platform is a NIOS system on a Altera DE1 development board.
Using an interrupt for this seems very pointless; it's much simpler to just poll the input on each loop, and call the proper function just as you're doing.
UPDATE: I just relized your code doesn't have a loop, so the above is a bit hard to understand, of course.
I meant that you can structure your program like this:
int main(void)
{
initialize_hardware();
while(1)
{
if(switch_HIGH)
modeA();
else
modeB();
}
}
This makes the CPU go around in an infinite loop, and on each iteration it checks the switch and calls either modeA() or modeB() depending on the current mode.
Adding an interrupt gains you nothing except adding more complexity.
That said, what I would do is use a function pointer to indicate the current mode, and change the function pointer's value inside the interrupt, depending on the state of the switch. Then in the main loop just call the pointed-at function.
Remember to initialize the function properly, since you probably won't get an interrupt when teh device comes out of reset. This is another argument against this solution; the complexity is much bigger than just checking the switch on each iteration.
How about calling the two functions as threads. The interrupt function can kill the active thread and start the other thread. Pseudo code:
thread threada,threadb;
flag a=0;
interrupt()
{
if(a==0)
{
thread_kill(threada);
threadb=thread_create(modeB);
a=1;
}
else
{
thread_kill(threadb);
threada=thread_create(modeA);
a=0;
}
}
main()
{
thread_create(threada);
a=1;
}
modeA()
{
while(1)
{
//do something
}
}
modeB()
{
while(1)
{
//do something
}
}
Rather than killing the thread, you can have graceful shutdown mechanism using some kind of synchronization.