I am familiar with using mgos_msleep(value) or mgos_usleep(value). However, using sleep is not good for the device.
Can someone suggest a better approach?
It depends on the architecture of the system and use case with you.
The sleep call in mongoose OS does not cause a busy wait. The sleep call conveys to OS to not schedule the particular process until the sleep duration is over. The 'mgos_usleep' function is a sleep with greater resolution (microseconds) which should have very less impact, however this in turn is based on your requirement / use case.
With respect to timer, the Mongoose OS supports both software timers and hardware timers. The decision to use either software timer or hardware timer is in turn based on the application requirement with you.
The mgos_set_timer sets up a software timer with milliseconds timeout and the respective callback. The software timer frequency is specified in milliseconds and the number of software timers is not limited.The software timer callback is executed in mongoose task context. This timer seems to be with fairly low accuracy and high jitter.
The mgos_set_hw_timer sets up a hardware timer with microseconds timeout and the respective callback. The hardware timer callback is executed in the ISR context and hence the actions are limited due it. The hardware timers or counters shall be available as per the type of processor that you use, hence you may need to have a look at the datasheet. Accordingly, the number of hardware timers is limited and the frequency is specified in microseconds.
Related
I have Read about co-operative Scheduler which not let higher priority task run till lower priority task block itself. so if there is no delay in task the lower task will take the CPU forever is it correct? because I have thought the non preemptive is another name for cooperative but there is another article which has confused me which say in non preemptive higher task can interrupt lower task at sys tick not in the middle between ticks so what's correct ?
is actually cooperative and non preemptive are the same?
and Rate monotonic is one type of preemptive scheduler right?
it's priority didn't set manually the scheduler Algo decide priority based on execution time or deadline it is correct?
is it rate monotonic better than fixed priority preemptive kernel (the one which FreeRtos Used)?
These terms can never fully cover the range of possibilities that can exist. The truth is that people can write whatever kind of scheduler they like, and then other people try to put what is written into one or more categories.
Pre-emptive implies that an interrupt (eg: from a clock or peripheral) can cause a task switch to occur, as well as it can occur when a scheduling OS function is called (like a delay or taking or giving a semaphore).
Co-operative means that the task function must either return or else call an OS function to cause a task switch.
Some OS might have one specific timer interrupt which causes context switches. The ARM systick interrupt is suitable for this purpose. Because the tasks themselves don't have to call a scheduling function then this is one kind of pre-emption.
If a scheduler uses a timer to allow multiple tasks of equal priority to share processor time then one common name for this is a "round-robin scheduler". I have not heard the term "rate monotonic" but I assume it means something very similar.
It sounds like the article you have read describes a very simple pre-emptive scheduler, where tasks do have different priorities, but task switching can only occur when the timer interrupt runs.
Co-operative scheduling is non-preemptive, but "non-preemptive" might describe any scheduler that does not use preemption. It is a rather non-specific term.
The article you describe (without citation) however, seems confused. Context switching on a tick event is preemption if the interrupted task did not explicitly yield. Not everything you read in the Internet is true or authoritative; always check your sources to determine thier level of expertise. Enthusiastic amateurs abound.
A fully preemptive priority based scheduler can context switch on "scheduling events" which include not just the timer tick, but also whenever a running thread or interrupt handler triggers an IPC or synchronisation mechanism on which a higher-priority thread than the current thread is waiting.
What you describe as "non-preemptive" I would suggest is in fact a time triggered preemptive scheduler, where a context switch occurs only in a tick event and not asynchronously on say a message queue post or a semaphore give for example.
A rate-monotonic scheduler does not necessarily determine the priority automatically (in fact I have never come across one that did). Rather the priority is set (manually) according to rate-monotonic analysis of the tasks to be executed. It is "rate-monotonic" in the sense that it supports rate-monotonic scheduling. It is still possible for the system designer to apply entirely inappropriate priorities or partition tasks in such a way that they are insufficiently deterministic for RMS to actually occur.
Most RTOS schedulers support RMS, including FreeRTOS. Most RTOS also support variable task priority as both a priority inversion mitigation, and via an API. But to be honest if your application relies on either I would argue that it is a failed design.
As it relates to process scheduling by the OS: I understand that the scheduler requires a "clock" like device, known as an interval timer, to keep track of the amount of time used by each process and when to switch to a ready process.
My question is - where does the interval timer run? It seems like it needs to be running constantly, parallel to any processes, so that it can always keep track of time, including the amount of time being used by the running process. But as we all know only one thing can run on a CPU at any one time, and if the process is running, it means the interval timer cannot run. So therefore, is the interval timer implemented in hardware rather than software? And if so, if I was building a custom OS and scheduler, how would I access and communicate with it in my custom scheduler code?
The "interval timer" as you call it is a hardware timer. It generates an interrupt at a fixed period. When the "RTOS tick" interrupt occurs, the tick handler (typically):
increments the tick counter,
updates any running software timers,
if a task delay or software timer expires, any task blocked on that becomes ready,
the scheduler is run, the highest priority ready task runs.
Note that this is not the only time the scheduler runs. For example scheduling occurs whenever a task explicitly suspends on a delay, timer, semaphore, mutex, event flag, or mailbox for example. Any RTOS call that causes the running task to block/wait causes the scheduler to run.
And if so, if I was building a custom OS and scheduler, how would I access and communicate with it in my custom scheduler code?
You would simply configure the hardware timer to generate the tick interrupt and proceed as above. You might take a look at an existing open-source RTOS to see how it is done. Although FreeRTOS which you tagged is not exactly conventional, uC/OS-II may be a better starting point - it is deliberately simple and was originally implemented to teach RTOS design and implementation. The associate book describing the kernel is freely available in PDF form at https://weston-embedded.com/micrium-books.
I'm working a project where I am getting digital samples continuously through DMA on STM32f4. DMA generates a complete callback interrupt after every sample where I do some DSP. My plan is to allow freeRTOS to work on other tasks while DMA is waiting on the callback. However, DMA is generating callback too frequently, not allowing freeRTOS to run. I want to make it so that after every DMA complete callback, freeRTOS tasks is allowed to run for 6ms. I thought of calling __disable_irq() from complete callback and __enable_irq() from one of the tasks but that would not guarantee 6ms also I have a high priority button interrupt. I also tried disabling just DMA interrupt calling __set_BASEPRI(priority<<(8-__NVIC_PRIO_BITS)) then starting a timer for 6ms. On timer period elapsed callback in call __set_BASEPRI(0) to enable DMA interrupt. But for some reason this did not allow freeRTOS to run at all. It goes back and forth between DMA complete callback and Timer period elapsed callback.
I am new to embedded programming so any comment on this will help. Thank You.
You should not think of the DSP process being separate from the RTOS tasks, do the DSP in an RTOS task - the signal processing is the most time critical aspect of your system, you have to process the data as fast as it arrives with no loss.
If the DSP is being done in an interrupt context and starving your tasks, then clearly you are doing too much work in the interrupt context, and have too high an interrupt rate. You need to fix your design for something more schedulable.
If your DMA transfers are single samples, you will get one interrupt per sample - the ADC will do that on its own; so using DMA in that manner offers no advantage over direct ADC interrupt processing.
Instead you should use block processing, so you DMA a block of say 80 samples samples cyclically, for which you get a half-transfer interrupt at 40 samples, and full-transfer interrupt at 80 samples. So for each interrupt you might then trigger a task-event or semaphore to defer the DSP processing to a high-priority RTOS task. This achieves two things;
For the entirety of the n sample block acquisition time, the RTOS is free to:
be performing the DSP processing for the previous block,
use any remaining time to process the lower priority tasks.
Any interrupt overhead spent context switching etc. is reduced by 1/n, allowing more time performing core signal processing and background tasks.
Apart form reducing the number of interrupts and software overhead, the signal processing algorithms themselves can be optimised more readily when performing block-processing.
A variation on the above is rather then triggering a task event or semaphore from the DMA interrupt handler, you could place the new sample block in a message queue, which will then provide some buffering. This is useful if the DSP processing might be less deterministic, so cannot always guarantee to complete processing of one block before the next is ready. However overall it remains necessary that on average you complete block processing in the time it takes to acquire a block, with time to spare for other tasks.
If your lower priority tasks are still starved, then the clear indication is that your DSP process is simply too much for your processor. There may be scope for optimisation, but that would be a different question.
Using the suggested block-processing strategy I have in the past migrated an application from a TI C2000 DSP running at 200MHz and 98% CPU load, to a 72MHz STM32F1xx at 60% CPU load. The performance improvement is potentially very significant if you get it right.
With respect to your "high-priority" button interrupt, I would question your priority assignment. Buttons are operated manually with human response and perception times measured in 10's or even 100's of milliseconds. That is hardly your time critical task, whereas missing an ADC sample of a few microseconds would cause your signal processing to go seriously awry.
You may be making the mistake of confusing "high-priority" with "important". In the context or a real-time system, they are not the same thing. You could simply poll the button in a low-priority task, or if you use an interrupt, the interrupt should do no more than signal a task (or more realistically trigger a de-bounce timer) (see Rising edge interrupt triggering multiple times on STM32 Nucleo for example).
What is the mechanism used to account for cpu time, including that spent in-kernel (sys in the output of top)?
I'm thinking about limitations here because I remember reading about processes being able avoid showing up their cpu usage, if they yield before completing their time slice.
Context
Specifically, I'm working on some existing code in KVM virtualization.
if (guest_tsc < tsc_deadline)
__delay(tsc_deadline - guest_tsc);
The code is called with interrupts disabled. I want to know if Linux will correctly account for long busy-waits with interrupts disabled.
If it does, it would help me worry less about certain edge case configurations which might cause long, but bounded busy-waits. System administrators could at least notice if it was bad enough to degrade throughput (though necessarily latency), and identify the specific process responsible (in this case, QEMU, and the process ID would allow identifying the specific virtual machine).
In Linux 4.6, I believe process times are still accounted by sampling in the timer interrupt.
/*
* Called from the timer interrupt handler to charge one tick to current
* process. user_tick is 1 if the tick is user time, 0 for system.
*/
void update_process_times(int user_tick)
So it may indeed be possible for a process to game this approximation.
In answer to my specific query, it looks like CPU time spent with interrupts disabled will not be accounted to the specific process :(.
Does context switch between process take equal time for all the Process ( Constant Time ) or the context switch time is dependent on various local factors which varies from process to process ( like process size,stack size etc..) ?
EDIT :
Assume the OS and Hardware are fixed, means will the time be same in a given OS and hwd. environment ?
It varies with hardware as well as OS/process :( To run a thread from a different process, memory-management context, floating-point context etc. must be swapped. This is easier/quicker on some hardware than others.
Drivers vary widely in the time they take to handle their hardware and signal the OS that a thread should be made running - so that's another complication.
In some cases, such a swap may need the preemption of a thread running on another core than the one that received the hardware/software interrupt that initiated the swap. This takes a lot longer than swapping context on the same processor.
It's difficult to come up with any sort of average figure on this. Where would you time it from - the driver interrupt that initiated the inter-process thread swap or from the entry to the scheduler from the driver?
So, overall, we can probably agree that it takes some time and it can vary.