/Firmware_Over_The_Air

graduation project of ITI, flashing a new firmware over the air for automotive industry

Primary LanguageC

Firmware Over The Air

This project's purpose is to flash a new firmware over the air for automotive industry,

List of components we used:

Raspberry Pi 3B+ and 16 GB SdCard (simulates the car)
3.5 Inch Raspberry Pi screen (simulates car's dashboard)
STMF103 microcontroller (simulates car's ECU)
Google Cloud Server (the bridge between the car and the company)
PC GUI APP. ( the company uses to upload the Firmware to the server)

Through the GUI the company selects:

the new firmware file
the car's model
a specific car's ID from the available cars in that model

And then this selected car will:

fetch the file from the server
and after the car owner confirm to flash now through a Pop-Up window appear on the car's dashboard it parses the downloaded file into frames to be sent to the ECU through UART

After the flashing is done:

another Pop-Up window appears on the car's dashboard to notify the user that the flashing is done
also the PC GUI app. will be notified

Tutorial

Raspberry Pi

The image for Raspberry Pi

unzip 2019-09-26-raspbian-buster.zip

  • Then insert your SD card into your laptop, To discover the SD card

lsblk -p (this name should be /dev/mmcblk0 or /dev/sdX)

  • Now time to Copy the unzipped image onto the mounted device using command dd.

dd bs=4M if=raspbian.img of=/dev/sdX status=progress conv=fsync

Enable Ethernet connection

To Configure a static IP for RPI3, Modify the file "/etc/network/interfaces" on your Raspbian image (or any Debian image):

Disable the DHCP client for eth0 interface by commenting this line using "#"

iface eth0 inet dhcp ====> #iface eth0 inet dhcp

Add these lines after it to configure eth0 interface to use static IP:

auto eth0
iface eth0 inet static
wait-delay 15
hostname $(hostname)
address 192.168.5.30
netmask 255.255.255.0

To enable ssh create an empty file named "ssh" in boot directory

touch ssh

To enable password authentication, uncomment

sudo nano /etc/ssh/sshd_config
#PasswordAuthentication yes ====> PasswordAuthentication yes

To connect with RaspberryPi:

ssh-keygen -f "/home/$USER/.ssh/known_hosts" -R "192.168.5.30"
ssh pi@192.168.5.30 (defualt user: pi, default password: raspberry)

Enable built in WIFI

  • enter this in terminal to configure wifi

sudo raspi-config

  • then select network

  • then select WIFI

  • then enter WiFi Name (SSID) and password, now you done with raspi-config.

  • then enter this command

sudo wpa_cli -i wlan0 reconfigure #it will reply with "OK"

connect to Raspberry Pi terminal over WIFI

add those lines to "/etc/network/interfaces"

auto wlan0
iface wlan0 inet static
wait-delay 30
pre-up wpa_supplicant -B -Dwext -iwlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf
post-down killall -q wpa_supplicant
address 192.168.1.30
netmask 255.255.255.0
gateway 192.168.1.1

Configure the built in UART of the Raspberry Pi

sudo raspi-config

  • select -> interfacing options

  • then, select serial option to enable UART

  • then select No to login shell to be accessible over serial

  • then select Yes to enable hardware serial port

  • Now our UART is enabled for serial communication on Tx and Rx of RaspberryPi

  • add "enable_uart=1" at the end of /boot/config.txt

  • if you are testing using TTL, connecat as: connect your TTL(Tx) ==> RaspberryPi (pin 15) Rx and then TTL(Rx) ==> RaspberryPi (pin 14) Tx, and connect TTL(GND) to Raspberry Pi (GND)

  • if you are connecting Raspberry Pi to the microcontroller connect STMF103 Tx (pin 9) ==> RaspberryPi (pin 15) Rx and then STMF103 (pin 10) Rx ==> RaspberryPi (pin 14) Tx, and connect STMF103 (GND) to Raspberry Pi (GND)

In PC(Linux) terminal

  • to make sure it is connected and given a port name by the kernel use:

dmesg -wH (ex. /dev/ttyUSB0 )

  • to change its permissions so you can read and write to it:

sudo chmod o+rw /dev/ttyUSB0

  • to test read from (ex. ttyUSB0):

sudo cat /dev/ttyUSB0

  • to test writing to (ex. ttyUSB0) :

sudo echo "hello" > /dev/ttyUSB0

In Raspberry Pi terminal

  • To check if mini UART (ttyS0) or PL011 UART (ttyAMA0) is mapped to UART pins, enter following commands:

ls -l /dev

  • to test reading from (ttyS0):

cat /dev/ttyS0

  • to test writing to (ttyS0):

echo "hello" > /dev/ttyS0

You can check the references for further help on how they are created.

Adding python3 library

sudo apt install python3-pyelftools

Adding xml library

sudo apt install xmlstarlet

google cloud for Raspberry Pi

we are using google cloud to fetch the .elf from,
sign in to google cloud using gmail account then create a new project

and then create a new bucket inside this project.

Raspberry Pi GUI

we're using bash script to generete this GUI by using YAD

  • a touch screen is connected to the raspberry Pi as a simulation for Car's dashboard, and we send a notification message to the car on the screen once a new firmware is available and already downloaded to the raspberry Pi

you can try this GUI by:

yad --title="3faret El Embedded FOTA project" --list --width=500 --height=200 --column "New Firmware for $controller_name is available. select action" 'Flash now' 'Snooze 5 min' --no-buttons --timeout=60using

  • after the flashing of the new firmware is done, we also notify the car on the screen

you can also try this by:

yad --title="3faret El Embedded FOTA project" --text="Flashing for $controller_name is done" --width=350 --height=10 --timeout=5 --dnd

Raspberry Pi touch screen

we're using 3.5 Inch screen, description of the pins are shown below:

  • Raspberry Pi configurations for 3.5” LCD Display Screen

sudo raspi-config

  • Navigate to Boot Options -> Desktop/CLI ,select option B4 Desktop Autologin Desktop GUI, automatically logged in as ‘pi’ user

  • Now again navigate to interfacing options and enable SPI

note: you may need to recheck if the UART is enabled

  • now install your Raspberry Pi screen driver

sudo rm -rf LCD-show \

git clone https://github.com/goodtft/LCD-show.git \

chmod -R 755 LCD-show \

cd LCD-show/ \

sudo ./LCD35-show \

now reboot the Raspberry Pi

note

to run our script as a daemon that runs as a "background" process (without a terminal or user interface),
we used rc.local before using GUI, but when we added the Raspberry Pi GUI part we had to use "LXDE autostart" instead to load the script when the Raspbian desktop started.
craete a file located in /etc/xdg/autostart and we shall call it My-Cool-App.desktop

sudo nano /etc/xdg/autostart/My-Cool-App.desktop

Inside the file we need to create the following structure:

[Desktop Entry]
Type=Application
Name=Elf fetcher
Comment=Fetching the elf file
NoDisplay=false
Exec=sudo bash /home/pi/myApplications/elf_fecher_GUI.elf #remember to add "sudo" in your command xD
NotShowIn=GNOME;KDE;XFCE;

Adding google cloud sdk for Debian (from Raspberry by terminal):

  • Add the Cloud SDK distribution URI as a package source

echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list

  • Import the Google Cloud Platform public key

curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add

  • Update the package list and install the Cloud SDK

sudo apt-get update && sudo apt-get install google-cloud-sdk

  • initialize the connection with google cloud and select the project to work on.

gcloud init # you need to run this command @ (root user) if you run elf_fetcher.sh at the boot

  • to upload a file to google cloud (using Raspberry by terminal)

gsutil -m cp -R [file name] gs://[Bucket name]/

  • to download a file from google cloud (using Raspberry by terminal)

gsutil -m cp -R gs://[Bucket name]/[file name]

shutdown script

Create a systemd service
we have two files:
one is the service file /etc/systemd/system/FOTA.service
and the other one is your desired script to be run right before shutdown /usr/local/bin/FOTA_shutdown

this is the first one: /etc/systemd/system/FOTA.service

[Unit]
Description=FOTA_shutdown
After=networking.service

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true
ExecStop=/usr/local/bin/FOTA_shutdown

[Install]
WantedBy=multi-user.target

this is the second one: /usr/local/bin/FOTA_shutdown

#!/bin/sh
echo "do" >> /home/pi/debug.txt
gsutil -m cp -R gs://fotaproject_bucket/cars_ids.xml /home/pi/ >> /home/pi/debug.txt
xmlstarlet ed -u '/cars/verna_2018_1' -v "unavailable" </home/pi/cars_ids.xml>/home/pi/new_status.xml
echo "xml" >> /home/pi/debug.txt
mv /home/pi/new_status.xml /home/pi/cars_ids.xml
gsutil -m cp -R /home/pi/cars_ids.xml gs://fotaproject_bucket/ >> /home/pi/debug.txt
echo "done" >> /home/pi/debug.txt

note

make sure that the both files are executable

sudo chmod +x /usr/local/bin/FOTA_shutdown
sudo chmod +x /etc/systemd/system/FOTA.service

Additional commands to enable the service here i'm assuming my service name is "FOTA"

#use this if you change a service configuration, to reload it
sudo systemctl daemon-reload
#to enable the service
sudo systemctl enable FOTA.service --now
#to check if the service is enabled
systemctl is-enabled FOTA
#to check if the service is active systemctl is-active FOTA
#service manually triggering
sudo systemctl restart FOTA

PC GUI Application

python -m pip install --upgrade pip

  • install pySide2

pip install PySide2

  • Adding google cloud compatible python library packages (Windows Cmd)

pip install google-cloud-datastore
pip install google-cloud-storage

What is the service accounts and keys in google clouds

What are service accounts? A service account is a special kind of account used by an application or a virtual machine (VM) instance, not a person. Applications use service accounts to make authorized API calls. For example, a Compute Engine VM may run as a service account, and that account can be given permissions to access the resources it needs. This way the service account is the identity of the service, and the service account's permissions control which resources the service can access.

Differences between a service account and a user account Service accounts differ from user accounts in a few key ways: • Service accounts do not have passwords, and cannot log in via browsers or cookies. • Service accounts are associated with private/public RSA key-pairs that are used for authentication to Google. • Cloud IAM permissions can be granted to allow other users (or other service accounts) to impersonate a service account.

Creating Service key account for generating .json file (From cloud.google guides)

hint: The python script won't connect to the google cloud server throught the json file if the PC time is not right

  • From Google cloud Platform go to the IAM & Admin Section and select Service Accounts

  • Click on CREATE SERVICE ACCOUNT

  • Add Service account name and Service account description

  • Select a role for the created Service account

  • Grant specific user access to the created service account

  • Generate an authenticated key file through creating a key and press done

  • The generated .JSON key file can be used through VMs for accessing the cloud server that generated this service account key through different APIs, in our project we connected through this key file through Python using google.cloud provided library.

Service Account Key Constaints

  • If this .Json key file that includes all the credentials is shared through any online platform e.g: Github, Whatsapp , …etc. Google’s support immediately notifies the owner through the registered email address and it can be followed by a suspension to the whole project but it can be reopened be requesting an appeal.

  • If you detected any violations from any generated service key account it can be disabled immediately by the owner.

PC GUI

  • Python script connected to google cloud to upload .elf file and a text file that announces for a new firmware release

References

Connecting to RPI3 - SSH Over Wired

UART configurations of RaspberryPi

RaspberryPi intenet connection over builtin wifi

Python on RaspberryPi

google cloud project creation and its sdk for Debian

google cloud and python integerarion (Windows)

Raspberry Pi GUI

Raspberry Pi touch screen

shutdown scripts

others