Project Specification
The project of the present course will aim to use a (very very) simplified
car and applying what learned in the lectures to a “real” use case.
(Source: https://cdn.motor1.com/images/mgl/rKoeb9/s1/la-peugeot-104-peugette-con-un-solo-sedile.jpg)
You are going to build a system composed by:
- injection system controller1
- car infosystem
- wipers
- proximity sensor2
- vehicle health analysis
1: it is a simple car but still holding a working engine
2: we do not like paying high insurance fees because we run over
pedestrians, do we?
The car simulator
Our car simulator implements the following behaviors:
- It is made of a mix of periodic / aperiodic tasks.
- Tasks may access shared resources and thus dependent of each other.
- Some tasks have hard real-time constraints, so you have to show that these constraints are met.
- The software is implemented using safety features, as explained in the related codelabs.
Phases
The software will be implemented in several phases as listed below. The deadlines for delivering the deliverables of each phase are described in the plan. The deliverables must be made available as defined in the project organization section
Once the infrastructure of the project is setup, the phases of the project are:
- Setting up the infrastructure of the project (Phase 0).
- Simulation and implementation of independent periodic tasks (Phase A).
- Integration of aperiodic tasks (Phase B).
- Integration of shared resources among tasks and of safety concepts (Phase C).
All phases contain deliverables detailed in each section below.
Phase 0: Setting up of the infrastructure
Once you have completed the Scheduling of periodic tasks codelab and the Robust Development Methodologies codelab, the basic infrastructure for starting the project will be in place. Use the code base Scheduling of periodic tasks codelab (using TTCE) as base for your GitHub repository whose name is TeamName-CarSim.
Warning
Make sure all code written by you does follow MISRA C:2012 as well as Google’s C++ Style guidelines.
Phase A: Periodic tasks
The car simulator must implement the following periodic tasks:
Task | Function | WCET [ms] | Period [ms] | \(\Phi\) |
---|---|---|---|---|
Engine | Performs car engine checks periodically | 10 | 50 | 0 |
Display | Displays car information | 15 | 125 | 0 |
Tire | Performs tire pressure checks | 10 | 200 | 0 |
Rain | Performs rain detection | 25 | 250 | 0 |
Phase A Deliverables
Based on the instructions in the Scheduling of periodic tasks codelab, you must:
Expected Deliverables and Additional Requirements
-
Demonstrate that this set of tasks is feasible using RMA and simulate this set of tasks.
- Deliverable: the “README.md” file at the root of the project must contain the demonstration of the schedulability of the task set by the Rate Mononotic Algorithm and a screenshot of the results obtained using the simulator. You must also upload the simulator configuration file in json format onto your repository.
-
Implement this set of tasks with a multi-tasking program using Keil RTX5.
- Requirement: all the work is done on a dedicated
git branch
namedphase_a
and merged once the tasks are completed. The merge shall happen through a Pull Request (PR) so as to ensure proper code review (so, do not forget to add a reviewer 😉) - Requirement: the phase between the different tasks must be \(0\), meaning that the start of the period of the first instance of all tasks is the same.
- Requirement: as in the related
codelab,
computing time must be implemented using a busy wait (e.g. by using the
busy_wait_ms()
function). - Requirement: each task must be implemented in a separate function
defined/declared in a dedicated
.c/.h
file as shown under theApplication
folder. - Requirement: all written code shall follow MISRA C:2012 guidelines. For this purpose, you must apply all code analysis and all possible fixes to your source code as described in the related codelab.
- Deliverable: a screenshot of the dynamic analysis of your program using Tracealyzer must also be added to the “README.md”. Note that it is expected that simulation and dynamic analysis show the same application behavior.
- Deliverable: the source code of your application in your github repository with the tag/release “PhaseA”.
- Requirement: all the work is done on a dedicated
Phase B: Mix of periodic and aperiodic tasks
Ensuring quality
Before addressing the details about new functionality of Phase B, let us consider
ensuring good product quality. A good practice for developing qualitatively
good products is to only develop new functionality on dedicated branches so as
to preserve the main
branch from undesired consequences (for instance, a new
instance introducing instabilities).
For doing so systematically, one would protect the main
branch - that is, one
cannot commit to main
directly any longer but is obliged to create a specific
branch and then merge changes into main
after checks have been passed. Those
checks can be mechanical (automated tests) as well as humans (code reviews). So,
for Phase B you will use this already and to activate the protection you will
need to :
-
In order to protect the quality of the
main
branch, usually this is protected. Protected in this context means that no changes are accepted without application of the four eye principle (see at the bottom of the page for a definition).
In order to activate the protection, you need to :- go to your repository Settings and click on Branches
- there you need to choose Branch protection rules and Add rule
- once the Add rule page opens up, fill in the information as
per the following picture:
Although not in the picture, one may add more checks to this stage (e.g. “Require status checks to pass before merging”)
-
When are finished, you should be able to see the following:
-
Once a fix is available, you shall create a Pull Request
- When you are creating the pull request, you shall define at least one
reviewer. Normally, at least the issue issuer shall be invited to review
the correction.
- After the reviewer has approved the change, for as long as there are no
conflicts, the merge can occur into
main
. It can even do automatically if one chooses so (Enable auto-merge).
Warning
Once branch protection is installed, this needs to be respected for bug fixing as well. Not only is this good practice (see Note 2 of Robust Development Methodologies(II)), but it also works for everyone - contrary to bypassing branch protection that only works for administrators.
Phase B features
The goal of Phase B is to implement a system with three components, as illustrated below:
- The set of periodic tasks described in the Phase A section is executed using the Rate Monotonic scheduling algorithm.
- Given this set of periodic tasks, a Deferrable Server task is added to the system. The period of this task is chosen so that the schedulability of the entire set of periodic tasks is preserved. Note that while sporadic tasks may usually be rejected by an acceptance test, we do not implement this behavior in this project.
- A background task is also added to the system. This task executes with the smallest priority among all application tasks.
In addition to the periodic tasks, the car simulator must also implement the following aperiodic tasks:
Task | Function | WCET [ms] |
---|---|---|
Presence detection (PD) | Sensor detecting presence nearby the vehicle | 50 |
Search for peripheral devices (SPD) | Detect nearby devices | 200 |
The properties of the two aperiodic tasks are as follows:
- The presence detection (PD) task is a sporadic task. It must be served through a deferrable server and the server shall be implemented as per the related codelab.
- The presence detection (PD) task arrives at the following times in each major cycle :
\(t = {60, 300, 630, 900}\).
Generation of aperiodic requests shall be implemented as described here, with the appropriate changes for generating aperiodic requests continuously. - The search for peripheral devices (SPD) task must be served as a background task. It shall be implemented as in the related codelab. The implementation in your project differs from the codelab in the way aperiodic requests are notified. While the codelab was getting aperiodic events from a queue, the implementation in the project uses a event flag mechanism. More details are given below.
- The search for peripheral devices (SPD) task arrives whenever the user presses on the device button. If the user presses on the button while the task is still running, then the related event flag is set again. This means that it can be set while the background task is still running, but setting it more than one time will have no additional effect.
Phase B Deliverables
Based on the instructions above, you shall comply to the following:
Expected Deliverables
- Deliverable: the source code of your application in your github repository
with the tag/release
PhaseB
and the work on new features realized on a dedicated branch namedPhaseB_Features
. A screenshot of the dynamic analysis using Tracealyzer of your program must also be added to the “README.md”. - Deliverable:
main
branch shall be protected and all changes are added to it through Pull Requests - Deliverable: the analysis made for determining the smallest possible \(T_{S}\) that guarantees schedulability of the set of periodic tasks with the deferrable server task must be added to the “README.md” file.
- Deliverable: all written code shall follow the project structure described in Project Structure.
- Deliverable: all written code shall follow MISRA C:2012 as well as Google’s C++ Style guidelines.
- Deliverable: all bugs reported as issues to your github repository for Phase A must be fixed, following the guidelines described in Bug Fixes from Phase A.
Code for implementing the button behavior
For implementing the button behavior, you may follow the following steps:
-
The function
HAL_GPIO_EXTI_Callback
must be added to thebutton.c
file:application/button.cThis function defines the ISR routine that will be called when the user presses the button. For debugging the interrupt behavior, you may place a breakpoint in the routine when debugging the application and check whether the interrupt mechanism is properly configured./*--------------------------------------------------------------------------- HAL_GPIO_EXTI_Callback: Handles GPIOs IRQ *---------------------------------------------------------------------------*/ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin == GPIO_PIN_13) { uint32_t flag = osEventFlagsSet(event_flag_button, BTN_FLAG); if (flag != BTN_FLAG) { app_error_handler(CANNOT_SET_FLAGS); } } }
-
The background thread function must be modified as follows:
Observe how this function waits forever on an event to be set in the__NO_RETURN void background_task_thread(void* arg) { static const uint32_t background_wcet = 2000; for (;;) { // Wait for tbe BUTTON_any event to be signaled using flags, flags are cleared // automatically uint32_t flag = osEventFlagsWait(event_flag_button, BTN_FLAG, osFlagsWaitAny, osWaitForever); if (flag == BTN_FLAG) { // execute the background task busy_wait_ms(background_wcet); } } }
HAL_GPIO_EXTI_Callback
function. Whenever the button is pressed, the background thread will move fromBLOCKED
state toREADY
state. Once no other task is ready to be executed, the background task will then execute. -
Finally, the
app_main_background()
function - called from themain()
function must execute the following code, before it launchesbackground_task_thread
:This code creates the// create the event flags for catching button press const osEventFlagsAttr_t event_flag_attr = { .name = "Button", .attr_bits = 0, .cb_mem = NULL, .cb_size = 0}; event_flag_button = osEventFlagsNew(&event_flag_attr); if (event_flag_button == NULL) { app_error_handler(CANNOT_CREATE_EVENT_FLAGS); }
osEventFlagsId_t
instance and assigned it to a global variable namedevent_flag_button
.
Bug Fixes from Phase A
After you delivered the Phase A of the project, a few issues related to your project have been created. These will need to be fixed within Phase B.
Note
Make sure to follow the rules presented in
Write Better Commit Messages.
That is, put fix:
as type of your commits.
Obviously, setting the right type is valid for all commits, not just bug fixes.
In order to fix issues orderly, the proper way to do so is to create a
dedicated branch per issue and only commit the fix(es) related to that issue
on that branch. Once the fix is made available and approved, the branch created
for that purpose is deleted. Below you find a description how you shall go
about it.
Under the github project you created, under Issues,
chose the issue you intend to address and :
- Define who the issue is assigned to with the field
Assignees
- Declare what type of issue it is
Labels
(note: choose the correct type) - Potentially define at what milestone the issue should be fixed. In your case
add
Phase B
as milestone - Create a dedicated branch for fixing the particular issue
Afterwards you can pick the newly created branch to fix the issues with the following commands
git fetch origin git checkout 2-testing-guthub-functions-mispelled
- Go about fixing the issue and commit to the newly created branch
Or (as the example was fixed directly in github)
git add README.md git commit -m "fix: corrected github mispell"
- When the merge has been done, you should delete the specific branch created
for fixing the issue (see Delete branch in picture below)
Note
Make sure you replace 2-testing-guthub-functions-mispelled
in the example
above with the correct branch when you run above commands.
Quote - Four eyes principle
The Four eyes principle is a requirement that two individuals approve some action before it can be taken. The Four eyes principle is sometimes called the two-man rule or the two-person rule.