2014-02-03 00:19:58 +00:00
/* Teensyduino Core Library
* http : //www.pjrc.com/teensy/
* Copyright ( c ) 2013 PJRC . COM , LLC .
2014-09-28 23:44:57 +00:00
* Modifications by Jacob Alexander ( 2013 - 2014 )
2014-02-03 00:19:58 +00:00
*
* Permission is hereby granted , free of charge , to any person obtaining
* a copy of this software and associated documentation files ( the
* " Software " ) , to deal in the Software without restriction , including
* without limitation the rights to use , copy , modify , merge , publish ,
* distribute , sublicense , and / or sell copies of the Software , and to
* permit persons to whom the Software is furnished to do so , subject to
* the following conditions :
*
2014-09-28 23:44:57 +00:00
* 1. The above copyright notice and this permission notice shall be
2014-02-03 00:19:58 +00:00
* included in all copies or substantial portions of the Software .
*
2014-09-28 23:44:57 +00:00
* 2. If the Software is incorporated into a build system that allows
2014-02-03 00:19:58 +00:00
* 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 .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND ,
* EXPRESS OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY , FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT . IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER LIABILITY , WHETHER IN AN
* ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM , OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE .
*/
2014-09-28 23:44:57 +00:00
// ----- Includes -----
// Project Includes
2014-02-03 01:33:23 +00:00
# include <Lib/OutputLib.h>
2014-09-28 23:44:57 +00:00
// Local Includes
2013-01-27 06:47:52 +00:00
# include "usb_dev.h"
# include "usb_mem.h"
2014-09-28 23:44:57 +00:00
// ----- Variables -----
2013-01-27 06:47:52 +00:00
__attribute__ ( ( section ( " .usbbuffers " ) , used ) )
2014-09-28 23:44:57 +00:00
unsigned char usb_buffer_memory [ NUM_USB_BUFFERS * sizeof ( usb_packet_t ) ] ;
2013-01-27 06:47:52 +00:00
static uint32_t usb_buffer_available = 0xFFFFFFFF ;
2014-09-28 23:44:57 +00:00
// ----- Externs -----
extern void usb_rx_memory ( usb_packet_t * packet ) ;
// for the receive endpoints to request memory
extern uint8_t usb_rx_memory_needed ;
// ----- Functions -----
2013-01-27 06:47:52 +00:00
// use bitmask and CLZ instruction to implement fast free list
// http://www.archivum.info/gnu.gcc.help/2006-08/00148/Re-GCC-Inline-Assembly.html
// http://gcc.gnu.org/ml/gcc/2012-06/msg00015.html
// __builtin_clz()
2014-09-28 23:44:57 +00:00
usb_packet_t * usb_malloc ( )
2013-01-27 06:47:52 +00:00
{
unsigned int n , avail ;
uint8_t * p ;
__disable_irq ( ) ;
avail = usb_buffer_available ;
2014-09-28 23:44:57 +00:00
n = __builtin_clz ( avail ) ; // clz = count leading zeros
if ( n > = NUM_USB_BUFFERS )
{
2013-01-27 06:47:52 +00:00
__enable_irq ( ) ;
return NULL ;
}
usb_buffer_available = avail & ~ ( 0x80000000 > > n ) ;
__enable_irq ( ) ;
2014-09-28 23:44:57 +00:00
p = usb_buffer_memory + ( n * sizeof ( usb_packet_t ) ) ;
2013-01-27 06:47:52 +00:00
* ( uint32_t * ) p = 0 ;
* ( uint32_t * ) ( p + 4 ) = 0 ;
return ( usb_packet_t * ) p ;
}
2014-09-28 23:44:57 +00:00
void usb_free ( usb_packet_t * p )
2013-01-27 06:47:52 +00:00
{
unsigned int n , mask ;
2014-09-28 23:44:57 +00:00
n = ( ( uint8_t * ) p - usb_buffer_memory ) / sizeof ( usb_packet_t ) ;
if ( n > = NUM_USB_BUFFERS )
return ;
2013-01-27 06:47:52 +00:00
// if any endpoints are starving for memory to receive
// packets, give this memory to them immediately!
2014-09-28 23:44:57 +00:00
if ( usb_rx_memory_needed & & usb_configuration )
{
usb_rx_memory ( p ) ;
2013-01-27 06:47:52 +00:00
return ;
}
mask = ( 0x80000000 > > n ) ;
__disable_irq ( ) ;
usb_buffer_available | = mask ;
__enable_irq ( ) ;
}