In the following blog I will cover a use case of defining a dynamic static ethernet IP address in Petalinux.
For this I'll walk through the following stages:
- I'll start by going over the basic steps for building a Petalinux Image.
- I will then create a simple script to run at power up.
- Adding and mounting a "STUFF" partition in the SD card.
- Lastly, defining a dynamic static IP.
What does it mean a dynamic static IP? if an IP is static how can it be dynamic?
Well, The only difference here is that I want the user to be able to change this address whenever he wants, i.e., it will not be hard-coded in Petalinux image, and it can be dynamically changed, where only reboot is needed to take the new IP under account.
I’ve used the good old MicroZed as the target board, connected to IOCC. IOCC is actually not a must for this tutorial, yet it is used in one of my projects, so it is already installed. Basically it is a kind of breadboard, used to connect all MicroZed IO’s to external connectors. It is a very convenient board with added functionality of push buttons and dip-switches.
In my system I have a few identical boards (few MicroZeds for this matter) in which I want to connect them all to the same network, so each one must have its own static IP, a different one. Furthermore, as stated, I want the user to define this static IP (any IP he/she wants, for that matter). How would one do that with Petalinux?
The first step is building the Petalinux image. I’ve covered it thoroughly in my UIO tutorial, so I’ll go over it quickly (I'm using Ubuntu 18.04 LTS with Petalinux 2019.1, Vivado 2019.1, with MobaXterm and VirtualBox running on Win10 OS).
Logic design of my projectMy Vivado project is pretty simple, and based on an SPI interface for controlling a motor (PS in Zynq which is connected to EMIO). I will cover it in a future blog, as it is pretty nice how to control the motors and defining the device tree to do that:
The Zynq is connected to 3 to 8 decoder, since I have 8 SPI based motor drivers, so 8 CS’s are needed. All motors are cascaded in SPI. The MOSI, MISO and CLK signals are connected to my GPIO pins (via EMIO).
Altering the system-user.dtsi file is necessary for the design to work properly. I will not cover that here.
After compiling the design, Export Hardware is needed:
Before creating the image, we’ll download the BSP of microZed. UG1144 explains we can use the ‘- -template’ in case we don’t have a BSP:
MicroZed does have a downloadable BSP(see here, you’ll need an account to download it). I’ve used it, thus making the process much easier, since it is related to the specific board I’m using, so the device tree is ready and no changes are needed:
petalinux-create -t project -s mz7010_fmccc_2019_1.bsp -n myProjPL
After doing so, the following folders are created in the new project folder:
roy-m@kub18-fpga:/fpga/projects/linux_images/myProject$ cd myProjPL/
roy-m@kub18-fpga:/fpga/projects/linux_images/myProject/myProjPL$ ls -lrt
total 20
-rw-r--r-- 1 roy-m Dev_ISL_PCB-di 248 Sep 30 2019 config.project
drwxr-xr-x 6 roy-m Dev_ISL_PCB-di 4096 Sep 30 2019 project-spec
drwxr-xr-x 3 roy-m Dev_ISL_PCB-di 4096 Oct 1 2019 components
drwxr-xr-x 3 roy-m Dev_ISL_PCB-di 4096 Oct 1 2019 pre-built
drwxr-xr-x 3 roy-m Dev_ISL_PCB-di 4096 Oct 1 2019 hardware
Each of these folders can be used to predefine added applications, adding scripts at power up, defining device trees, etc. These are the basic elements used to create the image.
Next we’ll import the HDF.
The HDF is like a zip file, which contains the exported HW files used in the SDK and also the bit file (in case the checkbox of ‘include bit file’ is checked)
petalinux-config --get-hw-description=/fpga/projects/myFirstPL_uZed/project1/project1.sdk
Now we’re getting to the fun part of configuring the image. The first menu we see is the following:
Diving into the ethernet configuration, we’ll click the following, and see the IP is set to automatic, by default.
We can change the automatically IP address (DHCP) to a specific static one, by hitting the spacebar, then we see the following options:
In the example above, I chose 192.168.1.7 as my static address. Obviously the gateway should be the same prefix (192.168.1.1).
We can now go on and build the image, using petalinux-build. There are numerous nice features and tweaks worth mentioning. I’ll discuss those in a future blog.
Dynamic static IP addressAfter petalinux-build went smoothly, we need to take the image.ub, BOOT.bin and rootfs.tar.gz and copy them to the SD card or flash, to the appropriate folders:
image.ub & BOOT.bin in BOOT, un-tar the rootfs.tar.gz to DATA folder.
We can use Gparted, to define the partitions. See below sections
After power up, I powered on the system, and alright! it woke up with this static IP:
But wait a minute, this is not what I wanted…
This indeed creates a static IP image, and the board will always wake up with 192.168.1.7 IP address, which is a good thing, but I want the user to change this IP address dynamically, and to whatever static IP he/she wants.
The straight answer would be using:
ifconfig eth0 192.168.1.9 up #for setting IP as 192.168.1.9
So this is indeed doable, putting it in some script used by the Petalinux build tool when creating an image. Yet, it will make the system ALWAYS have this static IP, which is not what I wanted.
Googling it I’ve found various links, such as this one or that one. This is doable. I want to present here a different solution, rather sophisticated one which has also other future possibilities.
What if the user will pass the required IP address to an external file, and at power up, a bash script will read it and ifconfig it?
Seems nice. This could also be used for other apps to run at power up. Let’s do it!
My 2-steps solution for “dynamic-static IP”:- set an additional partition in the SD card. This is recommended and handy in any case, to pass files to/from external computer to the SD card.
- add a power-up script for reading a text file to configure the required IP address.
per UG1144:
So, I’ll write the following in my Linux shell:
petalinux-create -t apps --template install --name customScript --enable
Few points worth noticing here:
- The '--enable' parameter is letting Petalinux know we plan to use this application, thus it should be part of the rootfs files. We can do it also manualy, without using the --enable. I'll cover that in a future tips & tricks Petalinux blog I plan to post.
- Pay attention I did not write customScript.c, rather customScript. This is because I do not need c or c++ application, rather bash script, and this is what we'll get.
If we dig deeper to the recipe-apps folder, where all applications are stored, we can find the customScript new folder:
roy-m@kub18-fpga:/fpga/projects/linux_images/myProject/myProjPL$ cd project-spec/meta-user/recipes-apps/
roy-m@kub18-fpga:/fpga/projects/linux_images/myProject/myProjPL/project-spec/meta-user/recipes-apps$ ll
total 12
drwxr-xr-x 3 roy-m Dev_ISL_PCB-di 4096 Sep 30 2019 peekpoke
drwxr-xr-x 3 roy-m Dev_ISL_PCB-di 4096 Sep 30 2019 gpio-demo
drwxr-xr-x 3 roy-m Dev_ISL_PCB-di 4096 Dec 11 19:58 customScript
looking into the customScript folder, there's files folder and customScript.bb bitbake recipe file:
-rw-r--r-- 1 roy-m Dev_ISL_PCB-di 1234 Dec 11 19:58 README
drwxr-xr-x 2 roy-m Dev_ISL_PCB-di 4096 Dec 11 19:58 files
-rw-r--r-- 1 roy-m Dev_ISL_PCB-di 383 Dec 11 19:58 customScript.bb
The
bitbake recipe file should look like that:
#
# This file is the customScript recipe.
#
SUMMARY = "Simple customScript application"
SECTION = "PETALINUX/apps"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://customScript \
"
S = "${WORKDIR}"
do_install() {
install -d ${D}/${bindir}
install -m 0755 ${S}/customScript ${D}/${bindir}
}
I'll change it to look like that:
SUMMARY = "Simple customscript application"
SECTION = "PETALINUX/apps"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://customscript \
"
S = "${WORKDIR}"
FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
inherit update-rc.d
INITSCRIPT_NAME = "customscript"
INITSCRIPT_PARAMS = "start 99 S ."
do_install() {
install -d ${D}${sysconfdir}/init.d
install -m 0755 ${S}/customscript ${D}${sysconfdir}/init.d/customscript
}
FILES_${PN} += "${sysconfdir}/*"
The customcript bash file created has just two lines:
#!/bin/sh
echo "Hello PetaLinux World"
So, I'm going to tweak it a bit, and explain later on each line, bare with me on this one:
#!/bin/sh
echo "Let's change the IP at power up!"
# remember we set the static IP to 192.168.1.7?
# look above few paragraphs, if you don't...
# mounting additional folder to my SD card
mkdir -m 755 /media/sdstuff
mount -t ext4 /dev/mmcblk0p3 /media/sdstuff/
# defining the changeIP.txt file
file="/media/sdstuff/changeIP.txt"
echo "changing IP"
# checks if the IP txt file exists
if [[ -f "$file" ]]
then
echo "changing IP according to file"
while IFS= read -r line
do
echo '%s\n' "$line"
ifconfig eth0 $line up
done <"$file"
fi
Use GPARTED to add "stuff" partitionThe above script is rather self explanatory. What I did is the following:
1. mounted additional folder, called SDStuff to the SD card. I've used great tool called gparted to do that. With this tool one can the BOOT and DATA partition easily:
Partition 1: FAT32, Label: BOOT, size: 1GB
Partition 2: EXT4, Label: DATA, size: 2GB
Partition 2: EXT4, Label: STUFF, size: 1GB
Important to add 4MB of unallocated space ahead of the first partition will bring more stability to the system. This is because the MBR, which holds info of the logical partitions, is located before the BOOT partition. Most SD cards erase block size is 4MB. So, if we place the BOOT partition starting at address 0 (4MB alignment) without allocating space for MBR, we'll delete the MBR. Obviously, we do not want to do that...
2. defined a txt file named: changeIP.txt. This file resides in the SDTUFF partition, and passed by the user. It holds one line of the updated IP address, for example:
192.168.1.52
3. checks if the file exists, if so, replace the IP with the updated IP. If not, leave the IP as is (i.e., 192.68.1.7).
Last step is building the whole project, using 'build':
roy-m@kub18-fpga:/fpga/projects/linux_images/myProject/myProjPL$ petalinux-build
Now, after placing the various files in the SD card partitions, let's check the power up now. We've already seen it what happens when the file changeIP.txt does not exit (setting the fixed IP address). Before checking what happens when it does exist, just want to add that using WINSCP is a great way passing files from Windows OS to Linux, since my main OS is a Windows 10, so need to find some way of passing this txt file to the sdStuff folder.
In the above example I've set the IP in the txt file to be 192.168.1.52.
Checking it with 'ifconfig' we can see we have winner here!
And, always recommended to verify 'Dropbear' is working as expected, and we can ssh the session:
Let's also dive into the changeIP.txt file to see what's inside:
So, what we've seen here is the process of enable the user to change the IP dynamically, using a text file which holds only the desired IP address. This text file will be loaded at power up and configure the system.
Hope you enjoyed it as much as I did!
Comments
Please log in or sign up to comment.