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.

Reply via email to