Submissions by Harley tagged assembly

Went through and added TODO markers for all incomplete words. Made stubs for several subroutines. Implemented MUL & DIVMOD as well as untested >CFA & INTERPRET.

I think I mentioned this before, but the one thing I dislike about MSP430 assembly is the lack of multiplication & division mnenomics. That said, the naive multiply function is trivial:

/* Arguments are passed in r12 & r13, r15 is used to store the result */
    clr r15
1:  add r12, r15   /* ignores overflow */
    dec r13
    jnz 1b
/* To comply with the MSP430 GCC calling convension, the result would be put back into r12 */

Division is a bit more complicated, but still didn't seem too bad. I'm not posting that because I haven't done any verification of it yet. This one at least had minimal testing in isolation.

mul.S187 bytes
2 downloads

MSP430

A submission for Code @Home 27

Didn't get much done tonight. Found the msp430-elf-run command. Fixed some things when running it.

Keeping it short tonight since I've been terrible about sleeping a proper amount at night.

Shortly after posting last night, I remembered that I should be looking at the linker script for hints as to what it's expecting. Sure enough, up by the top there's something like:

__interrupt_vector_9   : { KEEP (*(__interrupt_vector_9 )) KEEP (*(__interrupt_vector_timer0_a1)) } > VECT9

So, of course I tested the human readable version

.macro SECTION_VECTOR vector
.section __interrupt_vector_\vector,"ax",@progbits
.endm

.global test_int
SECTION_VECTOR timer0_a1
.word test_int
.text
test_int:
    push r9
    mov #9, r9
    pop r9
    reti

Compiled it and did an objdump -S:

Disassembly of section __interrupt_vector_9:

0000fff0 <__interrupt_vector_9>:
    fff0:       2e c1           interrupt service routine at 0xc12e

0000c12e <test_int>:
    c12e:       09 12           push    r9              ;
    c130:       39 40 09 00     mov     #9,     r9      ;
    c134:       39 41           pop     r9              ;
    c136:       00 13           reti

So there you have it. Mystery solved (or at least, was a mystery to me.) They were nice enough to allow a tolower version of the vector name appended to __interrupt_vector_ be used to lookup the expected name. This was much easier than the weird preprocessor macro expansion I was trying to get working last night.

I seem to be unable to find the documentation regarding interrupts (especially with regard to the generated assembly.) I decided to write a quick C test to figure out what it's expecting. It's interesting, but not surprising, the old toolchain and new toolchain produce interrupts differently.

#include <msp430.h>
#define t_int(i) void __interrupt(i) test_##i() {}
t_int(TRAPINT_VECTOR)
t_int(PORT1_VECTOR)
t_int(PORT2_VECTOR)
t_int(ADC10_VECTOR)
t_int(USCIAB0TX_VECTOR)
t_int(USCIAB0RX_VECTOR)
t_int(TIMER0_A1_VECTOR)
t_int(TIMER0_A0_VECTOR)
t_int(WDT_VECTOR)
t_int(COMPARATORA_VECTOR)
t_int(TIMER1_A1_VECTOR)
t_int(TIMER1_A0_VECTOR)
t_int(NMI_VECTOR)
t_int(RESET_VECTOR)

compiled with:

msp430-elf-gcc -I$MSPGCC/include -mmcu=msp430g2553 -S test_inter.c

It results in (just a snippet):

        .balign 2
        .global test_TIMER0_A0_VECTOR
        .section        __interrupt_vector_10,"ax",@progbits
        .word   test_TIMER0_A0_VECTOR
        .text
test_TIMER0_A0_VECTOR:
; start of function
; attributes: interrupt 
; framesize_regs:     0
; framesize_locals:   0
; framesize_outgoing: 0
; framesize:          0
; elim ap -> fp       2
; elim fp -> sp       0
; saved regs:(none)
        ; start of prologue
        ; end of prologue
        ; start of epilogue
        RETI
        .size   test_TIMER0_A0_VECTOR, .-test_TIMER0_A0_VECTOR

A similar macro

#define t_int(i) void __attribute__((interrupt(i))) test_##i() {}

for the old toolchain produced:

        .p2align 1,0
.global test_TIMER0_A0_VECTOR
        .type   test_TIMER0_A0_VECTOR,@function
/***********************
 * Interrupt Vector 9 Service Routine `test_TIMER0_A0_VECTOR' 
 ***********************/
test_TIMER0_A0_VECTOR:
.global __isr_9
__isr_9:
        push    r4
        mov     r1, r4
        add     #2, r4
        pop     r4
        reti
.Lfe7:
        .size   test_TIMER0_A0_VECTOR,.Lfe7-test_TIMER0_A0_VECTOR
;; End of function

It's interesting that the new toolchain puts the interrupt in a different section, while the old toolchain has a predefined global that, I'm assuming, the linker knows to look for. Not sure which one I like, but both feel relatively under documented.

I got stuck mostly in setting up environments last night. I thought I hadn't really done much with my FIGnition yet, so I'd plug that in and go. It didn't take long to realize why I had been slow to really get full swing with it, QWERTY default. FIGkeys seems to allow most keys to be remapped, but requires a number pad. I decided to wait until tomorrow to get a PS2 or USB keyboard with a number pad.

Then I decided to get my BeagleBone Black setup. I tried Cloud9 a bit, but then decided to install Go. I forgot there weren't pre-built Go ARM/Linux packages. I pulled down Go from git, checked out the 1.4.1 tag, and started the build. When I realized it was going to take some time, I went on to the next thing.

Next thing was playing with the Launchpad some more trying to load mspforth, CamelForth, & Mecrisp, all without much luck of getting a serial connection. One thing that stuck out to me was that newer Launchpad boards potentially changed the USB serial pins. As a last ditch, even though none of the Forths seemed to support it, I fired up my new MSP430F5969 Launchpad, but Energia said I needed to update the drivers, which failed on Linux. Had to download a tool from TI that appeared to repair it. Tried again, and the update failed again. After repairing a second time, I decided to call it a night.

Overall, I didn't touch much code, but I did a bit with MSP430 assembly with naken_asm => msp430-gcc conversion, but nothing really worth posting.

This is an MSP430 assembly reimplementation of my day #1. One of the things that I really like about the MSP430 instruction set is that there are 52 instructions & 7 addressing modes. Because of this, I think the assembly tends to be very easy to follow. I did, however, get a bit lazy when writing this. The 6 local labels likely make this code a bit odd to read (especially without looking at the equivalent C code.) It's about 10 bytes larger than the C code compiled with -O

speaker.S702 bytes
2 downloads