What scheduling should I choose for my program on a FreeRTOS system? - c

I have a project (a 2-player game) made in FreeRTOS. The game has 3 tasks
(Game Render, Joystick Task and a PC Serial Communication).
Shared resources include:
Player 1 and Player 2 locations/coordinates. They are manipulated by Serial and Joystick task respectively. The game render reads both of these locations and displays them. (Player 1 location is shared with Game Render and Player 2 with Game Render).
A queue that is shared between the game render and the serial task (sending data and getting acks); the queue has been protected with a mutex on all write operations.
My question is which of these 2 scheduling is more suitable for this project: Rate Monotonic or Deadline Monotonic?
The tasks are not independent in a way that the serial communication uses acks? I think it should be Deadline Monotonic but not entirely sure?

To choose between DMS and RMS you need to know periods and deadlines for each task. From my experience it is better to focus on good overall design first and then measure and tweak the priorities to achieve best response times.
On of best summaries of good design principles I've encountered is this. In your case I would represent the two players as 'active objects' with own input event queues. Send event to the players from serial task, or even directly from ISR. The game render would then also be an AO receiving events from players, or a mutex-protected resource - it depends on what the render output is (how long does it take mostly). Serial input and serial output should be considered two separate things - in most cases it doesn't make sense to conflate the two.
Here is another link that might be useful - look at '1.4 The Design of the “Fly ‘n’ Shoot” Game'
Also, you don't need a mutex lock for xQueueSend and for sending from ISR you only need to use xQueueSendFromISR.

Related

Embedded system: How to identify required tasks/threads?

I'm studying embedded programming, so I'm new in this field.
Can someone explain how to identify tasks/threads from given system description. Also, how can I estimate timing constraints, execution times... I'm really stuck.
Here is system description I'm working on:
Implement a 2 degree of freedom servo motor system. A two-axis joystick is used for controlling servo motors. Additionally, enable recording and reproducing the user path of the joystick, so that identical movement could be replicated multiple times. It is necessary to support the recording of 3 motion profiles with a length of at least 5 minutes. The profile needs to be recorded to a non-volatile memory, and the recording/playback control via the joystick button. Provide appropriate signalling for the current selected profile and operating mode (recording / playback) using one LED for each profile. In the RT-Thread system realize the necessary drivers on the Raspberry Pi Pico platform as support for the devices used and the application itself that implements the described system with clear separated threads for each of the observed functionalities.
It is tempting to partition functionally, but in practice you should partition based on deadlines, determinism and update rates. For simple systems, that may turn out to be the same as a functional partitioning. The part:
clear separated threads for each of the observed functionalities
May lead you to an inappropriate partitioning. However that may be the partitioning your tutor expects even if it is sub-optimal.
There is probably no single solution, but obvious candidates for tasks are:
Joystick reader,
Servo controller,
Recorder,
Replayer.
Now considering these candidates, it can be seen that the joystick control and replay control are mutually exclusive, and also that replay itself is selected through the joystick button. Therefore it makes sense to make that a single task. Not least because the replayer will communicate with the servo controller in the same way as the joystick. So you might have:
Joystick reader / replayer,
Servo controller,
Recorder.
The recorder is necessarily a separate thread because access to NV memory may be slower and non-deterministic. You would need to feed time and x/y position data in a message queue of sufficient length to ensure the recording does not affect the timing motion control.
It is not clear what king of servo you are using or if your application is responsible for the PID motion control or simply sends a position signal to a servo controller. If the latter, there may be no reason to separate teh servo control from the reader/replayer. In which case you would have:
Joystick reader / replayer / Servo controller,
Recorder.
Other solutions are possible. For example the recorder might record the servo position over time rather the joystick position, and have the servo controller handle replay.
Joystick reader,
Servo controller / replayer,
Recorder.
That makes sense if the Joystick polling and Servo update rates differ, because you'd what to replay what the servo did, not what the joystick did.

Using Broadcast State To Force Window Closure Using Fake Messages

Description:
Currently I am working on using Flink with an IOT setup. Essentially, devices are sending data such as (device_id, device_type, event_timestamp, etc) and I don't have any control over when the messages get sent. I then key the steam by device_id and device_type to preform aggregations. I would like to use event-time given that is ensures the timers which are set trigger in a deterministic nature given a failure. However, given that this isn't always a high throughput stream a window could be opened for a 10 minute aggregation period, but not have its next point come until approximately 40 minutes later. Although the calculation would aggregation would eventually be completed it would output my desired result extremely late.
So my work around for this is to create an additional external source that does nothing other than pump fake messages. By having these fake messages being pumped out in alignment with my 10 minute aggregation period, even if a device hadn't sent any data, the event time windows would have something to force the windows closed. The critical part here is to make it possible that all parallel instances / operators have access to this fake message because I need to close all the windows with this single fake message. I was thinking that Broadcast state might be the most appropriate way to accomplish this goal given: "Broadcast state is replicated across all parallel instances of a function, and might typically be used where you have two streams, a regular data stream alongside a control stream that serves rules, patterns, or other configuration messages." Quote Source
Questions:
Is broadcast state the best method for ensuring all parallel instances (e.g. windows) receive my fake messages?
Once the operators have access to this fake message via the broadcast state can this fake message then be used to advance the event time watermark?
You can make this work with broadcast state, along the lines you propose, but I'm not convinced it's the best solution.
In an ideal world I'd suggest you arrange for the devices to send occasional keepalive messages, but assuming that's not possible, I think a custom Trigger would work well here. You can extend the EventTimeTrigger so that in addition to the event time timer it creates via
ctx.registerEventTimeTimer(window.maxTimestamp());
you also create a processing time timer, as a fallback, and you FIRE the window if the window still exists when that processing time timer fires.
I'm recommending this approach because it's simpler and more directly addresses the specific need. With the broadcast state approach you'll have to introduce a source for these messages, add a broadcast state descriptor and stream, add special fake watermarks for the non-broadcast stream (set to Watermark.MAX_WATERMARK), connect the broadcast and non-broadcast streams and implement a BroadcastProcessFunction (that probably doesn't really do anything), etc. It's a lot of moving parts spread across several different operators.

Timers in clojure?

I'm wondering if there is any widespread timer solution.
I want to write a simple game engine which would process users input on tick every 20ms (or perform some actions once after 20ms (or any other period)) and basically update "global" state via transactions, and also I plan to use futures so this solution should be able to deal with concurrency caveats.
Can you give me an advice?
You have actually got two distinct issues here.
The first is the issues of timers. You have lots of choices here:
Start a thread that sleeps between actions, something like (future (loop [] (do-something) (Thread/sleep 20) (when (game-still-running) (recur))))
Use a Java TimerTask - easy to call from Clojure
Use a library like my little utility Task that includes a DSL for repeating tasks
Use the timer functionality from whatever game engine you are using - most of these provide some tools for setting up a game loop
I'd probably just use the simple thread option - it's pretty easy to set up and easy to hack more features in later if you need to.
The second issue is handling game state. This is actually the trickier problem and you will need to design it around the particular type of game you are making, so I'll just give a few points of advice:
If your game state is immutable, then you get a lot of advantages: your rendering code can draw the current game state independently while the game update is computing the next game state. Immutability has some performance costs, but the concurrency advantages are huge if you can make it work. Both of my mini Clojure games (Ironclad and Alchemy) use this approach
You should probably try and store your game state in a single top-level var. I find this works better than splitting different parts of the game state over different vars. It also means that you don't really need ref-based transactions: an atom or agent will usually do the trick.
You may want to implement a queue of events that need to get processed sequentially by the game state update function. This is particularly important if you have multiple concurrent event sources (e.g. player actions, timer ticks, network events etc.)
Nowadays I would consider core/async to be a good choice, since
it scales very well when it comes to complex tasks that can be separated into activities that communicate using channels
avoids binding activity to a thread
here is the sketch
(require '[clojure.core.async :refer [go-loop]])
(go-loop []
(do
(do-something ...)
(Thread/sleep 1000)
(recur))))
This solution assumes you're writing Clojure on the JVM.
Something like this could work:
(import '(java.util TimerTask Timer))
(let [task (proxy [TimerTask] []
(run [] (println "Here we go!")))]
(. (new Timer) (schedule task (long 20))))

Time-Based Simulation Independent of Frame Rate

How would you account for an event during which time is very important? Most games use frames and the simulations take place in time steps. What if an event occurred that needed a specific time to take place on?
For example, in a game like DOTA, attack speed is very important. Now, let's say the time-step for this game is 50ms. Two heroes are fighting. HeroA attacks HeroB and lands a "killing blow" at 14ms into the time-step. HeroB attacks HeroA and also lands a "killing blow", only this occurs at 40ms into the time-step. However, neither one of these blows will be simulated until the 50ms time-step. Therefore, at 50ms, both heroes will be killed when really only HeroA should be left standing because he managed to attack first.
Is there some way to account for this?
I don't know how your game architecture is designed, but if you are able to get the timestamps of your events, you can easily put them into a buffer with another Thread and process them in the time specific order every 50ms.

event-driven finite state machine + threads : how to?

I would like to model an event-driven finite state machine in C as proposed here :
http://en.wikipedia.org/wiki/Event-driven_finite_state_machine
But I would also like the 'external' events to be handled in various threads.
Can I find such a code somewhere ? Or advices ?
Message queues are a way to solve your problem.
If you want to feed your state machine with external events from other threads, they can write these events in a message queue that will be read by your state machine.
If you want that other threads trigger on actions from your state machine, it can write to various message queues each associated to a thread that will read from its MQ.
One drawback is that events get sorted in chronological order. If your state machine is not in the mood of handling the event it just read from the queue, you have to decide what to do with this event: destroy it, put it back to the queue, remember it for future use...
Maybe the Quantum Framework is what you are looking for? See http://state-machine.com/ for further information. There are ports for many microcontrollers as well as for linux and windows.

Resources