MODSERIAL with support for more devices
Dependents: 1D-Pong BMT-K9_encoder BMT-K9-Regelaar programma_filter ... more
Check the cookbook page for more information: https://mbed.org/cookbook/MODSERIAL
Did you add a device? Please send a pull request so we can keep everything in one library instead of many copies. In that case also send a PM, since currently mbed does not inform of new pull requests. I will then also add you to the developers of this library so you can do other changes directly.
Revision 2:b936b4acbd92, committed 2010-11-21
- Comitter:
- AjK
- Date:
- Sun Nov 21 03:31:51 2010 +0000
- Parent:
- 1:b7e435fbfe8e
- Child:
- 3:0f10f536456e
- Commit message:
- 1.4
Changed in this revision
--- a/ChangeLog.c Sun Nov 21 02:15:07 2010 +0000 +++ b/ChangeLog.c Sun Nov 21 03:31:51 2010 +0000 @@ -1,5 +1,21 @@ /* $Id:$ + +1.3 - 21/11/2010 + + * Fixed a macro problem with txIsBusy() + * Started adding code to use "block data" sending using DMA +1.2 - 21/11/2010 + + * Removed unsed variables from flushBuffer() + * Fixed a bug where both RX AND TX fifos are cleared/reset + when just TX OR RX should be cleared. + * Fixed a bug that cleared IIR when in fact it should be left + alone so that any pending interrupt after flush is handled. + * Merged setBase() into init() as it wasn't required anywhere else. + * Changed init() to enforce _uidx is set by Serial to define the _base + address of the Uart in use. + 1.1 - 20/11/2010 * Added this file
--- a/FLUSH.cpp Sun Nov 21 02:15:07 2010 +0000 +++ b/FLUSH.cpp Sun Nov 21 03:31:51 2010 +0000 @@ -28,9 +28,6 @@ void MODSERIAL::flushBuffer(IrqType type) { - volatile char c __attribute__((unused)); - volatile uint32_t iir __attribute__((unused)); - uint32_t ier = _IER; switch(type) { case TxIrq: _IER &= ~(1UL << 1); break; @@ -40,9 +37,10 @@ buffer_out[type] = 0; buffer_count[type] = 0; buffer_overflow[type] = 0; - _FCR = MODSERIAL_FIFO_RX_RESET | MODSERIAL_FIFO_TX_RESET; - _FCR = MODSERIAL_FIFO_ENABLE; - iir = _IIR; + switch(type) { + case TxIrq: _FCR = MODSERIAL_FIFO_TX_RESET; break; + case RxIrq: _FCR = MODSERIAL_FIFO_RX_RESET; break; + } _IER = ier; }
--- a/INIT.cpp Sun Nov 21 02:15:07 2010 +0000 +++ b/INIT.cpp Sun Nov 21 03:31:51 2010 +0000 @@ -30,7 +30,13 @@ { disableIrq(); - setBase(); + switch(_uidx) { + case 0: _base = LPC_UART0; break; + case 1: _base = LPC_UART1; break; + case 2: _base = LPC_UART2; break; + case 3: _base = LPC_UART3; break; + default : _base = NULL; break; + } if (_base != NULL) { buffer_size[RxIrq] = rxSize; @@ -39,6 +45,7 @@ buffer_out[RxIrq] = 0; buffer_count[RxIrq] = 0; buffer_overflow[RxIrq] = 0; + dmaInUse[RxIrq] = -1; Serial::attach(this, &MODSERIAL::isr_rx, Serial::RxIrq); buffer_size[TxIrq] = txSize; @@ -47,8 +54,12 @@ buffer_out[TxIrq] = 0; buffer_count[TxIrq] = 0; buffer_overflow[TxIrq] = 0; + dmaInUse[TxIrq] = -1; Serial::attach(this, &MODSERIAL::isr_tx, Serial::TxIrq); } + else { + error("MODSERIAL must have a defined UART to function."); + } if (!txBufferSane()) { error("Failed to allocate memory for TX buffer"); @@ -63,16 +74,4 @@ enableIrq(); } -void -MODSERIAL::setBase(void) -{ - switch(_uidx) { - case 0: _base = LPC_UART0; break; - case 1: _base = LPC_UART1; break; - case 2: _base = LPC_UART2; break; - case 3: _base = LPC_UART3; break; - default : _base = NULL; break; - } -} - }; // namespace AjK ends
--- a/ISR_RX.cpp Sun Nov 21 02:15:07 2010 +0000 +++ b/ISR_RX.cpp Sun Nov 21 03:31:51 2010 +0000 @@ -28,7 +28,9 @@ void MODSERIAL::isr_rx(void) { - if (_base) { + if (! _base ) return; + + if ( dmaInUse[RxIrq] == NotInUse ) { while( MODSERIAL_RBR_HAS_DATA ) { rxc = (char)(_RBR & 0xFF); if ( MODSERIAL_RX_BUFFER_FULL ) {
--- a/ISR_TX.cpp Sun Nov 21 02:15:07 2010 +0000 +++ b/ISR_TX.cpp Sun Nov 21 03:31:51 2010 +0000 @@ -29,7 +29,9 @@ void MODSERIAL::isr_tx(void) { - if (_base) { + if (! _base ) return; + + if (dmaInUse[TxIrq] == NotInUse ) { while (! MODSERIAL_TX_BUFFER_EMPTY && MODSERIAL_THR_HAS_SPACE ) { _THR = txc = (uint8_t)(buffer[TxIrq][buffer_out[TxIrq]]); buffer_count[TxIrq]--;
--- a/MODSERIAL.cpp Sun Nov 21 02:15:07 2010 +0000 +++ b/MODSERIAL.cpp Sun Nov 21 03:31:51 2010 +0000 @@ -71,6 +71,12 @@ return MODSERIAL_RX_BUFFER_EMPTY; } +bool +MODSERIAL::txIsBusy(void) +{ + return (_LSR & (3UL << 5) == 0) ? true : false; +} + void MODSERIAL::disableIrq(void) {
--- a/MODSERIAL.h Sun Nov 21 02:15:07 2010 +0000 +++ b/MODSERIAL.h Sun Nov 21 03:31:51 2010 +0000 @@ -134,6 +134,19 @@ , BufferOversize = -2 /*!< Oversized buffer. */ }; + //! DMA channels. + enum dmaChannel { + NotInUse = -1 /*!< DMA not in use */ + , Channel0 = 0 /*!< Channel 0 */ + , Channel1 /*!< Channel 1 */ + , Channel2 /*!< Channel 2 */ + , Channel3 /*!< Channel 3 */ + , Channel4 /*!< Channel 4 */ + , Channel5 /*!< Channel 5 */ + , Channel6 /*!< Channel 6 */ + , Channel7 /*!< Channel 7 */ + }; + /** * The MODSERIAL constructor is used to initialise the serial object. * @@ -549,7 +562,7 @@ * @ingroup API * @return bool */ - bool txIsBusy(void) { return (_LSR & (3UL << 5) == 0) ? true : false; } + bool txIsBusy(void); #if 0 // Inhereted from Serial/Stream, for documentation only /** @@ -650,6 +663,12 @@ volatile int buffer_overflow[2]; /** + * DMA channel in use. + * @ingroup INTERNALS + */ + volatile int dmaInUse[2]; + + /** * Callback system. * @ingroup INTERNALS */ @@ -706,13 +725,7 @@ * Overloaded virtual function. */ virtual int _getc() { return __getc(true); } - - /** - * Set's the Uart base pointer. - * @ingroup INTERNALS - */ - void setBase(void); - + /** * Function: init * Initialize the MODSERIAL object
--- a/PUTC.cpp Sun Nov 21 02:15:07 2010 +0000 +++ b/PUTC.cpp Sun Nov 21 03:31:51 2010 +0000 @@ -29,24 +29,26 @@ MODSERIAL::__putc(int c, bool block) { uint32_t lsr = (uint32_t)*((char *)_base + MODSERIAL_LSR); - if (lsr & 0x20 && MODSERIAL_TX_BUFFER_EMPTY ) { - _THR = (uint32_t)c; - } - else { - if (buffer[TxIrq] != (char *)NULL) { - if (block) while ( MODSERIAL_TX_BUFFER_FULL ) ; // Blocks! - else if( MODSERIAL_TX_BUFFER_FULL ) { - buffer_overflow[TxIrq] = c; // Oh dear, no room in buffer. - _isr[TxOvIrq].call(); - return -1; + if ( dmaInUse[TxIrq] == NotInUse ) { + if (lsr & 0x20 && MODSERIAL_TX_BUFFER_EMPTY ) { + _THR = (uint32_t)c; + } + else { + if (buffer[TxIrq] != (char *)NULL) { + if (block) while ( MODSERIAL_TX_BUFFER_FULL ) ; // Blocks! + else if( MODSERIAL_TX_BUFFER_FULL ) { + buffer_overflow[TxIrq] = c; // Oh dear, no room in buffer. + _isr[TxOvIrq].call(); + return -1; + } + buffer[TxIrq][buffer_in[TxIrq]] = c; + buffer_count[TxIrq]++; + buffer_in[TxIrq]++; + if (buffer_in[TxIrq] >= buffer_size[TxIrq]) { + buffer_in[TxIrq] = 0; + } + _IER |= 0x2; } - buffer[TxIrq][buffer_in[TxIrq]] = c; - buffer_count[TxIrq]++; - buffer_in[TxIrq]++; - if (buffer_in[TxIrq] >= buffer_size[TxIrq]) { - buffer_in[TxIrq] = 0; - } - _IER |= 0x2; } }
--- a/example.cpp Sun Nov 21 02:15:07 2010 +0000 +++ b/example.cpp Sun Nov 21 03:31:51 2010 +0000 @@ -54,7 +54,7 @@ // Ensure the baud rate for the PC "USB" serial is much // higher than "uart" baud rate below. - pc.baud(115200); + pc.baud(PC_BAUD); // Use a deliberatly slow baud to fill up the TX buffer uart.baud(1200);