2012-10-29 07:16 AM
Hi,
I'm trying to switch SPI1 to DMA mode. First I just try to enable on RX channel only, but I tried both RX TX, and many configuration, and I can't figure why it doesn't want to start...#define NBR_BYTES_ 15
uint8_t SPI_MASTER_Buffer_Tx[NBR_BYTES_] = { ADDRESS_TO_READ, 0,0,0,0,0,0, 0,0,0,0,0,0,0,0 };
uint8_t SPI_MASTER_Buffer_Rx[NBR_BYTES_] = {99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};
SPI_InitTypeDef SPI_InitStructure;
SPI_I2S_DeInit(SPI1);
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; /// cad
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;/// cad
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Cmd(SPI1, ENABLE);
Init_device_in_poll_mode(); /// works ok
RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA2, ENABLE);
DMA_Cmd(DMA2_Stream0, DISABLE);
DMA_Cmd(DMA2_Stream5, DISABLE);
/////////////// RX DMA
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_BufferSize = NBR_BYTES_;
DMA_InitStructure.DMA_Channel = DMA_Channel_3;
DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)SPI_MASTER_Buffer_Rx;
DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001300C;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // DMA_Mode_Circular; //DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
/////////////// TX DMA
// DMA_InitStructure.DMA_BufferSize = NBR_BYTES_;
// DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI_MASTER_Buffer_Tx;
// DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001300C;
// DMA_InitStructure.DMA_Channel = DMA_Channel_3;
// DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
// DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
// DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
// DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
// DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
// DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // DMA_Mode_Circular; //DMA_Mode_Normal;
// DMA_InitStructure.DMA_Priority = DMA_Priority_High;
// DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
// DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
// DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
// DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
// DMA_Init(DMA2_Stream5, &DMA_InitStructure);
// DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
// DMA_ITConfig(DMA2_Stream5, DMA_IT_TC, ENABLE);
while(SPI1->SR & SPI_SR_TXE == 0); // wait for empty TX buffer
SPI1->DR = ADDRESS_TO_READ;
// DMA_Cmd(DMA2_Stream5, ENABLE);
DMA_Cmd(DMA2_Stream0, ENABLE);
GPIO_ResetBits(GPIOB, GPIO_Pin_15); ///// debug blue led
while(!DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TCIF0));
GPIO_SetBits(GPIOB, GPIO_Pin_15); ///// debug blue ledTx for your help !
2012-10-29 07:21 AM
In bound SPI on a master is driven by the transmit clock, generated by out bound data, receive is merely a side effect.
You need to transmit something, even if it is junk.2012-10-29 07:29 AM
Thank you Clive1,
You mean with something like this ?#define NBR_BYTES_ 15
uint8_t SPI_MASTER_Buffer_Tx[NBR_BYTES_] = { ADDRESS_TO_READ, 0,0,0,0,0,0, 0,0,0,0,0,0,0,0 };
uint8_t SPI_MASTER_Buffer_Rx[NBR_BYTES_] = {99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};
SPI_InitTypeDef SPI_InitStructure;
SPI_I2S_DeInit(SPI1);
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; /// cad
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;/// cad
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Cmd(SPI1, ENABLE);
Init_device_in_poll_mode(); /// works ok
RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA2, ENABLE);
DMA_Cmd(DMA2_Stream0, DISABLE);
DMA_Cmd(DMA2_Stream5, DISABLE);
/////////////// RX DMA
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_BufferSize = NBR_BYTES_;
DMA_InitStructure.DMA_Channel = DMA_Channel_3;
DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)SPI_MASTER_Buffer_Rx;
DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001300C;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // DMA_Mode_Circular; //DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
/////////////// TX DMA
DMA_InitStructure.DMA_BufferSize = NBR_BYTES_;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI_MASTER_Buffer_Tx;
DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001300C;
DMA_InitStructure.DMA_Channel = DMA_Channel_3;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // DMA_Mode_Circular; //DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream5, &DMA_InitStructure);
// DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
// DMA_ITConfig(DMA2_Stream5, DMA_IT_TC, ENABLE);
while(SPI1->SR & SPI_SR_TXE == 0); // wait for empty TX buffer
SPI1->DR = ADDRESS_TO_READ;
DMA_Cmd(DMA2_Stream5, ENABLE);
DMA_Cmd(DMA2_Stream0, ENABLE);
GPIO_ResetBits(GPIOB, GPIO_Pin_15); ///// debug blue led
while(!DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TCIF0));
GPIO_SetBits(GPIOB, GPIO_Pin_15); ///// debug blue led
It doesn't work too, at the moment, and I can't figure why (I tried many combinations...)
2012-10-29 07:55 AM
Don't you need something like
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE); SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE); To light it off?2012-10-29 08:07 AM
I appreciate your help a lot, Clive
Now :#define NBR_BYTES_ 14uint8_t SPI_MASTER_Buffer_Tx[NBR_BYTES_] = { 0, 0,0,0,0,0,0, 0,0,0,0,0,0,0,0 };uint8_t SPI_MASTER_Buffer_Rx[NBR_BYTES_] = {99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};SPI_InitTypeDef SPI_InitStructure;SPI_I2S_DeInit(SPI1); SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; /// cad SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;/// cad SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure);SPI_Cmd(SPI1, ENABLE);Init_device_in_poll_mode(); /// works okRCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA2, ENABLE); DMA_Cmd(DMA2_Stream0, DISABLE);DMA_Cmd(DMA2_Stream5, DISABLE);/////////////// RX DMADMA_InitTypeDef DMA_InitStructure;DMA_InitStructure.DMA_BufferSize = NBR_BYTES_;DMA_InitStructure.DMA_Channel = DMA_Channel_3;DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)SPI_MASTER_Buffer_Rx;DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001300C;DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // DMA_Mode_Circular; //DMA_Mode_Normal;DMA_InitStructure.DMA_Priority = DMA_Priority_High;DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;DMA_Init(DMA2_Stream0, &DMA_InitStructure);/////////////// TX DMADMA_InitStructure.DMA_BufferSize = NBR_BYTES_;DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SPI_MASTER_Buffer_Tx;DMA_InitStructure.DMA_PeripheralBaseAddr = 0x4001300C;DMA_InitStructure.DMA_Channel = DMA_Channel_3;DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // DMA_Mode_Circular; //DMA_Mode_Normal;DMA_InitStructure.DMA_Priority = DMA_Priority_High;DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;DMA_Init(DMA2_Stream5, &DMA_InitStructure);// DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);// DMA_ITConfig(DMA2_Stream5, DMA_IT_TC, ENABLE); SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE); SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE); while(SPI1->SR & SPI_SR_TXE == 0); // wait for empty TX buffer SPI1->DR = ADDRESS_TO_READ; DMA_Cmd(DMA2_Stream5, ENABLE);DMA_Cmd(DMA2_Stream0, ENABLE);GPIO_ResetBits(GPIOB, GPIO_Pin_15); ///// debug blue ledwhile(!DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TCIF0));GPIO_SetBits(GPIOB, GPIO_Pin_15); ///// debug blue ledBut led is still on...I modified this part too : because I have to send ADDRESS_TO_READ, and then read 14 bytes coming from device : is that correct ?#define NBR_BYTES_ 14uint8_t SPI_MASTER_Buffer_Tx[NBR_BYTES_] = { 0, 0,0,0,0,0,0, 0,0,0,0,0,0,0 };uint8_t SPI_MASTER_Buffer_Rx[NBR_BYTES_] = {99, 99,99,99,99,99,99 ,99,99,99,99,99,99 ,99};2012-10-30 03:11 AM
Well, I've done my best, and it still light my led...
Does anybody can send me a known working SPI+DMA configuration (even if it's not a SPI1) on STM32F4xx please ?Is it possible it's related to the DMA2 bug (http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/ERRATA_SHEET/DM00037591.pdf
) ?I don't believe in a first step, it may be my initialization procedure. But I can't find any complete and working configuration example SPI+DMA.Your help would be greatly appreciated !2012-10-30 05:37 AM
SPI1 + DMA on a STM32F4
//#define SPI SPI1
#define SPI_PORT SPI1
#define SPI_PORT_CLOCK RCC_APB2Periph_SPI1
#define SPI_PORT_CLOCK_INIT RCC_APB2PeriphClockCmd
#define SPI_SCK_PIN GPIO_Pin_5
#define SPI_SCK_GPIO_PORT GPIOA
#define SPI_SCK_GPIO_CLK RCC_AHB1Periph_GPIOA
#define SPI_SCK_SOURCE GPIO_PinSource5
#define SPI_SCK_AF GPIO_AF_SPI1
#define SPI_MOSI_PIN GPIO_Pin_7
#define SPI_MOSI_GPIO_PORT GPIOA
#define SPI_MOSI_GPIO_CLK RCC_AHB1Periph_GPIOA
#define SPI_MOSI_SOURCE GPIO_PinSource7
#define SPI_MOSI_AF GPIO_AF_SPI1
#define SPI_PORT_DR_ADDRESS SPI_PORT->DR
#define SPI_PORT_DMA DMA2
#define SPI_PORT_DMAx_CLK RCC_AHB1Periph_DMA2
#define SPI_PORT_TX_DMA_CHANNEL DMA_Channel_3
#define SPI_PORT_TX_DMA_STREAM DMA2_Stream3
#define SPI_PORT_TX_DMA_FLAG_FEIF DMA_FLAG_FEIF3
#define SPI_PORT_TX_DMA_FLAG_DMEIF DMA_FLAG_DMEIF3
#define SPI_PORT_TX_DMA_FLAG_TEIF DMA_FLAG_TEIF3
#define SPI_PORT_TX_DMA_FLAG_HTIF DMA_FLAG_HTIF3
#define SPI_PORT_TX_DMA_FLAG_TCIF DMA_FLAG_TCIF3
#define SPI_PORT_DMA_TX_IRQn DMA2_Stream3_IRQn
#define SPI_PORT_DMA_TX_IRQHandler DMA2_Stream3_IRQHandler
uint8_t refresh_count;
//tells the DMA updater to refresh the display
uint8_t spi_buf[16];
DMA_InitTypeDef DMA_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure2;
//*****************************************************
//* Name: initDMD
//* Purpose:
//* In:
//* Out:
//*****************************************************
void
initDMD(
void
){
//******************* SPI *******************
// enable the SPI peripheral clock
SPI_PORT_CLOCK_INIT(SPI_PORT_CLOCK, ENABLE);
// enable the peripheral GPIO port clocks
RCC_AHB1PeriphClockCmd(SPI_SCK_GPIO_CLK | SPI_MOSI_GPIO_CLK, ENABLE);
// Connect SPI pins to AF5 - see section 3, Table 6 in the device data sheet
GPIO_PinAFConfig(SPI_SCK_GPIO_PORT, SPI_SCK_SOURCE, SPI_SCK_AF);
GPIO_PinAFConfig(SPI_MOSI_GPIO_PORT, SPI_MOSI_SOURCE, SPI_MOSI_AF);
// now configure the pins themselves
// they are all going to be fast push-pull outputs
// but the SPI pins use the alternate function
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = SPI_SCK_PIN;
GPIO_Init(SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = SPI_MOSI_PIN;
GPIO_Init(SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
// now we can set up the SPI peripheral
// Assume the target is write only and we look after the chip select ourselves
// SPI clock rate will be system frequency/4/prescaler
// so here we will go for 72/4/4 = 4.4mhz
SPI_I2S_DeInit(SPI_PORT);
SPI_StructInit(&SPI_InitStructure);
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
SPI_Init(SPI_PORT, &SPI_InitStructure);
// Enable the SPI port
SPI_Cmd(SPI_PORT, ENABLE);
//******************* DMA *******************
// first enable the clock
RCC_AHB1PeriphClockCmd(SPI_PORT_DMAx_CLK, ENABLE);
// start with a blank DMA configuration just to be sure
DMA_DeInit(SPI_PORT_TX_DMA_STREAM);
while
(DMA_GetCmdStatus (SPI_PORT_TX_DMA_STREAM) != DISABLE);
// Configure DMA controller to manage TX DMA requests for the HCMS display
// first make sure we are using the default values
DMA_StructInit (&DMA_InitStructure);
// these are the only parameters that change from the defaults
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & (SPI_PORT->DR);
DMA_InitStructure.DMA_Channel = SPI_PORT_TX_DMA_CHANNEL;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
/*
* It
is
not possible to call DMA_Init without values
for
the source
* address and non-zero size even though a transfer
is
not done here.
* These are
checked
only when the assert_param macro
is
active though.
*/
DMA_InitStructure.DMA_Memory0BaseAddr = 0;
DMA_InitStructure.DMA_BufferSize = 1;
DMA_Init (SPI_PORT_TX_DMA_STREAM, &DMA_InitStructure);
// Enable the DMA transfer complete interrupt
DMA_ITConfig (SPI_PORT_TX_DMA_STREAM, DMA_IT_TC, ENABLE);
// enable the interrupt in the NVIC
NVIC_InitStructure.NVIC_IRQChannel = SPI_PORT_DMA_TX_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init (&NVIC_InitStructure);
// Enable dma tx request.
SPI_I2S_DMACmd(SPI_PORT, SPI_I2S_DMAReq_Tx, ENABLE);
}
//*****************************************************
//* Name: SPI_PORT_DMA_TX_IRQHandler
//* Purpose:
//* In:
//* Out:
//*****************************************************
void
SPI_PORT_DMA_TX_IRQHandler(){
// Test if DMA Stream Transfer Complete interrupt
if
(DMA_GetITStatus (SPI_PORT_TX_DMA_STREAM, DMA_IT_TCIF3)) {
DMA_ClearITPendingBit (SPI_PORT_TX_DMA_STREAM, DMA_IT_TCIF3);
// make sure spi dmd transfer is complete
//while (SPI_I2S_GetFlagStatus (SPI_PORT, SPI_I2S_FLAG_TXE) == RESET) {};
//while (SPI_I2S_GetFlagStatus (SPI_PORT, SPI_I2S_FLAG_BSY) == SET) {};
}
}
//*****************************************************
//* Name: updateDMD
//* Purpose:
//* In:
//* Out:
//*****************************************************
void
updateDMD(uint8_t phase_){
// use SPI+DMA to shift out the 16 bytes per row
for
(i=0; i<16; i++)
spi_buf[i] = 0x00;
SPI_PORT_TX_DMA_STREAM->NDTR = (uint32_t) 16;
SPI_PORT_TX_DMA_STREAM->M0AR = (uint32_t) spi_buf;
DMA_Cmd(SPI_PORT_TX_DMA_STREAM, ENABLE);
}
2012-10-30 06:30 AM
Thanks a lot Pirie,
There is a lack of working example SPI+DMA on the net, so I believe it will help a lot. Unfortunately, I didn't succeed by inspiring from your code. I didn't noticed any IRQ on Tx channel, even with Rx channel disabled. One question : why do you change thos registers after initialization, and not during initialization ? Was it a bug fix ?DMA2_Stream3->NDTR = (uint32_t) 16;
DMA2_Stream3->M0AR = (uint32_t) spi_buf;
DMA2_Stream3->NDTR is DMA_BufferSize?
DMA2_Stream3->M0AR is DMA_Memory0BaseAddr?
Is it possible it comes from theSPI_Direction_2Lines_FullDuplex ? Thanks again2012-10-30 08:39 AM
Still debugging, I found this :
char
temp_string_3[512];
sprintf
(temp_string_3,
''REGISTERS DMA2_Stream0 %u %u %u
REGISTERS DMA2_Stream3 %u %u %u || %u
''
,
(unsigned
int
)DMA2_Stream0->NDTR,
(unsigned
int
)DMA2_Stream0->M0AR,
(unsigned
int
)DMA2_Stream0->PAR,
(unsigned
int
)DMA2_Stream3->NDTR,
(unsigned
int
)DMA2_Stream3->M0AR,
(unsigned
int
)DMA2_Stream3->PAR,
(unsigned
int
)((SPI1->DR) )
);
USART_puts( USART1, temp_string_3);
Give this in console, before intialization and the same after !!!
REGISTERS DMA2_Stream0 0 0 0
REGISTERS DMA2_Stream3 0 0 0 || 104
With 104 which last value read() in poll mode with success.
Any advice ?
2012-10-30 09:50 AM
http://www.micromouseonline.com/2012/03/11/adding-dma-to-the-spi-driver-with-the-stm32f4