Wednesday 17 May 2023

Starting a new Zephyr project using West

Zephyr and its package manager West are getting a lot of attention these days. Unfortunately the rapid pace of software development isn't always matched with documentation and West in particular is pretty obscure.

When starting a new project, I tend to set-up the environment first with a "Hello World" type example and then write software from there. With this in mind, here's a minimal west.yaml file that you can use to build your project on top of, but separate from, Zephyr:

manifest:
  version: "0.13"

  remotes:
    - name: FOO
      url-base: https://github.com/FOO
    - name: zephyrproject
      url-base: https://github.com/zephyrproject-rtos

  defaults:
    remote: FOO

  projects:
    - name: zephyr
      remote: zephyrproject
      path: zephyr
      west-commands: scripts/west-commands.yml
      revision: main

  self:
    path: BAR

  1. Copy & paste the above into a west.yaml file in the root of your FOO/BAR repository
  2. Copy a Zephyr sample from https://github.com/zephyrproject-rtos/zephyr/tree/main/samples into the root of your FOO/BAR repository. I use hello_world.
  3. Install west - see any number of web tutorials about how to do this
  4. Create an empty directory somewhere and cd into it
  5. Run west init -m https://github.com/FOO/BAR
  6. Run west update
  7. Run west build BAR to build the sample which is now completely detached from Zephyr

Tuesday 24 January 2023

Fixing Circuit Specialists CSI3003SM Power Supply

It was a cheap power supply and never worked particularly well. Probably should have paid a little more and bought a TENMA (which I eventually did) but hey - live & learn.

Degradation

I calibrate my power supplies every 2 years and found that the current display was getting progressively inaccurate. In 2019 the offset was +40mA overreading and 2021 this rose to +200mA. Voltage reading was always good but the knobs became increasingly unreliable making it difficult to select a voltage. The voltage setting drifts over time too. All in all, this little PSU isn't in a happy place.

Regulation

The power supply itself is fine, and from a software engineer's point of view the 240VAC to 30VDC is the scary bit. I decided to buy a ZK-4KX Buck Regulator on eBay for £13.30 - it was from a UK seller which costs a couple of pounds more than direct from China but then the import duties are somebody else's problem; no VAT receipt was provided. No manual either.

Buck Boost

The first experiment was to power the ZK-4KX with around 8V at ~500mA current limit and see what it did. I also have an Array 3710A DC load which is essential if you're testing power supplies. The first pleasant surprise is that the ZK-4KX powered-up generating 12V from the 8V input - so this really is a Buck Boost regulator capable of raising its input voltage. Nice. Slightly disappointed that its default is to start in the ON state but pressing the rotary knob dropped the output to 0V pretty quickly.

The Plan

  • Select the highest voltage/current setting available from CSI3003SM - this is around 30.8V and 3.1A on my unit, or 95W.
  • Wire the CSI3003SM output into the ZK-4KX and set its power limit to 91W so as not to trigger the CSI3003SM current limit.
  • Remove the CSI3003SM voltage/current display board and insert the ZK-4KZ into the slightly enlarged hole.
  • Remove the CSI3003SM voltage/current knobs and wire the ZK-4KX output to new 4mm sockets on the front panel.
  • Add an earth socket - I like floating power supplies but also value having a common ground across my workbench. I usually pull GND to Earth with a ~100k resistor.

DANGER

Modifying a PSU is dangerous. Proceed at your own risk. Be aware that current kills, not voltage, and you're playing with over 3A. If you don't understand how voltage and current are related then you're not ready to take apart your PSU. If you accidentally put 90W through a metal watch or wedding ring you're going to have a really bad day.

Make a mess

Unplug your PSU from everything and undo 4 screws on each side. Remove the lid.

Undo 2 screws at the front underside. Unplug the display and adjustment boards. Remove the front panel.

Remove knobs and unscrew potentiometers from front panel. Unscrew both boards.



Modification

Enlarge the display aperture to fit the ZK-4KX module. I use an old 0.5mm soldering iron to melt the plastic and scalpel to clean the edges. Doesn't have to be super neat because ZK-4KX has a generous bezel that will cover the hole.

I also decided to put new 4mm plugs in the holes where the potentiometers used to be. You'll need low-profile ones to fit. Alternatively I suppose you could re-use the existing 4mm sockets.


De-solder the potentiometers from their board and replace with 4x wire links and 2x 10kOhm resistors. This has the same effect as turning all pots fully clockwise.

SEE IMPROVED MODIFICATION LATER BEFORE TRYING THIS!


Note that I used the legs of the resistors to link to the next post hole

Reassemble




Performance

Well it works! One surprise is that the ZK-4KX output power is limited to 35W by default and the maximum is 50W. I should have read the description more carefully (you can find sort-of datasheets of this thing online). It's only going to support 35W output without a cooling fan on the heatsink and even with a fan it'll only support 50W output. So you have 0-30V, 0-4A output but not at the same time. 

The side screws foul slightly on the plastic casing of the ZK-4KX. Not a major problem but they tend to push it out a little.

The hardwiring of the CSI3003SM appears to select 31.7V and at least 3A. That triggers the ZK-4KV overvoltage so I modified the adjustment board to select high coarse and low fine potentiometer settings, replacing two links with 1kOhm resistors:


This gives 26V with current limit just under 3A

Accuracy

ZK 12.00V, 1.000A current limit, 200mA load

DC load reports 12.01V. ZK reports 199mA

ZK 12.00V, 1.000A current limit, 400mA load

DC load reports 12.01V. ZK reports 401mA

ZK 12.00V, 1.000A current limit, 1000mA load

DC load reports 12V. ZK reports 999mA

ZK 12.00V, 1.000A current limit, 1001mA load

DC load reports 10.5V. ZK reports 1000mA

Tuesday 14 June 2022

OpenVPN Cloud with OpenWRT Client

 OpenVPN Cloud is a remote access VPN server with a free plan that supports 3 simultaneous clients.

Whilst they make clients available for common desktop operating systems, you can also get clients for Linux based networking equipment such as OpenWRT. This makes it possible for me to configure my office router to be a client and tunnel site-to-site traffic over the much more secure SSH protocol without having to mess around with static IP addresses etc.

The problem was the default route table that OpenVPN Cloud pushes to its clients:

Kernel IP routing table

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface

default         192.168.5.1     0.0.0.0         UG    10     0        0 eth0.2

100.80.0.0      100.96.X.Y      255.240.0.0     UG    0      0        0 tun0

100.96.0.0      100.96.X.Y      255.224.0.0     UG    0      0        0 tun0

100.96.X.Z      *               255.255.255.240 U     0      0        0 tun0

172.16.1.0      *               255.255.255.0   U     0      0        0 br-lan

192.168.5.0     *               255.255.255.0   U     10     0        0 eth0.2

192.168.9.0     *               255.255.255.0   U     0      0        0 br-guest

This is using the default "Full Mesh" mode which just routes all traffic between all connected clients - in my case between my laptop and my router.

It didn't work.

The problem appears to be that the subnets 100.96/11 (the mesh) and 100.96.X.Z/28 (the uplink) overlap and OpenWRT can't figure out which one to use to send IP traffic. The former is a gateway and the latter is an interface but that doesn't matter to OpenWRT (this is possibly a bug but hey)

Route metrics are a way out of this: the router will prefer one of the subnets over the other because is has a lower "cost".

I didn't find a way to set route metrics on the OpenVPN Cloud server but you can add a line to the client .ovpn configuration - you can find it in the Luci control panel under VPN -> Open VPN -> Edit

route-metric 1

This results in the correct route table and it works beautifully:

Kernel IP routing table

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface

default         192.168.5.1     0.0.0.0         UG    10     0        0 eth0.2

100.80.0.0      100.96.X.Y      255.240.0.0     UG    1      0        0 tun0

100.96.0.0      100.96.X.Y      255.224.0.0     UG    1      0        0 tun0

100.96.X.Z      *               255.255.255.240 U     0      0        0 tun0

172.16.1.0      *               255.255.255.0   U     0      0        0 br-lan

192.168.5.0     *               255.255.255.0   U     10     0        0 eth0.2

192.168.9.0     *               255.255.255.0   U     0      0        0 br-guest

Monday 21 February 2022

Board Bring-Up Recipe

Board "bring-up" is the first time you apply power to a newly designed and manufactured PCB. It's something I've been doing for nearly 30 years now and is probably the most intense and rewarding part of my job.

Ground Rules

Work as a team: avoid blame. You'll need as a minimum a hardware engineer (probably the PCB designer) and a software engineer (probably the software lead engineer). Keep the team small and focused. Clear your schedule, get plenty of coffee: this may be a long day/night/nights!

Prepare

Make a minimal version of software for your first run: leave out as many bells and whistles as possible. A flashing light "blinky" demo or "Hello, World" on a terminal is perfect.

Get hold of quite a few PCBs: you're likely to fry the first ones and people will want to start using the others once they're running. However many you get you'll be using them all soon and will probably want more.

It won't work first time

My experience is that when you first apply power to a board it doesn't work. Use as low a current limit as possible and DON'T PANIC. Work methodically through the PCB finding out why it's not responding. Check components are placed the correct way around. Check transmit/receive lines are connected as you expect. Check your software doesn't depend on some component (e.g. a crystal or a pull-up resistor) that is present on the evaluation board but absent in the custom design.

You realise the problem

Generally something has gone wrong, often a misunderstanding between the hardware and software teams. DON'T PANIC. Work through the problem without blame: you're trying to achieve the same goal here.

You realise the solution

Don't be afraid to make a bit of a mess here. Maybe a nasty software hack, maybe hardware, probably both. The aim is to prove something works then pretty it up later. Progress rather than perfection and keep your eye on the goal rather than how you achieve it.

It's working!

Make detailed notes of what you had to do to make it work. Ideally save a software branch of your hacks to refer to later when you do it "properly". Everything you can should be recorded so that theoretically if you go off sick the next day another engineer can pick-up where you left off. You're pretty high on caffeine and adrenaline right now and you won't remember those details in the morning.

Celebrate

Go out for a beer or just watch the sunset (or sunrise!) with a last coffee and savour the moment. You climbed an intellectual mountain and it's time to take a break and enjoy the view.

Wash-up

Now is the time to have that meeting: bring management up-to-speed with what happened and an estimate of the effort to make a working product. Take time to show the junior members of the team what you did and why: they'll be doing this someday and probably sooner than they think.

Keep improving

Now that you have a custom board you can realise performance approaching the promises in the component datasheets. They always lie a bit economical with the truth so don't expect to achieve exactly the same numbers but if you're significantly out then this indicates that there are still improvements to be made. Don't tolerate higher current consumption than expected: this usually means something isn't working right.

Friday 4 February 2022

Passwords considered harmful

A client of mine has an extensive Cyber Security department.

Every 90 days they insist that I change my memorable password to another memorable password and then I spend the rest of the morning typing that new memorable password into various machines. They also use 2-stage authentication but as I'm asked to re-authenticate myself every few days I'm quite used to a random popup appearing and having to re-enter my credentials. I confess I don't check too carefully where this popup comes from; often it's difficult to tell anyway.

I like to think I run a fairly tight ship from a Cyber Security perspective too.

  • I use a hardened and regularly patched OpenWRT firewall (runs on an old wifi access point)
  • I encrypt the drives of machines that leave my office
  • I use ECDSA-256 to login to remote machines

The only time I enter a password is when I'm starting my laptop. The encrypted drive has private ECDSA keys which it uses to authenticate with the rest of the network and most of the Internet. In Cyber Security terms my password is the "root of trust" and thus only used sparingly.

If a popup appeared on my own desktop asking for my ECDSA private key I'm not sure where I'd start (copy and paste?) but I'd certainly know something funny is going on: that key never leaves the machine its assigned to - and yes different machines get different keys.

So my point? Please consider reducing your use of passwords: the more you use them the less secure they get.

https://www.ncsc.gov.uk/collection/passwords/updating-your-approach


Tuesday 2 June 2020

GDB hosted printf() for AVR8

Atmel Studio 7.0 has a rather nice AVR8 hardware simulator but they don't support a debug channel so it can be hard to figure out what your code is doing.

Happily, their simulator supports GDB (their whole toolchain is GNU) and there's a feature of GDB that can be used to provide a debug channel without interference with the simulator.

First build the obligatory "Hello, World!" program

debug.c:
// Note the optimiser will remove this if it's not compiled independently
void dputs(const char* sz)
{}

main.c:
extern void dputs(const char*);
void main()
{
    dputs("Hello, World!");
}

Then start the simulator with thanks to Morten
atbackend.exe /avr8-gdb-ports=12345

Then start gdb attached to the simulator
avr-gdb.exe -iex "target remote :12345" \
            -ex "monitor tool simulator" \
            -ex "monitor device ATmega640" \

A few commands sets up the target and debug channel
load HELLOWORLD.ELF
file HELLOWORLD.ELF
monitor reset
dprintf dputs,"%s",_
continue

And hey presto!


What happened there? Well from the simulator's point of view it was an empty function call that took a couple of clock cycles. However, GDB inserted a breakpoint that halts the simulator, including simulated peripherals, and read some RAM from the simulation before allowing it to continue.

There's no particular reason why this wouldn't work over JTAG too. However, be aware that the clock only stops for the microprocessor; other peripherals and in particular off-chip peripherals will notice the lag incurred by GDB stopping the chip, reading the RAM, starting the chip again.

Rigol DS1000E series 'scope and Windows 10

Rigol have sadly been a bit lax in their support of this brilliant little 'scope and their elderly Ultra Scope GUI (which was quite good) doesn't work on Windows 10 x64.

However, you can use the open source tool PulseView which has a rigol-ds driver! The easiest way to make this work is Zadig which lets you install WinUSB for arbitrary USB devices (particularly ones without signed .INF or .CAT files)....

  1. Plug in your scope. Windows won't find a driver.
  2. Install Zadig, select your scope from the pull-down and pick WinUSB (takes a few seconds)
  3. Install PulseView - mine picked up the scope automatically

Admittedly it's not as fancy as the Rigol GUI (which really did look like a mock-up of your scope on screen) but it does the job and lets you screen share your 'scope when required.