/****************************************************************************** * * $RCSfile: $ * $Revision: $ * * This module provides interface routines to the LPC ARM UARTs. * Copyright 2004, R O SoftWare * No guarantees, warrantees, or promises, implied or otherwise. * May be used for hobby or commercial purposes provided copyright * notice remains intact. * * Modified by Martin Thomas for LPC23xx 24xx *****************************************************************************/ #include "app_types.h" #include "LPC_REGS.h" #include "sys_config.h" #include "uart3.h" #ifndef USHRT_MAX #define USHRT_MAX 16 #endif #include "armVIC.h" #include "uart3ISR.h" #define U3_TX_PINSEL_REG PINSEL0 #define U3_TX_PINSEL (2UL<<0) /* PINSEL4 Value for UART3 TX */ #define U3_TX_PINMASK (3UL<<0) /* PINSEL4 Mask for UART3 RX */ #define U3_RX_PINSEL_REG PINSEL0 #define U3_RX_PINSEL (2UL<<2) /* PINSEL4 Value for UART3 TX */ #define U3_RX_PINMASK (3UL<<2) /* PINSEL4 Mask for UART3 RX */ uint8_t uart3_rx_buffer[UART3_RX_BUFFER_SIZE]; uint16_t uart3_rx_insert_idx, uart3_rx_extract_idx; uint8_t uart3_tx_buffer[UART3_TX_BUFFER_SIZE]; uint16_t uart3_tx_insert_idx, uart3_tx_extract_idx; int uart3_tx_running; t_uart3_txcomplete uart3_tx_complete_callback; void uart3TxFinished(void); void uart3Init(uint16_t baud, uint8_t mode, uint8_t fmode) { PCONP |= BIT( 25 ); // power on UART3 // set port pins for UART3 // mthomas PINSEL0 = (PINSEL0 & ~U0_PINMASK) | U0_PINSEL; // set port pins for UART3 // PINSEL0 = (PINSEL0 & ~U0_PINMASK) | U0_PINSEL; U3_TX_PINSEL_REG = ( U3_TX_PINSEL_REG & ~U3_TX_PINMASK ) | U3_TX_PINSEL; U3_RX_PINSEL_REG = ( U3_RX_PINSEL_REG & ~U3_RX_PINMASK ) | U3_RX_PINSEL; U3IER = 0x00; // disable all interrupts U3IIR; // clear interrupt ID U3RBR; // clear receive register U3LSR; // clear line status register // Set CLOCK for UART3 device (4x) //PCLKSEL1 = 0x00040000; // Set CLOCK for UART3 device (4x) PCLKSEL1 &= 0xFFF7FFFF; PCLKSEL1 |= 0x00080000; // Preset callback function uart3_tx_complete_callback = 0; // set the baudrate U3LCR = ULCR_DLAB_ENABLE; // select divisor latches U3DLL = (uint8_t)baud; // set for baud low byte U3DLM = (uint8_t)(baud >> 8); // set for baud high byte // set the number of characters and other // user specified operating parameters U3LCR = (mode & ~ULCR_DLAB_ENABLE); U3FCR = fmode; // initialize the interrupt vector VICIntSelect &= ~VIC_CHAN_TO_MASK(VIC_CHAN_NUM_UART3); VICIntEnClr = VIC_CHAN_TO_MASK(VIC_CHAN_NUM_UART3); VICVectAddr29 = (uint32_t)uart3ISR; VICVectPriority29 = 0xF; VICIntEnable = VIC_CHAN_TO_MASK(VIC_CHAN_NUM_UART3); // initialize the transmit data queue uart3_tx_extract_idx = uart3_tx_insert_idx = 0; uart3_tx_running = 0; // initialize the receive data queue uart3_rx_extract_idx = uart3_rx_insert_idx = 0; // enable receiver interrupts U3IER = UIER_RBR; } /****************************************************************************** * * Function Name: uart3Putch() * * Description: * This function puts a character into the UART output queue for * transmission. * * Calling Sequence: * character to be transmitted * * Returns: * ch on success, -1 on error (queue full) * *****************************************************************************/ int uart3Putch(int ch) { uint16_t temp; unsigned cpsr; temp = (uart3_tx_insert_idx + 1) % UART3_TX_BUFFER_SIZE; if (temp == uart3_tx_extract_idx) return -1; // no room cpsr = disableIRQ(); // disable global interrupts U3IER &= ~UIER_THRE; // disable TX interrupts restoreIRQ(cpsr); // restore global interrupts // check if in process of sending data if (uart3_tx_running) { // add to queue uart3_tx_buffer[uart3_tx_insert_idx] = (uint8_t)ch; uart3_tx_insert_idx = temp; } else { // set running flag and write to output register uart3_tx_running = 1; U3THR = (uint8_t)ch; } cpsr = disableIRQ(); // disable global interrupts U3IER |= UIER_THRE; // enable TX interrupts restoreIRQ(cpsr); // restore global interrupts return (uint8_t)ch; } /****************************************************************************** * * Function Name: uart3Space() * * Description: * This function gets the available space in the transmit queue * * Calling Sequence: * void * * Returns: * available space in the transmit queue * *****************************************************************************/ uint16_t uart3Space(void) { int space; if ((space = (uart3_tx_extract_idx - uart3_tx_insert_idx)) <= 0) space += UART3_TX_BUFFER_SIZE; return (uint16_t)(space - 1); } /****************************************************************************** * * Function Name: uart3Puts() * * Description: * This function writes a NULL terminated 'string' to the UART output * queue, returning a pointer to the next character to be written. * * Calling Sequence: * address of the string * * Returns: * a pointer to the next character to be written * (\0 if full string is written) * *****************************************************************************/ const char *uart3Puts(const char *string) { register char ch; while ((ch = *string) && (uart3Putch(ch) >= 0)) string++; return string; } /****************************************************************************** * * Function Name: uart3Write() * * Description: * This function writes 'count' characters from 'buffer' to the UART * output queue. * * Calling Sequence: * * * Returns: * 0 on success, -1 if insufficient room, -2 on error * NOTE: if insufficient room, no characters are written. * *****************************************************************************/ int uart3Write(const char *buffer, uint16_t count) { if (count > uart3Space()) return -1; while (count && (uart3Putch(*buffer++) >= 0)) count--; return (count ? -2 : 0); } /****************************************************************************** * * Function Name: uart3TxEmpty() * * Description: * This function returns the status of the UART transmit data * registers. * * Calling Sequence: * void * * Returns: * FALSE - either the tx holding or shift register is not empty * !FALSE - if both the tx holding & shift registers are empty * *****************************************************************************/ int uart3TxEmpty(void) { return (U3LSR & (ULSR_THRE | ULSR_TEMT)) == (ULSR_THRE | ULSR_TEMT); } int uart3RxEmpty(void) { if (uart3_rx_insert_idx == uart3_rx_extract_idx) // check if character is available { return 1; } else { return 0; } } /****************************************************************************** * * Function Name: uart3TxFlush() * * Description: * This function removes all characters from the UART transmit queue * (without transmitting them). * * Calling Sequence: * void * * Returns: * void * *****************************************************************************/ void uart3TxFlush(void) { unsigned cpsr; U3FCR |= UFCR_TX_FIFO_RESET; // clear the TX fifo // "Empty" the transmit buffer. cpsr = disableIRQ(); // disable global interrupts U3IER &= ~UIER_THRE; // disable TX interrupts restoreIRQ(cpsr); // restore global interrupts uart3_tx_insert_idx = uart3_tx_extract_idx = 0; } /****************************************************************************** * * Function Name: uart3Getch() * * Description: * This function gets a character from the UART receive queue * * Calling Sequence: * void * * Returns: * character on success, -1 if no character is available * *****************************************************************************/ int uart3Getch(void) { uint8_t ch; if (uart3_rx_insert_idx == uart3_rx_extract_idx) // check if character is available return -1; ch = uart3_rx_buffer[uart3_rx_extract_idx++]; // get character, bump pointer uart3_rx_extract_idx %= UART3_RX_BUFFER_SIZE; // limit the pointer return ch; } void uart3SubscribeTxFinished( t_uart3_txcomplete callback ) { uart3_tx_complete_callback = callback; } void uart3UnsubsribeTxFinished( t_uart3_txcomplete callback ) { uart3_tx_complete_callback = 0; } void uart3TxFinished(void) { if (uart3_tx_complete_callback != 0) { uart3_tx_complete_callback(); } }