The Quest for an AVR simulator

Do you really need a dragon ?

54_6Just a word on words…

In this post, I will often use the term simulator, as does most litterature on this topic, where the term emulator, In My Humble Opinion, should rather be used. It is because we are at a border, between pure software emulation, and electrical simulation of a board. To pass through this border, the boolean state of some bit should become a modelized electrical state of a pin.

But, AVR simulator are mainly “simulating” boolean states, using a discrete time model…

On this point, I apologize in advance for any lexical inconvience.

The concerns

When I started my try to implement a thread scheduler for 8bit AVR, and for another project after that, it quickly became an essential urge to setup a step-by-step debugger, and rather using an emulation tool :

Step-by-step Debugger :

  1. to grant fine control on program execution flow, dumping device state (memory and registers),

Emulator :

  1. to avoid flashing many times physical device with buggy-work-in-progess code,
  2. spare money of buying an AVR dragon (which allows OnChip Debugging of a physical device using avr-gdb),
  3. Use a computer, nothing more needed (AVR thread scheduling, at this step, is still at a purely theorical stage — no need to imply physical devices for now).

 

Browsing for it on the Web

Here is a merely complete state of the art on this topic. Ask on freenode’s #avr, if you want, I or any guy there should answer the same…

  1. Atmel Studio : it’s a proprietary tool, published by Atmel. It includes a simulator, and a debugger. The customised GUI allows to display any register or memory map, where each modified byte is highlighted. Sadly, it is runs only under windows, since build on Visual Studio. A shame, knowing that underling compiling toolchain is GCC anyway…
  2. SimulAVR : an OSS tool written in C++, and packaged as a simulator executable, but providing a really awesome framework.
    • Tcl and Python bindings are available.
    • Repository is available on github (I appreciated to be able to fork it in one click to start to integrate one or two modifs/fixes in my own repo),
    • It is designed to be interfaced with avr-gdb. ;
    • It allows dumping trace of the execution (as a sequencial log of instruction), but also VCD files usable with gtkwave,
    • For the record, Arch user, PKGBUILD is not in the AUR, but easily foundable on the web.
  3. simavr : Another awesome OSS project, written in C. It provides mainly the same features that simulAVR, but :

    • It comes with a collection of directives defined as macro to specify simulation parameters directly into an ELF custom section,
    • It is written in C. The code is awesomly clean,
    • It is integrated in Arch Linux as a Community package.
  4. AVRora : Crossed this one during my quest, but I don’t like this project : it is stalled since 12/2008, it seems to be wrtten in Java. But as existing, it is worth to quoted, and maybe to play with a bit.

 

 

 

Advertisements

Raspberry Pi : Root NFS with Arch Linux

Abstract : How-to setup a Raspberry Pi and a x86 host, both installed with Arch Linux, to make the Pi to boot on a filesystem stored on the host, and manage this filesystem (package installations/upgrades) from the host, taking advantage of its “horse” power, and saving writes to the SD card — but not only.

Introduction

Context

Embedded devices use flash memory to store the linux kernel and the root filesystem they use to boot. One concern when developping an embedded system, is that you should avoid to burn the device’s flash memory each time you want to test a new code : first to improve productivity, second to avoid to “burn out” your device’s flash memory.

The Raspberry Pi is a bit specific since it uses removable micro-SD card as a flash memory device. Since it is easily replaceable, the write cycle limit of the flash memory is far less a concern than on a R.Pi. I think this is not a reason to waste write cycles, and anyway, the productivity argument remains.

Objectives

First, we want to export our root filesytem onto an NFS mount.

Secondly we want to manage our root filesystem using the Arch Linux standard tools : pacman for officially supported packages and Arch Building System (PKGBUILD / makepkg) for other packages (either found AS IS in the AUR, and or written/modified by ourselves).

 

NFS Boot

Prerequisites

The Host is an x86 machine running an Arch Linux distribution. It can be either natively or in a VM, and it should work with any Arch derivativate, like Manjaro.

Obviously, your Raspberry Pi should be installed with Arch linux ARM (or a derivative).

Create the NFS-shared root FileSystem (from an already booting SD card)

If not done yet, install an NFS server on the Host, and enable/start it.

To copy the root filesystem, the easiest way is to mount physically the SD card into the host, and mount it :

create an hosting directory for the root FS (let it  be /srv/nfs/R.Pi) :

$ sudo mkdir -p /srv/nfs/R.Pi && sudo mount /dev/mmcblk0p2 /tmp/RPI

Copy the root filesystem content into the NFS share (-a flag for ‘archive’ copy just like tar):

$ cp -a /tmp/RPI /srv/nfs/R.Pi

Then add it to the NFS exported directories by adding following line to /etc/exports

/srv/nfs/R.Pi *(rw,sync,no_root_squash,no_subtree_check)

A word on the options :

  • * means any client can connect. You can white-list authorized clients here.
  • rw : I want a Read/Write root filesystem when I boot from NFS, since it will be for development purposes. It is unlikely, but you should want to set ro (a use case could be a Pi using a tiny — or maybe damaged — SD for boot only, on a network that has a NAS that host other partitions…)
  • sync : it is a default option, probably only to avoid a warning when the default changed from async to sync. Quoting the man page exports (5) : “To help make system administrators aware of this change, exportfs will issue a warning if neither sync nor async is specified.”
  • no_root_squash : linked to rw option, once again let’s state exports (5) man page :
  • no_subtree_check : probably superfluous (this option is the default, according to the man page). TODO : Try without and EDIT

Finally restart the nfs-server unit.

Setup the PI kernel command line

Next step is to adjust kernel command line parameters : mount boot partition of the Pi (to edit cmdline):

$ sudo umount /tmp/RPI
$ sudo mount /dev/mmcblk0p1 /tmp/RPI

First make some copies of your cmdline :

  • cmdline.txt.ORIG : absolute reference (optional, but ensure against any unwanted edit of cmdline.txt.flash).
  • cmdline.txt.flash : base reference file for flash boot. Keep unchanged at first
  • cmdline.txt.NFS : We’ll edit it to boot on NFS share.

The two cmdlines :

Flash :

root=/dev/mmcblk0p2 rw rootwait console=ttyAMA0,115200 console=tty1 selinux=0 plymouth.enable=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 kgdboc=ttyAMA0,115200 elevator=noop

NFS :

root=/dev/nfs nfsroot=192.168.0.11:/srv/nfs/R.Pi/,tcp,vers=3 rw rootwait console=ttyAMA0,115200 console=tty1 selinux=0 plymouth.enable=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 kgdboc=ttyAMA0,115200 elevator=noop

Command line diff summary :

  • root= parameters differs from /dev/mmcblk0p2 to /dev/nfs
  • Additional nfsroot=192.168.0.11:/srv/nfs/R.Pi/,tcp,vers=3 to specify where is the root NFS. Remember that HOST_IP=192.168.0.11
  • Note that I use NFS parameter “vers=3” : it is probably superfluous, and a relicate of experimentation I did about problem I got at work (my target board was still booting nfs version 2 by default, since using a kernel 2.6, while my up-to-date archlinux host nfs-utils deprecated version 2, so I had to force vers=3. TODO : try without and edit)
  • ip=dhcp parameter is “mandatory” : not that dhcp is mandatory (static IP is an option), but network must be UP before the kernel attempt to mount the root NFS. I guess one could boot using wifi key as long as required modules are statically linked, or loadables without root fs mounted yet (initramfs ?).
  • rootfstype=nfs… Heh, I don’t know why it should be specified, and neither test without, but does not eat much bread, and seems to be the obvious… TODO : Study it and edit

Now the Pi should be able to boot.

Troubleshooting

I used the following procedure to debug the Pi NFS access to the Host (set all debug flags) :

$ sudo rpcdebug -m rpc -s all && sudo rpcdebug -m nfsd -s all && sudo journalctl -fl

NOTE that sudoing the journalctl call is quite important, regular users don’t see logs for system daemons like nfs-server

When debugging acheived, switch off logging to the journal, clearing the debug flags :

$ sudo rpcdebug -m rpc -c all && sudo rpcdebug -m nfsd -c all

Package Management from Host

Now that we have a system that boot from the Pi on the host root FS (while the kernel is still hosted on SD card), we may want to take advantage of the Host to manage (even when the Pi is offline) the root filesystem, for package upgrade, which is the concern here, but also for other purposes, like file-system analysis for system hardeninng, etc.

pacman.pi

The solution I have settled on my system is a script-command, pacman.pi, hosted is ~/bin (my $PATH includes it). Here is the script :

#/bin/bash

sudo mkdir -p /tmp/pacman.pi.cache
sudo mount --bind $PI_ROOT/etc/pacman.d/ /etc/pacman.d/
sudo pacman -v --debug -r $PI_ROOT --config $PI_ROOT/etc/pacman.conf --cachedir /tmp/pacman.pi.cache --logfile /var/log/pacman.pi.log $*
sudo umount /etc/pacman.d/

Obviously, $PI_ROOT environment variable is to be set conviniently in root user default environment, hereit is to be set with “/srv/nfs/R.Pi”).

Binding /etc/pacman.d/ to the RPi root fs is the workaround I found to get the mirror working for synchronizing database, no option seems to be provided so far… Maybe a potential contribution to the Arch !

NOTE that specifying the pi root FS DOES NOT implies using etc/pacman.conf and databases located inside it. Actually it is a big mess up ; and  -v and –debug option are here in order to check that pacman reads the right config file, databases, etc.

Nevertheless, there are many wins here :

  • The cache for packages is on the host (save writes / gain in speed),
  • The root filesystem too (but it could be an NFS export from the Pi, either…),
  • Avoid logs in the Pi.. But let’s speak about /var a bit…

 When /var is rather a mounted partition…

Avoiding to have /var on the root partition is helpful to save writes to the flash since it is made for logs, caches, and so on. Furthermore, if you want the base root filesystem to be read-only (for security), mounting /var on some writable partition allows logging anyway.

In all cases, if /var is a separate partition, it will be needed to mount or bind the /var of the Pi into $PI_ROOT/var of the host.

 

 

 

Happy PI day

Yesterday was the 3/14 (14th of March), the PI day !!

Here a little graphical composition to celebrate it (even if i’am a bit late) :

pi_day

I probably infrige some copyright, but I don’t give a shit, let’s see at the trial !

Restore a LiPo battery

Abstract : How-to “hack” a battery charger to achieve the initial charge (if not done, for instance, on a brand new battery newly delivered from China).

Introduction

I recently ordered 2 « Litium Polymer » batteries from china.

model

My Lipo model

Both are 3S / 3300mAh…

For the record : it is too big to “fit in” a standard ZMR 250 frame build… 😯. It can be bound on the top, but will fill this stage, preventing other mounts…

Then, I will have to find out a way to “hack” the frame  with an additional piece, to make it fit UNDER the first stage (but not on the ground of the frame)… Which is an exciting challenge. 😆 Ideally, more the center of the gravity is inside the plan defined by the four motors, easier will be the control (further if done by learning, natural stability will avoid random crashes).

I formerly bougth an IMax B6mini… Actually a genuine one (checked the hologram S/N on skyrc website). For the price it was a very good deal !

1 – Unboxing

So when received the batteries I tested them immediately using the charger, but also in-flight voltage monitors (there is a bunch of clones on the market, mine are 1-8S LiPo tester with buzzers and a LCD dispay, which beeps when individual cell voltage falls below a preset limit, see illustration below).

Lipo-tester-3

One of the LiPo tester implementation — many clones are available

All measures were converging, the diagnostic made no doubt : one of my battery was under-charged (overall under 7.5V, all cells under 2.5V), where the storage value should be around 11.2V – 11.4V  (3.8V/cell).

The charger was OK to start a charge cycle on the “good battery” but not on the “bad one”. By the time I was not able to understand why…

2 – The time of questions

Nevertheless, the problem at that point was to find out if the battery was completly broken, or if something gone wrong in the process (like missing an initial charge after manufacturing ?)

I wrote to the vendor, but I found out chineese guy with a poor english level (which was quite bad at first, and but got better, upto medium, after i uploaded photos as proof -_-‘ ).

On his side he seemed not fully surprized nor embarasted, but proposed a silly deal : me to bring it to repair and he to pay for the fees. Why it is “silly” : first, the cost of the repair could reach easily the price of the battery, second, I am not aware that we have any vendor with such activity here in France… But maybe i didn’t search enough, maybe some toy/hobby vendors could help. Anyway, for a 18€ battery, I suppose the cost would be relatively prohibitive.

I decided that, if a random vendor would be able to achieve a charge, I should be able to do the same, armed with an engineering degree, my charger and the Internet. And I was right !

I found out that :

  • First, as low as the voltage is dropped on a battery, you can still theorically charge it. The biggest concern is that internal resistance increase exponentially as voltage decrease.  If one do a charge with high current on a battery with high internal resistance, it wil make the battery heat a lot. For a LiPo, it means (probably) setting it on fire.
  • Chargers have a cut-off voltage for battery recharge : it allows more security, as chargers won’t allow to charge an under-charged battery and set it on fire dumbly. It a good point, but I needed to breakthrough/workaround this, as the cut-off voltage is typically 2.5V.

3 – The Time for the Solution

The solution came from a very good blog on RC toys, and this article (sorry for original author’s site, it was easier to find it again on Instructables).

You just have to set a Ni-MH or any other charge program that dont feature this cut-off. Program it with minimum current as possible to limit the battery heating and go.

charginh_low

initial charge : 0.1 A under Nickel – Metal Hydride recharge program / minimal current

I just let it charge something like 15/20 minutes. At first, the charger limited the current to the battery so it displayed 0.0A, but the voltage was increasing quickly on the display.

After a while the current reach the driving value (0.1A) and voltage increased slower at this point… Upto 9V, which was the program threshold.

after_1_charge

Volatge after initial charge : it’s quite better !

At this point it was easy to go throught config menu and to start a LiPo cycle “STOrage” charge, since all cell are above 2.5V…

finishing

Normal LiPo 3S 1A storage charge

And that was it ! Now the battery is stored at correct voltage storage level in LiPo gard sack ;°)

Have fun with LiPos, and take care of them… And of you and your stuff.

PS : No heat was detected by touching the battery with fingers during the process. Just feeling like it was still at room temperature : 18°C.

 Conclusion

I will never find out if my battery was “discharged” or “never charged”, but my belief is going to the latter.

Scheduling threads on 8bit AVR – Introducing myself

Who I am, where I am in AVR world.

I’m an Arduino enthusiast : it made some of my week ends 🙂

This way I learned about AVR 8bit architecture.
Soon I guessed Arduino IDE was way too limitative. then, I seeked a way to break free from the IDE. Then, I found out that Atmel toolchain was based on GCC, AVR flavoured ; so could theorically compile any ASM, C or C++ project using avr-gcc.

By that time, in Arduino IDE, it was hard to use two different lib in one single sketche. But using GCC and Make, I could wipe out those limitations, restoring a clean tree for project sources, and mainly reusable libs — Thanks to :  Arduino Makefile (on github).

Note that Arduino-Makefile is able to compile pure avr-libc projects ! Nowadays, I use it to make && make upload any of my projects, either using Arduino lib parts, or not… (I’m used to link against Serial class for debugging purpose, even if i know some ways to work without, like coding some putc() enabling printf(), but… I’m lazy on this topic).

After some toy-projects with Aduino libs, I had a dive into the Atmel datasheet. I gave born to my first serious theorical appraoch of AVR:

could we even schedule threads on Arduinos ?

Once… upon a time, I was attending a conference about Linux Xenomai (for short it deals with hard real-time constraints). Stories about real-time systems often involve Big Bad Watchdogs. and  Daemonic Timers… Timers are used to preempt some task and switch to another. Then, I was day dreaming… : “An AVR like atmega328 on an Arduino has timers and linked interrupts ; why the f*** does it not have threads implemented ?

I tried to write out an implementation : it attempt to copy CPU state and the stack into a know location, and then smash the stack and CPU state with previous saved (or manually cooked — for initialization) data. The trick can make think of the buffer overflow attack, since we’re replacing return address in the stack. But here the address of return pointer changes with new task’s stack size ! Here, hopefully, and despite buffer overflow attack, we are are free to set SP register to point updated return address.

Sadly, it does not work : it manages to switch 3 times two simple tasks :

  • one is a thread function, other being the main loop ; writing to an I/O port, in this source version, a special port used as stdout with the simulavr emulator),
  • the other being the “main” loop.

…but the last (I)RET drive any simulator I tried crazy (then, I never tried on hardware). I guess that, somewhen, I smash the stack (or a stored copy later restored).

I did not go further in debug because i don’t believe anymore in task/thread scheduling on AVR… at least following this way.

Maybe, it could be used, with caution :

  • in a purely pedagogic context, or,
  • very conscientiously, with a low switch context frequency and low growing stacks per thread.

My first conclusion was… AVR is not for threads…

… As I implemented it :

  • the first problem is memory amount ; switch context imply to copy the Stack. Dedicated memory to thread stacks decrease available memory to the application ;
  • the second is about CPU consumption : not only there is a contant overhead, implied by saving/restoring a constant number of state registers, but, futhermore, we have to save and restore the stack, which size is variable by nature.
  • urgent events are to be hold and processed by ISR sub-routines. Not by a thread context with (potentially very high) latency.

In conclusion, this implies that 8bit AVR threads (as I am implementing them) remains a kind of “hi-jacking” of the chip architecture which is clearly not dedicated to thread context switching.

A typical “Arduino” application using such a library to interlace applicative threads execution is not likely to work properly : GCC is used to compile C/C++ with extensive use of the stack… It is true, at least, on a genuine « Arduino Uno R3 » and it’s atmega328, with 2K SRAM embeded only.

 A new Hope…

In a galaxy far far away…

I was hopeless about task scheduling (not using co-routines, they are great, but no real “tasks”) when I heard about FreeRTOS, which implements on real task concept.

If I need task scheduling for any reason, that jusify ISR are not enough, I would use FreeRTOS.

Other  initiative …

 

 

 

Grand Opening

I’m SKZ 81, a french embeded software developper.

I created this blog as a technical one, mainly for sharing my hobby experimentations. My main concern are currently drones (quadcopters, purely autonomous ; or FirstPersonView piloted), and related to, AVR microcontrollers.

Nevertheless, it is not limitative : I also have some personal projects involving web technologies like Django, and may like to share about them 🙂

In short, this post is just to say :

Hello World !