{"id":122,"date":"2018-02-05T15:39:12","date_gmt":"2018-02-05T23:39:12","guid":{"rendered":"https:\/\/sysprogs.com\/tutorials\/?p=122"},"modified":"2018-02-05T15:39:12","modified_gmt":"2018-02-05T23:39:12","slug":"building-and-deploying-raspberry-pi-kernel","status":"publish","type":"post","link":"https:\/\/sysprogs.com\/VisualKernel\/tutorials\/raspberry\/buildkernel\/","title":{"rendered":"Building and Deploying Raspberry PI Kernel"},"content":{"rendered":"<p>This tutorial shows how to build a Raspberry PI kernel and install it on the device. As building the kernel on Raspberry PI itself could take several days due to a relatively slow CPU, we will be using an additional Linux machine to build it.<\/p>\n<ol>\n<li>Raspberry PI kernel is stored in a Git repository and requires installing a Git client to fetch the files. Install the client on your build machine. E.g. on Debian-based systems it can be done by running the following command:\n<pre class=\"code\">sudo apt-get install git<\/pre>\n<\/li>\n<li>Create a directory to store Raspberry-related files (e.g.\u00a0<strong>\/home\/&lt;username&gt;\/raspberry<\/strong>) and run the following command in that directory:\n<pre class=\"code\">git clone https:\/\/github.com\/raspberrypi\/linux.git<\/pre>\n<p>The Raspberry PI kernel source will be downloaded to the &#8216;linux&#8217; subdirectory (1.5-2 GB):<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/raspberry\/buildkernel\/img\/01-getsource.png\" width=\"700\" height=\"348\" \/><\/li>\n<li>Download Raspberry PI cross-compilers by running the following command on your build machine:\n<pre class=\"code\">git clone https:\/\/github.com\/raspberrypi\/tools<\/pre>\n<p>The tools will be unpacked into the &#8216;tools&#8217; subdirectory and will occupy ~1GB of space:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/raspberry\/buildkernel\/img\/02-tools.png\" width=\"700\" height=\"348\" \/><\/li>\n<li>The Raspberry PI tools directory contains several toolchain versions:\n<ul>\n<li>tools\/arm-bcm2708\/arm-bcm2708hardfp-linux-gnueabi<\/li>\n<li>tools\/arm-bcm2708\/arm-bcm2708-linux-gnueabi<\/li>\n<li>tools\/arm-bcm2708\/gcc-linaro-arm-linux-gnueabihf-raspbian<\/li>\n<\/ul>\n<p>The last one is the toolchain containing the linaro patches, so we will use it for cross-compilation. Set the CCPREFIX environment variable to the prefix of the third toolchain and test it by invoking GCC using the prefix, e.g.:<\/p>\n<pre class=\"code\">export CCPREFIX=\/home\/testuser\/raspberry\/tools\/arm-bcm2708\/gcc-linaro-arm-linux-gnueabihf-raspbian\/bin\/arm-linux-gnueabihf-\u00a0\r\n${CCPREFIX}gcc -v<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/raspberry\/buildkernel\/img\/03-gcc.png\" width=\"700\" height=\"671\" \/><\/li>\n<li>Before we can build the kernel we need to configure it. A very good starting point would be the configuration file from your existing Raspberry PI that can be obtained by reading and unpacking the\u00a0<strong>\/proc\/config.gz<\/strong>\u00a0file on Raspberry PI. Go to the &#8216;linux&#8217; subdirectory with the downloaded kernel sources and run the following commands there (assuming &#8216;<strong>raspberrypi<\/strong>&#8216; is the host name of your Raspberry PI):\n<pre class=\"code\">scp pi@raspberrypi:\/proc\/config.gz .\u00a0\r\ngunzip -c config.gz &gt; .config<\/pre>\n<p>If the config.gz file is missing, run the following command to load the module that provides it:<\/p>\n<pre class=\"code\">sudo modprobe configs<\/pre>\n<\/li>\n<li>Run the following command in the Linux kernel source directory to bootstrap the new kernel configuration from the<strong>.config<\/strong>\u00a0file obtained from Raspberry PI. Note that if you used an old SD card image, you will get a lot of questions on recently added features not mentioned in the old config file:\n<pre class=\"code\">ARCH=arm CROSS_COMPILE=${CCPREFIX} make oldconfig<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/raspberry\/buildkernel\/img\/05-oldconfig.png\" width=\"700\" height=\"523\" \/><span class=\"warning\">Do not forget to specify ARCH. Otherwise the kernel will be configured using x86 configuration options and will be missing ARM ones leading to a build failure.<\/span><\/li>\n<li>Now reset all previous options related to debug symbols and enable them explicitly:\n<pre class=\"code\">grep -v DEBUG_INFO &lt; .config &gt; newconfig\u00a0\r\nmv newconfig .config\u00a0\r\nARCH=arm CROSS_COMPILE=${CCPREFIX} make oldconfig<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/raspberry\/buildkernel\/img\/debuginfo.png\" width=\"700\" height=\"422\" \/>Enable the &#8216;DEBUG_INFO&#8217; option and don&#8217;t enable the DEBUG_INFO_REDUCED option.<\/li>\n<li>Now it&#8217;s time to build the kernel. Run the following command:\n<pre class=\"code\">ARCH=arm CROSS_COMPILE=${CCPREFIX} make<\/pre>\n<p>Building the kernel can take several hours and can be sped up by adding a &#8216;-j&lt;amount of cores&gt;&#8217; on a multi-core machine to parallelize the build.<\/li>\n<li>If the build breaks on an internal compiler error while generating debug information for some functions, open the corresponding source file and add the following line before the failing function:\n<pre class=\"code\">#pragma GCC optimize(\"-g0\")<\/pre>\n<p>This will disable debug information generation for the rest of that source file, while keeping it enabled for the reset of the kernel.<\/li>\n<li>Once the kernel build is complete we need to verify that it contains the symbols. Open the kernel image using the gdb from the cross-toolchain and look at the value of\u00a0<strong>init_uts_ns.name.release<\/strong>:\n<pre class=\"code\">${CCPREFIX}gdb vmlinux\u00a0\r\nprint init_uts_ns.name.release<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/raspberry\/buildkernel\/img\/gdbkernelver.png\" width=\"700\" height=\"422\" \/>If GDB can display the kernel release string, the kernel has been built with sufficient symbols for kernel debugging.<\/li>\n<li>Now that we have verified that the kernel contains the symbols, we will need to generate a directory containing kernel modules that Raspberry PI can load when needed. Run the following command to copy the modules to the &#8216;..\/modules&#8217; directory:\n<pre class=\"code\">ARCH=arm CROSS_COMPILE=${CCPREFIX} INSTALL_MOD_PATH=..\/modules make modules_install<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/raspberry\/buildkernel\/img\/06-modules.png\" width=\"700\" height=\"523\" \/><\/li>\n<li>Now we need to upload the new kernel and the new modules to Raspberry PI. First we will create an uncompressed kernel image and upload it to the temporary directory on Raspberry PI. Run the following commands on your build machine:\n<pre class=\"code\">cd &lt;raspberry pi downloads&gt;\/tools\/mkimage\u00a0\r\n.\/imagetool-uncompressed.py ..\/..\/linux\/arch\/arm\/boot\/zImage\u00a0\r\nscp kernel.img pi@raspberrypi:\/tmp<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/raspberry\/buildkernel\/img\/07-uploadkernel.png\" width=\"700\" height=\"310\" \/><\/li>\n<li>Then go to the &#8216;modules&#8217; subdirectory we created before, make a tar archive containing the modules and upload it to Raspberry PI:\n<pre class=\"code\">cd &lt;raspberry pi downloads&gt;\/tools\/modules\u00a0\r\ntar czf modules.tgz *\u00a0\r\nscp modules.tgz pi@raspberrypi:\/tmp<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/raspberry\/buildkernel\/img\/08-uploadmodules.png\" width=\"700\" height=\"310\" \/><\/li>\n<li>Finally we need to install the kernel and the modules. Connect to your Raspberry PI over SSH and run the following commands:\n<pre class=\"code\">cd \/\u00a0\r\nsudo mv \/tmp\/kernel.img \/boot\/\u00a0\r\nsudo tar xzf \/tmp\/modules.tgz\u00a0\r\nrm \/tmp\/modules.tgz<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/raspberry\/buildkernel\/img\/09-unpack.png\" width=\"688\" height=\"300\" \/>If you now list the contents of \/lib\/modules you will see that it now also contains the modules for the new kernel.<\/li>\n<li>Restart your Raspberry PI to boot the new kernel:\n<pre class=\"code\">sudo shutdown -r now<\/pre>\n<\/li>\n<li>Once Raspberry PI boots, connect to it over SSH and run the &#8216;uname -r&#8217; command to see the new kernel release:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/raspberry\/buildkernel\/img\/10-version.png\" width=\"635\" height=\"300\" \/>The release string should match the one we queried before when testing the kernel symbols.<\/li>\n<li>Now you should be able to debug your kernel. Follow our\u00a0<a href=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/raspberry\/jtagsetup\/\">Raspberry PI JTAG setup tutorial<\/a>\u00a0if you have not done that already. Once the JTAG connection is established, begin debugging by running the following command on your build machine:\n<pre class=\"code\">${CCPREFIX}gdb vmlinux<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/raspberry\/buildkernel\/img\/12-gdb.png\" width=\"700\" height=\"422\" \/><\/li>\n<li>Connect to OpenOCD by running the &#8220;target remote &lt;OpenOCD host&gt;:3333&#8221; command and display the stack trace using the\u00a0<a href=\"http:\/\/visualgdb.com\/gdbreference\/commands\/backtrace\">bt<\/a>\u00a0command:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/raspberry\/buildkernel\/img\/13-stack.png\" width=\"700\" height=\"422\" \/><\/li>\n<li>Now we&#8217;ll test breakpoint support by setting a breakpoint at the\u00a0<strong>sys_open()<\/strong>\u00a0function:\n<pre class=\"code \">break sys_open continue<\/pre>\n<\/li>\n<li>Now go to the Raspberry PI SSH window and run &#8216;ls \/tmp&#8217; command. The\u00a0<strong>sys_open<\/strong>\u00a0breakpoint will be triggered. Run &#8220;print (char *)filename&#8221; to see the name of the file being opened:<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sysprogs.com\/VisualKernel\/legacy_tutorials\/raspberry\/buildkernel\/img\/14-break.png\" width=\"700\" height=\"521\" \/>You will see that the Linux kernel is opening handles to libraries used by the &#8216;ls&#8217; command.<\/li>\n<\/ol>\n<p>Now that the basic debugging works you can\u00a0<a href=\"http:\/\/sysprogs.com\/VisualKernel\/tutorials\/raspberry\/basicmodule\/\">setup a VisualKernel project to create and debug a basic kernel module<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to build a Raspberry PI kernel and install it on the device. As building the kernel<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[35],"tags":[38,37],"_links":{"self":[{"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/posts\/122"}],"collection":[{"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/comments?post=122"}],"version-history":[{"count":1,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/posts\/122\/revisions"}],"predecessor-version":[{"id":123,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/posts\/122\/revisions\/123"}],"wp:attachment":[{"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/media?parent=122"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/categories?post=122"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sysprogs.com\/tutorials\/wp-json\/wp\/v2\/tags?post=122"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}