objects

Menu

Category Archives: Uncategorized

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.)

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 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

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.

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:

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 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

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

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?)

About

This is a quick summary of other posts. I disambiguate terms in an object oriented way. I explain elementary things.

I capitalize words to emphasize they are well-known objects, with well-known data and behaviour. You should verify, I could be wrong and I wrote this in haste. Errors here might illustrate the confusion surrounding the subject.

See Also

Disambiguation

UnsynchronizedShortTime is a basic Counter. It is not expected to be synchronized with other instances. It rolls over every few days.

RealTime is the notion of time used in the real world. It takes many bits to keep RealTime that is precise to seconds and won’t roll over within centuries. It takes even more bits (say 64 bits) to keep RealTime that is precise to micro seconds (uSec.) RealTime is expected to be synchronized with other RealTimes.

A Clock keeps time. Methods are:

set the time

ask for the time (now, or current time)

set alarms to go off at a certain time.

Subclasses of Clock:

RealTimeClock

LongClock

A RealTimeClock is a hardware Device or Peripheral. It comprises a Counter and a CompareRegister. The Counter is free-running. You can configure the RTC so that when the Counter equals the CompareRegister, an Event and/or Interrupt is generated. A RTC Counter is typically 24-bits. There is some ambiguity here: a RealTimeClock does not always keep RealTime and need not be synchronized or accurate.

There is much ambiguity here: some use RTC to mean real time counter, some use it to mean real time clock. Some use Real Time Counter to describe a Clock (having alarm functions.)

A LongClock is a longer running clock (before it rolls over.) A LongClock is typically implemented in software using a RealTimeClock. A LongClock may keep RealTime, or not.

This is where you typically find ambiguity: some “RTC IC’s (chips)” implement RealTime in hardware (they keep time very accurately, and have many bits of time available in a format you typically use in the real world e.g. YYYY:MM:DD:SS. ) RealTimeClock’s embedded as a Peripheral of a SystemOnAChip (SoC) typically do not implement RealTime (although they can be accurate.)

Precision and Accuracy and Drift (see wiki.) Accuracy and Drift are the same notion describing the relation between two Clock instances.

RealTimeClock subclasses:

RTCByRCOscillator

RTCByCrystal.

They differ in accuracy.

A RTCByRCOscillator uses a resistor and capacitor oscillator embedded in the hardware. Its accuracy is typically worse than 200 ppm. That gives a drift of a second every few days.

A RTCByCrystal uses a resonant, ceramic crystal (and sometimes capacitors) external to the hardware. (There is some ambiguity here: the circuit the crystal is part of can also be called an oscillator.) Its accuracy is typically better than 20 ppm. That gives a drift of a second every month.

A Timer just sets off an alarm. You can’t tell Time from a Timer (unless you record when you started the Timer.) You can ask a Timer for time remaining, which is a TiA LongClock meDelta (not a Time.) Timers are implemented in software using a Clock.

Use Cases

A TimeStamp is a read-only copy of a Time instance. Many applications don’t need TimeStamps, but only need differences between Times. Often you need to compute a Time difference to set an alarm.

You must be careful when computing differences between Time instances if the Clock has rolled over between the two Time instances. It is useful to keep a LongClock because pragmatically you don’t need to worry about roll over when computing differences.

Generally Times are kept as unsigned ints. It is safe to difference two Times if the Clock from which they were taken has only rolled over once between, and if the subtracted Time was actually earlier than the second, later, subtrahend time. (Since difference of unsigned ints is modulo, like a circular clock.) If the first time was actually later than the second time, it is not safe to use the difference operator to get a delta. And it is not safe if the Clock has rolled over twice between.

Design considerations

A RTCByRCOscillator embedded in a SoC is free, using no extra components or board space.

A RTCByCrystal requires an extra component and board space. A crystal is typically $1.

An external RTC IC requires more board space for itself, and also for a crystal.

A LongClock implemented in software using an embedded RealTimeClock: the software is free (except for the hassle of finding/writing it) but might still require a crystal.

In general, low-frequency (low precision or resolution) clocks take less power. Because in general, in CMOS semiconductors, it is the switching of flip-flops that takes power.

How LongClock is implemented

Keep upper (most significant) bits in a memory word. Keep the lower bits in a RealTimeClock. Configure the RealTimeClock to trigger an event when it rolls over. The handler for the roll over event increments the upper bits memory word.

How Timers are implemented

Usually a library provides multiple, concurrent Timers. The library uses one Clock. Keep an ordered queue of alarm times of the timer instances. When the clock alarm goes off, reset the clock alarm for the next timer in the queue (set the counter to the DeltaTime from now to the next alarm time.)

Specifics for the nrf5x embedded radio chip

low-frequency Counters that can be ByRCOscillator or ByCrystal (if you add an external crystal.) The frequency is 32kHz. Called LFRC and LFXO.

high-frequency 16Mhz Counters. The crystal is not optional. Its accuracy is needed by the radio. These use much more power than the low-frequency counters. Called HFRC and HRXO. To use the radio, you must start the HFCLK. Then the radio automatically switches between HFRC and HRXO as needed (switching it to RC source to save power when not transceiving.)

Not all modules (boards with an nrf5x on them) have a 32-kHz crystal. E.g. the RedBear BLE Nano does, the Rigado BMD-300 doesn’t. They MUST have a 16MHz crystal (or else they have low-performance radios, or will they even work at all?)

The RTC section describes an instance of RealTimeClock (having a compare register.) Its source can be either of the low-frequency Counters. It is 24-bits. Its roll-over depends on the prescaler.

The Timer section describes another instance of RealTimeClock. Its source is the HFCLK, whose source is either of the high-frequency Counters.

The app_timer library provided by Nordic uses the RTC. It provides Timers (alarms in the future.) It allows many concurrent Timers.

Implementing a LongClock using Nordic app_timer. This is really my goal, and where I leave off until I figure it out. I want a LongClock (with usec resolution) so I don’t need to worry about roll over, but I want to use app_timer API so I don’t have to worry about low-level interface to the RTC.

The toolchain is not very modern with respect to finding and declaring dependencies: you must maintain your own Makefile (starting from one provided by Nordic in their examples) and you must create new soft linked resources in the project. (When you change your project to call additional functions in the SDK.)

Components:

IDE: Eclipse

compiler: GNU gcc compiler for ARM

debugger: GNU gdb for ARM

interface to the dev board: SEGGER tools, JLink

flashing: nrfjprog command line tool

My host platform is a clean Ubuntu 16.04.1 installation.

My target is the nrf52 family (nrf52832 chip) on a development board from Nordic, which includes a SEGGER brand debugger probe (JTAG interface.)

install SEGGER JLink tools (interface to the debugger probe on the target development board)

install nRF5x command line tools (to flash the target)

import an example project into Eclipse

choose a Dev pack for the project (a dev pack is a description of the target, optional for debugging)

modify the project and its Makefile

build

flash

debug your example project

Details

These are selected details about the steps. (But I gloss over other details that are easily searched.)

Since I keep my projects in local git repositories and use the “Team” functions of Eclipse:

sudo apt-get install git

Eclipse is written in Java:

sudo apt-get install default-jre

At the Eclipse website you first download a small installer app. (“Ubuntu Software” app will let you install an older Eclipse.)

Then you run that app and choose from a variety of environments, here C/C++

A third party plugin adds function to Eclipse for developing embedded ARM. The Nordic chip has an ARM mcu. Search for “Eclipse ARM plugin” and find the page where you can just drag an icon into Eclipse. Alternatively, you can use the more usual method of installing Eclipse plugins, that is, choose Help>Install New Software, then enter a URL to the place where this Eclipse plugin lives, etc.

There is a gcc compiler and gdb debugger for ARM that are not installed with the usual development tools (such as make) that are already installed on many Linux hosts.

sudo apt-get install gcc-arm-none-eabi

sudo apt-get install gdb-arm-none-eabi

The Nordic SDK includes many libraries (in source form) and example projects (including Makefiles for this dev environment.) This toolchain uses soft links to various files in the SDK (the source is not copied to the project.)

The development board includes a SEGGER brand of hardware debugger probe (a JTAG interface to the target) so you are entitled to use SEGGER’s tools to talk to it from Eclipse. See below.

The nRF5x command line tools are a separate download from the Nordic site. It yields nrfjprog, a tool to flash your app to the target. I am not sure you need it, you can also use JFlash, a SEGGER tool?

Outdated example projects are attached to the tutorial as zip files. The example projects contains an “Eclipse project file”, i.e. it is not just the source files, but a file that configures Eclipse with many soft links to the SDK. Example Makefiles and .ld files are in the SDK. E.G. $(NRF_SDK_ROOT)/examples/peripheral/blinky/pca10040/blank/armgcc/Makefile, but using those you must create your own Eclipse project.

After you create a debug configuration, make sure you choose the correct one: the arrow to the right of the Debug icon lists the configurations. You will have two after you create another one. If you choose the wrong one (the C/C++ Application configuration) you get:

nrf52832_xxaa.out: cannot execute binary file: Exec format error

Note that the “Main>C/C++ Application” field is “_build/nrf52832.out”, not .elf. Other than that, I only entered the device name field, “nRF53832_xxAA”. (Since I had not already loaded a dev pack it was not filled in automatically?)

Do not choose “Connect to running target” because you usually want to reset the mcu before you start debugging.

When you debug (for example by clicking on the Debug icon), expect Eclipse to change to the debug perspective and for the debugger to break at main(). This worked for me even though I had not flashed the test program, i.e. it stopped at the standard location for main.

More details of installing packs

In Eclipse, switch to the Packs perspective. Click the refresh button at the top of the “Packs” pane. It takes many minutes to refresh (from the web.) If it fails to refresh packs, try deleting the Packages folder. Expect a list to appear in the Packs pane.

The left pane is for filtering the Packvoid RTC1_IRQHandler(void);s pane. If you select an entry there, it filters the list in the Packs pane.

I selected the “Device” tab in the left, filtering pane, and selected “Nordic Semiconductor>nRF52 Series.” Then in the “Packs” pane I expanded the “nRF_DeviceFamilyPack” item, and right-mouse-button clicked on the latest version and chose “Install” from the pop-up menu.

I don’t understand what the “Board” tab does, and I didn’t use it.

After you install a device pack, the debugger magically (without you needing to change the debug configuration) starts showing more information, such as dissassembly and registers. Until you do this, they are empty or blank.

More details of futzing with the project (step 12)

Fix path variables in the project

In Project>Properties>Resource>Linked Resources>Path Variables, add a new entry “NRF_SDK_ROOT” to point to where you installed the SDK.

In …Linked Resource>Linked Resources, edit each entry that is broken (has an exclamation point) to use the NRF_SDK_ROOT path variable you just defined.

Fix the path to the compiler in the Makefile

(This is described in the Nordic tutorial, but obliquely, for Windows.)

The Makefile in the example project includes a Makefile.posix from the SDK. Makefile.posix defines the path to the gcc compiler for ARM. Edit $(NRF_SDK_ROOT)/examples/toolchain/gcc/Makefile.posix. Change the first definition (of GNU_INSTALL_ROOT) to have the value “/usr”

Fix capitalization errors (case) in the SDK

The SDK was developed on a Windows host, which is case-insensitive to filenames. There are some capitalization changes (bugs that Nordic is aware of) needed:

$(NRF_SDK_ROOT)/components/toolchain/gcc/gcc_startup_nrf52.S => .s

In the Makefile:

CMSinclude/Include => cmsis/include

Define path variables in the Makefile

More details on a Flash target (step 14)

The Makefile has a target (something you can ask to make) for flashing. The target invokes the Nordic command line tool nrfjprog. (In more modern toolchains, for non-embedded programming, you neither maintain the Makefile nor invoke more than one make target. For desktop app, other targets might package an app. For embedded, you must flash the app.)

You can configure Eclipse so that you can click an icon to make that target (and flash your app to the dev board): in the C/C++ perspective, in the right pane, select the “Make Target” tab, next to the “Outline” tab. Then select your project in the body of the pane. Then choose the “New Make Target” icon (an icon of green, concentric rings with a plus sign.) Expect a dialog to open.

Enter a “Target name” (extracted from the Makefile), in this case “flash”.

Choose OK. Expect the dialog to close and a new entry named “flash” in the body of the pane.

To flash your app, double-click that new entry . Expect the console to show messages about the progress of the flash.

The tool nrfjprog must be in your shell path, or you can modify the makefile to invoke it using an absolute path to its installed location.

More about debugging (step 15)

When you click on the Debug icon (and choose the proper debug configuration) the perspective changes to the Debug perspective and the program is halted at main() (a default of the configuration?) You can choose from the icons to Resume, Step Into, etc.

If you have installed a dev pack, the Dissassembly tab of the right, middle pane will show assembly code (sometimes?) The Outline tab of the same pane will show the context of the current program counter? Sometimes it shows that you have wandered into an exception handler (a green dot?)

The left, middle pane has an arrow in the left margin showing where the program counter is in the source code. If the PC is in a macro such as APP_TIMER_INIT, that is not very useful.

If you are stepping along and the console shows “Starting target CPU…” and the blue arrow does not advance in the source code, it means you have thrown an exception and entered an infinite loop in the default exception handlers (see startup_nrf52.s). Click the Pause icon to see where you are looping. Then the Debug pane in the upper left will show you the call stack and you can examine it to see where in the code you were when the exception was thrown.

Debugging using NRF_LOG

This section is work in progress, not working yet because NRF_LOG has C linkage, not C++

This section is highly dependent on SDK version, here using v12.

The two usual techniques for debugging are:

use a debugger e.g. gdb

use “printf” or “log” statements sprinkled through your code

NRF_LOG is a logging library from Nordic. A logging library is glorified printf: it adds the capability to specify a logging level such as: INFO, DEBUG, etc. The level can change for each module.

Here NULL means: without timestamping. I chose to ignore any error return.

Logging to the Eclipse console

TODO Does this work???? The log can go to the Eclipse console. The log statements will be interspersed with messages from the SEGGER GDB Server (e.g. “Reading registers…”)

To arrange that in Eclipse, click on the arrow next to the Debug icon. Expect a pop-up menu. Choose “Debug Configurations.” Expect a dialog. Select your configuration in the left pane. Expect the right pane to refresh with the attributes of your configuration. In the right pane, choose the “Startup” tab. Choose the “Enable semihosting” checkbox and the “GDB client” checkbox. Choose “Apply” and “Close.”

Logging to SEGGER RTT

You can also use a faster solution, SEGGER RTT. Faster means it takes less cpu cycles away from say your ISR routines. It is faster because the logging goes directly from your target mcu to a terminal app on your host, without going through the GDB Server on your host?

Described by E. Styger’s post. That requires more setup, and requires a SEGGER probe (which your nrf52 DK board has.)

Debugging off in the weeds, lost in never never land

Especially if you are debugging your own code (versus an example project), you might end up with the program state “Running” but not hitting any of your breakpoints you expect to hit. When you click the “Pause” icon, it might show the PC in:

WDT_IRQHandler

HardFault_Handler

I think this means an interrupt occurred for which you did not define a handler. Default handlers are provided in startup_nrf52.s. You can also see them in the .map file.

Each of the internal interrupts (for exceptions such as invalid op code, invalid memory address, etc.) has a separate default handler defined. They are all just infinite loops, but at different addresses.

The default handlers for IRQ (external interrupts) are all just one, same handler (at the same address) that is an infinite loop (assembly code: “BR . ” that is, branch to the value of the current PC program counter register, i.e. a loop.)

WDT_IRQHandler

The debugger will say it is the WDT_IRQHandler, because that is the last name that points to this location. But it might not be the WDT device that interrupted, and started looping in the default handler. Once you are paused, to know what IRQ device interrupt occurred, examine the XPSR register. One of its sub-registers is the IPSR register, the low-order 9 bits. (For unknown reasons, SEGGER and gdb did not show the IPSR sub-register by itself, and showed the contents of the full XPSR register in decimal.) Convert to hex (using a calculator) and mask off all but the low-order 9 bits. From that value, subtract decimal 16 (hex 10). That gives you the index of the interrupt. Then examine /components/device/nrf52.h for its list of the interrupt indices. In my case, I got zero, meaning the “POWER_CLOCK” IRQ.

Then you can define your own handler in C, just a function with the same name e.g. WDT_IRQHandler. The default handlers are defined as “weak” in assembly language, so defining the same name function in C overrides the default.

Here, I am using C++ compiler so I am careful to specify C linkage so that the compiler doesn’t mangle the name and the linker then overrides the default, weak definition:

extern "C" {
void WDT_IRQHandler() {
while (1);
}}

In my case, the interrupt I was not handling was one used by app_timer. In the SDK /components/drivers_nrf/clock/nrf_drv_clock.h I added this (so that the C++ compiler did not mangle the name and thus fail to override the weak default):

This is only because I used app_timer from the Nordic library. In general, if you use more from the library that might use interrupts, you should examine your .map file for any “…IRQHandler” whose name is mangled by the C++ compiler.

If you fail to make these changes (and you are using C++ and app_timer) the symptoms will be: your app compiles but halts, showing a stack trace that ends in some IRQHandler, after a call to an app_timer function.

Note that Nordic does NOT fully support C++. Thus you may find instances such as above, where you need to alter the SDK code to support C++. There are many places in the SDK code that seem to support C++ (i.e. #ifdef __cplusplus) , but the support seems to be incomplete.

(Here I rant: I hate C++ but I like object oriented programming. I use C++ in a highly constrained way. I don’t want to use a C standard dated to 1999. I need all the help I can get from a compiler. I wish Nordic would embrace C++, or even some other modern language like Python or Rust. )

HardFault_Handler

A short summary is: many bugs (programming errors) such as bad pointers end up as hard faults. (And not necessarily an op code exception or a memory exception, depending on how exceptions are enabled?) The debugger often does not show you the call stack when a hard fault occurs. So install a handler for this exception that helps the debugger show you the call stack when the exception occurred. A few statements/instructions before the last call is often the errant code.

After thoughts

The build system takes much hands on maintenance of the Makefile, and is not as smart as some build systems about avoiding redoing steps that don’t need doing:

build, it only compiles.

flash, it compiles then flashes

debug, it builds, then starts the debugger, without flashing!

Some of the dependencies are defined in the Makefiles which you are maintaining. If you create a dependency error in the Makefile, it might build with stale code.

Other build steps are specified in the Eclipse configuration.

If the debugger ever seems lost, start over by cleaning, building, flashing, and debugging.

Balanced: all units have the same power. None are powered by an electric utility grid.

Ultra-low power: units use microamps of power on average. They use milliamps when active, but they are duty cycled (sleeping often.) They use harvested energy such as solar energy. They have a small or no battery. They often reboot as energy is exhausted.

Single-hop: all units can communicate directly with all other units. No unit needs to relay or route messages. The network topology is bipartite.

Sensors: the units do not sense external events not synchronized with the network. They can sleep for as long as necessary, without concern for missing sensing external events (that don’t have interrupts.)

Wireless: the units have a radio. Messages can be broadcast. There is contention for shared channels. A radio may not be able to transmit and receive at the same time.

Relevant Literature

Digi Corporation’s proprietary DigiMesh product apparently has a sleep synchronization algorithm. It apparently is a leader-election algorithm. Many details are unavailable?

“Firefly Clock Synchronization in an 802.15.4 Wireless Network”, Leidenfrost and Elmenreich, 2009 describes an algorithm where units can sleep and synchronize. They call it a “reach back firefly” algorithm. Unlike a firefly (where a message is just a one-bit blink at the time of the synchronization point, without content), here a sync message is transmitted at an offset from the synchronization point and has the offset (many bits of information) as content. Like most firefly algorithms, all units send sync messages.

Wireless HART has sleep synchronization, but it is centralized: synchronization propagates from a gateway device that has more resources (a connection to the internet) than other units.

There is much more literature, see later.

Background

In clock synchronization, a network (the units together) maintain a global notion of time. This lets units schedule internal events to occur simultaneously, or timestamp external events. The units communicate to synchronize clocks.

Sleep synchronization means: synchronize the events: unit awaken and unit sleep. Many clock synchronization algorithms assume the units are always awake. It is harder to synchronize when units may sleep.

Time is kept by a Clock. It need not be referenced to an external, real time, such as sidereal (sun) time.

Each unit has a hardware clock, really just a counter.

A GlobalClock keeps the global time. Each unit has a GlobalClock. It is based on the hardware clock. A GlobalClock is just an offset from the hardware clock. Initially the offset is zero. When a unit receives a sync message from a master, a unit can calculate an offset and the local GlobalClock becomes ‘in sync’ with the master’s GlobalClock.

Hardware clocks drift (have slightly different tick rates) and so each unit’s GlobalClock drifts from every other units GlobalClock (especially the master’s.) Thus to maintain an accurate GlobalClock, a unit must periodically receive a sync giving message.

Assumptions

Each unit is duty-cycled: sleeping and waking. When sleeping, unable to receive since mcu and radio are powered off (only a timer to wake the mcu is powered.)

The network is symmetric-powered. No unit has more power than others. No unit is not duty-cycled.

Units are the same, hardware and software. Each unit is capable of assuming any role.

Units have one transceiver that cannot transmit and receive at the same time. A unit cannot detect its own transmission has collided.

There is contention: collisions can occur on the radio channels.

Network topology is totally connected. Each unit can hear all other units (and does so, except for collisions.) No unit relays messages to other units.

Duty-cycle is high (sleeping mostly.) That is, put a high priority on conserving power at the cost of slow execution or missing external events. For example, when energy is harvested and units are small, the power available may be very low, supporting only a very high duty cycle (sleeping most of the time.)

Low performance. The work being done is not critical and extremely low data rate. Don’t care if the work doesn’t get done always. Only care that the work gets done sometimes. Here the work is both the synchronization and some additional coordination or data exchange.

Not Constrained

Not assume that units play equal, same role.

Not assume that the communication is uniform. Some units may play roles having more communication than others.

Not assume that lower layers of the protocol stack, e.g. the MAC layer, support synchronization, e.g. by timestamping messages with clocks used in those layers.

Not assume a sensing network. That is, the network may do something self-contained, without sensing external conditions or events. Because units sleep so often, they probably would miss sensing many external events.

Classes of Algorithms

In “firefly” algorithms, roles are equal. Firefly insects are leaderless.

In “leader election” algorithms, some units play the role of leader (master of the clock.) Opposite of firefly.

In “time triggered protocol” algorithms, units have a common, slotted schedule, a priori, built into the protocol. Not only is the wake period scheduled, but the wake period is divided into slots reserved for certain units and tasks. Eventually, the schedules of different units are synchronized. This is TDMA.

Keywords

This is a list of search terms. In searching, you must cast a wide net, since authors use diverse terms for subject matter that overlaps.

Leader elections algorithms

Some algorithms form cliques (clusters) of units where units within a clique are synchronized, but cliques not synchronized with each other. The algorithms are said to go through phases of startup and maintenance. In the startup phase, cliques form and merge. Eventually all units are synchronized in one clique, and the algorithm is in the maintenance phase.

The maintenance phase corrects clock drift, and merges new cliques, when units join the network dynamically. Joining units may form new cliques until they synchronize with existing cliques.

General review of concerns in the literature

The general literature has many concerns. Here I briefly discuss those concerns.

Coverage: in multi-hop networks (not bi-partite), insuring that the area covered by the awake network is maximal, so that any external events e.g. are sensed.

Precision: the goal may be more clock precision (e.g. uSec) than is needed just to synchronize sleep (e.g. mSec). This might require support in lower layers such as MAC.

Dynamic: networks in which units (possibly mobile) may join/leave the network.

Fault tolerance: if one unit fails or has inadequate power, the algorithm still keeps or recovers synchronization.

Drift correction: the drift of one hardware clock can be estimated. Drift is generally linear. Thus it can be corrected for. That saves effort in global synchronization.

Correctness: whether you can prove mathematically that the algorithm works: 1. doesn’t suffer deadlock 2. converges to a single synchronized clique.

Routing under energy constraints: when the network is multi-hop (not bipartite), routing through nodes having the most energy reserves.

The protocol is in the app/transport layer. No master, each unit sends sync (firefly). A unit sends sync in the wake period of its own schedule. A unit periodically listens for the entire sync period (to hear other cliques.) A unit also transmits sync in the sleep period of its schedule, to apprise other cliques (redundantly with listening.)
“A Survey of Energy-Efficient Scheduling Mechanisms in Sensor Networks”, Wang and Xiao.

GLOSSY. The concern here is flooding, with clock synchronization as a secondary benefit. The novel idea: when two nodes simultaneously send an exact same message (with no distinguishing characteristics such as sender ID), the messages do NOT destructively interfere, but are heard by many receivers as one message.
FLOPSYNC-2

Firefly algorithms

Firefly algorithms are non-centralized and leaderless.

In general, firefly algorithms are not concerned with sleeping. Firefly insects don’t sleep while they are synchronizing. They also can transmit and receive at the same time. Also, they can communicate with multiple others at the same instant, since their eyes are multi-processing.

Firefly algorithms may be concerned with multi-hop networks, since firefly insects can be spread so far that each firefly cannot see some others.

Firefly algorithms (especially for insects, i.e. models of biology) may assume only a binary message, a pulse.

IEEE 1588 Precision Time Protocol (PTP)

This is “leader election.” An advance form sends two messages to establish a precise time: the first announces intent to synchronize at a time, and the second gives the precise time the first message was sent. The timestamp in the first message is not precise because of inherent unpredictable delays in the protocol stack, while some stacks will give you the precise time that a timestamped message WAS sent (via the return code or interrupt from the sending of the first message.)

Thus there are two sub-classes of “leader election”: “imprecise subclass” in which only one message is sent, and “precise subclass” in which two messages are sent.

PTP is not concerned with energy conservation and assumes network is always on.

Bluetooth as the Communication Stack

Classic Bluetooth is asymmetric power and connection oriented. A Central is typically a phone with much power. A Peripheral is typically low power and listens periodically for connections, but after a connection is made, stays awake.

Bluetooth radios have a choice of counter/clocks: precise crystals or imprecise resistor capacitor.

The Scanner/Observer roles can be used for broadcasting (without connections), not just for classic advertising of services.

BT advertiser is multiple access, but not carrier sense?

Typical jitter in the stack is as much as 5 milliseconds.
Beacons

My specific use case

Ultra low power. Units lack batteries, instead use harvested solar power. They may sleep at night. They may have periods without enough power to sustain the volatile memory or a timer, and reboot often, say every morning. Duty cycle is very low, say 1%. Bipartite: units are all within range of each other. The units just display in sync, they blink an led or move.

About this post

This pulls together various other posts and links. Audience is someone who is new to embedded microprocessors (MCU) but otherwise familiar with software development.

Context

Energia is an IDE. It is a port of the Arduino IDE (swapping out Atmel AVR mcu for the TI MSP430 mcu.) In other words, it is the Wiring development platform, but specialized for a different embedded mcu.

The IDE lets you edit programs and write them (flash them) to a target board. This particular IDE does not have integrated debugging.

MSP430 is a family of ultra low power microprocessors from TI. See the FAQ.

The EZ430-F2013 is one model of development kit for the MSP430. It includes:

an FET (flash emulation tool) hardware

a detachable target board (detachable is unusual, most have pluggable IC’s)

other IDE software tools on a CD

A FET is an adaptor from your development PC to the target board. Adaptor: it has a USB connector on one end, and a connector to the target board on the other end. It adapts from USB serial to Spy Bi Wire serial. This particular FET and connected target board are in a USB stick form factor or package. With the IDE, it lets you:

flash the memory of the target board

debug the target board using a version of gdb talking JTAG/SBW to the target

The target board is a small PCB having:

the MSP430F2013 model mcu

one LED

two rows of breakout pins for you to add circuitry

a four-pin connector to the FET.

You can also buy a EZ430-F2012 (part number), which is a package of three compatible target boards, except they have the MSP430F2012 (model number) mcu.

Why this combination?

Pros of all TI’s other development kits:

cheap, TI seems to be subsidizing

target mcu is ultra low power, TI seems to be emphasizing low power for the IOT, and has many other low power chips

target mcu is small in area

Pros of this development kit:

the target mcu is VERY small (a few tens of mm squared)

you could use the detachable target board as a component (although it has an odd half-moon shape). It’s the size of your thumbnail.

Pros of Energia:

it has an approachable language (a simple subset of C++)

it has many built-in libraries

you can also program in C++

Cons:

its basic, low-end, and older

the target mcu has too small 2K flash memory for large programs

the target mcu has few IO pins

the target mcu has few modules (peripherals): only an ADC, and a few timers

its not very popular, most professionals use other development kits, other IDE’s, and other programming languages (assembler or C)

several IDE functions use the command line (debugging)

it flashes using SBW, which is slower than a full JTAG programmer

it doesn’t interface the serial port of the target board (to let you print)

For learning, its great. But consider whether the target board will meet the needs of your application.

where ‘foo’ is the group that you belong to. You need to be superuser, so use >sudo nano or >sudo vi to create the file. What this does: at boot time, the OS gives permission for anyone in the group to read and write the OS device file (/dev/tty?).

Restart your computer.

Patch Energia for the MSP430F2012 or 2013

Energia doesn’t properly support this development kit (there are patches waiting to be approved and merged on GitHub.) But you can fix that by:

Edit ~/ener*/hardware/msp430/boards.txt.

Copy and paste the first block of text.

In the copy, change:

‘r2500’ to ‘uif’ after the word ‘protocol’.

‘msp430g2331’ to ‘msp430f2012’ or ‘msp430f2013’ everywhere in the copied block only

If you omit this step, when uploading you may see the error message:

usbutil: unable to find a device matching 0451:f432

Start Energia

Open a terminal.

>cd ~/energ*
>./energ*

Expect a GUI application to start. Stuff will still scroll in your terminal window, but the same stuff appears in the bottom pane of the GUI.

Swapping target boards

You can pry the plastic USB case apart with a small blade or screwdriver. It is split down the middle. It has friction fit, plastic pins. Pry one half straight up. Then the target board pulls off the end. You probably should saw the end off the plastic case so you can handle the unit but more easily change the target board (if you intend to flash more than one target board.)

If you intend to use the ADC of the F2012 mcu, swap the target board out first thing. The F2013 has a different ADC (a SMA_16 16-bit) versus the F2012’s ADC10 (10-bit). The ADC registers are at different addresses. The MSP430 architecture (ISA) does NOT generate exceptions (trap) for all illegal addresses or illegal opcodes! Instead, it quietly lets you read and write some addresses (device registers) for which there is no device. In other words, if your program that uses the ADC doesn’t work as expected, maybe you are including the .h file for a different target and addressing the wrong ADC. The ISA is subject to change between models, read the datasheets carefully.

Plugin your EZ430-F2013 USB stick

Plugin your EZ430 USB stick. Expect it’s LED to start blinking. (When powered up, it resets, and the factory programmed “blink” program starts running.) The LED may never blink again, depending on your programming skills.

Test the Blink program

Choose File>Examples>Basics>Blink. Expect a new program to load into the IDE. This program is compatible with the target board (which has one green LED on Port1.Bit0).

Note that here I have already swapped out the F2013 target board for a F2012.

Expect your USB stick blinking again.

Now you can go on to write other programs.

Using the serial port

The menu Tools>Serial Port remains greyed out (disabled) and will remain so. The FET has two pins toward the target board that are not connected to the target board. Thus the FET can not read the serial port of the target board, and your program will not be able to print to the serial port and expect it to appear on the IDE.

The target board does have breakout holes for the TXD and RXD pins of the target mcu. You might be able to jumper them to the FET.

Probably the designers of the target board decided that since memory on the target board is limited, it would not hold a library implementing serial IO (in addition to other program code.)

Debugging

You can use gdb on a command line to debug the target device remotely (the target supports JTAG so this is possible) as described by an Energia dev.

Energia invokes the mspgcc compiler with optimization. You might need to alter you program (remove inlining) to insure that functions appear as symbols.

From an obscure post by Ingo:

mspdebug does not use debug symbols (the ones you enable with the -g compiler switch), just the plain symbol names that are also used for linking. However, in the ELF format, each symbol has a type field, and mspdebug only uses symbols of certain types (object, function, etc.). You can display the symbol table of an ELF object with “readelf –syms file.o”. Symbols whose type is listed as NOTYPE will be ignored by mspdebug.

the intrinsics to assembler that the compiler supports (section 6.8 of the above)

interrupt handling and the ‘vector’ pragma (section 6.7)

the runtime environment (section 6. It sets up the stack, etc.)

the include file that defines target addresses, constants, and other language constructs (in this case “#include msp430f2012.h” or …f2013.h ) which are found at ~/ener*/hardware/tools/msp430/msp430/include/

Development Kit User’s Guide

Using the FET for other targets

You can design your production PCB with a matching four-pin connector, and program/debug it using the FET portion of the development kit. The four pin connector has Vcc, Vss, and two SBW signal lines.

You might be able to use the FET with a different target. I haven’t tried it yet. I don’t know of any impediments. My opinion is that TI is downplaying the ability of the FET. The User’s Guide says it will work with other devices in the ‘MSP430F20xx’ family. (I am hoping it works with devices in the MSP430FRxxxx family.)

Ultra Low Power Hardware and Coding

Ultra low means: less than about 1uA average current. That gives tens of years on a coin cell battery. Or lets you use energy harvesting.

The mcu when active draws tens or hundreds of uA. Thus to achieve ultra low power, the mcu must be sleeping (in a low power mode) much of the time, and use interrupts to wake up.

If you have external interrupts, the lowest power mode is LPM4 (the mcu and peripherals off, but external interrupts will wake.) Called ‘Off Mode with RAM Retention’. Draws 0.1uA.

If you don’t have external interrupts, sleeping is low power mode LPM3 with a timer peripheral running in the mcu to interrupt and wake the cpu up. In this mode (called standby), the MSP430F201x draws 0.5uA.

If you need accurate time, you can implement a 32-bit RTC in software, as described by a TI Application Report, using an external clock crystal (loses 1 second per month) to the 16-bit timer (which wakes up the system every few seconds to tick the 32-bit software RTC.)

If you don’t need accurate time, you can use the VLO portion of the clock module as the clock source for your timer. That is the lowest power standby mode. See the datasheet for the MSP430201x.

If you need even lower average power, you can switch power Vcc to the mcu, using an external chip such as the TPL5010 Nano Timer which draws only 35nA (0.035uA.) But then you might lose any data saved in volatile memory (RAM) such as the context of your application (and the application must restart.)

TI makes MSP430FRxxxx‘s having FRAM and using as little as 0.35uA current in standby mode. Some models have a 32-bit RTC implemented in hardware. Check the datasheets, its not clear to me for which applications this family saves power. The smallest member/package for this family has 24 pins, compared to the 14 pins of the F2012, and is 16mm square, about the same area. (These packages are near the limits of what you can solder at home.)

More about JTAG and Spy By Wire (SBW)

See JTAG and SBW. JTAG uses many signal wires, SBW only two. SBW is slower.

In short, it means that you can use a software debugger (similar to gdb) to remotely debug a program on an embedded MCU while in-circuit (soldered to a prototype or production PCB) using only two wires to connect from the development machine to the PCB. That is, you don’t need to simulate, you can debug under actual hardware conditions. If the hardware timing conditions are not so severe that you need a more powerful solution.

Context

This is a log, or instructions. Disclaimer:

things change, this will quickly become outdated.

I sometimes make mistakes

there may be other ways to do this

This is similar to my post about using Linux host for the same purpose. Here, I switched to a new host: OSX. I decided that OSX was a better host than Linux, since OSX supports more targets (OSX, iOS, and Android) whereas Linux only targets (Linux and Android.)

There are only slight differences between using host OSX and host Linux:

where menu items live in the QtCreator GUI.

how prerequisite third-party tools are packaged

My use case is also using pyqtdeploy. So in this example, I start with a QtCreator project that pyqtdeploy created for me. You might also use these instructions for a Qt example project.

Prepare tools that QtCreator depends on

QtCreator, to build for Android, requires third-party tools. Install:

Android SDK (Google)

Android NDK (Google)

Ant (Apache ) (a better ‘make’, that QtCreator uses.)

JDK (Oracle)

OLD: Follow widely published instructions. But …

New: QtCreator is smart enough to help you download these things: choose the download icons (a green arrow pointing down into a tray) in QtCreator>Preferences>Android.

Expect:

a directory e.g. $HOME/android-sdk-macosx

a directory e.g. $HOME/android-ndk-r10d

a directory e.g. $HOME/apache-ant-1.9.4

a scattered installation of the JDK (it comes as an OSX .dmg, or self-installer)

You should not expect any executables to be installed in your PATH, i.e. ‘which ant’ returns nothing. Or at least you will not be invoking any executables: instead you will configure QtCreator to know where the executables live.

Open a project and configure it with a kit

Here I double-clicked on the .pro file that pyqtdeploy created. Expect QtCreator to start and show you a dialog asking you to choose a kit.

In my case (probably because of futzing I had done earlier) there were multiple Android kits, including one that apparently I had created earlier. I chose ‘Android for armeabi-v7a (GCC 4.0, Qt 5.4.0)’, which I think is one that is distributed (not the one I had created earlier.)

I also changed the ‘build directory’ to the one that was specialized with ‘android’ e.g. /Users/bootch/pensoolpyqtdeploy/build-Pensool-Android_for_armeabi_v7a_GCC_4_9_Qt_5_4_0-Debug (not $HOME/pyqtdeploy/build which is the directory that pyqtdeploy created.)

Expect link errors (at least in my case using pyqtdeploy, I had not properly compiled a static Python?) Or, if it deploys, expect a mysterious crash (better to use target iOS from this host, since it gives much better crash reports.)

The rest of this is cruft. If you choose the kit distributed with QtCreator, you won’t need this. If you choose a kit that you created.

Configure the build settings for a custom kit

At least for me, I needed to configure:

the build directory

the compiler

Choose the ‘Projects’ icon in the left panel. Expect it to show a tabbed panel, initially on the ‘Build&Run’ tab.

Expect that tab to have a nested tabbed panel initially displaying one kit ‘Qt5.4.0 for Android armv7’.

Expect that kit to have a toggle button ‘Build/Run’. Ensure it is toggled to ‘Build’.

Configuring the compiler for the kit

Choose the ‘Manage Kits…’ button to the left of the ‘Qt5.4.0 for Android armv7’ tab. Expect a ‘Preferences’ dialog to open.

Ensure that ‘Build&Run’ is selected in the left panel. Expect the right panel to be titled ‘Build&Run’ and to have tabs such as ‘General’, ‘Kits’, etc.

Choose the ‘Compilers’ tab. Expect the tabbed panel to display a list of compilers under the heading ‘Auto-detected.’