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