Wednesday 4 April 2018

Yocto with Theja


Best For Yocto / bitbake open embedded articles:

Development Environment Setup
Working with Bitbake Recipes
Managing meta layers
Embedded Distributions using Yocto
Peripherals and Libraries with Yocto
Customising Yocto
Error and Failures
Reference’s, Books and Documentation

Every thing is covered in below link:       

http://www.lynxbee.com/build-framework-articles/yocto-bitbake-openembedded-articles/

compile and install dts


Integrating Linux kernel module inside Linux kernel source and building it as part of kernel compilation


If you have already followed “Writing first Linux kernel Module and understanding Kernel module compilation, loading and unloading”, you might have already understood how to build simple kernel module for x86 which we compiled from outside kernel source code for a x86 system which was already running with linux kernel,
Now, Lets try to integrate same kernel module as part of Linux kernel source code, so we can also cross compile the same for ARM and also set an option to make it as part of kernel binary ( zImage/uImage) or build it as module using kernel build framework.
Follow, steps from “Cross Compilation and Booting of Linux kernel for Raspberry Pi3 – Manual Compilation” to clone kernel source code for Raspberry Pi, toolchain and setup the environment to cross compile kernel image zImage and modules from the default configuration.
 cd linux 
create a directory to write a kernel module as,
 mkdir drivers/helloworld/ 
Now, lets write our basic helloworld kernel module / device driver in drivers/helloworld/helloworld.c
 vim drivers/helloworld/helloworld.c 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
 
static int __init hello_init(void) {
        printk(KERN_INFO "Hello, world\n");
        return 0;
}
 
static void __exit hello_exit(void) {
        printk(KERN_INFO "Goodbye, world\n");
}
 
module_init(hello_init);
module_exit(hello_exit);
To, get this driver module compiled as part of kernel, we need to write Makefile and Kconfig file by following Linux kernel build mechanism, the contents of those files will be as below,
 vim drivers/helloworld/Makefile 
1
obj-$(CONFIG_HELLOWORLD) += helloworld.o
 vim drivers/helloworld/Kconfig 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#
# Helloworld driver as part of kernel source
#
 
menu "Helloworld Driver"
 
config HELLOWORLD
        depends on ARM
        tristate "helloworld module"
        default y
        help
          Helloworld kernel module integrated as part of kernel source.
 
endmenu
here, as part of Kconfig, we are telling the Kernel build framework, that this driver can have 3 states for configuration as, “not selected”, “y” i.e. selected as part of kernel image and “m” selected to build as kernel module which is indicated by “tristate” , configuration parameter “depends” tells build framework to select this kernel module if “ARM” has been selected, ( you can change as you want to set dependency ), parameter “default y” selects this Confifuration parameter HELLOWORLD as “CONFIG_HELLOWORLD=y” in the default configuration, where as “help” shows the respective information in “make menuconfig”
Now, we need to tell the kernel build framework to consider our newly created driver directory for the compilation, by appending following line into “drivers/Kconfig” as,
 vim drivers/Kconfig 
1
source "drivers/helloworld/Kconfig"
and
append following line to drivers/Makefile as,
 vim drivers/Makefile 
1
obj-$(CONFIG_HELLOWORLD)       += helloworld/
Now, we are ready to start the compilation of the kernel, currently because we have mentioned “config HELLOWORLD” as “default y” , if we do
 make ARCH=arm CROSS_COMPILE=arm-bcm2708-linux-gnueabi- menuconfig 
we will see following things in “Device Drivers —> Helloworld Driver —> <*> helloworld module” in “Help”

You can use space bar to select and deselect “helloworld module” for,
1. deselect as < > helloworld module
2. select as module, helloworld module
3. select as in built to kernel image as, <*> helloworld module
after selecting proper type as above, click “Exit” till you see following window,
  
                              Do you wish to save your new configuration?
                           │  (Press  to continue kernel configuration.)    │  
                           ├──────────────────────────────────────────────────────────┤  
                           │                   < Yes >      <  No  >         
select “yes” in this as if you open updated, .config file you will see a new option added as,
#
# Helloworld Driver
#
CONFIG_HELLOWORLD=y
Now, lets build kernel image, as
 $ make ARCH=arm CROSS_COMPILE=arm-bcm2708-linux-gnueabi- zImage
  CHK     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  CHK     include/generated/bounds.h
  CHK     include/generated/timeconst.h
  CHK     include/generated/asm-offsets.h
  CALL    scripts/checksyscalls.sh
  CHK     include/generated/compile.h

  CC      drivers/helloworld/helloworld.o
  LD      drivers/helloworld/built-in.o
  LD      drivers/built-in.o

  LD      vmlinux.o
  MODPOST vmlinux.o
  GEN     .version
  CHK     include/generated/compile.h
  UPD     include/generated/compile.h
  CC      init/version.o
  LD      init/built-in.o
  KSYM    .tmp_kallsyms1.o
  KSYM    .tmp_kallsyms2.o
  LD      vmlinux
  SORTEX  vmlinux
  SYSMAP  System.map
  OBJCOPY arch/arm/boot/Image
  Kernel: arch/arm/boot/Image is ready
  GZIP    arch/arm/boot/compressed/piggy_data
  AS      arch/arm/boot/compressed/piggy.o
  LD      arch/arm/boot/compressed/vmlinux
  OBJCOPY arch/arm/boot/zImage
  Kernel: arch/arm/boot/zImage is ready
Now to compile same driver as kernel module, select it as “m” in kernel menuconfig as,
 make ARCH=arm CROSS_COMPILE=arm-bcm2708-linux-gnueabi- menuconfig 
we will see following things in “Device Drivers —> Helloworld Driver —> helloworld module”
and then compile as,
$ make ARCH=arm CROSS_COMPILE=arm-bcm2708-linux-gnueabi- modules
  scripts/kconfig/conf  --silentoldconfig Kconfig
  CHK     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  CC      kernel/bounds.s
  CHK     include/generated/bounds.h
  CHK     include/generated/timeconst.h
  CC      arch/arm/kernel/asm-offsets.s
  CHK     include/generated/asm-offsets.h
  CALL    scripts/checksyscalls.sh
  CC      scripts/mod/empty.o
  MKELF   scripts/mod/elfconfig.h
  HOSTCC  scripts/mod/modpost.o
  CC      scripts/mod/devicetable-offsets.s
  GEN     scripts/mod/devicetable-offsets.h
  HOSTCC  scripts/mod/file2alias.o
  HOSTCC  scripts/mod/sumversion.o
  HOSTLD  scripts/mod/modpost
  GZIP    kernel/config_data.gz
  CHK     kernel/config_data.h
  UPD     kernel/config_data.h
  CC [M]  kernel/configs.o
  CC [M]  drivers/helloworld/helloworld.o
  Building modules, stage 2.
  MODPOST 1561 modules
  CC      drivers/helloworld/helloworld.mod.o
  LD [M]  drivers/helloworld/helloworld.ko
  CC      kernel/configs.mod.o
  LD [M]  kernel/configs.ko
Now, we have to install this modules for copying into hardware, to do that we have to create separate directory for output binaries and setting INSTALL_MOD_PATH to this directory,
 $ mkdir out 
 $ make ARCH=arm CROSS_COMPILE=arm-bcm2708-linux-gnueabi- modules_install INSTALL_MOD_PATH=./out 
So this will create a out directory with all

Writing first Linux kernel Module and understanding Kernel module compilation, loading and unloading

We will try to understand the simple kernel driver which initially we will compile for ubuntu host and later for a embedded hardware.
 $ mkdir module_workspace 
 $ vim hello.c 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
 
static int __init hello_init(void)
{
printk(KERN_INFO “Hello, world\n”);
return 0;
}
 
static void __exit hello_exit(void)
{
printk(KERN_INFO “Goodbye, world\n”);
}
 
module_init(hello_init);
module_exit(hello_exit);
Create a Makefile,
 $ vim Makefile

obj-m += hello.o

all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Now, compile this kernel module for ubuntu x86 based host,
$ make
make -C /lib/modules/3.19.0-30-generic/build M=/home/devbee/devlab/module_workspace modules
make[1]: Entering directory '/usr/src/linux-headers-3.19.0-30-generic'
CC [M] /home/devbee/devlab/module_wokspace/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/devbee/devlab/module_workspace/hello.mod.o
LD [M] /home/devbee/devlab/module_workspace/hello.ko
make[1]: Leaving directory '/usr/src/linux-headers-3.19.0-30-generic'
 $ ls
hello.c hello.mod.c hello.o modules.order
hello.ko hello.mod.o Makefile Module.symvers
 $ file hello.ko
hello.ko: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), BuildID[sha1]=2a1da63ae5631484cc4db328425ad533b8b7b5a0, not stripped
$ tree
.
├── hello.c
├── hello.ko
├── hello.mod.c
├── hello.mod.o
├── hello.o
├── Makefile
├── modules.order
└── Module.symvers

0 directories, 8 files
The “tree” command shows the output files generated during compilation process. Now, we will try to insert that module to kernel as,
$ sudo insmod ./hello.ko
Notice, the error if any, now you can check if the module is successfully inserted to the system,
$ dmesg
[ 2260.748252] hello: module license 'unspecified' taints kernel.
[ 2260.748261] Disabling lock debugging due to kernel taint
[ 2260.748315] hello: module verification failed: signature and/or required key missing - tainting kernel
[ 2260.748790] Hello, world
$ lsmod | grep hello
hello 16384 0
Notice that the module has been inserted into the system with some license warning, which we will try to understand ahead, lsmod shows the list of modules running.
Now, lets try to remove this module from kernel as below,
$ sudo rmmod hello
$ dmesg
[ 3026.031566] Goodbye, world
above dmesg command shows, rmmod command called “module_exit” from our driver and displayed the message.
Here, in above code we had got th e following warning,
$ dmesg
[ 2260.748252] hello: module license 'unspecified' taints kernel.
[ 2260.748261] Disabling lock debugging due to kernel taint
[ 2260.748315] hello: module verification failed: signature and/or required key missing - tainting kernel
This was due to missing LICENSE, so we added the following lines at the end of kernel module hello.c
MODULE_AUTHOR(“DEVBEE”);
MODULE_DESCRIPTION(“Hello World Example”);
MODULE_LICENSE(“GPL”);
Which will remove this warning.
$ make 
$ sudo insmod ./hello.ko 
$ dmesg
[ 4051.863842] Hello, world
In our next post, we will try to understand “Passing command line Arguments / Parameters to Linux kernel module

Understanding bbappend file and writing the bbappend bitbake recipe



A recipe that appends Metadata to another recipe is called a BitBake append file. A BitBake append file uses the .bbappend file type suffix, while the corresponding recipe to which Metadata is being appended uses the .bb file type suffix.
You can use a .bbappend file in your layer to make additions or changes to the content of another layer’s recipe without having to copy the other layer’s recipe into your layer. Your .bbappend file resides in your layer, while the main .bb recipe file to which you are appending Metadata resides in a different layer.
Being able to append information to an existing recipe not only avoids duplication, but also automatically applies recipe changes from a different layer into your layer. If you were copying recipes, you would have to manually merge changes as they occur.
When you create an append file, you must use the same root name as the corresponding recipe file. For example, the append file someapp_2.4.bbappend must apply to someapp_2.4.bb. This means the original recipe and append file names are version number-specific. If the corresponding recipe is renamed to update to a newer version, you must also rename and possibly update the corresponding .bbappend as well. During the build process, BitBake displays an error on starting if it detects a .bbappend file that does not have a corresponding recipe with a matching name. See the BB_DANGLINGAPPENDS_WARNONLY variable for information on how to handle this error.
As an example, consider the main formfactor recipe and a corresponding formfactor append file both from the Source Directory. Here is the main formfactor recipe, which is named formfactor_0.0.bb and located in the “meta” layer at meta/recipes-bsp/formfactor:

SUMMARY = "Device formfactor information"
SECTION = "base"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
PR = "r45"
S = "${WORKDIR}"
PACKAGE_ARCH = "${MACHINE_ARCH}"
INHIBIT_DEFAULT_DEPS = "1"
do_install() {
    # Install file only if it has contents
        install -d ${D}${sysconfdir}/formfactor/
        install -m 0644 ${S}/config ${D}${sysconfdir}/formfactor/
    if [ -s "${S}/machconfig" ]; then
            install -m 0644 ${S}/machconfig ${D}${sysconfdir}/formfactor/
    fi



In the main recipe, note the SRC_URI variable, which tells the OpenEmbedded build system where to find files during the build.

Following is the append file, which is named formfactor_0.0.bbappend and is from the Raspberry Pi BSP Layer named meta-raspberrypi. The file is in the layer at recipes-bsp/formfactor:
FILESEXTRAPATHS_prepend := “${THISDIR}/${PN}:”

By default, the build system uses the FILESPATH variable to locate files. This append file extends the locations by setting the FILESEXTRAPATHS variable. Setting this variable in the .bbappend file is the most reliable and recommended method for adding directories to the search path used by the build system to find files.
The statement in this example extends the directories to include ${THISDIR}/${PN}, which resolves to a directory named formfactor in the same directory in which the append file resides (i.e. meta-raspberrypi/recipes-bsp/formfactor. This implies that you must have the supporting directory structure set up that will contain any files or patches you will be including from the layer.
Using the immediate expansion assignment operator := is important because of the reference to THISDIR. The trailing colon character is important as it ensures that items in the list remain colon-separated.
Note
BitBake automatically defines the THISDIR variable. You should never set this variable yourself. Using “_prepend” as part of the FILESEXTRAPATHS ensures your path will be searched prior to other paths in the final list.
Also, not all append files add extra files. Many append files simply exist to add build options (e.g. systemd). For these cases, your append file would not even use the FILESEXTRAPATHS statement.

Reference –
http://www.lynxbee.com/yocto-understanding-bbappend-file-and-writing-the-bbappend-bitbake-recipe/
http://www.yoctoproject.org/docs/latest/mega-manual/mega-manual.html