在調(diào)試ch374過程中發(fā)現(xiàn)了數(shù)據(jù)丟失的現(xiàn)象
測(cè)試程序的功能是,從pc接到的數(shù)據(jù)再回傳到pc,最終發(fā)現(xiàn),單片機(jī)側(cè)能夠?qū)?shù)據(jù)完整的 收下,但是回傳到pc端,丟失了大量數(shù)據(jù),原數(shù)據(jù)360K,實(shí)際回傳只有300k左右,驅(qū)動(dòng)實(shí)現(xiàn)在linux系統(tǒng)上,具體實(shí)現(xiàn)就是中斷中接收到數(shù)據(jù)后放入 一個(gè)fifo,當(dāng)應(yīng)用層調(diào)用讀取后,將數(shù)據(jù)從fifo中取出返還到應(yīng)用層,寫操作是應(yīng)用層將數(shù)據(jù)寫入驅(qū)動(dòng)層的發(fā)送fifo中,當(dāng)收到IN中斷后,將數(shù)據(jù)從 fifo中寫入ch374中,所謂中斷處理,實(shí)際上使用了中斷的下文工作隊(duì)列,關(guān)鍵代碼如下:
判斷是傳輸中斷后的處理,
?? ??? ?switch(s & BIT_STAT_PID_ENDP){
?? ??? ?case USB_INT_EP2_OUT: {? // 批量端點(diǎn)下傳成功
?? ??? ??? ?if ( s & BIT_STAT_TOG_MATCH )
?? ??? ??? ?{
?? ??? ??? ??? ?ch374_usb_bulk_rcv();
?? ??? ??? ??? ?ch374_wr_reg( REG_USB_ENDP2, M_SET_EP2_TRAN_ACK( ch374_rd_reg( REG_USB_ENDP2 ) ) ^ BIT_EP2_RECV_TOG );
?? ??? ??? ?}
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?case USB_INT_EP2_IN: {? // 批量端點(diǎn)上傳成功,未處理
?? ??? ??? ?if(kfifo_is_empty(&ch374_dev.wr_fifo) != 0)
?? ??? ??? ?{
?? ??? ??? ??? ?ch374_dev.tx_flag = 0;
?? ??? ??? ??? ?break;
?? ??? ??? ?}
?? ??? ??? ?kfifo_out(&ch374_dev.wr_fifo, &fifo_node, sizeof(Fifo_node_t));
?? ??? ??? ?ch374_wr_block( RAM_ENDP2_TRAN, fifo_node.len, fifo_node.buf );
?? ??? ??? ?ch374_wr_reg( REG_USB_LENGTH, fifo_node.len );
?? ??? ??? ?ch374_wr_reg( REG_USB_ENDP2, M_SET_EP2_TRAN_ACK( ch374_rd_reg( REG_USB_ENDP2 ) ) ^ BIT_EP2_TRAN_TOG );
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?case USB_INT_EP1_IN: {? // 中斷端點(diǎn)上傳成功,未處理
?? ??? ??? ?ch374_wr_reg( REG_USB_ENDP1, M_SET_EP1_TRAN_NAK( ch374_rd_reg( REG_USB_ENDP1 ) ) ^ BIT_EP1_TRAN_TOG );
?? ??? ??? ?//printk("******USB_INT_EP1_IN\n");
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?case USB_INT_EP0_SETUP: {? // 控制傳輸
?? ??? ??? ?//printk("USB_INT_EP0_SETUP\r\n");
?? ??? ??? ?USB_SETUP_REQ?? ?SetupReqBuf;
?? ??? ??? ?l = ch374_rd_reg( REG_USB_LENGTH );
?? ??? ??? ?if ( l == sizeof( USB_SETUP_REQ ) ) {
?? ??? ??? ??? ?ch374_rd_block( RAM_ENDP0_RECV, l, (u8 *)&SetupReqBuf );
?? ??? ??? ??? ?SetupLen = SetupReqBuf.wLengthL;
?? ??? ??? ??? ?if ( SetupReqBuf.wLengthH || SetupLen > 0x7F ) SetupLen = 0x7F;? // 限制總長(zhǎng)度
?? ??? ??? ??? ?l = 0;? // 默認(rèn)為成功并且上傳0長(zhǎng)度
?? ??? ??? ??? ?if ( ( SetupReqBuf.bType & DEF_USB_REQ_TYPE ) != DEF_USB_REQ_STAND ) {? /* 只支持標(biāo)準(zhǔn)請(qǐng)求 */
?? ??? ??? ??? ??? ?l = 0xFF;? // 操作失敗
?? ??? ??? ??? ?}
?? ??? ??? ??? ?else {? // 標(biāo)準(zhǔn)請(qǐng)求
?? ??? ??? ??? ??? ?SetupReq = SetupReqBuf.bReq;? // 請(qǐng)求碼
?? ??? ??? ??? ??? ?switch( SetupReq ) {
?? ??? ??? ??? ??? ??? ?case DEF_USB_GET_DESCR:
?? ??? ??? ??? ??? ??? ??? ?switch( SetupReqBuf.wValueH ) {
?? ??? ??? ??? ??? ??? ??? ??? ?case 1:
?? ??? ??? ??? ??? ??? ??? ??? ??? ?pDescr = (u8 *)( &MyDevDescr[0] );
?? ??? ??? ??? ??? ??? ??? ??? ??? ?l = sizeof( MyDevDescr );
?? ??? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ??? ??? ?case 2:
?? ??? ??? ??? ??? ??? ??? ??? ??? ?pDescr = (u8 *)( &MyCfgDescr[0] );
?? ??? ??? ??? ??? ??? ??? ??? ??? ?l = sizeof( MyCfgDescr );
?? ??? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ??? ??? ?case 3:
?? ??? ??? ??? ??? ??? ??? ??? ??? ?switch( SetupReqBuf.wValueL ) {
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?case 1:
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?pDescr = (u8 *)( &MyManuInfo[0] );
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?l = sizeof( MyManuInfo );
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?case 2:
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?pDescr = (u8 *)( &MyProdInfo[0] );
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?l = sizeof( MyProdInfo );
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?case 0:
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?pDescr = (u8 *)( &MyLangDescr[0] );
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?l = sizeof( MyLangDescr );
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?default:
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?l = 0xFF;? // 操作失敗
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ??? ??? ?default:
?? ??? ??? ??? ??? ??? ??? ??? ??? ?l = 0xFF;? // 操作失敗
?? ??? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ??? ?if ( SetupLen > l ) SetupLen = l;? // 限制總長(zhǎng)度
?? ??? ??? ??? ??? ??? ??? ?l = SetupLen >= RAM_ENDP0_SIZE ? RAM_ENDP0_SIZE : SetupLen;? // 本次傳輸長(zhǎng)度
?? ??? ??? ??? ??? ??? ??? ?ch374_wr_block( RAM_ENDP0_TRAN, l, pDescr );? /* 加載上傳數(shù)據(jù) */
?? ??? ??? ??? ??? ??? ??? ?SetupLen -= l;
?? ??? ??? ??? ??? ??? ??? ?pDescr += l;
?? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ?case DEF_USB_SET_ADDRESS:
?? ??? ??? ??? ??? ??? ??? ?SetupLen = SetupReqBuf.wValueL;? // 暫存USB設(shè)備地址
?? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ?case DEF_USB_GET_CONFIG:
?? ??? ??? ??? ??? ??? ??? ?ch374_wr_reg( RAM_ENDP0_TRAN, UsbConfig );
?? ??? ??? ??? ??? ??? ??? ?if ( SetupLen >= 1 ) l = 1;
?? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ?case DEF_USB_SET_CONFIG:
?? ??? ??? ??? ??? ??? ??? ?UsbConfig = SetupReqBuf.wValueL;
?? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ?case DEF_USB_CLR_FEATURE:
?? ??? ??? ??? ??? ??? ??? ?if ( ( SetupReqBuf.bType & 0x1F ) == 0x02 ) {? // 不是端點(diǎn)不支持
?? ??? ??? ??? ??? ??? ??? ??? ?switch( SetupReqBuf.wIndexL ) {
?? ??? ??? ??? ??? ??? ??? ??? ??? ?case 0x82:
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?ch374_wr_reg( REG_USB_ENDP2, M_SET_EP2_TRAN_NAK( ch374_rd_reg( REG_USB_ENDP2 ) ) );
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ??? ??? ??? ?case 0x02:
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?ch374_wr_reg( REG_USB_ENDP2, M_SET_EP2_RECV_ACK( ch374_rd_reg( REG_USB_ENDP2 ) ) );
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ??? ??? ??? ?case 0x81:
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?ch374_wr_reg( REG_USB_ENDP1, M_SET_EP1_TRAN_NAK( ch374_rd_reg( REG_USB_ENDP1 ) ) );
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ??? ??? ??? ?case 0x01:
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?ch374_wr_reg( REG_USB_ENDP1, M_SET_EP1_RECV_ACK( ch374_rd_reg( REG_USB_ENDP1 ) ) );
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ??? ??? ??? ?default:
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?l = 0xFF;? // 操作失敗
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ??? ?else l = 0xFF;? // 操作失敗
?? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ?case DEF_USB_GET_INTERF:
?? ??? ??? ??? ??? ??? ??? ?ch374_wr_reg( RAM_ENDP0_TRAN, 0 );
?? ??? ??? ??? ??? ??? ??? ?if ( SetupLen >= 1 ) l = 1;
?? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ?case DEF_USB_GET_STATUS:
?? ??? ??? ??? ??? ??? ??? ?ch374_wr_reg( RAM_ENDP0_TRAN, 0 );
?? ??? ??? ??? ??? ??? ??? ?ch374_wr_reg( RAM_ENDP0_TRAN + 1, 0 );
?? ??? ??? ??? ??? ??? ??? ?if ( SetupLen >= 2 ) l = 2;
?? ??? ??? ??? ??? ??? ??? ?else l = SetupLen;
?? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ??? ?default:
?? ??? ??? ??? ??? ??? ??? ?l = 0xFF;? // 操作失敗
?? ??? ??? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ??? ?else l = 0xFF;? // 操作失敗
?? ??? ??? ?if ( l == 0xFF ) {? // 操作失敗
?? ??? ??? ??? ?ch374_wr_reg( REG_USB_ENDP0, M_SET_EP0_RECV_STA( M_SET_EP0_TRAN_STA( 0 ) ) );? // STALL
?? ??? ??? ?}
?? ??? ??? ?else if ( l <= RAM_ENDP0_SIZE ) {? // 上傳數(shù)據(jù)
??
??? ??? ??? ?ch374_wr_reg( REG_USB_ENDP0, M_SET_EP0_TRAN_ACK(
M_SET_EP0_RECV_ACK( ch374_rd_reg( REG_USB_ENDP0 ) ), l ) |
BIT_EP0_TRAN_TOG );? // DATA1
?? ??? ??? ?}
?? ??? ??? ?else {? // 下傳數(shù)據(jù)或其它
??
??? ??? ??? ?ch374_wr_reg( REG_USB_ENDP0, M_SET_EP0_TRAN_NAK(
M_SET_EP0_RECV_ACK( ch374_rd_reg( REG_USB_ENDP0 ) ) ) | BIT_EP0_RECV_TOG
);? // DATA1
?? ??? ??? ?}
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?case USB_INT_EP0_IN: {
?? ??? ??? ?switch( SetupReq ) {
?? ??? ??? ??? ?case DEF_USB_GET_DESCR:
?? ??? ??? ??? ??? ?l = SetupLen >= RAM_ENDP0_SIZE ? RAM_ENDP0_SIZE : SetupLen;? // 本次傳輸長(zhǎng)度
?? ??? ??? ??? ??? ?ch374_wr_block( RAM_ENDP0_TRAN, l, pDescr );? /* 加載上傳數(shù)據(jù) */
?? ??? ??? ??? ??? ?SetupLen -= l;
?? ??? ??? ??? ??? ?pDescr += l;
?? ??? ??? ??? ??? ?ch374_wr_reg( REG_USB_ENDP0, M_SET_EP0_TRAN_ACK( ch374_rd_reg( REG_USB_ENDP0 ), l ) ^ BIT_EP0_TRAN_TOG );
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?case DEF_USB_SET_ADDRESS:
?? ??? ??? ??? ??? ?ch374_wr_reg( REG_USB_ADDR, SetupLen );
?? ??? ??? ??? ?default:
?? ??? ??? ??? ??? ?ch374_wr_reg( REG_USB_ENDP0, M_SET_EP0_TRAN_NAK( 0 ) );? // 結(jié)束
?? ??? ??? ??? ??? ?break;
?? ??? ??? ?}
?? ??? ??? ?//printk("******USB_INT_EP0_IN\n");
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?case USB_INT_EP0_OUT: {
?? ??? ??? ?switch( SetupReq ) {
?? ??? ??? ??? ?case DEF_USB_GET_DESCR:
?? ??? ??? ??? ?default:
?? ??? ??? ??? ??? ?ch374_wr_reg( REG_USB_ENDP0, M_SET_EP0_TRAN_NAK( 0 ) );? // 結(jié)束
?? ??? ??? ??? ??? ?break;
?? ??? ??? ?}
?? ??? ??? ?//printk("******USB_INT_EP0_OUT\n");
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?default:
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?ch374_wr_reg( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_TRANSFER );? // 清中斷標(biāo)志
驅(qū)動(dòng)中寫的接口實(shí)現(xiàn)
static ssize_t ch374_dev_write(struct file *filep, const char __user *buf,
?? ??? ??? ???? size_t count, loff_t *ptr)
{
?? ?int i = 0;
?? ?unsigned int len = count;
?? ?Fifo_node_t fifo_node;
?? ?if (copy_from_user((void *)tx_buf, buf, len)) {
?? ??? ?return -EFAULT;
?? ?}
?? ?else {
?? ??? ?if(ch374_dev.tx_flag == 0)
?? ??? ?{
?? ??? ??? ?fifo_node.len = (len > EPDATA_LEN_MAX)?EPDATA_LEN_MAX:len;
?? ??? ??? ?memcpy(fifo_node.buf, tx_buf, fifo_node.len);
?? ??? ??? ?ch374_wr_block( RAM_ENDP2_TRAN, fifo_node.len, fifo_node.buf );
?? ??? ??? ?ch374_wr_reg( REG_USB_LENGTH, fifo_node.len );
?? ??? ??? ?ch374_wr_reg( REG_USB_ENDP2, M_SET_EP2_TRAN_ACK( ch374_rd_reg( REG_USB_ENDP2 ) ) ^ BIT_EP2_TRAN_TOG );
?? ??? ??? ?ch374_dev.tx_flag = 1;
?? ??? ??? ?i++;
?? ??? ?}
?? ??? ?for(; i < len/EPDATA_LEN_MAX; i++)
?? ??? ?{
?? ??? ??? ?fifo_node.len = EPDATA_LEN_MAX;
?? ??? ??? ?memcpy(fifo_node.buf, tx_buf + i*EPDATA_LEN_MAX, fifo_node.len);
?? ??? ??? ?kfifo_in(&ch374_dev.wr_fifo, &fifo_node, sizeof(Fifo_node_t));
?? ??? ?}
?? ??? ?if(len%EPDATA_LEN_MAX != 0)
?? ??? ?{
?? ??? ??? ?fifo_node.len = len%EPDATA_LEN_MAX;
?? ??? ??? ?memcpy(fifo_node.buf, tx_buf + i*EPDATA_LEN_MAX, fifo_node.len);
?? ??? ??? ?kfifo_in(&ch374_dev.wr_fifo, &fifo_node, sizeof(Fifo_node_t));
?? ??? ?}
?? ?}
?? ?return len;
}