- 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.