00001 /********************************************************************************* 00002 00003 Copyright 2006-2008 MakingThings 00004 00005 Licensed under the Apache License, 00006 Version 2.0 (the "License"); you may not use this file except in compliance 00007 with the License. You may obtain a copy of the License at 00008 00009 http://www.apache.org/licenses/LICENSE-2.0 00010 00011 Unless required by applicable law or agreed to in writing, software distributed 00012 under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 00013 CONDITIONS OF ANY KIND, either express or implied. See the License for 00014 the specific language governing permissions and limitations under the License. 00015 00016 *********************************************************************************/ 00017 00018 /* 00019 BASIC INTERRUPT DRIVEN DRIVER FOR SERIAL PORT. 00020 00021 This file contains all the components that must be compiled 00022 to ARM mode. The components that can be compiled to either ARM or THUMB 00023 mode are contained in Serial.c 00024 00025 */ 00026 00027 /* Scheduler includes. */ 00028 #include "FreeRTOS.h" 00029 #include "task.h" 00030 #include "queue.h" 00031 #include "semphr.h" 00032 #include "Board.h" 00033 #include "serial_internal.h" 00034 00035 /*-----------------------------------------------------------*/ 00036 00037 extern Serial_ Serial[ SERIAL_PORTS ]; 00038 00039 /*-----------------------------------------------------------*/ 00040 00041 /* The interrupt entry point is naked so we can control the context saving. */ 00042 void SerialIsr_Wrapper( void ) __attribute__ ((naked)); 00043 00044 /* The interrupt handler function must be separate from the entry function 00045 to ensure the correct stack frame is set up. */ 00046 void SerialIsr_Handler( void ); 00047 00048 /*-----------------------------------------------------------*/ 00049 00050 void SerialIsr_Handler( void ) 00051 { 00052 unsigned portLONG ulStatus; 00053 signed portCHAR cChar; 00054 00055 long xTaskWokenByTx = false; 00056 long xTaskWokenByPost = false; 00057 00058 int index; 00059 for ( index = 0; index < SERIAL_PORTS; index++ ) 00060 { 00061 long xTaskWokenByTxThis = false; 00062 long xTaskWokenByPostThis = false; 00063 00064 Serial_* sp = &Serial[ index ]; 00065 00066 /* What caused the interrupt? */ 00067 ulStatus = ( sp->at91UARTRegs->US_CSR ) & ( sp->at91UARTRegs->US_IMR ); 00068 00069 if( ulStatus & AT91C_US_TXRDY ) 00070 { 00071 /* The interrupt was caused by the THR becoming empty. Are there any 00072 more characters to transmit? */ 00073 if( xQueueReceiveFromISR( sp->transmitQueue, &cChar, &xTaskWokenByTx ) == pdTRUE ) 00074 { 00075 /* A character was retrieved from the queue so can be sent to the 00076 THR now. */ 00077 sp->at91UARTRegs->US_THR = cChar; 00078 } 00079 else 00080 { 00081 /* Queue empty, nothing to send so turn off the Tx interrupt. */ 00082 sp->at91UARTRegs->US_IDR = AT91C_US_TXRDY; 00083 } 00084 } 00085 00086 if( ulStatus & AT91C_US_RXRDY ) 00087 { 00088 /* The interrupt was caused by a character being received. Grab the 00089 character from the RHR and place it in the queue or received 00090 characters. */ 00091 int t = sp->at91UARTRegs->US_RHR; 00092 cChar = t & 0xFF; 00093 xTaskWokenByPost = xQueueSendFromISR( sp->receiveQueue, &cChar, xTaskWokenByPost ); 00094 } 00095 00096 xTaskWokenByTx = xTaskWokenByTx || xTaskWokenByTxThis; 00097 xTaskWokenByPost = xTaskWokenByPost || xTaskWokenByPostThis; 00098 } 00099 00100 /* End the interrupt in the AIC. */ 00101 AT91C_BASE_AIC->AIC_EOICR = 0; 00102 00103 /* If a task was woken by either a frame being received then we may need to 00104 switch to another task. If the unblocked task was of higher priority then 00105 the interrupted task it will then execute immediately that the ISR 00106 completes. */ 00107 if( xTaskWokenByPost || xTaskWokenByTx ) 00108 { 00109 portYIELD_FROM_ISR(); 00110 } 00111 } 00112 00113 void SerialIsr_Wrapper( void ) 00114 { 00115 /* Save the context of the interrupted task. */ 00116 portSAVE_CONTEXT(); 00117 00118 /* Call the handler to do the work. This must be a separate 00119 function to ensure the stack frame is set up correctly. */ 00120 SerialIsr_Handler(); 00121 00122 /* Restore the context of whichever task will execute next. */ 00123 portRESTORE_CONTEXT(); 00124 } 00125 00126
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.