[CCC DEV] Transterpreter/Plumbing ported to the AT90CANxxx: First attempt and a problem
Stefan Heymer
stefan.heymer at gmx.de
Wed Oct 27 18:40:00 BST 2010
Hi Matt and list,
the mystery is solved... the problem didn't lie in the source code, but
between my ears.
I simply was too dumb to flash the correct hex file, taking the (from
what I saw on my compilation of the KRoC tool set for AVR, superfluous)
"binary" generated by avr-occbuild and flashing it into the processor.
Some inserted debug messages, lots of head scratching, DEBUG flag turned
on I finally found out _where_ the Transterpreter VM bailed out on my
user code. And substituting that code with "the real thing", I got
flurry of lots and lots of debug lines on the terminal, and a message
that the end of the program was reached. Yay!
Yet, using the same "hello world" program on the AVR platform didn't
yield a noticable output on the terminal connected to the board. Guess
that's another piece of the story...
I'll take my hands next on duplicating the .../arduino code branch,
completing the port to the AT90CANxxx processors, and trying my luck
with some old fashioned Blinkenlights on my smaller target board.
I'll keep you posted on the progress...
Have a nice day,
Stefan
Am 21.10.2010 14:32, schrieb Stefan Heymer:
> 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);
> }
>
>
> _______________________________________________
> developers mailing list
> developers at concurrency.cc
> http://unhosting.org/mailman/listinfo/developers
>
>
More information about the developers
mailing list