Bringing to life a Custom-developed Linux Board

Written by Martin Tramšak on May 7, 2016

We helped an R&D company booting a freshly developed custom Linux board.

Who doesn't love beagles?

As part of our R&D services we provide, we were contacted by Strip's, an R&D company developing a product based on the Beaglebone black. Beaglebone black is a popular development board used mostly for education purposes and small-quantity products.

It features a Texas instruments AM335x single core application ARM processor with frequency up to 1 GHz. It is also packed with peripherals and has a special peripheral interconnect principle that enables the developer to route the peripherals to different physical pins based on specific board requirements.

Strip's contacted us because they developed their own board featuring the same AM335x processor and the same amount of RAM yet the rest of the board was custom-routed to enable specific use in industrial environment. Instead of the Beaglebone black MMC, they opted for cheaper NAND flash storage. For their application, they needed two USB ports, two ethernet ports, one SPI, two I2Cs, Modbus support with RS485 interface, and a single CAN interface. CAN and RS485 interfaces were also optically isolated to meet industrial standards.

Do your really know Linux?

Linux is a well-known operating system which originally targeted personal computers. Due to its modular design it can be configured to run in constrained environments such as embedded boards. To be able to boot to Linux, certain steps first need to be taken in order to prepare the hardware for kernel boot. These steps are different not only to each architecture but also to each particular microprocessor.

The procedure described below is the final boot procedure we came up with. Namely, after the board is delivered from the fabrication facility, the NAND flash storage is of course empty and the U-Boot and Linux kernel binaries have to be programmed into it as follows:

  • first, we load the first-stage bootloader from NAND to the internal 128kB of SRAM;
  • the first-stage bootloader initializes DRAM and uses it to store the second-stage bootloader named U-Boot;
  • U-Boot reads the Linux kernel and device tree binaries from NAND, and loads both of them into DRAM;
  • after being loaded into DRAM, the second-stage bootaloder loads the kernel with specific command-line arguments which let the kernel know where the userspace partition is located (i.e. NAND) and where to output the console to.

Linux Development Environment

The major part of the development process for this kind of application is setting up the correct development environment. In order to develop for Linux, a PC with Linux is preferred if not mandatory. Since reprogramming the NAND takes time and multiple minor changes need to be made during development, the board bringup is usually done from Ethernet.

The filesystem and Linux kernel are both loaded from Ethernet via NFS and TFTP protocols. This assumes that the U-Boot is already working and is present in the NAND. For this step, our processor also has an internal bootloader that can load the first-stage bootloader from Ethernet via BOOTP and TFTP, and then the first-stage bootloader can load U-Boot from TFTP. This was the route we took, with these exact steps:

  • compile both the first-stage bootloader and the U-Boot to be loaded from the Ethernet interface;
  • run the RAM tests to ensure that the board is properly routed and without any possible issues;
  • fine tune the RAM, if necessary;
  • create the required patches to initialize and use the NAND flash IC that was used (this involves setting the timing parameters for the GPMC interface);
  • compile the Linux kernel with NFS support and prepare the device tree with support for our specific hardware (the device tree also contains information about pin multiplexing and additional hardware support);
  • program the kernel and device tree to NAND from U-Boot, and set U-Boot to load the kernel from NAND;
  • after we have a working Linux kernel and userspace, we can test the interfaces to make sure there are no onboard issues;
  • finally, flash the UBIFS partition to NAND and modify Linux kernel boot parameters to use the UBIFS NAND filesystem as the primary userspace partition.

He's alive, Jim!

The final task is automating the process described above for every board that comes from the production line. This is also the most critical part of the bringup since every minute on the production line represents a certain expense. Furthermore, it is essential that all the interfaces are properly tested to make sure that manufacturing errors are noticed and corrected.

This is also the step most companies have problems with. Besides programming the NAND flash, each board should be given a unique serial number (for internal tracking and for customer management) as well as unique MAC addresses for each of the Ethernet ports. This means that custom software needs to be developed for registering each board in the system and generating the appropriate numbers automatically.

At MULTILUX, we are glad that we were given the opportunity to participate in this project, which allowed us to showcase our deep Linux knowledge and to contribute to this very promising project.

Does your project require a full-stack engineering team?

Drop us a line and we will be more than happy to work on an exciting new project with you.

  Back to Projects