Can't receive over duplex SPI with DMA
I'm trying to communicate with AD5750 over the SPI. It requires full duplex SPI, where according to the timing diagram on page 9 of 36 in the data sheet, AD5750 is a slave SPI device, which is responding to a command with a readback. I wan't to fetch this readback and I'm able to poll it. However I would like to use the DMA so that I'm not loosing any time for waiting the communication to finish. The problem is that though I'm able to transmit data over the DMA, I'm not able to receive it, because RXEN flag is never set. Here is my initialization code:
static void SPI_Config(void) {
GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; DMA_InitTypeDef DMA_Init_Structure; NVIC_InitTypeDef NVIC_InitStructure;// NVIC_InitTypeDef NVIC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); /* Connect SPI pins to AF5 */ // GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_SPI1); //SS GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); //SCK GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1); //MISO GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1); //MOSI GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //SCK GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //MISO GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //MOSI GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //SS GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); //SPI Configuration RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE); SPI_I2S_DeInit(SPI1); SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //AD5620 doku page 18 falling edge of SCLK SPI_InitStructure.SPI_CRCPolynomial = 0; //x_8+x_2+x_1+1 in python hex(2**8+2**2+2+1) SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; //AD5620 input register is 16 bit SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_Init(SPI1, &SPI_InitStructure); //DMA Globul Interrupt NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //DMA Globul Interrupt NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //DMA Configuration RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); DMA_DeInit(DMA2_Stream3); DMA_DeInit(DMA2_Stream2); DMA_Init_Structure.DMA_BufferSize = 1; DMA_Init_Structure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_Init_Structure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_Init_Structure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_Init_Structure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_Init_Structure.DMA_MemoryInc = DMA_MemoryInc_Disable; DMA_Init_Structure.DMA_Mode = DMA_Mode_Normal; DMA_Init_Structure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init_Structure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_Init_Structure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_Init_Structure.DMA_Priority = DMA_Priority_High; //Configure Tx DMA DMA_Init_Structure.DMA_Channel = DMA_Channel_3; DMA_Init_Structure.DMA_Memory0BaseAddr = (uint32_t)(&spi_tx_val); DMA_Init_Structure.DMA_PeripheralBaseAddr = (uint32_t) (&(SPI1->DR)); DMA_Init_Structure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_Cmd(DMA2_Stream3, DISABLE); while (DMA2_Stream3->CR & DMA_SxCR_EN); DMA_Init(DMA2_Stream3,&DMA_Init_Structure); //Configure Rx DMA DMA_Init_Structure.DMA_Channel = DMA_Channel_3; DMA_Init_Structure.DMA_Memory0BaseAddr = (uint32_t)(&spi_rx_val); DMA_Init_Structure.DMA_PeripheralBaseAddr = (uint32_t) (&(SPI1->DR)); DMA_Init_Structure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_Cmd(DMA2_Stream2, DISABLE); while (DMA2_Stream2->CR & DMA_SxCR_EN); DMA_Init(DMA2_Stream2,&DMA_Init_Structure); // DMA_ITConfig(DMA2_Stream3,DMA_IT_TC,ENABLE); DMA_ClearFlag(DMA2_Stream3, DMA_FLAG_FEIF3|DMA_FLAG_DMEIF3|DMA_FLAG_TEIF3|DMA_FLAG_HTIF3|DMA_FLAG_TCIF3); DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_FEIF2|DMA_FLAG_DMEIF2|DMA_FLAG_TEIF2|DMA_FLAG_HTIF2|DMA_FLAG_TCIF2); DMA_Cmd(DMA2_Stream3, ENABLE); //DMA SPI TX stream DMA_Cmd(DMA2_Stream2, ENABLE); //DMA SPI RX stream // SPI_SSOutputCmd(SPI1, ENABLE);// SPI_NSSInternalSoftwareConfig(SPI1,SPI_NSSInternalSoft_Set); SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx, ENABLE); SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx, ENABLE); SPI_Cmd(SPI1, ENABLE); }I have a breakpoint at DMA2_Stream3_IRQHandler which is never triggered. Why is the RXEN flag never set? It should be set after the last SCLK front. Should I use the SPI_SSOutputCmd()? I've tried it both ways, but neither is working.
