Dec 112010
 
RX: H8 modernized

H8 evolved to H8S which evolved to H8SX which evolved into the RX line of Renesas. It’s not another RISC CPU, which usually would not matter at all as everyone uses C/C++ for programming microcontrollers (yes, I know, exceptions do exist), but for short code like the startup code, a little bit of assembler is still needed. Neither ARM nor MIPS nor SPARC assembler is fun to read or write.

Here some examples taken from a software I2C driver inspired from the I2C driver from MES:

C code:

union un_p6dr {                                         /* union P6DR   */
              unsigned char BYTE;                       /*  Byte Access */
              struct {                                  /*  Bit  Access */
                     unsigned char B7:1;                /*    Bit 7     */
                     unsigned char B6:1;                /*    Bit 6     */
                     unsigned char B5:1;                /*    Bit 5     */
                     unsigned char B4:1;                /*    Bit 4     */
                     unsigned char B3:1;                /*    Bit 3     */
                     unsigned char B2:1;                /*    Bit 2     */
                     unsigned char B1:1;                /*    Bit 1     */
                     unsigned char B0:1;                /*    Bit 0     */
                     }      BIT;
};
#define P6DDR   (*(volatile unsigned char   *)0xFEE005) /* P6DDR Address*/
#define P6DR    (*(volatile union  un_p6dr  *)0xFFFFD5) /* P6DR  Address*/

#define I2CDDR  P6DDR
#define SDA_MASK 0x01
#define SCL_MASK 0x02
#define SDA     P6DR.BIT.B0
#define SCL     P6DR.BIT.B1

void i2c_stop(void)
{
  I2CDDR=SDA_MASK|SCL_MASK;
  SDA=0;
  SCL=1;
  wait_us(4);
  SDA=1;
}

AVR (8 bit RISC):

i2c_stop:
        push r16
        push r17
/* prologue: function */
/* frame size = 0 */
        ldi r24,lo8(3)
        sts -8187,r24
        ldi r16,lo8(-43)
        ldi r17,hi8(-43)
        mov r30,r16
        mov r31,r17
        ld r24,Z
        andi r24,lo8(127)
        st Z,r24
        ld r24,Z
        ori r24,lo8(64)
        st Z,r24
        ldi r24,lo8(4)
        ldi r25,hi8(4)
        rcall wait_us
        mov r30,r16
        mov r31,r17
        ld r24,Z
        ori r24,lo8(-128)
        st Z,r24
/* epilogue start */
        pop r17
        pop r16
        ret

MIPS (32 bit):

i2c_stop:
        .set    nomips16
        .frame  $sp,24,$31              # vars= 0, regs= 2/0, args= 16, gp= 0
        .mask   0x80010000,-4
        .fmask  0x00000000,0
        .set    noreorder
        .set    nomacro

        addiu   $sp,$sp,-24
        li      $3,3
        li      $2,16711680                     # 0xff0000
        sw      $31,20($sp)
        sw      $16,16($sp)
        li      $16,16777216                    # 0x1000000
        sb      $3,-8187($2)
        lbu     $2,-43($16)
        li      $3,-2                   # 0xfffffffffffffffe
        and     $2,$2,$3
        sb      $2,-43($16)
        lbu     $3,-43($16)
        li      $4,4                    # 0x4
        ori     $3,$3,0x2
        sb      $3,-43($16)
        jal     wait_us
        nop

        lbu     $2,-43($16)
        nop
        ori     $2,$2,0x1
        sb      $2,-43($16)
        lw      $31,20($sp)
        lw      $16,16($sp)
        j       $31
        addiu   $sp,$sp,24

H8/300H (16 bit):

_i2c_stop:
        mov.w   r6,@-r7
        mov.w   r7,r6
        mov.w   r4,@-r7
        mov.b   #3,r2l
        mov.b   r2l,@-8187:16
        mov.w   #-43,r4
        bclr    #0,@r4
        bset    #1,@r4
        mov.w   #4,r0
        jsr     @_wait_us
        bset    #0,@r4
        mov.w   @r7+,r4
        mov.w   @r7+,r6
        rts

RX (16/32 bit):

_i2c_stop:
        push.l  r7
        mov.L   #0xfee005, r14
        mov.L   #0xffffd5, r7
        mov.B   #3, [r14]
        mov.B   [r7], r14
        mov.L   #4, r1
        bclr    #7, r14
        mov.B   r14, [r7]
        mov.B   [r7], r14
        bset    #6, r14
        mov.B   r14, [r7]
        bsr     _wait_us
        mov.B   [r7], r14
        bset    #7, r14
        mov.B   r14, [r7]
        rtsd    #4, r7-r7

x86_64 (64 bit):

i2c_stop:
        .cfi_startproc
        subq    $8, %rsp
        .cfi_def_cfa_offset 16
        movb    $3, 16703493
        movzbl  16777173, %eax
        movl    $4, %edi
        andl    $127, %eax
        movb    %al, 16777173
        movzbl  16777173, %eax
        orl     $64, %eax
        movb    %al, 16777173
        call    wait_us
        movzbl  16777173, %eax
        orl     $-128, %eax
        movb    %al, 16777173
        addq    $8, %rsp
        ret

Easy to see why C wins this. ARM is not too bad too for a RISC CPU, but I have no example available. A notable oddity is that RX reversed bits (7,6 instead of 0,1). Not sure this is a bug or a feature.

Some more examples can be seen in the “99 bottles of beer” program examples under “A” like “assembler”.

It’s funny what makes one pick a microcontroller CPU. Since I don’t need performance or price for 1000 units, I can pick which assembler code looks easiest or nicest to me.
H8 and RX look like something readable and memorizable. In fact, H8 looks like Motorola M68k assembler. Both are said to be DEC PDP-11 related (see here and here)

Now this RX62N demo board is packed with interesting things and the price (US$99) is hard to beat. It also runs FreeRTOS since version 6.1, and Ethernet works too, which I have not yet working on my AKI-H8 board. And s JTAG based debugger is on-board too. And a graphics LCD. I think it’s a bargain similar to the STM32VLDiscovery or the STM8SDiscovery for each US$11.

Now let’s see how long Digikey takes to deliver them to Japan.

Update: 4 days.