Tips to Reduce processor load

Hello guys,

I have to reduce the processor load, in a way like unwanted code should not run unnecessarily.

So that I am making my system partially event based, and I am giving priority to each event so that every part of the code (event handler) has a priority.

could you please suggest me something on this to improve my code.

Thanks for your contribution.

The first question is why do you even HAVE “unwanted code” that is running “unnecessarily”?

In a real-time system, code should be designed to only run when it is needed, and should be blocking when it isn’t.

Using an “Event Based” system is a way to make a single task do different things based on what is happening, but such a system requires that YOU the programmer, design the system to meet your requirements.

one crucial thing to determine is which of your tasks are cpu bound (ie spend the majority oth their time making CPU intensive computations) or I/O bound (spending most of their time suspended waiting for I/O), respectively. An RTOS works best for a mix of the two where you can “squeeze the cpu bound computations” into the time periods where the I/O bound compuations are waiting.

If most your tasks positively need lots of CPU time, the only gain from a preemptive RTOS is that all tasks make some progress over time, but the overall throughput will not change (single core MCU assumed, SMP is of course another level).

Another thing to consider is task interdepencency; a lot of people tend to be overcautious and back door serialize tasks or (on the other end) split up fully serialzed code paths unnecessarily into muliple tasks which makes them co routines.

As Richard pointed out, it is mostly an issue of system design.

Hi. Probably you wish to save a battery? If so,
enable Idle hook by setting configUSE_IDLE_HOOK to 1 in OS configuration. Then provide the functon: vApplicationIdleHook()
And in that function put STOP or SLEEP command for the CPU. How to exit from STOP or SLEEP mode is anoter story which is depending on the system you running the OS on. Also while exiting the STOP or SLEEP, the system timer should be restored to keep the time correctly if was stopped during sleeping time.

Using tickless idle is a better way to do that: Low Power Support - FreeRTOS™.

Actually, which is better depends a lot on use case. tickless idle is a good and easy to implement system to give modest gains when you don’t know well what the system will be doing. With the IDLE HOOK, you can go into much lower power modes if you know that you really don’t have something to do for a while.

For me, tickless idle is the best in all cases, even on ports that don’t include a default tickless implementation. The Cortex M ports include a default implementation, which includes hooks to allow you to customize. To Richard’s point, if you don’t customize it or replace it, you’ll get only modest gains (basic sleep).

Tickless idle is designed specifically to allow you as the developer to select the depth of low-power mode. Whatever sleep code you would write with the idle-hook approach, you should write for tickless idle instead. With tickless idle, the architecture for entering/exiting low-power mode is already in place; FreeRTOS tells you the expected idle time and helps you manage the race conditions associated with going to sleep.

You can go either way (idle hook or tickless idle) and accomplish all the same things, but the tickless idle API is tailored for low power.

Hello guys,

My requirement is every function should meet it’s deadlines, So that I need to come up with a solution for this.

I am attaching my code below, It would be so helpful if you give feedback (Pros & Cons) on my design.

scheduler_version_2.c (3.5 KB)

vcuExApp.c (1.1 KB)

scheduler_version_2.h (1.1 KB)

Thanks for your time and efforts.

First, I will note that your code doesn’t “schedule” anything, just dishes out requests at defined rates, hoping that things complete in time.

Second, it seems your basic structure is to shoehorn any operation into some repetative operation at one of a couple discrete rates, so if you need an action every 50 ms, you need to schedule every 10, and skip 4 of 5, which will cause a lot of “dead” context swaps.

A given “module” seems to be able to have both long infrequent operations, and short fast one, but because you just handle them as they come up, and don’t have any pre-emption ability, the quick operations can be delayed by the slow ones for a given module.

This code is NOT “event based”, but just crude time tick based.

To meet a requirement of meeting deadlines, you first need to specify the deadlines. Operation rates are NOT deadlines. You might have a task that needs to be once a second, but it might be very urgent and need to be finished with a few milliseconds of that second boundry, for instance if you are producing a “pacing” tick. You also need to know the resources needed by each of the operations, like the time they will need the CPU, and time that will elapse while they are waiting for something to complete.

Your limiting factor is that your design blends all sorts of different types of requests into a single channel, mixing potentially long operations to block urgent ones.

Part of the issue is that the code seems to be based on the idea of Task == Module, every module having a task and tasks are assigned to modules, and these tasks are constrained to have similar APIs, and thus how a module works is molded into that framework. My preference is to first think about the operations that a given module needs to perform, and then based on that figure out what sort of implementation to use, perhaps using a task, or a timer call back, or just do things in a module API request call. This means that tasks only wake up and do something if they actually have something to do, and thus there is no unwanted code running.

Adding your “scheduler” on top of the FreeRTOS scheduler is just creating opportunity for busywork, and waste.

Hi @richard-damon ,

I will clarify my requirement first.

  • each module will have each task, each task should execute 10ms,100ms and 1000ms function periodically.

  • when ever a task required to execute a function then only it should run otherwise that task should be in blocked state.

  • I will calculate the deadline of each function in a task and keep it less than a milli second.

This depends on the module priority, If a task(module) priority is high then it wont be blocked.

But this is my requirement here, It may waste the time of the task by executing this periodic functions, but the project needs to be done module by module, work happening in this formate.

It would be great help if you give any ideas in this architecture where and all I can save the processor load, and code should be in the format of easy to debug?

Thanks for your suggesions.

This isn’t a “requirement”, but a design strategy, and as I pointed out, not a good one.

Again, not actually a requirement, but a design stratagy. Requirements are WHAT needs to get done, and and BY WHEN, not HOW.

You still don’t seem to understand what a requirement is.
The deadline is when the task needs to be done to meet the functional requirements. As the implementing programmer, you don’t get to make these up, the come out for the functional requirements developed by the system designer (which might also be you wearing a different hat). You can calculate when that deadline is (numerically), but the deadline was always the deadline, unless it never really was one.

When does the operation really need to be done for the system to be FUNCTIONAL? Not just when you would like it to be done based on swag guesses of allocations.

This sounds more like a decision that you want you code to be “fast”, and not actually work on what your actual requirements are.

Sure it will be, because if the module is already running one operation, it can’t start another because you don’t look for it until it finishes the previous one. Note, “block” here is about the OPERATION, not the task state. Since you allocated a single task for all of 10 ms, 100 ms, and 1000ms operations, one of these will “block” the task from doing a different on. If you really mean that the operations actually have a functional deadline of 1 ms from when the interrupt requesting them to occur, that means that the SUM of the times for those 3 functions must be less 1 millisecond, and not higher priority task get it its way.

No, I doubt that is your actual requirement, unless you have a boss that doesn’t understand requirements and tasked you this way.

Requirements are rarely that generic: “All modules might run functions at 10ms, 100ms, or 1000ms periods that must be completed within 1 ms of their requesting” doesn’t sound like an actual functional requirement, but a system implementation designed to try to support limited real time support, and one that needs very careful coding to make sure you keep the requests apart, and the work for each one small enough.

But your problem IS you architecture.

You ask about reducing waste, but then say that the waste is part of the “requirements” (which aren’t really the requirements, but an implementation decision)

My guess is this format came out of a “big ol’ loop” code design which was decided needed improvements, and has been given just a surface treatment to try to do that. Task == Module is a common crutch used when doing that. As I described before, the definition of Tasks is a later implementation decision on how to implement on operation defined by the system operational requirements, not part of those requirements. (remember, requirements are WHAT and WHEN, not HOW)

In my experience, “real time” operations are normally NOT operaitons run strictly periodically, but are done in RESPONCE to something happening, which ideally is something that can generate an interrupt to the processor, or is something detected in other processing that is going on. Yes, sometimes you need to be periodically sampling to get data to detect, but then the response time is inherently slower based on that sampling rate, and include an inherent processor load for that sampling.

Hi @richard-damon ,

So you are telling design itself is wrong.

And functional requirement means:

  • what needs to be done
  • when it needs to be done

Not how it needs to be done, understood.

So Can I make the system design like every interrupt to the system is event. I will process the event in event handler, I will change the state of the system based on the event if required, running the main state machine, state transition based on the event?

Could I develop in this way otherwise could you suggest me any RTOS based firmware architecture for battery management system?

Thanks for helping me out.

Interrupts ARE “events” to the processor, but the ISR is often not the “event handler” for the program, but translates the CPU event into an event for some sub-system in your program.

When you talk of a “main” state machine, be a bit careful. “Real-time” systems tend not to break down into a single master state machine, as that sort of system tends not to need the resources of a “real-time” operating system as a single state machine tends not to need significant parallel operations.

There might be a main state machine that handles major functional state of the system, but there will normally be several other state machines taking input from that overall state, as well as other events, processing things not directly under the control of that main state machine.

As for your application of a “Battery Management System”, if that is the full goal of the system, I would likely not use a RTOS, as normally a prime requirement is minimal use of power, and the processing requirements tend to be simple enough that the overhead wouldn’t be needed. It could well be one of the sub-systems of a larger system using an RTOS.

Hello everyone,

my system requirement is

1)Need to send CAN messages out

  • 10 messages should be transmitted every 100ms
  • 10 messages should be transmitted every 500ms
  • 10 messages should be transmitted every 2000ms

2)Need to send vehicle data to cloud every 2sec

3)Need to handle user inputs.

For this requirement I am planing to create 3 tasks.

refer the below attached code give me your valuable suggestion if any correction is needed in my approach.

del.c (1.6 KB)

Thanks and regards.

The CAN task should be taking minimal time if we assume the CAN driver is interrupted based. Given that, I likely wouldn’t use ANY of your time based ISRs, but setup the system to have a system tick that was at 100 Hz (or some multiple of that) and use a xTaskDelayUntil to send messages at 100 Hz, being at base, one of the 100 ms messages, and rotate between them. For every 5 of those, you add sending after it one of the 500 ms message, and every 20 of them one of the 2000 ms messages. This task likely should be the highest priority so none of the messages gets delayed. By using xTaskDelayUntil, the system will try to catch up if it does fall behind for some reason.

The send to cloud would be another vTaskDelayUntil with a 2 second period doing your cloud send. This task could be the lowest priority.

The user interface task looks reasonable, you have ISRs sending flags to be handled, and a loop to process them. You should test the return value of the xTaskNotifyWait, and if it didn’t get a notification, don’t try to process what you didn’t get. Also, since it is possible to have multiple events sent that get read at once, don’t use a switch testing for each bit individually, but just check each bit in sequence and process it if needed. This task would be a medium priority task. Its operation can be momentarily suspended to handle the more critical CAN task, but it doesn’t want to be delayed by the slower cloud operations

Overall, the program feels like it has grown out of a “bare metal” background, as it makes minimal use of FreeRTOS to handle scheduling.

Hi @richard-damon ,

Thanks for your reply,

I have one more task, which has 5 function that doing heavy calculation, each function takes 5 to 10 ms time to finish the execution.

But here I need every function should execute every 500ms, but the function is executing every 543ms because of the function execution time, is there any way I could resolve this?

any drawback is there from this design?

What you have shown so far has fairly little overhead, so nothing that could be significantly improved.

The drawback is complexity, and adding a bit of processor overhead for the ISR and queue operations. I don’t think it adds up to the 8.6% you are running short, but it could be contributing to it.

If you are running out of CPU resources, it is best to look at what is actually using a lot of the resources. Something doesn’t add up in your numbers as the 5 functions, even if they take the high end 10 ms each, only add up to 50 ms of usage, not the 543 ms.

Could you perhaps NOT be using interrupt based I/O? If your CAN bus operations are blocking, and use up the CPU for the whole transfer, THAT could be a major problem. Often the example vendor drivers are not interrupt based, or at least the simpler ones to use are not. It may be you need to switch to an interrupt based design, maybe needing to write the driver yourself if they don’t provide one.

Hi @richard-damon ,

Can I use same timer ISR based notification method to call these function every 500ms?

void taskHandler(void* parm)

{

xTaskWaitNotify(&notifyValue,pdMS_TO_TICKS(portDELAY_MAX - 1))

{

switch (notifyValue)

{

case 1:

fun1();

case 2:

fun2();

case 3:

fun3();

case 4:

fun4();

case 5:

fun5();

}

}

}

ISR()//triggers every 100 ms

{

if(++count <= 5)

xTaskNotify(taskHandler);

}

else

{

count = 0;

}

}

will this approach cause any issue?

Mostly, but why are still trying to setup another ISR timer when you have a perfectly good one with the FreeRTOS tick?

The problem with your ISR is that one time in 5 it doesn’t notify anybody due to the if. You also need to pass the value to set for the notification value.

You also need to put the task into an infinite loop, or you ARE wasting a lot of time creating tasks.

Hi @richard-damon ,

So you are telling I can use systick handler instead of hardware timer to notify my task?

understood I will pass the count value as notifyValue.

okay, I will use while (1) inside the task. where and all I am wasting cpu time in this approach?