ser_xmega.c
Go to the documentation of this file.
00001 00044 #include "hw/hw_ser.h" /* Required for bus macros overrides */ 00045 #include <hw/hw_cpufreq.h> /* CPU_FREQ */ 00046 00047 #include <cfg/macros.h> /* DIV_ROUND */ 00048 #include <cfg/debug.h> /* debug configuration */ 00049 00050 #include <drv/ser.h> 00051 #include <drv/ser_p.h> 00052 #include <drv/timer.h> 00053 00054 #include <struct/fifobuf.h> 00055 00056 #include <avr/io.h> /* AVR IO ports and structures */ 00057 #include <avr/interrupt.h> /* AVR Interrupt methods */ 00058 00059 /* 00060 * Scalefactor to use for computing the baudrate 00061 * this scalefactor should be an integer value between -7 00062 * and 7 00063 */ 00064 #ifndef USART_SCALE_FACTOR 00065 #define USART_SCALE_FACTOR (-7) 00066 #else 00067 #if USART_SCALE_FACTOR > 7 || USART_SCALE_FACTOR < -7 00068 #error USART_SCALE_FACTOR should be an integer between -7 and 7 00069 #endif 00070 #endif 00071 00072 /* Helper macros, mostly taken from the Atmel Examples 00073 * Slightly alterd to match the BeRTOS naming convention 00074 */ 00075 00076 /* \brief Set USART baud rate. 00077 * 00078 * Sets the USART's baud rate register. 00079 * 00080 * UBRR_Value : Value written to UBRR 00081 * ScaleFactor : Time Base Generator Scale Factor 00082 * 00083 * Equation for calculation of BSEL value in asynchronous normal speed mode: 00084 * If ScaleFactor >= 0 00085 * BSEL = ((I/O clock frequency)/(2^(ScaleFactor)*16*Baudrate))-1 00086 * If ScaleFactor < 0 00087 * BSEL = (1/(2^(ScaleFactor)*16))*(((I/O clock frequency)/Baudrate)-1) 00088 * 00089 * \note See XMEGA manual for equations for calculation of BSEL value in other 00090 * modes. 00091 * 00092 * \param _usart Pointer to the USART module. 00093 * \param _bselValue Value to write to BSEL part of Baud control register. 00094 * Use uint16_t type. 00095 * \param _bScaleFactor USART baud rate scale factor. 00096 * Use uint8_t type 00097 */ 00098 #define USART_SET_BAUDRATE(_usart, _bselValue, _bScaleFactor) \ 00099 (_usart)->BAUDCTRLA =(uint8_t)_bselValue; \ 00100 (_usart)->BAUDCTRLB =(_bScaleFactor << USART_BSCALE0_bp)|(_bselValue >> 8) 00101 00102 /* \brief Enable USART receiver. 00103 * 00104 * \param _usart Pointer to the USART module 00105 */ 00106 #define USART_RX_ENABLE(_usart) ((_usart)->CTRLB |= USART_RXEN_bm) 00107 00108 /* \brief Disable USART receiver. 00109 * 00110 * \param _usart Pointer to the USART module. 00111 */ 00112 #define USART_RX_DISABLE(_usart) ((_usart)->CTRLB &= ~USART_RXEN_bm) 00113 00114 /* \brief Enable USART transmitter. 00115 * 00116 * \param _usart Pointer to the USART module. 00117 */ 00118 #define USART_TX_ENABLE(_usart) ((_usart)->CTRLB |= USART_TXEN_bm) 00119 00120 /* \brief Disable USART transmitter. 00121 * 00122 * \param _usart Pointer to the USART module. 00123 */ 00124 #define USART_TX_DISABLE(_usart) ((_usart)->CTRLB &= ~USART_TXEN_bm) 00125 00126 /* \brief Set USART RXD interrupt level. 00127 * 00128 * Sets the interrupt level on RX Complete interrupt. 00129 * 00130 * \param _usart Pointer to the USART module. 00131 * \param _rxdIntLevel Interrupt level of the RXD interrupt. 00132 * Use USART_RXCINTLVL_t type. 00133 */ 00134 #define USART_SET_RX_INTERRUPT_LEVEL(_usart, _rxdIntLevel) \ 00135 ((_usart)->CTRLA = ((_usart)->CTRLA & ~USART_RXCINTLVL_gm) | _rxdIntLevel) 00136 00137 /* \brief Set USART TXD interrupt level. 00138 * 00139 * Sets the interrupt level on TX Complete interrupt. 00140 * 00141 * \param _usart Pointer to the USART module. 00142 * \param _txdIntLevel Interrupt level of the TXD interrupt. 00143 * Use USART_TXCINTLVL_t type. 00144 */ 00145 #define USART_SET_TX_INTERRUPT_LEVEL(_usart, _txdIntLevel) \ 00146 (_usart)->CTRLA = ((_usart)->CTRLA & ~USART_TXCINTLVL_gm) | _txdIntLevel 00147 00148 /* \brief Set USART DRE interrupt level. 00149 * 00150 * Sets the interrupt level on Data Register interrupt. 00151 * 00152 * \param _usart Pointer to the USART module. 00153 * \param _dreIntLevel Interrupt level of the DRE interrupt. 00154 * Use USART_DREINTLVL_t type. 00155 */ 00156 #define USART_SET_DRE_INTERRUPT_LEVEL(_usart, _dreIntLevel) \ 00157 (_usart)->CTRLA = ((_usart)->CTRLA & ~USART_DREINTLVL_gm) | _dreIntLevel 00158 00159 /* \brief Set the mode the USART run in. 00160 * 00161 * Set the mode the USART run in. The default mode is asynchronous mode. 00162 * 00163 * \param _usart Pointer to the USART module register section. 00164 * \param _usartMode Selects the USART mode. Use USART_CMODE_t type. 00165 * 00166 * USART modes: 00167 * - 0x0 : Asynchronous mode. 00168 * - 0x1 : Synchronous mode. 00169 * - 0x2 : IrDA mode. 00170 * - 0x3 : Master SPI mode. 00171 */ 00172 #define USART_SET_MODE(_usart, _usartMode) \ 00173 ((_usart)->CTRLC = ((_usart)->CTRLC & (~USART_CMODE_gm)) | _usartMode) 00174 00175 /* \brief Check if data register empty flag is set. 00176 * 00177 * \param _usart The USART module. 00178 */ 00179 #define USART_IS_TX_DATA_REGISTER_EMPTY(_usart) (((_usart)->STATUS & USART_DREIF_bm) != 0) 00180 00181 /* \brief Put data (5-8 bit character). 00182 * 00183 * Use the macro USART_IsTXDataRegisterEmpty before using this function to 00184 * put data to the TX register. 00185 * 00186 * \param _usart The USART module. 00187 * \param _data The data to send. 00188 */ 00189 #define USART_PUT_CHAR(_usart, _data) ((_usart)->DATA = _data) 00190 00191 /* \brief Checks if the RX complete interrupt flag is set. 00192 * 00193 * Checks if the RX complete interrupt flag is set. 00194 * 00195 * \param _usart The USART module. 00196 */ 00197 #define USART_IS_RX_COMPLETE(_usart) (((_usart)->STATUS & USART_RXCIF_bm) != 0) 00198 00199 /* \brief Get received data (5-8 bit character). 00200 * 00201 * This macro reads out the RX register. 00202 * Use the macro USART_RX_Complete to check if anything is received. 00203 * 00204 * \param _usart The USART module. 00205 * 00206 * \retval Received data. 00207 */ 00208 #define USART_GET_CHAR(_usart) ((_usart)->DATA) 00209 00210 /* configurable macros */ 00211 00212 #if !CONFIG_SER_HWHANDSHAKE 00213 00217 #define RTS_ON do {} while (0) 00218 #define RTS_OFF do {} while (0) 00219 #define IS_CTS_ON true 00220 #define EIMSKF_CTS 0 00221 /*\}*/ 00222 #endif 00223 00224 /* 00225 * \name Overridable serial bus hooks 00226 * 00227 * These can be redefined in hw.h to implement 00228 * special bus policies such as half-duplex, 485, etc. 00229 * 00230 * 00231 * \code 00232 * TXBEGIN TXCHAR TXEND TXOFF 00233 * | __________|__________ | | 00234 * | | | | | | | | | 00235 * v v v v v v v v v 00236 * ______ __ __ __ __ __ __ ________________ 00237 * \/ \/ \/ \/ \/ \/ \/ 00238 * ______/\__/\__/\__/\__/\__/\__/ 00239 * 00240 * \endcode 00241 * 00242 * \{ 00243 */ 00244 00245 #ifndef SER_UART_BUS_TXINIT 00246 /* 00247 * Default TXINIT macro - invoked in uart_init() 00248 * 00249 * - Enable both the receiver and the transmitter 00250 * - Enable only the RX complete interrupt 00251 */ 00252 #define SER_UART_BUS_TXINIT(_usart) do { \ 00253 USART_RX_ENABLE(_usart); \ 00254 USART_TX_ENABLE(_usart); \ 00255 USART_SET_RX_INTERRUPT_LEVEL(_usart, USART_RXCINTLVL_MED_gc); \ 00256 } while (0) 00257 #endif 00258 00259 #ifndef SER_UART_BUS_TXBEGIN 00260 /* 00261 * Invoked before starting a transmission 00262 * 00263 * - Enable both the receiver and the transmitter 00264 * - Enable both the RX complete and UDR empty interrupts 00265 */ 00266 #define SER_UART_BUS_TXBEGIN(_usart) do { \ 00267 USART_SET_RX_INTERRUPT_LEVEL(_usart, USART_RXCINTLVL_MED_gc); \ 00268 USART_SET_DRE_INTERRUPT_LEVEL(_usart, USART_DREINTLVL_MED_gc);\ 00269 } while (0) 00270 #endif 00271 00272 #ifndef SER_UART_BUS_TXCHAR 00273 /* 00274 * Invoked to send one character. 00275 */ 00276 #define SER_UART_BUS_TXCHAR(_usart, c) do { \ 00277 USART_PUT_CHAR(_usart, c); \ 00278 } while (0) 00279 #endif 00280 00281 #ifndef SER_UART_BUS_TXEND 00282 /* 00283 * Invoked as soon as the txfifo becomes empty 00284 * 00285 * - Keep both the receiver and the transmitter enabled 00286 * - Keep the RX complete interrupt enabled 00287 * - Disable the UDR empty interrupt 00288 */ 00289 #define SER_UART_BUS_TXEND(_usart) do { \ 00290 USART_SET_DRE_INTERRUPT_LEVEL(_usart, USART_DREINTLVL_OFF_gc); \ 00291 } while (0) 00292 #endif 00293 00294 #ifndef SER_UART_BUS_TXOFF 00295 /* 00296 * \def SER_UART_BUS_TXOFF 00297 * 00298 * Invoked after the last character has been transmitted 00299 * 00300 * The default is no action. 00301 */ 00302 #ifdef __doxygen__ 00303 #define SER_UART_BUS_TXOFF(_usart) 00304 #endif 00305 #endif 00306 00307 /*\}*/ 00308 00309 /* From the high-level serial driver */ 00310 extern struct Serial *ser_handles[SER_CNT]; 00311 00312 /* TX and RX buffers */ 00313 #if IMPLEMENT_SER_UART0 00314 static unsigned char uart0_txbuffer[CONFIG_UART0_TXBUFSIZE]; 00315 static unsigned char uart0_rxbuffer[CONFIG_UART0_RXBUFSIZE]; 00316 #endif 00317 #if IMPLEMENT_SER_UART1 00318 static unsigned char uart1_txbuffer[CONFIG_UART1_TXBUFSIZE]; 00319 static unsigned char uart1_rxbuffer[CONFIG_UART1_RXBUFSIZE]; 00320 #endif 00321 #if IMPLEMENT_SER_UART2 00322 static unsigned char uart2_txbuffer[CONFIG_UART2_TXBUFSIZE]; 00323 static unsigned char uart2_rxbuffer[CONFIG_UART2_RXBUFSIZE]; 00324 #endif 00325 #if IMPLEMENT_SER_UART3 00326 static unsigned char uart3_txbuffer[CONFIG_UART3_TXBUFSIZE]; 00327 static unsigned char uart3_rxbuffer[CONFIG_UART3_RXBUFSIZE]; 00328 #endif 00329 #if IMPLEMENT_SER_UART4 00330 static unsigned char uart4_txbuffer[CONFIG_UART4_TXBUFSIZE]; 00331 static unsigned char uart4_rxbuffer[CONFIG_UART4_RXBUFSIZE]; 00332 #endif 00333 #if IMPLEMENT_SER_UART5 00334 static unsigned char uart5_txbuffer[CONFIG_UART5_TXBUFSIZE]; 00335 static unsigned char uart5_rxbuffer[CONFIG_UART5_RXBUFSIZE]; 00336 #endif 00337 #if IMPLEMENT_SER_UART6 00338 static unsigned char uart6_txbuffer[CONFIG_UART6_TXBUFSIZE]; 00339 static unsigned char uart6_rxbuffer[CONFIG_UART6_RXBUFSIZE]; 00340 #endif 00341 #if IMPLEMENT_SER_UART7 00342 static unsigned char uart7_txbuffer[CONFIG_UART7_TXBUFSIZE]; 00343 static unsigned char uart7_rxbuffer[CONFIG_UART7_RXBUFSIZE]; 00344 #endif 00345 00346 /* 00347 * Internal hardware state structure 00348 * 00349 * The \a sending variable is true while the transmission 00350 * interrupt is retriggering itself. 00351 * 00352 * the \a usart variable will point to the USART_t structure 00353 * that should be used. 00354 * 00355 * the \a port variable will point to the PORT_t structure 00356 * that should be modified to set the tx pin as an output and the 00357 * rx pin as an input 00358 * 00359 * the \a txpin variable will hold the pinnumber of the pin to use 00360 * as the tx output 00361 * 00362 * the \a rxpin variable will hold the pinnumber of the pin to use 00363 * as the rx input 00364 * 00365 * For the USARTs the \a sending flag is useful for taking specific 00366 * actions before sending a burst of data, at the start of a trasmission 00367 * but not before every char sent. 00368 * 00369 * For the SPI, this flag is necessary because the SPI sends and receives 00370 * bytes at the same time and the SPI IRQ is unique for send/receive. 00371 * The only way to start transmission is to write data in SPDR (this 00372 * is done by spi_starttx()). We do this *only* if a transfer is 00373 * not already started. 00374 */ 00375 struct AvrxmegaSerial 00376 { 00377 struct SerialHardware hw; 00378 volatile bool sending; 00379 volatile USART_t* usart; 00380 volatile PORT_t* port; 00381 uint8_t txpin; 00382 uint8_t rxpin; 00383 }; 00384 00385 /* 00386 * Callbacks 00387 * The same callbacks are used for all USARTS. 00388 * By casting the SerialHardware structure to the AvrxmegaSerial 00389 * structure a pointer to the USART_t structure can be obtained, 00390 * to perform the callback for the specific USART. 00391 * This methode might cost some more cpu time, but saves on 00392 * code duplication and code size. 00393 */ 00394 00395 00396 /* 00397 * \brief Initializes the uart 00398 * 00399 * The TX pin of the uart will be set as an outputpin 00400 * The RX pin of the uart will be set as an inputpin 00401 * The usart will be initialized 00402 * \see SER_UART_BUS_TXINIT 00403 * 00404 * \param _hw struct AvrxmegaSerial 00405 * \param ser Unused 00406 */ 00407 static void uart_init(struct SerialHardware * _hw, UNUSED_ARG(struct Serial *, ser)) 00408 { 00409 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw; 00410 //set transmit pin as output 00411 hw->port->DIRSET = BV(hw->txpin); 00412 hw->port->OUTCLR = BV(hw->txpin); 00413 //set receive pin as input 00414 hw->port->DIRCLR = BV(hw->rxpin); 00415 //initialize the USART 00416 SER_UART_BUS_TXINIT(hw->usart); 00417 RTS_ON; 00418 SER_STROBE_INIT; 00419 } 00420 00421 /* 00422 * \brief Cleans up / Disables the uart 00423 * 00424 * \param _hw struct AvrxmegaSerial 00425 */ 00426 static void uart_cleanup(struct SerialHardware * _hw) 00427 { 00428 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw; 00429 hw->usart->CTRLA = 0; 00430 hw->usart->CTRLB = 0; 00431 } 00432 00433 /* 00434 * \brief Enableds the TX interrupt 00435 * 00436 * \param _hw struct AvrxmegaSerial 00437 */ 00438 static void uart_enabletxirq(struct SerialHardware *_hw) 00439 { 00440 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw; 00441 00442 /* 00443 * WARNING: racy code here! The tx interrupt sets hw->sending to false 00444 * when it runs with an empty fifo. The order of statements in the 00445 * if-block matters. 00446 */ 00447 if (!hw->sending) 00448 { 00449 hw->sending = true; 00450 SER_UART_BUS_TXBEGIN(hw->usart); 00451 } 00452 } 00453 00454 /* 00455 * \brief sets the uart to the provided baudrate 00456 * 00457 * For setting the baudrate an scale factor (bscale) and a period 00458 * setting (BSEL) is required. 00459 * 00460 * The scale factor should be privided by defining USART_SCALE_FACTOR 00461 * 00462 * Atmel specifies BSEL for normal speed mode and bscale >= 0 as: 00463 * BSEL = (cpu_freq / ((2^bscale) * 16 * rate)) - 1 00464 * To allow BSEL to be calculated with an power function this can be 00465 * rewriten to: 00466 * BSEL = BSEL = (cpu_freq / ((1 << bscale) * 16 * rate)) - 1 00467 * 00468 * Atmel specifies BSEL for normal speed mode and bscale < 0 as: 00469 * BSEL = (1 / (2^bscale)) * ( (cpu_freq / (16 * rate)) - 1) 00470 * To calculte this float atheritmic is required as the second product will be smaller 00471 * than zero in a lot of cases. 00472 * To allow BSEL to be calculated with interger devision and no power function 00473 * this can be rewriten by folowing simple math rules to: 00474 * BSEL = ((1 << -bscale) * (cpu_freq - (16 * rate)) / (16 * rate) 00475 * 00476 * \param _hw struct AvrxmegaSerial 00477 * \param _rate the required baudrate 00478 * 00479 */ 00480 static void uart_setbaudrate(struct SerialHardware * _hw, unsigned long _rate) 00481 { 00482 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw; 00483 /* Compute baud-rate period, this requires a valid USART_SCALE_FACTOR */ 00484 #if USART_SCALE_FACTOR < 0 00485 uint16_t bsel = DIV_ROUND((1 << (-(USART_SCALE_FACTOR))) * (CPU_FREQ - (16 * _rate)), 16 * _rate); 00486 #else 00487 uint16_t bsel = DIV_ROUND(CPU_FREQ, (1 << (USART_SCALE_FACTOR)) * 16 * _rate) - 1; 00488 #endif 00489 USART_SET_BAUDRATE(hw->usart, bsel, USART_SCALE_FACTOR); 00490 } 00491 00492 /* 00493 * \brief Sets the parity of the uart 00494 * 00495 * \param _hw struct AvrxmegaSerial 00496 * \param _parity the parity to set 00497 */ 00498 static void uart_setparity(struct SerialHardware * _hw, int _parity) 00499 { 00500 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw; 00501 USART_SET_MODE(hw->usart, _parity); 00502 } 00503 00504 /* 00505 * \brief Returns true if Transmitter is sending 00506 * 00507 * \param _hw struct AvrxmegaSerial 00508 * \return true if transmitter is sending 00509 */ 00510 static bool tx_sending(struct SerialHardware* _hw) 00511 { 00512 struct AvrxmegaSerial *hw = (struct AvrxmegaSerial *)_hw; 00513 return hw->sending; 00514 } 00515 00516 00517 // FIXME: move into compiler.h? Ditch? 00518 #if COMPILER_C99 00519 #define C99INIT(name,val) .name = val 00520 #elif defined(__GNUC__) 00521 #define C99INIT(name,val) name: val 00522 #else 00523 #warning No designated initializers, double check your code 00524 #define C99INIT(name,val) (val) 00525 #endif 00526 00527 /* 00528 * High-level interface data structures 00529 */ 00530 static const struct SerialHardwareVT UART_VT = 00531 { 00532 C99INIT(init, uart_init), 00533 C99INIT(cleanup, uart_cleanup), 00534 C99INIT(setBaudrate, uart_setbaudrate), 00535 C99INIT(setParity, uart_setparity), 00536 C99INIT(txStart, uart_enabletxirq), 00537 C99INIT(txSending, tx_sending) 00538 }; 00539 00540 /* 00541 * Xmega UARTDesc data structure 00542 * Contains all information required to manage a serial port. 00543 * 00544 * Serial ports are assigned (as far as present on the xmega family) as: 00545 * SER_UART0 -> USARTC0 00546 * SER_UART1 -> USARTD0 00547 * SER_UART2 -> USARTE0 00548 * SER_UART3 -> USARTC1 00549 * SER_UART4 -> USARTD1 00550 * SER_UART5 -> USARTE1 00551 * SER_UART6 -> USARTF0 00552 * SER_UART7 -> USARTF1 00553 */ 00554 static struct AvrxmegaSerial UARTDescs[SER_CNT] = 00555 { 00556 #if IMPLEMENT_SER_UART0 00557 { 00558 C99INIT(hw, ) { 00559 C99INIT(table, &UART_VT), 00560 C99INIT(txbuffer, uart0_txbuffer), 00561 C99INIT(rxbuffer, uart0_rxbuffer), 00562 C99INIT(txbuffer_size, sizeof(uart0_txbuffer)), 00563 C99INIT(rxbuffer_size, sizeof(uart0_rxbuffer)), 00564 }, 00565 C99INIT(sending, false), 00566 C99INIT(usart, &USARTC0), 00567 C99INIT(port, &PORTC), 00568 C99INIT(txpin, PIN3_bp), 00569 C99INIT(rxpin, PIN2_bp), 00570 }, 00571 #endif 00572 #if IMPLEMENT_SER_UART1 00573 { 00574 C99INIT(hw, ) { 00575 C99INIT(table, &UART_VT), 00576 C99INIT(txbuffer, uart1_txbuffer), 00577 C99INIT(rxbuffer, uart1_rxbuffer), 00578 C99INIT(txbuffer_size, sizeof(uart1_txbuffer)), 00579 C99INIT(rxbuffer_size, sizeof(uart1_rxbuffer)), 00580 }, 00581 C99INIT(sending, false), 00582 C99INIT(usart, &USARTD0), 00583 C99INIT(port, &PORTD), 00584 C99INIT(txpin, PIN3_bp), 00585 C99INIT(rxpin, PIN2_bp), 00586 }, 00587 #endif 00588 #if IMPLEMENT_SER_UART2 00589 { 00590 C99INIT(hw, ) { 00591 C99INIT(table, &UART_VT), 00592 C99INIT(txbuffer, uart2_txbuffer), 00593 C99INIT(rxbuffer, uart2_rxbuffer), 00594 C99INIT(txbuffer_size, sizeof(uart2_txbuffer)), 00595 C99INIT(rxbuffer_size, sizeof(uart2_rxbuffer)), 00596 }, 00597 C99INIT(sending, false), 00598 C99INIT(usart, &USARTE0), 00599 C99INIT(port, &PORTE), 00600 C99INIT(txpin, PIN3_bp), 00601 C99INIT(rxpin, PIN2_bp), 00602 }, 00603 #endif 00604 #if IMPLEMENT_SER_UART3 00605 { 00606 C99INIT(hw, ) { 00607 C99INIT(table, &UART_VT), 00608 C99INIT(txbuffer, uart3_txbuffer), 00609 C99INIT(rxbuffer, uart3_rxbuffer), 00610 C99INIT(txbuffer_size, sizeof(uart3_txbuffer)), 00611 C99INIT(rxbuffer_size, sizeof(uart3_rxbuffer)), 00612 }, 00613 C99INIT(sending, false), 00614 C99INIT(usart, &USARTC1), 00615 C99INIT(port, &PORTC), 00616 C99INIT(txpin, PIN7_bp), 00617 C99INIT(rxpin, PIN6_bp), 00618 }, 00619 #endif 00620 #if IMPLEMENT_SER_UART4 00621 { 00622 C99INIT(hw, ) { 00623 C99INIT(table, &UART_VT), 00624 C99INIT(txbuffer, uart4_txbuffer), 00625 C99INIT(rxbuffer, uart4_rxbuffer), 00626 C99INIT(txbuffer_size, sizeof(uart4_txbuffer)), 00627 C99INIT(rxbuffer_size, sizeof(uart4_rxbuffer)), 00628 }, 00629 C99INIT(sending, false), 00630 C99INIT(usart, &USARTD1), 00631 C99INIT(port, &PORTD), 00632 C99INIT(txpin, PIN7_bp), 00633 C99INIT(rxpin, PIN6_bp), 00634 }, 00635 #endif 00636 #if IMPLEMENT_SER_UART5 00637 { 00638 C99INIT(hw, ) { 00639 C99INIT(table, &UART_VT), 00640 C99INIT(txbuffer, uart5_txbuffer), 00641 C99INIT(rxbuffer, uart5_rxbuffer), 00642 C99INIT(txbuffer_size, sizeof(uart5_txbuffer)), 00643 C99INIT(rxbuffer_size, sizeof(uart5_rxbuffer)), 00644 }, 00645 C99INIT(sending, false), 00646 C99INIT(usart, &USARTE1), 00647 C99INIT(port, &PORTE), 00648 C99INIT(txpin, PIN7_bp), 00649 C99INIT(rxpin, PIN6_bp), 00650 }, 00651 #endif 00652 #if IMPLEMENT_SER_UART6 00653 { 00654 C99INIT(hw, ) { 00655 C99INIT(table, &UART_VT), 00656 C99INIT(txbuffer, uart6_txbuffer), 00657 C99INIT(rxbuffer, uart6_rxbuffer), 00658 C99INIT(txbuffer_size, sizeof(uart6_txbuffer)), 00659 C99INIT(rxbuffer_size, sizeof(uart6_rxbuffer)), 00660 }, 00661 C99INIT(sending, false), 00662 C99INIT(usart, &USARTF0), 00663 C99INIT(port, &PORTF), 00664 C99INIT(txpin, PIN3_bp), 00665 C99INIT(rxpin, PIN2_bp), 00666 }, 00667 #endif 00668 #if IMPLEMENT_SER_UART7 00669 { 00670 C99INIT(hw, ) { 00671 C99INIT(table, &UART_VT), 00672 C99INIT(txbuffer, uart7_txbuffer), 00673 C99INIT(rxbuffer, uart7_rxbuffer), 00674 C99INIT(txbuffer_size, sizeof(uart7_txbuffer)), 00675 C99INIT(rxbuffer_size, sizeof(uart7_rxbuffer)), 00676 }, 00677 C99INIT(sending, false), 00678 C99INIT(usart, &USARTF1), 00679 C99INIT(port, &PORTF), 00680 C99INIT(txpin, PIN7_bp), 00681 C99INIT(rxpin, PIN6_bp), 00682 } 00683 #endif 00684 }; 00685 00686 struct SerialHardware *ser_hw_getdesc(int unit) 00687 { 00688 ASSERT(unit < SER_CNT); 00689 return &UARTDescs[unit].hw; 00690 } 00691 00692 00693 /* 00694 * Interrupt handlers 00695 */ 00696 static inline void usart_handleDreInterrupt(uint8_t usartNumber) 00697 { 00698 SER_STROBE_ON; 00699 struct FIFOBuffer * const txfifo = &ser_handles[usartNumber]->txfifo; 00700 if (fifo_isempty(txfifo)) 00701 { 00702 SER_UART_BUS_TXEND(UARTDescs[usartNumber].usart); 00703 #ifndef SER_UART_BUS_TXOFF 00704 UARTDescs[usartNumber].sending = false; 00705 #endif 00706 } 00707 else 00708 { 00709 char c = fifo_pop(txfifo); 00710 SER_UART_BUS_TXCHAR(UARTDescs[usartNumber].usart, c); 00711 } 00712 SER_STROBE_OFF; 00713 } 00714 00715 #define USART_DRE_INTERRUPT_VECTOR(_vector, _usart) \ 00716 DECLARE_ISR(_vector) \ 00717 { \ 00718 usart_handleDreInterrupt( _usart ); \ 00719 } 00720 00721 /* 00722 * Serial RX complete interrupt handler. 00723 * 00724 * This handler is interruptible. 00725 * Interrupt are reenabled as soon as recv complete interrupt is 00726 * disabled. Using INTERRUPT() is troublesome when the serial 00727 * is heavily loaded, because an interrupt could be retriggered 00728 * when executing the handler prologue before RXCIE is disabled. 00729 */ 00730 static inline void USART_handleRXCInterrupt(uint8_t usartNumber) 00731 { 00732 SER_STROBE_ON; 00733 /* read status */ 00734 ser_handles[usartNumber]->status |= (UARTDescs[usartNumber].usart)->STATUS & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR); 00735 /* To clear the RXC flag we must _always_ read the UDR even when we're 00736 * not going to accept the incoming data, otherwise a new interrupt 00737 * will occur once the handler terminates. 00738 */ 00739 char c = (UARTDescs[usartNumber].usart)->DATA; 00740 struct FIFOBuffer * const rxfifo = &ser_handles[usartNumber]->rxfifo; 00741 if (fifo_isfull(rxfifo)) 00742 { 00743 ser_handles[usartNumber]->status |= SERRF_RXFIFOOVERRUN; 00744 } 00745 else 00746 { 00747 fifo_push(rxfifo, c); 00748 #if CONFIG_SER_HWHANDSHAKE 00749 if (fifo_isfull(rxfifo)) 00750 { 00751 RTS_OFF(UARTDescs[usartNumber].usart); 00752 } 00753 #endif 00754 } 00755 SER_STROBE_OFF; 00756 } 00757 00758 #define USART_RXC_INTERRUPT_VECTOR(_vector, _usart) \ 00759 DECLARE_ISR(_vector) \ 00760 { \ 00761 USART_handleRXCInterrupt( _usart ); \ 00762 } 00763 00764 #if IMPLEMENT_SER_UART0 00765 USART_DRE_INTERRUPT_VECTOR(USARTC0_DRE_vect, SER_UART0) 00766 USART_RXC_INTERRUPT_VECTOR(USARTC0_RXC_vect, SER_UART0) 00767 #endif 00768 #if IMPLEMENT_SER_UART1 00769 USART_DRE_INTERRUPT_VECTOR(USARTD0_DRE_vect, SER_UART1) 00770 USART_RXC_INTERRUPT_VECTOR(USARTD0_RXC_vect, SER_UART1) 00771 #endif 00772 #if IMPLEMENT_SER_UART2 00773 USART_DRE_INTERRUPT_VECTOR(USARTE0_DRE_vect, SER_UART2) 00774 USART_RXC_INTERRUPT_VECTOR(USARTE0_RXC_vect, SER_UART2) 00775 #endif 00776 #if IMPLEMENT_SER_UART3 00777 USART_DRE_INTERRUPT_VECTOR(USARTC1_DRE_vect, SER_UART3) 00778 USART_RXC_INTERRUPT_VECTOR(USARTC1_RXC_vect, SER_UART3) 00779 #endif 00780 #if IMPLEMENT_SER_UART4 00781 USART_DRE_INTERRUPT_VECTOR(USARTD1_DRE_vect, SER_UART4) 00782 USART_RXC_INTERRUPT_VECTOR(USARTD1_RXC_vect, SER_UART4) 00783 #endif 00784 #if IMPLEMENT_SER_UART5 00785 USART_DRE_INTERRUPT_VECTOR(USARTE1_DRE_vect, SER_UART5) 00786 USART_RXC_INTERRUPT_VECTOR(USARTE1_RXC_vect, SER_UART5) 00787 #endif 00788 #if IMPLEMENT_SER_UART6 00789 USART_DRE_INTERRUPT_VECTOR(USARTF0_DRE_vect, SER_UART6) 00790 USART_RXC_INTERRUPT_VECTOR(USARTF0_RXC_vect, SER_UART6) 00791 #endif 00792 #if IMPLEMENT_SER_UART7 00793 USART_DRE_INTERRUPT_VECTOR(USARTF1_DRE_vect, SER_UART7) 00794 USART_RXC_INTERRUPT_VECTOR(USARTF1_RXC_vect, SER_UART7) 00795 #endif 00796 00797 #ifdef SER_UART_BUS_TXOFF 00798 static inline void USART_handleTXCInterrupt(uint8_t usartNumber) 00799 { 00800 SER_STROBE_ON; 00801 struct FIFOBuffer * const txfifo = &ser_handles[usartNumber]->txfifo; 00802 if (fifo_isempty(txfifo)) 00803 { 00804 SER_UART_BUS_TXOFF(UARTDescs[usartNumber].usart); 00805 UARTDescs[usartNumber].sending = false; 00806 } 00807 else 00808 { 00809 SER_UART_BUS_TXBEGIN(UARTDescs[usartNumber].usart); 00810 } 00811 SER_STROBE_OFF; 00812 } 00813 00814 /* 00815 * Serial port 0 TX complete interrupt handler. 00816 * 00817 * This IRQ is usually disabled. The UDR-empty interrupt 00818 * enables it when there's no more data to transmit. 00819 * We need to wait until the last character has been 00820 * transmitted before switching the 485 transceiver to 00821 * receive mode. 00822 * 00823 * The txfifo might have been refilled by putchar() while 00824 * we were waiting for the transmission complete interrupt. 00825 * In this case, we must restart the UDR empty interrupt, 00826 * otherwise we'd stop the serial port with some data 00827 * still pending in the buffer. 00828 */ 00829 #define USART_TXC_INTERRUPT_VECTOR(_vector, _usart) \ 00830 DECLARE_ISR(_vector) \ 00831 { \ 00832 USART_handleTXCInterrupt( _usart ); \ 00833 } 00834 00835 #if IMPLEMENT_SER_UART0 00836 USART_TXC_INTERRUPT_VECTOR(USARTC0_TXC_vect, SER_UART0) 00837 #endif 00838 #if IMPLEMENT_SER_UART1 00839 USART_TXC_INTERRUPT_VECTOR(USARTD0_TXC_vect, SER_UART1) 00840 #endif 00841 #if IMPLEMENT_SER_UART2 00842 USART_TXC_INTERRUPT_VECTOR(USARTE0_TXC_vect, SER_UART2) 00843 #endif 00844 #if IMPLEMENT_SER_UART3 00845 USART_TXC_INTERRUPT_VECTOR(USARTC1_TXC_vect, SER_UART3) 00846 #endif 00847 #if IMPLEMENT_SER_UART4 00848 USART_TXC_INTERRUPT_VECTOR(USARTD1_TXC_vect, SER_UART4) 00849 #endif 00850 #if IMPLEMENT_SER_UART5 00851 USART_TXC_INTERRUPT_VECTOR(USARTE1_TXC_vect, SER_UART5) 00852 #endif 00853 #if IMPLEMENT_SER_UART6 00854 USART_TXC_INTERRUPT_VECTOR(USARTF0_TXC_vect, SER_UART6) 00855 #endif 00856 #if IMPLEMENT_SER_UART7 00857 USART_TXC_INTERRUPT_VECTOR(USARTF1_TXC_vect, SER_UART7) 00858 #endif 00859 #endif /* SER_UART_BUS_TXOFF */
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)