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

serial.c

Go to the documentation of this file.
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 /* Library includes. */
00019 #include <string.h>
00020 #include <stdio.h>
00021 
00022 /* Scheduler includes. */
00023 #include "FreeRTOS.h"
00024 #include "task.h"
00025 
00026 /* Hardware specific headers. */
00027 #include "Board.h"
00028 #include "AT91SAM7X256.h"
00029 
00030 #include "config.h"
00031 #include "io.h"
00032 
00033 #include "serial.h"
00034 #include "serial_internal.h"
00035 
00036 #define DEFAULT_SERIAL_Q_LEN 100
00037 Serial_ Serial[ SERIAL_PORTS ];
00038 
00039 extern void ( SerialIsr_Wrapper )( void );
00040 
00041 static int Serial_Init( int index );
00042 static int Serial_Deinit( int index );
00043 static int Serial_SetDefault( int index );
00044 static int Serial_SetDetails( int index );
00045 
00046 
00047 /** \file serial.c  
00048   Functions for working with the Serial Interface on the Make Controller Board.
00049 */
00050 
00051 /** \defgroup serial Serial
00052   Send and receive data via the Make Controller's serial ports.
00053 
00054   There are 2 full serial ports on the Make Controller, and this library provides support for both of them.
00055 
00056   Control all of the common serial characteristics including:
00057   - \b baud - the speed of the connection (110 - > 2M) in baud or raw bits per second.  9600 baud is the default setting.
00058   - \b bits - the size of each character (5 - 8).  8 bits is the default setting.
00059   - \b stopBits - the number of stop bits transmitted (1 or 2)  1 stop bit is the default setting.
00060   - \b parity - the parity policy (-1 is odd, 0 is none and 1 is even).  Even is the default setting.
00061   - \b hardwareHandshake - whether hardware handshaking is used or not.  HardwareHandshaking is off by default.
00062 
00063   The subsystem is supplied with small input and output buffers (of 100 characters each) and at present
00064   the implementation is interrupt per character so it's not particularly fast.
00065 
00066   \todo Convert to DMA interface for higher performance, and add support for debug UART
00067 
00068   \ingroup Core
00069   @{
00070 */
00071 
00072 /**
00073   Set the active state of a serial port.
00074   This is automatically set to 
00075   true by any call to Serial_Write or Serial_Read.
00076   @param index Which serial port - SERIAL_0 or SERIAL_1
00077   @param state An integer specifying the active state - 1 (on) or 0 (off).
00078   @return CONTROLLER_OK (=0) on success.
00079 */
00080 int Serial_SetActive( int index, int state )
00081 {
00082   if ( index < 0 || index >= SERIAL_PORTS )
00083     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00084 
00085   Serial_* sp = &Serial[ index ];
00086 
00087   if ( state && !sp->active )
00088     return Serial_Init( index );
00089   else if( !state && sp->active )
00090     return Serial_Deinit( index );
00091 
00092   return CONTROLLER_OK;
00093 }
00094 
00095 /**
00096   Read the active state of the Serial subsystem.
00097   @param index Which serial port - SERIAL_0 or SERIAL_1
00098   @return State - 1/non-zero (on) or 0 (off).
00099 */
00100 bool Serial_GetActive( int index )
00101 {
00102   if ( index < 0 || index >= SERIAL_PORTS )
00103     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00104 
00105   Serial_* sp = &Serial[ index ];
00106 
00107   return sp->active;
00108 }
00109 
00110 /** 
00111   Write a block of data to the Serial port.  Will block for the time specified (in ms)
00112   if the queue fills up.
00113   @param index Which serial port - SERIAL_0 or SERIAL_1
00114   @param buffer A pointer to the buffer to write from.
00115   @param count An integer specifying the number of bytes to write.
00116   @param timeout Time in milliseconds to block waiting for the queue to free up. 0 means don't wait.
00117   @return status.
00118 */
00119 int Serial_Write( int index, uchar* buffer, int count, int timeout )
00120 {
00121   if ( index < 0 || index >= SERIAL_PORTS )
00122     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00123 
00124   Serial_* sp = &Serial[ index ];
00125 
00126   if ( !sp->active )
00127   {
00128     int status = Serial_SetActive( index, 1 );
00129     if ( status != CONTROLLER_OK )
00130       return status;
00131   }
00132 
00133   // Do the business
00134   while ( count )
00135   {
00136     if( xQueueSend( sp->transmitQueue, buffer++, timeout ) == 0 ) 
00137       return CONTROLLER_ERROR_QUEUE_ERROR; 
00138     count--;
00139   }
00140    
00141   /* Turn on the Tx interrupt so the ISR will remove the character from the 
00142   queue and send it. This does not need to be in a critical section as 
00143   if the interrupt has already removed the character the next interrupt 
00144   will simply turn off the Tx interrupt again. */ 
00145   sp->at91UARTRegs->US_IER = AT91C_US_TXRDY; 
00146  
00147   return CONTROLLER_OK;
00148 }
00149 
00150 /** 
00151   Read data from the Serial port.  Will block for the time specified (in ms) if 
00152   there are insufficient characters.  Blocking can be avoided if Serial_GetReadable( )
00153   is used to determine how many characters are available to read prior to calling
00154   this function.
00155   @param index Which serial port - SERIAL_0 or SERIAL_1
00156   @param buffer A pointer to the buffer to read into.
00157   @param size An integer specifying the maximum number of bytes to read.
00158   @param timeout Time in milliseconds to block waiting for the specified number of bytes. 0 means don't wait.
00159   @return number of bytes read (>=0) or error <0 .
00160 */
00161 int Serial_Read( int index, uchar* buffer, int size, int timeout )
00162 {
00163   if ( index < 0 || index >= SERIAL_PORTS )
00164     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00165 
00166   Serial_* sp = &Serial[ index ];
00167 
00168   if ( !sp->active )
00169   {
00170     int status = Serial_SetActive( index, 1 );
00171     if ( status != CONTROLLER_OK )
00172       return status;
00173   }
00174 
00175   // Do the business
00176   int count = 0;
00177   while ( count < size )
00178   {
00179     /* Place the character in the queue of characters to be transmitted. */ 
00180     if( xQueueReceive( sp->receiveQueue, buffer++, timeout ) == 0 )
00181       break;
00182     count++;
00183   }
00184 
00185   return count;
00186 }
00187 
00188 /** 
00189   Returns the number of bytes in the queue waiting to be read.
00190   @param index Which serial port - SERIAL_0 or SERIAL_1
00191   @return bytes in the receive queue.
00192 */
00193 int Serial_GetReadable( int index )
00194 {
00195   if ( index < 0 || index >= SERIAL_PORTS )
00196     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00197 
00198   Serial_* sp = &Serial[ index ];
00199 
00200   return uxQueueMessagesWaiting( sp->receiveQueue );
00201 }
00202 
00203 /** 
00204   Sends a character (in the range of 0 to 255) to the write queue
00205   @param index Which serial port - SERIAL_0 or SERIAL_1
00206   @param character The character to be sent.  Must be 0 <= c < 256.
00207   @return status.
00208 */
00209 int Serial_SetChar( int index, int character )
00210 {
00211   if ( index < 0 || index >= SERIAL_PORTS )
00212     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00213 
00214   Serial_* sp = &Serial[ index ];
00215 
00216   if ( !sp->active )
00217   {
00218     int status = Serial_SetActive( index, 1 );
00219     if ( status != CONTROLLER_OK )
00220       return status;
00221   }
00222 
00223   if ( character >= 0 && character < 256 )
00224   {
00225     unsigned char c = (unsigned char)character;
00226     if( xQueueSend( sp->transmitQueue, &c, 0 ) == 0 ) 
00227       return CONTROLLER_ERROR_QUEUE_ERROR; 
00228     sp->at91UARTRegs->US_IER = AT91C_US_TXRDY; 
00229    }
00230 
00231   return CONTROLLER_OK;
00232 }
00233 
00234 /** 
00235   Sets the serial baud rate.
00236   @param index Which serial port - SERIAL_0 or SERIAL_1
00237   @param baud The desired baud rate.
00238   @return status.
00239 */
00240 int Serial_SetBaud( int index, int baud )
00241 {
00242   if ( index < 0 || index >= SERIAL_PORTS )
00243     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00244 
00245   Serial_* sp = &Serial[ index ];
00246 
00247   // If there are no default values, get some
00248   if ( !sp->detailsInitialized )
00249     Serial_SetDefault( index );
00250 
00251   sp->baud = baud;
00252   Serial_SetDetails( index );
00253 
00254   return CONTROLLER_OK;
00255 }
00256 
00257 /** 
00258   Sets the number of bits per character.  5 - 8 are legal values.  8 is the default.
00259   @param index Which serial port - SERIAL_0 or SERIAL_1
00260   @param bits bits per character
00261   @return status.
00262 */
00263 int Serial_SetBits( int index, int bits )
00264 {
00265   if ( index < 0 || index >= SERIAL_PORTS )
00266     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00267 
00268   Serial_* sp = &Serial[ index ];
00269 
00270   // If there are no default values, get some
00271   if ( !sp->detailsInitialized )
00272     Serial_SetDefault( index );
00273 
00274   if ( sp->bits >= 5 && sp->bits <= 8 )
00275     sp->bits = bits;
00276   else
00277     sp->bits = 8;
00278 
00279   Serial_SetDetails( index );
00280 
00281   return CONTROLLER_OK;
00282 }
00283 
00284 /** 
00285   Sets the parity.  -1 is odd, 0 is none, 1 is even.  The default is none - 0.
00286   @param index Which serial port - SERIAL_0 or SERIAL_1
00287   @param parity -1, 0 or 1.
00288   @return status.
00289 */
00290 int Serial_SetParity( int index, int parity )
00291 {
00292   if ( index < 0 || index >= SERIAL_PORTS )
00293     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00294 
00295   Serial_* sp = &Serial[ index ];
00296 
00297   // If there are no default values, get some
00298   if ( !sp->detailsInitialized )
00299     Serial_SetDefault( index );
00300 
00301   if ( parity >= -1 && parity <= 1 )
00302     sp->parity = parity;
00303   else
00304     sp->parity = 1;
00305   Serial_SetDetails( index );
00306 
00307   return CONTROLLER_OK;
00308 }
00309 
00310 /** 
00311   Sets the stop bits per character.  1 or 2 are legal values.  1 is the default.
00312   @param index Which serial port - SERIAL_0 or SERIAL_1
00313   @param stopBits stop bits per character
00314   @return status.
00315 */
00316 int Serial_SetStopBits( int index, int stopBits )
00317 {
00318   if ( index < 0 || index >= SERIAL_PORTS )
00319     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00320 
00321   Serial_* sp = &Serial[ index ];
00322 
00323   // If there are no default values, get some
00324   if ( !sp->detailsInitialized )
00325     Serial_SetDefault( index );
00326 
00327   if ( stopBits == 1 || stopBits == 2 )
00328     sp->stopBits = stopBits;
00329   else
00330     sp->stopBits = 1;
00331 
00332   Serial_SetDetails( index );
00333 
00334   return CONTROLLER_OK;
00335 }
00336 
00337 /** 
00338   Sets whether hardware handshaking is being used.
00339   @param index Which serial port - SERIAL_0 or SERIAL_1
00340   @param hardwareHandshake sets hardware handshaking on (1) or off (0)
00341   @return status.
00342 */
00343 int Serial_SetHardwareHandshake( int index, int hardwareHandshake )
00344 {
00345   if ( index < 0 || index >= SERIAL_PORTS )
00346     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00347 
00348   Serial_* sp = &Serial[ index ];
00349 
00350   // If there are no default values, get some
00351   if ( !sp->detailsInitialized )
00352     Serial_SetDefault( index );
00353 
00354   sp->hardwareHandshake = hardwareHandshake;
00355   Serial_SetDetails( index );
00356   
00357   return CONTROLLER_OK;
00358 }
00359 
00360 /** 
00361   Returns a single character from the receive queue if available.
00362   This character is returned unsigned - i.e. having a value of 0 - 255.  
00363   The return value is -1 if there is no character waiting.
00364   @param index Which serial port - SERIAL_0 or SERIAL_1
00365   @return character from the queue or -1 if there is no character.
00366 */
00367 int Serial_GetChar( int index )
00368 {
00369   if ( index < 0 || index >= SERIAL_PORTS )
00370     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00371 
00372   Serial_* sp = &Serial[ index ];
00373 
00374   if ( !sp->active )
00375   {
00376     int status = Serial_SetActive( index, 1 );
00377     if ( status != CONTROLLER_OK )
00378       return -1;
00379   }
00380 
00381   if ( uxQueueMessagesWaiting( sp->receiveQueue ) )
00382   {
00383     unsigned char c;
00384     if( xQueueReceive( sp->receiveQueue, &c, 0 ) == 0 )
00385       return -1;
00386     else
00387       return (int)c;
00388   }
00389   else
00390     return -1; 
00391 }
00392 
00393 /** 
00394   Returns the current baud rate
00395   @param index Which serial port - SERIAL_0 or SERIAL_1
00396   @return baud
00397 */
00398 int Serial_GetBaud( int index )
00399 {
00400   if ( index < 0 || index >= SERIAL_PORTS )
00401     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00402 
00403   Serial_* sp = &Serial[ index ];
00404 
00405   // If there are no default values, get some
00406   if ( !sp->detailsInitialized )
00407     Serial_SetDefault( index );
00408 
00409   return sp->baud;
00410 }
00411 
00412 /** 
00413   Returns the number of bits for each character
00414   @param index Which serial port - SERIAL_0 or SERIAL_1
00415   @return bits
00416 */
00417 int Serial_GetBits( int index )
00418 {
00419   if ( index < 0 || index >= SERIAL_PORTS )
00420     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00421 
00422   Serial_* sp = &Serial[ index ];
00423 
00424   // If there are no default values, get some
00425   if ( !sp->detailsInitialized )
00426     Serial_SetDefault( index );
00427 
00428   return sp->bits;
00429 }
00430 
00431 /** 
00432   Returns the current parity.  -1 means odd, 0 means none, 1 means even
00433   @param index Which serial port - SERIAL_0 or SERIAL_1
00434   @return parity
00435 */
00436 int Serial_GetParity( int index )
00437 {
00438   if ( index < 0 || index >= SERIAL_PORTS )
00439     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00440 
00441   Serial_* sp = &Serial[ index ];
00442 
00443   // If there are no default values, get some
00444   if ( !sp->detailsInitialized )
00445     Serial_SetDefault( index );
00446 
00447   return sp->parity;
00448 }
00449 
00450 /** 
00451   Returns the number of stop bits.
00452   @param index Which serial port - SERIAL_0 or SERIAL_1
00453   @return stopBits
00454 */
00455 int Serial_GetStopBits( int index )
00456 {
00457   if ( index < 0 || index >= SERIAL_PORTS )
00458     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00459 
00460   Serial_* sp = &Serial[ index ];
00461 
00462   // If there are no default values, get some
00463   if ( !sp->detailsInitialized )
00464     Serial_SetDefault( index );
00465 
00466   return sp->stopBits;
00467 }
00468 
00469 /** 
00470   Returns whether hardware handshaking is being employed or not.
00471   @param index Which serial port - SERIAL_0 or SERIAL_1
00472   @return hardwareHandshake
00473 */
00474 int Serial_GetHardwareHandshake( int index )
00475 {
00476   if ( index < 0 || index >= SERIAL_PORTS )
00477     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00478 
00479   Serial_* sp = &Serial[ index ];
00480 
00481   // If there are no default values, get some
00482   if ( !sp->detailsInitialized )
00483     Serial_SetDefault( index );
00484 
00485   return sp->hardwareHandshake;
00486 }
00487 
00488 /**
00489   Clear out the serial port.
00490   Ensures that there are no bytes in the incoming buffer.
00491   @param index Which serial port - SERIAL_0 or SERIAL_1
00492 
00493   \b Example
00494   \code
00495   Serial_SetActive(SERIAL_0, 1);
00496   Serial_Flush(SERIAL_0); // after starting up, make sure there's no junk in there
00497   \endcode
00498 */
00499 void Serial_Flush( int index )
00500 {
00501   char c;
00502   if ( index < 0 || index >= SERIAL_PORTS )
00503     return;
00504 
00505   while( Serial_GetReadable( index ) )
00506     c = Serial_GetChar( index );
00507 }
00508 
00509 /**
00510   Reset the error flags in the serial system.
00511   In the normal course of operation, the serial system may experience
00512   a variety of different error modes, including buffer overruns, framing 
00513   and parity errors, and more.  When in an error state, the serial system
00514   may behave differently than normal.
00515 
00516   Serial_ClearErrors() resets the appropriate status bits to a state of
00517   normal operation.  It will only reset the error states if there are 
00518   currently any errors.
00519   @param index Which serial port - SERIAL_0 or SERIAL_1
00520   @see Serial_GetErrors
00521   
00522   \b Example
00523 
00524   \code 
00525   Serial_ClearErrors(SERIAL_0);
00526   // that's all there is to it.
00527   \endcode
00528 */
00529 void Serial_ClearErrors( int index )
00530 {
00531   if ( index < 0 || index >= SERIAL_PORTS )
00532     return;
00533   
00534   Serial_* sp = &Serial[ index ];
00535   if( sp->at91UARTRegs->US_CSR & (AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE) )
00536     sp->at91UARTRegs->US_CR = AT91C_US_RSTSTA; // clear all errors
00537 }
00538 
00539 /**
00540   Read whether there are any errors.
00541   We can check for three kinds of errors in the serial system:
00542   - buffer overrun
00543   - framing error
00544   - parity error
00545   
00546   Each parameter will be set with a true or a false given the current
00547   error state.  If you don't care to check one of the parameters, just
00548   pass in 0.
00549   
00550   @param index Which serial port - SERIAL_0 or SERIAL_1
00551   @param overrun A bool that will be set with the overrun error state.
00552   @param frame A bool that will be set with the frame error state.
00553   @param parity A bool that will be set with the parity error state.
00554   @return True if there were any errors, false if there were no errors.
00555   @see Serial_ClearErrors( )
00556 
00557   \b Example
00558   \code
00559   bool over, fr, par;
00560   if( Serial_GetErrors( SERIAL_0, &over, &fr, &par ) )
00561   {
00562     // if we wanted, we could just clear them all right here with Serial_ClearErrors()
00563     // but here we'll check to see what kind of errors we got
00564     if(over)
00565     {
00566       // then we have an overrun error
00567     }
00568     if(fr)
00569     {
00570       // then we have a framing error
00571     }
00572     if(par)
00573     {
00574       // then we have a parity error
00575     }
00576   }
00577   else
00578   {
00579     // there were no errors
00580   }
00581   \endcode
00582 */
00583 bool Serial_GetErrors( int index, bool* overrun, bool* frame, bool* parity )
00584 {
00585   bool retval = false;
00586   if ( index < 0 || index >= SERIAL_PORTS )
00587     return false;
00588   
00589   Serial_* sp = &Serial[ index ];
00590 
00591   bool ovre = sp->at91UARTRegs->US_CSR & AT91C_US_OVRE;
00592   if(ovre)
00593     retval = true;
00594   if(overrun)
00595     *overrun = ovre;
00596 
00597   bool fr = sp->at91UARTRegs->US_CSR & AT91C_US_FRAME;
00598   if(fr)
00599     retval = true;
00600   if(frame)
00601     *frame = fr;
00602 
00603   bool par = sp->at91UARTRegs->US_CSR & AT91C_US_PARE;
00604   if(par)
00605     retval = true;
00606   if(parity)
00607     *parity = par;
00608   
00609   return retval;
00610 }
00611 
00612 /**
00613   Start the transimission of a break.
00614   This has no effect if a break is already in progress.
00615   @param index Which serial port - SERIAL_0 or SERIAL_1
00616 
00617   \b Example
00618   
00619   \code 
00620   Serial_StartBreak(SERIAL_0);
00621   \endcode
00622 */
00623 void Serial_StartBreak( int index )
00624 {
00625   if ( index < 0 || index >= SERIAL_PORTS )
00626     return;
00627   Serial[ index ].at91UARTRegs->US_CR = AT91C_US_STTBRK;
00628 }
00629 
00630 /**
00631   Stop the transimission of a break.
00632   This has no effect if there's not a break already in progress.
00633   @param index Which serial port - SERIAL_0 or SERIAL_1
00634 
00635   \b Example
00636   
00637   \code 
00638   Serial_StopBreak(SERIAL_0);
00639   \endcode
00640 */
00641 void Serial_StopBreak( int index )
00642 {
00643   if ( index < 0 || index >= SERIAL_PORTS )
00644     return;
00645   Serial[ index ].at91UARTRegs->US_CR = AT91C_US_STPBRK;
00646 }
00647 
00648 /** @}
00649 */
00650 
00651 int Serial_Init( int index )
00652 {
00653   if ( index < 0 || index >= SERIAL_PORTS )
00654     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00655 
00656   Serial_* sp = &Serial[ index ];
00657 
00658   // default to SERIAL_0 values
00659   int id = AT91C_ID_US0;
00660   int rxPin = IO_PA00;
00661   int txPin = IO_PA01;
00662   long rxPinBit = IO_PA00_BIT;
00663   long txPinBit = IO_PA01_BIT;
00664   switch( index )
00665   {
00666     case SERIAL_0:
00667       // values already set for this above
00668       sp->at91UARTRegs = AT91C_BASE_US0;
00669       break;
00670     case SERIAL_1:
00671       id = AT91C_ID_US1;
00672       rxPinBit = IO_PA05_BIT;
00673       txPinBit = IO_PA06_BIT;
00674       rxPin = IO_PA05;
00675       txPin = IO_PA06;
00676       sp->at91UARTRegs = AT91C_BASE_US1;
00677       break;
00678   }
00679 
00680   // Enable the peripheral clock
00681   AT91C_BASE_PMC->PMC_PCER = 1 << id;
00682    
00683   int status = Io_StartBits( rxPinBit | txPinBit, false  );
00684   if ( status != CONTROLLER_OK )
00685     return status;
00686 
00687   Io_SetPeripheralA( rxPin );
00688   Io_SetPeripheralA( txPin );
00689   Io_SetPio( rxPin, false );
00690   Io_SetPio( txPin, false );
00691   
00692   // Create the queues
00693   if( sp->rxQSize == 0 )
00694    sp->rxQSize = DEFAULT_SERIAL_Q_LEN;
00695   sp->receiveQueue = xQueueCreate( sp->rxQSize, 1 );
00696 
00697   if( sp->txQSize == 0 )
00698      sp->txQSize = DEFAULT_SERIAL_Q_LEN;
00699   sp->transmitQueue = xQueueCreate( sp->txQSize, 1 );
00700 
00701   // Disable interrupts
00702   sp->at91UARTRegs->US_IDR = (unsigned int) -1;
00703 
00704   // Timeguard disabled
00705   sp->at91UARTRegs->US_TTGR = 0;
00706 
00707   unsigned int mask = 0x1 << id;    
00708                         
00709   /* Disable the interrupt on the interrupt controller */         
00710   AT91C_BASE_AIC->AIC_IDCR = mask ;                   
00711   /* Save the interrupt handler routine pointer and the interrupt priority */ 
00712   AT91C_BASE_AIC->AIC_SVR[ id ] = (unsigned int)SerialIsr_Wrapper;      
00713   /* Store the Source Mode Register */                  
00714   AT91C_BASE_AIC->AIC_SMR[ id ] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 4  ;       
00715   /* Clear the interrupt on the interrupt controller */         
00716   AT91C_BASE_AIC->AIC_ICCR = mask ;         
00717 
00718   AT91C_BASE_AIC->AIC_IECR = mask;
00719 
00720   sp->at91UARTRegs->US_IER = AT91C_US_RXRDY; 
00721 
00722   sp->active = true;
00723 
00724   // If there are no default values, get some
00725   if ( !sp->detailsInitialized )
00726     Serial_SetDefault( index );
00727   // Most of the detail setting is done in here
00728   // Also Resets TXRX and re-enables RX
00729   Serial_SetDetails( index );
00730 
00731   return CONTROLLER_OK;
00732 }
00733 
00734 int Serial_Deinit( int index )
00735 {
00736   if ( index < 0 || index >= SERIAL_PORTS )
00737     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00738 
00739   Serial_* sp = &Serial[ index ];
00740   vQueueDelete( sp->receiveQueue );
00741   vQueueDelete( sp->transmitQueue );
00742   sp->active = false;
00743   return CONTROLLER_OK;
00744 }
00745 
00746 int Serial_SetDetails( int index )
00747 {
00748   if ( index < 0 || index >= SERIAL_PORTS )
00749     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00750 
00751   Serial_* sp = &Serial[ index ];
00752 
00753   if ( sp->active )
00754   {
00755      // Reset receiver and transmitter
00756     sp->at91UARTRegs->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS; 
00757 
00758     // MCK is 47923200 for the Make Controller Kit
00759 
00760     // Calculate ( * 10 )
00761     int baudValue = ( MCK * 10 ) / ( sp->baud * 16 );
00762     // Round (and / 10)
00763     if ( ( baudValue % 10 ) >= 5 ) 
00764       baudValue = ( baudValue / 10 ) + 1; 
00765     else 
00766       baudValue /= 10;
00767 
00768     sp->at91UARTRegs->US_BRGR = baudValue; 
00769 
00770     sp->at91UARTRegs->US_MR = 
00771       ( ( sp->hardwareHandshake ) ? AT91C_US_USMODE_HWHSH : AT91C_US_USMODE_NORMAL ) |
00772       ( AT91C_US_CLKS_CLOCK ) |
00773       ( ( ( sp->bits - 5 ) << 6 ) & AT91C_US_CHRL ) |
00774       ( ( sp->stopBits == 2 ) ? AT91C_US_NBSTOP_2_BIT : AT91C_US_NBSTOP_1_BIT ) |
00775       ( ( sp->parity == 0 ) ? AT91C_US_PAR_NONE : ( ( sp->parity == -1 ) ? AT91C_US_PAR_ODD : AT91C_US_PAR_EVEN ) );
00776       // 2 << 14; // this last thing puts it in loopback mode
00777 
00778 
00779     sp->at91UARTRegs->US_CR = AT91C_US_RXEN | AT91C_US_TXEN; 
00780   }
00781   return CONTROLLER_OK;
00782 }
00783 
00784 int Serial_SetDefault( int index )
00785 {
00786   if ( index < 0 || index >= SERIAL_PORTS )
00787     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00788 
00789   Serial_* sp = &Serial[ index ];
00790 
00791   sp->baud = 9600;
00792   sp->bits = 8;
00793   sp->stopBits = 1;
00794   sp->parity = 0;
00795   sp->hardwareHandshake = 0;
00796 
00797   sp->detailsInitialized = true;
00798   return CONTROLLER_OK;
00799 }
00800 
00801 #ifdef OSC
00802 /** \defgroup SerialOSC Serial - OSC
00803   Configure the Serial Port and Read Characters via OSC.
00804   \ingroup OSC
00805 
00806   \section devices Devices
00807   There are 2 serial ports, so use 0 or 1 as an index.
00808   
00809   \section properties Properties
00810   The Serial Subsystem has the following properties:
00811   - baud
00812   - bits
00813   - stopbits
00814   - parity
00815   - hardwarehandshake
00816   - readable
00817   - char
00818   - block
00819 
00820   \subsection Baud
00821   The Baud rate of the device. Valid from 110 baud to >2M baud.
00822   To set baud rate to 115200 on the first serial port, for example, send the message
00823   \verbatim /serial/0/baud 112500\endverbatim
00824   
00825   \subsection Bits
00826   The number of bits per character.  Can range from 5 to 8.
00827   To set the number of bits to 7 on the first serial port, for example, send the message
00828   \verbatim /serial/0/bits 7\endverbatim
00829   
00830   \subsection StopBits
00831   The number of stop bits per character.  Can be 1 or 2\n
00832   To set the number of stop bits to 2 on the second serial port, for example, send the message
00833   \verbatim /serial/1/stopbits 2\endverbatim
00834 
00835   \subsection Parity
00836   The parity of the character.  Can be -1 for odd, 0 for none or 1 for even.
00837   To set the parity to even, for example, send the message
00838   \verbatim /serial/0/parity 1\endverbatim
00839 
00840   \subsection HardwareHandshake
00841   Whether hardware handshaking (i.e. CTS RTS) is being employed.
00842   To set hardware handshaking on, for example, send the message
00843   \verbatim /serial/0/hardwarehandshake 1\endverbatim
00844 
00845   \subsection Readable
00846   How many characters are presently available to read.
00847   To check, for example, send the message
00848   \verbatim /serial/0/readable\endverbatim
00849 
00850   \subsection Char
00851   Send and receive individual characters with the char property.
00852   To send a character 32 (a space), for example, send the message
00853   \verbatim /serial/0/char 32\endverbatim
00854   To get a character send the message
00855   \verbatim /serial/0/char\endverbatim
00856   In this case the reply will be an unsigned value between 0 and 255 or -1 if there is 
00857   no character available.
00858 
00859   \subsection Block
00860   This property allows for reading or writing a block of characters to/from the serial port.  If you're
00861   writing a block, you must send the block you want to write as an OSC blob.
00862   
00863   For example, to send a block:
00864   \verbatim /serial/1/block blockofchars\endverbatim
00865   To get a block, send the message
00866   \verbatim /serial/1/block\endverbatim
00867   In this case the reply will be a block of up to 100 unsigned chars, or the chars currently available to read
00868   from the serial port.
00869 
00870 */
00871 
00872 #include "osc.h"
00873 #include "string.h"
00874 #include "stdio.h"
00875 
00876 #include "types.h"
00877 
00878 // Need a list of property names
00879 // MUST end in zero
00880 static char* SerialOsc_Name = "serial";
00881 static char* SerialOsc_IntPropertyNames[] = { "active", "char", "baud", "bits", "stopbits", "parity", "hardwarehandshake", "readable", 0  }; // must have a trailing 0
00882 static char* SerialOsc_BlobPropertyNames[] = { "block", 0  }; // must have a trailing 0
00883 
00884 int SerialOsc_IntPropertySet( int index, int property, int value );
00885 int SerialOsc_IntPropertyGet( int index, int property );
00886 
00887 int SerialOsc_BlobPropertySet( int index, int property, uchar* blob, int length );
00888 int SerialOsc_BlobPropertyGet( int index, int property, uchar* blob, int size );
00889 
00890 // Returns the name of the subsystem
00891 const char* SerialOsc_GetName( )
00892 {
00893   return SerialOsc_Name;
00894 }
00895 
00896 // Now getting a message.  This is actually a part message, with the first
00897 // part (the subsystem) already parsed off.
00898 int SerialOsc_ReceiveMessage( int channel, char* message, int length )
00899 {
00900   int status = Osc_IndexIntReceiverHelper( channel, message, length, SERIAL_PORTS,
00901                                       SerialOsc_Name,
00902                                       SerialOsc_IntPropertySet, SerialOsc_IntPropertyGet, 
00903                                       SerialOsc_IntPropertyNames );
00904 
00905   if ( status != CONTROLLER_OK )
00906     status = Osc_IndexBlobReceiverHelper( channel, message, length, SERIAL_PORTS,
00907                                       SerialOsc_Name,
00908                                       SerialOsc_BlobPropertySet, SerialOsc_BlobPropertyGet, 
00909                                       SerialOsc_BlobPropertyNames );                        
00910 
00911   if ( status != CONTROLLER_OK )
00912     return Osc_SendError( channel, SerialOsc_Name, status );
00913   return CONTROLLER_OK;
00914 }
00915 // Set the index LED, property with the value
00916 int SerialOsc_IntPropertySet( int index, int property, int value )
00917 {
00918   switch ( property )
00919   {
00920     case 0: 
00921       Serial_SetActive( index, value );
00922       break;      
00923     case 1: 
00924       Serial_SetChar( index, value );
00925       break;      
00926     case 2: 
00927       Serial_SetBaud( index, value );
00928       break;      
00929     case 3: 
00930       Serial_SetBits( index, value );
00931       break;    
00932     case 4: 
00933       Serial_SetStopBits( index, value );
00934       break;
00935     case 5: 
00936       Serial_SetParity( index, value );
00937       break;    
00938     case 6: 
00939       Serial_SetHardwareHandshake( index, value );
00940       break;    
00941   }
00942   return CONTROLLER_OK;
00943 }
00944 
00945 // Get the index, property
00946 int SerialOsc_IntPropertyGet( int index, int property )
00947 {
00948   int value = 0;
00949   switch ( property )
00950   {
00951     case 0:
00952       value = Serial_GetActive( index );
00953       break;
00954     case 1:
00955       value = Serial_GetChar( index );
00956       break;
00957     case 2:
00958       value = Serial_GetBaud( index );
00959       break;
00960     case 3:
00961       value = Serial_GetBits( index );
00962       break;
00963     case 4:
00964       value = Serial_GetStopBits( index );
00965       break;
00966     case 5:
00967       value = Serial_GetParity( index );
00968       break;
00969     case 6:
00970       value = Serial_GetHardwareHandshake( index );
00971       break;
00972     case 7:
00973       value = Serial_GetReadable( index );
00974       break;
00975   }
00976   
00977   return value;
00978 }
00979 
00980 // Get the index, property
00981 int SerialOsc_BlobPropertyGet( int index, int property, uchar* blob, int maxSize )
00982 {
00983   int xfer = 0;
00984   switch ( property )
00985   {
00986     case 0:
00987     {
00988       int length = Serial_GetReadable( index );
00989       xfer = ( length < maxSize ) ? length : maxSize;
00990       if ( xfer > 0 )
00991         Serial_Read( index, blob, xfer, 100 );
00992       break;
00993     }
00994   }
00995   
00996   return xfer;
00997 }
00998 
00999 
01000 // Set the index LED, property with the value
01001 int SerialOsc_BlobPropertySet( int index, int property, uchar* blob, int length )
01002 {
01003   switch ( property )
01004   {
01005     case 0: 
01006       Serial_Write( index, blob, length, 100 );
01007       break;      
01008   }
01009   return CONTROLLER_OK;
01010 }
01011 
01012 #endif

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.