Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Michele Dionisio & Pietro Lorefice - Developing and testing a device driver without the device

85 views

Published on

The development of device drivers usually requires hardware availability. We will try to address this issue by simulating our “missing” device thanks to a QEMU ARM machine. The fake device will be tested and debugged using bare-metal software, again running in QEMU. Finally, we will write a Linux device driver from scratch that will interact with the device and expose it to the userspace.

The training assumes some basic knowledge of the C programming language and using Linux as a development platform. During the training, we will show how to build the Linux kernel and write a simple yet complete device driver, how to use QEMU as a development platform and a few notions of bare-metal and kernel code debugging.

Published in: Software
  • Be the first to comment

  • Be the first to like this

Michele Dionisio & Pietro Lorefice - Developing and testing a device driver without the device

  1. 1. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Developing and testing a device driver without the device 1 git clone --recurse-submodules git@github.com:mdionisio/linuxlab2018.git
  2. 2. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com BEFORE WE START 2 git clone --recurse-submodules git@github.com :mdionisio/linuxlab2018.git apt-get install build-essential apt-get install crossbuild-essential-armhf apt-get install gcc-arm-linux-gnueabihf apt-get install gcc-arm-none-eabi apt-get install libncurses5-dev apt-get install bison flex libssl-dev bc apt-get install python pkg-config libglib2.0-dev libpixman-1-dev apt-get install sudo cpio lzop gzip apt-get install gdb-multiarch
  3. 3. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Who we are 3
  4. 4. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com What we will see 4 1. Qemu a. Introduction b. Developing a new simple emulated device c. Adding it to an existing machine 2. Test a. Simple bare-metal cortex a9 project b. Test and debug with qemu 3. Test with Linux a. Create a minimal rootfs 4. Develop a test a linux driver a. Developing device driver b. Adding it to and existing board configuring the device tree c. Test
  5. 5. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com 5 Image coming from qemu web site: www.qemu.org
  6. 6. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Device Specification 6 1. One memory mapped RW registry. You can read on it the last value write plus 1. 2. If you write 1 and interrupt is raised and writing 0 the interrupt is acknowledged Device is installed in a custom board coming from Sambrelite board This board is based on i.mx6 that is a ARM Cortex A9 MP processor so we will use a gcc for that platform for developing and testing
  7. 7. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com And now …. A brief introduction to QOM. And jump to the C code 7
  8. 8. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com We have the device emulated and we can start to add it to a machine emulated. So go back to the QEMU source code 8
  9. 9. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com A bare metal CORTEX-A9 startup.S 9
  10. 10. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com And now LINUX 10 To develop and test a linux device driver we need a working Linux system. So before start to develop we have to create a minimal Linux system. 1. Build linux kernel 2. Build busybox 3. Build a minimal rootfs that can be mounted in ram. INITRAMFS The result is not a full linux distribution but is something perfect for develop and test.
  11. 11. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Test the created Linux system 11
  12. 12. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com 12 Questions ? Image coming from film Io Robot
  13. 13. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Organization of a Linux system 13 © CC BY-SA 3.0 Bootlin, 2004-2018
  14. 14. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Role of the Linux kernel ▸ Interact with the underlying hardware ▸ Provide a set of portable, architecture-independent API ▸ Handle concurrent access 14
  15. 15. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Interacting with the kernel: syscalls ▸ Kernel and userspace communicate using system calls, or syscalls ▹ A modern Linux kernel implements around 300 syscalls ▸ Syscalls are propagated by the kernel to the dedicated driver ▸ Drivers handle the request and return a status code to the calling process 15
  16. 16. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Interacting with the kernel: pseudo-filesystems ▸ Kernel can also present statistics and configurations using pseudo-filesystems ▸ Usually mounted automatically at boot ▸ Several pseudo-filesystems exist with different roles ▹ proc, mounted on /proc ▹ sysfs, mounted on /sys 16
  17. 17. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Kernel organization 17 © CC BY-SA 3.0 Bootlin, 2004-2018
  18. 18. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Working on the Linux kernel 18
  19. 19. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Cross-compiling 19 ▸ By default, Linux is configured and built for the host system ▸ Use ARCH and CROSS_COMPILE variables to change target platform ▸ Different configuration options are available for different platforms
  20. 20. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Configuring the kernel 20 ▸ To use an existing configuration: make <config-name>_defconfig ▹ Configurations available in arch/<arch>/configs/ ▸ To modify the current configuration: make menuconfig
  21. 21. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Building the kernel 21 ▸ To build the kernel: make -jN ▸ Build outputs ▹ ./vmlinux ▹ ./arch/<arch>/boot/*Image ▹ ./arch/<arch>/boot/dts/*.dtb ▹ ./**/*.ko
  22. 22. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Writing a kernel driver 22
  23. 23. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Hello World! 23 ▸ (Optional) Create a dedicated directory under drivers/ ▸ Create the necessary Kconfig options and Makefile rules ▸ Write code!
  24. 24. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Some words of warning ▸ A kernel module is not a userspace application! ▹ Does not execute sequentially ▹ Does no automatic cleanup ▹ Can be interrupted ▹ Does not have floating-point support 24
  25. 25. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Device drivers 25
  26. 26. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com ▸ Access to the hardware is abstracted as a stream of bytes ▹ Serial ports and text consoles are example of char devices ▸ Many hardware peripherals can be abstracted as char devices ▹ Flash memories ▹ Frame grabbers ▹ ADC, DAC, shift registers Character device 26
  27. 27. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Majors and minors 27 ▸ Char devices are accessed using device nodes ▹ Usually located in the /dev directory ▸ A combination of major and minor is used to identify the device ▹ The major number identifies the device driver ▹ Minors usually identify a device instance of a given driver
  28. 28. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Platform drivers 28
  29. 29. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Platform device ▸ A device located on a bus with minimal infrastructure ▹ Most peripheral controllers on ARM SoCs are platform devices ▸ Usually addressed directly by the CPU ▹ Eg. using memory-mapped registers ▸ In Linux, they are handled using platform drivers 29
  30. 30. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Platform driver ▸ Implemented using struct platform_driver ▹ Registered using platform_driver_register() ▸ Enumeration is performed by the kernel ▹ During enumeration, .probe() is invoked ▹ During shutdown, .remove() is invoked ▸ The driver should actually check that the hardware exists 30
  31. 31. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Device Tree 31
  32. 32. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Device Tree 32 ▸ Embedded architectures often have non-discoverable peripherals ▹ This is the case for ARM processors, for example ▸ We need a way to describe the hardware connected to such platforms ▸ Enter the Device Tree!
  33. 33. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Device Tree 33 ▸ Organized in .dts and .dtsi files ▸ Compiled in .dtb files ▸ Several roles in the Linux kernel ▹ Describing devices attached to non-discoverable buses ▹ Configure pin muxing on SoCs ▹ Configure some system parameters (memory layout, flash partitioning etc.)
  34. 34. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Device Tree 34 #include "imx6q.dtsi" #include "imx6qdl-sabrelite.dtsi" / { model = "Freescale i.MX6 Quad SABRE Lite Board"; compatible = "fsl,imx6q-sabrelite", "fsl,imx6q"; soc { qemudev: qemu-test@50000000 { compatible = "linuxlab,qemu-test"; reg = <0x50000000 4>; status = "okay"; }; }; };
  35. 35. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com I/O operations 35
  36. 36. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com I/O operations ▸ I/O operations performed on device nodes are propagated to the driver ▹ open(), read(), write(), close(), … ▸ Drivers need to define a callback for each handled syscall ▸ This is done using the struct file_operations ▹ Structure members are all function pointers 36
  37. 37. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Common file operations ▸ open() – called each time the device is opened from userspace ▸ read() – called when data is sent from the device to userspace ▸ write() – called when data is sent from userspace to the device ▸ release() – called when the device is closed in userspace 37
  38. 38. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Exchanging data with userspace ▸ Special care must be used to access user memory pointers in I/O callbacks ▹ User memory is different from kernel memory, and can’t be accessed directly ▸ copy_to_user() – Copy data from kernel memory to user memory ▸ copy_from_user() – Copy data from user memory to kernel memory 38
  39. 39. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Interrupt handling 39
  40. 40. Pietro Lorefice | Develer S.r.l. | pietro@develer.comMichele Dionisio | Powersoft SPA | michele.dionisio@powersoft.com Interrupts ▸ Most peripherals or devices use interrupts to signal asynchronous events ▹ ADC conversion performed, SPI transfer completed, etc. ▸ In Linux, drivers can request to serve one or more specific interrupts ▹ Usually each peripheral controller has its own interrupt line ▸ A device tree entry can be used to specify the interrupt index ▹ Interrupt numbering is platform- and controller-specific 40

×