cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407 SPI-DMA Continuous Transmit and Receive.

abhisheke
Associate II
Posted on May 27, 2015 at 12:11

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);

//

http://www.ti.com/product/CC3100

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);

}
6 REPLIES 6
abhisheke
Associate II
Posted on May 29, 2015 at 10:30

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.

abhisheke
Associate II
Posted on June 01, 2015 at 07:26

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.

Posted on June 01, 2015 at 08:40

You might want to test the communication without DMA, in polled mode, first.

JW

abhisheke
Associate II
Posted on June 01, 2015 at 09:08

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.

abhisheke
Associate II
Posted on June 02, 2015 at 07:15

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;

}

abhisheke
Associate II
Posted on June 02, 2015 at 09:15

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.