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-30 11:35 AM
Yes Peter, it helped...
Get it working, I believe it's ok. I'll do some complete tests tomorrow, and will post good config, because it's a big mess at the moment...Tx all !2012-10-31 04:06 AM
Ok, so this config works :
#define NBR_BYTES 14
unsigned
char
SPI_MASTER_Buffer_Tx[NBR_BYTES] = { 0, 0,0,0,0,0,0, 0,0,0,0,0,0 ,0, 0, 0 };
unsigned
char
SPI_MASTER_Buffer_Rx[NBR_BYTES+1] = { 99, 99,99,99,99,99,99, 99,99,99,99,99,99 ,99, 99, 99};
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
DMA_DeInit (DMA2_Stream3);
/*
* Check if the DMA Stream is disabled before enabling it.
* Note that this step is useful when the same Stream is used multiple times:
* enabled, then disabled then re-enabled... In this case, the DMA Stream disable
* will be effective only at the end of the ongoing data transfer and it will
* not be possible to re-configure it before making sure that the Enable bit
* has been cleared by hardware. If the Stream is used only once, this step might
* be bypassed.
*/
while
(DMA_GetCmdStatus (DMA2_Stream3) != DISABLE);
DMA_StructInit (&DMA_InitStructure);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & (SPI1->DR);
DMA_InitStructure.DMA_Channel = DMA_Channel_3;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralInc = 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_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_InitStructure.DMA_Memory0BaseAddr =(uint32_t)&SPI_MASTER_Buffer_Tx;
DMA_InitStructure.DMA_BufferSize = NBR_BYTES;
DMA_Init (DMA2_Stream3, &DMA_InitStructure);
// Enable dma tx request.
SPI_I2S_DMACmd (SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
///////////////////////////////
//////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
///////////////////////////////
DMA_InitTypeDef DMA_InitStructure_RX;
NVIC_InitTypeDef NVIC_InitStructure_RX;
DMA_DeInit (DMA2_Stream0);
/*
* Check if the DMA Stream is disabled before enabling it.
* Note that this step is useful when the same Stream is used multiple times:
* enabled, then disabled then re-enabled... In this case, the DMA Stream disable
* will be effective only at the end of the ongoing data transfer and it will
* not be possible to re-configure it before making sure that the Enable bit
* has been cleared by hardware. If the Stream is used only once, this step might
* be bypassed.
*/
while
(DMA_GetCmdStatus (DMA2_Stream0) != DISABLE);
DMA_StructInit (&DMA_InitStructure_RX);
DMA_InitStructure_RX.DMA_PeripheralBaseAddr = (uint32_t) & (SPI1->DR);
DMA_InitStructure_RX.DMA_Channel = DMA_Channel_3;
DMA_InitStructure_RX.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure_RX.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure_RX.DMA_PeripheralInc = DMA_MemoryInc_Enable;
DMA_InitStructure_RX.DMA_PeripheralDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure_RX.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
/// DMA_MemoryDataSize_Byte;
DMA_InitStructure_RX.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure_RX.DMA_Priority = DMA_Priority_High;
DMA_InitStructure_RX.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure_RX.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure_RX.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure_RX.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_InitStructure_RX.DMA_Memory0BaseAddr = (uint32_t)&SPI_MASTER_Buffer_Rx;
/// (uint32_t)&SPI_MASTER_Buffer_Rx->preamble;
DMA_InitStructure_RX.DMA_BufferSize = (NBR_BYTES+1);
DMA_Init (DMA2_Stream0, &DMA_InitStructure_RX);
///////////// INTERRUPTIONS
DMA_ITConfig (DMA2_Stream0, DMA_IT_TC, ENABLE);
// Transfer complete interrupt mask
// DMA_ITConfig (DMA2_Stream0, DMA_IT_HT, ENABLE); // Half transfer complete interrupt mask
// DMA_ITConfig (DMA2_Stream0, DMA_IT_TE, ENABLE); // Transfer error interrupt mask
// DMA_ITConfig (DMA2_Stream0, DMA_IT_FE, ENABLE); // FIFO error interrupt mask
NVIC_InitStructure_RX.NVIC_IRQChannel = DMA2_Stream0_IRQn;
NVIC_InitStructure_RX.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure_RX.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure_RX.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init (&NVIC_InitStructure_RX);
// Enable dma tx request.
SPI_I2S_DMACmd (SPI1, SPI_I2S_DMAReq_Rx, ENABLE);
while
(1)
{
delay_us(10);
GPIO_SetBits(GPIOC, GPIO_Pin_4);
///// toggle PC4 = GPIO_EXT1
DMA_ClearFlag(DMA2_Stream0, DMA_FLAG_TCIF3);
GPIO_ResetBits(GPIOB, GPIO_Pin_0);
///// Low CS
//////// engage transfer in poll
while
(SPI1->SR & SPI_SR_TXE == 0);
// wait for empty TX buffer
SPI1->DR = (ADDRESS_READ);
//////////////// ENABLE DMA transfer Mode Normal : cad one shot / stop
DMA_Cmd(DMA2_Stream0, ENABLE);
/// RX
DMA_Cmd(DMA2_Stream3, ENABLE);
/// TX
///////// you can test during transfer :
// uint16_t Data_received_nbr = DMA_GetCurrDataCounter(DMA2_Stream0);
GPIO_ResetBits(GPIOB, GPIO_Pin_15);
///// allume LED BLEU
uint16_t Idle_cpteur = 0;
while
(!DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TCIF3)){
/// RX
// while(!DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TCIF0)){ /// TX
Idle_cpteur++;
}
GPIO_SetBits(GPIOB, GPIO_Pin_0);
///// HIGH CS
//////////////// DISABLE DMA transfer Mode Normal : cad one shot / stop
DMA_Cmd(DMA2_Stream0, DISABLE);
/// RX
DMA_Cmd(DMA2_Stream3, DISABLE);
/// TX
GPIO_SetBits(GPIOB, GPIO_Pin_15);
///// eteinds LED BLEU
GPIO_ResetBits(GPIOC, GPIO_Pin_4);
///// toggle PC4 = GPIO_EXT1
}
}
void
DMA2_Stream0_IRQHandler(){
//////////// RECEPTION SPI1
if
(DMA_GetITStatus (DMA2_Stream0, DMA_IT_TCIF0)) {
/// RX complete
DMA_ClearITPendingBit (DMA2_Stream0, DMA_IT_TCIF0);
// make sure spi dmd transfer is complete
//while (SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_RXNE) == SET) {};
//while (SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_BSY) == SET) {};
}
}