So, a question to you. What is an operating system? What do you expect from an operating system? Simultaneous running of the tasks, implementing different modules, hardware resources management, interrupt and scheduling of the tasks. All these operating systems should handle. However, now let's focus on a microcontroller. A thing running, for example, at 72 MHz, having one single core and doing everything it can to manage your application. So, a question, can a single core of Cortex-M4, for example, execute tasks in parallel? No, it can't. There is one core, one execution pipeline for instruction. So, it always will execute one instruction at a time, which means that it can switch between the tasks very quickly, but it can't execute them truly in parallel. So, it's from the user perspective that they run in parallel because they, for example, switch every millisecond or faster and at that moment, you as a user have the feeling of the parallel execution, but for the microcontroller, it's a heavy job of doing part of your tasks, switch to another one, do another task, switch to another one, do it, switch to another one, check if it is synchronized and waiting for a good thing and then coming back to the first one. So, it's always doing a part of the job and coming to another job. The Friartos can't be compared to something like Windows because it's a tiny scheduler, it's a tiny thing to switch the tasks and manage synchronization between them. It's nothing that would contain peripheral drivers. It's nothing that would give you for free networking. So, if you want to implement something big, it gives you the tools to create it, but it doesn't give you all the ecosystem integrated inside just like it is. So, it needs a little bit of work. In the best case, clicking on I want the Ethernet stack in a QBemix and let it generate your code. So, this is the minimum you need to do to have a working communication stack on top. But the Friartos itself is not responsible for the connectivity. So, the operating system is something that takes care about the environment where your applications are running. Same definition is valid for the Friartos, but you can't expect a really big implementation, especially if you run on small microcontrollers and you on top expect, for example, a low current consumption. So, a question, what is a task, is explained on the slide. You can see that in terms of the definition on a microcontroller, it's a C function. The C function typically has got some initialization code and then it has got a never-ending loop. In this never-ending loop, your task or mini-application should be executed and it should manage its communication and lifetime. It should as well manage its own timing. This mini-program or mini-application has as well associated its own stack in a place where it can place local variables and, for example, return address and context when it gets into the interrupt or into sub-functions. So, each of the mini-applications has its own stack defined in the memory and it has as well a priority. The priority can be changed dynamically so you can increase it and decrease it in the application lifetime. But it has a very big meaning when the core of the Friartos schedules which task will operate next. So, the whole idea behind the Friartos is to give you a time slice. This is a time that the microcontroller spends executing your task and when it's time slice elapses, for example, after a millisecond of periodical interrupt, the scheduler will take the list of the running tasks and it will look which one has currently the highest priority. And then it will switch to this one and execute it maybe for another millisecond and then it will again enter this switching process and it will check, hey, is there another task that is alive that has highest priority than this one? And if yes, Bingo will switch to it and we will execute it. So, this is the way how the Friartos or typically any other Artos takes care about task switching. You will later see that there exists a preemptive task switching and cooperative task switching. This has quite a big impact on the design of your application. So, you will see later in detail. Further, each of the tasks can operate in four different states. The first one is when it is created, it becomes ready. What that means? Red means that such task is able to be executed. So, the scheduler can pick it up and it can start execution. However, when I have got a task with a higher priority, I can put this task aside and it can be as well put back to ready state. So, it comes from ready to running and back from running to ready. And that's the decision of the scheduler which task will execute. There is one more possibility when the task asks for a resource that is not available. It can be data in the queue, it can be a mutex, it can be waiting for a semaphore or for a signal. So, if such resource is not available, the task can become blocked. At that moment, the scheduler will remember that the task waits for something. And it will put in a specific queue in a specific list telling that it's blocked and it waits for a resource. And when the resource becomes available, like somebody releases the mutex or you get a semaphore or you send a message to this task, the kernel will evaluate it. It will notice that this task received the message. It will unblock it and it can move it back to the ready state. And if this task currently when it's unblocked has the highest priority, it will come back to the running state immediately. Additionally, you can force the task to a suspended state where it's removed from the scheduling process and it doesn't consume any CPU time. It has one advantage, you don't bother with this task, you don't waste the time evaluating its priority. So, it's very effective when you simply need to remove this task and don't care about it. Still, it's there. You have it at hand, you don't need to recreate it. You can execute it any time you want when you remove it from the suspended state. These are the main states that you can expect from any of your many tasks or many applications. The transition between all these comes in terms of API calls to the kernel or by the scheduler itself. So, you can, for example, force yourself from the running state to the ready. If you call the function OS yield, you just give up the CPU time and you let the scheduler select another task if it is available. So, you get, for example, into the blocked state if you wait for some time. You can say, okay, now I'm toggling the LED. So, let's put the task into the blocked state by calling a delay function. So, you want to toggle the LED every 200 milliseconds. So, your function will look like LED toggle and OS delay 200 milliseconds. Then the task will be automatically put into the blocked state for 200 milliseconds and the scheduler will put it back to red after the 200 milliseconds elapsed. So, it gives you the chance for timing the task execution. Now, when you know how the tasks change their lifetime and how they cooperate through the scheduler, you probably should understand that if you have already a CPU running at 100% of your time in a bare metal application, putting a free RTOS may not be a big help for you. Because performance-wise, you will spend approximately 0.1, 0.5% of the time in task switching. But free RTOS can help you in simplifying your application and splitting it into much more simple tasks. But it will not help you to accelerate it, especially if you already use all the microcontroller time and you will put the free RTOS on top of this. Priority of the tasks, it will help you in managing the communication between them, but it will not increase the performance. Of course, if you have functions that, for example, spend too much time by synchronization of the data between the tasks, free RTOS can be more effective. If you need to wait for a given resource, then, for example, switching in the state machine, whether it will go this way or this way, the free RTOS can give you a little bit more performance. But overall, it will not increase the performance. One more thing, the task should never end. If you leave the task function, you crash the free RTOS. That's because it doesn't have any return address. It doesn't know where to return. The next thing you should expect from the free RTOS is its scheduler. This is a background part of code that takes care about switching between the tasks. The scheduler is a thing that gets called by different API functions. At the end of interrupts and whenever you, for example, call a blocking function. When it's activated, it decides what other tasks should be running. It can decide that it will return back to the original task if it's the only one with the highest priority. But if by internal or external API calls, another task became ready and it gets higher priority than the current one, then the scheduler will choose the task with the higher priority. It's always about priority. And if you have two or more tasks with the same priority, then it will move in a under bin. So if I have got three tasks with the same priority and task number one finishes, then it will look into the task number two. And if task number two finishes, it will look in task number three. And when three is finished, then it will look again in task number one. But if you have a task number five with higher priority, it will always jump to task number five if five is ready. Now, what is differentiation between a preemptive and cooperative mode? This is a very important thing to understand. And this is as well about fine-tuning your application. In preemptive mode, if a task gets a higher priority and becomes ready, it is immediately switched over. So you can see here that if task number two is awakened or if the scheduler gets, for example, a time-based tick, it can immediately jump to the task number two if it has a higher priority than task number one. So in preemptive mode, the task switching happens immediately when the kernel knows it, when it recognizes it. And it can be on the function call, it can be on the periodical interrupt on the time-base, or from interrupts by sending signals, messages, or other synchronization objects. So in preemption, the task switching happens anytime in your application lifetime. The cooperative mode is different. In cooperative mode, the kernel will not switch immediately, but it will switch only when the original task gave up its time by getting into the blocked state. So in cooperative, you always must create functions by the way of calling OS delay, OS yield, or waiting for some synchronization object. Otherwise, even if the task one has a lower priority than task two, the task one, if it never gives a CPU time, it will never switch to task two. So even if task two has a higher priority, it must wait until task one finishes its job. The truth is that the preemptive gives you a feeling of faster responsiveness. But on the other side, I could say that the preemptive mode is a little bit less efficient because the task switching takes some time and additionally, if you need to synchronize the tasks, for example, their timing, it can be a little bit more difficult to handle. While in cooperative mode, if you are waiting for something, if you are stuck in a task that, for example, does an FFT calculation, then you are stuck for this time. But the FFT is finished as one block and you have got the result in the shortest possible time. So when I do my applications, I prefer the cooperative because it seems to me to be a little bit more stable. I can tell you that I've got some demo application created that runs approximately 22 tasks. And in the cooperative mode, it works. If I switch it to the preemptive, it doesn't crash but doesn't work well. So you have to test it. You have to think well how you design the application. Further, let's talk about the heap of the operating system. You already know that when you have a task, it contains a stack. Stack is part of memory where it places its local variables and context when it jumps to sub-functions or interrupts. However, these stacks need to be placed in a RAM memory and managed. And when you create a new task, its stack has to be dynamically allocated. And when you kill the task, it can be deallocated. Additionally, a lot of other objects or effectively all RTOS objects need some part of the memory that can be allocated dynamically. This allocation happens on a chunk of memory that's managed globally by the free RTOS in the heap. So free RTOS has its own heap management. And we will see later which methods can be used for the heap management. But right now, you can notice what the heap contains. So when it's created, it's initialized during initialization of the free RTOS. And then free RTOS takes care about putting different objects and allocating the memory in the heap to these objects. So the first part of the heap is dedicated for the main application, but it doesn't need to be used. It can be used, for example, for printf function and some other RTLC functions, but it's not used by free RTOS itself. Free RTOS then defines a block of memory. Normally, it can be a variable that you define as a static variable with some size. It can be as well placed anywhere in the memory, SD RAM, internal SRAM, external SRAM, and so on. But that's what the free RTOS will take care of in terms of its content and allocation. And when you look at the global RAM here that we have, we still need to allocate a stack for the interrupts and for the main application before we start and jump the scheduler. So if we look into the heap, you can see that the heap contains the data for the tasks that we define. So when I create a task A, I am creating a block of memory in the heap of the free RTOS that belongs to this task. And it consists of two parts. The first one is the task control block. This is a chunk of memory that describes the task. It tells to the scheduler where the task resides in the memory. It gives a snapshot of the CPU registers stored in this block. It contains the information of where the allocation of the stack for this task is. And it gives all the states like whether the task is ready, whether it's waiting for something. So all this information is stored in the task control block. And the second part of the task allocated memory is its stack. So when you create a task, it creates the TCB and the stack. And when it launches the task, it puts the top of the stack to the top of the area that it allocated in the heap. The advantage, each task can work as an independent many application with its own dedicated memory, which is a stack of the task. Now what happens when you create a second task? When you create a task B, the RTOS against creates or takes part of the memory from its heap and it creates its own TCB and its own stack for the task B. And now what happens when the scheduler switches from task A to task B? Who will decide how big stack you allocate to the task, right? You as a programmer. How you can do it? When you compile your application, the compiler and linker can give you a call tree with an estimated depth of the stack. So you can look in the map file or in the file that lists the call tree and you can try to deduct. Unfortunately, you have to count for recursive functions and then you don't know how deep stack you will need. So unfortunately, it's you. Of course, you can help yourself by this call tree. But another possibility is when you debug your application, you can simply give it a big stack. So as much memory as you can and when you run your application and you test it in different scenarios, in different corner cases, the stack has got, when it's created, it has got a special pattern written into it. So the free RTOS is able to check periodically and at the moment of switching to this task, how much of the stack was overwritten. So it checks from the bottom of the stack and goes upwards and looks how much dead beef is in there and it gives you this amount in the task description. So in runtime, you can observe how much stack is used for a given task and if you see there is too much unnecessary space, you can reduce it. When you create a new version of your application. So by this, you can adapt the stack size. And additionally, when a task switcher recognizes that the stack was corrupted, which means that even the bottom safety part was overwritten, it will give you or it can give you a hook that there was a stack overflow. So the free RTOS can help you in debugging such situation by telling you how much stack is used or whether the stack overflow happened. So if you have stack overflow, you should increase the stack size. But on the other side, if you see that only small part of the stack is used, you can reduce it. CortexM itself doesn't have any means of preventing the application from overflowing your stack. There is nothing in the core. On the other side, it has got a memory protection unit. So if you use the free RTOS-MPU extension, you can define for each task how big stack it has. And when you switch to it, the MPU can define regions where the task is accessible in the memory. And if it guards the stack and it runs out of the stack, you get memory protection exception. So it's possible, but the dash MPU is a specific port of the free RTOS. And it has got some support when the task creation is done, but you as well need to help yourself because it doesn't know where you have got, for example, global variables. So you need to split among the eight regions you have. Four of them are user-selectable and four of them are selectable by the free RTOS. So it can help you in this matter. But natively, without the MPU extension, this is not used. And only when you do tasks which you can recognize what happens with the stack. So I will come back to the question, what defines a context of your task in a run state? And it's executed on the core. So if you do a task switch, the scheduler will take these 17 registers. It will put them in the TCP task control block. And then it will load the same 17 registers, R0 to R15 plus the program status register from the task control block of the other task. It will simply load the registers. It will do the interrupt return. And a second task is running. That's simple it is. So whenever you get a task switch, the context switcher takes these registers, puts them in the appropriate TCP, marks the task as ready or blocked, depending. And it chooses another task, loads its own registers, and that's done. New task is running. This, however, is valid only under one condition. You don't use a floating point unit. If you use a floating point unit, there is another set of registers that need to be saved. Another 17 registers. So if you use Cortex M4, the free RTOS will require that you enable the support for a floating point unit. And it will as well deal with the floating point registers on top of the standard ones. So you need to be careful whether you enable the floating point unit or let it disabled. Additionally, when all the tasks are created and you create a new object like Q1 in this example, it's as well put on your heap. So it resides in the same heap. And you can see that by defining other objects, especially queues that can hold quite a lot of information, the amount of heap in your application can be quite quickly exhausted. So I give you one set hint. You will always fight for your memory, especially for a RAM. There is always lack of RAM for the full extent of your application.  Do you have any idea how you can save some memory if you really have a lack of heap? For example, many communication tasks, a graphical task and so on. I had an application that needed a lot of memory, but not at the same time. So I was operating with graphics, but once the graphical object was created, I didn't need this memory. Then I needed memory for a communication task, again dynamically allocated and allocated quite quickly. So if I would do this in separate tasks, if I would need this memory, each of the tasks would need to have a very big stack. So instead of that, I decided to create one super task that received commands from different tasks and it used one common stack that was shared between the tasks. So there was a switch. If I get this command, please use the memory this way and when you are finished, release it. When you get this command, again use your own stack this way and then release it. So by this way, I was able to share the memory in time, still giving many different tasks the chance to operate with a big chunk of memory. So this way, I was able to save my application until I came to another way of memory allocation, but you will see later.


This is the animation minute as always it's our jobs even though it's short and sweet Nathan is tweeting that they're looking for a effects artist if you go to the list here You can see a bunch of animation jobs as well and Gustavo is looking for pixel art animators, and that's it Now let's move over to some news Cartoon Brew is tweeting about a cheat sheet to almost every game developers remote work policies that super helpful That's cool. Disney Pixar has released light-year the teaser to their new movie. It's gonna be awesome I have an animation analysis on my channel. You want to check it out the trailer soup goal And it also comes with a brand new poster also really neat So you can brand new poster and short make sure to check us bright fright. It's the best thing ever I love it really make sure to check it out. It's correct. In other news animation showcase streams top new titles for award seasons That is the title and that's what it is Imagine Dragons has a really cool clip with really nice animation you can see school up here There's parts of it really well done as always switching over to the third by Edward I love these this time is confessions of an action director lots of cool stuff here always stories and anecdotes and tips It's great in other news Rococo has released their smarts who pro and especially cool is the ready for elevation tracking feature That is a huge upgrade speaking for cocoa. This is a crazy compilation clips of Clips that people haven't done using their suits. We're not gonna spoil this so check it out So she coming quickly to Nintendo. They have a really cool layout for the games check this out lots of art I love this. Oh so good so many for memories to check it out for three of the games It's a really cool layout Harvey Newman continues his awesome chats with people and this time it's Keith Lango I have learned everything from him when I was at school. He is a legend So make sure to check out that discussion, you know, I love to the effects. Look at this Which you can it's on loop. It's awesome speak of awesome Look at these I love the colors. I love the designs. It's really neat. I love it. So you have a loving it Look at this. That is my jam More art this time. It's 3d. That's cool little character inside. It's me and more organic nights. That's Like this look at that. That is awesome Speaking of awesome mind of three is the best TV show ever and it rivals so many movies and also has a really cool Poster here. Look at this. Oh, seriously, check out the show. It's awesome. This is crazy, too Just throw that in there a couple effects here, but let me go through the beginning. Look at this That's cool. I like it more art. So cute At this come on. I love it This is probably the crazy animation they've made. It's also super cool I love that they're playing in a slow motion and then we're going from super detailed to more low-res But still super cute great timing These are great. I love when you have sceneries like this. They're slightly animated not slightly characters moving a lot But it's great. So good and last but not least let's check this out I love if people wear backpacks and contraptions and they do stuff. It's really cool And that is that for the animation minute. You can find it every Monday on my channel at 10 a.m


The Australian Open finally done for 2023, we have some massive changes in the rankings this week, a massive change to the top of the men's rankings, and of course some changes to the women's rankings as well, but we're going to start with the past results because we had two big tournaments, WTA and ATP, Australian Open winners, let's go check out who won. Starting with the ladies champion at the Australian Open and it was of course Arena Sabalenka winning in three sets, very close match against Rabakina, 4-6, 6-3, 6-4 to lift her first Grand Slam trophy, and on the men's side of things of course Novak Djokovic winning his 20 second slam, defeating Stefano Siddi-Bas, 6-3, 7-6, 7-6, and also his 10th Australian Open and all of those players got a boost in the rankings. Let's start with the WTA rankings now because we had some massive changes, Fiontex data number one, we had a change at number two with Sabalenka getting back to number two after winning the Australian Open, she's gone three spots up, pushing down Jaberdith number three, Pagula down number four, and Garcia goes down to number five with Sabalenka closing the gap on Shfiontex, we also had a change in the middle with Goff going up to number six and Zachary getting pushed down to number seven, Kazakina stays at number eight, and Kudamatova, she drops out of the top ten making way for Bencic who goes up one spot to number nine, and Alina Rabakina, 15 spots higher than last week, finally getting into the top ten, a career high for her at number ten after making the final of the Australian Open. Having a look at the race of the finals now it's the first time we actually get to look at the race of the finals because we've got some massive points now and this is definitely going to change over the next few months, but at number one Sabalenka after winning the Australian Open and Adelaide she starts the season off on fire, Rabakina is number two after making the Australian Open final, Azarenka at three, Lynette at four after they both got a lot of points for making the semifinals of Australia, Pagula comes in at number five, Bencic at six, Gofford seven, Vekic at eight, Oztapenko at nine, and Pliskova rounds out the top ten for the WTA finals race, this of course will look so different month to month so we'll keep an update on this. Jumping over the men's ranking now and we've got a big change at the top with Novak Djokovic going up four spots to world number one again, pushing Alcares down to number two, who of course didn't play the Australian Opens, so number one again Novak Djokovic four spots higher than last week, Zizibas goes up one spot to number three which equals his career high after making the final of the Australian Open, pushing Root down to number four, Rubelev goes up to number five and Rafa, he's dropped for a number two down to number six after failing to defend his title at the Australian Open this year, Ozealia seems stays at number seven and another change with Medvedev dropping out of the top ten, four spots lower than last week allowing Fritz to go up to number eight, Root into go up to number nine which is a career high for him and her catch to go up to number ten to round up the top ten rankings after the Australian Open. Let's have a look at the ATB finals race now and very similar to the women's side, those who did well in Australia did very well on this list, Djokovic, he's at number one and Zizibas at number two, Hashinomi at number three with Paul at number four, both those guys doing well in Australia making the semi-finals, Shelton, he comes in at number five in the race to the finals with Korda at number six, Lehetko at number seven, Nori at number eight, Fritz at number nine and Rubelev rounds out the top ten but as I said this is very very early on, don't expect a lot of these names to stick around in the top ten for very long, there's a lot of other players that are trying to knock on the door and get to that finals top eight. So there it is, after the Australian Open the rankings are looking interesting and now we can start talking about the finals race of course a lot of the names in the finals race are probably not going to be there come November but it's good to get that underway and start looking at some of the points as well, let me know down in the comments below. What's the biggest shock for you? Is it the wrappers maybe dropped down or maybe Mehmedev out of the top ten or are you shocked about the women's side of things that some players maybe aren't as close as Fiontech after the first month? Remember Fiontech's got a lot of points to defend over the next couple of months so let's see if you can hang on to that top spot because Sabaleng is coming for her but it's a hell of a tournament the Australian Open it's over for another year and some big changes in the rankings this week.