Continuous Serial Communications Clock of K21F DSPI

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Continuous Serial Communications Clock of K21F DSPI

1,154 Views
fredfu
NXP Employee
NXP Employee

       One of my key customer is using DSPI1 to read extern flash, now they meet one problem, they want to read flash content via DMA,but SPI1 has only one DMA request source number for Transmit or Receive, so they send the flash command manually(without DMA), then enable DMA and set CONT_SCKE to generate continuous SCK signal to read flash,DMA can't get any data, the buffer is empty,We use Oscilloscope to observe wave, we can find the data from Flash;If they sent the dummy data( CONT_SCKE is clear) manually and received data using DMA, it is OK. I don't know if there is any error on SPI setting and DMA setting, or K21 can't support the usage? Thanks


int STDCALL SFlashHwInit(VOID)
{
  //SPI配置结构体定义
    SPI_InitTypeDef   SPI_InitStructure = SPI_INIT_DEFAULT;
 
  //时钟初始化
    SIM_SCGxClockEnable(SCG6, SFLASH_SPI_CLK_MASK);
    SIM_SCGxClockEnable(SCG5, SFLASH_GPIO_CLK_MASK);
   
//SPI IO口设置
GPIO_Set(SFLASH_SCK_GPIO, SFLASH_SCK_PIN, GPIO_Direction_OUT, SFLASH_SCK_MUX, GPIO_SlewRate_Fast | GPIO_DriveStrength_High);
GPIO_Set(SFLASH_MOSI_GPIO, SFLASH_MOSI_PIN, GPIO_Direction_OUT, SFLASH_MOSI_MUX, GPIO_SlewRate_Fast);
GPIO_Set(SFLASH_CS_GPIO, SFLASH_CS_PIN, GPIO_Direction_OUT, SFLASH_CS_MUX, GPIO_SlewRate_Fast);
GPIO_Set(SFLASH_MISO_GPIO, SFLASH_MISO_PIN, GPIO_Direction_IN, SFLASH_MISO_MUX, GPIO_SlewRate_Fast);
GPIO_Set(GPIOA, GPIO_Pin_13, GPIO_Direction_OUT, GPIO_MUX_ALT1, GPIO_SlewRate_Fast);
    GPIO_SetBits(SFLASH_CS_GPIO, SFLASH_CS_PIN);
    #ifdef SFLASH_WP_PIN
GPIO_Set(SFLASH_WP_GPIO, SFLASH_WP_PIN, GPIO_Direction_OUT, SFLASH_WP_MUX, GPIO_SlewRate_Fast);
#endif

    //spi, clock is 48/2 = 24 MHz
    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_BaudrateScaler = SPI_BAUDRATE_SCALER_4;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_PSCState = SPI_PSC0State_High;
    SPI_InitStructure.SPI_BaudratePreScaler = SPI_BAUDRATE_PRESCALER_2;
    SPI_Init(SFLASH_SPI, &SPI_InitStructure);
    SPI1DMAConfig(szSPIBuf, SPI_DMA_BUF_LEN);
    SPI_Cmd(SFLASH_SPI, ENABLE);
#ifdef SFLASH_WP_PIN
    //WP设为上拉输入,由硬件上拉,此处也做上拉处理
    GPIO_SetBits(SFLASH_WP_GPIO, SFLASH_WP_PIN);
#endif

     //DMA_ReqCmd(DMA_CH3, ENABLE);
  
    return SUCCESS;
}

// void _SFlashWaitData(void)
// {
//  while ((SFLASH_SPI->SR & SPI_FLAG_RFDF) == RESET)
//  {
//   ;
//  }
//  SFLASH_SPI->SR |= SPI_FLAG_RFDF;
// }

INT SPI1DMAConfig(P_U8 DMABuf, UINT DMABufLen)
{
    DMA_InitTypeDef DMA_InitStructure;

  // 打开DMA时钟
    SIM_ModuleClockCmd(DMA_CLK, ENABLE);
    SIM_ModuleClockCmd(DMAMUX_CLK, ENABLE);
SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK;

    DMA_InitStructure.DMA_Channelx = DMA_CH3;
    DMA_InitStructure.DMA_Source_Req = 18;//SPI1_REV_DMAREQ;
    DMA_InitStructure.DMA_Trigger = DMA_Trigger_Disable;
    DMA_InitStructure.DMA_Major_Iteration_Count = DMABufLen;
    DMA_InitStructure.DMA_Minor_loop_Length = 1;
    DMA_InitStructure.DMA_Source_Addr = (U32)(&(SPI_POPR_REG(SPI1)));
    DMA_InitStructure.DMA_Source_Size = DMA_SRC_8BIT;
    DMA_InitStructure.DMA_Source_Addr_inc = 0;
    DMA_InitStructure.DMA_Source_Adj_Addr = 0;
    DMA_InitStructure.DMA_Dest_Addr = (U32)DMABuf;
    DMA_InitStructure.DMA_Dest_Size = DMA_DST_8BIT;
    DMA_InitStructure.DMA_Dest_Addr_inc = 1;
    DMA_InitStructure.DMA_Dest_Adj_Addr = (U32)(-DMABufLen);
    DMA_InitStructure.DMA_AutoClose = DMA_AutoClose_NOT;
   
    DMA_Init(&DMA_InitStructure);
    //DMA_ReqCmd(DMA_CH3, ENABLE);
    //USART_DMARxCmd(pUartBase, ENABLE);
    SPI_RSER_REG(SPI1_BASE_PTR) |= SPI_RSER_RFDF_RE_MASK | SPI_RSER_RFDF_DIRS_MASK;// | SPI_RSER_TFFF_RE_MASK | SPI_RSER_TFFF_DIRS_MASK;
   
    return SUCCESS;
}

INT STDCALL SFlashDrvReadBytes(UINT uAddr, PVOID pBuf, INT uRdSize)
{
    UINT uRdNum;
    UINT uRdRemainNum;
    UINT uSFlashAddr;
PBYTE pRdBuf = pBuf;
//U32 u32DummyData = SFCMD_DUMMY;

    uRdNum = 0;
    uSFlashAddr = uAddr - SFLASH_ADDR_BEGIN;
    uRdNum = uRdSize>>2UL;
    uRdRemainNum = uRdSize & 0x3;
    //ENTER_HW_IRQL_PRTCT   
//DMA_ReqCmd(DISABLE);
        _SFlashCSLow();
        _SFlashSendByte(SFCMD_READ_50MHZ);
        //发送地址,24位地址,发送3次,STM32F10X的SPI 8位数据帧格式发送的是低8位数据
        _SFlashSendByte((uSFlashAddr & 0xFF0000)>>16UL);
        _SFlashSendByte((uSFlashAddr & 0xFF00)>>8UL);
        _SFlashSendByte(uSFlashAddr & 0xFF);
        //接收数据
        ClearRecvData();       
    //设置数据长度,长度每次递减。也可以称为 当前主循环计数器 current major loop count
  DMA_BASE_PTR->TCD[DMA_CH3].CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(uRdSize);
  //起始循环计数器,当主循环计数器为零的时候,将装载起始循环计数器的值
  DMA_BASE_PTR->TCD[DMA_CH3].BITER_ELINKNO = DMA_CITER_ELINKNO_CITER(uRdSize);

  DMA_BASE_PTR->TCD[DMA_CH3].DLAST_SGA = (U32)(-uRdSize);
  DMA_ReqCmd(DMA_CH3, ENABLE);
  //u32DummyData |= (SPI_PUSHR_REG(SFLASH_SPI)  & 0xffff0000);
  #define _DMA_SPI_
  #ifndef _DMA_SPI_
        for(; uRdNum != 0; uRdNum--)
        {
            //((PBYTE)pBuf)[uRdNum++] = _SFlashSendByte(SFCMD_DUMMY);
   //
   _SFlashSendData(SFLASH_SPI, SPI_PUSHR_REG(SFLASH_SPI));
   _SFlashWaitSend();
   //*pRdBuf++ = _SFlashReciveData(SFLASH_SPI);
           
            _SFlashSendData(SFLASH_SPI, SPI_PUSHR_REG(SFLASH_SPI));
   _SFlashWaitSend();
   //*pRdBuf++ = _SFlashReciveData(SFLASH_SPI);
           
            _SFlashSendData(SFLASH_SPI, SPI_PUSHR_REG(SFLASH_SPI));
   _SFlashWaitSend();
   //*pRdBuf++ = _SFlashReciveData(SFLASH_SPI);
           
            _SFlashSendData(SFLASH_SPI, SPI_PUSHR_REG(SFLASH_SPI));
   _SFlashWaitSend();
   //*pRdBuf++ = _SFlashReciveData(SFLASH_SPI);
        }
        for(; uRdRemainNum != 0; uRdRemainNum--)
        {
            _SFlashSendData(SFLASH_SPI, SPI_PUSHR_REG(SFLASH_SPI));
   _SFlashWaitSend();
   //*pRdBuf++ = _SFlashReciveData(SFLASH_SPI);
        }
    extern U8 szSPIBuf[];

    memcpy(pRdBuf, szSPIBuf, uRdSize);

  //   SPI_MCR_REG(SPI1) |= SPI_MCR_CONT_SCKE_MASK;

  //for(uRdRemainNum = uRdSize; uRdRemainNum > 0; uRdRemainNum--)
  //{
  // //while((SFLASH_SPI->SR & SPI_FLAG_TCF) == 0)
  // //{
  // //}
  // //SFLASH_SPI->SR |= SPI_FLAG_TCF;
  // *pRdBuf++ = _SFlashReciveData(SFLASH_SPI);
  //}
  //  SPI_MCR_REG(SPI1) &= ~SPI_MCR_CONT_SCKE_MASK;

  #else
  SPI_MCR_REG(SPI1) |= SPI_MCR_CONT_SCKE_MASK;
  while((DMA_TCD3_CSR & 0x80) == 0);
  SPI_MCR_REG(SPI1) &= ~SPI_MCR_CONT_SCKE_MASK;

  extern U8 szSPIBuf[];
  //uRdSize = (uRdSize >= DMA_CITER_ELINKNO_CITER(DMA_BASE_PTR->TCD[DMA_CH3].CITER_ELINKNO)) ? DMA_CITER_ELINKNO_CITER(DMA_BASE_PTR->TCD[DMA_CH3].CITER_ELINKNO) : uRdSize;
  memcpy(pRdBuf, szSPIBuf, uRdSize);
  DMA_TCD3_CSR |= 0x10;
  #endif
        //拉高SFlash的CS
        _SFlashCSHigh();
DMA_ReqCmd(DMA_CH3, DISABLE);

    //EXIT_HW_IRQL_PRTCT

    return uRdSize;
}

For picture:
Green: SCK
Blue: MISO
Purple: MISO
Yellow: CS

SPI连续时钟波形(绿色时钟,蓝色接收数据,紫色发送数据,黄色片选).PNG

Labels (1)
Tags (1)
4 Replies

850 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Yanrong Fu,

I'd like to suggest that you can refer to a practical experiment document about the SPI integrate with DMA throught the link as below.

If you have any further questions about it, please feel free to contact with me.

使用DMA降低SPI通信过程中内核负荷 Reduce core work load with DMA Module during SPI communication
Have a great day,

Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

850 Views
fredfu
NXP Employee
NXP Employee

Hi Ping,

    Thanks you for your infromation.But my problem is difference with the ref., my customer use DSPI1, DSPI1 has only one DMA request source number for Transmit or Receive, I can't use one DMA channel for transmitting and another DMA channel for receiving.

Capture.PNG

  

Best Regards,

Fred Fu

0 Kudos
Reply

850 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Yanrong Fu,

As you mentioned at first, the MCU could received the data from external flash correctly through the DMA while the SPI was sending the dummy data.

Follow to this method, did it not work with K21?
Have a great day,

Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply

849 Views
fredfu
NXP Employee
NXP Employee


Hi Ping,

    It is now being used in ways, because  DSPI can't use DMA to transmit when DAM for receiving, the efficiency is low. Now they want to improve the efficiency, they enable CONT_SCKE to generate clk for flash(you can see the source code),then DMA for receiving, but DMA can't get any data, I want to know if K21F can support the way. Thanks.

Best Regards,

Fred Fu

0 Kudos
Reply