請問…
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
}
}
}
..
Jian Zhou:
AM335x的USB CORE的寄存器自交需要签署NDA才能获得。
Shine:
回复 Jian Zhou:
请联系当地的TI销售或者代理商签订NDA。
jiew:
回复 Jian Zhou:
謝謝您的回復,我並不是這個意思
我是問…
如果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;};