00001 /* 00002 FreeRTOS.org V4.6.0 - Copyright (C) 2003-2007 Richard Barry. 00003 00004 This file is part of the FreeRTOS.org distribution. 00005 00006 FreeRTOS.org is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 FreeRTOS.org is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with FreeRTOS.org; if not, write to the Free Software 00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 00020 A special exception to the GPL can be applied should you wish to distribute 00021 a combined work that includes FreeRTOS.org, without being obliged to provide 00022 the source code for any proprietary components. See the licensing section 00023 of http://www.FreeRTOS.org for full details of how and when the exception 00024 can be applied. 00025 00026 *************************************************************************** 00027 See http://www.FreeRTOS.org for documentation, latest information, license 00028 and contact details. Please ensure to read the configuration and relevant 00029 port sections of the online documentation. 00030 *************************************************************************** 00031 */ 00032 00033 00034 /* 00035 BASIC INTERRUPT DRIVEN DRIVER FOR USB. 00036 00037 This file contains all the usb components that must be compiled 00038 to ARM mode. The components that can be compiled to either ARM or THUMB 00039 mode are contained in USB-CDC.c. 00040 00041 */ 00042 00043 /* MakingThings */ 00044 #include "config.h" 00045 #ifdef MAKE_CTRL_USB 00046 00047 #include "FreeRTOS.h" 00048 #include "task.h" 00049 #include "queue.h" 00050 #include "Board.h" 00051 // MakingThings: renamed 00052 #include "usb_internal.h" 00053 #include "USB-CDC.h" 00054 00055 #define usbINT_CLEAR_MASK (AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP | AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 ) 00056 /*-----------------------------------------------------------*/ 00057 00058 /* Messages and queue used to communicate between the ISR and the USB task. */ 00059 static xISRStatus xISRMessages[ usbQUEUE_LENGTH + 1 ]; 00060 extern xQueueHandle xUSBInterruptQueue; 00061 /*-----------------------------------------------------------*/ 00062 00063 /* The ISR can cause a context switch so is declared naked. */ 00064 void vUSB_ISR_Wrapper( void ) __attribute__ ((naked)); 00065 00066 /* The function that actually performs the ISR work. This must be separate 00067 from the wrapper function to ensure the correct stack frame gets set up. */ 00068 void vUSB_ISR_Handler( void ); 00069 /*-----------------------------------------------------------*/ 00070 00071 void vUSB_ISR_Handler( void ) 00072 { 00073 portCHAR cTaskWokenByPost = pdFALSE; 00074 static volatile unsigned portLONG ulNextMessage = 0; 00075 xISRStatus *pxMessage; 00076 unsigned portLONG ulRxBytes; 00077 unsigned portCHAR ucFifoIndex; 00078 00079 /* Use the next message from the array. */ 00080 pxMessage = &( xISRMessages[ ( ulNextMessage & usbQUEUE_LENGTH ) ] ); 00081 ulNextMessage++; 00082 00083 /* Save UDP ISR state for task-level processing. */ 00084 pxMessage->ulISR = AT91C_BASE_UDP->UDP_ISR; 00085 pxMessage->ulCSR0 = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ]; 00086 00087 /* Clear interrupts from ICR. */ 00088 AT91C_BASE_UDP->UDP_ICR = AT91C_BASE_UDP->UDP_IMR | AT91C_UDP_ENDBUSRES; 00089 00090 00091 /* Process incoming FIFO data. Must set DIR (if needed) and clear RXSETUP 00092 before exit. */ 00093 00094 /* Read CSR and get incoming byte count. */ 00095 ulRxBytes = ( pxMessage->ulCSR0 >> 16 ) & usbRX_COUNT_MASK; 00096 00097 /* Receive control transfers on endpoint 0. */ 00098 if( pxMessage->ulCSR0 & ( AT91C_UDP_RXSETUP | AT91C_UDP_RX_DATA_BK0 ) ) 00099 { 00100 /* Save FIFO data buffer for either a SETUP or DATA stage */ 00101 for( ucFifoIndex = 0; ucFifoIndex < ulRxBytes; ucFifoIndex++ ) 00102 { 00103 pxMessage->ucFifoData[ ucFifoIndex ] = AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_0 ]; 00104 } 00105 00106 /* Set direction for data stage. Must be done before RXSETUP is 00107 cleared. */ 00108 if( ( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_RXSETUP ) ) 00109 { 00110 if( ulRxBytes && ( pxMessage->ucFifoData[ usbREQUEST_TYPE_INDEX ] & 0x80 ) ) 00111 { 00112 AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] |= AT91C_UDP_DIR; 00113 00114 /* Might not be wise in an ISR! */ 00115 while( !(AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_DIR) ); 00116 } 00117 00118 /* Clear RXSETUP */ 00119 AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] &= ~AT91C_UDP_RXSETUP; 00120 00121 /* Might not be wise in an ISR! */ 00122 while ( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_RXSETUP ); 00123 } 00124 else 00125 { 00126 /* Clear RX_DATA_BK0 */ 00127 AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] &= ~AT91C_UDP_RX_DATA_BK0; 00128 00129 /* Might not be wise in an ISR! */ 00130 while ( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_RX_DATA_BK0 ); 00131 } 00132 } 00133 00134 /* If we received data on endpoint 1, disable its interrupts until it is 00135 processed in the main loop */ 00136 if( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] & ( AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 ) ) 00137 { 00138 AT91C_BASE_UDP->UDP_IDR = AT91C_UDP_EPINT1; 00139 } 00140 00141 AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] &= ~( AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT ); 00142 00143 /* Clear interrupts for the other endpoints, retain data flags for endpoint 00144 1. */ 00145 AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] &= ~( AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP ); 00146 AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_2 ] &= ~usbINT_CLEAR_MASK; 00147 AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_3 ] &= ~usbINT_CLEAR_MASK; 00148 00149 /* Post ISR data to queue for task-level processing */ 00150 cTaskWokenByPost = xQueueSendFromISR( xUSBInterruptQueue, &pxMessage, cTaskWokenByPost ); 00151 00152 /* Clear AIC to complete ISR processing */ 00153 AT91C_BASE_AIC->AIC_EOICR = 0; 00154 00155 /* Do a task switch if needed */ 00156 if( cTaskWokenByPost ) 00157 { 00158 /* This call will ensure that the unblocked task will be executed 00159 immediately upon completion of the ISR if it has a priority higher 00160 than the interrupted task. */ 00161 portYIELD_FROM_ISR(); 00162 } 00163 } 00164 /*-----------------------------------------------------------*/ 00165 00166 void vUSB_ISR_Wrapper( void ) 00167 { 00168 /* Save the context of the interrupted task. */ 00169 portSAVE_CONTEXT(); 00170 00171 /* Call the handler to do the work. This must be a separate 00172 function to ensure the stack frame is set up correctly. */ 00173 vUSB_ISR_Handler(); 00174 00175 /* Restore the context of whichever task will execute next. */ 00176 portRESTORE_CONTEXT(); 00177 } 00178 00179 #endif // MAKE_CTRL_USB 00180
The Make Controller Kit is an open source project maintained by MakingThings.
MakingThings code is released under the Apache 2.0 license.
Bug tracker, development wiki and status can be found at http://dev.makingthings.com.
This document was last updated on 18 May 2009.