Skip to content

Instantly share code, notes, and snippets.

@RickKimball
Last active January 1, 2018 16:28
Show Gist options
  • Save RickKimball/ead0b3b0f28f0dbf426c51f46ced59ab to your computer and use it in GitHub Desktop.
Save RickKimball/ead0b3b0f28f0dbf426c51f46ced59ab to your computer and use it in GitHub Desktop.
MSP430 - skeleton standalone assembler project for msp430-elf-gcc and mspdebug
target remote localhost:2000
monitor reset
monitor erase
load blinkasm.elf
b
disassemble
nexti
disassemble
nexti
info registers
b timer0_toggle
continue
;-------------------------------------------------------------------------------
; blinkasm.S - gcc compatible interrupt driven led blinker in msp430 asm
;
; Version 1.0 - 10/22/2011 [email protected]
; Version 1.01 - 7/22/2014 [email protected] modified for msp430-elf-gcc
; Version 1.02 - 11/02/2014 [email protected] more changes for msp430-elf-gcc
; $ msp430-elf-gcc blinkasm.S -D_GNU_ASSEMBLER_ -Wall -Os -g \
; -fdata-sections -ffunction-sections -mmcu=msp430g2553 -T \
; -T msp430g2553.ld -I/tmp/a/include -L /tmp/a/include/ -nostdlib
;
;-------------------------------------------------------------------------------
.file "blinkasm.S"
#include <msp430.h>
;-------------------------------------------------------------------------------
;;; ---- gcc doesn't know about PC,SP,SR,CG1,CG2 ----
#define PC r0
#define SP r1
#define SR r2
;-------------------------------------------------------------------------------
;;; ---- CONSTANTS ----
//#define TEST_IRQ_OVERHEAD
#ifndef TEST_IRQ_OVERHEAD
#define _50USEC (50-1) /* @1MHz MCLK results in 50uSec/interrupt */
#define _500MSEC 10000 /* @1MHz MCLK results in 500ms/LED toggle */
#else
;; This test illustrates the minimum CCR0 value that can be used
;; 22 cycles is based on the interrupt overhead
#define _50USEC 22 /* @1MHz MCLK results in 23uSec/interrupt */
#define _500MSEC 1 /* @1MHz MCLK results in 23uSec/LED toggle */
#endif
#define _LED_PIN BIT6 /* PORT1 pin, Launchpad has BIT0=Red and BIT6=Green */
;-------------------------------------------------------------------------------
;;; ---- Registers used as globals ----
#define LED_PIN r4
#define TIMER_CYCLES r5
#define INTERVAL_CNT r6
#define CNT r7
;; or you could use some ram variables
.lcomm tcycles,2 ; example use of local bss data variable
.lcomm cnt,2 ; example use of local bss data variable
;-------------------------------------------------------------------------------
.section .text,"ax",@progbits
;-------------------------------------------------------------------------------
_start:
;; disable watchdog and set stack to highest RAM addr
mov.w #WDTPW|WDTHOLD,&WDTCTL
mov.w #__stack,SP ; gcc ldscripts compute __stack based on mmcu
;; initialize clock,gpio,timer
init:
;; configure DCO to precalibrated 1MHz
clr.b &DCOCTL
mov.b &CALBC1_1MHZ,&BCSCTL1
mov.b &CALDCO_1MHZ,&DCOCTL
;; initialize global register values
mov.w #_LED_PIN,LED_PIN ; load constant into register constant
mov.w #_50USEC,TIMER_CYCLES ; load constant into register constant
mov.w #_500MSEC,INTERVAL_CNT ; load constant into register constant
mov.w INTERVAL_CNT,CNT ; initialize register based counter
;; initialize GPIO
bic.b LED_PIN,&P1OUT ; LED turned off to start
bis.b LED_PIN,&P1DIR ; Configure P1.0 as output pin
;; initialize TimerA0
mov.w #CCIE,&TA0CCTL0 ; Enable TA0CCR0 interrupt
mov.w TIMER_CYCLES,&TA0CCR0 ; Set TIMER_CYCLES cycles
mov.w #TASSEL_2|MC_2,&TACTL ; SMCLK, Continuous Up Mode
;; enable interrupts and loop forever
;; real work done in the CCR0 interrupt
nop
eint
loop:
;; Note: could sleep here instead
jmp loop ; cycles:2
;-------------------------------------------------------------------------------
; TIMER0_A0_ISR - TimerA0 CCR0 interrupt handler
;-------------------------------------------------------------------------------
TIMER0_A0_ISR:
;; before we even start running the mcu does a push PC, and a push SR cycles:6
dec.w CNT ; have we looped INTERVAL_CNT times? cycles:1
jnz 1f ; exit if we haven't reached 0 cycles:2
;; toggle led pin after (INTERVAL * TIMER_CYCLES) has occured
xor.b LED_PIN,&P1OUT ; cycles:4
mov.w INTERVAL_CNT,CNT ; reinitialize interval counter cycles:1
1:
add.w TIMER_CYCLES,&TA0CCR0 ; set new CCR0 and go again cycles:4
reti ; cycles:5
;------------------------------------------------------------------------------
; UNEXPECTED_ISR - default handler for unhandled interrupt
;-------------------------------------------------------------------------------
UNEXPECTED_ISR:
reti ; cycles: 5
;------------------------------------------------------------------------------
; Interrupt Vectors - see the datasheet for your chip
; *msp430g2553 vectors described below
;------------------------------------------------------------------------------
.section "__interrupt_vector_10","ax",@progbits
.word TIMER0_A0_ISR ;0xfff2 (TIMER0_A0_VECTOR)
.section ".resetvec","ax",@progbits
.word _start ;0xfffe (RESET_VECTOR)
.end
; vim: ts=8 sw=8 expandtab:
#
# Makefile - blinkasm.elf
#
# Author: Rick Kimball
# email: [email protected]
# Version: 1.04 Initial version 10/21/2011
#
APP = blinkasm
MCU ?= msp430g2553
# MSP430_DEV_IN should be the directory where *.ld and devices.csv are located
MSP430_DEV_INC ?= ${HOME}/opt64/msp430-elf/include
CC=msp430-elf-gcc
CXX=msp430-elf-g++
COMMON=-Wall -Os -g -I./ -I $(MSP430_DEV_INC)
CFLAGS += -mmcu=$(MCU) $(COMMON)
CXXFLAGS += -mmcu=$(MCU) $(COMMON)
ASFLAGS += -mmcu=$(MCU) $(COMMON)
LDFLAGS = -L $(MSP430_DEV_INC) -Wl,-Map,$(APP).map -nostdlib -nostartfiles -T $(MCU).ld
all: $(APP).elf
$(APP).elf: $(APP).o
$(CC) $(CFLAGS) $(APP).o $(LDFLAGS) -o $(APP).elf
msp430-elf-objdump -Sd -W $(APP).elf >$(APP).lss
msp430-elf-size $(APP).elf
msp430-elf-objcopy -O ihex blinkasm.elf blinkasm.hex
install: all
mspdebug --force-reset rf2500 "prog $(APP).elf"
cycle_count: all
naken430util -disasm $(APP).hex > $(APP)_cc.txt
debug: all
clear
@echo -e "--------------------------------------------------------------------------------"
@echo -e "-- Make sure you are running mspdebug in another window --"
@echo -e "--------------------------------------------------------------------------------"
@echo -e "$$ # you can start it like this:"
@echo -e "$$ mspdebug rf2500 gdb\n"
msp430-elf-gdb --command=blinkasm.gdb $(APP).elf
clean:
rm -f $(APP).o $(APP).elf $(APP).lss $(APP).map $(APP).hex $(APP)_cc.txt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment