usb_drv.c File Reference


Detailed Description

Low-level driver for AVR32 USBB.

This file contains the USBB low-level driver routines.

Author:
Atmel Corporation: http://www.atmel.com
Support and FAQ: http://support.atmel.no/

Definition in file usb_drv.c.

#include "usb_drv.h"
#include "usb_descriptors.h"

Go to the source code of this file.

Functions

void host_disable_all_pipes (void)
 --------------------------------------------------------- ------------------ HOST --------------------------------- ---------------------------------------------------------
U32 host_read_p_rxpacket (U8 p, void *rxbuf, U32 data_length, void **prxbuf)
 host_read_p_rxpacket
U32 host_set_p_txpacket (U8 p, U8 txbyte, U32 data_length)
 host_set_p_txpacket
U32 host_write_p_txpacket (U8 p, const void *txbuf, U32 data_length, const void **ptxbuf)
 host_write_p_txpacket
Status_bool_t usb_init_device (void)
 --------------------------------------------------------- ------------------ DEVICE ------------------------------- ---------------------------------------------------------
U32 usb_read_ep_rxpacket (U8 ep, void *rxbuf, U32 data_length, void **prxbuf)
 usb_read_ep_rxpacket
U32 usb_set_ep_txpacket (U8 ep, U8 txbyte, U32 data_length)
 usb_set_ep_txpacket
U32 usb_write_ep_txpacket (U8 ep, const void *txbuf, U32 data_length, const void **ptxbuf)
 usb_write_ep_txpacket

Variables

UnionVPtr pep_fifo [MAX_PEP_NB]
 Pointers to the FIFO data registers of pipes/endpoints Use aggregated pointers to have several alignments available for a same address.


Function Documentation

void host_disable_all_pipes ( void   ) 

--------------------------------------------------------- ------------------ HOST --------------------------------- ---------------------------------------------------------

host_disable_all_pipes This function disables all pipes for the host controller. Useful to execute upon disconnection.

Returns:
Void

Definition at line 468 of file usb_drv.c.

References Host_disable_pipe, Host_disable_pipe_interrupt, Host_reset_pipe, Host_unallocate_memory, Is_host_pipe_enabled, and MAX_PEP_NB.

Referenced by usb_general_interrupt_non_naked(), and usb_host_task().

00469 {
00470 #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE
00471   Bool sav_glob_int_en;
00472 #endif
00473   U8 p;
00474 
00475 #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE
00476   // Disable global interrupts
00477   if ((sav_glob_int_en = Is_global_interrupt_enabled())) Disable_global_interrupt();
00478 #endif
00479   for (p = 0; p < MAX_PEP_NB; p++)
00480   { // Disable the pipe <p> (disable interrupt, free memory, reset pipe, ...)
00481     Host_disable_pipe_interrupt(p);
00482     Host_reset_pipe(p);
00483     Host_unallocate_memory(p);
00484     Host_disable_pipe(p);
00485   }
00486 #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE
00487   (void)Is_host_pipe_enabled(MAX_PEP_NB - 1);
00488   // Restore the global interrupts to the initial state
00489   if (sav_glob_int_en) Enable_global_interrupt();
00490 #endif
00491 }

U32 host_read_p_rxpacket ( U8  p,
void *  rxbuf,
U32  data_length,
void **  prxbuf 
)

host_read_p_rxpacket

This function reads the selected pipe FIFO to the buffer pointed to by rxbuf, using as few accesses as possible.

Parameters:
p Number of the addressed pipe
rxbuf Address of buffer to write
data_length Number of bytes to read
prxbuf NULL or pointer to the buffer address to update
Returns:
Number of non-read bytes
Note:
The selected pipe FIFO may be read in several steps by calling host_read_p_rxpacket several times.
Warning:
Invoke Host_reset_pipe_fifo_access before this function when at FIFO beginning whether or not the FIFO is to be read in several steps.

Do not mix calls to this function with calls to indexed macros.

Definition at line 756 of file usb_drv.c.

References Host_byte_count, and pep_fifo.

Referenced by host_get_data(), host_transfer_control(), and usb_pipe_interrupt().

00757 {
00758   // Use aggregated pointers to have several alignments available for a same address
00759   UnionCVPtr  p_fifo;
00760   UnionPtr    rxbuf_cur;
00761 #if (!defined __OPTIMIZE_SIZE__) || !__OPTIMIZE_SIZE__  // Auto-generated when GCC's -Os command option is used
00762   StructCPtr  rxbuf_end;
00763 #else
00764   UnionCPtr   rxbuf_end;
00765 #endif  // !__OPTIMIZE_SIZE__
00766 
00767   // Initialize pointers for copy loops and limit the number of bytes to copy
00768   p_fifo.u8ptr = pep_fifo[p].u8ptr;
00769   rxbuf_cur.u8ptr = rxbuf;
00770   rxbuf_end.u8ptr = rxbuf_cur.u8ptr + min(data_length, Host_byte_count(p));
00771 #if (!defined __OPTIMIZE_SIZE__) || !__OPTIMIZE_SIZE__  // Auto-generated when GCC's -Os command option is used
00772   rxbuf_end.u16ptr = (U16 *)Align_down((U32)rxbuf_end.u8ptr, sizeof(U16));
00773   rxbuf_end.u32ptr = (U32 *)Align_down((U32)rxbuf_end.u16ptr, sizeof(U32));
00774   rxbuf_end.u64ptr = (U64 *)Align_down((U32)rxbuf_end.u32ptr, sizeof(U64));
00775 
00776   // If all addresses are aligned the same way with respect to 16-bit boundaries
00777   if (Get_align((U32)rxbuf_cur.u8ptr, sizeof(U16)) == Get_align((U32)p_fifo.u8ptr, sizeof(U16)))
00778   {
00779     // If pointer to reception buffer is not 16-bit aligned
00780     if (!Test_align((U32)rxbuf_cur.u8ptr, sizeof(U16)))
00781     {
00782       // Copy 8-bit data to reach 16-bit alignment
00783       if (rxbuf_cur.u8ptr < rxbuf_end.u8ptr)
00784       {
00785         // 8-bit accesses to FIFO data registers do require pointer post-increment
00786         *rxbuf_cur.u8ptr++ = *p_fifo.u8ptr++;
00787       }
00788     }
00789 
00790     // If all addresses are aligned the same way with respect to 32-bit boundaries
00791     if (Get_align((U32)rxbuf_cur.u16ptr, sizeof(U32)) == Get_align((U32)p_fifo.u16ptr, sizeof(U32)))
00792     {
00793       // If pointer to reception buffer is not 32-bit aligned
00794       if (!Test_align((U32)rxbuf_cur.u16ptr, sizeof(U32)))
00795       {
00796         // Copy 16-bit data to reach 32-bit alignment
00797         if (rxbuf_cur.u16ptr < rxbuf_end.u16ptr)
00798         {
00799           // 16-bit accesses to FIFO data registers do require pointer post-increment
00800           *rxbuf_cur.u16ptr++ = *p_fifo.u16ptr++;
00801         }
00802       }
00803 
00804       // If pointer to reception buffer is not 64-bit aligned
00805       if (!Test_align((U32)rxbuf_cur.u32ptr, sizeof(U64)))
00806       {
00807         // Copy 32-bit data to reach 64-bit alignment
00808         if (rxbuf_cur.u32ptr < rxbuf_end.u32ptr)
00809         {
00810           // 32-bit accesses to FIFO data registers do not require pointer post-increment
00811           *rxbuf_cur.u32ptr++ = *p_fifo.u32ptr;
00812         }
00813       }
00814 
00815       // Copy 64-bit-aligned data
00816       while (rxbuf_cur.u64ptr < rxbuf_end.u64ptr)
00817       {
00818         // 64-bit accesses to FIFO data registers do not require pointer post-increment
00819         *rxbuf_cur.u64ptr++ = *p_fifo.u64ptr;
00820       }
00821 
00822       // Copy 32-bit-aligned data
00823       if (rxbuf_cur.u32ptr < rxbuf_end.u32ptr)
00824       {
00825         // 32-bit accesses to FIFO data registers do not require pointer post-increment
00826         *rxbuf_cur.u32ptr++ = *p_fifo.u32ptr;
00827       }
00828     }
00829 
00830     // Copy remaining 16-bit data if some
00831     while (rxbuf_cur.u16ptr < rxbuf_end.u16ptr)
00832     {
00833       // 16-bit accesses to FIFO data registers do require pointer post-increment
00834       *rxbuf_cur.u16ptr++ = *p_fifo.u16ptr++;
00835     }
00836   }
00837 
00838 #endif  // !__OPTIMIZE_SIZE__
00839 
00840   // Copy remaining 8-bit data if some
00841   while (rxbuf_cur.u8ptr < rxbuf_end.u8ptr)
00842   {
00843     // 8-bit accesses to FIFO data registers do require pointer post-increment
00844     *rxbuf_cur.u8ptr++ = *p_fifo.u8ptr++;
00845   }
00846 
00847   // Save current position in FIFO data register
00848   pep_fifo[p].u8ptr = (volatile U8 *)p_fifo.u8ptr;
00849 
00850   // Return the updated buffer address and the number of non-copied bytes
00851   if (prxbuf) *prxbuf = rxbuf_cur.u8ptr;
00852   return data_length - (rxbuf_cur.u8ptr - (U8 *)rxbuf);
00853 }

U32 host_set_p_txpacket ( U8  p,
U8  txbyte,
U32  data_length 
)

host_set_p_txpacket

This function fills the selected pipe FIFO with a constant byte, using as few accesses as possible.

Parameters:
p Number of the addressed pipe
txbyte Byte to fill the pipe with
data_length Number of bytes to write
Returns:
Number of non-written bytes
Note:
The selected pipe FIFO may be filled in several steps by calling host_set_p_txpacket several times.
Warning:
Invoke Host_reset_pipe_fifo_access before this function when at FIFO beginning whether or not the FIFO is to be filled in several steps.

Do not mix calls to this function with calls to indexed macros.

Definition at line 512 of file usb_drv.c.

References Host_byte_count, Host_get_pipe_size, and pep_fifo.

00513 {
00514   // Use aggregated pointers to have several alignments available for a same address
00515   UnionVPtr   p_fifo_cur;
00516 #if (!defined __OPTIMIZE_SIZE__) || !__OPTIMIZE_SIZE__  // Auto-generated when GCC's -Os command option is used
00517   StructCVPtr p_fifo_end;
00518   Union64     txval;
00519 #else
00520   UnionCVPtr  p_fifo_end;
00521   union
00522   {
00523     U8 u8[1];
00524   } txval;
00525 #endif  // !__OPTIMIZE_SIZE__
00526 
00527   // Initialize pointers for write loops and limit the number of bytes to write
00528   p_fifo_cur.u8ptr = pep_fifo[p].u8ptr;
00529   p_fifo_end.u8ptr = p_fifo_cur.u8ptr +
00530                      min(data_length, Host_get_pipe_size(p) - Host_byte_count(p));
00531 #if (!defined __OPTIMIZE_SIZE__) || !__OPTIMIZE_SIZE__  // Auto-generated when GCC's -Os command option is used
00532   p_fifo_end.u16ptr = (U16 *)Align_down((U32)p_fifo_end.u8ptr, sizeof(U16));
00533   p_fifo_end.u32ptr = (U32 *)Align_down((U32)p_fifo_end.u16ptr, sizeof(U32));
00534   p_fifo_end.u64ptr = (U64 *)Align_down((U32)p_fifo_end.u32ptr, sizeof(U64));
00535 #endif  // !__OPTIMIZE_SIZE__
00536   txval.u8[0] = txbyte;
00537 #if (!defined __OPTIMIZE_SIZE__) || !__OPTIMIZE_SIZE__  // Auto-generated when GCC's -Os command option is used
00538   txval.u8[1] = txval.u8[0];
00539   txval.u16[1] = txval.u16[0];
00540   txval.u32[1] = txval.u32[0];
00541 
00542   // If pointer to FIFO data register is not 16-bit aligned
00543   if (!Test_align((U32)p_fifo_cur.u8ptr, sizeof(U16)))
00544   {
00545     // Write 8-bit data to reach 16-bit alignment
00546     if (p_fifo_cur.u8ptr < p_fifo_end.u8ptr)
00547     {
00548       *p_fifo_cur.u8ptr++ = txval.u8[0];
00549     }
00550   }
00551 
00552   // If pointer to FIFO data register is not 32-bit aligned
00553   if (!Test_align((U32)p_fifo_cur.u16ptr, sizeof(U32)))
00554   {
00555     // Write 16-bit data to reach 32-bit alignment
00556     if (p_fifo_cur.u16ptr < p_fifo_end.u16ptr)
00557     {
00558       *p_fifo_cur.u16ptr++ = txval.u16[0];
00559     }
00560   }
00561 
00562   // If pointer to FIFO data register is not 64-bit aligned
00563   if (!Test_align((U32)p_fifo_cur.u32ptr, sizeof(U64)))
00564   {
00565     // Write 32-bit data to reach 64-bit alignment
00566     if (p_fifo_cur.u32ptr < p_fifo_end.u32ptr)
00567     {
00568       *p_fifo_cur.u32ptr++ = txval.u32[0];
00569     }
00570   }
00571 
00572   // Write 64-bit-aligned data
00573   while (p_fifo_cur.u64ptr < p_fifo_end.u64ptr)
00574   {
00575     *p_fifo_cur.u64ptr++ = txval.u64;
00576   }
00577 
00578   // Write remaining 32-bit data if some
00579   if (p_fifo_cur.u32ptr < p_fifo_end.u32ptr)
00580   {
00581     *p_fifo_cur.u32ptr++ = txval.u32[0];
00582   }
00583 
00584   // Write remaining 16-bit data if some
00585   if (p_fifo_cur.u16ptr < p_fifo_end.u16ptr)
00586   {
00587     *p_fifo_cur.u16ptr++ = txval.u16[0];
00588   }
00589 
00590   // Write remaining 8-bit data if some
00591   if (p_fifo_cur.u8ptr < p_fifo_end.u8ptr)
00592   {
00593     *p_fifo_cur.u8ptr++ = txval.u8[0];
00594   }
00595 
00596 #else
00597 
00598   // Write remaining 8-bit data if some
00599   while (p_fifo_cur.u8ptr < p_fifo_end.u8ptr)
00600   {
00601     *p_fifo_cur.u8ptr++ = txval.u8[0];
00602   }
00603 
00604 #endif  // !__OPTIMIZE_SIZE__
00605 
00606   // Compute the number of non-written bytes
00607   data_length -= p_fifo_cur.u8ptr - pep_fifo[p].u8ptr;
00608 
00609   // Save current position in FIFO data register
00610   pep_fifo[p].u8ptr = p_fifo_cur.u8ptr;
00611 
00612   // Return the number of non-written bytes
00613   return data_length;
00614 }

U32 host_write_p_txpacket ( U8  p,
const void *  txbuf,
U32  data_length,
const void **  ptxbuf 
)

host_write_p_txpacket

This function writes the buffer pointed to by txbuf to the selected pipe FIFO, using as few accesses as possible.

Parameters:
p Number of the addressed pipe
txbuf Address of buffer to read
data_length Number of bytes to write
ptxbuf NULL or pointer to the buffer address to update
Returns:
Number of non-written bytes
Note:
The selected pipe FIFO may be written in several steps by calling host_write_p_txpacket several times.
Warning:
Invoke Host_reset_pipe_fifo_access before this function when at FIFO beginning whether or not the FIFO is to be written in several steps.

Do not mix calls to this function with calls to indexed macros.

Definition at line 636 of file usb_drv.c.

References Host_byte_count, Host_get_pipe_size, and pep_fifo.

Referenced by host_send_data(), host_send_data_interrupt(), host_transfer_control(), and usb_pipe_interrupt().

00637 {
00638   // Use aggregated pointers to have several alignments available for a same address
00639   UnionVPtr   p_fifo;
00640   UnionCPtr   txbuf_cur;
00641 #if (!defined __OPTIMIZE_SIZE__) || !__OPTIMIZE_SIZE__  // Auto-generated when GCC's -Os command option is used
00642   StructCPtr  txbuf_end;
00643 #else
00644   UnionCPtr   txbuf_end;
00645 #endif  // !__OPTIMIZE_SIZE__
00646 
00647   // Initialize pointers for copy loops and limit the number of bytes to copy
00648   p_fifo.u8ptr = pep_fifo[p].u8ptr;
00649   txbuf_cur.u8ptr = txbuf;
00650   txbuf_end.u8ptr = txbuf_cur.u8ptr +
00651                     min(data_length, Host_get_pipe_size(p) - Host_byte_count(p));
00652 #if (!defined __OPTIMIZE_SIZE__) || !__OPTIMIZE_SIZE__  // Auto-generated when GCC's -Os command option is used
00653   txbuf_end.u16ptr = (U16 *)Align_down((U32)txbuf_end.u8ptr, sizeof(U16));
00654   txbuf_end.u32ptr = (U32 *)Align_down((U32)txbuf_end.u16ptr, sizeof(U32));
00655   txbuf_end.u64ptr = (U64 *)Align_down((U32)txbuf_end.u32ptr, sizeof(U64));
00656 
00657   // If all addresses are aligned the same way with respect to 16-bit boundaries
00658   if (Get_align((U32)txbuf_cur.u8ptr, sizeof(U16)) == Get_align((U32)p_fifo.u8ptr, sizeof(U16)))
00659   {
00660     // If pointer to transmission buffer is not 16-bit aligned
00661     if (!Test_align((U32)txbuf_cur.u8ptr, sizeof(U16)))
00662     {
00663       // Copy 8-bit data to reach 16-bit alignment
00664       if (txbuf_cur.u8ptr < txbuf_end.u8ptr)
00665       {
00666         // 8-bit accesses to FIFO data registers do require pointer post-increment
00667         *p_fifo.u8ptr++ = *txbuf_cur.u8ptr++;
00668       }
00669     }
00670 
00671     // If all addresses are aligned the same way with respect to 32-bit boundaries
00672     if (Get_align((U32)txbuf_cur.u16ptr, sizeof(U32)) == Get_align((U32)p_fifo.u16ptr, sizeof(U32)))
00673     {
00674       // If pointer to transmission buffer is not 32-bit aligned
00675       if (!Test_align((U32)txbuf_cur.u16ptr, sizeof(U32)))
00676       {
00677         // Copy 16-bit data to reach 32-bit alignment
00678         if (txbuf_cur.u16ptr < txbuf_end.u16ptr)
00679         {
00680           // 16-bit accesses to FIFO data registers do require pointer post-increment
00681           *p_fifo.u16ptr++ = *txbuf_cur.u16ptr++;
00682         }
00683       }
00684 
00685       // If pointer to transmission buffer is not 64-bit aligned
00686       if (!Test_align((U32)txbuf_cur.u32ptr, sizeof(U64)))
00687       {
00688         // Copy 32-bit data to reach 64-bit alignment
00689         if (txbuf_cur.u32ptr < txbuf_end.u32ptr)
00690         {
00691           // 32-bit accesses to FIFO data registers do not require pointer post-increment
00692           *p_fifo.u32ptr = *txbuf_cur.u32ptr++;
00693         }
00694       }
00695 
00696       // Copy 64-bit-aligned data
00697       while (txbuf_cur.u64ptr < txbuf_end.u64ptr)
00698       {
00699         // 64-bit accesses to FIFO data registers do not require pointer post-increment
00700         *p_fifo.u64ptr = *txbuf_cur.u64ptr++;
00701       }
00702 
00703       // Copy 32-bit-aligned data
00704       if (txbuf_cur.u32ptr < txbuf_end.u32ptr)
00705       {
00706         // 32-bit accesses to FIFO data registers do not require pointer post-increment
00707         *p_fifo.u32ptr = *txbuf_cur.u32ptr++;
00708       }
00709     }
00710 
00711     // Copy remaining 16-bit data if some
00712     while (txbuf_cur.u16ptr < txbuf_end.u16ptr)
00713     {
00714       // 16-bit accesses to FIFO data registers do require pointer post-increment
00715       *p_fifo.u16ptr++ = *txbuf_cur.u16ptr++;
00716     }
00717   }
00718 
00719 #endif  // !__OPTIMIZE_SIZE__
00720 
00721   // Copy remaining 8-bit data if some
00722   while (txbuf_cur.u8ptr < txbuf_end.u8ptr)
00723   {
00724     // 8-bit accesses to FIFO data registers do require pointer post-increment
00725     *p_fifo.u8ptr++ = *txbuf_cur.u8ptr++;
00726   }
00727 
00728   // Save current position in FIFO data register
00729   pep_fifo[p].u8ptr = p_fifo.u8ptr;
00730 
00731   // Return the updated buffer address and the number of non-copied bytes
00732   if (ptxbuf) *ptxbuf = txbuf_cur.u8ptr;
00733   return data_length - (txbuf_cur.u8ptr - (U8 *)txbuf);
00734 }

Status_bool_t usb_init_device ( void   ) 

--------------------------------------------------------- ------------------ DEVICE ------------------------------- ---------------------------------------------------------

usb_init_device This function initializes the USB device controller and configures the Default Control Endpoint.

Returns:
Status

Definition at line 81 of file usb_drv.c.

References DIRECTION_OUT, EP_CONTROL, EP_CONTROL_LENGTH, Is_usb_endpoint_enabled, Is_usb_id_device, SINGLE_BANK, TYPE_CONTROL, and Usb_configure_endpoint.

Referenced by usb_general_interrupt_non_naked(), and usb_start_device().

U32 usb_read_ep_rxpacket ( U8  ep,
void *  rxbuf,
U32  data_length,
void **  prxbuf 
)

usb_read_ep_rxpacket

This function reads the selected endpoint FIFO to the buffer pointed to by rxbuf, using as few accesses as possible.

Parameters:
ep Number of the addressed endpoint
rxbuf Address of buffer to write
data_length Number of bytes to read
prxbuf NULL or pointer to the buffer address to update
Returns:
Number of non-read bytes
Note:
The selected endpoint FIFO may be read in several steps by calling usb_read_ep_rxpacket several times.
Warning:
Invoke Usb_reset_endpoint_fifo_access before this function when at FIFO beginning whether or not the FIFO is to be read in several steps.

Do not mix calls to this function with calls to indexed macros.

Definition at line 354 of file usb_drv.c.

References pep_fifo, and Usb_byte_count.

Referenced by device_template_task().

00355 {
00356   // Use aggregated pointers to have several alignments available for a same address
00357   UnionCVPtr  ep_fifo;
00358   UnionPtr    rxbuf_cur;
00359 #if (!defined __OPTIMIZE_SIZE__) || !__OPTIMIZE_SIZE__  // Auto-generated when GCC's -Os command option is used
00360   StructCPtr  rxbuf_end;
00361 #else
00362   StructCPtr  rxbuf_end;
00363 #endif  // !__OPTIMIZE_SIZE__
00364 
00365   // Initialize pointers for copy loops and limit the number of bytes to copy
00366   ep_fifo.u8ptr = pep_fifo[ep].u8ptr;
00367   rxbuf_cur.u8ptr = rxbuf;
00368   rxbuf_end.u8ptr = rxbuf_cur.u8ptr + min(data_length, Usb_byte_count(ep));
00369 #if (!defined __OPTIMIZE_SIZE__) || !__OPTIMIZE_SIZE__  // Auto-generated when GCC's -Os command option is used
00370   rxbuf_end.u16ptr = (U16 *)Align_down((U32)rxbuf_end.u8ptr, sizeof(U16));
00371   rxbuf_end.u32ptr = (U32 *)Align_down((U32)rxbuf_end.u16ptr, sizeof(U32));
00372   rxbuf_end.u64ptr = (U64 *)Align_down((U32)rxbuf_end.u32ptr, sizeof(U64));
00373 
00374   // If all addresses are aligned the same way with respect to 16-bit boundaries
00375   if (Get_align((U32)rxbuf_cur.u8ptr, sizeof(U16)) == Get_align((U32)ep_fifo.u8ptr, sizeof(U16)))
00376   {
00377     // If pointer to reception buffer is not 16-bit aligned
00378     if (!Test_align((U32)rxbuf_cur.u8ptr, sizeof(U16)))
00379     {
00380       // Copy 8-bit data to reach 16-bit alignment
00381       if (rxbuf_cur.u8ptr < rxbuf_end.u8ptr)
00382       {
00383         // 8-bit accesses to FIFO data registers do require pointer post-increment
00384         *rxbuf_cur.u8ptr++ = *ep_fifo.u8ptr++;
00385       }
00386     }
00387 
00388     // If all addresses are aligned the same way with respect to 32-bit boundaries
00389     if (Get_align((U32)rxbuf_cur.u16ptr, sizeof(U32)) == Get_align((U32)ep_fifo.u16ptr, sizeof(U32)))
00390     {
00391       // If pointer to reception buffer is not 32-bit aligned
00392       if (!Test_align((U32)rxbuf_cur.u16ptr, sizeof(U32)))
00393       {
00394         // Copy 16-bit data to reach 32-bit alignment
00395         if (rxbuf_cur.u16ptr < rxbuf_end.u16ptr)
00396         {
00397           // 16-bit accesses to FIFO data registers do require pointer post-increment
00398           *rxbuf_cur.u16ptr++ = *ep_fifo.u16ptr++;
00399         }
00400       }
00401 
00402       // If pointer to reception buffer is not 64-bit aligned
00403       if (!Test_align((U32)rxbuf_cur.u32ptr, sizeof(U64)))
00404       {
00405         // Copy 32-bit data to reach 64-bit alignment
00406         if (rxbuf_cur.u32ptr < rxbuf_end.u32ptr)
00407         {
00408           // 32-bit accesses to FIFO data registers do not require pointer post-increment
00409           *rxbuf_cur.u32ptr++ = *ep_fifo.u32ptr;
00410         }
00411       }
00412 
00413       // Copy 64-bit-aligned data
00414       while (rxbuf_cur.u64ptr < rxbuf_end.u64ptr)
00415       {
00416         // 64-bit accesses to FIFO data registers do not require pointer post-increment
00417         *rxbuf_cur.u64ptr++ = *ep_fifo.u64ptr;
00418       }
00419 
00420       // Copy 32-bit-aligned data
00421       if (rxbuf_cur.u32ptr < rxbuf_end.u32ptr)
00422       {
00423         // 32-bit accesses to FIFO data registers do not require pointer post-increment
00424         *rxbuf_cur.u32ptr++ = *ep_fifo.u32ptr;
00425       }
00426     }
00427 
00428     // Copy remaining 16-bit data if some
00429     while (rxbuf_cur.u16ptr < rxbuf_end.u16ptr)
00430     {
00431       // 16-bit accesses to FIFO data registers do require pointer post-increment
00432       *rxbuf_cur.u16ptr++ = *ep_fifo.u16ptr++;
00433     }
00434   }
00435 
00436 #endif  // !__OPTIMIZE_SIZE__
00437 
00438   // Copy remaining 8-bit data if some
00439   while (rxbuf_cur.u8ptr < rxbuf_end.u8ptr)
00440   {
00441     // 8-bit accesses to FIFO data registers do require pointer post-increment
00442     *rxbuf_cur.u8ptr++ = *ep_fifo.u8ptr++;
00443   }
00444 
00445   // Save current position in FIFO data register
00446   pep_fifo[ep].u8ptr = (volatile U8 *)ep_fifo.u8ptr;
00447 
00448   // Return the updated buffer address and the number of non-copied bytes
00449   if (prxbuf) *prxbuf = rxbuf_cur.u8ptr;
00450   return data_length - (rxbuf_cur.u8ptr - (U8 *)rxbuf);
00451 }

U32 usb_set_ep_txpacket ( U8  ep,
U8  txbyte,
U32  data_length 
)

usb_set_ep_txpacket

This function fills the selected endpoint FIFO with a constant byte, using as few accesses as possible.

Parameters:
ep Number of the addressed endpoint
txbyte Byte to fill the endpoint with
data_length Number of bytes to write
Returns:
Number of non-written bytes
Note:
The selected endpoint FIFO may be filled in several steps by calling usb_set_ep_txpacket several times.
Warning:
Invoke Usb_reset_endpoint_fifo_access before this function when at FIFO beginning whether or not the FIFO is to be filled in several steps.

Do not mix calls to this function with calls to indexed macros.

Definition at line 110 of file usb_drv.c.

References pep_fifo, Usb_byte_count, and Usb_get_endpoint_size.

00111 {
00112   // Use aggregated pointers to have several alignments available for a same address
00113   UnionVPtr   ep_fifo_cur;
00114 #if (!defined __OPTIMIZE_SIZE__) || !__OPTIMIZE_SIZE__  // Auto-generated when GCC's -Os command option is used
00115   StructCVPtr ep_fifo_end;
00116   Union64     txval;
00117 #else
00118   UnionCVPtr  ep_fifo_end;
00119   union
00120   {
00121     U8 u8[1];
00122   } txval;
00123 #endif  // !__OPTIMIZE_SIZE__
00124 
00125   // Initialize pointers for write loops and limit the number of bytes to write
00126   ep_fifo_cur.u8ptr = pep_fifo[ep].u8ptr;
00127   ep_fifo_end.u8ptr = ep_fifo_cur.u8ptr +
00128                       min(data_length, Usb_get_endpoint_size(ep) - Usb_byte_count(ep));
00129 #if (!defined __OPTIMIZE_SIZE__) || !__OPTIMIZE_SIZE__  // Auto-generated when GCC's -Os command option is used
00130   ep_fifo_end.u16ptr = (U16 *)Align_down((U32)ep_fifo_end.u8ptr, sizeof(U16));
00131   ep_fifo_end.u32ptr = (U32 *)Align_down((U32)ep_fifo_end.u16ptr, sizeof(U32));
00132   ep_fifo_end.u64ptr = (U64 *)Align_down((U32)ep_fifo_end.u32ptr, sizeof(U64));
00133 #endif  // !__OPTIMIZE_SIZE__
00134   txval.u8[0] = txbyte;
00135 #if (!defined __OPTIMIZE_SIZE__) || !__OPTIMIZE_SIZE__  // Auto-generated when GCC's -Os command option is used
00136   txval.u8[1] = txval.u8[0];
00137   txval.u16[1] = txval.u16[0];
00138   txval.u32[1] = txval.u32[0];
00139 
00140   // If pointer to FIFO data register is not 16-bit aligned
00141   if (!Test_align((U32)ep_fifo_cur.u8ptr, sizeof(U16)))
00142   {
00143     // Write 8-bit data to reach 16-bit alignment
00144     if (ep_fifo_cur.u8ptr < ep_fifo_end.u8ptr)
00145     {
00146       *ep_fifo_cur.u8ptr++ = txval.u8[0];
00147     }
00148   }
00149 
00150   // If pointer to FIFO data register is not 32-bit aligned
00151   if (!Test_align((U32)ep_fifo_cur.u16ptr, sizeof(U32)))
00152   {
00153     // Write 16-bit data to reach 32-bit alignment
00154     if (ep_fifo_cur.u16ptr < ep_fifo_end.u16ptr)
00155     {
00156       *ep_fifo_cur.u16ptr++ = txval.u16[0];
00157     }
00158   }
00159 
00160   // If pointer to FIFO data register is not 64-bit aligned
00161   if (!Test_align((U32)ep_fifo_cur.u32ptr, sizeof(U64)))
00162   {
00163     // Write 32-bit data to reach 64-bit alignment
00164     if (ep_fifo_cur.u32ptr < ep_fifo_end.u32ptr)
00165     {
00166       *ep_fifo_cur.u32ptr++ = txval.u32[0];
00167     }
00168   }
00169 
00170   // Write 64-bit-aligned data
00171   while (ep_fifo_cur.u64ptr < ep_fifo_end.u64ptr)
00172   {
00173     *ep_fifo_cur.u64ptr++ = txval.u64;
00174   }
00175 
00176   // Write remaining 32-bit data if some
00177   if (ep_fifo_cur.u32ptr < ep_fifo_end.u32ptr)
00178   {
00179     *ep_fifo_cur.u32ptr++ = txval.u32[0];
00180   }
00181 
00182   // Write remaining 16-bit data if some
00183   if (ep_fifo_cur.u16ptr < ep_fifo_end.u16ptr)
00184   {
00185     *ep_fifo_cur.u16ptr++ = txval.u16[0];
00186   }
00187 
00188   // Write remaining 8-bit data if some
00189   if (ep_fifo_cur.u8ptr < ep_fifo_end.u8ptr)
00190   {
00191     *ep_fifo_cur.u8ptr++ = txval.u8[0];
00192   }
00193 
00194 #else
00195 
00196   // Write remaining 8-bit data if some
00197   while (ep_fifo_cur.u8ptr < ep_fifo_end.u8ptr)
00198   {
00199     *ep_fifo_cur.u8ptr++ = txval.u8[0];
00200   }
00201 
00202 #endif  // !__OPTIMIZE_SIZE__
00203 
00204   // Compute the number of non-written bytes
00205   data_length -= ep_fifo_cur.u8ptr - pep_fifo[ep].u8ptr;
00206 
00207   // Save current position in FIFO data register
00208   pep_fifo[ep].u8ptr = ep_fifo_cur.u8ptr;
00209 
00210   // Return the number of non-written bytes
00211   return data_length;
00212 }

U32 usb_write_ep_txpacket ( U8  ep,
const void *  txbuf,
U32  data_length,
const void **  ptxbuf 
)

usb_write_ep_txpacket

This function writes the buffer pointed to by txbuf to the selected endpoint FIFO, using as few accesses as possible.

Parameters:
ep Number of the addressed endpoint
txbuf Address of buffer to read
data_length Number of bytes to write
ptxbuf NULL or pointer to the buffer address to update
Returns:
Number of non-written bytes
Note:
The selected endpoint FIFO may be written in several steps by calling usb_write_ep_txpacket several times.
Warning:
Invoke Usb_reset_endpoint_fifo_access before this function when at FIFO beginning whether or not the FIFO is to be written in several steps.

Do not mix calls to this function with calls to indexed macros.

Definition at line 234 of file usb_drv.c.

References pep_fifo, Usb_byte_count, and Usb_get_endpoint_size.

Referenced by device_template_task(), usb_get_descriptor(), and usb_set_feature().

00235 {
00236   // Use aggregated pointers to have several alignments available for a same address
00237   UnionVPtr   ep_fifo;
00238   UnionCPtr   txbuf_cur;
00239 #if (!defined __OPTIMIZE_SIZE__) || !__OPTIMIZE_SIZE__  // Auto-generated when GCC's -Os command option is used
00240   StructCPtr  txbuf_end;
00241 #else
00242   UnionCPtr   txbuf_end;
00243 #endif  // !__OPTIMIZE_SIZE__
00244 
00245   // Initialize pointers for copy loops and limit the number of bytes to copy
00246   ep_fifo.u8ptr = pep_fifo[ep].u8ptr;
00247   txbuf_cur.u8ptr = txbuf;
00248   txbuf_end.u8ptr = txbuf_cur.u8ptr +
00249                     min(data_length, Usb_get_endpoint_size(ep) - Usb_byte_count(ep));
00250 #if (!defined __OPTIMIZE_SIZE__) || !__OPTIMIZE_SIZE__  // Auto-generated when GCC's -Os command option is used
00251   txbuf_end.u16ptr = (U16 *)Align_down((U32)txbuf_end.u8ptr, sizeof(U16));
00252   txbuf_end.u32ptr = (U32 *)Align_down((U32)txbuf_end.u16ptr, sizeof(U32));
00253   txbuf_end.u64ptr = (U64 *)Align_down((U32)txbuf_end.u32ptr, sizeof(U64));
00254 
00255   // If all addresses are aligned the same way with respect to 16-bit boundaries
00256   if (Get_align((U32)txbuf_cur.u8ptr, sizeof(U16)) == Get_align((U32)ep_fifo.u8ptr, sizeof(U16)))
00257   {
00258     // If pointer to transmission buffer is not 16-bit aligned
00259     if (!Test_align((U32)txbuf_cur.u8ptr, sizeof(U16)))
00260     {
00261       // Copy 8-bit data to reach 16-bit alignment
00262       if (txbuf_cur.u8ptr < txbuf_end.u8ptr)
00263       {
00264         // 8-bit accesses to FIFO data registers do require pointer post-increment
00265         *ep_fifo.u8ptr++ = *txbuf_cur.u8ptr++;
00266       }
00267     }
00268 
00269     // If all addresses are aligned the same way with respect to 32-bit boundaries
00270     if (Get_align((U32)txbuf_cur.u16ptr, sizeof(U32)) == Get_align((U32)ep_fifo.u16ptr, sizeof(U32)))
00271     {
00272       // If pointer to transmission buffer is not 32-bit aligned
00273       if (!Test_align((U32)txbuf_cur.u16ptr, sizeof(U32)))
00274       {
00275         // Copy 16-bit data to reach 32-bit alignment
00276         if (txbuf_cur.u16ptr < txbuf_end.u16ptr)
00277         {
00278           // 16-bit accesses to FIFO data registers do require pointer post-increment
00279           *ep_fifo.u16ptr++ = *txbuf_cur.u16ptr++;
00280         }
00281       }
00282 
00283       // If pointer to transmission buffer is not 64-bit aligned
00284       if (!Test_align((U32)txbuf_cur.u32ptr, sizeof(U64)))
00285       {
00286         // Copy 32-bit data to reach 64-bit alignment
00287         if (txbuf_cur.u32ptr < txbuf_end.u32ptr)
00288         {
00289           // 32-bit accesses to FIFO data registers do not require pointer post-increment
00290           *ep_fifo.u32ptr = *txbuf_cur.u32ptr++;
00291         }
00292       }
00293 
00294       // Copy 64-bit-aligned data
00295       while (txbuf_cur.u64ptr < txbuf_end.u64ptr)
00296       {
00297         // 64-bit accesses to FIFO data registers do not require pointer post-increment
00298         *ep_fifo.u64ptr = *txbuf_cur.u64ptr++;
00299       }
00300 
00301       // Copy 32-bit-aligned data
00302       if (txbuf_cur.u32ptr < txbuf_end.u32ptr)
00303       {
00304         // 32-bit accesses to FIFO data registers do not require pointer post-increment
00305         *ep_fifo.u32ptr = *txbuf_cur.u32ptr++;
00306       }
00307     }
00308 
00309     // Copy remaining 16-bit data if some
00310     while (txbuf_cur.u16ptr < txbuf_end.u16ptr)
00311     {
00312       // 16-bit accesses to FIFO data registers do require pointer post-increment
00313       *ep_fifo.u16ptr++ = *txbuf_cur.u16ptr++;
00314     }
00315   }
00316 
00317 #endif  // !__OPTIMIZE_SIZE__
00318 
00319   // Copy remaining 8-bit data if some
00320   while (txbuf_cur.u8ptr < txbuf_end.u8ptr)
00321   {
00322     // 8-bit accesses to FIFO data registers do require pointer post-increment
00323     *ep_fifo.u8ptr++ = *txbuf_cur.u8ptr++;
00324   }
00325 
00326   // Save current position in FIFO data register
00327   pep_fifo[ep].u8ptr = ep_fifo.u8ptr;
00328 
00329   // Return the updated buffer address and the number of non-copied bytes
00330   if (ptxbuf) *ptxbuf = txbuf_cur.u8ptr;
00331   return data_length - (txbuf_cur.u8ptr - (U8 *)txbuf);
00332 }


Variable Documentation

UnionVPtr pep_fifo[MAX_PEP_NB]

Pointers to the FIFO data registers of pipes/endpoints Use aggregated pointers to have several alignments available for a same address.

Todo:
Implement macros for pipe DMA registers and descriptors

Definition at line 64 of file usb_drv.c.

Referenced by host_read_p_rxpacket(), host_set_p_txpacket(), host_write_p_txpacket(), usb_read_ep_rxpacket(), usb_set_ep_txpacket(), and usb_write_ep_txpacket().


Generated on Fri Feb 19 02:27:51 2010 for AVR32 - USB Enumeration Example by  doxygen 1.5.5