...
View file | ||
---|---|---|
|
Introduction
Welcome to the firmware team! We’re glad to have you.
In this lesson we’ll be covering:
What firmware is
An overview of our firmware system
...
How we’re working remotely
What our process for writing firmware is
Just a quick preface note before we jump into the content, here’s what these lessons are not:
...
A C programming tutorial. Although we have a number of videos on C programming, joining up in the hopes it’ll teach you programming is unlikely to get you very far. We really don’t have the resources to teach you programming right from scratch, and there are much more qualified people out on the internet to teach you the basics. Here is a link to get familiarized with the basic concepts of C.
...
An insult to your intelligence. Aside from C, there are plenty of other skills members may or may not have acquired through hobbies, co-ops, or classes. If you feel like we’re moving too slowly, try to work ahead, but these lessons are targeting the lowest common denominator.
...
. All of our modules assume that you have some familiarity with programming, specifically the C language. You unfortunately won’t be able to do much until you have some familiarity with the language (specifically pointers, functions and structures).
C Language Resources:
Midnight sun specific Intro to C programming (Shoutout Arshan Khanifar)
Interactive tutorial - Learn-C.org. If you’ve programmed before in other languages before, the most important parts for our team are listed below:
With that out of the way, let’s get started!
What’s firmware?
It’s not software.
It’s not hardware.
...
… That joke definitely worked better in person.
To understand what firmware is, let’s first examine what software is.
What’s Software?
...
Software vs. Firmware
Software is a set of instructions that you run on a computer. For example, your favourite video game or code editor is software. It’s normally stored on your hard drive, then when you want to execute it, your operating system (Windows or Mac OS or Linux) will grab those instructions, put them into working memory (RAM), and execute those instructions. Once you’re done with the program, they’ll be erased from RAM to make room for other things.
...
Firmware is also a set of instructions, but instead of being stored on your hard drive, they’re stored forever in memory that’s wired directly to the electrical components of the computer. As soon as the computer is powered on, it’ll start executing the instructions it has in firmware.An example of some firmware can be found in your laptop: something called your BIOS (basic input/output system) is the first program that runs when you power on, which then loads your operating systemthese base instructions.
In our firmware team, we work mainly on writing code for microcontrollers (like think Arduino but we don’t use Arduino) that control electrical signals or monitor the solar car. This an important aspect of firmware, which is that firmware focuses more on controlling a device’s hardware.Microcontrollers are essentially just computers but way cooler!
Why does it matter?
Firmware generally has a lot more restrictions than software. Firstly, the The processor we use isn’t (comparatively) very fast and there isn’t much memory available, so our code needs to be simple and not too demanding. We partially can get around this restriction by breaking the firmware into small projects and running it on different boards, each responsible for controlling a different part of the car. Breaking it down also helps us work on different parts at the same time.
The purpose of firmware
At the end of the day, in Midnight Sun, the firmware is there to support the hardware, not the other way around. This means we’re not the protagonist!
If you’re a budding software engineer with big dreams of making the world a better place through AI and blockchain or whatever other buzzwords are trending nowadays, this team might not be for you. We keep things simpleprojects in parallel.
Hardware and Firmware
Our team coexists with hardware and it is mandatory for you to be interested and willing to learn electronic basics. This is what makes firmware super cool! It isn’t just software and it isn’t just hardware. We bring life to PCBs and give our vehicle functionality.
Systems overview
Here’s a diagram of the car’s electrical system:
...
If this scares you, don’t worry! It scares us too. Thankfully, implementing what’s in this diagram is the hardware team’s job, not ours!
Firmware system overview
...
See, we don’t even need to worry about wires. Much cleaner and easier to understand.
Each non-bolded line in the diagram represents a firmware project that controls a part of the car’s electrical system, grouped under the headings in bold. Here’s a quick rundown of what each firmware project does:
Battery: Ensures the battery doesn’t explode.
Driver controls: Takes input from the driver and passes it on to the rest of the system.
Power distribution: Turns other boards on and off (controls which boards are powered).
Drivetrain: Converts the angle that the pedal is at to the current levels for the motors (so if you floor it the car will go faster).
Charging: Manages charging of the battery from an off-the-shelf wall electric car wall charger or from the solar array.
For the most part, our firmware projects are detailed in Confluence. Boards Each subpage is the home for an electrical board’s documentation, most of which have a sub-page for the firmware.
How we’re working remotely
...
Your PC vs a Microcontroller
We write all the code on our personal computers, but we need it to build it differently so that we can flash it over to run on our microcontrollers in a way that they understand. There are a few differences between the two that we need to consider.
Quick disclaimer: if this section doesn’t really make sense to you, that’s ok! You can still write code without it. But, this should help you understand what the difference is between working remotely and working directly with hardware.
First, let’s talk about compiling code.
Compiling code
As you may or may not know, to run C code, first you have to compile it. This means turning the higher level instructions you write as code into simpler instructions for the computer to understand.
...
An important caveat here is that not all computers understand the same instructions. For example, the processor in your laptop understands instructions called x86 (instruction set for Intel processors), while the computer chips we run our firmware on understands instructions called ARM.
Compiling our code
To do things like turn headlights on or off and read voltages from our hardware components on the BMS (battery management system) through code, we use pieces of code that are called libraries. Our firmware projects implement the logic parts we need, like determining when and how often we want an LED to blink and then we use the library to actually talk to the LED to turn it on or off. What this allows us to do is have different versions of the libraries for different types of computers:
...
This is the key to letting us work remotely! We can write all our C code and run it on our laptops, and never worry about actually touching the hardware, right?
...
Unfortunately, it’s not quite that simple. Some things are really hard to emulate on x86, especially things that are time-sensitive since you don’t know what else your laptop might be doing while you’re running the code. Microcontrollers have internal clocks which may differ from the one on your computer. However, it still gives us enough capability to write code and test our main logic.
Also, the hardware is still around, we’re just not close to it anymore. Good thing zoom, discord, and slack all exist! If we want to run our code on real hardware, we just have to call up the hardware member with the board and ask them to run it for us. Yes, this is more inconvenient, but it’s better than showing up a month later without having tested anything at all on hardware.
Writing code
As for actually writing code, it’s important now more than ever that we follow a process for writing code since it’s a little harder for me to peek over your shoulder and ask how you’re doing. Our process for writing firmware is as follows:
Our Process
Writing Code
Our firmware runs in safety-critical situations, and as such it can be dangerous if it goes wrong. To help prevent this we have a structure for creating and testing our firmware.
High-level design: We come up with a high-level structure of the project that fulfils the requirement.
Detail design: we sort out the specifics, like what events or messages need to be passed between modules of the project
...
Implementation: we write the code.
Unit testing: we write tests that test specific parts of the code to make sure our logic works the way we think it does.
IO testing/Hardware validation: input/output testing. We run the project on hardware, and make sure the hardware works the way we expect it to.
Integration testing: we connect multiple boards together and make sure they work together the way we expect them to.
Notice how much testing we go through! This is really important. In firmware, writing the code is often only half the battle, and there can be many unforeseen delays when you actually start interacting with hardware.
Collaboration
The TL;DR of this is that we use GitHub and JIRA. We’ll be going over the detailed processes for these in later lessons, but otherwise, if you’re familiar with the basics, feel free to skip this section.
...
Tools
GitHub:
Git is a version control system that lets us have a master version of our firmware code as well as “branches”. GitHub allows you to use git to Each branch can have modifications made to it in an isolated environment, then once the changes are checked and verified, they can be “merged” back into master. We use this as a way to give each member an isolated environment to work on their changes. Excellent tutorials can be found here: https://www.atlassian.com/git/tutorials/using-branches
as well as from our own retired firmware lead Arshan Khanifar: https://www.youtube.com/watch?v=n0attCkKQUU&list=PLwHCeNgf9lKdt6LN6D54__moOb4Mkj5NQ&index=3.
JIRA is a
JIRA:
A project tracking tool that lets us easily keep track of all the tasks people are assigned to and their progress.
...
Specifically, we use a kanban board, which is just a visual way of looking at work that helps us make sure not too much is assigned to someone at once. This is part of a much bigger work process called Agile which you should read up on if you’re interested in project management, but we’re just sticking to the very basics and using this board to track tasks.We put “tickets” on the board, which include the task, the assignee, and some other information about the task.
Again, we’ll be going over how we use these two tools in more depth as part of later lessons.
Conclusion
Thanks for sticking through! In conclusion, here’s what you should come away from reading this with an understanding of:
What firmware is
What our firmware systems do at a high level
How we’re able to work on firmware without direct access to the hardware
Our process for completing firmware projects
Next in firmware 102, we’ll go into more depth on our firmware system, controller boards, our project structure, testing and validation, and our collaboration platforms. We hope to see you there!
Homework
...
FW 101 Tasks
Each of these modules comes with some tasks or projects that should be completed before moving onto the next part. There will usually be a deliverable so that we can check off that you’ve completed the homework.
*One important thing: as you are working through your tasks, you will encounter errors. The leads are happy to answer questions about any of these issues, but most of the time it can be solved by a quick google. 90% of the errors you will encounter can usually be solved with answers from Stack Overflow, and a little bit of thinking.
FW 101 Tasks
There are several tasks that need to be completed as part of this module:
Learn about Git and the Command Line by watching/reading the following tutorials
Git Tutorial Videos (part 1 and 2) and branching lesson
Command Line Tutorials (Part 1 and 2)
Get your environment set up by following the instructions listed at Setup
Write your very own Hello World program!
1. Intro Videos
These videos give an introduction to two of the main tools we use on our team, Git and the shell command line. We suggest watching them if you aren’t very experienced in one or the other, since the rest of the onboarding content will rely heavily on these concepts. However, we also do explain it as we go, so feel free to continue on even if you still haven’t fully grasped the concepts, and use these resources when you get stuck.
2. Setup
Assuming you have followed the steps listed in the setup page, we can now try out your new repository.
Once you’ve got your box set up (you should be in the vagrant environment. If you type whoami
in your console it should print vagrant
below) and have pulled the firmware_xiv fwxv repository, build the can_communication project, we can build and run it on the x86 platform.
We use SCons to compile and build our software. It is generally invoked with arguments which tells it how and what to build. You should now run the following command (fill in the blankin your command line; this will build and then run our “leds” program.
Code Block |
---|
makescons runsim PROJECT=... PLATFORM=... |
Once it’s started, take a screenshot and send it to the firmware lead (Ryan Dancy). It should look something like this:
...
--project=leds --platform=x86 |
You will see a bunch of build output printed to your screen, and then a periodic printing of the word “blink”, something like below:
...
Don’t worry about what anything means, this is just to make sure you’ve got things up and running. We will talk more about scons and building software later.
3.
...
Hello World
This section will cover writing a basic hello world program (using the C language), and running it in the environment we have just set up.
Let’s take a quick look at our fwxv repository before we get started. Type ls
in your command line (at the fwxv directory) to list the directory contents. You should see something like the image below:
...
The two main things we care about right now are the projects
and libraries
items. These are directories, which hold the firmware we write.
Libraries contains the code that is standalone, to be included the main programs we write, using #include "library.h"
. Some of these libraries we write ourselves, some of them (such as the FreeRTOS source code) we get from other sources. Each library will generally consist of a header file (.h) and a C-file (.c). The header file holds any new data types which are used in library, and declarations for functions the library may provide, and other useful information. The .c file contains the definitions for these functions.
The projects directory is where we write and build our main software which will run. If you are familiar with C programs, you know that they have a “main” function which is where the program starts when it runs. This is in a main.c file for all our projects. The projects directory is where the main file and any other project-specific software lives.
We will start by creating a new project where we will write our hello world program. Luckily, we can run the following command to do it for us! Make sure you are in the fwxv directory, this is where all commands must be called from.
Code Block |
---|
scons new --project=hello_world |
This will create a new project with the name “hello_world”. We can view it by listing the projects directory with ls projects
. It should look something like this
...
As you can see, there were already a few projects existing, including the leds one that we built and ran earlier. Each project is a directory as well, with the file structure shown below.
Code Block |
---|
project/
├─ src/
│ ├─ main.c
├─ inc/
├─ test/
├─ config.json
├─ README.md |
The main file and any other .c files go in the src/
directory, and any header files go in the inc/
directory. The readme is a text file where you can give a description of your project, and the config.json is needed for including external libraries, but we will get to that later.
We need to create a main.c file in our src directory. You can do this from the command-line, or you can open up the fwxv folder in your favourite text editor and do it there (If you don’t have one, VS Code is recommended, but it doesn’t really matter). We then need to open our main.c file for editing.
A C program is comprised of the following main components.
Code Block | ||
---|---|---|
| ||
#include <stdio.h>
#include "mylibrary.h" // The library includes
#define BUF_SIZE 10 // Any defined constants or preprocessor directives
static int buf[BUF_SIZE]; // Any static/global declarations
static int prv_my_func(int *input) { // Function declarations/definitions
*input++;
return *input; // Increments the value passed and returns it
}
int main(void) {
int in = 0;
int out;
for(int i = 0; i < BUF_SIZE; i++) {
out = prv_my_func(&in);
buf[i] = out;
printf("In %d, Out %d\n", in, out);
}
return 0;
}
|
As you can see, we have a simple program which increments an integer and stores its value in a buffer array. Using this template, we are now going to write our very own hello world program!
The Program
The goal of this next part is to write a program which increments an integer using a function, and prints it to the console every second along with “Hello world”.
You will need to use a few things from our code base for this project.
Include the “log.h” library. We have our own version of printf which allows us to safely print to the console. You can use it the exact same way as printf, just replacing it with LOG_DEBUG, ie:
LOG_DEBUG("Hello World %d\n", my_int);
Run the program using the scons command from above (with a different project name).This program should run forever in a while true loop.
When you are done, take a screenshot of your output or bring your computer over and show it to a lead. You are officially done FW 101, Congrats!