Archive

Archive for March, 2008

Slug Upgrade – on Batteries

March 28, 2008 Pari Leave a comment

I’m in a place where we have random power cuts during this time of the year, so didn’t want to risk bricking my slug (NSLU2) during an upgrade and so decided to power it by batteries. My fear was that I might end up bricking the slug if there was a power cut right when flashing it. Later I found out it was unfounded, as according to the upslug2 documentation there is really no way for you frag the RedBoot bootloader unless you intentionally do so, as by default, even if your flash image contains RedBoot and SysConfig sections, it does not overwrite the RedBoot and SysConfig areas (they remain untouched).

Anyway… here are some notes on upgrading a slug while on battery power.

Decided to upgrade my Slug to Debian 5.0 (debian-5.0beta1.zip). Followed the steps here (used the upslug2 method for flashing). It’s handy to have a serial console to see if it’s picking up the DHCP stuff properly. I hooked up the Slug directly to my laptop (running Ubuntu) via crossover cable.

Here are some stats. The Slug upgrade took 2 hrs 50min (on a 266MHz Slug, with a 200Kbps DSL connection, 57MB download). At around 2 hrs you’re prompted to create root and user accounts. About 15 minutes later you’re prompted for additional package selection (I unchecked all). In the next 30 minutes it prepares and flashes the kernel image to the Slugs flash memory. On a Slug (with a 2GB USB flash drive plugged into it), 4 freshly charged AA NiMH 2700mAH batteries (5.6v no load) lasted 3 hrs 10min before it dropped to a 4.3v (no load).

Categories: Slug

Freaky Assembly?

March 9, 2008 Pari 1 comment

After a looong time, I was debugging some embedded C code and thought I found something freaky:

C code

for (i = 0; i < 1000000; i++);

ARM code disassembly (as generated by GNU ARM gcc)

0×0000019c <main+196>: mov r3, #0 ; 0×0
0×000001a0 <main+200>: str r3, [r11, #-16]
0×000001a4 <main+204>: b 0×1b4 <main+220>
0×000001a8 <main+208>: ldr r3, [r11, #-16]
0×000001ac <main+212>: add r3, r3, #1 ; 0×1
0×000001b0 <main+216>: str r3, [r11, #-16]
0×000001b4 <main+220>: ldr r2, [r11, #-16]
0×000001b8 <main+224>: mov r3, #999424 ; 0xf4000
0×000001bc <main+228>: add r3, r3, #572 ; 0×23c
0×000001c0 <main+232>: add r3, r3, #3 ; 0×3

0×000001c4 <main+236>: cmp r2, r3
0×000001c8 <main+240>: bls 0×1a8 <main+208>

The three highlighted lines above in affect initialize r3 with 999999 (first initializes r3 with 999424, then adds 572 to it, then adds 3 to it).

What puzzled me was why couldn’t it do that directly (mov r3, #999999)?

Then after some scratching my head, an almost faint memory of ARM assembly language dawned on me… ARM instructions are 32-bit, of which Operand 2 can be only 12-bits. In addition:

- Of these 12 bits, 8-bits are for data, and 4-bits are used for ROR.
- The ROR bits are in turn multiplied by 2 before being applied on the 8-bits.

The combination of ROR and shifting by 2 greatly extends the range. The assembler automatically does it for you if it sees an operand greater than 8-bits.

This can be a great interview question :-).

Do the math, verify…

999424 + 572 + 3 is the closest tuples you can get to add up to 999999 using the 12-bit ROR with x2 multiplier for the RoR.

Just for verification, here are the instructions from memory:

1b8: 3D39A0E3 ; 0xE3A0393D
1bc: 8F3F83E2 ; 0xE2833F8F
1c0: 033083E2 ; 0xE2833003

To get 999424 (0×0F4000):
0×0000003D ROR 18 (0×9 x 2) = 0×000F4000 (ROR 18 = LSL 6)
As confirmed by the instruction: E3A03 93D

To get 572 (0×023C):
0×0000008F ROR 30 (0xF x 2) = 0×0000023C (ROR 30 = LSL 2)
As confirmed by the instruction: E2833 F8F

To get 3 (0×0003):
0×00000003 ROR 00 (0×0 x 2) = 0×00000003 (ROR 00 = LSL 0)
As confirmed by the instruction: E2833 003

Note: the LSL is just for convenience, it’s good only if data has all zeros padded on the left (at least enough to cover the LSL).

Categories: ARM, Coding