Skip to content

Commit 34ae343

Browse files
committed
added support for isochornous interrupts
1 parent bc56395 commit 34ae343

1 file changed

Lines changed: 75 additions & 13 deletions

File tree

targets/core/atmel/atsam4s/usb.hpp

Lines changed: 75 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)