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.

cppi41_dma.c 如何取得USB BULK OUT 資料

Expert 2272 points


請問...

SDK6 Kernel 3.2

我想要取得主存內的usb bulk out 資料  在"usb_process_rx_bd" ?? (cppi41_dma.c )

我可以透過USB FIFO方式得到BULK OUT 資料,但讀取FIFO後會引發後續資料有問題

請問應該要怎麼寫才可以在usb_process_rx_bd 內取得BULK OUT資料???

 

下列可以透過FIFO方式取得資料,但下一次PC BULK OUT會有其他問題

if(rx_ch->channel.actual_len==64){ 
for(i=0;i<2;i++){
data[i]=readl(rx_ch->end_pt->ep_out.hw_ep->fifo);

printk("data[%d]=%08x\r\n",i,data[i]);
}
tmc_bulkout_len=data[1]+12;
}

下列方式取得資料都是0,或是資料不正確

for(i=0;i<512;i++){
data[i]=cppi_readl(rx_ch->queue_obj.base_addr+(i*4));
printk("data[%d]=%08x\r\n",i,data[i]);
}

for(i=0;i<512;i++){
data[i]=cppi_readl(rx_ch->dma_ch_obj.base_addr+(i*4));
printk("data[%d]=%08x\r\n",i,data[i]);
}

 

 

 

static void usb_process_rx_bd(struct cppi41 *cppi,
struct usb_pkt_desc *curr_pd)
{
static u8 read_debug=0;
static u16 tmc_bulkout_len=0;
u8 en_bd_intr = cppi->en_bd_intr;
struct cppi41_channel *rx_ch;
u8 ch_num, ep_num;
struct musb *musb = cppi->musb;
u32 length = 0, orig_buf_len;
u8 sched_tbl_ctrl = cppi->cppi_info->sched_tbl_ctrl;
u32 data[512];
u32 *u32ptr;
u16 i;

/* Extract the data from received packet descriptor */
length = curr_pd->hw_desc.desc_info & CPPI41_PKT_LEN_MASK;
ch_num = curr_pd->ch_num;
ep_num = curr_pd->ep_num;

/* the cppi41 dma will set received byte length as 1 when
* zero length packet is received, fix this dummy byte by
* setting acutal length received as zero
*/
////printk("jjjRx complete: dma channel(%d) ep%d len %d\n",ch_num, ep_num, length);


if (curr_pd->hw_desc.pkt_info & CPPI41_ZLP){
length = 0;
////printk("ZLP\r\n");

}

rx_ch = &cppi->rx_cppi_ch[ch_num];
dev_dbg(musb->controller, "Rx complete: dma channel(%d) ep%d len %d\n",
ch_num, ep_num, length);

rx_ch->channel.actual_len += length;


if (curr_pd->eop) {
curr_pd->eop = 0;

printk("curr_pd->eop\r\n");
/* disable the rx dma schedular */
if (sched_tbl_ctrl && is_peripheral_active(cppi->musb) &&
!cppi->cppi_info->rx_inf_mode)
cppi41_schedtbl_remove_dma_ch(0, 0,
cppi->cppi_info->ep_dma_ch[ch_num], 0);
}

/*
* Return Rx PD to the software list --
* this is protected by critical section
*/
usb_put_free_pd(cppi, curr_pd);

orig_buf_len = curr_pd->hw_desc.orig_buf_len;
if (en_bd_intr)
orig_buf_len &= ~CPPI41_PKT_INTR_FLAG;

dev_dbg(musb->controller,
"curr_pd=%p, len=%d, origlen=%d,rxch(alen/len)=%d/%d\n",
curr_pd, length, orig_buf_len,
rx_ch->channel.actual_len, rx_ch->length);

#if 0 
printk("length = %d rx_ch->channel.actual_len=%d rx_ch->length=%d orig_buf_len=%d rx_ch->curr_offset=%d\n",length,rx_ch->channel.actual_len,rx_ch->length,orig_buf_len,rx_ch->curr_offset);

#endif

if (rx_ch->channel.actual_len/*832*/ >= rx_ch->length/*2060*/ ||
length/*60 or 64*/ < orig_buf_len/*64*/) {

#if defined(CONFIG_SOC_OMAPTI81XX) || defined(CONFIG_SOC_OMAPAM33XX)
struct musb_hw_ep *ep;
u8 isoc, next_seg = 0;

/* Workaround for early rx completion of
* cppi41 dma in Generic RNDIS mode for ti81xx
*/
if (is_host_enabled(cppi->musb) && !rx_ch->channel.completed) {
u32 pkt_size = rx_ch->pkt_size;
ep = cppi->musb->endpoints + ep_num;
isoc = musb_readb(ep->regs, MUSB_RXTYPE);
isoc = (isoc >> 4) & 0x1;

if (!isoc
&& (rx_ch->dma_mode == USB_GENERIC_RNDIS_MODE)
&& (rx_ch->channel.actual_len < rx_ch->length)
&& !(rx_ch->transfer_mode)
&& !(rx_ch->channel.actual_len % pkt_size))
next_seg = 1;
}
if (next_seg) {
rx_ch->curr_offset = rx_ch->channel.actual_len;
cppi41_next_rx_segment(rx_ch);
} else
#endif
{
rx_ch->channel.status = MUSB_DMA_STATUS_FREE;
rx_ch->channel.completed = 1;

if (rx_ch->inf_mode) {
cppi41_rx_ch_set_maxbufcnt(
&rx_ch->dma_ch_obj, 0);
rx_ch->inf_mode = 0;
}

/* Rx completion routine callback */
musb_dma_completion(cppi->musb, ep_num, 0);
#if 1 
musb_writew(rx_ch->end_pt->regs, MUSB_RXCSR, MUSB_RXCSR_FLUSHFIFO /*| MUSB_RXCSR_CLRDATATOG*/);
printk("jjj musb_dma_completion\r\n");

#endif
}
} else {
if ((rx_ch->length - rx_ch->curr_offset) > 0){


#if 1 
//// printk("xxx rx_ch->length=%d rx_ch->curr_offset=%d rx_ch->channel.actual_len=%d\r\n",rx_ch->length,rx_ch->curr_offset,rx_ch->channel.actual_len);

if(rx_ch->channel.actual_len==64){ 
for(i=0;i<2;i++){
data[i]=readl(rx_ch->end_pt->ep_out.hw_ep->fifo);

printk("data[%d]=%08x\r\n",i,data[i]);
}
tmc_bulkout_len=data[1]+12;
}


#if 1 
printk("rx_ch->start_addr + rx_ch->curr_offset=%08x\r\n",rx_ch->start_addr + rx_ch->curr_offset);
for(i=0;i<2;i++){
data[i]=cppi_readl(rx_ch->start_addr + rx_ch->curr_offset);
printk("Xdata[%d]=%08x\r\n",i,data[i]);
}
#endif


#if 0


for(i=0;i<512;i++){
data[i]=cppi_readl(rx_ch->queue_obj.base_addr+(i*4));
printk("data[%d]=%08x\r\n",i,data[i]);
}

for(i=0;i<512;i++){
data[i]=cppi_readl(rx_ch->dma_ch_obj.base_addr+(i*4));
printk("data[%d]=%08x\r\n",i,data[i]);
}


#endif
#if 0
printk("-----------------------------------\r\n");
u32ptr=curr_pd->hw_desc.buf_ptr;
printk("u32ptr=%p\r\n",u32ptr);

u32 io_base;
io_base = (volatile u32 *)ioremap (curr_pd->hw_desc.buf_ptr, 64);

data[0]=*((volatile u32 *)(io_base));
printk("data[0]=%08x\r\n",data[0]);

#endif


//printk("rx_ch->end_pt.epnum=%d rx_ch->end_pt->fifo=%p data[0]=%08x data[1]=%08x\r\n",rx_ch->end_pt->epnum,rx_ch->end_pt->fifo,data[0],data[1]);

if(rx_ch->channel.actual_len>tmc_bulkout_len)
{
rx_ch->channel.status = MUSB_DMA_STATUS_FREE;
rx_ch->channel.completed = 1;

if (rx_ch->inf_mode) {
cppi41_rx_ch_set_maxbufcnt(&rx_ch->dma_ch_obj, 0);
rx_ch->inf_mode = 0;
}

/* Rx completion routine callback */
musb_dma_completion(cppi->musb, ep_num, 0);
printk("kkk musb_dma_completion rx_ch->channel.actual_len=%d > tmc_bulkout_len=%d \r\n",rx_ch->channel.actual_len,tmc_bulkout_len);
musb_writew(rx_ch->end_pt->regs, MUSB_RXCSR, MUSB_RXCSR_FLUSHFIFO /*| MUSB_RXCSR_CLRDATATOG*/);
}
else{
cppi41_next_rx_segment(rx_ch);
}

#else
cppi41_next_rx_segment(rx_ch);

#endif

}
}
}

..

  • AM335x的USB CORE的寄存器自交需要签署NDA才能获得。

  • 请联系当地的TI销售或者代理商签订NDA。

  • 謝謝您的回復,我並不是這個意思

    我是問...

    如果PC 送出64byte的資料到AM335X USB裝置(Peripheral+ Transparent DMA Mode)

    我要怎麼取得這 64BYTE的資料,在cppi41_dma kernel driver ?

    因為PC在送出 64BYTE資料後,無送出ZLP 包, 所以我 無法從gadget層取得64BYTE資料


    我有追蹤了相關流程,當PC BULK OUT 64BYTE資料時, CPPI41 DMA DRIVER會運行下列流程

    cppi41dma_Interrupt => cppi41_completion => usb_process_rx_queue => usb_process_rx_bd...


    但我透過下列方法,皆無法取得那64BYTE資料

    data[i]=cppi_readl(rx_ch->queue_obj.base_addr+(i*4));
    printk("data[%d]=%08x\r\n",i,data[i]);

    io_base = (volatile u32 *)ioremap (curr_pd->hw_desc.buf_ptr, 64);
    data[0]=*((volatile u32 *)(io_base));
    printk("data[0]=%08x\r\n",data[0]);

    附上CPPI41 DMA STRUCT 
    /**
    * struct cppi41_channel - DMA Channel Control Structure
    *
    * Using the same for Tx/Rx.
    */
    struct cppi41_channel {
    struct dma_channel channel;

    struct cppi41_dma_ch_obj dma_ch_obj; /* DMA channel object */
    struct cppi41_queue src_queue; /* Tx queue or Rx free descriptor/ */
    /* buffer queue */
    struct cppi41_queue_obj queue_obj; /* Tx queue object or Rx free */
    /* descriptor/buffer queue object */

    u32 tag_info; /* Tx PD Tag Information field */

    /* Which direction of which endpoint? */
    struct musb_hw_ep *end_pt;
    u8 transmit;
    u8 ch_num; /* Channel number of Tx/Rx 0..3 */

    /* DMA mode: "transparent", RNDIS, CDC, or Generic RNDIS */
    u8 dma_mode;
    u8 autoreq;

    /* Book keeping for the current transfer request */
    dma_addr_t start_addr;
    u32 length;
    u32 curr_offset;
    u16 pkt_size;
    u8 transfer_mode;
    u8 zlp_queued;
    u8 inf_mode;
    u8 tx_complete;
    u8 rx_complete;
    u8 hb_mult;
    u8 txdma_intr_first;
    u8 txfifo_intr_enable;
    u8 count;
    u8 txfifo_intr_first;
    u8 xfer_state;
    struct usb_pkt_desc *curr_pd;
    };