2011-10-13 08:15 AM
Hello,
We are trying to send a 44 byte report over SPI from one STM32F103 to another board.Our master sends this data out every 5ms, and our slave receives data based on an interrupt.
We are experiencing an issue were our last byte from one report is received before the first byte of the second report (so we receive it 5ms later and with the wrong report).Once the first byte comes in and triggers the interrupt, we loop for the rest of the values rather than having 44 interrupts happen. We also send some bytes during the receiving period, but this part has not been fully implemented/tested yet. Currently, we are using SPI2 with these master configurations:/** Initializes SPI clock */RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);SPI_InitTypeDef SPI_InitStructure;/* SPI2 Config -------------------------------------------------------------*/SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 0;SPI_Init(SPI2, &SPI_InitStructure);SPI_CalculateCRC(SPI2, DISABLE);/* Enable SPI2 */SPI_Cmd(SPI2, ENABLE);//GPIOGPIO_InitTypeDef GPIO_InitStructure;/* Configure SPI2 pins: SCK, MOSI, MISO -------------------------*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; //changed from 2MhzGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);/* Configure SPI2 pins: NSS ---------------------------------*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //was Mode_out_PPGPIO_Init(GPIOB, &GPIO_InitStructure);And our slave configurations:/** Initializes SPI clock */RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);SPI_InitTypeDef SPI_InitStructure;/* SPI1 Config -------------------------------------------------------------*/SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 0;SPI_Init(SPI2, &SPI_InitStructure);SPI_CalculateCRC(SPI2, DISABLE);/* Enable SPI2 */SPI_Cmd(SPI2, ENABLE);//GPIOGPIO_InitTypeDef GPIO_InitStructure;/* Configure SPI2 pins: MOSI, MISO -------------------------*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);/* Configure SPI2 pins: NSS ------------------------------------*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;GPIO_Init(GPIOB, &GPIO_InitStructure);Here is out ISR configurations:NVIC_InitTypeDef NVIC_InitStructure;// Enable SPI IRQ IRQ Channel -----------------------------------------NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQChannel;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 7;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);We are running into a few odd problems.1) Occasionally the receiver reads the data as if it was bit-shifted by some amount. When we check the data on the logic analyzer it is coming out correctly from the master. The only way we have seen to fix this is to restart both and try again.2) This is the more serious problem we are experiencing. We receive the last byte of each report at the beginning of the next report. From our logic analyzer testing, we are sending out the data at the correct time though. so we send:Master sends:byte 41 -> byte 42 -> byte 43 -> byte 44 ---------------5ms-------------------- byte 1 -> byte 2Receiver gets:byte 41 -> byte42 -> byte 43 ------------------5ms-------------------- byte 44 -> byte 1 -> byte 2Here is our receiving code:void rx_only_spi2_isr(void){ SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, DISABLE); int cnt=0; for(;cnt<44;cnt++) { if(cnt>34 && cnt<43) SPI_I2S_SendData( SPI2, cnt ); while( SPI_I2S_GetFlagStatus( SPI2, SPI_I2S_FLAG_RXNE ) == RESET ); spi_buf[cnt] = SPI_I2S_ReceiveData( SPI2 ); } SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);}Any help would be greatly appreciated.2011-10-13 08:38 AM
I'm not sure of the wisdom of disabling/enabling the interrupt in this fashion. Keep the interrupt brief, ie don't spin and poll stuff endlessly, use a state machine and account for each byte as it arrives, and forward the complete packet when done.
Also make sure that the RXNE is cleared before starting, otherwise it can flag with old/stale data.2011-10-14 08:38 AM
Clive1, are you saying to do a dummy read of the Receive buffer to clear RXNE? If so, I have added in the code during the initialization and it doesn't change anything.
Also, as far as the state machine idea. While it has merit and sounds good, I can't justify spending the time writing that up since we have SPI1 working with the current code and configurations (/8 to maintain the same speed, I think). Let me know what you think about that, it would be really nice if we can get SPI2 to work properly also.2011-10-14 10:17 AM
So what happens when your working SPI1 code blocks all further processing of SPI2?
You're interrupt processing methodology is broken, time spent fixing it will be time saved later.2011-10-14 01:40 PM
Its not how the code runs really. What I am saying is we have copied this code over to SPI1 instead, just to see if it would work. and it does. We will only have 1 SPI that is running interrupt based, but it would be nice if we could get the choice.
Can you explain what you mean by the interrupt processing methodology is broken?