cancel
Showing results for 
Search instead for 
Did you mean: 

SPI read inside TIM1 Update interrupt freeze

Bogdan
Senior
Posted on January 22, 2018 at 17:56

Hello all,

i have a aplication for a 3 phase motor, where i have 3 sensors read via SPI.

The microcontroler is a stm32F427 device

I am using timer1 for 6 pwm output, and the timer in countin mode   TIM_CounterMode_CenterAligned3    

So i am expecting a update event on the middle of the 'ON period', till here everything works as expected.

I am using two main IRQ handlers,   one is timer2 where i  setup the timer1 outputs ( acording to HALL inputs on TIM2 and XORED)

And the other IRQ handler is TIM1 Update handler

My problem is that if i have SPI read inside the timer1 update handler, the microcontroler wont start the motor.

If i dont have spi code,  everything works.  Why?   

What is even courious, that i have SPI activiti which seems ok ( seen with a logic analyzer)... I

void TIM1_UP_TIM10_IRQHandler(void){

if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)

{

TIM_ClearITPendingBit(TIM1, TIM_IT_Update);

// Read Phase current U

GPIOE->BSRRH = GPIO_Pin_10; // set Chip select 3 Low

SPI1->DR = 0x00;/// write dummy data to trigger clock

while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete

while( !(SPI1->SR & SPI_I2S_FLAG_RXNE) ); // wait until receive complete

while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore

current[0] =SPI1->DR; // return received data from SPI data register

GPIOE->BSRRL = GPIO_Pin_10; //

set Chip select 3

High

 

    }

}
4 REPLIES 4
Andrew Neil
Evangelist
Posted on January 23, 2018 at 18:48

busy loop delays inside an ISR are never a good thing ...

busy loop delays with no timeout escape are never a good thing ...

T J
Lead
Posted on January 23, 2018 at 23:32

your code seems incorrect,

// Read Phase current

while( !(SPI1->SR & SPI_I2S_FLAG_RXNE) )

current[0] =SPI1->DR;                                 // empty receiver

GPIOE->BSRRH = GPIO_Pin_10; // set Chip select 3 Low

SPI1->DR = 0x00;/// write dummy data to trigger clock

while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete

while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore

current[0] =SPI1->DR; // return received data from SPI data register

Bogdan
Senior
Posted on January 23, 2018 at 23:54

Hello,

i have moved along with the SPI trough a DMA which handles TX and RX of the SPI periph.

The big question now is, how to trigger the SPI1 TX stream  from the timer update event interrupt? 

The timer1 update occurs in the middle of each pwm ON period,   and from here, i want to trigger a DMA SPI TX event. Is this posible?

bellow is my SPI DMA code

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 , ENABLE);

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines

SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // transmit in master mode, NSS pin has to be always high

SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; // one packet of data is 8 bits wide

SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // clock is low when idle

SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // data sampled at first edge

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set; // set the NSS management to internal and pull internal NSS high

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; // SPI frequency is APB2 frequency / 4

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first

SPI_Init(SPI1, &SPI_InitStructure);

/* Deinitialize DMA Streams */

DMA_DeInit(DMA2_Stream0);

DMA_DeInit(DMA2_Stream3);

DMA_InitTypeDef DMA_InitStructure;

/* Configure DMA Initialization Structure */

DMA_InitStructure.DMA_BufferSize = SPI_BUFF_SIZE ;

DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable ;

DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull ;

DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 16bit of data

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;//DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t) (&(SPI1->DR)) ;

DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

/* Configure TX DMA */

DMA_InitStructure.DMA_Channel = DMA_Channel_3;

DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral ;

DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)aTxBuffer ;

DMA_Init(DMA2_Stream3, &DMA_InitStructure);

/* Configure RX DMA */

DMA_InitStructure.DMA_Channel = DMA_Channel_3 ;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory ;

DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)aRxBuffer ;

DMA_Init(DMA2_Stream0, &DMA_InitStructure);

//Enable the transfer complete interrupt for DMA2 Stream5

DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);

/* Enable DMA SPI TX Stream */

DMA_Cmd(DMA2_Stream3,ENABLE);

/* Enable DMA SPI RX Stream */

DMA_Cmd(DMA2_Stream0,ENABLE);

/* Enable SPI DMA TX Requsts */

SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);

/* Enable SPI DMA RX Requsts */

SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);

SPI_Cmd(SPI1, ENABLE); // enable SPI1
Posted on January 31, 2018 at 12:30

DMA_FIFOThreshold_1QuarterFull ;

are you sure that is what you want?