2015-05-27 03:11 AM
Hi,
I am trying to configure the DMA based SPI communication for STM32F407. STM32F407 is the host controller(master), the slave is CC3100 WiFi module. I am implementing the DMA for SPI2. Following is my configuration code:- static void InitSPI(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; // Enable peripheral clock RCC_APB1PeriphClockCmd(WIFI_SPI_CLK, ENABLE); // CLK pin RCC_AHB1PeriphClockCmd(WIFI_SPI_CLK_GPIO_CLK, ENABLE); GPIO_InitStructure.GPIO_Pin = WIFI_SPI_CLK_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = WIFI_GPIO_SPEED; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; // GPIO_PuPd_UP GPIO_Init(WIFI_SPI_CLK_GPIO_PORT, &GPIO_InitStructure); GPIO_PinAFConfig(WIFI_SPI_CLK_GPIO_PORT, WIFI_SPI_CLK_SOURCE, WIFI_SPI_CLK_AF); // MISO pin RCC_AHB1PeriphClockCmd(WIFI_SPI_MISO_GPIO_CLK, ENABLE); GPIO_InitStructure.GPIO_Pin = WIFI_SPI_MISO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = WIFI_GPIO_SPEED; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; // GPIO_PuPd_UP GPIO_Init(WIFI_SPI_MISO_GPIO_PORT, &GPIO_InitStructure); GPIO_PinAFConfig(WIFI_SPI_MISO_GPIO_PORT, WIFI_SPI_MISO_SOURCE, WIFI_SPI_MISO_AF); // MOSI pin RCC_AHB1PeriphClockCmd(WIFI_SPI_MOSI_GPIO_CLK, ENABLE); GPIO_InitStructure.GPIO_Pin = WIFI_SPI_MOSI_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = WIFI_GPIO_SPEED; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; // GPIO_PuPd_UP GPIO_Init(WIFI_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure); GPIO_PinAFConfig(WIFI_SPI_MOSI_GPIO_PORT, WIFI_SPI_MOSI_SOURCE, WIFI_SPI_MOSI_AF); // SPI configuration SPI_I2S_DeInit(WIFI_SPI); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // SPI_CPOL_High SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // SPI_CPHA_2Edge SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // SPI_NSS_Hard / SPI_NSSInternalSoft_Set SPI_InitStructure.SPI_BaudRatePrescaler = WIFI_SPI_BAUDRATE_PRESCALER; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(WIFI_SPI, &SPI_InitStructure); DMA_InitTypeDef DMA_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE); DMA_DeInit(DMA1_Stream4); //SPI1_TX_DMA_STREAM DMA_DeInit(DMA1_Stream3); //SPI1_RX_DMA_STREAM //Enabling DMA for SPI DMA_InitStructure.DMA_BufferSize = WIFI_DMA_SIZE; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable ; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull ; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(SPI2->DR)); DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_Priority = DMA_Priority_High; /* Configure Tx DMA */ DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) gu8a_INIT_DmaWifiTx; DMA_Init(DMA1_Stream4, &DMA_InitStructure); /* Configure Rx DMA */ DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) gu8a_INIT_DmaWifiRx; DMA_Init(DMA1_Stream3, &DMA_InitStructure); DMA_Cmd(DMA1_Stream4, ENABLE); /* Enable the DMA SPI TX Stream */ DMA_Cmd(DMA1_Stream3, ENABLE); /* Enable the DMA SPI RX Stream */ /* Enable the SPI Rx/Tx DMA request */ SPI_I2S_DMACmd(WIFI_SPI, SPI_I2S_DMAReq_Rx, ENABLE); SPI_I2S_DMACmd(WIFI_SPI, SPI_I2S_DMAReq_Tx, ENABLE); // Enable SPI2 SPI_Cmd(WIFI_SPI, ENABLE); }2015-05-29 01:30 AM
Further, the slave CC3100 is configured to call the functions sl_IfWrite and sl_IfRead for sending and receiving data.
The following are the two functions:- sl_IfWrite() { /* SPI in Tramitter mode */ if (SPI_I2S_GetITStatus(WIFI_SPI, SPI_I2S_IT_TXE) == SET) { if (WiFiTxIndex < WIFI_DMA_SIZE) { /* Send Transaction data */ SPI_I2S_SendData(WIFI_SPI, gu8a_INIT_DmaWifiTx[WiFiTxIndex++]); } else { WiFiTxIndex=0; /* Disable the Tx buffer empty interrupt */ SPI_I2S_ITConfig(WIFI_SPI, SPI_I2S_IT_TXE, DISABLE); } while (DMA_GetFlagStatus(DMA1_Stream4,DMA_FLAG_TCIF4)==RESET); /* Clear DMA Transfer Complete Flags */ //DMA_ClearFlag(DMA1_Stream4,DMA_FLAG_TCIF4); } } sl_IfRead() { /* SPI in Receiver mode */ if (SPI_I2S_GetITStatus(WIFI_SPI, SPI_I2S_IT_RXNE) == SET) { if (WiFiRxIndex < WIFI_DMA_SIZE) { /* Receive Transaction data */ gu8a_INIT_DmaWifiRx[WiFiRxIndex++] = SPI_I2S_ReceiveData(WIFI_SPI); } else { WiFiRxIndex=0; /* Disable the Rx buffer not empty interrupt */ SPI_I2S_ITConfig(WIFI_SPI, SPI_I2S_IT_RXNE, DISABLE); } while (DMA_GetFlagStatus(DMA1_Stream3,DMA_FLAG_TCIF3)==RESET); /* Clear DMA Transfer Complete Flags */ //DMA_ClearFlag(DMA1_Stream3,DMA_FLAG_TCIF3); } } But i am unable to achieve the communication. Any suggestion would be helpful. Regards, Abhishek.2015-05-31 10:26 PM
Hi,
I tried changing the send and receive functions to achieve DMA data transfer, as follows:-sl_IfWrite(int fd, unsigned char* data, unsigned char length) { WIFI_CS_LOW(); for (i = 0; i < length; i++) { gu8a_WifiTx[i] = data[i]; } WIFI_CS_HIGH(); }sl_IfRead(int fd, unsigned char* data, unsigned char length) { int i; WIFI_CS_LOW(); for (i = 0; i < length; i++) { data[i] = gu8a_WifiRx[i]; } WIFI_CS_HIGH(); } and the DMA interrupt handlers:-void DMA1_Stream4_IRQHandler() { unsigned char TXcnt = 0; if(DMA_GetITStatus(DMA1_Stream4, DMA_IT_TCIF4) /*|| DMA_GetITStatus(DMA1_Stream4, DMA_IT_HTIF4)*/) { TXcnt = DMA_GetCurrDataCounter(DMA1_Stream4); while(TXcnt) { gu8a_INIT_DmaWifiTx[WiFiDMATxIndex] = gu8a_WifiTx[WiFiTxIndex]; WiFiTxIndex++; if(WiFiTxIndex >= WIFI_TX_RX_SIZE) WiFiTxIndex = 0; TXcnt--; WiFiDMATxIndex++; if(WiFiDMATxIndex == WIFI_DMA_SIZE) { WiFiDMATxIndex = 0; } } ErrorOnDevice.btCommandError = 0; //DMA_ClearITPendingBit(DMA1_Stream4, DMA_IT_HTIF4); DMA_ClearITPendingBit(DMA1_Stream4, DMA_IT_TCIF4); } }void DMA1_Stream3_IRQHandler() { unsigned char RXcnt = 0; if(DMA_GetITStatus(DMA1_Stream3, DMA_IT_TCIF3) /*|| DMA_GetITStatus(DMA1_Stream3, DMA_IT_HTIF3)*/) { RXcnt = DMA_GetCurrDataCounter(DMA1_Stream3); while(RXcnt) { gu8a_WifiRx[WiFiRxIndex] = gu8a_INIT_DmaWifiRx[WiFiDMARxIndex]; WiFiRxIndex++; if(WiFiRxIndex >= WIFI_TX_RX_SIZE) WiFiRxIndex = 0; RXcnt--; WiFiDMARxIndex++; if(WiFiDMARxIndex == WIFI_DMA_SIZE) { WiFiDMARxIndex = 0; } } ErrorOnDevice.btCommandError = 0; //DMA_ClearITPendingBit(DMA1_Stream3, DMA_IT_HTIF3); DMA_ClearITPendingBit(DMA1_Stream3, DMA_IT_TCIF3); } } In this trial, i am getting both the DMA interrupts only once. Still unable to achieve the SPI-DMA communication. Please help!! Thank you in advance, Abhishek.2015-05-31 11:40 PM
You might want to test the communication without DMA, in polled mode, first.
JW2015-06-01 12:08 AM
Hi Jan Waclawek,
Thank you very much for replying. Sorry i didn't mention that, but i did check with polled mode. It is working when i poll the SPI flags and send data one-by-one. But it is not working when i fill the DMA Tx and Rx buffers and poll the DMA Flags. Thanks and regards, Abhishek.2015-06-01 10:15 PM
Hi Jan,
I checked in polled mode. I am able to do the communication in polled mode, by polling the TXE and RXNE flags. Here are the functions:- int SendData(int fd, unsigned char* data, unsigned char length) { int i; WIFI_CS_LOW(); for (i = 0; i < length; i++) { SendByte(data[i]); } WIFI_CS_HIGH(); return i; } int ReceiveData(int fd, unsigned char* data, unsigned char length) { int i; WIFI_CS_LOW(); for (i = 0; i < length; i++) { data[i] = SendByte(WIFI_DUMMY_BYTE); } WIFI_CS_HIGH(); return i; } static unsigned char SendByte(unsigned char data) { unsigned char b = 0; int i; // Wait until the transmit buffer is empty i = 0; while (SPI_I2S_GetFlagStatus(WIFI_SPI, SPI_I2S_FLAG_TXE) == RESET) i++; // Send the byte to the SPI bus SPI_I2S_SendData(WIFI_SPI, data); // Wait to Read a byte i = 0; while (SPI_I2S_GetFlagStatus(WIFI_SPI, SPI_I2S_FLAG_RXNE) == RESET) i++; // Wait until SPI is not busy anymore while (SPI_I2S_GetFlagStatus(WIFI_SPI, SPI_I2S_FLAG_BSY) == SET) ; // Return the byte read from the SPI bus b = SPI_I2S_ReceiveData(WIFI_SPI); return b; }2015-06-02 12:15 AM
Hi,
Let me explain where i am exactly stuck. Probably that will make it easier for you to help me...
The CC3100 is WIFI chip, connected through SPI interface to my HOST controller STM32F407.I am using non-os based environment.
1)The CC3100 gives an interrupt (external IRQ) to the HOST controller that it is ready to transmit/receive data.
2)The functions sl_IfWrite and sl_IfRead are called internally.
3)The sl_IfWrite writes data into the SPI to send to CC3100 and the sl_IfRead reads data on the SPI from the CC3100.
I have achieved the communication by polling the SPI flags.
Now, my problem is, i don't want to poll the flags and wait for the SPI transfer to complete.
I want to achieve this SPI transfer on SPI or DMA interrupt.
But i am unable to achieve this.
Maybe you can point me in the right direction now.
Thanks and regards,
Abhishek.