stm32f4 SPI DMA FLASH 传输调试

来源:项目中需要用stm32对外部spi flash(m25p16  2MB)进行快速读取,主要是图像数据。

平台:stm32f407---168MHz,FreeRTOS V7.3.0 

主要参考:http://blog.csdn.net/sinat_20598829/article/details/44408125

貌似发现了其中的一个小问题,未使用中断!!!见图

stm32f4 SPI DMA FLASH 传输调试_第1张图片

期间还参考帖子:http://blog.csdn.net/chenwei2002/article/details/49722373,本人不才,未能实现文中使用的方法。对于文中所讲:我们把SPI模式配置成只读模式,如上面程序中的样子,这个时候就可以直接读取数据,而不需要在发送无效数据0xff,大大提高了性能。SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_RxOnly; 然而在配置为只读模式后没有spi时钟驱动flash进行数据输出,故放弃此方法。

代码来源:st 官方spi flash驱动文件

(STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\Project\STM32F4xx_StdPeriph_Examples\SPI\SPI_FLASH)

在官方文件的基础上进行修改(注意修改红色部分):

/**
  ******************************************************************************
  *
  *          +-----------------------------------------------------------+
  *          |                     Pin assignment                        |
  *          +-----------------------------+---------------+-------------+
  *          |  STM32 SPI Pins             |     sFLASH    |    Pin      |
  *          +-----------------------------+---------------+-------------+
  *          | sFLASH_CS_PIN               | ChipSelect(/S)|    1        |
  *          | sFLASh_SPI_MISO_PIN / MISO  |   DataOut(Q)  |    2        |
  *          |                             |   VCC         |    3 (3.3 V)|
  *          |                             |   GND         |    4 (0 V)  |
  *          | sFLASH_SPI_MOSI_PIN / MOSI  |   DataIn(D)   |    5        |
  *          | sFLASH_SPI_SCK_PIN / SCK    |   Clock(C)    |    6        |
  *          |                             |    VCC        |    7 (3.3 V)|
  *          |                             |    VCC        |    8 (3.3 V)|
  *          +-----------------------------+---------------+-------------+
  ******************************************************************************
  * @attention
  * 
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "spi_dma_flash.h"
#include 
/** @addtogroup STM32F4xx_StdPeriph_Examples
  * @{
  */

/** @addtogroup SPI_FLASH
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define USE_SPI_DMA
#define SET_SPI1_ENABLE     SPI_Cmd(sFLASH_DMA_SPI, ENABLE);

#define DMA2_TX_STREAM      DMA2_Stream3
#define DMA2_TX_CHANNEL     DMA_Channel_3

#define DMA2_RX_STREAM      DMA2_Stream0
#define DMA2_RX_CHANNEL     DMA_Channel_3

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

static DMA_InitTypeDef DMA2_Tx_InitStructure;
static DMA_InitTypeDef DMA2_Rx_InitStructure;
/* Private function prototypes -----------------------------------------------*/
void sFLASH_DMA_LowLevel_DeInit(void);
void sFLASH_DMA_LowLevel_Init(void);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  DeInitializes the peripherals used by the SPI FLASH driver.
  * @param  None
  * @retval None
  */
void sFLASH_DMA_DeInit(void)
{
  sFLASH_DMA_LowLevel_DeInit();
}

/**
  * @brief  Initializes the peripherals used by the SPI FLASH driver.
  * @param  None
  * @retval None
  */
void sFLASH_DMA_Init(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
    
  sFLASH_DMA_LowLevel_Init();

  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_DMA_CS_HIGH();

  /*!< SPI configuration */
  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_High;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  
 
  DMA_Configuration_SPI1();
  SPI_Init(sFLASH_DMA_SPI, &SPI_InitStructure); 
  SET_SPI1_ENABLE;

}

/**
  * @brief  Erases the specified FLASH sector.
  * @param  SectorAddr: address of the sector to erase.
  * @retval None
  */
void sFLASH_DMA_EraseSector(uint32_t SectorAddr)
{
  /*!< Send write enable instruction */
  sFLASH_DMA_WriteEnable();

  /*!< Sector Erase */
  /*!< Select the FLASH: Chip Select low */
  sFLASH_DMA_CS_LOW();
  /*!< Send Sector Erase instruction */
  sFLASH_DMA_SendByte(sFLASH_DMA_CMD_SE);
  /*!< Send SectorAddr high nibble address byte */
  sFLASH_DMA_SendByte((SectorAddr & 0xFF0000) >> 16);
  /*!< Send SectorAddr medium nibble address byte */
  sFLASH_DMA_SendByte((SectorAddr & 0xFF00) >> 8);
  /*!< Send SectorAddr low nibble address byte */
  sFLASH_DMA_SendByte(SectorAddr & 0xFF);
  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_DMA_CS_HIGH();

  /*!< Wait the end of Flash writing */
  sFLASH_DMA_WaitForWriteEnd();
}

/**
  * @brief  Erases the entire FLASH.
  * @param  None
  * @retval None
  */
void sFLASH_DMA_EraseBulk(void)
{
  /*!< Send write enable instruction */
  sFLASH_DMA_WriteEnable();

  /*!< Bulk Erase */
  /*!< Select the FLASH: Chip Select low */
  sFLASH_DMA_CS_LOW();
  /*!< Send Bulk Erase instruction  */
  sFLASH_DMA_SendByte(sFLASH_DMA_CMD_BE);
  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_DMA_CS_HIGH();

  /*!< Wait the end of Flash writing */
  sFLASH_DMA_WaitForWriteEnd();
}

/**
  * @brief  Writes more than one byte to the FLASH with a single WRITE cycle
  *         (Page WRITE sequence).
  * @note   The number of byte can't exceed the FLASH page size.
  * @param  pBuffer: pointer to the buffer  containing the data to be written
  *         to the FLASH.
  * @param  WriteAddr: FLASH's internal address to write to.
  * @param  NumByteToWrite: number of bytes to write to the FLASH, must be equal
  *         or less than "sFLASH_DMA_PAGESIZE" value.
  * @retval None
  */
void sFLASH_DMA_WritePage(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
  /*!< Enable the write access to the FLASH */
  sFLASH_DMA_WriteEnable();

  /*!< Select the FLASH: Chip Select low */
  sFLASH_DMA_CS_LOW();
  /*!< Send "Write to Memory " instruction */
  sFLASH_DMA_SendByte(sFLASH_DMA_CMD_WRITE);
  /*!< Send WriteAddr high nibble address byte to write to */
  sFLASH_DMA_SendByte((WriteAddr & 0xFF0000) >> 16);
  /*!< Send WriteAddr medium nibble address byte to write to */
  sFLASH_DMA_SendByte((WriteAddr & 0xFF00) >> 8);
  /*!< Send WriteAddr low nibble address byte to write to */
  sFLASH_DMA_SendByte(WriteAddr & 0xFF);

  /*!< while there is data to be written on the FLASH */
  while (NumByteToWrite--)
  {
    /*!< Send the current byte */
    sFLASH_DMA_SendByte(*pBuffer);
    /*!< Point on the next byte to be written */
    pBuffer++;
  } 

  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_DMA_CS_HIGH();

  /*!< Wait the end of Flash writing */
  sFLASH_DMA_WaitForWriteEnd();
}

/**
  * @brief  Writes block of data to the FLASH. In this function, the number of
  *         WRITE cycles are reduced, using Page WRITE sequence.
  * @param  pBuffer: pointer to the buffer  containing the data to be written
  *         to the FLASH.
  * @param  WriteAddr: FLASH's internal address to write to.
  * @param  NumByteToWrite: number of bytes to write to the FLASH.
  * @retval None
  */
int sFLASH_DMA_WriteBuffer(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
  uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;

  Addr = WriteAddr % sFLASH_DMA_SPI_PAGESIZE;
  count = sFLASH_DMA_SPI_PAGESIZE - Addr;
  NumOfPage =  NumByteToWrite / sFLASH_DMA_SPI_PAGESIZE;
  NumOfSingle = NumByteToWrite % sFLASH_DMA_SPI_PAGESIZE;

  if (Addr == 0) /*!< WriteAddr is sFLASH_DMA_PAGESIZE aligned  */
  {
    if (NumOfPage == 0) /*!< NumByteToWrite < sFLASH_DMA_PAGESIZE */
    {
      sFLASH_DMA_WritePage(pBuffer, WriteAddr, NumByteToWrite);
    }
    else /*!< NumByteToWrite > sFLASH_DMA_PAGESIZE */
    {
      while (NumOfPage--)
      {
        sFLASH_DMA_WritePage(pBuffer, WriteAddr, sFLASH_DMA_SPI_PAGESIZE);
        WriteAddr +=  sFLASH_DMA_SPI_PAGESIZE;
        pBuffer += sFLASH_DMA_SPI_PAGESIZE;
      }

      sFLASH_DMA_WritePage(pBuffer, WriteAddr, NumOfSingle);
    }
  }
  else /*!< WriteAddr is not sFLASH_DMA_PAGESIZE aligned  */
  {
    if (NumOfPage == 0) /*!< NumByteToWrite < sFLASH_DMA_PAGESIZE */
    {
      if (NumOfSingle > count) /*!< (NumByteToWrite + WriteAddr) > sFLASH_DMA_PAGESIZE */
      {
        temp = NumOfSingle - count;

        sFLASH_DMA_WritePage(pBuffer, WriteAddr, count);
        WriteAddr +=  count;
        pBuffer += count;

        sFLASH_DMA_WritePage(pBuffer, WriteAddr, temp);
      }
      else
      {
        sFLASH_DMA_WritePage(pBuffer, WriteAddr, NumByteToWrite);
      }
    }
    else /*!< NumByteToWrite > sFLASH_DMA_PAGESIZE */
    {
      NumByteToWrite -= count;
      NumOfPage =  NumByteToWrite / sFLASH_DMA_SPI_PAGESIZE;
      NumOfSingle = NumByteToWrite % sFLASH_DMA_SPI_PAGESIZE;

      sFLASH_DMA_WritePage(pBuffer, WriteAddr, count);
      WriteAddr +=  count;
      pBuffer += count;

      while (NumOfPage--)
      {
        sFLASH_DMA_WritePage(pBuffer, WriteAddr, sFLASH_DMA_SPI_PAGESIZE);
        WriteAddr +=  sFLASH_DMA_SPI_PAGESIZE;
        pBuffer += sFLASH_DMA_SPI_PAGESIZE;
      }

      if (NumOfSingle != 0)
      {
        sFLASH_DMA_WritePage(pBuffer, WriteAddr, NumOfSingle);
      }
    }
  }
	return 0;
}


/**
  * @brief  Reads FLASH identification.
  * @param  None
  * @retval FLASH identification
  */
uint32_t sFLASH_DMA_ReadID(void)
{
  uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;

  /*!< Select the FLASH: Chip Select low */
  sFLASH_DMA_CS_LOW();

  /*!< Send "RDID " instruction */
  sFLASH_DMA_SendByte(0x9F);

  /*!< Read a byte from the FLASH */
  Temp0 = sFLASH_DMA_SendByte(sFLASH_DMA_DUMMY_BYTE);

  /*!< Read a byte from the FLASH */
  Temp1 = sFLASH_DMA_SendByte(sFLASH_DMA_DUMMY_BYTE);

  /*!< Read a byte from the FLASH */
  Temp2 = sFLASH_DMA_SendByte(sFLASH_DMA_DUMMY_BYTE);

  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_DMA_CS_HIGH();

  Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;

  return Temp;
}

/**
  * @brief  Reads a byte from the SPI Flash.
  * @note   This function must be used only if the Start_Read_Sequence function
  *         has been previously called.
  * @param  None
  * @retval Byte Read from the SPI Flash.
  */
uint8_t sFLASH_DMA_ReadByte(void)
{
  return (sFLASH_DMA_SendByte(sFLASH_DMA_DUMMY_BYTE));
}

/**
  * @brief  Sends a byte through the SPI interface and return the byte received
  *         from the SPI bus.
  * @param  byte: byte to send.
  * @retval The value of the received byte.
  */
uint8_t sFLASH_DMA_SendByte(uint8_t byte)
{
  /*!< Loop while DR register in not empty */
  while (SPI_I2S_GetFlagStatus(sFLASH_DMA_SPI, SPI_I2S_FLAG_TXE) == RESET);

  /*!< Send byte through the SPI1 peripheral */
  SPI_I2S_SendData(sFLASH_DMA_SPI, byte);

  /*!< Wait to receive a byte */
  while (SPI_I2S_GetFlagStatus(sFLASH_DMA_SPI, SPI_I2S_FLAG_RXNE) == RESET);

  /*!< Return the byte read from the SPI bus */
  return SPI_I2S_ReceiveData(sFLASH_DMA_SPI);
}


/**
  * @brief  Enables the write access to the FLASH.
  * @param  None
  * @retval None
  */
void sFLASH_DMA_WriteEnable(void)
{
  /*!< Select the FLASH: Chip Select low */
  sFLASH_DMA_CS_LOW();

  /*!< Send "Write Enable" instruction */
  sFLASH_DMA_SendByte(sFLASH_DMA_CMD_WREN);

  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_DMA_CS_HIGH();
}

/**
  * @brief  Polls the status of the Write In Progress (WIP) flag in the FLASH's
  *         status register and loop until write operation has completed.
  * @param  None
  * @retval None
  */
void sFLASH_DMA_WaitForWriteEnd(void)
{
  uint8_t flashstatus = 0;

  /*!< Select the FLASH: Chip Select low */
  sFLASH_DMA_CS_LOW();

  /*!< Send "Read Status Register" instruction */
  sFLASH_DMA_SendByte(sFLASH_DMA_CMD_RDSR);

  /*!< Loop as long as the memory is busy with a write cycle */
  do
  {
    /*!< Send a dummy byte to generate the clock needed by the FLASH
    and put the value of the status register in FLASH_Status variable */
    flashstatus = sFLASH_DMA_SendByte(sFLASH_DMA_DUMMY_BYTE);

  }
  while ((flashstatus & sFLASH_DMA_WIP_FLAG) == SET); /* Write in progress */

  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_DMA_CS_HIGH();
}

/**
  * @brief  Initializes the peripherals used by the SPI FLASH driver.
  * @param  None
  * @retval None
  */
void sFLASH_DMA_LowLevel_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /*!< Enable the SPI clock */
  sFLASH_DMA_SPI_CLK_INIT(sFLASH_DMA_SPI_CLK, ENABLE);

  /*!< Enable GPIO clocks */
  RCC_AHB1PeriphClockCmd(sFLASH_DMA_SPI_SCK_GPIO_CLK | sFLASH_DMA_SPI_MISO_GPIO_CLK |
                         sFLASH_DMA_SPI_MOSI_GPIO_CLK | sFLASH_DMA_CS_GPIO_CLK, ENABLE);

  /*!< SPI pins configuration *************************************************/

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

  /*!< SPI SCK pin configuration */
  GPIO_InitStructure.GPIO_Pin = sFLASH_DMA_SPI_SCK_PIN;
  GPIO_Init(sFLASH_DMA_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);

  /*!< SPI MOSI pin configuration */
  GPIO_InitStructure.GPIO_Pin =  sFLASH_DMA_SPI_MOSI_PIN;
  GPIO_Init(sFLASH_DMA_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);

  /*!< SPI MISO pin configuration */
  GPIO_InitStructure.GPIO_Pin =  sFLASH_DMA_SPI_MISO_PIN;
  GPIO_Init(sFLASH_DMA_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);

  /*!< Connect SPI pins to AF5 */
  GPIO_PinAFConfig(sFLASH_DMA_SPI_SCK_GPIO_PORT, sFLASH_DMA_SPI_SCK_SOURCE, sFLASH_DMA_SPI_SCK_AF);
  GPIO_PinAFConfig(sFLASH_DMA_SPI_MISO_GPIO_PORT, sFLASH_DMA_SPI_MISO_SOURCE, sFLASH_DMA_SPI_MISO_AF);
  GPIO_PinAFConfig(sFLASH_DMA_SPI_MOSI_GPIO_PORT, sFLASH_DMA_SPI_MOSI_SOURCE, sFLASH_DMA_SPI_MOSI_AF);

  /*!< Configure sFLASH_DMA Card CS pin in output pushpull mode ********************/
  GPIO_InitStructure.GPIO_Pin = sFLASH_DMA_CS_PIN;
  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(sFLASH_DMA_CS_GPIO_PORT, &GPIO_InitStructure);
}

/**
  * @brief  DeInitializes the peripherals used by the SPI FLASH driver.
  * @param  None
  * @retval None
  */
void sFLASH_DMA_LowLevel_DeInit(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /*!< Disable the sFLASH_DMA_SPI  ************************************************/
  SPI_Cmd(sFLASH_DMA_SPI, DISABLE);

  /*!< DeInitializes the sFLASH_DMA_SPI *******************************************/
  SPI_I2S_DeInit(sFLASH_DMA_SPI);

  /*!< sFLASH_DMA_SPI Periph clock disable ****************************************/
  sFLASH_DMA_SPI_CLK_INIT(sFLASH_DMA_SPI_CLK, DISABLE);

  /*!< Configure all pins used by the SPI as input floating *******************/
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_InitStructure.GPIO_Pin = sFLASH_DMA_SPI_SCK_PIN;
  GPIO_Init(sFLASH_DMA_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = sFLASH_DMA_SPI_MISO_PIN;
  GPIO_Init(sFLASH_DMA_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = sFLASH_DMA_SPI_MOSI_PIN;
  GPIO_Init(sFLASH_DMA_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = sFLASH_DMA_CS_PIN;
  GPIO_Init(sFLASH_DMA_CS_GPIO_PORT, &GPIO_InitStructure);
}

/**
  * @brief  Clear DMA transfer flags.
  * @param  None
  * @retval None
  */
void ClrDmaFlag(void)
{
    DMA_ClearFlag(DMA2_RX_STREAM, DMA_FLAG_TCIF0);
    DMA_ClearFlag(DMA2_TX_STREAM, DMA_FLAG_TCIF3);
}

/**
  * @brief  Reads a block of data from the FLASH.
  * @param  pBuffer: pointer to the buffer that receives the data read from the FLASH.
  * @param  ReadAddr: FLASH's internal address to read from.
  * @param  NumByteToRead: number of bytes to read from the FLASH.
  * @retval None
  */
void sFLASH_DMA_ReadBuffer(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{

  /*!< Select the FLASH: Chip Select low */
  sFLASH_DMA_CS_LOW();

  /*!< Send "Read from Memory " instruction */
  sFLASH_DMA_SendByte(sFLASH_DMA_CMD_READ);
   
  /*!< Send ReadAddr high nibble address byte to read from */
  sFLASH_DMA_SendByte((ReadAddr & 0xFF0000) >> 16);
  /*!< Send ReadAddr medium nibble address byte to read from */
  sFLASH_DMA_SendByte((ReadAddr& 0xFF00) >> 8);
  /*!< Send ReadAddr low nibble address byte to read from */
  sFLASH_DMA_SendByte(ReadAddr & 0xFF);

#ifdef  USE_SPI_DMA   //ʹÓÃDMA
    while (DMA_GetCmdStatus(DMA2_RX_STREAM) != DISABLE){}; 
    /* ÖØÐÂÅäÖÃDMAÔ´µØÖ· ¼°´«ÊäÏîÄ¿Êý */
    DMA2_Rx_InitStructure.DMA_Memory0BaseAddr = (uint32_t)pBuffer;
    DMA2_Rx_InitStructure.DMA_BufferSize = NumByteToRead;
    DMA_Init(DMA2_RX_STREAM, &DMA2_Rx_InitStructure);

    /* ʹÄÜDMA·¢Ë͵ÄÄ¿µÄÊÇÔÚ½ÓÊÕflashÊý¾ÝʱÐèÒªÌṩ½ÓÊÕʱÖÓ */
    while (DMA_GetCmdStatus(DMA2_TX_STREAM) != DISABLE){};
    DMA2_Tx_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&pBuffer;
    DMA2_Tx_InitStructure.DMA_BufferSize = NumByteToRead;
    DMA_Init(DMA2_TX_STREAM, &DMA2_Tx_InitStructure);
    
    /* ʹÄÜSPI DMA ½ÓÊպͷ¢ËÍÇëÇó */
	SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx|SPI_I2S_DMAReq_Tx, ENABLE);
  	
    /* ʹÄÜÒ»´ÎDMA ´«Êä */    
    DMA_Cmd(DMA2_RX_STREAM, ENABLE); 
    DMA_Cmd(DMA2_TX_STREAM, ENABLE);
    
    /*µÈ´ýDMA ´«ÊäÍê³É */
	while(DMA_GetFlagStatus(DMA2_RX_STREAM, DMA_FLAG_TCIF0) == RESET){};
    
    /* ±ØÐëÇå³ý ½ÓÊÕ¡¢·¢ËÍÍê³É±ê־λ */
    ClrDmaFlag();
    SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx|SPI_I2S_DMAReq_Tx, DISABLE); 

	sFLASH_DMA_CS_HIGH();
#else   //²»Ê¹ÓÃDMA   
    
    while (NumByteToRead--) /*!< while there is data to be read */
    {
        /*!< Read a byte from the FLASH */
        *pBuffer = sFLASH_DMA_SendByte(sFLASH_DMA_DUMMY_BYTE);
        /*!< Point to the next location where the byte read will be saved */
        pBuffer++;
    }
    /*!< Deselect the FLASH: Chip Select high */
    sFLASH_DMA_CS_HIGH();
#endif

}

/*******************************************************************************
* Function Name  : DMA_Configuration_SPI1
* Description    : SPI1 DMAÊý¾Ý´«ÊäÅäÖã¬ÊÊÓÃÓÚstm32F4ϵÁÐ
* Input          : none
* Output         : None
* Return         : None
*******************************************************************************/
void DMA_Configuration_SPI1(void)
{
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2 ʼÖÕ³õʼ»¯
    DMA_DeInit(DMA2_TX_STREAM);
     
    DMA2_Tx_InitStructure.DMA_Channel = DMA2_TX_CHANNEL;
    DMA2_Tx_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI1->DR;
    DMA2_Tx_InitStructure.DMA_Memory0BaseAddr = 0;
    DMA2_Tx_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
    DMA2_Tx_InitStructure.DMA_BufferSize = 0;
    DMA2_Tx_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA2_Tx_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
    DMA2_Tx_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA2_Tx_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA2_Tx_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA2_Tx_InitStructure.DMA_Priority = DMA_Priority_Medium;
    DMA2_Tx_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA2_Tx_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA2_Tx_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA2_Tx_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    
    /* DMA2 stream0 --- SPI1-RX configuration */
    DMA_DeInit(DMA2_RX_STREAM);
    DMA2_Rx_InitStructure.DMA_Channel = DMA2_RX_CHANNEL;
    DMA2_Rx_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI1->DR;
    DMA2_Rx_InitStructure.DMA_Memory0BaseAddr = 0;
    DMA2_Rx_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
    DMA2_Rx_InitStructure.DMA_BufferSize = 0;
    DMA2_Rx_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA2_Rx_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA2_Rx_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA2_Rx_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA2_Rx_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA2_Rx_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA2_Rx_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;    //FIFOģʽ¹Ø±Õ
    DMA2_Rx_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA2_Rx_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;           //  ÄÚ´æÍ»·¢µ¥´Î´«Êä
    DMA2_Rx_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;  //ÍâÉèÍ»·¢µ¥´Î´«Êä
  
}


/**
  * @brief  M25P16д²âÊÔ: 32¸öÉÈÇø £¬Ã¿¸öÉÈÇø64KB 
  * @param  None
  * @retval 0: true, 1:flase
  */
uint8_t dmaFlashWrite_Test(void)
{
	uint8_t flashData[256];
	uint32_t i=0;
	sFLASH_DMA_EraseBulk();
//    sFLASH_DMA_EraseSector(0x0);    
    for (i=0x0;i<0x100;i++)
    {
		flashData[i]= i;
    }
    for (i=0;i<8192;i++)
    { 
        sFLASH_DMA_WriteBuffer(flashData, i*256, 256);
    }
    printf("spi flash write done!\r\n");
    return 0;
    
}


/**
  * @brief  M25P16¶Á²âÊÔ
  * @param  None
  * @retval 0: true, 1:flase
  */
u8 Rx_Buffer[65535];
uint8_t dmaFlashRead_Test(void)
{

	uint32_t i,j=0;  
    for(i=0; i<16; i++)
    {
        sFLASH_DMA_ReadBuffer(Rx_Buffer, i*65535, 0xFFFF);
    
        if(i==10)
        {
            for(j=1; j<0x100; j++)
            {  
 //               printf("0x%02x ",Rx_Buffer[j]); 
            }
//            memset(Rx_Buffer, 0, 0xffff);
        }
        else if(i==15)
        {
          for(j=1; j<0x100; j++)
            {  
//                printf("0x%02x ",Rx_Buffer[j]); 
            }  
        }
 //       printf("\rspi flash read 65k count:%d \r\n", i);
    }
	return 0;
}


/**
  * @}
  */

/**
  * @}
  */

/*****END OF FILE****/

调试信息:

stm32f4 SPI DMA FLASH 传输调试_第2张图片

上图的关键信息在于不使用DMA接收完成中断时,需要再次进行DMA传输时要及时手动清接收及发送完成FLAG。

参考测试结果:总共读取1MB数据,每次数据量65536,总共16次。

可用宏USB_SPI_DMA 使能DMA传输功能

开启DMA传输后用时约260 ticks(1S = 1000ticks)

未开启用时约900 ticks

貌似性能提升也不是很高,有童鞋测试结果明显的,分享下优化方法吧。

你可能感兴趣的:(STM32,嵌入式)