Contiki 2.6
|
00001 /** @file hal/micro/cortexm3/uart.c 00002 * @brief STM32W uart drivers, supporting IAR's standard library 00003 * IO routines. 00004 * 00005 * <!--(C) COPYRIGHT 2010 STMicroelectronics. All rights reserved. --> 00006 */ 00007 00008 #include PLATFORM_HEADER 00009 #include "hal/micro/micro-common.h" 00010 #include "hal/micro/cortexm3/micro-common.h" 00011 #include "uart.h" 00012 #ifdef __GNUC__ 00013 #include <sys/stat.h> 00014 #include <stdio.h> 00015 #define _LLIO_STDIN ((int) stdin) 00016 #define _LLIO_STDOUT ((int) stdout) 00017 #define _LLIO_STDERR ((int) stderr) 00018 #define _LLIO_ERROR (-1) 00019 #define __write _write 00020 #define __read _read 00021 #undef putchar 00022 void __io_putchar( char c ); 00023 int putchar (int c) 00024 { 00025 __io_putchar((char) c); 00026 return c; 00027 } 00028 #endif 00029 #define RECEIVE_QUEUE_SIZE (128) 00030 00031 int8u rxQ[RECEIVE_QUEUE_SIZE]; 00032 int16u rxHead; 00033 int16u rxTail; 00034 int16u rxUsed; 00035 00036 ////////////////////////////////////////////////////////////////////////////// 00037 // Initialization 00038 00039 void uartInit(int32u baudrate, int8u databits, SerialParity parity, int8u stopbits) 00040 { 00041 int32u tempcfg; 00042 int32u tmp; 00043 00044 assert( (baudrate >= 300) && (baudrate <=921600) ); 00045 00046 tmp = (2*12000000L + baudrate/2) / baudrate; 00047 SC1_UARTFRAC = tmp & 1; 00048 SC1_UARTPER = tmp / 2; 00049 00050 if(databits == 7) { 00051 tempcfg = 0; 00052 } else { 00053 tempcfg = SC_UART8BIT; 00054 } 00055 00056 if (parity == PARITY_ODD) { 00057 tempcfg |= SC_UARTPAR | SC_UARTODD; 00058 } else if( parity == PARITY_EVEN ) { 00059 tempcfg |= SC_UARTPAR; 00060 } 00061 00062 if ((stopbits & 0x0F) >= 2) { 00063 tempcfg |= SC_UART2STP; 00064 } 00065 SC1_UARTCFG = tempcfg; 00066 00067 SC1_MODE = SC1_MODE_UART; 00068 00069 rxHead=0; 00070 rxTail=0; 00071 rxUsed=0; 00072 00073 halGpioConfig(PORTB_PIN(1),GPIOCFG_OUT_ALT); 00074 halGpioConfig(PORTB_PIN(2),GPIOCFG_IN); 00075 00076 // Make the RX Valid interrupt level sensitive (instead of edge) 00077 SC1_INTMODE = SC_RXVALLEVEL; 00078 // Enable just RX interrupts; TX interrupts are controlled separately 00079 INT_SC1CFG |= (INT_SCRXVAL | 00080 INT_SCRXOVF | 00081 INT_SC1FRMERR | 00082 INT_SC1PARERR); 00083 INT_SC1FLAG = 0xFFFF; // Clear any stale interrupts 00084 INT_CFGSET = INT_SC1; 00085 } 00086 00087 ////////////////////////////////////////////////////////////////////////////// 00088 // Transmit 00089 00090 // IAR Standard library hook for serial output 00091 size_t __write(int handle, const unsigned char * buffer, size_t size) 00092 { 00093 size_t nChars = 0; 00094 00095 /* This template only writes to "standard out" and "standard err", 00096 * for all other file handles it returns failure. */ 00097 if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR) { 00098 return _LLIO_ERROR; 00099 } 00100 00101 if (buffer == 0) { 00102 // This means that we should flush internal buffers. 00103 //spin until TX complete (TX is idle) 00104 while ((SC1_UARTSTAT&SC_UARTTXIDLE)!=SC_UARTTXIDLE) {} 00105 return 0; 00106 } 00107 00108 // ensure port is configured for UART 00109 if(SC1_MODE != SC1_MODE_UART) { 00110 return _LLIO_ERROR; 00111 } 00112 00113 while(size--) { 00114 //spin until data register has room for more data 00115 while ((SC1_UARTSTAT&SC_UARTTXFREE)!=SC_UARTTXFREE) {} 00116 SC1_DATA = *buffer; 00117 buffer++; 00118 00119 ++nChars; 00120 } 00121 00122 return nChars; 00123 } 00124 #ifdef __GNUC__ 00125 int fflush (FILE *f) 00126 #endif 00127 #ifdef __ICCARM__ 00128 size_t fflush(int handle) 00129 #endif 00130 { 00131 return __write(_LLIO_STDOUT, NULL, 0); 00132 } 00133 00134 static void halInternalUart1TxIsr(void) 00135 { 00136 // Nothing for now, as ouput is blocking from the __write function 00137 } 00138 00139 00140 ////////////////////////////////////////////////////////////////////////////// 00141 // Receive 00142 00143 // IAR Standard library hook for serial input 00144 size_t __read(int handle, unsigned char * buffer, size_t size) 00145 { 00146 int nChars = 0; 00147 00148 /* This template only reads from "standard in", for all other file 00149 * handles it returns failure. */ 00150 if (handle != _LLIO_STDIN) 00151 { 00152 return _LLIO_ERROR; 00153 } 00154 00155 for(nChars = 0; (rxUsed>0) && (nChars < size); nChars++) { 00156 ATOMIC( 00157 *buffer++ = rxQ[rxTail]; 00158 rxTail = (rxTail+1) % RECEIVE_QUEUE_SIZE; 00159 rxUsed--; 00160 ) 00161 } 00162 00163 return nChars; 00164 } 00165 00166 static void halInternalUart1RxIsr(void) 00167 { 00168 00169 // At present we really don't care which interrupt(s) 00170 // occurred, just that one did. Loop reading RXVALID 00171 // data, processing any errors noted 00172 // along the way. 00173 while ( SC1_UARTSTAT & SC_UARTRXVAL ) { 00174 int8u errors = SC1_UARTSTAT & (SC_UARTFRMERR | 00175 SC_UARTRXOVF | 00176 SC_UARTPARERR ); 00177 int8u incoming = (int8u) SC1_DATA; 00178 00179 if ( (errors == 0) && (rxUsed < (RECEIVE_QUEUE_SIZE-1)) ) { 00180 rxQ[rxHead] = incoming; 00181 rxHead = (rxHead+1) % RECEIVE_QUEUE_SIZE; 00182 rxUsed++; 00183 } else { 00184 // IAR standard library doesn't allow for any error handling in the 00185 // case of rx errors or not having space in the receive queue, so the 00186 // errors are just silently dropped. 00187 } 00188 } // end of while ( SC1_UARTSTAT & SC1_UARTRXVAL ) 00189 } 00190 00191 00192 ////////////////////////////////////////////////////////////////////////////// 00193 // Interrupts 00194 00195 void halSc1Isr(void) 00196 { 00197 int32u interrupt; 00198 00199 //this read and mask is performed in two steps otherwise the compiler 00200 //will complain about undefined order of volatile access 00201 interrupt = INT_SC1FLAG; 00202 interrupt &= INT_SC1CFG; 00203 00204 while (interrupt != 0) { 00205 00206 INT_SC1FLAG = interrupt; // acknowledge the interrupts early 00207 00208 // RX events 00209 if ( interrupt & (INT_SCRXVAL | // RX has data 00210 INT_SCRXOVF | // RX Overrun error 00211 INT_SC1FRMERR | // RX Frame error 00212 INT_SC1PARERR ) // RX Parity error 00213 ) { 00214 halInternalUart1RxIsr(); 00215 } 00216 00217 // TX events 00218 if ( interrupt & (INT_SCTXFREE | // TX has room 00219 INT_SCTXIDLE ) // TX idle (more room) 00220 ) { 00221 halInternalUart1TxIsr(); 00222 } 00223 00224 interrupt = INT_SC1FLAG; 00225 interrupt &= INT_SC1CFG; 00226 } 00227 } 00228 00229 /******************************************************************************* 00230 * Function Name : __io_getcharNonBlocking 00231 * Description : Non blocking read 00232 * Input : none 00233 * Output : dataByte: buffer containing the read byte if any 00234 * Return : TRUE if there is a data, FALSE otherwise 00235 *******************************************************************************/ 00236 boolean __io_getcharNonBlocking(int8u *data) 00237 { 00238 if (__read(_LLIO_STDIN,data,1)) 00239 return TRUE; 00240 else 00241 return FALSE; 00242 }/* end serialReadByte() */ 00243 00244 void __io_putchar( char c ) 00245 { 00246 __write(_LLIO_STDOUT, (unsigned char *)&c, 1); 00247 } 00248 00249 int __io_getchar() 00250 { 00251 unsigned char c; 00252 __read(_LLIO_STDIN, &c, 1); 00253 return (int)(c); 00254 } 00255 00256 void __io_flush( void ) 00257 { 00258 __write(_LLIO_STDOUT, NULL, 0); 00259 }