cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407 SPI stop working after some (random) number of sends

alessandro
Associate
Posted on October 22, 2015 at 00:24

Good day everybody,

    I'm having an usual problem on STM32F407 SPI. I'm using a STM32F407 discovery board with a custom made breakout board (SPI2 pins used are PB13, PB14 and PB15 and are connected to a AD7190 ADC through 100ohm resistors).

Compiled program (about 4k) is downloaded to RAM and executed. Until now the board gave me no problem.

A basic description of the problem is that the SPI stops to work after a (seemingly random) number of bytes send. Stripped down code is:

int main(void)

{

  initializeUSART(&USART0);

  putString(&USART0,''Usart ok'');

  putNewLine(&USART0);

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

  GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_SPI2);

  GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2);

  GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2);

  GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2);

  GPIO_InitTypeDef setting;

  GPIO_StructInit(&setting);

  setting.GPIO_Pin=GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;

  setting.GPIO_Mode = GPIO_Mode_AF;

  setting.GPIO_OType = GPIO_OType_PP;

  setting.GPIO_Speed = GPIO_Speed_50MHz;

  setting.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_Init(GPIOB, &setting);

 SPI_I2S_DeInit (SPI2);

 SPI_InitTypeDef spiSetting;

 SPI_StructInit (&spiSetting);

 spiSetting.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_2;

 spiSetting.SPI_Direction=SPI_Direction_2Lines_FullDuplex;

 spiSetting.SPI_Mode=SPI_Mode_Master;

 spiSetting.SPI_DataSize=SPI_DataSize_8b;

 spiSetting.SPI_CPOL=SPI_CPOL_High; // 1 when clock is idle

 spiSetting.SPI_CPHA=SPI_CPHA_2Edge; // Transmit data on second edge

 spiSetting.SPI_NSS=SPI_NSS_Hard;

 spiSetting.SPI_FirstBit=SPI_FirstBit_MSB;

 SPI_Init(SPI2,&spiSetting);

 SPI_Cmd(SPI2,ENABLE);

 //putNewLine(&USART0);

  for(int i=0;;i++)

  {

    while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==RESET)

    {

      //msleep(100);

      putString(&USART0,''.'');

    }

    putNewLine(&USART0);

    putInt(&USART0,i,10);

    putNewLine(&USART0);

    SPI_I2S_SendData(SPI2,0x55);

  }

}

With this code i get correct signals for some (random?) number of bytes the suddenly SPI (the program stalls on while loop). Example outputs are:

Usart ok

0

.

1

.

2

[...]

144

.................................................... (loop is blocked)

Consecutive execution of program gave me following number of bytes sent and approximate time from start to program start:

1 350uS

172 16.2ms

256 24.7ms

271 26.2ms

179 17ms

108 9.8ms

245 23.6ms

and so on. Can anybody think of a possible cause for this problem?
2 REPLIES 2
alessandro
Associate
Posted on October 22, 2015 at 01:42

Further strip down of problem. I removed the custom expansion board, connected oscilloscope directly to discovery board PB13 (clock). I kept code only for initializing the SPI and replaced calls to send data and query flags with direct writes/reads from register.

My problem is that if some time passes between consecutive writes to data register SPI locks. The following code still halts (after sending data for about 400-800ms, still random). Commenting the busy wait line makes program run (and send SPI data) forever. I really doubt it can be an hardware problem so it is probably something stupid done in initialization. Since i do not own a second board could anybody check if it is a common problem? Thank you and regards

#include ''stm32f4xx_rcc.h''

#include ''stm32f4xx_gpio.h''

#include ''stm32f4xx_spi.h''

void initialize(void)

{

}

int main(void)

{

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

  GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_SPI2);

  GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2);

  GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2);

  GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2);

  GPIO_InitTypeDef setting;

  GPIO_StructInit(&setting);

  setting.GPIO_Pin=GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;

  setting.GPIO_Mode = GPIO_Mode_AF;

  setting.GPIO_OType = GPIO_OType_PP;

  setting.GPIO_Speed = GPIO_Speed_50MHz;

  setting.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_Init(GPIOB, &setting);

 SPI_I2S_DeInit (SPI2);

 SPI_InitTypeDef spiSetting;

 SPI_StructInit (&spiSetting);

 spiSetting.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_64;

 spiSetting.SPI_Direction=SPI_Direction_2Lines_FullDuplex;

 spiSetting.SPI_Mode=SPI_Mode_Master;

 spiSetting.SPI_DataSize=SPI_DataSize_8b;

 spiSetting.SPI_CPOL=SPI_CPOL_High; // 1 when clock is idle

 spiSetting.SPI_CPHA=SPI_CPHA_2Edge; // Transmit data on second edge

 spiSetting.SPI_NSS=SPI_NSS_Hard;

 spiSetting.SPI_FirstBit=SPI_FirstBit_MSB;

 SPI_Init(SPI2,&spiSetting);

 SPI_Cmd(SPI2,ENABLE);

  for(;;)

  {

    volatile int j;

    while(SPI2->SR&0x80); //0x02 for TXE

    for(j=0;j<5000;j++); // Comment this line to make everything work

    SPI2->DR=0x55;

  }

}
Posted on October 22, 2015 at 06:46

You wrote in your post that you run the code from RAM. How do you locate it there? Where are the variables and the stack located (don't they overlap the code?)

Do you have any interrupt in action?

Disassembler is your friend.

JW