/********************************************************/
/* ZEN UART library for LPC ARM */
/* */
-/* ver. 3.0 release */
+/* ver. 3.3 release */
/* */
-/* (c) 2006, 2007 Ondrej Spinka, DCE FEE CTU Prague */
+/* (c) 2006-2009 Ondrej Spinka, DCE FEE CTU Prague */
/* */
/* no animals were harmed during development/testing */
/* of this software product, except the author himself */
/* like, safe for satanistic rituals. */
/********************************************************/
+#ifndef _UART_ZEN_H
+#define _UART_ZEN_H
+
#include <types.h>
#include <lpc21xx.h>
* @{
*/
-/*!\def SYSTEM_CLK
-* System clock frequency in Hz.
-*/
-#define SYSTEM_CLK 10000000
-
/*!\def UART_BUFF_LEN
* Incomming data buffer length.
*/
-#define UART_BUFF_LEN 64
+#define UART_BUFF_LEN 250
/*! @} */
/*!\def UART1_OFFSET
* UART1 number.
*/
#define UART1 1
+
+/*! @defgroup error_codes Error Codes
+* @ingroup defines
+* Following constants define the error code masks.
+* @{
+*/
+#define ROUND_BUFFER_OVERRUN_ERR_MASK 0x01
+#define RX_BUFFER_OVERRUN_ERR_MASK 0x02
+#define PARITY_ERR_MASK 0x04
+#define FRAME_ERR_MASK 0x08
+#define BREAK_IRQ_ERR_MASK 0x10
+/*! @} */
/*! @} */
/*! @defgroup prototypes Function Prototypes
/*! UART initialization function.
* Takes three arguments:
-* \param uart_num unsigned 8-bit int UART device number
+* \param uart_num unsigned 8-bit int UART number (0 or 1)
* \param baud_rate unsigned 32-bit int baud rate in bps
+* \param pclk unsigned 32-bit int peripheral clock frequency in Hz
* \param rx_isr_vect unsigned 32-bit int interrupt vector number
*/
-void UART_init ( uint8_t uart_num, uint32_t baud_rate, unsigned rx_isr_vect );
+void UART_init ( uint8_t uart_num, uint32_t baud_rate, uint32_t pclk, unsigned rx_isr_vect );
/*! Data read function.
* \param uart_num unsigned 8-bit int UART number (0 or 1)
/*! Determine possible UART transmission errors.
* \param uart_num unsigned 8-bit int UART number (0 or 1)
-* \return Returns error code (0 no errors, -1 UART error, -2 incoming data buffer overrun).
+* \return Returns error code (0 no errors; bit0 - incoming data buffer overrun, bit1 - overrun error, bit2 - parity error, bit3 - framing error bit4 - break interrupt).
*/
-int8_t UART_test_err ( uint8_t uart_num );
+uint8_t UART_test_err ( uint8_t uart_num );
/*! Determine whether new data wait in the UART round buffer.
* \param uart_num unsigned 8-bit int UART number (0 or 1)
* \return Returns 1 if there are unreaded data in the incoming data buffer, 0 otherwise.
*/
-inline uint8_t UART_new_data ( uint8_t uart_num );
+uint8_t UART_new_data ( uint8_t uart_num );
/*! Data write function.
* Takes two arguments:
* \param uart_num unsigned 8-bit UART number (0 or 1)
* \param data unsigned 8-bit int byte (character) to send
+* \return Returns -1 if line was busy and no data were sent, 0 in case of success.
*/
-void write_UART_data ( uint8_t uart_num, uint8_t data );
+int8_t write_UART_data ( uint8_t uart_num, uint8_t data );
/*! @} */
+
+#endif
\ No newline at end of file
/********************************************************/
/* ZEN UART library for LPC ARM */
/* */
-/* ver. 3.0 release */
+/* ver. 3.3 release */
/* */
-/* (c) 2006, 2007 Ondrej Spinka, DCE FEE CTU Prague */
-/* modified: 2008 Jiri Kubias DCE FEE CTU */
-/* - fixed baudrate computing */
+/* (c) 2006-2009 Ondrej Spinka, DCE FEE CTU Prague */
/* */
/* no animals were harmed during development/testing */
/* of this software product, except the author himself */
#define UART_REG_ADDR(base_reg, dev_num) ( *( (volatile char *) ( ( (volatile void *) &base_reg ) + ( (dev_num) * UART1_OFFSET ) ) ) )
/*! @} */
-volatile uint8_t err_flag[2] = {0, 0}, new_data_flag[2] = {0, 0}, over_flag[2] = {0, 0}; //!< UART0 and UART1 error flags, new data flags and buffer overflow flags
-volatile uint8_t i_w[2] = {0, 0}, i_r[2] = {0, 0}; //!< UART0 and UART1 read and write buffer indexes
+volatile uint8_t err_flag[2] = {0, 0}; //!< UART0 and UART1 error flags
+volatile uint16_t write_buffer_index[2] = {0, 0}, read_buffer_index[2] = {0, 0}; //!< UART0 and UART1 read and write buffer indexes
uint8_t buff[2][UART_BUFF_LEN]; //!< UART0 and UART1 data buffers
/*! UART0 interrupt handler prototype */
* \param uart_num unsigned 8-bit int UART number (0 or 1)
*/
void UART_isr ( uint8_t uart_num ) {
- if ( i_w[uart_num] > UART_BUFF_LEN - 1 ) i_w[uart_num] = 0; // when buffer is full, start overwriting oldest data
-
- err_flag[uart_num] = UART_REG_ADDR ( U0LSR, uart_num ) & 0x8E; // check the line status
+ if ( !( err_flag[uart_num] & 0x1E ) ) err_flag[uart_num] |= UART_REG_ADDR ( U0LSR, uart_num ) & 0x1E; // check the line status
if ( ( UART_REG_ADDR ( U0IIR, uart_num ) & RX_MASK ) == RX_INT ) { // if Rx data ready IRQ is pending
- buff[uart_num][i_w[uart_num]++] = UART_REG_ADDR ( U0RBR, uart_num ); // store new character into the receive buffer
- new_data_flag[uart_num] = 1; // set the new data flag
- }
-
- if ( i_w[uart_num] == i_r[uart_num] ) { // when round buffer is full
- i_r[uart_num]++; // shift the oldest byte pointer
- over_flag[uart_num] = 1; // set the data overwrite flag
+ buff[uart_num][write_buffer_index[uart_num]] = UART_REG_ADDR ( U0RBR, uart_num ); // store new character into the receive buffer
+ if ( ++write_buffer_index[uart_num] >= UART_BUFF_LEN ) write_buffer_index[uart_num] = 0; // shift the write buffer index
+
+ if ( write_buffer_index[uart_num] == read_buffer_index[uart_num] ) { // when round buffer is full (overflow condition)
+ if ( write_buffer_index[uart_num] == 0 ) write_buffer_index[uart_num] = UART_BUFF_LEN - 1; else write_buffer_index[uart_num]--; // shift the write buffer index back
+ UART_REG_ADDR ( U0IER, uart_num ) = 0x00; // disable Rx interrupt (to prevent new data reception)
+ err_flag[uart_num] |= 0x01; // set the overflow condition bit in the error flag
+ }
}
-
- VICVectAddr = 0; // int acknowledge
}
/*! UART0 Rx interrupt service rutine.
* This rutine might be modified according user demands.
*/
void UART0_irq ( void ) {
- UART_isr ( UART0 );
+ UART_isr ( UART0 ); // call UART0 ISR
+ VICVectAddr = 0; // int acknowledge
}
/*! UART1 Rx interrupt service rutine.
* This rutine might be modified according user demands.
*/
void UART1_irq ( void ) {
- UART_isr ( UART1 );
+ UART_isr ( UART1 ); // call UART1 ISR
+ VICVectAddr = 0; // int acknowledge
}
/*! UART initialization function.
* Takes three arguments:
* \param uart_num unsigned 8-bit int UART number (0 or 1)
* \param baud_rate unsigned 32-bit int baud rate in bps
+* \param pclk unsigned 32-bit int peripheral clock frequency in Hz
* \param rx_isr_vect unsigned 32-bit int interrupt vector number
*/
-void UART_init ( uint8_t uart_num, uint32_t baud_rate, unsigned rx_isr_vect ) {
+void UART_init ( uint8_t uart_num, uint32_t baud_rate, uint32_t pclk, unsigned rx_isr_vect ) {
+ uint16_t divisor = ( pclk + ( ( baud_rate * 16 ) / 2 ) ) / ( baud_rate * 16 ); // baud divisor computation
- uint16_t divisor = (SYSTEM_CLK + (baud_rate * 16)/2) / (baud_rate * 16); // baud divisor computation
-
-
PINSEL0 &= ( 0xFFFFFFF0 - ( uart_num * 0xEFFF1 ) ); //enable UART functionality on respective processor pins
PINSEL0 |= ( 0x00000005 + ( uart_num * 0x4FFFB ) );
UART_REG_ADDR ( U0LCR, uart_num ) = 0x83; // 8-bit data, no parity, set DLAB = 1
UART_REG_ADDR ( U0DLM, uart_num ) = *( ( (uint8_t *) &divisor ) + 1 ); // write divisor hi-byte
UART_REG_ADDR ( U0LCR, uart_num ) &= 0x7F; // clear DLAB
UART_REG_ADDR ( U0FCR, uart_num ) = 0x01; // enable UART FIFO, interrupt level 1 byte - this might be modified by the user
- UART_REG_ADDR ( U0IER, uart_num ) = 0x01; // enable RBR interrupt
+ UART_REG_ADDR ( U0IER, uart_num ) = 0x01; // enable Rx interrupt
if ( !uart_num ) ( ( uint32_t * ) &VICVectAddr0 )[rx_isr_vect] = ( uint32_t ) UART0_irq; // if UART0 register UART0 interrupt handler
else ( ( uint32_t * ) &VICVectAddr0 )[rx_isr_vect] = ( uint32_t ) UART1_irq; // else register UART1 interrupt handler
-
+
( ( uint32_t * ) &VICVectCntl0 )[rx_isr_vect] = 0x20 | ( 6 + uart_num ); // enable IRQ slot, set UART interrupt number
VICIntEnable = ( ( uart_num + 1 ) * 0x00000040 ); //enable UART IRQ
}
uint8_t read_UART_data ( uint8_t uart_num ) {
uint8_t data; // readed data byte
- while ( !new_data_flag[uart_num] ); // wait for new Rx data
+ while ( read_buffer_index[uart_num] == write_buffer_index[uart_num] ); // wait for new Rx data
- if ( i_r[uart_num] > UART_BUFF_LEN - 1 ) i_r[uart_num] = 0; // when top of the buffer is reached, return the read pointer to 0
- data = buff[uart_num][i_r[uart_num]++]; // read new data from the data buffer
- if ( i_r[uart_num] == i_w[uart_num] ) new_data_flag[uart_num] = 0; // when all data was read clear the new data flag
+ data = buff[uart_num][read_buffer_index[uart_num]]; // read new data from the data buffer
+ if ( ++read_buffer_index[uart_num] >= UART_BUFF_LEN ) read_buffer_index[uart_num] = 0; // shift the oldest unread byte index
+
+ if ( ( err_flag[uart_num] & 0x01 ) && ( read_buffer_index[uart_num] == write_buffer_index[uart_num] ) ) { // if in overflow condition and buffer is empty
+ err_flag[uart_num] &= 0xFE; // clear the overflow condition bit
+ UART_REG_ADDR ( U0IER, uart_num ) = 0x01; // enable Rx interrupt (to allow new data reception)
+ }
return data; // return new data byte
}
/*! Determine possible UART transmission errors.
* \param uart_num unsigned 8-bit int UART number (0 or 1)
-* \return Returns error code (0 no errors, -1 UART error, -2 incoming data buffer overrun).
+* \return Returns error code (0 no errors; bit0 - incoming data buffer overrun, bit1 - overrun error, bit2 - parity error, bit3 - framing error bit4 - break interrupt).
*/
-int8_t UART_test_err ( uint8_t uart_num ) {
- if ( err_flag[uart_num] ) { // check the UART0 error flag
- err_flag[uart_num] = 0; // reset the UART0 error flag
- return -1; // return error code
- }
-
- if ( over_flag[uart_num] ) { // check the UART0 incoming data buffer overrun flag
- over_flag[uart_num] = 0; // reset the UART0 incoming data buffer overrun flag
- return -2; // return error code
- }
-
- return 0; // no errors
+uint8_t UART_test_err ( uint8_t uart_num ) {
+ uint8_t aux = err_flag[uart_num]; // store the error flag into auxiliary variable
+ err_flag[uart_num] &= 0x01; // reset the error flag (but preserve the overflow condition bit)
+ return aux; // return error code
}
/*! Determine whether new data wait in the UART round buffer.
* \param uart_num unsigned 8-bit int UART number (0 or 1)
* \return Returns 1 if there are unreaded data in the incoming data buffer, 0 otherwise.
*/
-inline uint8_t UART_new_data ( uint8_t uart_num ) {
- return new_data_flag[uart_num]; // return UART new data flag
+uint8_t UART_new_data ( uint8_t uart_num ) {
+ if ( read_buffer_index[uart_num] == write_buffer_index[uart_num] ) return 0; // check whether round buffer is empty
+ else return 1; // if not empty, return 1
}
/*! Data write function.
* Takes two arguments:
* \param uart_num unsigned 8-bit UART number (0 or 1)
* \param data unsigned 8-bit int byte (character) to send
+* \return Returns -1 if line was busy and no data were sent, 0 in case of success.
*/
-void write_UART_data ( uint8_t uart_num, uint8_t data ) {
- while ( !( UART_REG_ADDR ( U0LSR, uart_num ) & TX_EMPTY ) ); // wait for the transmitter holding register emptying
+int8_t write_UART_data ( uint8_t uart_num, uint8_t data ) {
+ if ( !( UART_REG_ADDR ( U0LSR, uart_num ) & TX_EMPTY ) ) return -1; // if transmitter holding register is not empty, return -1
UART_REG_ADDR ( U0THR, uart_num ) = data; // write the data byte to the transmitter holding register
+ return 0; // return success
}