I got a simple and user friendly msp430 assembler for linux. It is the "naken430asm", developed by Michael Khon. It is free to download from his website http://www.mikekohn.net
Here are few example programs which I had done as a part of learning msp430 assembly language programming..
(microcontroller used -> MSP430G2231)
(assembler used ->naken430asm)
To familiarize the assembly language programming, I did some basic codes and tested it in the launchpad. Those codes are below...
Example .1
To turn on the RED led (P1.0) on the msp430 launchpad:
.include "msp430g2x31.inc"
org 0xf800
start:
mov.w #(WDTPW|WDTHOLD), &WDTCTL ; disable watchdog timer
mov.b #1,&P1DIR ; set P1.0 as output
mov.b #1,&P1OUT ; set P1.0 bit as high
loop1:
jmp loop1 ; infinite loop
org 0xfffe ; reset vector
dw 0xf800 ; pointing the reset vector to starting address
Steps to program the chip on the launchpad:
(assuming naken430asm and mspdebug are already installed)
- save the file as *.asm, say led.asm.
- in terminal, type naken430asm led.asm to generate the hex file.
- now using mspdebug, the hex file could be burned into the launhpad.
- command: sudo mspdebug rf2500
- type prog out.hex to program the chip.
- type run to run the code in chip
- to stop, press ctrl + c
Example .2
To blink RED led (P1.0)
.include "msp430g2x31.inc"
org 0xf800
start:
mov.w #(WDTPW|WDTHOLD), &WDTCTL
mov.b #1, &P1DIR
loop1:
xor.b #1, &P1OUT
mov #50000, r15 ;delay depends on the value moved to r15
delay:
dec r15
jnz delay
jmp loop1
org 0xfffe
dw start
Example .3
To toggle LED1 and LED2 (P1.0 ans P1.6)
.include "msp430g2x31.inc"
org 0xf800
start:
mov.w #(WDTPW|WDTHOLD), &WDTCTL
mov.b #(1|64), &P1DIR ; set P1.0 as output
mov.b #1, &P1OUT
loop1:
xor.b #(1|64), &P1OUT
mov #0xffff, r15
delay:
dec r15
jnz delay
jmp loop1
org 0xfffe
dw start
Example .4
To toggle LED1 and LED2 (P1.0 ans P1.6)- (delay as a function)
.include "msp430g2x31.inc"
org 0xf800
;;;;;;;;DELAY FUNCTION;;;;;;;;;
delay:
mov.w #60000, r5
l1:
dec r5
jnz l1
ret
;;;;;;;;START;;;;;;;;;;;;;;;;;;
start:
mov.w #(WDTPW|WDTHOLD), &WDTCTL
mov.w #0x280, SP
;;;;;;;;MAIN;;;;;;;;;;;;;;;;;;;
main:
mov.b #01000001b, &P1DIR
mov.b #1, &P1OUT
mainloop:
xor.b #01000001b, &P1OUT
call #delay
jmp mainloop
;;;;;;;;;VECTORS;;;;;;;;;;;;;;;
org 0xfffe
dw start
'call #delay' will call the delay function. What exactly happening is,
SP - 2 ->SP, PC+2 ->@SP, #delay ->PC
Now in 'ret' ,
@SP ->PC, SP+2 ->SP
Example .5
Timer interrupt on TAR overflow
.include "msp430g2x31.inc"
org 0xf800
start:
mov.w #(WDTPW|WDTHOLD), &WDTCTL
mov.w #0x280, SP
mov.b #255,&P1DIR
mov.b #0,&P1OUT
mov.w #(TASSEL_2|MC_2|ID_3|TAIE), &TACTL
eint
gg:
jmp gg
isr:
xor.b #1,&P1OUT ;toggle LED.1 on interrupt
bic.w #1, &TACTL ;clearing the TAIFG (flag)
reti
org 0xfffe ;reset vector
dw start
org 0xfff0
dw isr
Here, the LED.1 will toggle on every timer interrupt... On every timer overflow (TAR), the timer interrupt flag (TAIFG) will set.. Since GIE and TAIE is enabled, on every timer overflow, a timer interrupt will occur. At this time, the program counter will be loaded with the address stored in the timer interrupt vector address 0xfff0.
Example .6
Timer interrupt when TAR = TACCR0 (CCIFG)
.include "msp430g2x31.inc"
org 0xf800
start:
mov.w #(WDTPW|WDTHOLD), &WDTCTL
mov.w #0x280, SP
mov.b #255,&P1DIR
mov.b #0,&P1OUT
mov.w #(TASSEL_2|MC_1|ID_3), &TACTL
mov.w #(CCIE), &TACCTL0
mov.w #50000, &TACCR0
eint
gg:
jmp gg
isr:
xor.b #1,&P1OUT ; toggle LED1 on interrupt
reti
org 0xfffe ;reset vector
dw start
org 0xfff2
dw isr
In this case, the interrupt occur when the timer value (TAR) matches the TACCR0 value.. Here the interrupt vector(0xfff2) is different from the previous example. Also, instead of TAIE , CCIE is enabled... We could set the value of TACCR0 to adjust the time period of the periodic interrupt... Here, the CCIFG is cleared automatically in the hardware...
Example .7
Software implementation of a Linear Feedback shift register (LFSR)
(Pseudo random number generation)
(A 16-bit Fibonacci LFSR)
.include "msp430g2x31.inc"
org 0xf800
start:
mov.w #(WDTPW|WDTHOLD), &WDTCTL
mov.w #0x280, SP
mov.b #255,&P1DIR
mov #3323,R4 ;seed value in r4
loop1:
mov.b r4, &P1OUT ;showing 8 bit of the shift register in port1
mov r4,r5
mov r4,r10
rra r5
rra r5
xor r5,r10
rra r5
xor r5,r10
rra r5
rra r5
xor r5,r10
rra r4
bit #1,r10
jnz aa
bic #(1<<15),r4
jmp bb
aa:
bis #(1<<15),r4
bb:
mov #30000,r6
cc:
dec r6
jnz cc
jmp loop1
org 0xfffe ;reset vector
dw start
This is just a software implementation of a 16 bit fibonacci LFSR (in above figure)Here, register r4 emulates the linear feedback shift register. Instruction rra is used to shift one position to right. 8 bits of r4 is moved to PORT1 to show the 8 least bits of the LFSR on LEDs connected to PORT1. Also, if we connect a single LED at any of the P1 bits, we could observe the streaming of 'pseudo' random sequence. It is called 'pseudo' just because it is not really a random sequence even though it seems to be a ramdom sequence....
LFSR have great practical importance, for example:
Direct-sequence spread spectrum radio, Generating an approximation of white noice ,Cryptography etc.......
Example .8
1 second accurate timer using ACLK clock (32768Hz external crystal oscillator is to be soldered)
;---------------------------------------------------------
;author :vinod s (vinodstanur@gmail.com)
;date : sat June 9, 11:42:51PM
;PROCESSOR : MSP430G2231
;assembler : naken430asm
;development platform : linux
;NOTE: 32768Hz crystal must be soldered to the launchpad
; before doing this test program
;--------------------------------------------------------
.include "msp430g2x31.inc"
org 0xf800 ;flash begins
start: ;startup code which sets the stack pointer and disable WDT
mov.w #(WDTPW|WDTHOLD), &WDTCTL ;disabling watch dog timer, otherwise it will reset on regular interval
mov.w #0x27f, SP ;SETTING TOP OF THE STACK ON STACK POINTER
call #main ; NOT NEEDED ANY WAY :-)
main:
mov.b #0, &P1OUT
mov.b #1,&P1DIR ;setting port1 bit 0 as output
mov.b #(XCAP_3), BCSCTL3 ;selecting internal capacitor value for crystal
mov.w #32767, &TACCR0 ;seting the timer compare value for interrupt
mov.w #CCIE, &TACCTL0 ;compare interrupt enable
mov.w #(TASSEL_1|MC_1|TACLR), &TACTL ;setting the timer with ACLK clock
eint ;general interrupt enable
bis.b #(11011000b),SR ;entering LOW POWER MODE 3
;WILL NEVER REACH HERE (CPU OFF , SMCLK OFF)
isr: ;LED flashing routine which happens on every second
mov.b #1, &P1OUT
mov.w #10000, R10
small_delay_loop: dec.w R10
jnz small_delay_loop
mov.b #0, &P1OUT
reti
;VECTORS
org 0xfffe ;reset vector
dw start ;to write start address to 0xfffe on programming
org 0xfff2 ;timer interrupt vector (CC)
dw isr ;to write isr address to 0xfff2 on programming
Very good post. In the example number 2 you load the register "r15" with the number 50000. Can you tell me how long is the delay? Thank you very much.
ReplyDeletei have also published some examples based on msp430.
ReplyDeletehttp://emergingtechnologies1.blogspot.in/2014/05/msp-exp430g2-assembly-languge.html
How to set dco clock in assembly language.
ReplyDeletelove your post.
ReplyDeleteHappy Independence Day Quotes About India in Tamil 2018
There is now a clock course in assembly on Udmey.com entitled MSP430FR4311 Clock Operation Notes that pretty much does it all.
ReplyDelete