{"id":107,"date":"2012-10-22T22:51:19","date_gmt":"2012-10-22T22:51:19","guid":{"rendered":"http:\/\/elene.dahners.com\/blog\/?p=107"},"modified":"2012-10-25T23:25:15","modified_gmt":"2012-10-25T23:25:15","slug":"compiling-a-kernel-module-for-beaglebone","status":"publish","type":"post","link":"http:\/\/elene.dahners.com\/blog\/2012\/10\/22\/compiling-a-kernel-module-for-beaglebone\/","title":{"rendered":"Compiling a Kernel Module for BeagleBone"},"content":{"rendered":"<h1>Preface<\/h1>\n<p>This post was written as I attempted to create a kernel module for BeagleBone. The contents includes my troubleshooting efforts and a final resolution as to the method I found which worked, found at the end of the post.<\/p>\n<h1>Troubleshooting Phase<\/h1>\n<p>Here&#8217;s what I started with:<br \/>\nBeagleBone A6 (<code>beaglebone:~$ uname -a<br \/>\nLinux beaglebone 3.2.28 #1 Sun Oct 21 15:51:05 CEST 2012 armv7l GNU\/Linux<\/code>)<br \/>\nUbuntu 11.04 via VMWare Player with the following installed:<\/p>\n<ul>\n<li>git<\/li>\n<li>gawk<\/li>\n<li>subversion<\/li>\n<li>texinfo (stand-in for makeinfo)<\/li>\n<li>texi2html<\/li>\n<li>chrpath<\/li>\n<\/ul>\n<p>To get the Angstrom kernel source, I followed the instructions from <a href=\"http:\/\/www.angstrom-distribution.org\/building-angstrom\">Angstrom<\/a>, plus some hints from the beaglebone specific <a href=\"http:\/\/www.angstrom-distribution.org\/demo\/beaglebone\">page<\/a>.<\/p>\n<pre>git clone git:\/\/github.com\/Angstrom-distribution\/setup-scripts.git\r\ncd setup-scripts\r\nMACHINE=beaglebone .\/oebb.sh config beaglebone\r\nMACHINE=beaglebone .\/oebb.sh update\r\nMACHINE=beaglebone .\/oebb.sh bitbake virtual\/kernel<\/pre>\n<p>On that last step, building the kernel, I ran into an issue:<\/p>\n<pre>NOTE: Error expanding variable buildhistory_get_imageinfo       | ETA:  00:04:56\r\nNOTE: Error during finalise of \/home\/user\/setup-scripts\/sources\/meta-openembedded\/meta-initramfs\/recipes-bsp\/images\/initramfs-kexecboot-klibc-image.bb\r\nERROR: Failure expanding variable buildhistory_get_imageinfo, expression was \tif [ \"${@base_contains('BUILDHISTORY_FEATURES', 'image', '1', '0', d)}\" = \"0\" ] ; then\r\n\t\treturn\r\n\tfi\r\n\r\n...\r\nwhich triggered exception OSError: [Errno 12] Cannot allocate memory\r\nERROR: Command execution failed: Exited with 1\r\nNOTE: Error expanding variable buildhistory_get_imageinfo\r\nNOTE: Error during finalise of \/home\/user\/setup-scripts\/sources\/meta-openembedded\/meta-initramfs\/recipes-bsp\/images\/initramfs-kexecboot-image.bb<\/pre>\n<p>I had started out with only 512MB RAM, being that I only have 2GB on the host machine. I tried upping it to 1GB for the virtual machine, but no dice. Last RAM modification attempt, 2 GB specified for the virtual machine, and yet the failure remained. In my searches, I came across someone who&#8217;d been working on a <a href=\"https:\/\/beagleboard.googlegroups.com\/attach\/f65cb644e2b4cab8\/Kernel%20Module%20Documentation.txt?pli=1&amp;view=1&amp;part=7\">similar setup<\/a> and found they&#8217;d used some additional tools I had not installed:<\/p>\n<ul>\n<li>build-essential (turned out to already be installed, not of my doing)<\/li>\n<li>python-psyco (did not resolve the problem)<\/li>\n<\/ul>\n<p>One of the messages that came up during the config stage had said it preferred bash to dash, but that it was going to access it via \/bin\/sh, so if I really wanted it to be happy, I should remap the symbolic link, which I did. Another message that comes up during the bitbaking suggests to do &#8216;. \/home\/user\/.oe\/environment-angstromv2012.05&#8217; and then run bitbake something (I chose nano) without using .\/oebb.sh. So I gave that a try. It failed almost identically.<\/p>\n<pre>bitbake nano\r\nPseudo is not present but is required, building this first before the main build\r\nNOTE: angstrom DOES NOT support libiconv because the eglibc provided iconv library is used\r\nNOTE: angstrom DOES NOT support libiconv because the eglibc provided iconv library is used\r\nNOTE: Error expanding variable do_populate_sdk#########         | ETA:  00:01:58\r\nNOTE: Error during finalise of \/home\/user\/setup-scripts\/sources\/openembedded-core\/meta\/recipes-core\/meta\/external-python-tarball.bb\r\nERROR: Failure expanding variable METADATA_REVISION, expression was ${@base_detect_revision(d)} which triggered exception OSError: [Errno 12] Cannot allocate memory\r\nERROR: Command execution failed: Exited with 1\r\nNOTE: Error expanding variable toolchain_create_sdk_version\r\nNOTE: Error during finalise of \/home\/user\/setup-scripts\/sources\/openembedded-core\/meta\/recipes-core\/meta\/meta-toolchain-gmae.bb\r\n\r\nSummary: There were 2 ERROR messages shown, returning a non-zero exit code.<\/pre>\n<p>So, I got a borrowed Ubuntu 11.04 machine, as the memory note really seemed important. I started with cloning the setup-scripts repo, configuring for beaglebone, and running the update. Then I stopped, and did the <code>. \/home\/user\/.oe\/environment-angstromv2012.05<\/code> and then run <code>bitbake nano<\/code> steps as previously suggested. This time was much more positive! Note that I disregarded the request to change \/bin\/sh to point to bash as the computer is a loaner. However, quite some time later, nano finished building. I hadn&#8217;t imagined it would take so long, so I wasn&#8217;t watching the clock, so I can only say it took several hours.<\/p>\n<p>Once nano built, I felt confident that I would finally be able to bitbake kernel\/virtual, so I started it and let it run, which it did within a few hours. I went ahead and bitbaked <code>systemd-image<\/code> as well, before finally bitbaking <code>virtual\/kernel -c compile -f<\/code>, as suggested in the\u00a0<a href=\"https:\/\/beagleboard.googlegroups.com\/attach\/f65cb644e2b4cab8\/Kernel%20Module%20Documentation.txt?pli=1&amp;view=1&amp;part=7\">similar setup<\/a> post I mentioned earlier. Finally this created files where the aforementioned post suggests, which look to be what is needed (for me the location was: \/home\/user\/setup-scripts\/build\/tmp-angstrom_v2012_05-eglibc\/work\/beaglebone-angstrom-linux-gnueabi\/linux-ti33x-psp-3.2.28-r16b+gitr720e07b4c1f687b61b147b31c698cb6816d72f01\/git).<\/p>\n<p>Now we should have what is needed to cross compile a kernel module for BeagleBone on Ubuntu. However, things aren&#8217;t just going to start being simple, are they? I set up my extremely basic kernel module:<\/p>\n<pre>#include &lt;linux\/module.h&gt;\r\n#include &lt;linux\/kernel.h&gt;\r\n\r\nstatic int __init enable_usermode(void)\r\n{\r\n        printk(KERN_INFO \"Usermode enabled.\\n\");\r\n        return 0;\r\n}\r\n\r\nstatic void __exit disable_usermode(void)\r\n{\r\n        printk(KERN_INFO \"Usermode disabled.\\n\");\r\n}\r\n\r\nmodule_init(enable_usermode);\r\nmodule_exit(disable_usermode);<\/pre>\n<p>And my Makefile:<\/p>\n<pre>obj-m += enable_usermode.o\r\n\r\nCROSS = \/home\/user\/setup-scripts\/build\/tmp-angstrom_v2012_05-eglibc\/sysroots\/x86_64-linux\/usr\/bin\/armv7a-angstrom-linux-gnueabi\/arm-angstrom-linux-gnueabi-\r\nKDIR = \/home\/user\/setup-scripts\/build\/tmp-angstrom_v2012_05-eglibc\/work\/beaglebone-angstrom-linux-gnueabi\/linux-ti33x-psp-3.2.28-r16b+gitr720e07b4c1f687b61b147b31c698cb6816d72f01\/git\r\n\r\nPWD := $(shell pwd)\r\n\r\nall:\r\n        make -C $(KDIR) M=$(PWD) CROSS_COMPILE=$(CROSS) modules\r\nclean:\r\n        make -C $(KDIR) M=$(PWD) CROSS_COMPILE=$(CROSS) clean<\/pre>\n<p>And ran make, which resulted in this output:<\/p>\n<pre>make -C \/home\/user\/setup-scripts\/build\/tmp-angstrom_v2012_05-eglibc\/work\/beaglebone-angstrom-linux-gnueabi\/linux-ti33x-psp-3.2.28-r16b+gitr720e07b4c1f687b61b147b31c698cb6816d72f01\/git M=\/home\/user\/LKM CROSS_COMPILE=\/home\/user\/setup-scripts\/build\/tmp-angstrom_v2012_05-eglibc\/sysroots\/x86_64-linux\/usr\/bin\/armv7a-angstrom-linux-gnueabi\/arm-angstrom-linux-gnueabi- modules\r\nmake[1]: Entering directory `\/home\/user\/setup-scripts\/build\/tmp-angstrom_v2012_05-eglibc\/work\/beaglebone-angstrom-linux-gnueabi\/linux-ti33x-psp-3.2.28-r16b+gitr720e07b4c1f687b61b147b31c698cb6816d72f01\/git'\r\n  CC [M]  \/home\/user\/LKM\/enable_usermode.o\r\ncc1: error: unrecognized command line option \"-m64\"\r\ncc1: error: unrecognized command line option \"-mno-red-zone\"\r\ncc1: error: unrecognized command line option \"-mcmodel=kernel\"\r\ncc1: error: unrecognized command line option \"-maccumulate-outgoing-args\"\r\nmake[2]: *** [\/home\/user\/LKM\/enable_usermode.o] Error 1\r\nmake[1]: *** [_module_\/home\/user\/LKM] Error 2\r\nmake[1]: Leaving directory `\/home\/user\/setup-scripts\/build\/tmp-angstrom_v2012_05-eglibc\/work\/beaglebone-angstrom-linux-gnueabi\/linux-ti33x-psp-3.2.28-r16b+gitr720e07b4c1f687b61b147b31c698cb6816d72f01\/git'\r\nmake: *** [all] Error 2<\/pre>\n<p>This is disappointing. I figure that there may be some aspect to the way the bitbake setup is done that I&#8217;m causing problems with from my side, so I figure it&#8217;s time to pursue moving to the BeagleBone. (Note, there was a resolution to the above, found below related to using make ARCH=arm.)<\/p>\n<h2>Compiling kernel modules directly on BeagleBone<\/h2>\n<p>I started with this in parallel to the effort on Ubuntu, by trying to get the kernel headers using <code>opkg install kernel-headers<\/code>, however this gave errors:<\/p>\n<pre>$ opkg install kernel-headers\r\nInstalling kernel-headers (3.2.28-r16a+gitr720e07b4c1f687b61b147b31c698cb6816d72f01) to root...\r\nDownloading http:\/\/feeds.angstrom-distribution.org\/feeds\/v2012.05\/ipk\/eglibc\/armv7a\/machine\/beaglebone\/kernel-headers_3.2.28-r16a+gitr720e07b4c1f687b61b147b31c698cb6816d72f01_beaglebone.ipk.\r\nwget: server returned error: HTTP\/1.1 404 Not Found\r\nCollected errors:\r\n* opkg_download: Failed to download http:\/\/feeds.angstrom-distribution.org\/feeds\/v2012.05\/ipk\/eglibc\/armv7a\/machine\/beaglebone\/kernel-headers_3.2.28-r16a+gitr720e07b4c1f687b61b147b31c698cb6816d72f01_beaglebone.ipk, wget returned 1.\r\n* opkg_install_pkg: Failed to download kernel-headers. Perhaps you need to run 'opkg update'?\r\n* opkg_install_cmd: Cannot install package kernel-headers.<\/pre>\n<p>So, I checked out http:\/\/feeds.angstrom-distribution.org\/feeds\/v2012.05\/ipk\/eglibc\/armv7a\/machine\/beaglebone\/, where sure enough the kernel-headers had been updated recently, so I ran <code>opkg update<\/code> as suggested. Unfortunately, using the same kernel module from earlier and the same Makefile with the KDIR changed to <code>KDIR := \/lib\/modules\/$(shell uname -r)\/build<\/code> (and no CROSS_COMPILE), the result of running <code>make<\/code> was a complaint:<br \/>\n<code>make: *** \/lib\/modules\/3.2.28\/build: No such file or directory.\u00a0 Stop.<\/code><br \/>\nLooking into the directory, of course there is no build folder. The only thing I had installed was kernel-headers, which apparently is insufficient for the task of building kernel modules directly on BeagleBone. More disappointingly, I noticed that the only kernel-headers version now available is 3.2.30, while my BeagleBone has Angstrom 3.2.28.<\/p>\n<p>Next, I decided to get a better idea of why I was getting conflicting information about what to use for KDIR in the Makefile. It seems that the standard is to have a symlink \/lib\/modules\/$(uname -r)\/build which points to a folder named for your linux kernel in \/usr\/src. What&#8217;s key is that there should be a Makefile here, which determines how kernel modules are built. So, I began a painfully slow scp of the output of the build on Ubuntu, first compressing setup-scripts\/build\/tmp-angstrom_v2012_05-eglibc\/work\/beaglebone-angstrom-linux-gnueabi\/linux-ti33x-psp-3.2.28-r16b+gitr720e07b4c1f687b61b147b31c698cb6816d72f01\/git to hopefully make the ordeal a bit faster.<\/p>\n<p>With the copy ongoing, I decided to give another shot at the cross compiling. I was looking in my Embedded Linux Primer book and realized that I&#8217;d forgotten about passing ARCH=arm when calling make. So I went back to my cross compile environment, and navigated to the folder with the Makefile and the basic kernel module code, and ran <code>make ARCH=arm<\/code>. It built! In a flurry of excitement, I copied it to my BeagleBone and tried to insmod, only to be greeted with: <code>insmod: error inserting 'enable_usermode.ko': -1 Invalid module format<\/code><\/p>\n<p>Finally the tar.gz finished copying, so I extracted it to ~\/angstrom-build. As root, I symlinked this to a couple places:<\/p>\n<pre>ln -s \/home\/beaglebone\/angstrom-build \/usr\/src\/linux-3.2.28\r\nln -s \/usr\/src\/linux-3.2.28 \/lib\/modules\/3.2.28\/build<\/pre>\n<p>Then I gave a quick try to building my kernel module, knowing it was likely I&#8217;d need to make modules and scripts, but wanting to see what might happen. The attempt yielded this error:<br \/>\n<code>\/bin\/sh: scripts\/basic\/fixdep: cannot execute binary file<\/code><br \/>\nSo I went back to ~\/angstrom-build and ran<\/p>\n<pre>make modules\r\nmake scripts<\/pre>\n<p>This took a couple hours and make scripts didn&#8217;t seem to do anything. Once this was done, I was able to build the kernel module, however, trying to insert it gave the same issue as when I had tried to insert the cross compiled kernel module. So, I decided to check out what <code>dmesg<\/code> had to say:<br \/>\nenable_usermode: disagrees about version of symbol module_layout<br \/>\nUh oh. It seems that even though the numerical version of the kernel matches, something else within the pre-built kernel distributed on the BeagleBone doesn&#8217;t match what I&#8217;ve built.<\/p>\n<p>So I have two options; the long way being to try to setup the kernel I built on an SD card, or the shorter way, upgrading the kernel on my BeagleBone to see if maybe the kernel-dev package I installed previously can be used once the kernel is upgraded. I chose to try to upgrade the kernel using <code>opkg upgrade<\/code>. With this selection, I went ahead and did <code>make scripts<\/code> in \/usr\/src\/kernel before changing the Makefile to use <code>KDIR = \/usr\/src\/kernel<\/code>, and voila! This time the kernel module built and was successfully inserted!<\/p>\n<h1>Suggested course of action to compile a kernel module on BeagleBone<\/h1>\n<p>Note that I include directives to switch user (su) as you&#8217;ll need to be root in some cases. You may replace \/home\/user with ~, I typed it out because I noticed that the font made it look like a hyphen sometimes. The command <code>exit<\/code> will take you back to the previous user, or if you are in the original user who signed in, will disconnect you (so don&#8217;t use exit if you only have one user, root). Finally, <code>dmesg<\/code> will show the kernel prints, so you can look for the text from the example kernel module to be printed when you insert and remove the module.<\/p>\n<pre>opkg update\r\nopkg --tmp-dir \/home\/user upgrade\r\n*reboot if kernel upgraded using: shutdown -r now*\r\nopkg install kernel-headers\r\nopkg install kernel-dev\r\ncd \/usr\/src\/kernel\r\nsu\r\nmake scripts\r\nexit\r\ncd \/home\/user\r\nmkdir mykernelmod\r\ncd mykernelmod\r\n*create the below described c file*\r\n*create the below described Makefile*\r\nmake ARCH=arm\r\nsu\r\ninsmod mykernelmod.ko\r\ndmesg\r\nrmmod mykernelmod.ko\r\ndmesg\r\nexit<\/pre>\n<p>mykernelmod.c<\/p>\n<pre>#include &lt;linux\/module.h&gt;\r\n#include &lt;linux\/kernel.h&gt;\r\n\r\nstatic int __init enable_mod(void)\r\n{\r\n        printk(KERN_INFO \"My Kernel Module is enabled.\\n\");\r\n        return 0;\r\n}\r\n\r\nstatic void __exit disable_mod(void)\r\n{\r\n        printk(KERN_INFO \"My Kernel Module is disabled.\\n\");\r\n}\r\n\r\nmodule_init(enable_mod);\r\nmodule_exit(disable_mod);<\/pre>\n<p>Makefile<\/p>\n<pre>obj-m += mykernelmod.o\r\nKDIR = \/usr\/src\/kernel\r\nPWD := $(shell pwd)\r\n\r\nall:\r\n        make -C $(KDIR) M=$(PWD) modules\r\nclean:\r\n        make -C $(KDIR) M=$(PWD) clean<\/pre>\n<h2>Some useful links<\/h2>\n<ul>\n<li><a href=\"http:\/\/downloads.angstrom-distribution.org\/demo\/beaglebone\">http:\/\/downloads.angstrom-distribution.org\/demo\/beaglebone<\/a><\/li>\n<li><a href=\"http:\/\/www.angstrom-distribution.org\/building-angstrom\">http:\/\/www.angstrom-distribution.org\/building-angstrom<\/a><\/li>\n<li><a href=\"https:\/\/groups.google.com\/forum\/#!topic\/beagleboard\/dyuax5415dc\">https:\/\/groups.google.com\/forum\/#!topic\/beagleboard\/dyuax5415dc<\/a>\n<ul>\n<li><a href=\"https:\/\/beagleboard.googlegroups.com\/attach\/f65cb644e2b4cab8\/Kernel%20Module%20Documentation.txt?pli=1&amp;view=1&amp;part=7\">https:\/\/beagleboard.googlegroups.com\/attach\/f65cb644e2b4cab8\/Kernel%20Module%20Documentation.txt?pli=1&amp;view=1&amp;part=7<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"http:\/\/veter-project.blogspot.de\/2012\/03\/comfortable-kernel-workflow-on.html\">http:\/\/veter-project.blogspot.de\/2012\/03\/comfortable-kernel-workflow-on.html<\/a><\/li>\n<li><a href=\"https:\/\/groups.google.com\/forum\/?fromgroups=#!topic\/beagleboard\/BKnNkP3qzQs\">https:\/\/groups.google.com\/forum\/?fromgroups=#!topic\/beagleboard\/BKnNkP3qzQs<\/a><\/li>\n<li><a href=\"http:\/\/elinux.org\/EBC_Exercise_08_Installing_Development_Tools#Download_and_Compile_the_Kernel\">http:\/\/elinux.org\/EBC_Exercise_08_Installing_Development_Tools#Download_and_Compile_the_Kernel<\/a><\/li>\n<li><a href=\"http:\/\/www.cemetech.net\/forum\/viewtopic.php?t=7814\">http:\/\/www.cemetech.net\/forum\/viewtopic.php?t=7814<\/a><\/li>\n<li><a href=\"http:\/\/azkeller.com\/blog\/?p=129\">http:\/\/azkeller.com\/blog\/?p=129<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Preface This post was written as I attempted to create a kernel module for BeagleBone. The contents includes my troubleshooting efforts and a final resolution as to the method I found which worked, found at the end of the post. &hellip; <a href=\"http:\/\/elene.dahners.com\/blog\/2012\/10\/22\/compiling-a-kernel-module-for-beaglebone\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17,11,18],"tags":[33,41,34,32,35,31],"class_list":["post-107","post","type-post","status-publish","format-standard","hentry","category-beaglebone","category-programming","category-troubleshooting","tag-angstrom","tag-beaglebone","tag-kernel","tag-kernel-module","tag-module","tag-ubuntu"],"_links":{"self":[{"href":"http:\/\/elene.dahners.com\/blog\/wp-json\/wp\/v2\/posts\/107","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/elene.dahners.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/elene.dahners.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/elene.dahners.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/elene.dahners.com\/blog\/wp-json\/wp\/v2\/comments?post=107"}],"version-history":[{"count":61,"href":"http:\/\/elene.dahners.com\/blog\/wp-json\/wp\/v2\/posts\/107\/revisions"}],"predecessor-version":[{"id":178,"href":"http:\/\/elene.dahners.com\/blog\/wp-json\/wp\/v2\/posts\/107\/revisions\/178"}],"wp:attachment":[{"href":"http:\/\/elene.dahners.com\/blog\/wp-json\/wp\/v2\/media?parent=107"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/elene.dahners.com\/blog\/wp-json\/wp\/v2\/categories?post=107"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/elene.dahners.com\/blog\/wp-json\/wp\/v2\/tags?post=107"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}