[CCC DEV] Transterpreter/Plumbing ported to the AT90CANxxx: First attempt and a problem

Stefan Heymer stefan.heymer at gmx.de
Thu Oct 21 13:32:31 BST 2010


Hi Matt, hi list,

First, thanks for the quick and detailed answer, didn't expect it in
that much detail that fast.

> ... I will say that you should definitely join the
> developers list (developers at concurrency.cc). ...

Here I am. :)

> We once gave a three-day workshop on CSP/occam at a telecomm firm in
> Vienna. It feels like a natural combo.

It definitely is, even though notations like MSC2000 and SDL from the
telcom field use a notion of asynchronuous communication. It would be
interesting to take such a specification and to try to translate it to
Occam-pi, for example with communication channels being modeled by
bounded buffer processes.

> Those look like fun parts -- if your work involves the CAN bus, and if
> you decide to do a CAN bus implementation in occam, I hope you'd be
> willing to share it. But, I digress...

CAN bus definitely is involved in my work, and I guess I could part with
something like a "simple" CAN mailbox implementation. :) For one of the
boards I use I could share the port --- the other two are proprietary
modules I brought home from work. The shareable board might even be
interesting in the aspect that it also incorporates an USB interface
(though the USB chip used is discontinued, and from personal experience,
is no fun to program).

> > for the enumeration of interrupts with a branch for the AT90s, listing
> > their interrupts, and mapping them later in the manner of the code for
>
> We often leave interrupts to "last", so to speak. Doing the
> enumeration work is fine, but I wouldn't make any of my test programs
> use interrupts. Get things working in a straight line, and then add
> the interrupts. But you know that. ...

Sure. Tests weren't _that_ far, I introduced the interrupt "names" and
vectors just for completeness.

> ... (For serial, we often do blocking
> serial first, to make sure things are good, and then we add in the
> interrupt-driven line.)

Ah, that's a good hint. Currently, I just ripped the two receive
channels rc2 and rc3 out of the implementation for the ATMega1280, and
left the remaining parts untouched.

> That sounds good. The devices are similar enough that it shouldn't be
an issue.

Yes, that's right what I thought, as there's no assembler code or more
specialised registers involved.

> >From what you're saying, it sounds like the first place I'd look is
> whether or not the TVM (our short name for the Transterpreter) is
> looking at the right location for the bytecode. That's a hard-coded
> value -- on the Arduino, it is 0x5000. ...

In the trunk from the SVN, this value is coded into the build script,
where it is changed to 0x5500 for the ATMega1280 --- my first guess at
the byte code address.

As the ATMega1280 is already in use in the Gator UAV, IIRC, this seemed
like a good address.

> ... You can probably pass that as a
> compile-time constant if you want, or change it in the sources. The
> point is, if the VM you compile doesn't know where to look, it will
> load garbage and fail.

This seems to be the case. My changes where all made in tvm/arduino,
where the address is already a parameter, is it possible that there's
also a change to be made in the tvm runtime library?

> > works with a virtual memory interface to cover the AVR's Harvard
> > architecture) wrong, and already raised the BYTECODE_ADDR to 0x6000 (as
> > the firmware is a bit bigger than for the Arduino).
>
> It looks like the AT90s have the same memory architecture...

Mostly. They have 2K/4K/4K of SRAM (AT90CAN32/64/128), and 32K/64K/128K
flash memory, the ATMega1280 having 8K SRAM and 128K flash.

> For the team: this is really one of those cases where I wish we had a
> distributed version control system... Stefan would have cloned/forked
> our project, made his edits, and we could just look at his code...

Well, please find enclosed the patch set for the changes I made. Nearly
as good as having me fork something. ;)

Have a nice day,

Stefan


diff -r -u -x '*.tb?' -x '*.o' -x '*.m4' -x '*.cache' -x .svn -x '*.in'
Native/kroc-svn/tvm/arduino/build.sh Arduino/kroc-svn/tvm/arduino/build.sh
--- Native/kroc-svn/tvm/arduino/build.sh    2010-10-20
11:55:35.266789368 +0200
+++ Arduino/kroc-svn/tvm/arduino/build.sh    2010-10-20
19:06:23.323910330 +0200
@@ -8,33 +8,49 @@
     autoreconf -vfi
 }
 
-MCUS="atmega328p atmega1280"
-FCPUS="16000000 8000000"
+MCUS="at90can64"
+FCPUS="16000000"
 # FCPUS="16000000"
 
-mcu="atmega1280"
-    for fcpu in $FCPUS
-    do
-        cleanup
-        ./configure \
-            --host=avr \
-            --with-bytecode-addr=0x5500 \
-            --with-mcu=$mcu \
-            --with-fcpu=$fcpu \
-            "$@"
-        make
-        make firmware.hex
-    done
+#mcu="atmega1280"
+#    for fcpu in $FCPUS
+#    do
+#        cleanup
+#        ./configure \
+#            --host=avr \
+#            --with-bytecode-addr=0x5500 \
+#            --with-mcu=$mcu \
+#            --with-fcpu=$fcpu \
+#            "$@"
+#        make
+#        make firmware.hex
+#    done
 
-mcu="atmega328p"
+#mcu="atmega328p"
+#    for fcpu in $FCPUS
+#    do
+#        cleanup
+#        ./configure \
+#            --host=avr \
+#            --with-mcu=$mcu \
+#            --with-fcpu=$fcpu \
+#            "$@"
+#        make
+#        make firmware.hex
+#    done
+
+mcu="at90can64"
     for fcpu in $FCPUS
     do
         cleanup
         ./configure \
             --host=avr \
+            --with-bytecode-addr=0x6000 \
             --with-mcu=$mcu \
             --with-fcpu=$fcpu \
             "$@"
         make
         make firmware.hex
     done
+
+
diff -r -u -x '*.tb?' -x '*.o' -x '*.m4' -x '*.cache' -x .svn -x '*.in'
Native/kroc-svn/tvm/arduino/configure.ac
Arduino/kroc-svn/tvm/arduino/configure.ac
--- Native/kroc-svn/tvm/arduino/configure.ac    2010-10-20
11:55:35.266789368 +0200
+++ Arduino/kroc-svn/tvm/arduino/configure.ac    2010-10-20
19:02:59.115909701 +0200
@@ -17,7 +17,7 @@
 
 AC_ARG_WITH([target-board],
             AC_HELP_STRING([--with-target-board=...],
-                           [target board (arduino, sanguino,
arduinomega, seeedmega)]),
+                           [target board (arduino, sanguino,
arduinomega, seeedmega, canboard)]),
             [target_board=$withval], [target_board=arduino])
 if test "x$target_board" = "xsanguino"
 then
@@ -38,6 +38,14 @@
     DUDEMCU=m1280
 fi
    
+if test "x$target_board" = "xcanboard"
+then
+    MCU=at90can64
+    DUDEMCU=c64
+    UPLOAD_RATE=115200
+    BYTECODE_ADDR=0x6000
+fi
+   
 # Defaults above are suitable for Arduino.
 if test "x$target_board" = ""
 then
diff -r -u -x '*.tb?' -x '*.o' -x '*.m4' -x '*.cache' -x .svn -x '*.in'
Native/kroc-svn/tvm/arduino/interrupts.c
Arduino/kroc-svn/tvm/arduino/interrupts.c
--- Native/kroc-svn/tvm/arduino/interrupts.c    2010-10-20
11:55:35.266789368 +0200
+++ Arduino/kroc-svn/tvm/arduino/interrupts.c    2010-10-20
17:45:06.878908602 +0200
@@ -54,6 +54,48 @@
     vintr_USART_TX3,
     NUM_INTERRUPTS
 };
+/*}}}*/
+/*{{{ AT90CANxxx enumeration */
+#elif defined(at90can32) || defined(at90can64) || defined(at90can128)
+enum {
+    vintr_INT0 = 0,
+    vintr_INT1,
+    vintr_INT2,
+    vintr_INT3,
+    vintr_INT4,
+    vintr_INT5,
+    vintr_INT6,
+    vintr_INT7,
+    vintr_TIMER2_COMP,
+    vintr_TIMER2_OVF,
+    vintr_TIMER1_CAPT,
+    vintr_TIMER1_COMPA,
+    vintr_TIMER1_COMPB,
+    vintr_TIMER1_COMPC,
+    vintr_TIMER1_OVF,
+    vintr_TIMER0_COMP,
+    vintr_TIMER0_OVF,
+    vintr_CANIT,
+    vintr_OVRIT,
+    vintr_SPI_STC,
+    vintr_USART_RX0,
+    vintr_USART_UDRE0,
+    vintr_USART_TX0,
+    vintr_ANALOG_COMP,
+    vintr_ADC,
+    vintr_EE_READY,
+    vintr_TIMER3_CAPT,
+    vintr_TIMER3_COMPA,
+    vintr_TIMER3_COMPB,
+    vintr_TIMER3_COMPC,
+    vintr_TIMER3_OVF,
+    vintr_USART_RX1,
+    vintr_USART_UDRE1,
+    vintr_USART_TX1,
+    vintr_TWI,
+    vintr_SPM_READY,
+    NUM_INTERRUPTS
+};
 #endif
 /*}}}*/
 
@@ -143,6 +185,8 @@
     ISR(vector) { \
         handle_interrupt (&interrupts[interrupt]); \
     }
+/*{{{ ATmega328 serial interrupts */
+#if defined(atmega328p)
 MAP_SIMPLE_INTERRUPT(INT0_vect, vintr_INT0)
 MAP_SIMPLE_INTERRUPT(INT1_vect, vintr_INT1)
 MAP_SIMPLE_INTERRUPT(PCINT0_vect, vintr_PCINT0)
@@ -152,8 +196,6 @@
 MAP_SIMPLE_INTERRUPT(TIMER2_OVF_vect, vintr_TIMER2)
 MAP_SIMPLE_INTERRUPT(ADC_vect, vintr_ADC)
 
-/*{{{ ATmega328 serial interrupts */
-#if defined(atmega328p)
 ISR(USART_RX_vect) {
     /* Disable the interrupt to stop it firing again immediately. */
     UCSR0B &= ~_BV (RXCIE0);
@@ -170,6 +212,15 @@
 /*}}}*/
 /*{{{ ATmega1280 serial interrupts */
 #elif defined(atmega1280)
+MAP_SIMPLE_INTERRUPT(INT0_vect, vintr_INT0)
+MAP_SIMPLE_INTERRUPT(INT1_vect, vintr_INT1)
+MAP_SIMPLE_INTERRUPT(PCINT0_vect, vintr_PCINT0)
+MAP_SIMPLE_INTERRUPT(PCINT1_vect, vintr_PCINT1)
+MAP_SIMPLE_INTERRUPT(PCINT2_vect, vintr_PCINT2)
+MAP_SIMPLE_INTERRUPT(TIMER1_OVF_vect, vintr_TIMER1)
+MAP_SIMPLE_INTERRUPT(TIMER2_OVF_vect, vintr_TIMER2)
+MAP_SIMPLE_INTERRUPT(ADC_vect, vintr_ADC)
+
 #define SERIAL_INTERRUPT(vect_RX, vintr_RX, \
                                                  vect_TX, vintr_TX, \
                                                  vect_UDRE, vintr_UDRE, \
@@ -192,6 +243,56 @@
 
 SERIAL_INTERRUPT(USART3_RX_vect, vintr_USART_RX3, USART3_TX_vect,
vintr_USART_TX3, USART3_UDRE_vect, vintr_USART_UDRE3, UCSR3B, RXCIE3,
UDRIE3)
 
+/*}}}*/
+/*{{{ ATmega1280 serial interrupts */
+#elif defined(at90can32) || defined(at90can64) || defined(at90can128)
+MAP_SIMPLE_INTERRUPT(INT0_vect, vintr_INT0)
+MAP_SIMPLE_INTERRUPT(INT1_vect, vintr_INT1)
+MAP_SIMPLE_INTERRUPT(INT2_vect, vintr_INT2)
+MAP_SIMPLE_INTERRUPT(INT3_vect, vintr_INT3)
+MAP_SIMPLE_INTERRUPT(INT4_vect, vintr_INT4)
+MAP_SIMPLE_INTERRUPT(INT5_vect, vintr_INT5)
+MAP_SIMPLE_INTERRUPT(INT6_vect, vintr_INT6)
+MAP_SIMPLE_INTERRUPT(INT7_vect, vintr_INT7)
+MAP_SIMPLE_INTERRUPT(TIMER2_COMP_vect, vintr_TIMER2_COMP)
+MAP_SIMPLE_INTERRUPT(TIMER2_OVF_vect, vintr_TIMER2_OVF)
+MAP_SIMPLE_INTERRUPT(TIMER1_CAPT_vect, vintr_TIMER1_CAPT)
+MAP_SIMPLE_INTERRUPT(TIMER1_COMPA_vect, vintr_TIMER1_COMPA)
+MAP_SIMPLE_INTERRUPT(TIMER1_COMPB_vect, vintr_TIMER1_COMPB)
+MAP_SIMPLE_INTERRUPT(TIMER1_COMPC_vect, vintr_TIMER1_COMPC)
+MAP_SIMPLE_INTERRUPT(TIMER1_OVF_vect, vintr_TIMER1_OVF)
+MAP_SIMPLE_INTERRUPT(TIMER0_COMP_vect, vintr_TIMER0_COMP)
+MAP_SIMPLE_INTERRUPT(CANIT_vect, vintr_CANIT)
+MAP_SIMPLE_INTERRUPT(OVRIT_vect, vintr_OVRIT)
+MAP_SIMPLE_INTERRUPT(SPI_STC_vect, vintr_SPI_STC)
+MAP_SIMPLE_INTERRUPT(ANALOG_COMP_vect, vintr_ANALOG_COMP)
+MAP_SIMPLE_INTERRUPT(ADC_vect, vintr_ADC)
+MAP_SIMPLE_INTERRUPT(EE_READY_vect, vintr_EE_READY)
+MAP_SIMPLE_INTERRUPT(TIMER3_CAPT_vect, vintr_TIMER3_CAPT)
+MAP_SIMPLE_INTERRUPT(TIMER3_COMPA_vect, vintr_TIMER3_COMPA)
+MAP_SIMPLE_INTERRUPT(TIMER3_COMPB_vect, vintr_TIMER3_COMPB)
+MAP_SIMPLE_INTERRUPT(TIMER3_COMPC_vect, vintr_TIMER3_COMPC)
+MAP_SIMPLE_INTERRUPT(TIMER3_OVF_vect, vintr_TIMER3_OVF)
+MAP_SIMPLE_INTERRUPT(TWI_vect, vintr_TWI)
+MAP_SIMPLE_INTERRUPT(SPM_READY_vect, vintr_SPM_READY)
+
+#define SERIAL_INTERRUPT(vect_RX, vintr_RX, \
+                                                 vect_TX, vintr_TX, \
+                                                 vect_UDRE, vintr_UDRE, \
+                                                 UCSRnB, RXCIEn, UDRIEn) \
+    ISR(vect_RX) { \
+    UCSRnB &= ~_BV (RXCIEn); \
+    handle_interrupt (&interrupts[vintr_RX]); \
+    } \
+    ISR(vect_UDRE) { \
+    UCSRnB &= ~_BV (UDRIEn); \
+    handle_interrupt (&interrupts[vintr_UDRE]); \
+    } \
+    MAP_SIMPLE_INTERRUPT(vect_TX, vintr_TX)
+
+SERIAL_INTERRUPT(USART0_RX_vect, vintr_USART_RX0, USART0_TX_vect,
vintr_USART_TX0, USART0_UDRE_vect, vintr_USART_UDRE0, UCSR0B, RXCIE0,
UDRIE0)
+
+SERIAL_INTERRUPT(USART1_RX_vect, vintr_USART_RX1, USART1_TX_vect,
vintr_USART_TX1, USART1_UDRE_vect, vintr_USART_UDRE1, UCSR1B, RXCIE1,
UDRIE1)
 #endif
 /*}}}*/
 
diff -r -u -x '*.tb?' -x '*.o' -x '*.m4' -x '*.cache' -x .svn -x '*.in'
Native/kroc-svn/tvm/arduino/serial.c Arduino/kroc-svn/tvm/arduino/serial.c
--- Native/kroc-svn/tvm/arduino/serial.c    2010-10-20
11:55:35.266789368 +0200
+++ Arduino/kroc-svn/tvm/arduino/serial.c    2010-10-20
18:04:17.247909843 +0200
@@ -1,5 +1,38 @@
 #include "tvm-arduino.h"
 
+#if defined(at90can64)
+static int serial_write(char c, FILE *f) {
+    /* Wait for transmit buffer to be empty */
+    while ((UCSR1A & _BV(UDRE1)) == 0)
+        ;
+
+    /* Put byte into transmit buffer */
+    UDR1 = c;
+
+    return 0;
+}
+
+void serial_stdout_init (long speed) {
+#ifndef at90can64
+    /* Set baud rate */
+    uint16_t factor = (F_CPU / 16 + speed / 2) / speed - 1;
+    UBRR1H = factor >> 8;
+    UBRR1L = factor;
+#else
+    UBRR1H = 0x00;
+    UBRR1L = 0x08;
+#endif
+
+    /* Set format (8N1) */
+    UCSR1C = 3 << UCSZ00;
+
+    /* Enable transmitter */
+    UCSR1B = _BV(TXEN1);
+
+    /* Set up stdout to write to the serial port */
+    stdout = fdevopen (serial_write, NULL);
+}
+#else
 static int serial_write(char c, FILE *f) {
     /* Wait for transmit buffer to be empty */
     while ((UCSR0A & _BV(UDRE0)) == 0)
@@ -26,11 +59,12 @@
     /* Set up stdout to write to the serial port */
     stdout = fdevopen (serial_write, NULL);
 }
+#endif
 
 /* FIXME: We really don't want these IFDEF statements.
    Further, this should be made to work on the Arduino as well.
 */
-#if defined(atmega1280)
+#if defined(atmega1280) || defined(at90can64)
 char rc0(void) {
             while ( !(UCSR0A & (1 << RXC0)) )
                 ;
@@ -43,6 +77,7 @@
             return UDR1;
 }
 
+#if defined(at90mega1280)
 char rc2(void) {
             while ( !(UCSR2A & (1 << RXC2)) )
                 ;
@@ -54,6 +89,7 @@
                 ;
             return UDR3;
 }
+#endif
 
 #define VAL_BYTE(w) (*(char*)&(w))
 #define BYTE(w) ((char *)(w))
@@ -71,8 +107,11 @@
     int   count = 0;
     char  ch;
     /* Declare the fn ptr */
+#if defined(atmega1280)
     char (*rca[])(void) = { rc0, rc1, rc2, rc3 };
-
+#else
+    char (*rca[])(void) = { rc0, rc1 };
+#endif
     cli();   
 
     /* Flush the USART */
diff -r -u -x '*.tb?' -x '*.o' -x '*.m4' -x '*.cache' -x .svn -x '*.in'
Native/kroc-svn/tvm/arduino/time.c Arduino/kroc-svn/tvm/arduino/time.c
--- Native/kroc-svn/tvm/arduino/time.c    2010-10-20 11:55:35.266789368
+0200
+++ Arduino/kroc-svn/tvm/arduino/time.c    2010-10-20 17:54:39.418919427
+0200
@@ -96,8 +96,11 @@
 void time_init ()
 {
     /* set timer 0 prescale factor to 64 */
+#if defined(at90can32) || defined(at90can64) || defined(at90can128)
+    TCCR0A |= 3 << CS00;
+#else
     TCCR0B |= 3 << CS00;
-
+#endif
     /* enable timer 0 overflow interrupt */
     TIMSK0 |= _BV (TOIE0);
 }





More information about the developers mailing list