...

MSP430 TI Launchpad


MSP430:

Using a Launchpad board Rev 1.5 for this exercise. This one came with a 2553.

Using Energia for the TI Launchpad

>> Installed Energia for Windows, on the Windows XP VirtualBox vm on my ubuntu machine.
Followed instructions from https://github.com/energia/Energia/wiki/Getting-Started.
Downloaded https://github.com/energia/Energia/raw/gh-pages/files/EZ430-UART.zip
Ran DPinst.exe
Downloaded https://github.com/downloads/energia/Energia/energia-0101E0006-windows.zip
Was then able to run energia.exe, to launch the IDE.
Plugged in the Launchpad. This is what the VirtualBox USB setup looked like, for the Launchpad.


MSP430 PDIP Device Pinout:

To use m430G2553 ouside of launchpad:

  • add a 0.1uF capacitor (markd 104) between Vcc and GND as close to the chip as possible.
  • tie the RST pin to Vcc through a 47k resistor. (schematic also showed RST being tied to GND through a 1nF or 10nF capacitor)


Serial on the Launchpad:

<< Launchpad versions 1.5 (see where it says "Rev 1.5" under the "MSP-EXP430G2" silkscreen), shipped with hardware UART chips (MSP430G2553). The jumpers on block J3 need to be setup correctly to allow hardware UART, like in the picture. The Rxd/Txd jumpers need to be like the silkscreen shows, they need to be flipped so the jumped pins are parallel with (and not straddling) the dotted dividing silkscreen line.

Should be able to use the regular Serial functions from the Arduino IDE (Don't have to use SoftwareSerial). Was able to run the following program, on both the Windows XP virtual box and Ubuntu (set Serial Monitor to "No line ending", and doesn't look like Energia can set it run at more that 9600 baud).

Test program:
int incomingByte = 0;   // for incoming serial data

void setup() {
  pinMode(14, OUTPUT); 
  Serial.begin(9600);     // opens serial port, sets data rate to 9600 bps
}

void loop() {
        // send data only when you receive data:
        if (Serial.available() > 0) {
                // read the incoming byte:
                incomingByte = Serial.read();
                digitalWrite(14, HIGH);
                delay(100);
                digitalWrite(14, LOW); 
                // say what you got:
                Serial.print("recvd: ");
                Serial.println(incomingByte, DEC);
        }
}

Serial works, when using the USB connection provided from the Launchpad itself, but I could not for the life of me get it to work directly from the UART pins of the 2553. I'm not sure what I'm doing wrong, and hopefully I can figure out how to solve this problem.

Another problem I saw was that when the jumpers are set for hardware UART, and the micro is sending characters through serial, Windows had trouble attaching the Launchpad. The jumpers had to be switched back to the software UART position before it could be programmed again.

Be careful using the DC-DC convertor to supply power to the chip, when using it outside the Launchpad board. It seems to work for simple programs, like blinking LEDs, but was causing issues when doing things like trying to read from an IR detector module (even with using filtering caps). I had to power the circuit through a L4931, before it started working properly.


Pin assignments:

LED1 can be turned on with:
 pinMode(2, OUTPUT);
 digitalWrite(2, HIGH);
Pins can also be address by there alternative names P1_0 ... P1_7 and P2_0 ... P2_5. See Energia/hardware/msp430/variants/launchpad/pins_energia.h for details. The LaunchPad pins_energia.h is here on github.

 pinMode(P1_0, OUTPUT);
 digitalWrite(P1_0, HIGH);
LED1, LED2, S2 and internal temp sensor can also be addressed by the alternative names:

 RED_LED
 GREEN_LED;
 PUSH2;
 TEMPSENSOR;
To turn on the red LED.

 pinMode(RED_LED, OUTPUT);
 digitalWrite(RED_LED, HIGH);
This diagram shows the complete pin map for the LaunchPad in Energia. Also see the examples in Energia.

                                   +--\-/--+
                            VCC   1|       |20  GND 
               (LED1) (A0)  P1.0  2|       |19  XIN 
   *(TXD/RXD) (TA0.0) (A1)  P1.1  3|   M   |18  XOUT
   *(TXD/RXD) (TA0.1) (A2)  P1.2  4|   S   |17  TEST
                 (S2) (A3)  P1.3  5|   P   |16  RST#  (S1)
                      (A4)  P1.4  6|   4   |15  P1.7  (A7)         (SDA) (MISO) depends on chip
              (TA0.0) (A5)  P1.5  7|   3   |14  P1.6  (A6) (TA0.2) (SCL) (MOSI) (LED2)
                            P2.0  8|   0   |13  P2.5
                            P2.1  9|       |12  P2.4
                            P2.2 10|       |11  P2.3
                                   +-------+
 
 *(TA0.2): Only flavors with a comparator have TA0.2 on PIN 6
 *(TXD/RXD): TimerSerial: P3 = TXD, P4 = RXD; Hardware Serial: P3 = RXD, P4 = TXD 
 * RED_LED = LED1 = P1_0 = pin 2 
 * GREEN_LED = LED2 = P1_6 = pin 14
 * PUSH2 = S2 = P1_3 = pin 5
V1.5 and later of the launchpad shipped without pullup resistors (C24 R34 47Kohm) on PUSH2 (S2 or P1_3 or pin 5). This is to reduce power consumption (77uA) if port P1_3 is driven LOW. On your LaunchPad just below the "M" in the text "MSP-EXP430G2" see if R34 is missing. To make sketches that are using PUSH2 on newer launchpads work, the pinMode has to be changed to enable the internal pullup resistor in the MSP430. This is a simple change

e.g. pinMode(PUSH2, INPUT); becomes pinMode(PUSH2, INPUT_PULLUP); or pinMode(P1_3, INPUT); becomes pinMode(P1_3, INPUT_PULLUP);

were defined in energia-0101E0006\hardware\msp430\variants\launchpad\pins_energia.h

/*
  ************************************************************************
  * pins_energia.h
  *
  * Energia core files for MSP430
  *  Copyright (c) 2012 Robert Wessels. All right reserved.
  *
  *     Contribution: Rei VILO
  *
  ***********************************************************************
  Derived from:
  pins_arduino.h - Pin definition functions for Arduino
  Part of Arduino - http://www.arduino.cc/

  Copyright (c) 2007 David A. Mellis

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General
  Public License along with this library; if not, write to the
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  Boston, MA  02111-1307  USA
*/

#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#ifndef BV
#define BV(x) (1 << (x))
#endif

#if defined(__MSP430_HAS_USCI__)
static const uint8_t SS   = 8;  /* P2.0 */
static const uint8_t SCK  = 7;  /* P1.5 */
static const uint8_t MOSI = 15; /* P1.7 */
static const uint8_t MISO = 14; /* P1.6 */
#endif

#if defined(__MSP430_HAS_USI__)
static const uint8_t SS   = 8;  /* P2.0 */
static const uint8_t SCK  = 7;  /* P1.5 */
static const uint8_t MOSI = 14; /* P1.6 */
static const uint8_t MISO = 15; /* P1.7 */
#endif

static const uint8_t A0 = 0;
static const uint8_t A1 = 1;
static const uint8_t A2 = 2;
static const uint8_t A3 = 3;
static const uint8_t A4 = 4;
static const uint8_t A5 = 5;
static const uint8_t A6 = 6;
static const uint8_t A7 = 7;
static const uint8_t A10 = 10; // special. This is the internal temp sensor

//                      +-\/-+
//               VCC   1|    |20  GND
//         (A0)  P1.0  2|    |19  XIN
//         (A1)  P1.1  3|    |18  XOUT
//         (A2)  P1.2  4|    |17  TEST
//         (A3)  P1.3  5|    |16  RST#
//         (A4)  P1.4  6|    |15  P1.7  (A7) (SCL) (MISO) depends on chip
//         (A5)  P1.5  7|    |14  P1.6  (A6) (SDA) (MOSI)
//               P2.0  8|    |13  P2.5
//               P2.1  9|    |12  P2.4
//               P2.2 10|    |11  P2.3
//                      +----+
//

// Pin names based on the silkscreen
//
static const uint8_t P1_0 = 2;
static const uint8_t P1_1 = 3;
static const uint8_t P1_2 = 4;
static const uint8_t P1_3 = 5;
static const uint8_t P1_4 = 6;
static const uint8_t P1_5 = 7;
static const uint8_t P2_0 = 8;
static const uint8_t P2_1 = 9;
static const uint8_t P2_2 = 10;
static const uint8_t P2_3 = 11;
static const uint8_t P2_4 = 12;
static const uint8_t P2_5 = 13;
static const uint8_t P1_6 = 14;
static const uint8_t P1_7 = 15;

static const uint8_t RED_LED = 2;
static const uint8_t GREEN_LED = 14;
static const uint8_t PUSH2 = 5;
static const uint8_t TEMPSENSOR = 10; // depends on chip


#ifdef ARDUINO_MAIN

const uint16_t port_to_dir[] = {
 NOT_A_PORT,
 (uint16_t) &P1DIR,
 (uint16_t) &P2DIR,
#ifdef __MSP430_HAS_PORT3_R__
 (uint16_t) &P3DIR,
#endif
};

const uint16_t port_to_sel[] = {
 NOT_A_PORT,
 (uint16_t) &P1SEL,
 (uint16_t) &P2SEL,
#ifdef __MSP430_HAS_PORT3_R__
 (uint16_t) &P3SEL,
#endif
};

const uint16_t port_to_ren[] = {
 NOT_A_PORT,
 (uint16_t) &P1REN,
 (uint16_t) &P2REN,
#ifdef __MSP430_HAS_PORT3_R__
 (uint16_t) &P3REN,
#endif
};

const uint16_t port_to_sel2[] = {
 NOT_A_PORT,
#ifdef P1SEL2_
 (uint16_t) &P1SEL2,
#else
        NOT_A_PORT,
#endif
#ifdef P2SEL2_
 (uint16_t) &P2SEL2,
#else 
        NOT_A_PORT,
#endif
#ifdef P3SEL2_
 (uint16_t) &P3SEL2,
#else
        NOT_A_PORT,
#endif
};

const uint16_t port_to_input[] = {
 NOT_A_PORT,
 (uint16_t) &P1IN,
 (uint16_t) &P2IN,
#ifdef __MSP430_HAS_PORT3_R__
 (uint16_t) &P3IN,
#endif
};
const uint16_t port_to_output[] = {
 NOT_A_PORT,
 (uint16_t) &P1OUT,
 (uint16_t) &P2OUT,
#ifdef __MSP430_HAS_PORT3_R__
 (uint16_t) &P3OUT,
#endif
};

/* 
 * Defines for devices with 2x TA3 timers (e.g. MSP430g2553). On the 20pin devices, upto 3 analog outputs are available
 * T0A1, T1A1 and T1A2 
 */
const uint8_t digital_pin_to_timer[] = {
 NOT_ON_TIMER, /*  dummy */
 NOT_ON_TIMER, /*  1 - VCC */
 NOT_ON_TIMER, /*  2 - P1.0 */
 T0A0,         /*  3 - P1.1, note: A0 output cannot be used with analogWrite */
 T0A1,         /*  4 - P1.2 */
 NOT_ON_TIMER, /*  5 - P1.3 */
 NOT_ON_TIMER, /*  6 - P1.4 note: special case. Leaving as no timer due to difficulty determining if available */
 T0A0,         /*  7 - P1.5 note: A0 output cannot be used with analogWrite  */
#if defined(__MSP430_HAS_T1A3__) 
 T1A0,         /*  8 - P2.0 note: A0 output cannot be used with analogWrite */
 T1A1,         /*  9 - P2.1 */
 T1A1,         /* 10 - P2.3 */
 T1A0,         /* 11 - P2.4 note: A0 output cannot be used with analogWrite  */
 T1A2,         /* 12 - P2.5 */
 T1A2,         /* 13 - P2.6 */
#else
 NOT_ON_TIMER, /*  8 - P2.0 */
 NOT_ON_TIMER, /*  9 - P2.1 */
 NOT_ON_TIMER, /* 10 - P2.3 */
 NOT_ON_TIMER, /* 11 - P2.4 */
 NOT_ON_TIMER, /* 12 - P2.5 */
 NOT_ON_TIMER, /* 13 - P2.6 */
#endif
 T0A1,         /* 14 - P1.6 */
 NOT_ON_TIMER, /* 15 - P1.7 */
 NOT_ON_TIMER, /* 16 - /RESET */  
 NOT_ON_TIMER, /* 17 - TEST */  
 NOT_ON_TIMER, /* 18 - XOUT - P2.7 */
 T0A1,         /* 18 - XIN - P2.6: */
 NOT_ON_TIMER, /* 20 - GND */
};

const uint8_t digital_pin_to_port[] = {
 NOT_A_PIN, /* dummy */
 NOT_A_PIN, /* 1 */
 P1, /* 2 */
 P1, /* 3 */
 P1, /* 4 */
 P1, /* 5 */
 P1, /* 6 */
 P1, /* 7 */
 P2, /* 8 */
 P2, /* 9 */
 P2, /* 10 */
 P2, /* 11 */
 P2, /* 12 */
 P2, /* 13 */
 P1, /* 14 */
 P1, /* 15 */
};

const uint8_t digital_pin_to_bit_mask[] = {
 NOT_A_PIN, /* 0,  pin count starts at 1 */
 NOT_A_PIN, /* 1,  VCC */
 BV(0),     /* 2,  port P1.0 */
 BV(1),     /* 3,  port P1.1 */
 BV(2),     /* 4,  port P1.2 */
 BV(3),     /* 5,  port P1.3*/
 BV(4),     /* 6,  port P1.4 */
 BV(5),     /* 7,  port P1.5 */
 BV(0),     /* 8,  port P2.0 */
 BV(1),     /* 9,  port P2.1 */
 BV(2),     /* 10, port P2.2 */
 BV(3),     /* 11, port P2.3 */
 BV(4),     /* 12, port P2.4 */
 BV(5),     /* 13, port P2.5 */
 BV(6),     /* 14, port P1.6 */
 BV(7),     /* 15, port P1.7 */
 NOT_A_PIN, /* 16, RST */
 NOT_A_PIN, /* 17, TEST */
 NOT_A_PIN, /* 18, XOUT */
 NOT_A_PIN, /* 19, XIN */
 NOT_A_PIN, /* 20, GND */
};
#endif
#endif

unity tweak related
-------------------
http://shuffleos.com/3395/how-to-run-programs-as-root-unity-launcher-ubuntu-11-10/
http://shuffleos.com/3274/how-to-create-desktop-launchers-in-ubuntu-11-10-oneiric-ocelot/
http://sqizit.bartletts.id.au/2011/11/07/unity-launchersidebar-missing-on-ubuntu-11-10/

bash serial port related
-----------------------
http://bashcurescancer.com/timeout-new-coreutils-command.html
http://stackoverflow.com/questions/687948/timeout-a-command-in-bash-without-unnecessary-delay
http://www.bashcookbook.com/bashinfo/source/bash-4.0/examples/scripts/timeout3
http://en.wikibooks.org/wiki/Serial_Programming/Serial_Linux#Serial_I.2FO_on_the_Shell_Command_Line


ser2net related
----------------
(ipkg install ser2net on the tomatousb router, then did a ipkg files ser2net, it listed the installed files)
http://mellowd.co.uk/ccie/?tag=ser2net
http://sites.google.com/site/pinguinotutorial/wrt54gl
http://motersho.com/blog/index.php/2009/10/12/smtp-commands-via-bash-script-and-devtcp-device-file/
http://en.wikipedia.org/wiki/Netcat

Using interrupts:
-----------------

maskable interrupt - cpu will

non-maskable interrupt - like reset, this will immediatedly stop the processor


example- to make pressing S2 (on P1.3) to trigger interrupt.

GIE (general interrupt enable) setting bits here enables masakble interrupts (not the non-maskable interrupts)


First, we need to configure the port to use interrupts.  The LaunchPad button is on P1.3, 
so all of our concern will be on that pin.  The pin needs to be configured as an input.  
Since the default state of the pin is logic 1, a high-low transition (a drop from 1 to 0) should be used to signal 
the interrupt.  We can code this using:
P1IES |= BIT3;   // high-to-low is selected with IES.x = 1.
P1IFG &= ~BIT3;  // To prevent an immediate interrupt, clear the flag for
                 // P1.3 before enabling the interrupt.
P1IE |= BIT3;    // Enable interrupts for P1.3

We've enabled the interrupt for P1 now, and a high-low transition caused by the button press will set the interrupt flag 
in P1IFG.  The processor, however, isn't set to recognize maskable interrupts like P1IFG.  
We can turn on the interrupts with:
_BIS_SR(GIE);

or equivalently:
_enable_interrupt();  // Note the singular name here!  It's not interrupts. intrinsic



void main(void) {
 
    WDTCTL = WDTPW + WDTHOLD; // disable watchdog
    // no need to explicitly set P1.3 as input, because they are input by default
    // 
    P1IES |= BIT3;   // high-to-low is selected with IESx = 1.
    P1IFG &= ~BIT3;  // To prevent an immediate interrupt, clear the flag for
                  // P1.3 before enabling the interrupt.
    P1IE |= BIT3;    // Enable interrupts for P1.3
 
    _enable_interrupt();
 
 for (;;) {           // Note the change in method; rather than flashing 5
  P1OUT ^= LED1;   // times, this program flashes the LED continuously.
  delay();
 }
} // main

void delay(void) {
 unsigned int n;
 for (n=0; n<60000; n++);
} // delay

/*  Interrupt Service Routines  */
#pragma vector = PORT1_VECTOR
__interrupt void P1_ISR(void) {
 switch(P1IFG & BIT3) {
  case BIT3:
   P1IFG &= ~BIT3;  // clear the interrupt flag
   BCSCTL1 = bcs_vals[i];
   DCOCTL = dco_vals[i];
   if (++i == 3)
    i = 0;
   return;
  default:
   P1IFG = 0;  // probably unnecessary, but if another flag occurs
               // in P1, this will clear it.  No error handling is
               // provided this way, though.
   return;
 }
} // P1_ISR






#define LED1 BIT3
#define LED2 BIT4

void main(void) {
    WDTCTL = WDTPW + WDTHOLD; // disable watchdog
    P1OUT = ~LED1; // preset LED1 on, LED2 off
    P1DIR = LED1 | LED2; // set LED1, LED2 to output
    __enable_interrupt();
    for (;;) {} / infinite loop, do nothing, interrupt does the work
}

#pragma vector = PORT1_VECTOR
__interrupt void P1_ISR(void) {
    P1OUT ^= LED1 | LED2; // toggle leds
}




reading button, in loop

#define LED1 BIT3
#define BTN1 BIT1

void main(void) {
  WDCTL = WDTPW | WDTHOLD;
  P2OUT |= LED1; // preload LED1 to off (active low)
  P2DIR = LED1; // set pin with LED1 to output
  for (;;) { // loop forever
    if ((P2IN & BTN1) == 0) { // is button down (active low)
        P2OUT $= ~LED1;  // turn on LED (active low)
    } else {
        P2OUT |= LED1; // turn off LED (active low)
    }
  }

}




P1SEL - this selects the mode of the pins of the port, 0 (default) makes the pin digital input/output
P1DIR - sets pins of the port as input or output. 0 (default) input, 1 makes the pin output
P1IE - enables interrupts on the pins of the port. 0 (default) is off, 1 enables output on the pin
P1IES - sets what transition triggers the interrupt. if 0, interrupt is on positive (low to high), if 1 then on negative edge (high to low).
        note- this register is not intitialized, so no default, so must be set before enabling interrupts with P1IE.
P1IFG - bit is set in this flag cwhen a transition occurs on the corresponding input pin (that has interrupt enabled).
        note- this bit can also be set in software, to generate a software interrupt.
PIREN - enables the internal pull up, pull down resistor on the pins of the port. 0 (default) is inactive, 1 enables.
        if enabled, if the corresponding bit in P1OUT is 0, then the resistor is a pull down to Vss, if 1 then the resistor is a pull up to Vcc.

----------------------------------------------------------------------------------------------
notes from (really good site)
http://dbindner.freeshell.org/msp430/
http://dbindner.freeshell.org/msp430/demo.html

add into /etc/udev/rules.d/46-TI_launchpad.rules
ATTRS{idVendor}=="0451", ATTRS{idProduct}=="f430", MODE="660", GROUP="plugdev"
ATTRS{idVendor}=="0451", ATTRS{idProduct}=="f432", MODE="660", GROUP="plugdev"

restart udev 
groups nr, make sure you belong to plugdev
or can look in /etc/groups, see if you are listed there for plugdev

$ msp430-gcc -mmcu=msp430x2211 -o hello.elf hello.c && mspdebug rf2500 'prog hello.elf'

The way to think of this command is, "Compile the source, and, if successful, run mspdebug to program the object code to the Launchpad."

            /* Toggle just pin 0. */
            P1OUT ^= pin0mask;
        } else {
            /* Toggle both pin 0 and pin 6 */
            P1OUT ^= pin0mask|pin6mask;

if(( P1IN & BIT3 ) == 0 ) { // check if button was pressed




http://mspdebug.sourceforge.net/manual.html
http://translate.google.com/translate?sl=auto&tl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fwww.mikrocontroller.net%2Farticles%2FMSP430_eclipse_helios_mspgcc4_gdb-proxy&act=url
http://karuppuswamy.com/wordpress/2010/10/14/setup-build-and-debug-environment-for-msp430-mcus-using-mspgcc-and-mspdebug-in-ubuntu-linux/
http://karuppuswamy.com/wordpress/2010/10/22/debugging-msp-exp430g2-launchpad-with-mspdebug-tool-in-ubuntu-linux/
http://springuin.nl/en/articles/launchpadwindows
msp430-gcc
mspdebug (replaces msp430-gdbproxy)

starting msp430-gdbproxy should start up,listening on port 2000
 (or --port=6667)

synaptic - eclipse, include eclipse-cdt (C/C++ development tools)
 
eclipse IDE for C/C++ developers
C/C++ perspective 
install new software -> CDT -> C/C++ GCC Cross Compiler Support, C/C++ GDB Hardware Debugging: 

uncheck Show project types and toolchains..., 
choose Empty Project under Executable as project type and MinGW GCC as Toolchain.

project ->Properties. Expand C/C++ Build and click Discovery Options. Enter msp430-gcc.exe in the Compiler invocation command-textbox. 

GCC C Compiler, enter msp430-gcc.exe as command: 

Includes under GCC C Compiler and add the include path mspgcc\msp430\include
 
Switch to the Build Artifact tab and enter elf as Artifact extension: 

Switch to the Binary Parsers tab, disable the PE Windows Parser and enable the Elf Parser: 

New -> source file