Interrupt Processing

leesp wrote on Wednesday, May 24, 2017:

I am reading Section 3.2 “Deferred Interrupt Processing” of FreeRTOS book

Assuming the tick is 10ms (configTICK_RATE_HZ = 100)

According to the book, when an external event happens, the ISR “gives” semaphor to the handler task in order to unblock it (I suppose ISR can accomplish this within sub-millisec)

Now the questions is: would the handler task gets unblocked immediately, or it is only unblocked when the next tick interrupt (which is 10ms) happens?

richard_damon wrote on Wednesday, May 24, 2017:

If Pre-emption is turn on, the unblocked task is now the highest priority ready task, and the ISR is written correctly (it activates the scheduler due to seeing the higher task woken flag), then the handler task will start immediately.

leesp wrote on Wednesday, May 24, 2017:

Ok… which means the task handler will not wait for the tick interrupt to trigger it?

hs2sf wrote on Wednesday, May 24, 2017:

Exactly

leesp wrote on Wednesday, May 24, 2017:

Now I’m confused. Refer to below scenario, assuming configTICK_RATE_Hz = 100 (or tick interrupt of 10ms)

Assuming task_1’s 5000ms expires and it wakes up, but then is almost immediately Blocked because of waiting for the mutex

Then now task_2 gives the mutex

Will (a) task_1 get the mutex immediately and goes into Running, or (b) it will wait until the current tick (10ms) period is up and the scheduler select it to run?

I would suppose the answer is (b), because the Scheduler only executes at the end of each tick interrupt. Am I right?

If I am right, then this scenario is in contrary with the scenario in my previos message, where the task handler gets Unblocked immediately, and start executing** immediately**

static void task_1(void *p) //Priority: 2
{
	(void)p;
	for (;;) {
		if (disp_mutex_take()) {
			...
			disp_mutex_give();
		}
		os_sleep(5000);
	}
}
static void task_2(void *p) //Priority: 1
{
	(void)p;
	for (;;) {
        ...
		if (disp_mutex_take()) {
			...
			disp_mutex_give();
		}
	}
}

hs2sf wrote on Wednesday, May 24, 2017:

Also in this scenario task_2 goes into running state as soon as higher prio task_1 falls asleep. Provided that your os_sleep is not a busy wait :wink:
The scheduler is and obviously should be invoked on each task state transition.

richarddamon wrote on Wednesday, May 24, 2017:

You incorrect assumption was that the scheduler only runs on the tick interrupt. On part of releasing a mutex is to see if any higher priority tasks were made ready, and if so, the scheduler is run, causing a context switch.

The scheduler is run anytime the current task blocks, something happens that makes a higher priority task become ready, or (if time slicing is enabled) on a tick interrupt (to cause time slicing).

leesp wrote on Thursday, May 25, 2017:

@Richard: thanks for pointing out! I total missed the points
Question: so time-slicing is used only when there are tasks with same priority?

richarddamon wrote on Thursday, May 25, 2017:

The system alway tries to run a highest priority ready task. Thus, you will only time slice between tasks of the same priority. Low priority in a RTOS sense doesn’t mean give it less time, it means give it time only if nothing higher is ready.

As far as I know, the only case where a highest priority ready task would not be running is if Pre-emption is turn off, then the current task will continue to run, even if some interrupt makes another task ready, until the current task makes a call to a FreeRTOS function that can perform a context switch, the the switch will occur.

hs2sf wrote on Thursday, May 25, 2017:

Yes. I’d also recommend to have a look at the (free !) books
e.g. Mastering the FreeRTOS Real Time Kernel chapter 3.12 Scheduling Algorithm
s

leesp wrote on Saturday, May 27, 2017:

In this example time-slicing is enabled. Task1 & Task2 are continuos processing tasks with same priority (1). Another periodic task which uses vTaskDelayUntil(), is of higher priority (2). It was explained in the book that “At time t5 the** tick interrupt finds that the Periodic task block period has expired **so it moves the Periodic task into the Ready state”

Q. Why is it that, the Periodic task enters Ready state only when the tick interrupt expires? It is of higher priority, and isn’t it supposed to be “event-driven” by the its own “periodic timer”, rather than the tick interrupt timer (I thought tick interrupt is only for tasks with same priority)? Or am I wrong altogether?

Another question not related to this example: if configUSE_TIME_SLICING = 0, would the tick interrupt still happens?

richard_damon wrote on Saturday, May 27, 2017:

All ttime periods are measured in ‘Ticks’, by the tick interrupt. vTaskDelay/vTaskDelayyUntil establish what count of the tick iinterrupt will put the task in a ready state. Many machines don’t have enough hardware timers to give tasks their own hardware timer, so FreeRTOS uses the Tick interrupt using the one timer that it needs to perform ALL its time base services.

You should note that all delays/timeouts in FreeRTOS are specified in ‘Ticks’, which is the time period of the Tick Interrupt.

leesp wrote on Saturday, May 27, 2017:

Ok… but what happen if the tick interrupt period is for example 10ms. And there is a event-driven task which must be put into Ready state within 1ms when the event arrives?

leesp wrote on Saturday, May 27, 2017:

…or put it another way. The tick is 10ms. So the interrupt happens at t=0, 10ms, 20ms, …
Task1 (Priority 1) is periodic with period 2ms, Task2 (Priority 2) is event-driven by external event
vTaskScheduler() is started at t=0
Q1. Would Task1 be in Running state at t=2ms, 4ms, 6ms…?
Q2. Would Task2 be in Running state at, for example t=21ms, when the external event happens?

richard_damon wrote on Saturday, May 27, 2017:

You need something to happen for it to be an event. If you really need a task to run at a periodic rate of 2ms, and there isn’t some hardware interrupt about that event that happens at that rate, then youu better have the system tick be at 500 Hz (or some multiple thereof).

YOU define the tick rate via FreeRTOSConfig,h, so it is part of your system definition, and need to be set appropriate for youur system needs, Not to fast to spend too much time processing the tick interupt and checking for periodic task scheduling, but also not to slow to not have a time base accurate enough to meet your needs.

Myy experiance is that 10ms is fine to deal wiith Human Interactions, and tends to give good enough resolution for error timeouts, and that many things that need to be faster have interrupts that can trigger the operations. The one case where I find I need a faster tick would be a process control loop, to start sampling the system and updating the control, but even then, often there is a way to program the measurement to automatically kick itself off at the desired rate, and then I can use the conversion complete interrupt to kick off that process (which removes the jitter in the sampling time, which tends to reduce noise issues).

So the question goes back to, your 2ms periodic task, is it purely a time based process, in which case you need a 500Hz tick rate, or is it tied to some hardware that can be told to run at 500Hz, and generatte interrupts to tthe processor, in which case your task isn’t really a ‘periodic’ task, but an event driven task.

leesp wrote on Saturday, May 27, 2017:

Ok so my understanding is:

  • To have a 2ms period software time-based task, I need to configure the tick to be at least 500Hz. This will make 2ms the smallest time unit for any other time-based tasks. All time-based tasks thereof must have period which is multiple COUNT of ticks (1x, 2x…)

  • Context switching can always happen between the ticks (eg. t = 3.1ms) when, i) a periodic task (with period 2ms) gets Blocked after running for 1.1ms, and a lower priority continuous process task gets switched in* immediately*, ii) an external interrupt happens at t = 3.1ms, and make another higher priority task Ready, and thus it gets switched in immediately, iii) a higher priority task which is currently Blocked, gets unblocked when it receives a mutex at t = 3.1ms, and thus it gets switched in immediately
    All the above 3 cases, the scheduler selects the new task to Run immediatly even before the next tick happens (ie. t = 3.1ms). Am I right?

Another question on the mechanism of taking and giving a semaphore:
When Task1 calls xSemaphoreGive, Task2 (which calls xSemaphoreTake) gets “notified” immediately, right? How is this implemented? Does xSemaphoreGive() invokes an interrupt or something like that?

richard_damon wrote on Saturday, May 27, 2017:

Yes, All time delays are specified in Ticks, so any period needs to be based on a multiple of ticks.

Assuming you have pre-emption enabled, then a context switch can be triggered by an interrupt, or a system call. For instance, calling a Delay function will always invoke a context switch. Giving a semaphore or mutex or putting or taking an item from a queue might also cause a context switch if the action makes ready a higher priority task. Depending on the processor and the port, this MIGHT be done by triggering an software interrupt, or it might not.

hs2sf wrote on Saturday, May 27, 2017:

or just use the source the see what’s going on :slight_smile: That’s another good thing about FreeRTOS besides that it’s free - you get the complete (high quality) code !