MakingThings
  • Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

serial_isr.c

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.