support 2nd player streaming from separate raw file
[teensytas.git] / teensy3 / usb_mem.c
index c6e902a..5d9b467 100644 (file)
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
  *
- * 1. The above copyright notice and this permission notice shall be 
+ * 1. The above copyright notice and this permission notice shall be
  * included in all copies or substantial portions of the Software.
  *
- * 2. If the Software is incorporated into a build system that allows 
+ * 2. If the Software is incorporated into a build system that allows
  * selection among a list of target devices, then similar target
  * devices manufactured by PJRC.COM must be included in the list of
  * target devices and selectable in the same manner.
  * SOFTWARE.
  */
 
-#include "mk20dx128.h"
-//#include "HardwareSerial.h"
 #include "usb_dev.h"
+#if F_CPU >= 20000000 && defined(NUM_ENDPOINTS)
+
+#include "kinetis.h"
+//#include "HardwareSerial.h"
 #include "usb_mem.h"
 
 __attribute__ ((section(".usbbuffers"), used))
@@ -45,22 +47,22 @@ static uint32_t usb_buffer_available = 0xFFFFFFFF;
 
 usb_packet_t * usb_malloc(void)
 {
-       unsigned int n, avail;
+       unsigned int n, avail, avail_new;
        uint8_t *p;
 
-       __disable_irq();
-       avail = usb_buffer_available;
-       n = __builtin_clz(avail); // clz = count leading zeros
-       if (n >= NUM_USB_BUFFERS) {
-               __enable_irq();
-               return NULL;
+       do {
+               avail = usb_buffer_available;
+               n = __builtin_clz(avail); // clz = count leading zeros
+               if (n >= NUM_USB_BUFFERS) return NULL;
+
+               //serial_print("malloc:");
+               //serial_phex(n);
+               //serial_print("\n");
+
+               avail_new = avail & ~(0x80000000 >> n);
        }
-       //serial_print("malloc:");
-       //serial_phex(n);
-       //serial_print("\n");
+       while (!__sync_bool_compare_and_swap(&usb_buffer_available, avail, avail_new));
 
-       usb_buffer_available = avail & ~(0x80000000 >> n);
-       __enable_irq();
        p = usb_buffer_memory + (n * sizeof(usb_packet_t));
        //serial_print("malloc:");
        //serial_phex32((int)p);
@@ -95,12 +97,11 @@ void usb_free(usb_packet_t *p)
        }
 
        mask = (0x80000000 >> n);
-       __disable_irq();
-       usb_buffer_available |= mask;
-       __enable_irq();
+       __sync_fetch_and_or(&usb_buffer_available, mask);
 
        //serial_print("free:");
        //serial_phex32((int)p);
        //serial_print("\n");
 }
 
+#endif // F_CPU >= 20 MHz && defined(NUM_ENDPOINTS)