[Tinyos-devel] Bug in

Kevin Klues klueska at gmail.com
Tue Jun 10 12:29:01 PDT 2008


Eric, did you get a chance to test this and see if it fixes your
problem?  Vlado will comiit if you can verify this solves your
problems.

Kevin

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
>>
>>
> _______________________________________________
> Tinyos-devel mailing list
> Tinyos-devel at millennium.berkeley.edu
> https://www.millennium.berkeley.edu/cgi-bin/mailman/listinfo/tinyos-devel
>



-- 
~Kevin


More information about the Tinyos-devel mailing list