Stm32f4 dma with spi

0

I've gotten my SPI line working and can successfully store and send data. Essentially the next step for me would be understanding and coding the DMAC.

The following is my SPI Code with the added DMA code:

#include "stm32f4xx.h"


int main(void)
{
//Initialize Variables
//*****************************************************************************

    //Variables to check the state of the SPI bus.
HAL_SPI_StateTypeDef t;
HAL_DMA_StateTypeDef t1;
//  uint32_t x;
uint8_t message = 0xDFDF;

//*****************************************************************************


//(1)Declare a SPI_HandleTypeDef handle structure, for example: SPI_HandleTypeDef  hspi;
//*****************************************************************************
SPI_HandleTypeDef  SPIinit;
SPIinit.Instance = SPI1;
//*****************************************************************************

//(2)Initialize the SPI low level resources by implementing the HAL_SPI_MspInit ()API:
//*****************************************************************************
HAL_SPI_MspInit(&SPIinit);
//*****************************************************************************

// (3) Enable the SPIx interface clock
//*****************************************************************************
__HAL_RCC_SPI1_CLK_ENABLE();
//*****************************************************************************

// (4) SPI pins configuration
//(4.a) Enable the clock for the SPI GPIOs
//*****************************************************************************
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
//*****************************************************************************

//(4.b) Configure these SPI pins as alternate function push-pull
//*****************************************************************************
//Configure the SPI SCK,MISO & MOSI pins
GPIO_InitTypeDef SCK;

SCK.Pin       = GPIO_PIN_3;
SCK.Mode      = GPIO_MODE_AF_PP;
SCK.Pull      = GPIO_NOPULL;
SCK.Speed     = GPIO_SPEED_HIGH;
SCK.Alternate = GPIO_AF5_SPI1;

HAL_GPIO_Init(GPIOB, &SCK);


GPIO_InitTypeDef MISO;

MISO.Pin       = GPIO_PIN_4;
MISO.Mode      = GPIO_MODE_AF_PP;
MISO.Pull      = GPIO_NOPULL;
MISO.Speed     = GPIO_SPEED_HIGH;
MISO.Alternate = GPIO_AF5_SPI1;

HAL_GPIO_Init(GPIOB, &MISO);


GPIO_InitTypeDef MOSI;

MOSI.Pin       = GPIO_PIN_5;
MOSI.Mode      = GPIO_MODE_AF_PP;
MOSI.Pull      = GPIO_NOPULL;
MOSI.Speed     = GPIO_SPEED_HIGH;
MOSI.Alternate = GPIO_AF5_SPI1;

HAL_GPIO_Init(GPIOB, &MOSI);

//Configure the SPI NSS pin
GPIO_InitTypeDef NSS;

NSS.Pin       = GPIO_PIN_4;
NSS.Mode      = GPIO_MODE_OUTPUT_PP;
NSS.Pull      = GPIO_NOPULL;
NSS.Speed     = GPIO_SPEED_HIGH;


HAL_GPIO_Init(GPIOA, &NSS);
//*****************************************************************************


//*****************************************************************************
//*********************SET UP THE DMA FOR MEM TO PERIPH*************************
//*****************************************************************************


//(+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive stream

DMA_HandleTypeDef DMAinit;
HAL_DMA_Init(&DMAinit);
HAL_DMA_DeInit(&DMAinit);

while (DMAinit.State != HAL_DMA_STATE_RESET )
  { t1 = DMAinit.State;
    HAL_DMA_DeInit(&DMAinit);
  }



//(+++) Enable the DMAx interface clock using
__HAL_RCC_DMA2_CLK_ENABLE();

//(+++) Configure the DMA handle parameters
DMAinit.Instance = DMA2_Stream3_IRQn;
DMAinit.Init.Channel = DMA_CHANNEL_3;
DMAinit.Init.Direction = DMA_MEMORY_TO_PERIPH;
DMAinit.Init.PeriphInc = DMA_PINC_DISABLE;
DMAinit.Init.MemInc = DMA_MINC_DISABLE;
DMAinit.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
DMAinit.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
DMAinit.Init.Mode = DMA_CIRCULAR;
DMAinit.Init.Priority = DMA_PRIORITY_VERY_HIGH;

//(+++) Configure the DMA Tx or Rx Stream


//(+++) Associate the initialized hdma_tx handle to the hspi DMA Tx or Rx handle

__HAL_LINKDMA(&SPIinit,hdmatx,DMAinit);


//(+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx or Rx Stream

HAL_DMA_Init(&DMAinit);
__HAL_DMA_ENABLE(&DMAinit);
//(5) Program the Mode, Direction , Data size, Baudrate Prescaler, NSS management, Clock polarity and phase, FirstBit and CRC configuration in the hspi Init structure
//*****************************************************************************
SPIinit.Init.Mode = SPI_MODE_MASTER;
SPIinit.Init.DataSize =  SPI_DATASIZE_16BIT;
SPIinit.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
SPIinit.Init.CLKPolarity = SPI_POLARITY_LOW;
SPIinit.Init.FirstBit = SPI_FIRSTBIT_MSB;
SPIinit.Init.TIMode = SPI_TIMODE_DISABLE ;
SPIinit.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
SPIinit.Init.NSS = SPI_NSS_SOFT;
SPIinit.Init.Direction = SPI_DIRECTION_2LINES;
//*****************************************************************************
//(6) Initialize the SPI registers by calling the HAL_SPI_Init() API:
//*****************************************************************************
HAL_SPI_Init(&SPIinit);
//*****************************************************************************

__HAL_SPI_ENABLE(&SPIinit);

t1 = DMAinit.State;

HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);

t1 = DMAinit.State;
t = SPIinit.State;

HAL_DMA_Start(&DMAinit,&message,&SPIinit,1);

t1 = DMAinit.State;
t = SPIinit.State;

HAL_SPI_Transmit_DMA(&SPIinit, &message, 1);

t1 = DMAinit.State;
t = SPIinit.State;

HAL_DMA_PollForTransfer(&DMAinit,HAL_DMA_FULL_TRANSFER,0x00);

t1 = DMAinit.State;
t = SPIinit.State;

HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);



}

//*****************************************************************************
//**************************ERROR AND STATE CHECKS*****************************
//*****************************************************************************

//  SPI STATE CHECK
// HAL_SPI_STATE_RESET      = 0x00,  /*!< SPI not yet initialized or disabled                */
// HAL_SPI_STATE_READY      = 0x01,  /*!< SPI initialized and ready for use                  */
// HAL_SPI_STATE_BUSY       = 0x02,  /*!< SPI process is ongoing                             */
// HAL_SPI_STATE_BUSY_TX    = 0x12,  /*!< Data Transmission process is ongoing               */
// HAL_SPI_STATE_BUSY_RX    = 0x22,  /*!< Data Reception process is ongoing                  */
// HAL_SPI_STATE_BUSY_TX_RX = 0x32,  /*!< Data Transmission and Reception process is ongoing */
// HAL_SPI_STATE_ERROR      = 0x03   /*!< SPI error state                                    */

//  SPI ERROR CHECK
//#define HAL_SPI_ERROR_NONE         ((uint32_t)0x00000000)   /*!< No error             */
//#define HAL_SPI_ERROR_MODF         ((uint32_t)0x00000001)   /*!< MODF error           */
//#define HAL_SPI_ERROR_CRC          ((uint32_t)0x00000002)   /*!< CRC error            */
//#define HAL_SPI_ERROR_OVR          ((uint32_t)0x00000004)   /*!< OVR error            */
//#define HAL_SPI_ERROR_FRE          ((uint32_t)0x00000008)   /*!< FRE error            */
//#define HAL_SPI_ERROR_DMA          ((uint32_t)0x00000010)   /*!< DMA transfer error   */
//#define HAL_SPI_ERROR_FLAG         ((uint32_t)0x00000010)   /*!< Flag: RXNE,TXE, BSY  */

//  DMA STATE CHECK

//HAL_DMA_STATE_RESET             = 0x00,  /*!< DMA not yet initialized or disabled */
//HAL_DMA_STATE_READY             = 0x01,  /*!< DMA initialized and ready for use   */
//HAL_DMA_STATE_READY_MEM0        = 0x11,  /*!< DMA Mem0 process success            */
//HAL_DMA_STATE_READY_MEM1        = 0x21,  /*!< DMA Mem1 process success            */
//HAL_DMA_STATE_READY_HALF_MEM0   = 0x31,  /*!< DMA Mem0 Half process success       */
//HAL_DMA_STATE_READY_HALF_MEM1   = 0x41,  /*!< DMA Mem1 Half process success       */
//HAL_DMA_STATE_BUSY              = 0x02,  /*!< DMA process is ongoing              */
//HAL_DMA_STATE_BUSY_MEM0         = 0x12,  /*!< DMA Mem0 process is ongoing         */
//HAL_DMA_STATE_BUSY_MEM1         = 0x22,  /*!< DMA Mem1 process is ongoing         */
//HAL_DMA_STATE_TIMEOUT           = 0x03,  /*!< DMA timeout state                   */
//HAL_DMA_STATE_ERROR             = 0x04,  /*!< DMA error state                     */


//  DMA ERROR CHECK
//#define HAL_DMA_ERROR_NONE      ((uint32_t)0x00000000)    /*!< No error             */
//#define HAL_DMA_ERROR_TE        ((uint32_t)0x00000001)    /*!< Transfer error       */
//#define HAL_DMA_ERROR_FE        ((uint32_t)0x00000002)    /*!< FIFO error           */
//#define HAL_DMA_ERROR_DME       ((uint32_t)0x00000004)    /*!< Direct Mode error    */
//#define HAL_DMA_ERROR_TIMEOUT   ((uint32_t)0x00000020)    /*!< Timeout error        */

I don't think its necessary to configure the NVIC as I'll be polling the DMA.

also this line avaids me as I'm not entirely sure what they'd like me to do:

//(+++) Configure the DMA Tx or Rx Stream (From the SPI c file)

I'm using a nucleo F446RE board with an stm32f446RET6U.

According to my understanding the DMA will pull data from memory(which I've just used as a variable, later I'll be pulling from SRAM and Flash) and push it to the peripheral in this case(the SPI line), through the bus matrix. The peripheral can then push this data to the slave without having to waste clock cycles fetching and filling data. Really not sure why my code might not be working, I did check the error codes for the DMA and receive none, except after polling, then I receive a timeout error. THE DMA remains ready until HAL__DMA_Start, the it switches to Busy. THE SPI error checks also produce none, and the SPI line state remains ready until after:

HAL_SPI_Transmit_DMA(&SPIinit, &message, 1);

Where state changes to:HAL_SPI_STATE_BUSY_TX.

Any chance, anyone can please help me or point me in the right direction? Been through reference manuals,etc.

Thanks in advance for any help

arm
stm32
nucleo

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0