SAMV71 XPlained Ultra -- QSPI MEMORY MODE -- DMA

dujiarui_001's picture
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Compiler/Assembler: 

您好:

     我使用 ATMEL STUDIO 7,SAMV71 XPlained Ultra 评估板。使用 QUARD SPI memory mode,发现用复制语句可以产生 QSPI 波形,但是用 DMA 操作(从内部 SRAM 向目标地址 0x80000000 开始的内存块复制32个字  )无法产生 QSPI 波形。

    QUARD SPI memory mode 可以使用 DMA 吗?该如何设置?

static void configure_qspi(void)
{
 struct qspi_config_t qspi_config ;
 
 qspi_config.serial_memory_mode = 1; // QSPI_MR. qspi memory mode
 qspi_config.loopback_en = false; // QSPI_MR.
 qspi_config.wait_data_for_transfer = false; // QSPI_MR. 
 qspi_config.csmode = 1;    // QSPI_MR. CS -- LASTXFER
 qspi_config.bits_per_transfer = QSPI_MR_NBBITS_8_BIT; // QSPI_MR.
 qspi_config.min_delay_qcs = 0;  // QSPI_MR. DLYCS = 0 : delay between the deactivation and the activation of QCS 
 qspi_config.delay_between_ct = 0; // QSPI_MR. DLYBCT = 0 : delay between two consecutive transfers
 qspi_config.clock_polarity = 1;  // QSPI_SCR. Figure 39-2
 qspi_config.clock_phase = 1;  // QSPI_SCR. Figure 39-2
 qspi_config.baudrate = 1000000;  // QSPI_SCR. 
 qspi_config.transfer_delay = 0x40; // QSPI_SCR. delay from QCS valid to the first valid QSCK transition 
 qspi_config.scrambling_en = false; // QSPI_SMR
 qspi_config.scrambling_random_value_dis = false; // 
 qspi_config.scrambling_user_key = 0; // QSPI_SKR

 sysclk_enable_peripheral_clock(ID_QSPI);
 qspi_initialize(QSPI,&qspi_config) ;
 
 if (1)
 {
  uint32_t mask = 0 ;
  mask |= ( QSPI_IFR_WIDTH_QUAD_CMD | QSPI_IFR_DATAEN | QSPI_IFR_TFRTYP_TRSFR_WRITE ) ;
  // QSPI_IFR_INSTEN, QSPI_IFR_ADDREN, QSPI_IFR_OPTEN, OPTL, ADDRL, CRM, NBDUM 均为 0。

  QSPI->QSPI_IFR = mask;
 }
 
 printf("QSPI Init OK!\r\n") ;
}

void config_xdmac (void)
{
 /* Initialize and enable DMA controller */
 pmc_enable_periph_clk(ID_XDMAC);

 /*Enable XDMA interrupt */
 NVIC_ClearPendingIRQ(XDMAC_IRQn);
 NVIC_SetPriority( XDMAC_IRQn ,1);
 NVIC_EnableIRQ(XDMAC_IRQn);
}


#pragma GCC push_options
#pragma GCC optimize("O0")
void xdmac_transfer (uint32_t xdma_channel, uint32_t* pSrc, uint32_t* pDst, uint32_t sizeW)
{
 xdmac_channel_disable(XDMAC, xdma_channel);
 
 // Initialize channel config
 xdmac_channel_cfg.mbr_ubc = sizeW ; 
 xdmac_channel_cfg.mbr_sa = (uint32_t)pSrc;
 xdmac_channel_cfg.mbr_da = (uint32_t)pDst;
 
 xdmac_channel_cfg.mbr_cfg = XDMAC_CC_TYPE_MEM_TRAN | // 0<<0
 XDMAC_CC_MEMSET_NORMAL_MODE |      // 0<<7
 XDMAC_CC_MBSIZE_SINGLE |       // 0<<1
 XDMAC_CC_DWIDTH_WORD |        // 0<<11
 XDMAC_CC_SIF_AHB_IF0 |        // 0<<13
 XDMAC_CC_DIF_AHB_IF0 |        // 0<<14
 XDMAC_CC_SAM_INCREMENTED_AM |      // 1<<16
 XDMAC_CC_DAM_INCREMENTED_AM;      // 1<<18
 xdmac_channel_cfg.mbr_bc = BLOCK_LEN - 1;    // 15
 xdmac_channel_cfg.mbr_ds =  0;
 xdmac_channel_cfg.mbr_sus = 0;
 xdmac_channel_cfg.mbr_dus = 0;

 xdmac_configure_transfer(XDMAC, xdma_channel, &xdmac_channel_cfg);

 // Initialize linked list descriptor
 lld[0].mbr_nda = 0 ;//(uint32_t)(&lld[1]);
 
 lld[0].mbr_ubc = XDMAC_UBC_NVIEW_NDV0 |     // 0x0u << XDMAC_UBC_NVIEW_Pos
 XDMAC_UBC_NDE_FETCH_EN |      // 1<<24
 XDMAC_UBC_NSEN_UPDATED |      // 1<<25
 XDMAC_UBC_NDEN_UPDATED |      // 1<<26
 XDMAC_UBC_UBLEN(sizeW);    // (XDMAC_UBC_UBLEN_Msk & ((value) << XDMAC_UBC_UBLEN_Pos))
 lld[0].mbr_da = (uint32_t)pDst;

 xdmac_channel_set_descriptor_control(XDMAC, xdma_channel, XDMAC_CNDC_NDVIEW_NDV0 | // 0<<3
 XDMAC_CNDC_NDE_DSCR_FETCH_EN |           // 1<<0
 XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED |         // 1<<1
 XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED);         // 1<<2
 xdmac_channel_set_descriptor_addr(XDMAC, xdma_channel, (uint32_t)(&lld[0]), 0);

 xdmac_enable_interrupt(XDMAC, xdma_channel);
 xdmac_channel_enable_interrupt(XDMAC, xdma_channel, XDMAC_CIE_BIE);
 xdmac_channel_enable(XDMAC, xdma_channel);
}
#pragma GCC pop_options

/**
 * \brief XDMAC interrupt handler.
 */
void XDMAC_Handler(void)
{
 volatile uint32_t dma_status;

 dma_status = xdmac_channel_get_interrupt_status(XDMAC, XDMA_MEM_CH);

 if (dma_status & XDMAC_CIS_LIS) // XDMAC_CIS_BIS 
 {
  g_xfer_done = 1;
 }
 
 dma_status = xdmac_channel_get_interrupt_status(XDMAC, XDMA_QSPI_CH);
 if (dma_status & XDMAC_CIS_LIS) // XDMAC_CIS_BIS
 {
  g_xdma_qspi_done = 1;
 }
 
 dmaint_num++;
}

int main (void)
{
// Initialize the SAM system. 
 sysclk_init();
 board_init();

 // Configure debug UART 
 configure_console();

 // Print example information. 
 puts(STRING_HEADER);
 
 // check reset source
 check_rst() ;

 // Bring up the ethernet interface & initialize timer0, channel0. 
 init_ethernet();

 // Bring up the web server. 
 httpd_init();
 
 //action_test() ; 
 
 configure_qspi() ;
 
 config_xdmac() ;config_xdmac() ;

xdmac_transfer(XDMA_MEM_CH, src_buf, (uint32_t *)QSPIMEM_ADDR, 32) ;
   while (!g_xfer_done)
   {
   }
}