diff --git a/ports/ARM7-LPC214x/GCC/lpc214x_serial.c b/ports/ARM7-LPC214x/GCC/lpc214x_serial.c index e3f5e4040..71dbc0b7b 100644 --- a/ports/ARM7-LPC214x/GCC/lpc214x_serial.c +++ b/ports/ARM7-LPC214x/GCC/lpc214x_serial.c @@ -22,8 +22,6 @@ #include "lpc214x.h" #include "lpc214x_serial.h" -#define SERIAL_BUFFERS_SIZE 128 - FullDuplexDriver COM1; BYTE8 ib1[SERIAL_BUFFERS_SIZE]; BYTE8 ob1[SERIAL_BUFFERS_SIZE]; @@ -68,16 +66,28 @@ static void ServeInterrupt(UART *u, FullDuplexDriver *com) { break; case IIR_SRC_TX: { +#ifdef FIFO_PRELOAD + int i = 0; + while (i < FIFO_PRELOAD) { + t_msg b = chFDDRequestDataI(com); + if (b < Q_OK) { + u->UART_IER &= ~IER_THRE; + break; + } + u->UART_THR = b; + i++; + } +#else t_msg b = chFDDRequestDataI(com); if (b < Q_OK) u->UART_IER &= ~IER_THRE; else u->UART_THR = b; +#endif } default: u->UART_THR; u->UART_RBR; - u->UART_IIR; } } } @@ -89,8 +99,20 @@ static void ServeInterrupt(UART *u, FullDuplexDriver *com) { static void OutNotify1(void) { UART *u = U0Base; - if (u->UART_LSR & LSR_THRE) + if (u->UART_LSR & LSR_THRE) { +#ifdef FIFO_PRELOAD + int i = 0; + while (i < FIFO_PRELOAD) { + t_msg b = chOQGetI(&COM1.sd_oqueue); + if (b < Q_OK) + break; + u->UART_THR = b; + i++; + } +#else u->UART_THR = chOQGetI(&COM1.sd_oqueue); +#endif + } u->UART_IER |= IER_THRE; } @@ -101,8 +123,20 @@ static void OutNotify1(void) { static void OutNotify2(void) { UART *u = U1Base; - if (u->UART_LSR & LSR_THRE) + if (u->UART_LSR & LSR_THRE) { +#ifdef FIFO_PRELOAD + int i = 0; + while (i < FIFO_PRELOAD) { + t_msg b = chOQGetI(&COM2.sd_oqueue); + if (b < Q_OK) + break; + u->UART_THR = b; + i++; + } +#else u->UART_THR = chOQGetI(&COM2.sd_oqueue); +#endif + } u->UART_IER |= IER_THRE; } diff --git a/ports/ARM7-LPC214x/GCC/lpc214x_serial.h b/ports/ARM7-LPC214x/GCC/lpc214x_serial.h index 1eaba687b..1ee910b4a 100644 --- a/ports/ARM7-LPC214x/GCC/lpc214x_serial.h +++ b/ports/ARM7-LPC214x/GCC/lpc214x_serial.h @@ -20,6 +20,23 @@ #ifndef _LPC214x_SERIAL_H_ #define _LPC214x_SERIAL_H_ +/* + * Configuration parameter, this values defines how many bytes are preloaded + * in the HW transmit FIFO for each interrupt, the maximum value is 16 the + * minimum is 2. + * NOTE: A greater value reduces the number of interrupts generated but can + * also increase the worst case interrupt response time. + * NOTE: You can undefine the following macro and revert to a simpler code + * that will generate an interrupt for each output byte, + */ +#define FIFO_PRELOAD 16 + +/* + * Configuration parameter, you can change the depth of the queue buffers + * depending on the requirements of your application. + */ +#define SERIAL_BUFFERS_SIZE 128 + void InitSerial(void); void SetUARTI(UART *u, int speed, int lcr, int fcr); void UART0IrqHandler(void); diff --git a/readme.txt b/readme.txt index 61ae140a4..833f79e88 100644 --- a/readme.txt +++ b/readme.txt @@ -47,6 +47,10 @@ AVR-AT90CANx-GCC - Port on AVR AT90CAN128, not complete yet. - Fixed a minor problem in the interrupt initialization code for the LPC214x demo, regrouped the VIC code into vic.c/vic.h. - Fixed a bug into the LPC2148 serial driver (limited to the serial port 2). +- Implemented HW transmit FIFO preloading in the LPC2142 serial driver in + order to minimize the number of interrupts generated, it is possible to + disable the feature and return to the old code which is a bit smaller, see + the configuration parameters in ./ARM7-LPC214x/GCC/lpc214x_serial.h. *** 0.3.4 *** - Fixed a problem in chVTSetI(). diff --git a/src/include/inline.h b/src/include/inline.h index afcfb9ae3..1982fd075 100644 --- a/src/include/inline.h +++ b/src/include/inline.h @@ -22,6 +22,8 @@ /* * Inlined functions if CH_OPTIMIZE_SPEED is enabled. + * Note: static inlined functions do not duplicate the code in every module + * this is true for GCC, not sure about other compilers. */ #ifdef CH_OPTIMIZE_SPEED static INLINE void fifo_insert(Thread *tp, ThreadsQueue *tqp) {