cancel
Showing results for 
Search instead for 
Did you mean: 

DMA completion interrupt not working for slave STM32 SPI

abouzar_nouri
Associate II
Posted on January 19, 2014 at 00:26

I am using stm32f103 to transmit some data over SPI while stm32 acts as slave. I need to use DMA for sending data to the SPI but the corresponding interrupt handler is never called.

The code comes in the following:

#include ''stm32f10x.h''

uint16_t SPI_Buffer[4];

void

DMA_Configure(

void

) {

DMA_InitTypeDef DMA_InitStructure;

/* DMA configuration */

DMA_DeInit(SPI_SLAVE_DMA);

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

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) SPI_Buffer;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

DMA_InitStructure.DMA_BufferSize = 4;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel6, &DMA_InitStructure);

/* Enable DMA Transfer Complete interrupt */

DMA_ITConfig(DMA1_Channel6, DMA1_IT_TC6, ENABLE);

/* Enable DMA */

DMA_Cmd(DMA1_Channel6, ENABLE);

}

void

SPI_Configure(

void

) {

/* SPI_SLAVE configuration */

SPI_InitTypeDef SPI_InitStructure;

SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;

SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;

SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;

SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;

SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

SPI_InitStructure.SPI_CRCPolynomial = 7;

SPI_Init(SPI_SLAVE, &SPI_InitStructure);

/* Enable SPI_SLAVE Tx request */

SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);

/* Enable SPI_SLAVE */

SPI_Cmd(SPI1, ENABLE);

}

void

GPIO_Configur(

void

) {

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

/* Configure NSS and SCK pins as Input Floating */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOA, &GPIO_InitStructure);

/* Configure MISO pin as Alternate Function Push Pull */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOA, &GPIO_InitStructure);

}

void

NVIC_Configur(

void

) {

NVIC_InitTypeDef NVIC_InitStructure;

/* 1 bit for pre-emption priority, 3 bits for subpriority */

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

/* Configure and enable SPI_DMA interrupt -------------------------------*/

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_Init(&NVIC_InitStructure);

}

void

RCC_Configur(

void

) {

/* PCLK2 = HCLK/2 := GPIO, SPI1)*/

RCC_PCLK2Config(RCC_HCLK_Div2);

/* Enable SPI_SLAVE Periph and GPIO clock */

RCC_APB2PeriphClockCmd(GPIOA | RCC_APB2Periph_SPI1, ENABLE);

/* Enable DMA1 clock */

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

}

int

main(

void

) {

RCC_Configur();

GPIO_Configur();

NVIC_Configur();

DMA_Configur();

SPI_Configur();

}

void

DMA1_Channel6_IRQHandler(

void

)

{

/* Test on SPI_DMA Channel Transfer Complete interrupt */

if

(DMA_GetITStatus(DMA1_IT_TC6))

{

// WE NEVER REACH THIS LINE :(

/* Clear DMA1 Channel6 Half Transfer, Transfer Complete and Global interrupt pending bits */

DMA_ClearITPendingBit(DMA1_IT_GL6);

}

}

When I use SPI interrupt handler, my system works. But using the code written above, interrupt handler of SPI_SLAVE_DMA channel is never called.

#stm32 #selective-cut-n-paste #spi #dma

5 REPLIES 5
Posted on January 19, 2014 at 01:19

Rule#1 Post ALL relevant code and defines, ideally something that will actually compile.

Make sure the interrupts are enabled in the NVIC
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
abouzar_nouri
Associate II
Posted on January 19, 2014 at 10:32

Thanks clive. I edited the first post. Now the complete code is there.

BTW, I'm using CoIDE with GNU tools.

Posted on January 19, 2014 at 10:44

Couple of quick observations:

DMA1 Clock not enabled

DMA1_Channel6 is not associated with SPI1_TX, that would need to be DMA1_Channel3
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
abouzar_nouri
Associate II
Posted on January 19, 2014 at 10:57

Thanks clive. I just missed to copy the line for enabling DMA clock. But I didn't know that there is a restriction on using DMA channels for different peripherals. I will check it out on my board.

Just a question. In which document I can find that which DMA channel works for a peripheral.

abouzar_nouri
Associate II
Posted on January 19, 2014 at 13:25

I found it!

In

http://www.st.com/web/en/resource/technical/document/reference_manual/CD00171190.pdf

, page 273, table 78.