[Tinyos-devel] Bug in

Jan Hauer jan.hauer at gmail.com
Mon Jun 16 00:33:33 PDT 2008


now fixed in CVS.
Jan

On Sat, Jun 14, 2008 at 8:40 AM, Eric Decker <cire831 at gmail.com> wrote:
> Code works.
>
> The issue with keeping the uart busy using the cpu stuffing chars is
> difficult.  I'm not sure if it is a problem worth solving.  Using the
> DMA engine works much better.
>
> Anyway the code works as provided by Jan.
>
> thanks Jan.
>
> On Wed, May 21, 2008 at 4:56 AM, Jan Hauer <jan.hauer at gmail.com> wrote:
>>
>> Yes, it is a bug, but I think the race condition is slightly different
>> from what you describe (because removing the clrT/RxIntr() lines
>> doesn't solve the problem for me). The problem is that in the
>> continueOp() function (in file
>> tinyos-2.x/tos/chips/msp430/usart/Msp430SpiNoDmaP.nc) two bytes are
>> written to the U0TXBUF before one is read from the U0RXBUF. This works
>> at 500Khz, because the time it takes for the second byte to be output
>> is enough for the first byte to be read from U0RXBUF. At 2Mhz it is
>> not, i.e. the second byte is moved from the receive-shift register to
>> U0RXBUF *before* the first byte has been read. This is actually
>> signalled through the OE (overrun) flag in U0RCTL, but it is never
>> checked in the code. It can be fixed by first reading U0RXBUF before
>> sending the second byte (see code snippet below). Also, we might
>> consider increasing SPI_ATOMIC_SIZE to more than the default value of
>> 2 otherwise the gain of a higher bus clock is (almost) neutralized by
>> the ISR overhead. Eric, can you please check whether the code below
>> works for you?
>>
>> Jan
>>
>>  void continueOp() {
>>
>>    uint8_t end;
>>    uint8_t tmp;
>>
>>    atomic {
>>      call Usart.tx( m_tx_buf ? m_tx_buf[ m_pos ] : 0 );
>>
>>      end = m_pos + SPI_ATOMIC_SIZE;
>>      if ( end > m_len )
>>        end = m_len;
>>
>>      while ( ++m_pos < end ) {
>>        while( !call Usart.isRxIntrPending() );
>>        tmp = call Usart.rx();
>>        if ( m_rx_buf )
>>          m_rx_buf[ m_pos - 1 ] = tmp;
>>        call Usart.tx( m_tx_buf ? m_tx_buf[ m_pos ] : 0 );
>>      }
>>    }
>>
>>  }
>>
>>
>>
>> On Thu, May 15, 2008 at 7:07 PM, Eric Decker <cire831 at gmail.com> wrote:
>> > in the file tinyos-2.x/tos/chips/msp430/usart/Msp430SpiNoDmaP.nc
>> > (current
>> > CVS repository)
>> > there are some bugs with how the Usart is being handled in Spi mode with
>> > no
>> > DMA.
>> >
>> > Background: The default setup in the tree is to run SMCLK at 1 MHz and
>> > the
>> > CPU clock
>> > at 4 MHz.  This means the SPI is being clocked at 1 MHz.  The MM3
>> > platform
>> > (very
>> > similar to a telosb) has a SD (secure digital flash device) attached to
>> > the
>> > SPI that
>> > we want to run as fast as possible.  So we are running SMCLK at 4 MHz
>> > and
>> > doing
>> > a /2 for the SPI.  We adjusted the initilization for the underlying
>> > timing
>> > for the Timers
>> > so the main timers are still ticking correctly.  (/4).
>> >
>> > Now here is the problem.  In continueOp (part of doing SpiPacket.send
>> > without DMA)
>> > the following code is explicitly clearing both the tx and rx interrupt
>> > flags.   Here is what
>> > is happening:
>> >
>> > write first byte out
>> > wait for the byte to get copied into the tx output shift register (tx
>> > ifg is
>> > asserted)
>> > clear the tx interrupt flag
>> > write the next byte to go out.
>> > wait for rx interrupt flag
>> > clear rx interupt flag
>> > read rx byte
>> >
>> > If the SPI is fast enough there is a race condition.  The first tx
>> > causes
>> > an rx byte to come in.  If this happens quickly enough (and it does
>> > with the SPI being clocked at 2 MHz vs. 500KHz) this byte will show
>> > up prior to the "wait for rx interrupt flag".  Note that the next tx
>> > byte
>> > has already been sent so the next rx byte is also on its way.  If this
>> > byte arrives prior to the "clear rx interrupt" then the corresponding
>> > rx interrupt flag will be lost.  This is exactly the behaviour I am
>> > seeing.
>> >
>> > The reason it works with the SPI being clocked at 500 MHz is it is
>> > running
>> > 4 times slower.
>> >
>> > The msp430 code that interacts with rx and tx interrupts shouldn't
>> > explicitly
>> > clear the interrupt flags.  The msp430 user manual states that writing
>> > to
>> > TXBUF will automatically clear the TX interrupt flag.  Similarily
>> > reading
>> > RXBUF will clear the RX interrupt flag.  So in the continueOp code there
>> > is no need to explicitly clear the interrupt flags.
>> >
>> > eric
>> >
>> >
>> >   void continueOp() {
>> >
>> >     uint8_t end;
>> >     uint8_t tmp;
>> >
>> >     atomic {
>> >       call Usart.tx( m_tx_buf ? m_tx_buf[ m_pos ] : 0 );
>> >
>> >       end = m_pos + SPI_ATOMIC_SIZE;
>> >       if ( end > m_len )
>> >         end = m_len;
>> >
>> >       while ( ++m_pos < end ) {
>> >         while( !call Usart.isTxIntrPending() );
>> >         call Usart.clrTxIntr();                 // writing txbuf
>> > automatically clears the interrupt.
>> >         call Usart.tx( m_tx_buf ? m_tx_buf[ m_pos ] : 0 );
>> >         while( !call Usart.isRxIntrPending() );
>> >         call Usart.clrRxIntr();                 // reading rxbuf
>> > automatically clears so this is a problem
>> >         tmp = call Usart.rx();
>> >         if ( m_rx_buf )
>> >           m_rx_buf[ m_pos - 1 ] = tmp;
>> >       }
>> >     }
>> >
>> >   }
>> >
>> >
>> > _______________________________________________
>> > Tinyos-devel mailing list
>> > Tinyos-devel at millennium.berkeley.edu
>> >
>> > https://www.millennium.berkeley.edu/cgi-bin/mailman/listinfo/tinyos-devel
>> >
>> >
>
>
>
> --
> Eric B. Decker
> Senior (over 50 :-) Researcher
> Autonomous Systems Lab
> Jack Baskin School of Engineering
> UCSC
>


More information about the Tinyos-devel mailing list