@@ -498,7 +498,8 @@ impl<USB: UsbPeripheral> usb_device::bus::UsbBus for UsbBus<USB> {
498498 write_reg ! ( otg_global, regs. global( ) , GINTMSK ,
499499 USBRST : 1 , ENUMDNEM : 1 ,
500500 USBSUSPM : 1 , WUIM : 1 ,
501- IEPINT : 1 , RXFLVLM : 1
501+ IEPINT : 1 , RXFLVLM : 1 ,
502+ IISOIXFRM : 1
502503 ) ;
503504
504505 // clear pending interrupts
@@ -585,8 +586,8 @@ impl<USB: UsbPeripheral> usb_device::bus::UsbBus for UsbBus<USB> {
585586
586587 let core_id = read_reg ! ( otg_global, regs. global( ) , CID ) ;
587588
588- let ( wakeup, suspend, enum_done, reset, iep, rxflvl) = read_reg ! ( otg_global, regs. global( ) , GINTSTS ,
589- WKUPINT , USBSUSP , ENUMDNE , USBRST , IEPINT , RXFLVL
589+ let ( wakeup, suspend, enum_done, reset, iep, rxflvl, iisoixfr ) = read_reg ! ( otg_global, regs. global( ) , GINTSTS ,
590+ WKUPINT , USBSUSP , ENUMDNE , USBRST , IEPINT , RXFLVL , IISOIXFR
590591 ) ;
591592
592593 if reset != 0 {
@@ -649,6 +650,53 @@ impl<USB: UsbPeripheral> usb_device::bus::UsbBus for UsbBus<USB> {
649650 write_reg ! ( otg_global, regs. global( ) , GINTSTS , USBSUSP : 1 ) ;
650651
651652 PollResult :: Suspend
653+ } else if iisoixfr != 0 {
654+ use crate :: ral:: endpoint_in;
655+
656+ // Incomplete isochronous IN transfer; see
657+ // RM0383 Rev 3 pp797 "Incomplete isochronous IN data transfers"
658+ write_reg ! ( otg_global, regs. global( ) , GINTSTS , IISOIXFR : 1 ) ;
659+
660+ let in_endpoints = self . allocator . endpoints_in
661+ . iter ( )
662+ . flatten ( )
663+ . map ( |ep| ep. address ( ) . index ( ) ) ;
664+
665+ let mut iep: u16 = 0 ;
666+
667+ for epnum in in_endpoints {
668+ let ep_regs = regs. endpoint_in ( epnum) ;
669+
670+ // filter out non-isochronous endpoints
671+ if read_reg ! ( endpoint_in, ep_regs, DIEPCTL , EPTYP ) & 0x11 != 0x01 { continue ; }
672+
673+ // identify incomplete transfers by the presence of the NAK event
674+ // see RM0383 Rev 3 pp 746 description of NAK:
675+ //
676+ // > In case of isochronous IN endpoints the interrupt gets
677+ // > generated when a zero length packet is transmitted due
678+ // > to unavailability of data in the Tx FIFO.
679+ if read_reg ! ( endpoint_in, ep_regs, DIEPINT ) & 1 <<13 == 0 { continue ; }
680+
681+ // Set NAK
682+ modify_reg ! ( endpoint_in, ep_regs, DIEPCTL , SNAK : 1 ) ;
683+ while read_reg ! ( endpoint_in, ep_regs, DIEPINT , INEPNE ) == 0 { }
684+
685+ // Disable the endpoint
686+ modify_reg ! ( endpoint_in, ep_regs, DIEPCTL , SNAK : 1 , EPDIS : 1 ) ;
687+ while read_reg ! ( endpoint_in, ep_regs, DIEPINT , EPDISD ) == 0 { }
688+ modify_reg ! ( endpoint_in, ep_regs, DIEPINT , EPDISD : 1 ) ;
689+ assert ! ( read_reg!( endpoint_in, ep_regs, DIEPCTL , EPENA ) == 0 ) ;
690+ assert ! ( read_reg!( endpoint_in, ep_regs, DIEPCTL , EPDIS ) == 0 ) ;
691+
692+ // Flush the TX FIFO
693+ modify_reg ! ( otg_global, regs. global( ) , GRSTCTL , TXFNUM : epnum as u32 , TXFFLSH : 1 ) ;
694+ while read_reg ! ( otg_global, regs. global( ) , GRSTCTL , TXFFLSH ) == 1 { }
695+
696+ iep |= 1 << epnum;
697+ }
698+
699+ PollResult :: Data { ep_out : 0 , ep_in_complete : iep, ep_setup : 0 }
652700 } else {
653701 let mut ep_out = 0 ;
654702 let mut ep_in_complete = 0 ;
0 commit comments