Question
Not able to run Two SPI in two streams of single DMA1 in STM32f407ZGT6
Hello,
I am having issue with running two SPI (SPI2 & SPI 3) in two streams like Stream4 and Stream7 in single DMA1.
Later on i checked individually checking Stream4 for output1 and then Stream7 for output 2. I found out i am able to get the wave forms for Stream 4 but not able to get the output for Stream7.
Can someone please help me out what is wrong with Stream7 in DMA1 with SPI.
void SigGenInitSigGen(void) {
uint16_t tempPrescalerValue = 0;
SigGenSpiInitData_u tempInitData;
//RCC_PCLK2Config(RCC_HCLK_Div1);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); //RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM12, ENABLE);
// Configuration GPIO
IoSpiGpioInit();
/* SPI configuration ------------------------------------------------*/
memset(&tempInitData, 0x00, sizeof(SigGenSpiInitData_u));
tempInitData.spiInitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
tempInitData.spiInitStructure.SPI_Mode = SPI_Mode_Master;
tempInitData.spiInitStructure.SPI_DataSize = SPI_DataSize_16b;
tempInitData.spiInitStructure.SPI_CPOL = SPI_CPOL_Low;
tempInitData.spiInitStructure.SPI_CPHA = SPI_CPHA_1Edge;
tempInitData.spiInitStructure.SPI_NSS = SPI_NSS_Soft;
tempInitData.spiInitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
tempInitData.spiInitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
tempInitData.spiInitStructure.SPI_CRCPolynomial = 10;
SPI_Init(SPI2, &(tempInitData.spiInitStructure));
/* DMA_Channel configuration ---------------------------------*/
memset(&tempInitData, 0x00, sizeof(SigGenSpiInitData_u));
DMA_DeInit(DMA1_Stream4); // De-initialize the DMA Stream (DMA1_Stream4 for SPI2 TX)
tempInitData.dmaInitStructure.DMA_Channel = DMA_Channel_1; // Channel selection
tempInitData.dmaInitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI2->DR; // SPI2 data register address
tempInitData.dmaInitStructure.DMA_Memory0BaseAddr = (uint32_t)m_SigGenGenBuffer_ch1; // Memory buffer address
tempInitData.dmaInitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; // Data direction: Memory to Peripheral
tempInitData.dmaInitStructure.DMA_BufferSize = CONF_SIGGEN_GEN_BUFFER_SIZE; // Buffer size
tempInitData.dmaInitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // Peripheral increment mode
tempInitData.dmaInitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // Memory increment mode
tempInitData.dmaInitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // Peripheral data size (16 bits)
tempInitData.dmaInitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // Memory data size (16 bits)
tempInitData.dmaInitStructure.DMA_Mode = DMA_Mode_Circular; // Circular mode
tempInitData.dmaInitStructure.DMA_Priority = DMA_Priority_VeryHigh; // Priority level
tempInitData.dmaInitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; // FIFO mode
// tempInitData.dmaInitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; // FIFO threshold
// tempInitData.dmaInitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; // Memory burst
// tempInitData.dmaInitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; // Peripheral burst
DMA_Init(DMA1_Stream4, &tempInitData);
//timer
/* Compute the prescaler value */
tempPrescalerValue = (uint16_t)(SystemCoreClock / 168000000) - 1;
/* Time base configuration */
memset(&tempInitData, 0x00, sizeof(SigGenSpiInitData_u));
tempInitData.timTimeBaseStructure.TIM_Period = CONF_SIGGEN_GEN_PERIOD;
tempInitData.timTimeBaseStructure.TIM_Prescaler =tempPrescalerValue;
tempInitData.timTimeBaseStructure.TIM_ClockDivision = 0;
tempInitData.timTimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM7, &(tempInitData.timTimeBaseStructure));
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure2;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseStructure2.TIM_Period = CONF_SIGGEN_GEN_PERIOD;
TIM_TimeBaseStructure2.TIM_Prescaler = tempPrescalerValue;
TIM_TimeBaseStructure2.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure2.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM12, &TIM_TimeBaseStructure2);
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = ( CONF_SIGGEN_GEN_PERIOD * 7 / 10 ); // Adjust the pulse width as needed
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC1Init(TIM12, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM12, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM12, ENABLE);
TIM_Cmd(TIM12, ENABLE); // Start Timer 12
/* TIM1 Update DMA Request enable */
TIM_DMACmd(TIM7, TIM_DMA_Update, ENABLE);
/* TIM1 counter enable */
TIM_Cmd(TIM7, ENABLE);
TIM_ARRPreloadConfig(TIM7, ENABLE);
/* Enable SPI DMA Tx request */
//SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);
/* Enable SPI */
SPI_Cmd(SPI2, ENABLE);
/* Enable the selected DMA interrupts */
DMA_ITConfig(DMA1_Stream4, DMA_IT_HT | DMA_IT_TC, ENABLE);
// /* 1 bit for pre-emption priority, 3 bits for subpriority */
// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
/* Configure and enable DMA interrupt -------------------------------*/
memset(&tempInitData, 0x00, sizeof(SigGenSpiInitData_u));
tempInitData.nvicInitStructure.NVIC_IRQChannel = DMA1_Stream4_IRQn;
tempInitData.nvicInitStructure.NVIC_IRQChannelPreemptionPriority = 0;
tempInitData.nvicInitStructure.NVIC_IRQChannelSubPriority = 0;
tempInitData.nvicInitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&(tempInitData.nvicInitStructure));
/* Enable DMA channels */
DMA_Cmd(DMA1_Stream4, ENABLE);
memset(&tempInitData, 0x00, sizeof(SigGenSpiInitData_u));
tempInitData.spiInitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
tempInitData.spiInitStructure.SPI_Mode = SPI_Mode_Master;
tempInitData.spiInitStructure.SPI_DataSize = SPI_DataSize_16b;
tempInitData.spiInitStructure.SPI_CPOL = SPI_CPOL_Low;
tempInitData.spiInitStructure.SPI_CPHA = SPI_CPHA_1Edge;
tempInitData.spiInitStructure.SPI_NSS = SPI_NSS_Soft;
tempInitData.spiInitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
tempInitData.spiInitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
tempInitData.spiInitStructure.SPI_CRCPolynomial = 10;
SPI_Init(SPI3, &(tempInitData.spiInitStructure));
/* DMA_Channel configuration ---------------------------------*/
memset(&tempInitData, 0x00, sizeof(SigGenSpiInitData_u));
DMA_DeInit(DMA1_Stream7); // De-initialize the DMA Stream (DMA1_Stream4 for SPI2 TX)// Activated to check output2 on 6th Jan Manas
tempInitData.dmaInitStructure.DMA_Channel = DMA_Channel_3; // Channel selection
tempInitData.dmaInitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI3->DR; // SPI2 data register address
tempInitData.dmaInitStructure.DMA_Memory0BaseAddr = (uint32_t)m_SigGenGenBuffer_ch2; // Memory buffer address
tempInitData.dmaInitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; // Data direction: Memory to Peripheral
tempInitData.dmaInitStructure.DMA_BufferSize = CONF_SIGGEN_GEN_BUFFER_SIZE; // Buffer size
tempInitData.dmaInitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // Peripheral increment mode
tempInitData.dmaInitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // Memory increment mode
tempInitData.dmaInitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // Peripheral data size (16 bits)
tempInitData.dmaInitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // Memory data size (16 bits)
tempInitData.dmaInitStructure.DMA_Mode = DMA_Mode_Circular; // Circular mode
tempInitData.dmaInitStructure.DMA_Priority = DMA_Priority_VeryHigh; // Priority level
tempInitData.dmaInitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; // FIFO mode
// tempInitData.dmaInitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; // FIFO threshold
// tempInitData.dmaInitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; // Memory burst
// tempInitData.dmaInitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; // Peripheral burst
DMA_Init(DMA1_Stream7, &tempInitData);
//
// //timer
//
// /* Compute the prescaler value */
tempPrescalerValue = (uint16_t)(SystemCoreClock / 168000000) - 1;
//
// /* Time base configuration */
memset(&tempInitData, 0x00, sizeof(SigGenSpiInitData_u));
tempInitData.timTimeBaseStructure.TIM_Period = CONF_SIGGEN_GEN_PERIOD;
tempInitData.timTimeBaseStructure.TIM_Prescaler =tempPrescalerValue;
tempInitData.timTimeBaseStructure.TIM_ClockDivision = 0;
tempInitData.timTimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &(tempInitData.timTimeBaseStructure));
TIM_DMACmd(TIM2, TIM_DMA_Update, ENABLE);
/* TIM1 counter enable */
TIM_Cmd(TIM2, ENABLE);
SPI_Cmd(SPI3, ENABLE);
/* Enable the selected DMA interrupts */
DMA_ITConfig(DMA1_Stream7, DMA_IT_HT | DMA_IT_TC, ENABLE);
// /* 1 bit for pre-emption priority, 3 bits for subpriority */
// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
/* Configure and enable DMA interrupt -------------------------------*/
memset(&tempInitData, 0x00, sizeof(SigGenSpiInitData_u));
tempInitData.nvicInitStructure.NVIC_IRQChannel = DMA1_Stream7_IRQn;
tempInitData.nvicInitStructure.NVIC_IRQChannelPreemptionPriority = 0;
tempInitData.nvicInitStructure.NVIC_IRQChannelSubPriority = 0;
tempInitData.nvicInitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&(tempInitData.nvicInitStructure));
TIM6_Config();
DMA_Cmd(DMA1_Stream7, ENABLE);
// TIM9_Config();
}
void DMA1_Stream4_IRQHandler(void)
{
if (DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_HTIF4) != RESET)
{
// Clear DMA transfer complete flag
DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_HTIF4); // Commented by Manas to check further with interrupt flag clear
//DMA_ClearITPendingBit(DMA1_Stream4, DMA_FLAG_HTIF4);
m_SigGenTempGenBufferPtr_ch1 = m_SigGenPingGenBufferPtr_ch1;
m_SigGenData_Op1.ptrCallBackInitGenBuffer();
// SigGenInitMonoPhasePulseGenBuffer();
// SigGenUpdateMonoPhasePulseGenParams();
if(gal_flag)
{
SigGenInitSine1GenBuffer();
}
// McuGalSwCh3On();
// McuGalSwCh4On();
}
if(DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_TCIF4) != RESET)
{
DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_TCIF4);// Commented by Manas to check further with interrupt flag clear
//DMA_ClearITPendingBit(DMA1_Stream4, DMA_FLAG_TCIF4);
m_SigGenTempGenBufferPtr_ch1 = m_SigGenPongGenBufferPtr_ch1;
m_SigGenData_Op1.ptrCallBackInitGenBuffer();
// SigGenInitSine1GenBuffer();
// SigGenInitMonoPhasePulseGenBuffer();
// SigGenUpdateMonoPhasePulseGenParams();
// McuGalSwCh3On();
// McuGalSwCh4On();
}
}
void DMA1_Stream7_IRQHandler(void)
{
if (DMA_GetFlagStatus(DMA1_Stream7, DMA_FLAG_HTIF7) != RESET)
{
// Clear DMA transfer complete flag
DMA_ClearFlag(DMA1_Stream7, DMA_FLAG_HTIF7);
//DMA_ClearITPendingBit(DMA1_Stream7, DMA_FLAG_HTIF7);
//m_SigGenTempGenBufferPtr_ch2 = m_SigGenPingGenBufferPtr_ch2;
//m_SigGenData_Op2.ptrCallBackInitGenBuffer();
if(gal_flag)
{
SigGenInitSine2GenBuffer();
}
}
if(DMA_GetFlagStatus(DMA1_Stream7, DMA_FLAG_TCIF7) != RESET)
{
DMA_ClearFlag(DMA1_Stream7, DMA_FLAG_TCIF7);
//DMA_ClearITPendingBit(DMA1_Stream7, DMA_FLAG_TCIF7);
//m_SigGenTempGenBufferPtr_ch2 = m_SigGenPongGenBufferPtr_ch2;
//m_SigGenData_Op2.ptrCallBackInitGenBuffer();
}
}