March 25, 2018

NetBSD features you may have missed

It's no secret NetBSD is the smallest of the three contemporary modern BSDs (FreeBSD, OpenBSD, NetBSD, intentionally ignoring PC-BSD/TrueOS). Many don't give NetBSD any more thought than 'oh its the one that can run on a toaster' (which is true as long as it has a MMU :)

the netbsd poster-child toaster-child (Full article here )

There are some interesting features that are useful on desktops as well as embedded that deserve being mentioned. I list some of the features that caught my eye in no particular order. Also in no way are these unique to NetBSD (well mostly), but some may surprise you.

Lua kernel / ring0 code

I'm not sure how popular it is or if its really used, but it is a possibility to write kernel modules in Lua. This is pretty darn cool and lua support in the kernel is the fruits of a previous Google Summer of Code (GSoC) project.

For Lua to work, you need to load the lua and lua sytem modules:

# modload lua
# modload luasystm

Then you can create a Lua state and load a script like so:

# luactl create state1
# luactl require state1 systm
# luactl load state1 ./luahello.lua

You can find full examples here Def checkout intro(9lua) too.

CGD disk/partition encryption

CGD (Cryptographic device driver) lets you encrypt disks at an entire disk or partition level. Of course, this is nothing new, but it has more flexibility for key sizes and available ciphers versus, eg, OpenBSD. This may no longer be true

rump kernel drivers in userspace

juicy rump

NetBSD Rump kernels offer many benefits, of particular interest is being able to compile kernel drivers and test it in seconds without using a VM. In simplified terms, it is basically the various drivers that usually live in kernel space, but running as separate entities in the rump kernel userspace.

Rump kernels are not an operating system specific concept, for background see What is a rump kernel? NetBSD 'anykernel' is (was?) the first implementation of a usable rump kernel though. It has a funny name to boot

pkgsrc can do some cool stuff

I have to admit I'm just starting to dip my toes in pkgsrc. It's a solid package manager, downloading and compiling sources for you and managing deps, as you would expect of a package manager in 2018. It has some lesser known auxiliary features:

  • Portable, you can use it on other BSDs as well as Linux!
  • Built in tools for auditing vulnerable software with pkg_admin audit
  • It can check licenses if you care about that. Eg warn/disable installing XYZ license software.

Veriexec - Ring0 binary/file/data verification

In layman terms, veriexec compares binaries and files to a pre-configured whitelist of hashes and refuses to run any that diverge. While this would require a bit of setup (and would be annoying for casual daily desktop use), you could really lock down a machine with this setup that would be resilient to even root privilege escalations.

With the state of MD5 and SHA1 hashes being worthless for integrity and having vulnerabilities and proof of collision respectively, it supports SHA256, SHA384, SHA512, and RMD160 hashing. There are a few levels of strictness which can make the machine dynamically learn or report in an IDS style of operation as well.

Sane config/directory hierarchies and other non-technical things

This is not so much a feature as my personal preferences, but on NetBSD you get things like a sane, centralized rc.d startup system. No 6 runlevels, no systemd, no having to rifle around to find defaults. /etc/rc.d after looking at /etc/defaults/rc.conf and be done with it.

Additionally, third party stuff always ends up in /usr/pkg and their configs go in /usr/pkg/etc. While GNU/Linux isnt awful, I am annoyed switching distros and having no idea where things go, install to, overwrite, etc.

Being able to install an entire system (with X) using an installer under 350mb is unheard of in this day and age too. I'm pretty sure the Nvidia drivers are bigger than that now.

March 22, 2018

NetBSD docs tarpits and kernel compiling

While my VM setup is the way to go I eventually got NetBSD-current going on the spare machines I previously mentioned. It would only be fair to mention that when NetBSD 8 comes out, it will work much better on amd64 systems.

With that said, I've been trucking along to basic usage and compiling the system. For package management, I've been just grabbing binary packages as needed with pkgin, not really interested in trying to compile big stuff with pkgsource yet.

As a beginner, I found the package management scenario presented in a burdened way. The flexibility of (having to) picking your package trees, binary versus sources, pkgsource config, pulling in CVS etc increases the cognitive load. I just needed tmux! So I only do basic pkgin usage for now.

Scan mailing lists

It's worth mentioning, even if you have no intention of running NetBSD-current or getting into the code, if you run into issues, visually scan or search the mailing list archives, someone else likely has already griped about your issue if its even remotely common.

There are actually two approaches to this, you can search GNATS, but its kinda slow to query, and you kind of have to know what you're looking for in issues. Or just check netbsd-bugs and netbsd-users mailing lists for a decent litmus-test.

netbsd-bugs

NetBSD-bugs will be slightly exaggerated noise with GNATS auto replies, but if you're having an issue it will likely be beaten to death by faithful testers here.

Moving on to grabbing tarballs of sources (sets as it were) and compiling the kernel, I googled and ended up at the NetBSD wikis for various things, eg:

I plodded through and things immediately went very badly and in hindsight I should have checked sooner..

oops

long story short: DO NOT USE THE WIKI (for stuff in the guide). It's basically redundant compared to the guide, and has largely fallen to the wayside. I think the guide is in tree next to sources and was mostly up to date.

I still ran into minor issues with the current release and reported them. But overall there was no show stoppers for the kernel compiling section of the guide.

System and kernel compiling

One minor issue I had was the build.sh instructions not working as prescribed. But looking at the error output, it was easy to figure out. For people less weathered it might not have been trivial to know to create an 'obj' folder or specify it and run as -U for non-root users. But then again NetBSD demands a bit of knowledge up front. For example (this is after you have dong config <cfgfile>, GENERIC on amd64 here), here's how I got going. Change -j9 to number of cores in your machine +/- 1 for best results. There is a useful file, BUILDING sitting in /usr/src once you have unzipped sets that has full explanations and useful examples. Alternatively the 'building the kernel manually' guide works fine still. I'm interested in using the excellent cross compiling capabilities of build.sh though.

$ cd /usr/src
$ mkdir obj
$ ./build.sh -U -u -O obj -j9 tools

(this will take a while, gcc is a bear of a compile)

$ ./build.sh -U -u -O obj -j9 kernel=GENERIC

--- netbsd ---
#      link  GENERIC/netbsd
/usr/src/obj/tooldir.NetBSD-7.1.2-amd64/bin/x86_64--netbsd-ld -Map netbsd.map --cref -T /usr/src/sys/arch/amd64/conf/kern.ldscript -Ttext 0xffffffff80100000 -e start -z max-page-size=0x100000 -X -o netbsd ${SYSTEM_OBJ} ${EXTRA_OBJ} vers.o
NetBSD 7.1.2 (GENERIC) #1: Fri Mar 23 13:51:54 MDT 2018
   text    data     bss     dec     hex filename
14223597         654556  593920 15472073         ec15c9 netbsd
===> Kernels built from GENERIC:
  /usr/src/obj/sys/arch/amd64/compile/GENERIC/netbsd
===> build.sh ended:      Fri Mar 23 13:51:57 MDT 2018
===> Summary of results:
         build.sh command:    ./build.sh -U -O obj -j9 kernel=GENERIC
         build.sh started:    Fri Mar 23 13:49:31 MDT 2018
         NetBSD version:      7.1.2
         MACHINE:             amd64
         MACHINE_ARCH:        x86_64
         Build platform:      NetBSD 7.1.2 amd64
         HOST_SH:             /bin/sh
         MAKECONF file:       /etc/mk.conf (File not found)
         TOOLDIR path:        /usr/src/obj/tooldir.NetBSD-7.1.2-amd64
         DESTDIR path:        /usr/src/obj/destdir.amd64
         RELEASEDIR path:     /usr/src/obj/releasedir
         Updated makewrapper: /usr/src/obj/tooldir.NetBSD-7.1.2-amd64/bin/nbmake-amd64
         Building kernel without building new tools
         Building kernel:     GENERIC
         Build directory:     /usr/src/obj/sys/arch/amd64/compile/GENERIC
         Kernels built from GENERIC:
          /usr/src/obj/sys/arch/amd64/compile/GENERIC/netbsd
         build.sh ended:      Fri Mar 23 13:51:57 MDT 2018
===> .

Finally, I can start digging in. This compile time certainly helps! Modern computing rules! This VM is not even on a SSD. I'm hopeful if I moved it and gave it a few more cores it could build in 60 seconds. A full release build of tools, userland and X across 16 cores probably still takes 10s of minutes though.

March 20, 2018

Installing NetBSD: amd64 pain ahoy

As covered in a previous post, I decided to deep dive a more UNIX'y operating system, ultimately NetBSD. And so it begins

When I want to learn something new, I go all-in. Diving into NetBSD, I wanted to go a 'total immersion' route, mostly because I'm fortunate enough to have lots of spare machines around I could test on and thought it would be best to use on real hardware. And focus on that machine with no distractions, just man pages like times past.

I also went all-in on coke cherry zero at my battlestation as you will see. This stuff is like nectar from the sugar free gods.

slurp

I picked NetBSD because I wanted a challenge and I wasn't exactly expecting smooth sailing but so far I've got challenges in all the places I was not expecting!

Sometimes I get irrationally mad or frustrated with things when in a hurry to get started, so this is more me aligning reality with expectations and documenting my progress.

Let me say this is not an attack on NetBSD, I understand that it's a smaller project compared to FreeBSD and OpenBSD and not even to mention GNU/Linux. It's not like companies are paying people to hack out drives for NetBSD.

Hardware

First, here's some of the hardware I've seriously tried (and remembered to write stuff down on) so far:

  • Dell Vostro 3500 laptop from 2011
  • i5 3570k Desktop with ancient 2008 intel sata SSD (Spoilers!)

I decided to start with the latest regular, non-development release NetBSD 7.1.2, the newest release (5 days old at time of writing)

Getting diagnostics during installation

But first an aside: know how to dig info off a machine during installation!

This may not be obvious for newer experimenters like myself, but it didn't occur to me how difficult it would be to grab outputs of dmesg off a machine during installation to share for help.

The easiest way is to have an USB stick formatted as FAT and insert it after dropping to shell from installer menu (if you can). I was booting off the installation USB stick, in that case I needed two. Do not have both plugged in when you boot, just installation media.

You can boot the install media and immediately bail to shell once you see the menu. Once there you can mount the USB stick like so

# mkdir /mnt/usbstick2

(plugin usb stick, at this point you might see in console, or:)

# dmesg

... check the latest message about mounting umass on device /dev/sd1 or such. Mine looked like this

umass1 at uhub2 port 7 configuration 1 interface 0
umass1: USB2.0 Flash Disk, rev 2.00/0.00, addr 5
umass1: using SCSI over Bulk-Only
scsibus1 at umass1: 2 targets, 1 lun per target
sd1 at scsibus1 target 0 lun 0: <USB2.0, Flash Disk, 2.60> disk removable
sd1: fabricating a geometry
sd1: 961 MB, 961 cyl, 64 head, 32 sec, 512 bytes/sect x 1968128 sectors
sd1: fabricating a geometry
sd1: mbr partition exceeds disk size

Now we know the device is 'sd1', so the first partition would be `sd1a':

# mount_msdos /dev/sd1a /mnt/usbstick2
# dmesg > /mnt/usbstick2/dmesg.txt
# sync (or you can do umount /dev/sd1a)

If you're coming from a gnu/linux background like me, take heed and do not typo it sda1 a million times, because the backspace key will NOT work correctly and you'll go mad.

Importantly, dont forget the sync or umount command. If you rip out the USB stick before hand, the file could be not there, or likely, present but empty.

Installation - laptop

Starting with the laptop, this one was very frustrating to figure out at first due to some red herring level issues.

In an effort to save anyone else chasing this, I basically saw this during boot of the installer:

# root device:

There was two steps to this

  1. Set hard drive mode from AHCI to IDE :(
  2. Boot from a cdrom instead of of USB stick

For reasons unclear to me booting from cdrom worked fine and successfully installed without issue. HOWEVER, booting the new installation ran into the same issue, even with the hard drive detected in either mode (IDE/AHCI), it fails to open. I never got past this and gave up on the laptop:

root device: wd0a
..
vfs_mountroot: can't open root device
cannot mount root, error = 6

Heres a lame picture to follow par for the course

barf

At this point I decided to move to the desktop, considering laptop no go. RIP

Installation - desktop

I booted off USB stick for desktop, but ran into same issue. It wouldnt detect hard drive in AHCI mode, but it did report an error. The error in dmesg which seemed to indicate hardware failure:

ahcisata0 channel 0: clearing WDCTL_RST failed for drive 0

I was very skeptical because this machine ran windows 10, Linux, other BSDs without issue right before this. I clicked it over to 'IDE' mode instead and it detected drive and started the installer. Smooth sailing from here right?

soda panic

I got a panic during auto configuration of a wifi card (which, by the way it detected no problem, go figure). I tried to reproduce it to report in GNATS but had no luck, so I just started over and skipped network configuration during installation.

At this point I had a working NetBSD 7.1.2 installation on the desktop. So at this point, I have NetBSD booting but unconfigured. I could technically move to configuration and usage at this point if I wanted. On fast hardware to boot!

Run current sources to test things

Bringing up some of the panics and really obnoxious issues, I looked into reporting/debugging them. I was told to try again on 'current' in NetBSD parlance, working sources. Which of course, is a good idea in case it has been fixed, and to ensure it is reproducible.

So I grabbed a recent snapshot of NetBSD 8-current and tried that installer. Mostly the same story there, no working AHCI.

One big thing I want to capture somewhere is that the installer failed to run due to some drivers. You'll get a panic something like this booting current:

boot growing soda panic2

After trying this tip from IRC:

14:02:38 <medfly_> you can drop to boot prompt
14:02:41 <medfly_> userconf disable i915*
14:02:44 <medfly_> userconf disable radeondrm*
14:02:47 <medfly_> userconf disable nouveau*
14:02:48 <medfly_> boot

Which by the way, the IRC channel (#NetBSD on freenode) had a lot of very patient and helpful people. The machine has an nvidia 780Ti so i try the last one, userconf disable nouveau* and boot. Bam Current installer off to the races!

I was able to install current at this point. One thing I need to figure out is how to make disabling nouveau permanent because I have to drop to boot prompt every reboot to do so. I could now use the machine. I'll probably just ssh into it moving forward.

Moving forward

After doing some cross-checking, the old intel SSD in the desktop is in fact actually starting to fail just now! This is no surprise considering its from 2008. With that in mind, I'll consider it non usable even tho it's running current doing not much right now.

I decided to just learn how to use the system in VM on my main desktop in the meantime. NetBSD mostly works great on the emulated hardware, and my primary desktop is an extremely fast machine which can build NetBSD in minutes. My beefy desktop has a 4k monitor, if you use it on 4k or similar make sure to set display scaling in virtualbox or else you will go blind:

display scaling

hello world

Eventually, I'll move some stuff around and put a good hard drive in the spare desktop and SSH into it. Now I can dig into usage, maybe run and build some software on it for starters.

Takeaway

NetBSD is very likely going to be difficult to install. Don't think amd64 will be smooth sailing just because its the comptemporary hardware of choice. While it's likely got the best coverage there are lots of open issues and lacking support for newer things like GPT/UEFI boot.

At some points I figured hacking custom u-boot code to get NetBSD to boot on a SBC would have been easier in some ways. But we'll see about that later.

Once it gets going, its pretty good. it's the consistent, rock solid UNIX experience I was hoping for. Coming from someone who primarily uses windows, but knows the basics of linux server administration, the UNIX experience equals I have no idea how to do anything in an otherwise familiar environment. I really like the simple rc.conf and rc.d init system and the sane directory hierarchies for third party software so far.

March 17, 2018

Waterboarding your brain / becoming a BSD curmudgeon

Buckle up, this is going to be a wordy, disjointed one.

“There is nothing noble in being superior to your fellow man; true nobility is being superior to your former self.”

― Ernest Hemingway

tacky, lofty quote opener: ✔️

Over the years I've been thrown into tasks at work I had zero experience or knowledge of. As those who work in the tech industry know, this isn't uncommon or even undesirable (for most).

One of the big pulls for people who are intellectually driven is the perk of getting paid to constantly tackle new and potentially interesting challenges and become better and stronger. For many, this is what makes the tech work fulfilling and satisfying. I assume this parallels in any other industry with creative or open ended efforts.

Drive and the perversions of nerdy desire

While I want to say "nobody would enjoy copy pasting mindlessly for 8 hours a day!" I worked with people doing just that for years in a few entry level jobs. For example, processing ten digit triggers in telephone switches. Another example would be 'ACDVs', Automated credit dispute verifications which consisted of copy pasting personal information from one form to blank along side it. Back when I worked in collections (over 10 years ago now..) it could not legally be automated, hence 'verification'.

boredom

Aside, let me be perfectly clear: That is completely ok. These people were not interested in becoming LLVM core contributors or porting the OCAML compiler to a MIPS processor for fun. They were working one of the only jobs in town, that they despised, to feed their family. All without complaint. And as mentioned, a few people actually enjoyed it. A certain Zen to it. I get that. I was not sitting there, stewing, thinking I was better than the work or anyone. More importantly, I was sitting right there too, grinding it out.

Barely passing high school and never going to college, I thought programming was going to probably remain just a hobby while I went through the motions at entry level jobs indefinitely unless I changed something (I didn't). And that's exactly what happened. But I practiced at home, and roughly knew what I was capable of. Getting paid to explore this further was a pipe dream. I got very lucky, That's a story for another day

The point

I want to really push myself in something I've never done before that is also technically very challenging (for me, of course). This may be a recipe for disaster, but, I'd rather face frustration and 'failure' (learning stuff on the way doesn't make this a loss) instead of becoming complacent or niche'd. Finding where your current capabilities lie and pushing them even further is about as core nerd experience as you can get.

So with that said, here's what I got in mind

UNIX and BSD operating systems

As I grow older and learn more and more about OS design, either through osmosis or casual reading, I find UNIX and modern BSD descendants growingly interesting. I couldn't tell you why, I can't run MUH GAMEZ on them. UNIX is the essence of bygone development simplicity.

unix teletype session Attracting ladies on OKCupid

The BSD family is the modern descendent of UNIX, though the family tree is quite nuanced and a story of copyright and tribulations, you can see the full thing Here (wikipedia)

I've been meaning to really get into BSD for a while, too. John Carmack having a honeymoon with OpenBSD recently really resonated with me, even just as a user of the OS.

Heck. You can run the first UNIX in docker or still read the first UNIX programmers manual. I think anyone with an interest in OS legacy owes it to themselves to get familiar or at least know about the UNIX bloodline. Yea, I'm a big hit at parties!

As I was writing this blog, I saw this tweet fly by:

https://twitter.com/BrendanEich/status/975514575012425728

I've used BSDs a little bit, but very superficially. I run FreeBSD on servers, but I couldn't tell you how to do more than install and configure PostgreSQL on one. Never mind fancy ZFS stuff.

So taking a break from complaining about there being no good video games to play, getting intimate with a BSD is probably a good deep dive choice.

Which one? Well, I was going to pick either NetBSD or OpenBSD under the impression they are still smaller than FreeBSD, whichever had a smaller USB installation media. For the current releases, by chance they are both exactly the same size.

I picked NetBSD because I find the project goals more interesting, and it seems to be in more of a need. Another one of my primary interests that I do not act on and just fetishize is embedded development. And most importantly, the deeply logical fact I like the logo.

At the end of the day, I find the folks hacking on BSDs hardcore of the hardcore (or maybe just most oldschool) of this realm, maybe unfairly so. Do I want to 'hang out with the big boys' or embarrass myself trying?

What about GNU/Linux

GNU/Linux would definitely be a more usable choice when it comes to contemporary hardware. It also has far more developers, more people using it, banging on it and writing about it too. I'm also just not as interested in it from a nerdy lore background if nothing else. I'll definitely dig into it later on. BSDs also have the advantage of the entire system being built together, userspace and kernel. I find this a huge benefit to the system expectations and stability. Not to mention no intrusive updaters or systemd (bandwagon: ✔️)

New challenge

I have some lofty goals in mind. I'd be happy to get 2 or 3 of these under my belt, especially with the way work has been going lately, I'll probably be weekend warrior'n these out. Battle plan:

  1. Install and setup NetBSD, basic usage and configuration
  2. Compile NetBSD from sources, run current/srcs
  3. Dissect boot process (mostly for extra credit real goal below)

I really haven't done any of the above, but this is all straight forward and documented. There are a lot of other minor tasks this involves. For example, The BSD projects still use CVS (for some good reason I presume), so that would be another thing to learn. These will all probably not be a challenge, just prerequisites. Hell, I should admit, I've never done any sizable development in C, so I'll need to brush up on that (along with compiler extensions, buildchain etc).

Here is a nice NetBSD milestone:

bring up NetBSD on a new or unsupported SBC/board

How cool would that be? It'd require a good understanding of the hardware AND the software from ground zero if it was a new board.

I have a lot of single board computers, a few of which are newer, like the Libre Computer and ASUS tinker board, surely I can find one that isn't currently supported. Of course I have Raspberry PIs too, but I'm sure lots of others will try to get those going (not that I'm opposed to helping out).

They are both ARM processors, so I don't think it would be a soul crushing endeavor. I'll likely just pick one and go until I get things booting (if no one else has), I'd prefer the Libre computer (Amlogic ARM Cortex A-53), I think the Rockchip ARM Cotrex-A17 the ASUS Tinker board has more coverage.

If I wanted to go an extra step, I could even try to do so for a MIPS board, the MIPS Creator CI20 from imgtec. It's basically dead in the water and they've sold back MIPS, probably not the most fruitful. In fact, one of the NetBSD devs started the process years ago.

I'm also, for the first time in my life, well equipped to tackle early boot (well, as much as you can be) debugging. I own a logic analyzer, several USB FTDI serial cables, an oscilloscope, etc. But this would be more for new board bringup. Slightly different ARM SoCs is probably not as bad.

Yep, that's it! How hard could it be right? How long before I lose interest and just stop talking about it like all those other projects? Only time will tell. If I could even finish the first 3 things, that'd be a net win for me (no pun intended). This post is already far too long so I shall document the journey in more discreet chunks! Instead of a glacier of content!

<titanic picture here>
March 12, 2018

MSP430 assembly part 1: Blinking LED hello world

Lets blink an LED on a MSP430 launchpad the old fashioned way! Assembly! Don't worry, MSP430 has a nice, small RISC instruction set. It's only true 24 instructions, with a total of 27 higher level ones emulated by the assembler.

The full user's guide for the MSP430 microcontroller i will be covering (on an older launchpad) is available here ,
grab a copy because it covers the instruction set and microcontroller completely.

First, I will present the source with the CCS generated boiler plate for ELF sections and stack setup:

            .cdecls C,LIST,"msp430.h"       ; Include device header file
            .def    RESET                   ; Export program entry-point to
                                            ; make it known to linker.
            .text                           ; Assemble into program memory.
            .retain                         ; Override ELF conditional linking
                                            ; and retain current section.
            .retainrefs                     ; And retain any sections that have
                                            ; references to current section.

    RESET       mov.w   #__STACK_END,SP         ; Initialize stackpointer
    StopWDT     mov.w   #WDTPW|WDTHOLD,&amp;WDTCTL  ; Stop watchdog timer

            ; our code will go here moving forward

    .global __STACK_END
    .sect   .stack
    .sect   ".reset"                ; MSP430 RESET Vector
    .short  RESET
            

For all intents and purposes we can ignore the setup scaffolding, it just turns off the watchdog timer and setups the stack and reset vector. This lets you press the reset button to .. jump to our RESET label.

To blink an LED on a microcontroller you need to do 2 things:

  • Set the pin(s) of the PORT the LED is connected to to OUTPUT
  • Switch the output high/low

On the Ti launchpad, there are two LEDs on PORT1. For simplicity we can set the entire port to output. To do this, mov an immediate value into the named mapping like so:

mov #0FFh, P1DIR ; P1DIR is port1 direction control. '#0FFh' is an immediate value in hex

Now the entire port is set as output. To check, you could just try to lightup all the LEDs by turning all the pins on:

mov #0FFh, P1OUT

However this isnt very exciting because they just stay lit. We need to toggle. The easiest way is an exclusive or (xor) of the bits.

xor #0FFh, P1OUT  ; flip all bits in P1OUT

However, we need to loop over this so we dont just change the output once and fall through:

LOOP
    xor #0FFh, P1OUT  ; flip all bits in P1OUT
    jmp LOOP
    

Astute readers know what's coming next. if you run this code the LEDs will appear to be solid. It's because the loop's executing so fast the human eye cannot see the difference. In fact there probably is no difference, as the rate this loop executes is many 1000s of instructions per second.

I lied when I said we only need to do 2 things. We need a delay loop. Unfortunately we do not have something as convenient as wiring's delay(). We need to make a delay loop by hand! This is much easier than it sounds. There are a few ways to do so, we will do the naive approach first:

  • Put a big value in a register
  • decrement the value until it hits zero
  • once it hits zero, execute our toggle code

The tricky part about this approach is figuring out how big of a number you need, which can depend on the MCU clock rate, and what instructions you effectively execute within the loop. Precise timing can be achieved with some math and nop sleds. But for our purpose, we can ballpark some visible delay.

Lets stuff our countdown in the first general register R4. The MSP430 is a 16-bit cpu so lets try the biggest 16-bit unsigned value to start with:

mov #0FFFFh, R4

Now lets run it down to zero. We can check if it hit zero using the status register SR, this is like the x86 EFLAGS register. It will have bits set automatically after certain instructions, which are documented for every instruction that affects status flags. Alternatively, there is a conditional jump when the zero flag is set, so we will use it - jnz.

DELAYLOOP
    SUB #1h, R4 
    jnz DELAYLOOP
    
    ; we fall through here once delay loop is done 
    

This will spinwait until R4 hits zero and then fall through, now all that's left is to jump to top loop again:

    jmp LOOP 
    

This will start the whole process over. On a MSP430G2553, this first try at a delay loop works out to around 250ms, making for a nice blinking rate.

For completeness, the entire body of our effective code looks like this (with some added comments):

            mov #0FFh, P1DIR    ; setup - set port1 to output
LOOP
            xor #0FFh, P1OUT    ; flip port 1 bits
            mov #0FFFFh, R4     ; R4 will be our delay counter

DELAYLOOP
            SUB #1h, R4         ; subtract 1 from R4...
            jnz DELAYLOOP       ; if we hit zero we're done with delay loop
            jmp LOOP
            

This code can be simplified even further, do you see how? This is an exercise left to the reader. It's also midnight and I'm starting to get tired in my old age.

In part two we will use the built in timer peripherals of the microcontroller and use interrupts for a cleaner approach. After that it will be on to PWM (Pulse Width Modulation) duty cycles and controlling a servo using an ADC input.

asm embedded msp430 blinky assembly
March 8, 2018

Simple sampling with Box-Muller transforms pt 1

I'm a technically uneducated idiot, so talking about math is a bit above my pay grade, but Box-Muller transform is a straightforward, computationally simple way to generate a distribution of points.

This is useful in many cases where you need to generate samples for simulations, so I think every programmer should have familiarity with it.

Lets take the example code from the wikipedia and convert it to standard C. This program will just print 60 x/y samples.

First, checkout the cool visualization of the transform on uniform inputs from the wikipedia! If you right click and view the image directly, you can hover on the crosses to see points there.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include <time.h>

static const double epilson = DBL_MIN;
static const double pi2 = 2.0 * M_PI;

struct sample {
    double z0;
    double z1;
};

struct sample box_muller_sample() {
    double u1;
    double u2;
    struct sample ret;

    do {
        u1 = rand() * (1.0 / RAND_MAX);
        u2 = rand() * (1.0 / RAND_MAX);
    } while (u1 <= epilson);

    ret.z0 = sqrt(-2.0 * log(u1)) * cos(pi2 * u2);
    ret.z1 = sqrt(-2.0 * log(u1)) * sin(pi2 * u2);
    /* no sigma or mu */
    return ret;
}

int main(int argc, char **argv) {
    time_t curtime;
    srand(time(&amp;curtime));

    puts("Box-Muller samples:");
    for (int line = 0; line < 10; line++) {
        for (int i = 0; i < 6; i++) {
            struct sample bm = box_muller_sample();
            printf("%0.3f:%0.3f\t", bm.z0, bm.z1);
        }
        printf("\n");
    }
    return 0;
}

a sample output looks like this:

Box-Muller samples:
-0.559:0.786    -0.798:-0.640   -0.365:-0.140   1.417:-0.197    0.210:1.734     0.738:1.026
-2.334:0.079    -0.973:-0.634   -0.674:1.263    0.765:1.705     -0.560:0.860    -0.576:-0.044
-1.242:-1.705   1.705:-0.471    0.063:-0.079    0.732:-1.173    -0.242:-0.756   -1.798:0.853
-1.088:1.138    2.096:1.439     0.556:0.168     -0.105:0.132    -0.397:-0.728   0.090:0.109
-0.850:-0.034   0.930:0.108     -1.105:0.016    -0.592:-1.795   1.073:-0.227    -1.198:-0.517
-0.901:-1.978   -0.524:-0.090   0.821:-1.595    0.783:-0.051    0.580:-0.458    0.416:1.115
0.888:0.337     -0.074:-0.526   1.667:0.233     -1.339:0.075    0.563:-0.379    0.236:-0.229
0.222:0.472     -0.364:0.061    0.413:1.185     0.265:0.083     -1.120:1.978    0.939:0.807
-0.344:1.586    0.162:-0.274    -0.309:-0.098   -0.728:-0.441   -0.358:-0.310   1.324:-0.816
0.187:-0.160    0.035:0.083     1.386:-0.823    0.117:-1.897    0.475:-0.387    0.295:-0.382

In a future post I'll cover an even more efficient algorithm to generate uniform sampling, which is appropriate when a very large amount of random sampling numbers is needed. It's called Ziggurat

c sampling math