Friday, November 23, 2012

Interrupts and timers

Interrupts stops executing main program and jumps to interrupt service routine. ISR is just function which address is stored in interrupt vector ( it is memory located in  flash at address 0xfffe ).
This is how is done in msp430gcc:
void Port1Int( void ) __attribute__( ( interrupt( PORT1_VECTOR ) ) );
void Port1Int( void )
{
   //our isr
}
We can use any name function, the thing that determines which interrupt will be served in this routine is vector name "PORT1_VECTOR". In this example we have PORT1 interrupt which fires when logic level is changed on any pin on port1 in the processor, we can decide which pin and what transition is working.

On lauchpad we have one press button that we can use for this task, it's P1.3.
P1DIR &= ~BIT3;  // make this pin input
P1REN |= BIT3;   // turn on internal pull resistor
P1OUT |= BIT3;   // make pulling up to VCC
P1IES |= BIT3;   // high to low transition fires interrupt
P1IFG &= ~BIT3;  // clear interrupt

We have to use internal pull resistor because in newer launchpads there is no resistor for push button. There is a place for one but they removed it probably to lower power consumption.
Let's use timer A0 for some led blinking, here is our setup:
TA0CTL =  TASSEL_2 | ID_2 | MC_1;
TA0CCR0 = 250000;
TA0CCTL0 = CCIE;
TASSEL_2 - set clock source for timer to SMCLK which is ~1MHz ID_3 - divide our source clock by /4 MC_1 - counting until we reach value in TACCR0 CCIE - enable compare interrupt
We want to have times around 1s so we divide clock to 1MHz/4 = 250 KHz, so our timer will count 250 000 times per second, it's still pretty fast. So, next we use compare register which will compare our timer value to it and when it's equal it's fire interrupt (CCIE). We compare to 25 000 value so our timer count to this value every 1/10 of second, so we have interrupt 10 times per second.
Let's use all this to make program which starts blinking after pressing push button.
#include 
#include 

uint16_t counter = 0;
uint8_t second = 0;

int main()
{
    WDTCTL = WDTPW + WDTHOLD;   
    
    BCSCTL1 = CALBC1_1MHZ;
    DCOCTL = CALDCO_1MHZ;
    
    TA0CCR0 = 25000;
    TA0CCTL0 = CCIE ;
    
    P1DIR &= ~BIT3;
    P1REN |= BIT3;
    P1OUT |= BIT3;
    P1IES |= BIT3;  
    P1IFG &= ~BIT3; 
    P1IE |= BIT3;   
 
    P1DIR |= BIT0 | BIT6;
    P1OUT &= ~( BIT0 | BIT6 );

    __bis_SR_register( GIE );
 
    while(1) {
 }

    return 0;
}
void Port1Int( void ) __attribute__( ( interrupt( PORT1_VECTOR ) ) );
void Port1Int( void )
{
 switch(P1IFG&BIT3) {
  case BIT3:
   P1IFG &= ~BIT3;
   TA0CTL = TASSEL_2 | ID_2 | MC_1; //run timer
   break;
 } 
}

void TimerA0Int( void ) __attribute__( ( interrupt( TIMER0_A0_VECTOR ) ) );
void TimerA0Int( void ) 
{
 P1OUT ^= BIT6;
 if ( counter == 5 ) {
  counter = 0;
  second++;
  P1OUT ^= BIT0;
  if ( second > 7 ) {
   TA0CTL = 0; //stop timer
   second = 0;
  }
 } 
 counter++;
}

11,12 - setting calibrated values to have more accurate 1MHz clock
17 - 22 - setting BIT3 PORT1 interrupt
24,25 - setting pins to drive led
26 - this is msp430gcc macro which handle Special Register, here we enable General interrupt enable. When set, enable maskable interrupts ( all except nmi interrupt )
28 - just do nothing and wait for interrupts.
36 - we use switch so we can handle more pins in future
38 - this is important we must clear this bit by software, so we won't renter interrupt again. Normally when there is one interrupt source it's cleared automatically but here we want to check which pin invoke interrupt.
39 - We start our timer so leds will start blinking
44 - It is isr for our timer compare interrupt. One led blinks fast another slower, we blink 7 second and then stopping timer.

Uff, I never thought writing tech blog is so time-consuming and hard. I think my explanation of interrupts and timers is very superficial so don't hesitate and ask question so i can explain more.

Friday, October 19, 2012

Making thinks easier with make and geany


This post will be about speeding things, from previous post we know how we made program for uC step by step. It is good to now how things work under the hood but for everyday development it's to time consuming so we will use very common and easy tools to help us out.

1. Make program.

Make know how to compile, link and download program to microcontroller. Whole procedure is described in file called "Makefile". We can define partial goals and variables and many other useful things to automate our process.

In this example i will use very simple makefile so it is easy to understand and control:
Important, when you write your makefile make sure command(e.g. line 10) after goal starts with <TAB>

PROJ=blink
CC=msp430-gcc
MCU=msp430g2553
CFLAGS=-Os -g -Wall -mmcu=$(MCU)
LDFLAGS=-g -mmcu=$(MCU)

OBJS=main.o

all:$(OBJS)
       @echo linking: $(PROJ).elf
       $(CC) $(LDFLAGS) -o $(PROJ).elf $(OBJS)
       @echo  "--== Size of firmware ==--"
       msp430-size $(PROJ).elf
%.o:%.c %.h
       @echo compiling file: $<
       $(CC) $(CFLAGS) -c $<

clean:
       @echo cleaning $<
       rm -fr $(PROJ).elf $(OBJS)


flash: all
       mspdebug rf2500 'erase' 'load $(PROJ).elf' 'exit'


First four lines are just defining variables for our compiler exec, mcu type, compiler,linker flags and objects to compile. When we want to add more file to our project we just
Next we define our goals:
all - creates our executable file and prints size statistics.
%.o - we tell that we want to build object files so make finds %.c files and compile them using command that is given below. After colon we add files that when changed force compilation.
clean - remove all object and elf files ( it's handy when you want to be sure for recompiling program )
flash - download our elf file to uC, word after colon tells that before flashing program needs to achieve goal "all".
Now we put this file in directory where our main.c file is and execute command:
make
Output:

msp430-gcc -Os -g -Wall -mmcu=msp430g2553   -c -o main.o main.c
linking: blink.elf
msp430-gcc -g -mmcu=msp430g2553 -o blink.elf main.o 
--== Size of firmware ==--
msp430-size blink.elf
   text   data    bss    dec    hex filename
    144      0      2    146     92 blink.elf


Make looks for our makefile and compile and link our program.
If we want to make our other goals we must invoke make with name of this goal:
make flash
make clean

To have permission for our lauchpad as normal user( no need to use sudo before make flash ) we have to make file with rules which will tell that launchpad can be used users that are in group for example dialout.

sudo vim /etc/udev/rules.d/46-TI_launchpad.rules

content:
ATTRS{idVendor}=="0451", ATTRS{idProduct}=="f432", MODE="0660", GROUP="dialout"

Now we have to add our user to dialout group and restart udev rules:
sudo usermod -a -G dialout our_user_name

sudo restart udev


2.Geany


Geany is nice little IDE for programing, we combine our makefile with geany so everything will be available after mouse click . To install geany:

sudo apt-get install geany
cd ~/our_project_dir
geany main.c




From menu we choose "Build"->"Set Build Commands" and we can fill like this:
"Compile" -> "make" 
"Build" -> "make clean; make" ( so we are sure we rebuild all project )
"Execute" -> "make flash"

Now everything we need is to press "F5" or nice gear icon to compile and download our project to launchpad:)


Monday, October 15, 2012

Hello world program in microntrollers world


Our first program: blinking led:

Some microcontroller theory:
Info about one of the launchpad's microcontroller.
Info about whole familly msp430x2xxx
http://www.ti.com/litv/pdf/slau144i

- msp430 low power 16-bit microcontroller
- handy peripherals
- flexible clock system ( 32 KHz external crystal )
- on board programmer and debugger
- usb to uart bridge ( only 9600 bps )
- two leds, user and reset button


Some led blinking theory:
What do we need to light the led:
- power source
- optimal voltage and current level
- polarization
- led:)
How it looks like with uC:
- led is turning on and off by microcontroller pin
- uC pin capabilities 6 mA, all pins 48 mA


Source for our first program:

#include <msp430.h>
void delay( unsigned int delay )
{
        unsigned int i;
        for ( i = 0; i < delay; i++) asm("nop");
}

int main()
{
        WDTCTL = WDTPW + WDTHOLD;       // Stop WDT     
        P1DIR |= BIT0;

        while(1) {
                P1OUT ^= BIT0;
                delay( 50000 );
        }
        return 0;
}
1 - include header file for names of special registers, peripheral registers, vector addreses and so on

2 - msp430 is very fast
Delay to see led blinking, using nop - no operation instruction( to be sure compiler won't cut it ). In this case, it will loop until the variable i increments to delay value.

10 - turning off watchdog:
This line of code turns off the watchdog timer, which can reset the device after a certain period of time.

11 - setting pin to output
P1DIR is a register that configures the direction (DIR) of a port pin as an output or an input.
Register is just address in ram memory.
To set a specific pin as output or input, we write a '1' or '0' on the appropriate bit of the register.
P1DIR = <PIN7><PIN6><PIN5><PIN4><PIN3><PIN2><PIN1><PIN0>
P1DIR = 0000 0001
P1DIR = 0x01     <-- this is the hexadecimal conversion of 0000 0001
For second led P1.6
P1DIR = 0100 0000
P1DIR = 0x40     <-- this is the hexadecimal conversion of 0100 0000

13 - never ending loop, our program will run forever:D

14 - P1OUT is another register which holds the status of the LED.
'1' specifies that it's ON or HIGH, while '0' specifies that it's OFF or LOW
Since our LED is tied to P1.0, we will toggle the 0 bit of the P1OUT register

17 - return 0 - just for compiler doesn't complain

Compiling...
msp430-gcc -Os -Wall -g -mmcu=msp430g2553 -c main.c
Os - code optimalization for efficient size
Wall - give us warnings to produce cleaner code
g - is used to embed debug info
mmcu=msp430g2553 - tells compiler which uC exactly do we use
c - compile and don't link!

Linking..
msp430-gcc  -g  -mmcu=msp430g2553 -o main.elf main.o
-we specify mmcu again that compiler knows which start-up files and run-time libraries to choose.
o - output file name and after this we give name of our compiled program this section can contain many files that's why we split it whole thing into compiling and linking part.

Downloading to launchpad...
sudo mspdebug rf2500 'erase' 'load main.elf' 'exit'
rf2500 - this is name of the launchpad programmer/debuger.
After this we give set of command or we could type them when (mspdebug) prompt appears.
Be sure to invoke this command where our file "main.elf" so we don't have to give full path.

If everything goes "ok" red led should start to blink:D


Firts steps to work with msp430 launchpad on linux


Installing linux on pendrive.


This example will be based on ubuntu 12.04 linux distribution. You can choose from every distributions that derive from it like LUBUNTU or MINT. Ubuntu distribution can be installed with preservance space on pendrive so you can keep changing data beetwen reboots.

http://unetbootin.sourceforge.net/

- download binary for yours operating system ( can be windows:)
- run and choose distribiton: Lubuntu version 12.04 live
- specify amount of space to preserve files across reboot ( 1GB min )
- after succesful installation boot your new linux system from pendrive:)

Install compiler, binutlis, c library for msp430.

sudo apt-get install binutils-msp430 gcc-msp430 msp430-libc

binutlis-msp430  - utlis like assembler, linker, objdump
gcc-msp430 - compiler
msp430-libc - standard C library

For newer version or if you distribution doesn't have packages you can compile it for yourself using Energia build script or download precompiled binaries from https://github.com/energia/Energia/downloads

wget https://github.com/downloads/energia/Energia/energia-0101E0008-linux.tgz
tar -zxvf energia-0101E0008-linux.tgz energia-0101E0008/hardware/tools/msp430
sudo mv energia-0101E0008/hardware/tools/msp430 /opt/
sudo apt-get install libgmp3c2 libmpfr4 libmpc2
If your system doesn't have libgmp3c2 in repository install manually:
wget http://ubuntu.mirror.cambrium.nl/ubuntu//pool/main/g/gmp/libgmp3c2_4.2.2+dfsg-1ubuntu2_i386.deb
sudo dpkg -i libgmp3c2_4.2.2+dfsg-1ubuntu2_i386.deb
rm -rf energia-0101E0008 energia-0101E0008-linux.tgz

Add this line to your ~/.bashrc file: 
"export PATH=$PATH:/opt/msp430/bin" 
so we can execute programs from this path. 
Open new terminal window and type:
msp430-gcc 
You should see:
msp430-gcc: fatal error: no input files
compilation terminated.
This is ok:D

Compile debuger and programmer for msp430 mspdebug.

Download from: http://mspdebug.sourceforge.net/download.html

cd ~/Download
wget http://sourceforge.net/projects/mspdebug/files/mspdebug-0.20.tar.gz
sudo apt-get install make libusb-dev
tar -xvzf mspdebug-0.20.tar.gz
cd mspdebug-0.20
make WITHOUT_READLINE=1
sudo make install

Connect launchpad to usb port and issue this command:

sudo mspdebug rf2500

If everything went ok you should see prompt (mspdebug) 

Now we have everything we need to write our first program on launchpad.

Friday, October 12, 2012

Introduction

Hello,

I'm electronic hobbyist. I want to share my knowledge about using msp430 launchpad on linux based system, currently I'm using linux mint 13 mate.

MSP40 launchpad kit is great for it's price and because it so cheap and easily available from ti store you can have plenty of them for every project you want.