Tutorial/strategy: layout a 2-layer PCB in KiCad EDA

This gives a high level overview or strategy for laying out a simple PCB in KiCad or other EDA tool.  This is for beginners.  It doesn’t give details, exactly how to use the user interface.  This is not polished.  It tries to teach something which is obvious only to experienced users, that might save beginners some learning time.

This is for a ‘simple’ design where:

  • most of the components are surface mount (SMD) on the front
  • the board is a 2-layer board (copper on the front and back, and not in a middle layer.  Such a board is the cheapest to buy, design, and assemble.)
  • there are few components, and few busses (bundles of signal lines routed together.)

The strategy is:

  • read the netlist
  • auto spread or place your components
  • add a board outline larger than you think the board will take
  • move and rotate the components into the board outline, to minimize crossing of rats nest lines
  • add a front zone for the ground net
  • add a zone on the back for the power net
  • run the DRC tool

Now many of the rats nest lines will be gone, since the ground and power nets are usually the largest nets, and the DRC tool will connect the front and back zones to many of the pads on those nets.  Most of the remaining rats nest lines are for “signal” nets.

Now add tracks and vias to any power pads (that are not through holes) to the power plane (zone) on the back.

Now iterate:

  • move and rotate components to reduce crossing of rats nest lines and to shrink the board area
  • run the DRC tool

When you have in some sense done all you can do to minimize crossing rats nest lines:

  • switch to the OpenGL view (push-and-shove only works in that view)
  • choose “Do not show filled areas in zones” (fill obscures tracks)
  • manually route the remaining rats nest lines, using push-and-shove instead of clicking at many places along the track’s route to make it go exactly where you want it.

If you need to move some components to get room for a signal track, use Grab instead of Move, since that will keep the tracks you have already connected to the component.

Now you might tweak by moving components and nodes of tracks, running the DRC often to check you haven’t violated design rules.  Generally you might tweak to reduce the size of the board, but it is better if you did that before you did manual routing.

Finally:

  • redraw your board outline
  • run DRC again and insure your zones are still contiguous, connected planes (if you reduce the outline too much, it might island your ground and power planes.  Generally a ring of copper around the board edge connects islands of the zone together.  The ground and power planes can have some enclosed island, but one point of a ground plane is to let the signals go where they want in short paths.)

 

 

Advertisements

0xFFFFFFFE, reclaim_reent() error symptoms of embedded programming

This is a report of one cryptic symptom (and possible) fixes you might encounter when you are embedded programming.  I report it because I have experienced it more than once and always forget what it means.

When you are trying to flash your embedded mcu,  the debugger seems to download to the chip, the debugger starts  and then stops showing a stack trace something like this:

0xFFFFFFFE
reclaim_reent()

Usually you expect the debugger to stop at main() and wait for you to tell the debugger to run (but that depends on whether you have configured your IDE and debugger to breakpoint at main.)

It might mean (not a program bug, a process error):

  • your linker script <foo>.ld describes the memory of your chip incorrectly
  • you haven’t erased the chip’s ROM yet

About the latter.  I am not sure, but modules you buy might already be flashed with a program such as a DFU bootloader, and are configured to protect a debugger from overwriting that code in ROM.  For example, on the Nordic NRF51, to remove the protection and erase all of ROM so that you can then use the debugger:

 nrfjprog --recover --family NRF51

 

 

Vagga Rust embedded

TL;DR

Work in progress: so far, a vagga container of Rust tools.  Eventually in the container, tools for embedded Rust (Xargo) and my own source project under version control.

A similar endeavour is Japaric’s “cross”.   The differences:

  • that uses a Docker container, here I use Vagga container
  • that might be ready to use, this is an explanatory exploration

A repository of source for this blog.

About

This is:

  • a log of my experience
  • well linked
  • for audience: developers/programmers.

Background

I have been programming embedded computers in C++.   I hate C++.  I have also used Python and Swift.  I read some background material:

So here I try to install Rust.  Ultimately I want to program in Rust an embedded ARM mcu on a NRF52 radio chip using the NRF52DK dev board.

Meta

Typically a developer knows/remembers how to set up a development machine (how to install the OS, development packages, an IDE, etc.)  Typically, you use the GUI, maybe write a shell script, take good notes, iterate when you discover packages missing.

Vagga helps you capture the entire process of setting up a development machine.  You capture the process in a vagga configuration file.  Which is a text configuration file or script; no GUI.

This blog itself is an annotated record of writing and debugging such a vagga configuration file.

Strategy

The Rust project moves fast.  I don’t want to struggle with keeping up to date.  I am not sure I will keep it.  So I will install Rust in a container.  A container is like a virtual machine, but lighter weight, and only on Linux.

Vagga github repository

Vagga implements containers.  Vagga is targeted for developers i.e. specialized to contain development environments. It seems like a natural fit.

Advantages of containers/virtual machines:

  • throwaway , non-invasive:  Can’t destroy your computer’s installation of non-development packages, your personal applications such as Gimp, LibreOffice )
  • distributable: you can give a container to other developers

Advantages of vagga:

  • is platform (Linux distribution) agnostic.  Vagga scripts might be portable to other developer’s machines (Linux-like.)
  • is a high-level package manager
  • userspace (doesn’t require root privileges)

Vagga is written in Rust.  (I hoped Vagga might even install Rust for me  but no, although written in Rust, I install a binary Vagga, which means I need to install Rust separately, but in a container.)  In this case, using Vagga is a form of “eating your own dog food”: if you are going to learn Rust, you might as well use tools that are written in Rust.

More meta

Vagga is a high-level package manager.  (discusses goals and future.)

Rustup is also a package manager (toolchain manager) exclusively for Rust.

Xargo is also a toolchain manager, exclusively for cross-compiling Rust language programs.

So it seems strange that to combat the proliferation of package managers, we invent yet another higher-level package manager.   And here we use a chain/graph of package managers:  vagga, rustup, cargo, xargo, your favorite Linux distribution’s package manager.

A high-level package manager makes more sense if you are targeting your app to many Linux distributions.  Here, I am only targeting (ultimately) one embedded architecture.  But by using a high-level package manager, I can distribute my development environment.  And I can easily replicate my home dev machine in other remote physical locations.

Installing Vagga

Vagga instructions for installation.

Per the above, on Ubuntu, just paste this into a terminal:

echo 'deb [arch=amd64 trusted=yes] https://ubuntu.zerogw.com vagga main' | sudo tee /etc/apt/sources.list.d/vagga.list
sudo apt-get update
sudo apt-get install vagga

(That adds a repository for vagga, and installs vagga from it.)

Putting an OS in my container

Vagga docs on configuration

Vagga is configured from a text file, vagga.yaml.

I created this simple directory tree:

rustdev/
    vagga.yaml

With the contents of vagga.yaml:

containers:
  rustdev:
    setup:
    - !Ubuntu yakkety
    
commands:
  test: !Command
    description: Test 
    container: rustdev
    run: [ps]
 

In other words, a container named “rustdev” and a command “test”.

Testing Vagga

At at terminal, change directory to “rustdev” and enter “vagga test”.  I got (unexpected):

(1/1) Installing alpine-keys (1.3-r0)
OK: 0 MiB in 1 packages
fetch http://repos.mia.lax-noc.com/alpine/v3.5/main/x86_64/APKINDEX.tar.gz
ERROR: http://repos.mia.lax-noc.com/alpine/v3.5/main: No such file or directory

Which seems like a problem with online repositories.  I entered “sudo apt-get update”, and tried again.  This time vagga seemed to install an OS in the container (in about a minute) and run the command, yielding:

PID TTY TIME CMD
 1 ? 00:00:00 exe
 2 ? 00:00:00 ps

IOW, there are only a few processes running in the container.

Emphasizing:  in my experience I had to do this to get it to work:

cd rustDev
vagga test    (fails to get alpine-keys)
sudo apt-get update
vagga test

Installing Rust compiler in the container

From my reading, I know the rust compiler command is “rustc”.  Entering that at a command line, expect:

The program 'rustc' is currently not installed. You can install it by typing:
sudo apt install rustc

So I know that ubuntu has a package.  I don’t want it installed directly, but in the vagga container.

Make this change in vagga.yaml:

    - !Ubuntu yakkety
    - !Install [rustc]

IOW, tell vagga you want to install the package named “rustc” in the container.

Now  “vagga test” first checks the container configuration for updates and yields:

Generating locales (this might take a while)...
 en_US.UTF-8... done
Generation complete.
Reading package lists... Done
E: Method mirror has died unexpectedly!
E: Sub-process mirror received a segmentation fault.
WARN:vagga::builder::commands::ubuntu: The `apt-get update` failed. You have no mirror setup, and default one is not always perfect.
Add the following to your ~/.vagga.yaml:
 ubuntu-mirror: http://CC.archive.ubuntu.com/ubuntu
Where CC is a two-letter country code where you currently are.

So I created a file named “.vagga.yaml” in my home directory (this is a hidden “settings” file.  Do not change your yagga configuration file i.e. ~/rustdev/vagga.yaml) with the contents

ubuntu-mirror: http://us.archive.ubuntu.com/ubuntu

Now, “vagga test” yields:

...
E: Failed to fetch http://security....
...
E: Some index files failed to download. They have been ignored, or old ones used instead.
WARN:vagga::builder::commands::ubuntu: The `apt-get update` failed. If this happens too often, consider changing the `ubuntu-mirror` in settings

So I followed this thread to find the “best” mirror, and changed the mirror, but it still fails.

So now I rethink: I really want embedded Rust, which suggests the nightly build of Rust, not the outdated package that Ubuntu provides.  I don’t want to install packaged Rust, I want to install rustup….

Installing rustup

Rust install instructions.

Rust is usually installed by the “rustup” tool.  New goal: install rustup in the container.  It seems like Ubuntu does not package rustup separately.  So edit vagga.yaml to add the instructions given by Rust.org for installing rustup, wrapped in a shell inside vagga.   Neively:

    - !Ubuntu yakkety
    - !Sh "curl https://sh.rustup.rs -sSf | sh"

But those instructions download a shell script and pipe it to a shell and the shell script is interactive.  So I hacked some more.  Summarizing the struggle:

  • curl was absent from the container
  • the curl package would not install because of mirrors outdated
  • I switched OS version to Xenial (Ubuntu 16.04LTS) hoping the mirrors were more stable
  • I switched to wget instead of curl
  • the rustup shell script requires curl

Now I read vagga examples.  From github:vagga-examples/python  I found:

  • Most developers install an omnibus package “build-essential” that includes all the commands a developer typically uses.  IOW,  a bare OS unsuited is for developers.
  • vagga has its own construct for downloading files

And the yagga configuration file for yagga itself builds a Rust development environment (since vagga is written in Rust.)

Using those examples, I ended up with the script which you can find in my git repository.  I don’t include the script here, it may suffer revisions.

If you enter “vagga test” expect:

/work/.home/.cargo/bin/rustup
/work/.home/.cargo/bin/rustc
rustc 1.15.1 (021bd294c 2017-02-08)

Now I wondering whether I can run my IDE in the container, and how my source code gets into and out of the container (probably git.)  The answer seems to be that the directory where you invoke vagga is the “project” directory and is mapped into the container as /work.  Your IDE can work outside the container.  All artifacts of the build should be in the container and not pollute your project directory?

Brief notes

Create a hidden setup or options file ~/.vagga.yaml with contents: ubuntu-mirror: http://us.archive.ubuntu.com/ubuntu

Until you get your vagga.yml correct, vagga seems to repeatedly download dependency packages.  IOW, errors prevent completion of the container.  When you achieve a correct container, then vagga knows, and only downloads dependency packages as needed (when the repository publishes a security update or a nightly update?  Commands don’t establish dependencies?)

Doing “sudo apt-get update” between iterations seems to help some errors.

The directory where you invoke vagga is the “project” directory and is mapped into the container as /work.

Vagga stores the container in the hidden file .vagga in the project directory (alongside your vagga.yaml.)  (To delete a container?)

Continue with Part Two…

 

 

Using relative coordinates in KiCad to design mechanical aspects of PCB boards

TL;DR: press the space bar to set the origin of the relative coordinate system and then watch the dx,dy cursor coordinates in the status bar as you draw.

See  section 2.6. “Displaying cursor coordinates” of the Eeschema reference manual.

There are two coordinates systems (frames) in KiCad:

  • absolute: origin is in one of the corners of the “paper” sheet, displays as “X…Y…”
  • relative: origin is wherever you set it using the space bar, displays as “dx…dy….”

KiCad continually displays the location of the cursor in the right side of the status bar which appears near the bottom of the application window.  KiCad updates the displayed location even as you use some tool to draw, place, etc.  KiCad displays the location of the cursor in both coordinate systems.

Use the relative coordinate system to layout a board mechanically.  First set the origin, say to the upper left corner of your board:

  • move the cursor to where you want it
  • press the space bar.  Expect the relative coordinates to change to “dx 0.0000 dy 0.0000.”

Then as you draw, you can stop the cursor at some precise dimension.

KiCad does not persist the origin of the relative coordinate system (save it in your project.)  You need to set the origin at the beginning of each design session.

KiCad does not display any particular symbol at the origin of the relative coordinate system.  You can add a fiducial symbol at the origin.

Few people use the absolute coordinate system and many people complain that you can’t set its origin.  But they should just use the relative coordinate system.

From a user-interface viewpoint, maybe KiCad should:

  • place more emphasis on the relative coordinate system (display relative coords left of/preceding the absolute coords)
  • make the origin persist
  • add a pop-up menu item to set the origin (space bar is too obscure)
  • make the displayed nomenclature more consistent (why is it not “dX,dY and dx,dy” or “X,Y and x,y” or “aX, aY and rX, rY” or “abs x,y and rel x, y”)