Saturday, March 9, 2019

VSCode and MSP430 debugging

In process of getting cozy with VSCode and playing with MSP430 via LanchPad here is a simple recipe for tooling my work up.

But first ...

Basic tooling

  • Build -  uses msp430-gcc.
  • Debug - uses: mspdebug and msp430-gdb

All msp430 tolls already prepackaged on multiple Linux distros (I use Mint which is Debian-based hence apt-get is your fried.)

Checking Connection to the Target

mspdebug rf2500 "exit"

If the output contains Device ID and Chip ID data you're good.

If it can't connect try again with sudo in case the problem is with permissions. If it works with sudo, you add udev rules to allow non-root access - plenty of info in the tubes on this (I would advice a reboot after adding rules file).

Sometimes, the hw debugger/drive gets stuck - a reconnect would fix it. Make sure it shows connected with 'lsusb|grep 430'.

Flashing the image into the device

mspdebug rf2500 "prog ./bin/firmware.elf"

Starting gdb Debug Server

The server is build into mspdebug it need to be running as gdb will use it to debug.

mspdebug rf2500 "gdb"

Starting gdb Proper

msp320-gdb bin/firmware.elf -ex "target remote :2000"

This tells the gdb to load debug info from the given elf file and execute commands to connect to the debug server. Normally, gdb uses this for remote debugin (as in on another PC) here the same is used for embedded systems.

NOTE: each time you disconnect/quit gdb the debug server must be restarted.

Convinience - Make File Targets

In the Ikea Ansluta hacking project (on github here) I have created make targets for continence:

make target-flash
make target-startdebug
make target-debug

I think it's easier to remember these than particular incantation of commands given above.

The CLI workflow would be:

edit+build with make
flash with make target-flash
debug with make target-debug

Note that target-flash makes sure the code build is up to date.

VSCode tooling

By adding tasks: build and flash I can Ctrl-Shift-B to build (as normal with VS) and I can also flash directly from the IDE be selecting "Flash" task. These are added to .vscode/tasks.json file manually. 

Starting debbugger with just F5 is tooled via .vscode/launch.json. This tells VSCode to use "msp430-gdb" instead of default one and it tells it to connect to remote debug server.

However, I could not make the a preLaunchTask to start the msbdebug in the background. This task seem to either exit and kill the mspdebug or the mspdebug is unable to connect despite the rules working file in shell. So for now the debug server must be started manually before entering visual debugging in the IDE.

Sunday, March 3, 2019

Ikea Ansluta Hacking - timer and key interrupts

That...was easy.

1) setup interrupt for P1 on P_KEY (the switch) pin

P2IFG = 0; // clear flags register
P2IE = P_KEY; // enable
P2IES = P_KEY; // edge

2) setup timer A0 to use SMCLK/8 and count up, start it

CCTL0 = CCIE; // CCR0 interrupt enabled
TACTL = TASSEL_2 + ID_3 + MC_1; // TASSEL_2 --> SMCLK (~1MHz), MC_1--> up, ID_3 --> SMCLK/8
CCR0 = 50000; // (SMCLK/8)/50000 = 2.5 Hz

3) enter a low power mode with wake on interrupt


4) in timer A0 - toggle the LED pin

#pragma vector = TIMERA0_VECTOR
__interrupt void Timer_A(void)
   P1OUT ^= P_LED; // toggle LED for now

5) in Port 1 interrupt - toggle the max count of timer A0 between 'slow' and 'fast' blinking.

#pragma vector = PORT2_VECTO
__interrupt void Port_2(void)
   // TODO - there is no debouncing of the switch
   if( P2IFG & P_KEY )
      CCR0 = CCR0 > 10000 ? 10000 : 50000; // toggle between two blink speeds
   P2IFG = 0; // clear all flags

Next: debounce the key, talk to CC2500.

Ikea Ansluta Hacking - bang on the pipes (or...LED)

After achieving target control and reverse engineering the original firmware, the next step was to test development abilities: code, build, flash, debug.


The 'bang on the pipes' or 'flash LED'.


Well, that's simple, eh? There some more code in main.c up front to setup the MPU. The Ansluta's specific definitions are all in ansluta.h.

The project is in github (later it may move beyond just flashing the LED).

The project builds from CLI on Linux (I now use Mint) but also contains VSCode workspace, intellisense and task definitions.

On VSCode

I have abandoned Geany for VSCode for several reasons (it's shiny, integrates with git, it's used everywhere, it's good at at-hoc projects).  Yes, VSCode is a bit "fatter", being an Electron app, but it still works on my old-but-good 10yr laptop w/ 2GB of RAM with Mint x64.

Next Steps

Two "targets" (pun intended): get timer to flash led, get key press to work - all with interrupts. Then,  talk to CC2500 radio.

Sunday, January 13, 2019

Ikea Ansluta Hacking - reverse engineering the firmware

Since acquiring target control via Spy-Bi-Wire and LaunchPad I am able to inspect and dump flash, disassemble and program back the flash to original stage

The extracted files are in git here:

Dumping Flash

In .hex intell format that is usable to programming it back:

mspdebug rf2500 "hexout 0xf800 2048 flash.hex"

In .raw binary format

mspdebug rf2500 "save_raw 0xf800 2048 flash.raw"

Reprogramming back to original

Use .hex Intel format

mspdebug rf2500 "prog flash.hex"

Disassembling flash

mspdebug rf2500 "dis 0xf800 2048 flash.dis"

Things learned from the disassembly:

  • Operating mode is low power state LM3 and waking on interrupt from key press (connected to P2.7). However, LM1 is also entered after key press, perhaps to await for another key press before going LM3. Does this save energy?
  • Apparently, the randomization of remote's ID is done ADC reads which ends up as middle 4 bytes of the message (each ADC read uses only lowest bit). That likely saves mfg time instead of individually programming each remote with ID - this is smart!
  • The SPI communication with CC2500 is bit-banged (not using build-in MSP's SPI engine). This is likely due to messed up hw design - the MOSI/MISO lines are switched from their default pins:

MSP430       Device
     P1.0    LED
RXD  P1.1    unused?
TXD  P1.2    CC2500 CS
     P1.3    CC2500 GDO0
     P1.4    CC2500 GDO2
SCLK P1.5    CC2500 SCLK
SOMI P1.6    CC2500 SI
SIMO P1.7    CC2500 SO
     P2.6    unused (N-FET's Gate in transformer)
     P2.7    Key (switch)

Saturday, January 12, 2019

Ikea Ansluta Hacking - target control via TI's lunchpad

Notes of hacking Ikea Ansluta LED lighting.

Notably, this is less important now as Ikea's own smart home gateway TRÅDFRI solves the problem of controlling Ansluta lights via home automation. Although, the system is very hack-able likely for other purposes.


Both the remote and power supplies are based on TI's MSP430 G2231 and CC2500 RF transciver. The Ansluta's PCBs have programming/debugging headers ready for hacking.

The 4 Pin Header by the Bat+ label (top) has the following pins: Vcc, T, R, Gnd (clearly labeled).

I connected these to LP EXP430 Spy-Bi-Wire
Vcc --> VCC (1)
T   --> TEST(17)
R   --> RST (18)
Gnd --> GND (20)

The LunchPad Exp439G2 will power up the remote, no need for batteries. Just remove the actual MPU from the socket. not try this with transformer! this is dangerous as it's directly powered from power line.


Debugging the target

I am using lubuntu 18.04 and mspdebug (0.25/compiled locally).  and I am able to connect and break into the running code.

Invoke (may need sudo):

mspdebug rf2500

Here is output (parts removed - there are complains about FET interface not working...)

Using Olimex identification procedure
Device ID: 0xf201
  Code start address: 0xf800
  Code size         : 2048 byte = 2 kb
  RAM  start address: 0x200
  RAM  end   address: 0x27f
  RAM  size         : 128 byte = 0 kb
Device: F20x2_G2x2x_G2x3x
Number of breakpoints: 2
fet: FET returned NAK
warning: device does not support power profiling
Chip ID data:
  ver_id:         01f2
  ver_sub_id:     0000
  revision:       40
  fab:            40
  self:           0000
  config:         02
  fuses:          00
Device: F20x2_G2x2x_G2x3x

run & break

(mspdebug) run
Running. Press Ctrl+C to interrupt...
    ( PC: 0fc9e)  ( R4: 077fd)  ( R8: 0ff17)  (R12: 00000)  
    ( SP: 0027a)  ( R5: 0bf96)  ( R9: 09ff6)  (R13: 00006)  
    ( SR: 000da)  ( R6: 0fffc)  (R10: 0ff7f)  (R14: 00006)  
    ( R3: 00000)  ( R7: 0efcd)  (R11: 00200)  (R15: 00008)  
    0fc9e: 30 41                     RET     
    0fca0: 0e 43                     CLR     R14
    0fca2: 3e 90 2f 00               CMP     #0x002f, R14
    0fca6: 09 2c                     JC      0xfcba
    0fca8: 4c 4e                     MOV.B   R14,    R12
    0fcaa: 5d 4e 8a fd               MOV.B   0xfd8a(R14), R13

Next? Replace it with my own fw...when I have more time.

Arduino with CC2250 

Here is my version of Arduino+CC2500 that is based on a great work done here.

It works!


TI Spy-by-wire



Monday, October 8, 2018

Picture Frame - gets PIR and saves energy

My RPiPF is doing good. So now the goal is to shut down the TV when nobody is watching.

This was done. Many times. Even here.

A simple PIR (passive infrared) connected to Rpi pin can be monitored and when no motion is detected for some time the TV gets turned off. This saves energy and potentially extends the TV life span.

The problem with (most) PIRs

The PIR devices are contain two main components: the actual sensor that converts light into electric signals and a very high-gain amplifier. And here the problem begins. The sensor gives a very weak signal that need to be amplified so it can be detected. The amplifier however will happily amplify anything on its input, including any interference. And RPI being a decently strong EM signal  emitter (WiFi radio) when placed close to the sensor will cause unwanted tripping.

I have tried the $5 sensors that worked great in the past, both with arduino and other laptops-picture-frames. These worked great as there was no interference source nearby.

The aluminium foil shield did not work. Neither did attempt to decouple power supply with capacitors (apparently it is an inducted interference rather than a noise conducted via supply/ground lines).

However, I found this particular mini PIR sensor resilient to the interference. The cost being the sensitivity - it's detecting motion only in less then 3-4 meters away, while the other sensors were  double this.

Bash the code

The complete code (bash script) is on github here:

The main parts to make PIR work are:

  • script to read the GPIO pin state: gpiord  
  • scripts to turn TV on and off
  • main controller script monitoring the PIR and deciding when to turn the TV on or off:

Bit and nuts of the script:

Keep time: these two lines store current time int the form of number of seconds since 'epoh'. This is convenient when comparing them later.

lastmotion=`date +%s`
nowts=`date +%s`

Here we read the pin #18, it's either 0 or 1.

pinstate=`gpiord 18`

And here we observe detected motion ($pinstate equal 1) and note when this happened.

  if [ $pinstate -eq 1 ]; then

Then compute how long it was since last time something moved

  let lastmotionage=$nowts-$lastmotion

Then decide to show or not (by extending existing schedule condition)

  if [ $lastmotionage -lt 600 ] && [ "$timeok" = true ]; then


That's it.

Monday, August 20, 2018

Picture Frame - a RPiPF on the schedule

The previous builds were smaller but smarter. They actually turned off when nobody was around to see. The RPiPF (RapsberyPi Picture Frame) is not there yet.

A small step forward: turn off when nobody's around to watch and turn on when there may be - on the schedule. Turn on at 7am, turn off 11pm.

To control the TV from RPI - CEC

Consumer Electronics Control (CEC) is a control channel over the HDMI cable.

Install cec-utils

sudo apt-get install cec-utils

Turn the TV off:

echo "standby 0" | cec-client -s -d 1 

Turn the TV on

echo "on 0" | cec-client -s -d 1

Don't mind the CLI plumbing - these command are like magic: '-s' means execute single command while '-d 1' limits the damage to you eyes by cutting down the logging spewed back at ya. Note that the echo just pipes the actual command to the cec-client - an interactive program by birth.

Flying on a Magic Script

The script that was previously used to just start feh. Now it does the scheduling.
The script loops and:
  • checks the time
  • decides if the slide show should or should not be running
  • depending on that decision either 
    • kills feh and turns off the TV or 
    • starts feh and turns on the TV
  • sleeps for 1 minute and repeats

logger "PF started"
while true; do
  now=`date +%H%M`
  fehpid=`pidof feh`
  if [ $now -gt 700 ] && [ $now -lt 2300 ]; then
    if [ -z $fehpid ]; then
      logger "PF now=$now fehpid=$fehpid ON"
      gofeh &
    if [ ! -z $fehpid ]; then
      logger "PF now=$now fehpid=$fehpid OFF"
      skill feh
  sleep 1m 

Taking it apart

  • The lines with 'logger ...' just put entries in /var/log/user.log so I know what was happening.
  • The line "PATH=" just adds /home/pi/bin (user's pi bin directory) to the path. Normally this should be done the .profile.
  • Then we loop forever...
  • The line 'now=... ' captures current time into the 'now' variable. The time is formatted as hhmm (in 24 hour format) for easier comparing later.
  • The 'fehpid=...'  captures the process ID of feh, the slide show process. If it is not running, the fehpid is empty string.
  • Then in the first 'if' the script compares the $now to fit between 700 and 2300, military style.
  • And finally, the nested 'ifs' decide to turn on the show or to stop it. The '-z' checks for empty, while the '! -z' checks for not empty.
  • The small command scripts:  tvon, tvoff, gofeh got created in ~/bin (and chmod +x them so they can be executed).
  • The gofeh is run in the background (with '&') so the script can continue monitoring the time after starting the slide show.