Embedded Linux on a 2-Layer Board!
A blog about Clementine Core, a fork-ready two-layer Linux computer you can build yourself.
Join the DZone community and get the full member experience.Join For Free
One of my favorite parts about the Altium CircuitMaker cloud ecosystem is the ability to create a new project using an existing design as a starting point. This functionality — called “forking” — is useful when you’ve found a design in the CircuitMaker community that is similar to something you’d like to build. When you fork the design, Altium will automatically clone the project and all project documents to your own account. You can fork any public project in the CircuitMaker community.
While forking projects is useful when you need to make minor changes to existing designs (like swapping out a voltage regulator, or changing the shape of the PCB), I’ve been experimenting with building what I call “fork-ready” projects to enable better design reuse. While there’s no automated way of combining multiple projects together, I’ve noticed that a ton of projects I work on use common schematic and PCB design elements. By creating fork-ready base projects, the community can rapidly create new hardware with minimal effort.
Fork-ready designs should be built the same way a class is built in object-oriented programming; they should provide a single, specific function, while abstracting the details of implementation by using CircuitMaker’s multi-sheet design functionality (with ports and harnesses). Fork-ready designs should be clearly documented, and shouldn’t contain functionality that will likely change on a per-project basis (i.e., connectors, or LED indicators). If a project can be manufactured as-is, it’s probably not fork-ready.
When does it make sense to build fork-ready projects? When a particular function requires a substantial amount of schematic capture / PCB layout, and this capture/layout is invariant of the project specifics. These tend to be analog- and power-heavy designs, like class D audio amplifiers (which require a ton of large, expensive passive components that need to be carefully selected and laid out), RF transceivers (which require thoughtful PCB layout, and often have complicated passive networks), and AC/DC offline switching converters (which tend to have lots of passives, and require careful layout for safety and regulatory purposes). Once you’ve laid out one of these designs once, you can essentially copy-and-paste it into a new project with minimal (if any) changes.
While these analog-heavy designs are good examples of when the CircuitMaker community should make fork-ready projects, I think the best example is the single-board computer. These designs — consisting of an application processor, a power-management unit, RAM, and flash storage — can be extremely complex, both from a schematic and layout perspective. It’s not uncommon for a single-board computer to span a dozen schematic sheets and a dozen layers on a PCB (check out the i.MX6 Rex if you don’t believe me). While these designs are complicated, they’re also largely invariant between projects. Whether you’re building an Android tablet, a WiFi router, or an industrial touchscreen controller, 90% of the PCB will remain unchanged. A fork-ready single-board computer design would allow people in the CircuitMaker community to quickly develop custom hardware that has the full power of Linux, without having to reinvent the wheel, or spend hours deciphering existing designs, trying to figure out what can be removed and what has to stay.
Introducing Clementine Core
For my first shot at creating a fork-ready design, I created Clementine Core — a 454 MHz ARM single-board computer with 64 MB of RAM, designed to boot Linux from a MicroSD card. Clementine Core uses the circa-2009 Freescale i.MX233 application processor, which, while getting a bit crusty, is still widely-available for less than $10/each and is guaranteed to be in production until at least 2019. This processor was selected because of its high level of integration — nothing other than external RAM and flash storage is required for it to boot into a full Linux environment. The i.MX233 also is available in a TQFP package, which allows the design to be laid out on a two-layer PCB and hand-soldered.
While the base Clementine Core design doesn’t have any external connectors, the i.MX233 and the Linux BSP support driving TFT LCDs (I’ve tested up to 800x480 resolution 18-bit panels), USB host functionality (great for low-cost WiFi), and audio functionality (in addition to the built-in audio codec, the i.MX233 has a mic preamp and a headphone driver). The processor supports typical MCU faire as well, such as SPI, I2C, UART debugging, ADC, and a sole PWM channel. There are 33 GPIO pins available for use.
The i.MX233 has found its way into a number of open-source designs, including Bunnie Huang’sChumby design, Olimex’s OLinuXino ecosystem, and the LittleBits CloudBit — Clementine contains bits and pieces of all of these designs, as well as the official Freescale reference design for the platform.
Customizing Clementine Core
If you’ve forked Clementine Core and compiled the project (Project > Compile), you’ll notice there is a top-level sheet called Clementine Core, plus a Memory, MicroSD, Power, and System sub-sheets.
Clementine Core takes full advantage of CircuitMaker’s advanced multi-sheet design capabilities; ports are used on the System sheet to bring out project-specific connectivity to the top sheet, allowing the designer to focus her attention on the details necessary to complete the project, without having to deal with the visual clutter of sorting through pages of schematics. Most users of Clementine Core will only need to modify the System sheet; no other changes will usually be necessary.
I prefer to put project-specific circuitry on a separate sheet, then connect everything together in the top-level Clementine Core sheet. Here’s an example of top-level schematic of a project that illustrates this:
As simple as this is, this schematic describes, at a high level, a full touchscreen-based Linux system. As you can see, Clementine Core is extended by adding a USB connector (J2), a debug connector (P2), a system power input (P1), a Display sub-sheet (containing a TFT connector, touchscreen controller, and a regulator to power the backlight), and a BuckRegulator sub-sheet (containing a 12V to 5V buck regulator).
So, what’s the minimum amount of stuff you have to add to Clementine Core to actually build something useful? Surprisingly, not much!
Clementine Core uses the built-in PMU functionality of the i.MX233, so you’ll only need to provide a 5V power source, connected to the “5V” net. While the i.MX233 has a built-in DC/DC converter, I’ve found it to be extremely sensitive to input voltage levels — many cell phone chargers I’ve tried produce strange behavior from i.MX233-based designs. To make the design more robust, I’ve disabled the DC/DC converter, relying on the built-in linear regulator. This decreases the efficiency of the board, but it allows a wider input voltage margin and simplifies the PCB design.
For basic operation, no other regulators are needed. Clementine Core will provide a 1V2_SYS, a 2V5_SYS, and a 3V3_SYS rail, as well as some low-power, low-noise analog supplies. Feel free to draw up to 100 mA from the 3V3_SYS rail for your own sensors/peripherals. However, if you want to drive a ton of LEDs, a TFT display, or any other high-current 3.3V devices, plan on adding your own 3.3V regulator to an isolated 3.3V net (do not wire it in parallel with the 3V3_SYS supply!).
The i.MX233 has built-in LiPo charging capabilities as well as soft power switching. You’ll have to modify the design slightly to activate this functionality — consult the Olimex OLinuXino i.MX233 schematics for an example. None of these customizations will require any software modification.
Note that all user-accessible I/O pins are wired for 3.3V operation. These pins are not 5V tolerant. First off, you should always break out the TTL serial debug connection to either 0.1” pin headers or the FTDI 3.5mm jack. This will allow you to interact with UBoot, see the Linux kernel messages, and interact with the console shell. If you don’t have room for connectors, try to at least lay down some test pads.
Almost all i.MX233-based designs end up with a USB connection used for WiFi or Ethernet networking, Bluetooth connectivity, or human input devices like keyboards or mice. Depending on your application, you may need additional USB ports, which can be easily integrated on-board with a USB hub IC, or off-board with an off-the-shelf USB hub.
Both the debug console and USB port are already broken out on the main sheet, ready for use. Other low-speed peripherals such as I2C, UART and SPI are available on several different pin multiplexings; consult the i.MX233 reference manual for a full list of available pin muxing options for these peripherals. Note that you’ll need to modify the Linux DTS file for the board if you want to activate any of these peripherals (the DTS configuration file is responsible for loading the peripheral’s driver, as well as configuring the driver and muxing the pins).
Clementine Core can directly drive a parallel TFT LCD with up to 18-bit color depth. Compared to DSI TFTs and displays with built-in controllers, parallel TFTs tend to be extremely low-cost (East Rising’s 480 x 272 resolution 4.3 inch display is only $10 in single quantities, and their 800x480 resolution 5 inch display is only $15). To get the display working in software, you’ll need to modify the DTS file for the board to mux the appropriate pins and configure/activate the LCD controller.
Pour a ground plane on the top and bottom layers of the board. Since CircuitMaker doesn’t have Altium Designer’s transparent layers functionality yet, I pour a hatched ground plane so I can see what’s going on under the pour. While the DDR routing is a bit out-of-spec, the design has been stress-tested and functions properly. Avoid altering the DDR or power distribution layouts unless you’re comfortable with high-speed design. Feel free to move the MicroSD connector (or swap the footprint) and re-route — but avoid extremely long traces, and keep a continuous ground plane under the traces at all times.
There are lots of different ways of getting Linux onto Clementine Core, and the method you choose largely depends on whether you need to customize the BSP at all, and how polished you want things to be.
If you want to quickly get started, Olimex has a Wiki page with pre-built MicroSD card image download links, and lots of information about getting Linux running. All of this is directly applicable to the Clementine Core (which is more or less an imx233-olinuxino-micro). Also, many posts on their forums explain things like kernel patching, bugfixes, and SD card image woes.
You can load a distro on an MicroSD card and use it just like a normal computer (albeit one with very little RAM and a slow, single-core processor), but if you’re designing a custom Linux board, you’ll probably have lots of goodies on-board that will interact with your system using I2C, SPI, or the LCD controller. To get these modules activated and configured, you’ll need to be able to compile a custom kernel (with a custom DTS configuration file). For most people new to embedded Linux, it’s not the actual code that’s overwhelming, but rather, setting up the environment. That’s totally outside the scope of this post, but I would recommend looking at either Yocto or Buildroot.
Both projects are used to build images you can boot from. Essentially, the build system will download and compile a toolchain, and then use that toolchain to cross-compile U-Boot, a Linux kernel, plus all the core software necessary to boot into Linux. These systems will also build other user applications and libraries you may want installed (like Firefox, or QT-Embedded, or XTerm). They will create the configuration files as well as the directory structure, initialization scripts, and everything else. Finally, they will create a virtual SD card image you can write to your MicroSD card.
Buildroot is a Makefile / menuconfig-based build system that’s quite simple to learn and understand. I think it’s slightly easier to iteratively develop code “in place” without futzing around with patches and custom build scripts than Yocto, but it’s not a very large project, and I think it’s mostly used by hobbyists and small firms.
However, if you want to build images the way the pros do, you’ll want to use Yocto. Yocto is a massive git/repo-based build system that uses inheritable Python configuration scripts parsed by the bitbake utility. It’s beautiful and ugly and wonderful and frustrating all at the same time. I wouldn’t recommend doing in-place iterative development with Yocto (in other words, building an image, then trying to edit the source code in the build system and rebuilding the image); it’s just too painful.
Instead, use Yocto to build a base image, then build a toolchain, install the toolchain, and copy the Linux source code into your own private area. Break things, experiment, make changes, and when you get your DTS file working and any other source code changes made, create a diff between your code and Yocto directory you copied it from, and wrap that patch into a recipe. Once you’ve done that, you’ll never have to touch the source code again, and you can focus on your userspace applications.
Freescale has a set of Yocto Training posts that will walk you through this process. Christian Jann’s blog provides useful instructions that are i.MX233-specific. Keep in mind that all of these posts were written several years ago; some things might be out of date. Always consult the latest documentation, and “fill in the blanks” with the Freescale-specific and i.MX233-specific stuff.
If you plan on building up a board based around Clementine Core, I would highly recommend you buy a few Olimex i.MX233 boards that you can use as reference platforms. Olimex is a great, open-source-centric company that spends a lot of effort on documenting things, so even if the boards weren’t extremely valuable for debugging purposes (which they are), I’d encourage you to support them anyway.
In the era of widely-available, off-the-shelf low-cost single-board Linux computers, why hassle with building your own (technologically inferior) single-board Linux computer? For the same price (or cheaper), you could buy a Raspberry Pi, BeagleBone Black, or one of the many other boards out there to accomplish many of the same goals.
For students and hobbyists interested in moving to the next level, forking Clementine Core and getting familiar with the hardware will serve as a stepping stone to real-world commercial work. I laid out my first Linux single-board computer based around the i.MX233 several years ago, and it helped me learn the ropes without getting completely overwhelmed. The design is low-cost enough that a couple goofy revisions sets you back $80 instead of $8000. Since then, I’ve done a lot of freelance work involving SoCs from Freescale, AllWinner, and Texas Instruments; they’re all very similar under the hood, and the skills I picked up working on the i.MX233-based projects has definitely helped me in my work.
Outside of education, the main reason you would fork Clemetine Core instead of dropping a Raspberry Pi into your project is because you want control. Control over size, control over power consumption, control over manufacturing, control over features, and control over cost. Many of these are traditionally thought of as commercial engineering concerns that hobbyists don’t bother with, but as the maker movement continues to grow, hobbyists are getting more and more advanced, and the line is starting to blur between product engineering and hobbyist geeking.
A great example is my Linux Wall Controller project. The idea is simple: I want to have touch screen controllers in the walls of my house to let me control music, get updates, and do other geeky things I haven’t even thought of yet. I want them running Linux, so I can develop the touchscreen software in a nice, high-level framework, like Qt Embedded. And I want these touchscreen controllers to fit in standard U.S. outlet boxes.
Without Clementine Core, this would be a fairly complex project for a hobbyist to build from scratch; I’d probably turn to an off-the-shelf single-board computer and then quickly realize that there’s no way to stuff it into a standard outlet box. I would be stuck buying an expensive system-on-module (SOM) designed for industrial applications, and designing a custom board that the SOM could snap into.
With Clementine Core already finished, I was able to fork it to the wall controller project, toss in a 12V to 5V buck converter, a I2C touchscreen controller, an LCD connector, and a 3.3V regulator to power it. The project was finished in just a couple of hours of work, and I’m in the process of ordering boards right now (fingers crossed!). Because of the low design complexity of the board, it will end up being cheaper than buying a Raspberry Pi / LCD combo. When was the last time that building a custom PCB assembly was cheaper than buying a mass-produced off-the-shelf product?
Speaking of board cost, that’s one of the main strengths of Clementine Core. While there are many other open-source single-board computer projects, most of these designs aren’t useful to electronics hobbyists, students, and makers since they’re built on 6-, 8-, or even 10-layer stack-ups, and use fine-pitch BGA components. At the end of the day, these designs can cost thousands of dollars to prototype and assemble. That’s fine as an R&D expenditure for my large-volume commercial work, but that’s simply out of the question for a Sunday afternoon hobbyist project.
Clementine Core is the only single-board computer I know of that can be produced on a two-layer “standard-spec” process targeting the low-cost Chinese PCB manufacturing houses. Being only 34 by 43 mm in size, Clementine Core fits comfortably on a typical 5x5 two-layer PCB, making the per-unit PCB cost about $1 even in low quantities.
BOM costs for the Clementine Core base design are in the range of $15-$25 depending on where you’re buying your parts.
In terms of assembly complexity, Clementine Core only has 9 BOM lines (for the sake of comparison, the 8-bit 16 MHz Arduino Uno has 23 BOM lines by my count). Since the base design has no QFNs or BGAs, the boards can be easily hand-soldered (though some beginners will struggle with the 0402 passives).
While this is great for DIY electronics enthusiasts, these qualities also make the design extremely low-cost to get assembled professionally. CircuitHub will build up a Clementine Core for about $40/each in quantities of 10, and $16/each if you do a low-volume production run of 1000 units. If you’re familiar with low-volume PCB assembly costs, you’ll recognize how remarkably inexpensive that is.
As CircuitMaker matures during its beta phase, it’s really exciting to see the designs the community is putting together. Altium’s cloud-centric functionality is useful for traditional collaboration methods, but I think the platform will also provide new ways for us to share our design content that will fundamentally change how electronics are made. This is an exciting time to be a part of the CircuitMaker community, and I would love to see other users start working on fork-ready projects that are built from the ground up to serve as a basis for designs. I imagine a not-too-distant future where designers starting a new project can “go shopping” for ready-to-go motor drivers, analog circuitry, power supplies, and advanced single-board computers.
I encourage you to fork a copy of Clementine Core next time you reach for your Raspberry Pi, and hopefully we can start a tradition in the CircuitMaker community of building excellent content for everyone to enjoy!
Published at DZone with permission of Jay Carlson, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.