[Tinyos-devel] Bug in
Eric Decker
cire831 at gmail.com
Thu May 15 10:07:26 PDT 2008
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;
}
}
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://www.millennium.berkeley.edu/pipermail/tinyos-devel/attachments/20080515/9f3f8b04/attachment-0001.htm
More information about the Tinyos-devel
mailing list