{"id":24,"date":"2021-11-22T01:08:58","date_gmt":"2021-11-22T01:08:58","guid":{"rendered":"https:\/\/petecudmore.com\/?p=24"},"modified":"2021-11-22T01:11:03","modified_gmt":"2021-11-22T01:11:03","slug":"beaglebone-black-baremetal","status":"publish","type":"post","link":"https:\/\/petecudmore.com\/?p=24","title":{"rendered":"Beaglebone Black Baremetal"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">The Beaglebone Black and Baremetal programming. <\/h2>\n\n\n\n<p>The <a href=\"https:\/\/beagleboard.org\/black\">BeagleBone Black<\/a> (BBB) is a system-on-a-module (SoM) based on the TI AM335x CPU series. It&#8217;s relatively cheap, extendable via &#8216;capes&#8217; (expansion boards) and has some interesting features such a programmable real-time co-processor units (PRU). I bought this board to mess around with real-time operating systems (RTOS) and bare-metal programming. Maybe not the ideal stating platform, but there is plenty of room to grow. <\/p>\n\n\n\n<p>Even to someone comfortable programming in C, the embedded space seems somewhat impenetrable and seems like a combination of antiquated tooling and black magic. My aim here is to fix some of that &#8211; which will require some experimentation, exploration and iteration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Host machine setup.<\/h2>\n\n\n\n<p>I&#8217;ll be using Ubuntu 20.04 as my development environment, not by choice &#8211; I would have preferred to use windows subsystem for Linux (WSL) as I&#8217;m running on a PC but WSL doesn&#8217;t handle USB very well, and I&#8217;ll be needing that to talk to the BeagleBone.<\/p>\n\n\n\n<p>Some things we need:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>A BeagleBone black.<\/li><li>A USB to TTL serial converter cable (I bought <a href=\"https:\/\/www.amazon.com.au\/gp\/product\/B08763GK1Q\/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&amp;psc=1\">this one<\/a>, and it seems to work just fine).<\/li><li>A microSD card (and some way to flash it)<\/li><li>GNU cross-compiler toolchain (apt package <code>gcc-arm-none-eabi<\/code>) and newlib<\/li><li>GNU make and associated build tools. <\/li><li>TI Starterware with the BeagleBone Black patch. (https:\/\/www.ti.com\/tool\/STARTERWARE-SITARA)<\/li><\/ul>\n\n\n\n<p>I&#8217;ll also be using <code>git<\/code> for source control, but you could just as well use <code>svn<\/code>. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Issue The First: Installing TI Starterware.<\/h2>\n\n\n\n<p>My first step was to ensure that I could build and deploy the TI examples onto the device. Not surprisingly, I ran into issues almost immediately. Firstly, TI Startware package is distributed as a 32-bit ELF binary, which means it wont run out of the box on a modern Linux distribution. I found this out via a bit of digging on stack-overflow, which pointed me at the Linux application <code>file<\/code> &#8211; which spits out information about the file type, surprisingly enough. Further digging on stack-overflow suggested that i needed to run the following to enable the execution of 32-bit binaries;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo dpkg --add-architecture i386\nsudo apt-get update\nsudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386(<\/code><\/pre>\n\n\n\n<p>(As an aside, one of my frustrations with Linux &#8211; and technology in general &#8211; is how much working out how to use the software feels like memorizing incantations. More on this another time&#8230;) <\/p>\n\n\n\n<p>The i386 issues is a feature of just how old the library is. TI have since replaced this with a new processor SDK which we may end up exploring later. However, the new SDK is tied to TI&#8217;s CodeComposer Studio &#8211; an Eclipse variant IDE for the TI chips. Personally, I wish TI was a bit more tooling agnostic, and spent more time and resources on documentation instead of &#8216;helping&#8217; via an IDE. I get the impression that this is standard practice in the embedded world, so I guess there are reasons for it?<\/p>\n\n\n\n<p>TI provides a patch for the BeagleBone Black, which can simply be extracted into the directory where the Starterware package was installed.<\/p>\n\n\n\n<p>Because I like to make things difficult for myself, I elected to install the latest version of the arm GCC cross compiler toolchain (x86_64 to arm-none-eabi) directly from the <a href=\"https:\/\/developer.arm.com\/tools-and-software\/open-source-software\/developer-tools\/gnu-toolchain\/gnu-a\/downloads\">arm developer website<\/a> and installed newlib (<code>libnewlib-arm-none-eabi<\/code>) via apt.<\/p>\n\n\n\n<p>At this point, we&#8217;re ready to try building the demo applications.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Issue The Second: Building TI Demo Applications.<\/h2>\n\n\n\n<p>Navigating the Startware SDK was pretty confusing at first, and the documentation was not much help. Eventually, I found the entry point to the build process in <code>build\/armv7a\/gcc\/am335x\/beaglebone\/makefile<\/code>. Unsurprisingly, it did not &#8216;just work&#8217; and so begins the task of debugging the build process.<\/p>\n\n\n\n<p> The first thing was an easy fix; the version of cross-compile toolchain needs to be correctly specified. To work out where this is set, we notice that the entry point makefile simply calls make in each of the specified sub-directories. Each makefile in a particular sub-directory then includes <code>build\/armv7a\/gcc\/makedefs<\/code> which is where we want to look. There, on the first non-comment line, we find the toolchain definition. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>build\/armv7a\/gcc\/makedefs - line 42<\/code>\n# LIB_GCC=${LIB_PATH}\/lib\/gcc\/arm-none-eabi\/4.7.2\/   &lt;- Old toolchain.\nLIB_GCC=${LIB_PATH}\/lib\/gcc\/arm-none-eabi\/10.3.1\/\nLIB_C=${LIB_PATH}\/arm-none-eabi\/lib\/<\/code><\/pre>\n\n\n\n<p>The other thing to note is that the environment variable <code>LIB_PATH<\/code> needs to be set so as to point to our cross compile toochain. Since I&#8217;ve install this into <code>\/opt<\/code>, I&#8217;m <code>export<\/code>ing <code>LIB_PATH=\/opt\/gcc-arm-10.3-2021.07-x86_64-arm-none-eabi<\/code> in <code>.bashrc<\/code>.<\/p>\n\n\n\n<p>Now, we should be able to compile some of the applications. Running make in the beaglebone directory does build some applications, but our console is being inundated with warnings about <code>-march<\/code> and <code>-mcpu<\/code> being incompatible. With a bit of digging, it seems that this is a change in modern GCC (vs the old 4.7 version the SDK shipped with), and that specifying the architecture is redundant. To fix this, simply delete the flag <code>-march=armv7a<\/code> from the <code>CFLAGS<\/code> on line 167 of <code>build\/armv7a\/gcc\/makedefs<\/code>.<\/p>\n\n\n\n<p>The final issue I encountered was a redefinition of <code>strnstr<\/code> in the demo application. My hypothesis is that the version of GCC\/newlib that this SDK was built against didn&#8217;t have <code>strnstr<\/code> implemented, which is required for the lightweight IP (LWIP) stack that the demo application uses. A bit of <code>grep<\/code>-ing discovered that LWIP provides a compiler define for this exact situation, meaning that the fix was an easy on &#8211; just add <code>DLWIP_HTTPD_STRNSTR_PRIVATE=0<\/code> to the <code>LWIPCFLAGS<\/code> make variable in the demo application makefile (line 91 of <code>build\/armv7a\/gcc\/am335x\/beaglebone\/demo\/makefile<\/code>).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Issue The Third: Booting the Beaglebone from an SD Card.<\/h2>\n\n\n\n<p>The Starterware documentation says that any &#8216;FAT&#8217; filesystem is sufficient for boot loader, and that one simply needs to rename the build artifacts with TI headers (<code>boot_ti.bin<\/code>, <code>demo_ti.bin<\/code>) to <code>MLO<\/code> and <code>app<\/code> respectively, for the bootloader to pick it up. Again, not so simple. The general approach here is as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Format the microSD to some FAT filesystem (W95 FAT32 LBA seems to work just fine.) <\/li><li>Copy across the <code>MLO<\/code> and <code>app<\/code> binaries.<\/li><li>Plug in the USB-TTL cable and point your serial application (<code>minicom<\/code> for me) at the corresponding tty port (<code>\/dev\/ttyUSB0<\/code> for me).<\/li><li>Insert the microSD card, and power cycle the beaglebone, holding the S2 switch (near the SD slot) on boot.<\/li><\/ul>\n\n\n\n<p>If this works, you should see a bunch of activity on the COM port. <\/p>\n\n\n\n<p>I encountered two fail-states. Firstly, if the card is not flashed correctly, you may receive &#8216;<code>CCC<\/code>&#8216; from the serial port. I couldn&#8217;t find out what that means, but I&#8217;m sure it&#8217;s not great. It was mostly likely an issue with the filesystem, or the onboard bootloader couldn&#8217;t find the <code>MLO<\/code> binary. <\/p>\n\n\n\n<p>In the second fail state, the COM port registered that the bootloader had started as &#8216;<code>StarterWare AM335x Boot Loader'<\/code> was sent down the COM port, but it failed to move onto the next stage. A bit of <code>printf<\/code> debugging isolated that the bootloader was getting stuck calling <code>f_open<\/code>. I have no idea why, but it does seem that this bug is not present in debug builds. I don&#8217;t have a JTAG emulator (which I think is what&#8217;s needed to debug this sort of thing) so I can&#8217;t really get too much insight into what&#8217;s going on. I guess it&#8217;s not too much of a concern for me though, since I&#8217;ll probably not be using the Starterware bootloader for too long. If worst comes to worst, the BeagleBone Black patch provided by TI comes with a pre-built bootloader, so I could always just use that, or (more likely) piggyback onto Uboot.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Next Steps<\/h2>\n\n\n\n<p>With the TI Starterware working, the next steps will be some tooling and planning. In particular:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Constantly copying across binaries to an microSD card is pretty inefficient. The existing bootloader (uboot) allows for booting over the network. Can we use that to make development easier.<\/li><li>The TI way of building doesn&#8217;t suit my tastes and the source is all over the place. Can we factor the &#8216;BeagleBone Black&#8217;-specific parts of the SDK (and bin the rest) into a something more suitable for what I want to explore.<\/li><li>What needs to happen to get the video working? Either via HDMI or LCD.<\/li><\/ul>\n\n\n\n<p>Til next time. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Beaglebone Black and Baremetal programming. The BeagleBone Black (BBB) is a system-on-a-module (SoM) based on the TI AM335x CPU series. It&#8217;s relatively cheap, extendable via &#8216;capes&#8217; (expansion boards) and has some interesting features such a programmable real-time co-processor units (PRU). I bought this board to mess around with real-time operating systems (RTOS) and bare-metal [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[8,4],"tags":[],"class_list":["post-24","post","type-post","status-publish","format-standard","hentry","category-beaglebone","category-programming"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/petecudmore.com\/index.php?rest_route=\/wp\/v2\/posts\/24","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/petecudmore.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/petecudmore.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/petecudmore.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/petecudmore.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=24"}],"version-history":[{"count":4,"href":"https:\/\/petecudmore.com\/index.php?rest_route=\/wp\/v2\/posts\/24\/revisions"}],"predecessor-version":[{"id":28,"href":"https:\/\/petecudmore.com\/index.php?rest_route=\/wp\/v2\/posts\/24\/revisions\/28"}],"wp:attachment":[{"href":"https:\/\/petecudmore.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=24"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/petecudmore.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=24"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/petecudmore.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=24"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}