Showing posts with label Raspbian. Show all posts
Showing posts with label Raspbian. Show all posts

Monday, October 18, 2021

Use Virtual Machine Manager to create a Raspberry Pi virtual machine on Ubuntu

I tried to use the Virtual Machine Manager (virt-manager)'s graphical user interface on Ubuntu to create a Raspberry Pi virtual machine. I found it to be a little tricky having to know the right parameters and configuration. This post describes the steps I went through to successfully create and run the Raspberry Pi virtual machine.

Install software prerequisites

If virt-manager and/or QEMU are not installed on the Ubuntu host, then run the following commands to install them.

$ sudo apt-get install qemu-kvm libvirt-clients libvirt-daemon-system bridge-utils virtinst libvirt-daemon virt-manager

Download a Raspberry Pi OS image

  1. Open up a browser to https://www.raspberrypi.com/software/operating-systems/.

  2. Click on a Raspberry Pi OS image of your choice to download. For example, Raspberry Pi OS Lite.

  3. Unzip the download file and place the extracted image file e.g. 2021-05-raspios-buster-armhf-lite.img to a folder, e.g. /path/to/folder/.

Download a QEMU kernel and the device tree blob (.dtb) for Raspberry Pi

  1. Open up a browser and browse to the repository https://github.com/dhruvvyas90/qemu-rpi-kernel.

  2. Click on kernel-qemu-4.19.50-buster and download the kernel to a folder, e.g. /path/to/folder/.


  3. Next, click on versatile-pb-buster.dtb and download the file to a folder, e.g. /path/to/folder/.

Create a new VM

  1. On the Ubuntu host, run virt-manager.

    The Virtual Machine Manager graphical application appears.
     
  2. Click the Create a new virtual machine button.

    The New VM dialog box wizard appears.


  3. In the Architecture options drop down, choose armv6l in the Architecture combo box. Then select versatilepb in the Machine Type combo box. Press Forward.

    Step 2 page appears.
     
  4. In the Provide the existing storage path field, click Browse.

    The Choose Storage Volume dialog appears.


  5. Click Browse Local and choose to open the previously downloaded Raspberry Pi OS image, e.g. /path/to/folder/2021-05-raspios-buster-armhf-lite.img.



  6. In the Kernel path field, click the Browse button.

    The Choose Storage Volume appears again.


  7. Click Browse Local and choose to open the previously downloaded kernel file, e.g. /path/to/folder/kernel-qemu-4.19.50-buster.

  8. In the DTB path field, click the Browse button.

    The Choose Storage Volume appears.

  9. Click Browse Local and choose to open the previously downloaded dtb file, e.g. /path/to/folder/versatile-pb-buster.dtb.

  10. In the Kernel args field, type in the following:

    root=/dev/vda2 panic=1

  11. Finally, in the Choose the operating system you are installing field, type and choose the following:

    Generic default (generic)

    The Step 2 of the New VM dialog should look like the screen below.


  12. Click Forward.

    Page Step 3 appears.

  13. In the Memory field, change the value to 256.



  14. Click Forward.

    Page 4 appears.


  15. Optional. Change the Name from vm-armv6l if necessary.

     
  16. Toggle on Customize configuration before install. In the Network selection drop down, select Specify shared device name. Then type in virbr0 in the Bridge name.

  17. Click Finish.

    The vm-armv6l on QEMU/KVM dialog box appears.



Customize configuration

  1. Click CPUs. Then in the Model combo box, choose arm1176. Then click Apply to save the change.



  2. Click Boot Options. Toggle on Enable boot menu. Then Toggle on IDE Disk 1. Click Apply.




  3. Click on IDE Disk 1. Then click the Advanced options drop down. In the Disk bus field, change from IDE to VirtIO. Click Apply.



  4. Click the NIC icon. Then change the Device model to virtio. Click Apply.



  5. Optional. Click Add Hardware to add additional peripherals such as Serial mouse, Video card etc. if necessary.

  6. Click Begin Installation.

    The processing messages appear and the Raspberry Pi VM is created.


Monday, September 30, 2019

CMake example for cross compiling and using a static library for a Raspberry Pi on an Ubuntu PC

Compiling source code on a Raspberry Pi can be sluggish compared to a PC. So instead I decided that cross compilation on an Ubuntu PC would be faster and therefore more productive of my time. So after a few false starts, I finally managed to get the workflow working. This post shows a simple example of how to compile a C++ static library and using that in an executable for Raspberry Pi using the CMake build system on an Ubuntu PC.

Down the Raspberry Pi build tools
The first thing is to get the Raspberry cross compilation tools from the git repository.

In Ubuntu, open a Terminal. Type in the following to download the tools to a folder e.g. /path/to/programs/pi/.

$ cd ~/programs/pi/
$ git clone https://github.com/raspberrypi/tools.git


Create a CMake toolchain file
Next, create a cmake file e.g. /path/to/workspace/toolchain-rpi.cmake specifying the correct Raspberry cross compilation tools for compiling C/C++ source files with the CMAKE_C_COMPILER and CMAKE_CXX_COMPILER macros. Also the root folder of the Raspberry Pi libraries and include files need to be specified with the CMAKE_FIND_ROOT_PATH macro.

Choose the right ones for your Raspberry Pi chipset.

Listing of toolchain-rpi.cmake
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)

# define the C cross compiler for the Raspberry Pi 
SET(CMAKE_C_COMPILER $ENV{HOME}/programs/pi/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc)

# define the C++ cross compiler for the Raspberry Pi
SET(CMAKE_CXX_COMPILER $ENV{HOME}/programs/pi/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-g++)

# define the root location of the Raspberry Pi libraries and includes
SET(CMAKE_FIND_ROOT_PATH $ENV{HOME}/programs/pi/tools/arm-bcm2708/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot)

SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

add_definitions(-Wall -std=c11)

Create the workspace
In the same example project workspace folder /path/to/workspace/, create two folders animallib and uselib, the first for the library files, and the later for the executable files.



Create the static library
The next step is to create the header file and define the classes that will be used by the example executable. Place the Animal.h and Animal.cpp files respectively in the include and src folders under the /path/to/workspace/animallb/ folder.

Listing of Animal.h
#include <string>

using namespace std;

class Animal {
        private:
                string name;
        public:
                Animal(string);
                virtual void print_name();
};

Listing of Animal.cpp
#include <iostream>
#include "Animal.h"

using namespace std;

Animal::Animal(string name): name (name) {}

void Animal::print_name(){
        cout << "Name is " << this->name << endl;
}

Create the static library's CMakeLists.txt file in the animallib folder e.g. /path/to/workspace/animallib/. As defined, this will help to generate a static library libanimallib.a and a header file animallib_Export.h.

cmake_minimum_required(VERSION 2.8.6)
project (animallib)

set (BUILD_SHARED_LIBS OFF)
set (CMAKE_BUILD_TYPE Debug)

#include *.h files under the include folder and
#the project's output folder e.g. build
include_directories (include ${PROJECT_BINARY_DIR})

#compile all *.cpp source files under the src folder
file (GLOB SOURCES "src/*.cpp")

#output static library export file *.a and
#output macro definitions include file
include (GenerateExportHeader)
add_library(animallib STATIC ${SOURCES})
GENERATE_EXPORT_HEADER (animallib
        BASE_NAME animallib
        EXPORT_MACRO_NAME animallib_EXPORT
        EXPORT_FILE_NAME animallib_Export.h
        STATIC_DEFINE animallib_BUILT_AS_STATIC
        )

Open up a Terminal and change directory to the static library's folder e.g. /path/to/workspace/animallib/.

If the build folder does not exist, create it.

$ mkdir build
$ cd build

Type in the cmake command with the CMAKE_TOOLCHAIN_FILE variable pointing to the previously created Raspberry Pi toolchain CMake file.

$ cmake -D CMAKE_TOOLCHAIN_FILE=/path/to/workspace/toolchain-rpi.cmake ..

Build files are generated


In the Terminal, type in the make command to generate the static library file.
$ make
Static library compilation messages
Using the static library in a separate C++ application
Now that the library has been generated, the next thing is to use the library's classes and functions in an executable e.g. uselib project under /path/to/workspace/uselib/.

Listing of uselib.cpp
#include "Animal.h"

#include "animallib_Export.h"

int main(int argc, char *argv[]){
        Animal animal("Dog");
        animal.print_name();
        return (0);
}

Place the source code file uselib.cpp under the src directory e.g. /path/to/workspace/uselib/src/.

Then create a CMakeLists.txt file under the /path/to/workspace/uselib/ folder.
cmake_minimum_required(VERSION 2.8.6)
project (UseLib)

# link as a static library
set(CMAKE_EXE_LINKER_FLAGS "-static")

set (EXAMPLE_DIR $ENV{HOME}/Documents/workspace/learn_rpi/)

# name and location of the library to link with the executable
set (PROJECT_LINK_LIBS animallib)
link_directories (${EXAMPLE_DIR}/animallib/build/)

include_directories (
        ${EXAMPLE_DIR}/animallib/include
        ${EXAMPLE_DIR}/animallib/build
        )

#compile all *.cpp source files under src folder
file (GLOB SOURCES "src/*.cpp")

#output executable name as uselib
add_executable (uselib ${SOURCES})
target_link_libraries (uselib ${PROJECT_LINK_LIBS})

Open up a Terminal. Change directory to the /path/to/workspace/uselib/ folder.

If the build directory does not exist, type in the following to create it.

$ mkdir build

Type in the cmake command with the CMAKE_TOOLCHAIN_FILE variable pointing to the previously created Raspberry Pi toolchain CMake file.

$ cmake -D CMAKE_TOOLCHAIN_FILE=/path/to/workspace/toolchain-rpi.cmake ..

The build files are generated
Compile the executable with the make command.
$ make

Compilation messages
Once the executable uselib has been generated, it can be copied to the Raspberry Pi and run. If you have an arm emulator e.g. qemu installed on the Ubuntu PC, then it can be executed as shown below.
Running the Raspberry Pi executable on the Ubuntu PC with QEMU

Monday, September 16, 2019

Allocating more space to an emulated Raspbian disk image

The Raspberry Pi Raspbian images from http://downloads.raspberrypi.org/raspbian/images/ for QEMU have limited disk space, just enough for booting up and not much else. In the screenshot below, the image has just 3.3GB to it.

In order to work with ROS or other applications, the disk image has to be resized with more free disk space. This can be done by doing the following.
  1. Optional but recommended. Make a copy of the original Raspbian image and rename it, for example as raspbian.img.

    $ cp 2019-06-20-raspbian-buster.img raspbian.img
  2. Extend the copied image's size with the following command in the Terminal.

    $ qemu-img resize raspbian.img +6G


    Note: +6G means to extend the original size by 6 gigabytes
  3. Next, boot up the newly resized image with QEMU.

    $ qemu-system-arm -kernel kernel-qemu-4.4.34-jessie \
      -cpu arm1176 \
      -m 256 \
      -M versatilepb \
      -serial stdio \
      -append "root=/dev/sda2 rootfstype=ext4 rw" \
      -hda raspbian.img \
      -net nic \
      -net user,hostfwd=tcp::5022-:22 \
      -no-reboot


    The QEMU window appears.

  4. In the QEMU window, open up a Terminal.
  5. Enter the following commands to delete and create a new partition.

    $ sudo fdisk /dev/sda
  6. Print out the current partitions by entering p. Make a note of the starting offset of the second partition e.g. 540672.


  7. Delete the second partition by entering d followed by 2. Then recreate the second partition by entering c, n, p, 2, followed by the starting address noted from the previous steps e.g. 540672. Leave the signature alone when prompted.


  8. Now, reboot the emulated Raspbian OS.
  9. When QEMU has restarted the Raspbian OS, open a Terminal and enter the command to resize the file system.

    $ sudo resize2fs /dev/sda2

  10. To see the available disk space, enter the command:

    $ df -h