This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Mcasp can't transfer data when hard disk or nand flash write and read data

Dear all:

    Mcasp transfer data by EDMA  in ARM.  In the begining , the mcasp  can transfer data. When the hard disk or nand flash read and write large block data by multithreading, the  tx can't tansfer  data  but  rx can receive data. Otherwise, the TXEVT is normal.

   Moreover,Mcasp can't transfer data when syslink.ko is loaded or engine_open()  is called.

   The EDMA is ping-pong structure  and  interrupt period is 4 ms.

   Following  is  that EDMA request configuration:

   static int ys_tdm_dma_request(int id, int buf_size, int tx_channel, int rx_channel, int fifo_address)  {

    //init tx
    tx_dma_params_arry[id]->area = dma_alloc_writecombine(NULL, buf_size, &tx_dma_params_arry[id]->addr, GFP_KERNEL);
    tx_dma_params_arry[id]->ping_size = buf_size >> 1;
    tx_dma_params_arry[id]->asp_channel = edma_alloc_channel(tx_channel, NULL, NULL,EVENTQ_DEFAULT);  
    tx_dma_params_arry[id]->slot_link[0] = edma_alloc_slot(EDMA_CTLR(tx_dma_params_arry[id]->asp_channel), EDMA_SLOT_ANY);
    tx_dma_params_arry[id]->slot_link[1] = edma_alloc_slot(EDMA_CTLR(tx_dma_params_arry[id]->asp_channel), EDMA_SLOT_ANY);
    edma_link(tx_dma_params_arry[id]->slot_link[0], tx_dma_params_arry[id]->slot_link[1]);
    edma_link(tx_dma_params_arry[id]->slot_link[1], tx_dma_params_arry[id]->slot_link[0]);
    edma_read_slot(tx_dma_params_arry[id]->slot_link[0], &p_ram);
    p_ram.opt |= EDMA_TCC(EDMA_CHAN_SLOT(tx_dma_params_arry[id]->asp_channel));
    edma_write_slot(tx_dma_params_arry[id]->slot_link[0], &p_ram);
    edma_read_slot(tx_dma_params_arry[id]->slot_link[1], &p_ram);
    p_ram.opt |= EDMA_TCC(EDMA_CHAN_SLOT(tx_dma_params_arry[id]->asp_channel));
    edma_write_slot(tx_dma_params_arry[id]->slot_link[1], &p_ram);

    //init rx
    rx_dma_params_arry[id]->area = dma_alloc_writecombine(NULL, buf_size, &rx_dma_params_arry[id]->addr, GFP_KERNEL);
    rx_dma_params_arry[id]->ping_size = buf_size >> 1;
    if(id == YSTDM_PRI_ID)
        rx_dma_params_arry[id]->asp_channel = edma_alloc_channel(rx_channel, ys_tdm_dma_irq_pri,NULL, EVENTQ_DEFAULT); //分配channel,RX的channel
    else if(id == YSTDM_FX_ID)  
        rx_dma_params_arry[id]->asp_channel = edma_alloc_channel(rx_channel, ys_tdm_dma_irq_fx ,NULL, EVENTQ_DEFAULT); //分配channel,RX的channel
    rx_dma_params_arry[id]->slot_link[0] = edma_alloc_slot(EDMA_CTLR(rx_dma_params_arry[id]->asp_channel), EDMA_SLOT_ANY);
    rx_dma_params_arry[id]->slot_link[1] = edma_alloc_slot( EDMA_CTLR(rx_dma_params_arry[id]->asp_channel), EDMA_SLOT_ANY);
    /** circle ping-pong buffers */
    edma_link(rx_dma_params_arry[id]->slot_link[0], rx_dma_params_arry[id]->slot_link[1]);
    edma_link(rx_dma_params_arry[id]->slot_link[1], rx_dma_params_arry[id]->slot_link[0]);
    edma_read_slot(rx_dma_params_arry[id]->slot_link[0], &p_ram);
    p_ram.opt |= TCINTEN | EDMA_TCC(EDMA_CHAN_SLOT(rx_dma_params_arry[id]->asp_channel));
    edma_write_slot(rx_dma_params_arry[id]->slot_link[0], &p_ram);
    edma_read_slot(rx_dma_params_arry[id]->slot_link[1], &p_ram);
    p_ram.opt |= TCINTEN | EDMA_TCC(EDMA_CHAN_SLOT(rx_dma_params_arry[id]->asp_channel));
    edma_write_slot(rx_dma_params_arry[id]->slot_link[1], &p_ram);
    return 0;
}

  • Is the nand/hard drive block data transfers using EDMA?  If so, are they using the same queue as the McASP.  If that is the case, you should move those requests to a different EDMA queue.

    For background: The EDMA services requests on a given queue (which maps to a given TC) in order.  Thus, if a queue is servicing requests with a (relatively) short real time deadline (like McASP), you should avoid using the same queue for other purposes, especially for long transfers, or for transfers to slow peripherals. 

    Regards
    Kyle