nagjames wrote on Sunday, December 06, 2009:
Hi All, I’d like to send SPI full duplex data between and an ATmega168 16MHz (master) and AVR32 12MHz (slave).
It takes 250us to send 14 bytes. If I use RDRF Receive Data Register Full interrupt then I’ll miss the first few bytes because of the jump delay between the ISR and the handler task. ( a side note: I’m using xQueueSendToBackFromISR because for some reason the semaphore didn’t work. Would the semaphore take much less time?)
To solve the delay problem I use NSSR (NSS Rising) interrupt on the slave (AVR32) and create a pre-trigger on master NSS line 160us prior to sending the clock and data. In the slave ISR I disable NSSR interrupt and enable it again in the handler task after it has finished receiving the data. To ensure proper timing this handler task has the highest priority among the other tasks.
For testing purposes I’ve programmed the master (ATmega) to send the batches in 3 secs interval. After reset (both ATmega168 and AVR32) the first 14 bytes is send and received as expected but later on both sides gets messed up. What I mean by messed up is for example the master is sending “ABCDEFGHIJKLMN” and the slave is sending “abcdefghijklmn”.
On the master side I receive:
“abcdefghijklmn”
“abcdefghijklmn”
“abcdefghhhhjkl”
“mmmmmmmmmmmmm”
The slave handler code looks like this:
xStatusSPI = xQueueReceive( xQueueSPI, &lReceivedValue, portMAX_DELAY );
index = 0;
do {
Buffer_rec = spi->rdr ;
spi->tdr = Buffer_send;
++index;
timeout=10;
while ((spi->sr & (AVR32_SPI_SR_RDRF_MASK)) != (AVR32_SPI_SR_RDRF_MASK)){
if (!timeout-) {
no_more_data_received = 1;
break;
}
}
} while ( no_more_data_received != 1);
// initialize SPI and enable NSS interrupt again
errVal = spi_initSlave(spi, 8, 0);
spi_enable(spi);
spi->ier = AVR32_SPI_IER_NSSR_MASK;
on both master and slave side after sending the 14bytes batch I reinitialize SPI.
I’m missing something for sure. I’m looking for better ideas how to this. UART is no option I’d like to make this working with SPI.
I’m building a robot walker as a hobby project. AVR32 will send the position data while the ATmega168 controls the servos.
http://nagycnc.com/joomla/index.php?option=com_content&task=blogsection&id=9&Itemid=41
Thanks,
James