After a bit of fighting, I've got a fully free software ez430 development setup working on Linux.
Although msp430uif (http://www.diva.com/downloads/) is simple and doesn't support gdb proxy operations, it reads and programs just fine. It's a matter of - Get the ez430 USB device ID into the list of devices supproted by the ti_usb_3410_5052 linux driver. (There are various patches floating around.) - After plugging the ez430 in, change the USB device to configuration 2, using echo 2 > /sys/bus/usb/devices/<varies>/bConfigurationValue or a udev script. (Also floating around the net) - Either set up a /dev/uif symlink to /dev/ttyUSB0, or specify the device on the uif430 command line. uif430 uses Intel-format hex files. When dumping, it forgets to include the terminating end line, an easy fix. (I also hacked it to output 32 bytes per line, rather than 16.) Anyway, when playing with mspgcc in earnest, I noticed a few things. In case they're of any use to someone: gcc/gcc-3.3/msp430.h: - Why do the I and J ranges start at -32767 and not -32768? gcc/gcc-3.3/msp430.md: - In all of the standard ALU instructions, why not collapse same-size options together. E.g. (define_insn "*addhi3_3" [(set (match_operand:HI 0 "nonimmediate_operand_msp430" "=m,m,r,r") (plus:HI (match_operand:HI 1 "nonimmediate_operand_msp430" "%0,0,0,0") (match_operand:HI 2 "general_operand_msp430" "rP>,mi,rP>,mi")))] "" "add %2, %0" [(set_attr "length" "2,3,1,2") (set_attr "cc" "set_czn,set_czn,set_czn,set_czn")]) gcc/gcc-3.3/msp430.c file: - Why is the "task" attribute distinct from "noreturn"? - Could we allow __attribute__((interrupt(0xfff0))) instead of having to remember of that's interrupt 8 or 24 on this particular processor? - In function_prologue(), the naked prologue generation code appears twice; the second is redundant. msp430-libc/src/gcrt0.S: - Why is _unexpected_1_ there? Why not vector straight to _unexpected_? libgcc.S: - Why does __prologue_saver not use push instructions? - Could that first instruction in _reset_vector__ be clarified as: mov $0x5a80,&0x120 ; Stop the watchdog timer (WDTHOLD) - How about improving the copy loop that follows that to: mov #_etext,r15 mov #_edata-__data_start+_etext,r13 jmp 2f 1: mov.b @r15+,__data_start-_etext-1(r15) 2: cmp r13,r15 jlo 1b /* Clear BSS */ mov #__bss_end-__bss_start,r13 jmp 2f 1: mov.b #0,__bss_start(r13) ; 2/4 2: dec r13 ; 1/1 jc 1b ; 1/2 br #main - Can we assume that the data and bss segements are always 2-byte aligned, or is that a bad idea? ctype.h: - How about simplifying it to: extern inline int isascii(int c) { return (c & ~0x7f) == 0);} extern inline int isdigit(int c) { return c >= '0' && c <= '9';} extern inline int isprint(int c) { return c >= ' ' && c < 127;} extern inline int isblank(int c) { return c == ' ' || c == '\t';} extern inline int isupper(int c) { return c >= 'A' && c <= 'Z';} extern inline int islower(int c) { return c >= 'a' && c <= 'z';} extern inline int isalpha(int c) { return islower(c | 0x20); } extern inline int isalnum(int c) { return isalpha(c) || isdigit(c);} extern inline int isxdigit(int c) { return isdigit(c) || ((c|0x20) >= 'a' && (c|0x20) <= 'f'); } extern inline int ispunct(int c) { return isprint(c) && !isalnum(c) && c != ' '; } /* Since our islower() and isupper() return 0 or 1... */ extern inline int toupper(int c) { return c - 0x20 * islower(c);} extern inline int tolower(int c) { return c + 0x20 * isupper(c);} extern inline int toascii(int c) { return c & 0x7f; } iomacros.h: - Why do WRITE_SR() and WRITE_SP not take a "g"eneral source operand? There's no need for it to be "r". Likewise, READ_SR() and READ_SP can allow "ro" outputs (anything except post-increment). - Similarly, _BIS_SR and _BIC_SR can take a "g"eneral input. - It might be worth defining a single #ifdef __cplusplus #define EXTERN_C extern "C" #else #define EXTERN_C /* null string */ #endif and then eliminating a lot of other #ifdef __cplusplus code. For example, you can simplify #ifndef NAKED #define NAKED(x) \ EXTERN_C void x(void) __attribute__((naked)); \ void x(void) #endif common.h: - It would be nice to parenthesize the LPMx_bits macros, so that something like "WRITE_SR(LPM3_bits | GIE)" doesn't warn. Compiler output: - The interrupt attribute should imply attribute((used)). Otherwise, a static interrupt handler with no explicit call will be deleted by the optimizer, with resultant unhappiness. - I find that mspgcc is remarkably bad at generating autoincrement addressing modes. Even if I really try to generate it using a ">,g!???" operand constraint. (If I only allow ">", I get a compiler error.) - I'm used to the way that gcc in a 68000 optimizes 32-bit loops using dbra (which only works on 16 bits). Surely the same technique can be used on the msp430? unsigned x; do {...} while (x--); should compile to 1: ... add #-1,x /* Or sub #1,x */ jc 1b This business of an explicit compare to -1 is silly. Likewise, if x is unsigned long, it should produce 1: ... add #-1,xlo /* Or sub #1,x */ jc 1b add #-1,xhi /* Or subc #0,x */ jc 1b if optimizing for speed, or 1: ... add #-1,xlo addc #-1,xhi jc 1b if optimizing for space.
