@@ -322,18 +322,22 @@ namespace klib::core::atsam4s::io {
322322 }
323323 }
324324
325+ template <bool Isochronous>
325326 static void endpoint_out_callback (const uint8_t endpoint) {
326- // check if we are busy.
327- if (!state[endpoint].is_busy ) {
328- // set the flag we have a out interrupt pending
329- state[endpoint].interrupt_pending = true ;
330-
331- // disable the endpoint interrupt to prevent
332- // continuous triggers on the endpoint
333- Usb::port->IDR = (0x1 << endpoint);
334-
335- // do not read anything
336- return ;
327+ // only check if we are busy if we are not a iso endpoint
328+ if constexpr (!Isochronous) {
329+ // check if we are busy.
330+ if (!state[endpoint].is_busy ) {
331+ // set the flag we have a out interrupt pending
332+ state[endpoint].interrupt_pending = true ;
333+
334+ // disable the endpoint interrupt to prevent
335+ // continuous triggers on the endpoint
336+ Usb::port->IDR = (0x1 << endpoint);
337+
338+ // do not read anything
339+ return ;
340+ }
337341 }
338342
339343 // check both banks if the endpoint supports dual banks
@@ -419,7 +423,7 @@ namespace klib::core::atsam4s::io {
419423 }
420424 else {
421425 // call the out callback
422- endpoint_out_callback (endpoint);
426+ endpoint_out_callback< false > (endpoint);
423427 }
424428 }
425429 else if (value & (0x1 << 3 )) {
@@ -471,6 +475,53 @@ namespace klib::core::atsam4s::io {
471475 }
472476 }
473477
478+ static void isochronous_irq_handler () {
479+ // get all the isochronous endpoints
480+ uint32_t endpoints = iso_endpoints;
481+
482+ // amount of trailing zeros in the status register
483+ uint8_t trailing_zeros = 0 ;
484+
485+ // we have a frame interrupt. Mark all the isochronous
486+ // endpoints as not busy
487+ while ((trailing_zeros = klib::ctz (endpoints)) < 32 ) {
488+ // get the current endpoint
489+ const uint8_t endpoint = trailing_zeros;
490+
491+ // clear the bit from the endpoints
492+ endpoints &= ~(0x1 << endpoint);
493+
494+ // check if we are busy transmitting or receiving data
495+ if (!state[endpoint].is_busy ) {
496+ continue ;
497+ }
498+
499+ // check what kind of packet we have
500+ const uint32_t value = Usb::port->CSR [endpoint];
501+
502+ // check if the endpoint is enabled
503+ if (!(value & (0x1 << 15 ))) {
504+ continue ;
505+ }
506+
507+ // get the endpoint mode
508+ const auto mode = static_cast <endpoint_mode>((value >> 8 ) & 0x7 );
509+
510+ // check if the endpoint is isochronous
511+ if (mode != endpoint_mode::iso_in && mode != endpoint_mode::iso_out) {
512+ continue ;
513+ }
514+
515+ // check how we need to handle the endpoint
516+ if (raw_to_endpoint_mode (mode) == klib::usb::usb::endpoint_mode::out) {
517+ endpoint_out_callback<true >(endpoint);
518+ }
519+ else {
520+ endpoint_in_callback (endpoint);
521+ }
522+ }
523+ }
524+
474525 public:
475526 /* *
476527 * @brief Interrupt handler for the usb driver
@@ -524,7 +575,7 @@ namespace klib::core::atsam4s::io {
524575 device::template sleep<usb_type>();
525576 }
526577
527- // enable the wakeup and resume interrupts
578+ // enable the wakeup and resume interrupts
528579 Usb::port->IER = ((0x1 << 13 ) | (0x1 << 9 ));
529580
530581 // disable the suspend interrupt
@@ -543,6 +594,12 @@ namespace klib::core::atsam4s::io {
543594 // disable the wakeup and resume interrupts
544595 Usb::port->IDR = ((0x1 << 13 ) | (0x1 << 9 ));
545596 }
597+
598+ // check for a frame interrupt
599+ if (masked_status & (0x1 << 11 )) {
600+ // we have a frame interrupt. Handle it in the iso irq
601+ isochronous_irq_handler ();
602+ }
546603 }
547604
548605 public:
@@ -666,6 +723,11 @@ namespace klib::core::atsam4s::io {
666723 Usb::port->CSR [endpoint] = (
667724 (0x1 << 15 ) | (transfer_type_to_raw (mode, type) << 8 )
668725 );
726+
727+ // check if we need to enable the iso interrupt
728+ if (type == klib::usb::descriptor::transfer_type::isochronous) {
729+ Usb::port->IER = (0x1 << 11 );
730+ }
669731 }
670732
671733 /* *
0 commit comments