/******************************************************************************* * (c) Copyright 2011-2013 Microsemi SoC Products Group. All rights reserved. * * SmartFusion2 Microcontroller Subsystem MMUART bare metal software driver * implementation. * * SVN $Revision: 5610 $ * SVN $Date: 2013-04-05 18:49:30 +0530 (Fri, 05 Apr 2013) $ */ #include "mss_uart.h" #include "mss_uart_regs.h" #include "../../CMSIS/mss_assert.h" #include "../../CMSIS/hw_reg_io.h" #include "../../CMSIS/system_m2sxxx.h" #ifdef __cplusplus extern "C" { #endif /******************************************************************************* * Defines */ #define TX_COMPLETE 0u #define TX_FIFO_SIZE 16u #define FCR_TRIG_LEVEL_MASK 0xC0u #define IIRF_MASK 0x0Fu #define INVALID_INTERRUPT 0u #define INVALID_IRQ_HANDLER ((mss_uart_irq_handler_t) 0) #define NULL_HANDLER ((mss_uart_irq_handler_t) 0) #define MSS_UART_DATA_READY ((uint8_t) 0x01) #define SYNC_ASYNC_MODE_MASK (0x7u) /******************************************************************************* * Possible values for Interrupt Identification Register Field. */ #define IIRF_MODEM_STATUS 0x00u #define IIRF_THRE 0x02u #define IIRF_MMI 0x03u #define IIRF_RX_DATA 0x04u #define IIRF_RX_LINE_STATUS 0x06u #define IIRF_DATA_TIMEOUT 0x0Cu /******************************************************************************* * Receiver error status mask. */ #define STATUS_ERROR_MASK ( MSS_UART_OVERUN_ERROR | MSS_UART_PARITY_ERROR | \ MSS_UART_FRAMING_ERROR | MSS_UART_BREAK_ERROR | \ MSS_UART_FIFO_ERROR) /******************************************************************************* * Cortex-M3 interrupt handler functions implemented as part of the MSS UART * driver. */ #if defined(__GNUC__) __attribute__((__interrupt__)) void UART0_IRQHandler(void); #else void UART0_IRQHandler(void); #endif #if defined(__GNUC__) __attribute__((__interrupt__)) void UART1_IRQHandler(void); #else void UART1_IRQHandler(void); #endif /******************************************************************************* * Local functions. */ static void global_init(mss_uart_instance_t * this_uart, uint32_t baud_rate, uint8_t line_config); static void MSS_UART_isr(mss_uart_instance_t * this_uart); static void default_tx_handler(mss_uart_instance_t * this_uart); static void config_baud_divisors ( mss_uart_instance_t * this_uart, uint32_t baudrate ); /******************************************************************************* * Instance definitions */ mss_uart_instance_t g_mss_uart0; mss_uart_instance_t g_mss_uart1; /******************************************************************************* * Public Functions *******************************************************************************/ /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_init ( mss_uart_instance_t* this_uart, uint32_t baud_rate, uint8_t line_config ) { /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only * mss_uart_instance_t instances used to identify UART0 and UART1. */ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); /* Perform generic initialization */ global_init(this_uart, baud_rate, line_config); /* Disable LIN mode */ clear_bit_reg8(&this_uart->hw_reg->MM0, ELIN); /* Disable IrDA mode */ clear_bit_reg8(&this_uart->hw_reg->MM1, EIRD); /* Disable SmartCard Mode */ clear_bit_reg8(&this_uart->hw_reg->MM2, EERR); /* set default tx handler for automated TX using interrupt in USART mode */ this_uart->tx_handler = default_tx_handler; } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_lin_init ( mss_uart_instance_t* this_uart, uint32_t baud_rate, uint8_t line_config ) { /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only * mss_uart_instance_t instances used to identify UART0 and UART1. */ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); /* Perform generic initialization */ global_init(this_uart, baud_rate, line_config); /* Enable LIN mode */ set_bit_reg8(&this_uart->hw_reg->MM0, ELIN); /* Disable IrDA mode */ clear_bit_reg8(&this_uart->hw_reg->MM1, EIRD); /* Disable SmartCard Mode */ clear_bit_reg8(&this_uart->hw_reg->MM2, EERR); } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_irda_init ( mss_uart_instance_t* this_uart, uint32_t baud_rate, uint8_t line_config, mss_uart_rzi_polarity_t rxpol, mss_uart_rzi_polarity_t txpol, mss_uart_rzi_pulsewidth_t pw ) { /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only * mss_uart_instance_t instances used to identify UART0 and UART1. */ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); /* Perform generic initialization */ global_init(this_uart, baud_rate, line_config); /* Enable LIN mode */ clear_bit_reg8(&this_uart->hw_reg->MM0, ELIN); /* Disable IrDA mode */ set_bit_reg8(&this_uart->hw_reg->MM1, EIRD); ((rxpol == MSS_UART_ACTIVE_LOW) ? clear_bit_reg8(&this_uart->hw_reg->MM1,EIRX) : set_bit_reg8(&this_uart->hw_reg->MM1,EIRX)); ((txpol == MSS_UART_ACTIVE_LOW) ? clear_bit_reg8(&this_uart->hw_reg->MM1,EITX) : set_bit_reg8(&this_uart->hw_reg->MM1,EITX)); ((pw == MSS_UART_3_BY_16) ? clear_bit_reg8(&this_uart->hw_reg->MM1,EITP) : set_bit_reg8(&this_uart->hw_reg->MM1,EITP)); /* Disable SmartCard Mode */ clear_bit_reg8(&this_uart->hw_reg->MM2, EERR); } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_smartcard_init ( mss_uart_instance_t* this_uart, uint32_t baud_rate, uint8_t line_config ) { /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only * mss_uart_instance_t instances used to identify UART0 and UART1. */ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); /* Perform generic initialization */ global_init(this_uart, baud_rate, line_config); /* Disable LIN mode */ clear_bit_reg8(&this_uart->hw_reg->MM0, ELIN); /* Disable IrDA mode */ clear_bit_reg8(&this_uart->hw_reg->MM1, EIRD); /* Enable SmartCard Mode : Only when data is 8-bit and 2 stop bits*/ if( ( MSS_UART_DATA_8_BITS | MSS_UART_TWO_STOP_BITS) == (line_config & (MSS_UART_DATA_8_BITS | MSS_UART_TWO_STOP_BITS))) { set_bit_reg8(&this_uart->hw_reg->MM2, EERR); /* Enable single wire half-duplex mode */ set_bit_reg8(&this_uart->hw_reg->MM2,ESWM); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_polled_tx ( mss_uart_instance_t * this_uart, const uint8_t * pbuff, uint32_t tx_size ) { uint32_t char_idx = 0u; uint32_t size_sent; uint8_t status; ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(pbuff != ( (uint8_t *)0)); ASSERT(tx_size > 0u); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (pbuff != ((uint8_t *)0)) && (tx_size > 0u)) { /* Remain in this loop until the entire input buffer * has been transferred to the UART. */ do { /* Read the Line Status Register and update the sticky record */ status = this_uart->hw_reg->LSR; this_uart->status |= status; /* Check if TX FIFO is empty. */ if(status & MSS_UART_THRE) { uint32_t fill_size = TX_FIFO_SIZE; /* Calculate the number of bytes to transmit. */ if(tx_size < TX_FIFO_SIZE) { fill_size = tx_size; } /* Fill the TX FIFO with the calculated the number of bytes. */ for(size_sent = 0u; size_sent < fill_size; ++size_sent) { /* Send next character in the buffer. */ this_uart->hw_reg->THR = pbuff[char_idx]; char_idx++; } /* Calculate the number of untransmitted bytes remaining. */ tx_size -= size_sent; } } while(tx_size); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_polled_tx_string ( mss_uart_instance_t * this_uart, const uint8_t * p_sz_string ) { uint32_t char_idx = 0u; uint32_t fill_size; uint8_t data_byte; uint8_t status; ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(p_sz_string != ((uint8_t *)0)); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (p_sz_string != ((uint8_t *)0))) { /* Get the first data byte from the input buffer */ data_byte = p_sz_string[char_idx]; /* First check for the NULL terminator byte. * Then remain in this loop until the entire string in the input buffer * has been transferred to the UART. */ while(0u != data_byte) { /* Wait until TX FIFO is empty. */ do { status = this_uart->hw_reg->LSR; this_uart->status |= status; } while (0u == (status & MSS_UART_THRE)); /* Send bytes from the input buffer until the TX FIFO is full * or we reach the NULL terminator byte. */ fill_size = 0u; while((0u != data_byte) && (fill_size < TX_FIFO_SIZE)) { /* Send the data byte */ this_uart->hw_reg->THR = data_byte; ++fill_size; char_idx++; /* Get the next data byte from the input buffer */ data_byte = p_sz_string[char_idx]; } } } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_irq_tx ( mss_uart_instance_t * this_uart, const uint8_t * pbuff, uint32_t tx_size ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(pbuff != ((uint8_t *)0)); ASSERT(tx_size > 0u); if((tx_size > 0u) && ( pbuff != ((uint8_t *)0)) && ((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))) { /*Initialise the transmit info for the UART instance with the arguments.*/ this_uart->tx_buffer = pbuff; this_uart->tx_buff_size = tx_size; this_uart->tx_idx = (uint16_t)0; /* Clear any previously pended interrupts */ NVIC_ClearPendingIRQ(this_uart->irqn); /* assign default handler for data transfer */ this_uart->tx_handler = default_tx_handler; /* enables TX interrupt */ set_bit_reg8(&this_uart->hw_reg->IER,ETBEI); /* Enable UART instance interrupt in Cortex-M3 NVIC. */ NVIC_EnableIRQ(this_uart->irqn); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ int8_t MSS_UART_tx_complete ( mss_uart_instance_t * this_uart ) { int8_t ret_value = 0; uint8_t status = 0u; ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /* Read the Line Status Register and update the sticky record. */ status = this_uart->hw_reg->LSR; this_uart->status |= status; if((TX_COMPLETE == this_uart->tx_buff_size) && ((status & MSS_UART_TEMT) != 0u)) { ret_value = (int8_t)1; } } return ret_value; } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ size_t MSS_UART_get_rx ( mss_uart_instance_t * this_uart, uint8_t * rx_buff, size_t buff_size ) { size_t rx_size = 0u; uint8_t status = 0u; ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(rx_buff != ((uint8_t *)0)); ASSERT(buff_size > 0u); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (rx_buff != ((uint8_t *)0)) && (buff_size > 0u)) { status = this_uart->hw_reg->LSR; this_uart->status |= status; while(((status & MSS_UART_DATA_READY) != 0u) && (rx_size < buff_size)) { rx_buff[rx_size] = this_uart->hw_reg->RBR; ++rx_size; status = this_uart->hw_reg->LSR; this_uart->status |= status; } } return rx_size; } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_enable_irq ( mss_uart_instance_t * this_uart, mss_uart_irq_t irq_mask ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(MSS_UART_INVALID_IRQ > irq_mask); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (MSS_UART_INVALID_IRQ > irq_mask)) { /* Clear any previously pended interrupts */ NVIC_ClearPendingIRQ(this_uart->irqn); /* irq_mask encoding: 1- enable * bit 0 - Receive Data Available Interrupt * bit 1 - Transmitter Holding Register Empty Interrupt * bit 2 - Receiver Line Status Interrupt * bit 3 - Modem Status Interrupt */ this_uart->hw_reg->IER |= (uint8_t)irq_mask & IIRF_MASK; /* * bit 4 - Receiver time-out interrupt * bit 5 - NACK / ERR signal interrupt * bit 6 - PID parity error interrupt * bit 7 - LIN break detection interrupt * bit 8 - LIN Sync detection interrupt */ this_uart->hw_reg->IEM |= (uint8_t)(((uint32_t)irq_mask & ~((uint32_t)IIRF_MASK)) >> 4u); /* Enable UART instance interrupt in Cortex-M3 NVIC. */ NVIC_EnableIRQ(this_uart->irqn); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_disable_irq ( mss_uart_instance_t * this_uart, mss_uart_irq_t irq_mask ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /* irq_mask encoding: 1 - disable * bit 0 - Receive Data Available Interrupt * bit 1 - Transmitter Holding Register Empty Interrupt * bit 2 - Receiver Line Status Interrupt * bit 3 - Modem Status Interrupt */ this_uart->hw_reg->IER &= ((uint8_t)(~((uint32_t)irq_mask & (uint32_t)IIRF_MASK))); /* * bit 4 - Receiver time-out interrupt * bit 5 - NACK / ERR signal interrupt * bit 6 - PID parity error interrupt * bit 7 - LIN break detection interrupt * bit 8 - LIN Sync detection interrupt */ this_uart->hw_reg->IEM |= (uint8_t)(~(((uint32_t)irq_mask & ~((uint32_t)IIRF_MASK)) >> 8u)); /* Clear any previously pended interrupts */ NVIC_ClearPendingIRQ(this_uart->irqn); if(irq_mask == IIRF_MASK) { /* Disable UART instance interrupt in Cortex-M3 NVIC. */ NVIC_DisableIRQ(this_uart->irqn); } } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_rx_handler ( mss_uart_instance_t * this_uart, mss_uart_irq_handler_t handler, mss_uart_rx_trig_level_t trigger_level ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(handler != INVALID_IRQ_HANDLER ); ASSERT(trigger_level < MSS_UART_FIFO_INVALID_TRIG_LEVEL); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (handler != INVALID_IRQ_HANDLER) && (trigger_level < MSS_UART_FIFO_INVALID_TRIG_LEVEL)) { this_uart->rx_handler = handler; /* Set the receive interrupt trigger level. */ this_uart->hw_reg->FCR = (this_uart->hw_reg->FCR & (uint8_t)(~((uint8_t)FCR_TRIG_LEVEL_MASK))) | (uint8_t)trigger_level; /* Clear any previously pended interrupts */ NVIC_ClearPendingIRQ(this_uart->irqn); /* Enable receive interrupt. */ set_bit_reg8(&this_uart->hw_reg->IER,ERBFI); /* Enable UART instance interrupt in Cortex-M3 NVIC. */ NVIC_EnableIRQ(this_uart->irqn); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_loopback ( mss_uart_instance_t * this_uart, mss_uart_loopback_t loopback ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(MSS_UART_INVALID_LOOPBACK > loopback); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) || (MSS_UART_INVALID_LOOPBACK > loopback)) { switch(loopback) { case MSS_UART_LOCAL_LOOPBACK_OFF: /* Disable local loopback */ clear_bit_reg8(&this_uart->hw_reg->MCR,LOOP); break; case MSS_UART_LOCAL_LOOPBACK_ON: /* Enable local loopback */ set_bit_reg8(&this_uart->hw_reg->MCR,LOOP); break; case MSS_UART_REMOTE_LOOPBACK_OFF: case MSS_UART_AUTO_ECHO_OFF: /* Disable remote loopback & automatic echo*/ this_uart->hw_reg->MCR &= ~RLOOP_MASK; break; case MSS_UART_REMOTE_LOOPBACK_ON: /* Enable remote loopback */ this_uart->hw_reg->MCR |= (1u << RLOOP); break; case MSS_UART_AUTO_ECHO_ON: /* Enable automatic echo */ this_uart->hw_reg->MCR |= (1u << ECHO); break; case MSS_UART_INVALID_LOOPBACK: /* Fall through to default. */ default: ASSERT(0); break; } } } /***************************************************************************//** * UART0 interrupt service routine. * UART0_IRQHandler is included within the Cortex-M3 vector table as part of the * Fusion 2 CMSIS. */ #if defined(__GNUC__) __attribute__((__interrupt__)) void UART0_IRQHandler(void) #else void UART0_IRQHandler(void) #endif { MSS_UART_isr(&g_mss_uart0); } /***************************************************************************//** * UART1 interrupt service routine. * UART2_IRQHandler is included within the Cortex-M3 vector table as part of the * Fusion 2 CMSIS. */ #if defined(__GNUC__) __attribute__((__interrupt__)) void UART1_IRQHandler(void) #else void UART1_IRQHandler(void) #endif { MSS_UART_isr(&g_mss_uart1); } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_rxstatus_handler ( mss_uart_instance_t * this_uart, mss_uart_irq_handler_t handler ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(handler != INVALID_IRQ_HANDLER); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (handler != INVALID_IRQ_HANDLER)) { this_uart->linests_handler = handler; /* Clear any previously pended interrupts */ NVIC_ClearPendingIRQ(this_uart->irqn); /* Enable receiver line status interrupt. */ set_bit_reg8(&this_uart->hw_reg->IER,ELSI); /* Enable UART instance interrupt in Cortex-M3 NVIC. */ NVIC_EnableIRQ(this_uart->irqn); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_tx_handler ( mss_uart_instance_t * this_uart, mss_uart_irq_handler_t handler ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(handler != INVALID_IRQ_HANDLER); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (handler != INVALID_IRQ_HANDLER)) { this_uart->tx_handler = handler; /* Make TX buffer info invalid */ this_uart->tx_buffer = (const uint8_t *)0; this_uart->tx_buff_size = 0u; /* Clear any previously pended interrupts */ NVIC_ClearPendingIRQ(this_uart->irqn); /* Enable transmitter holding register Empty interrupt. */ set_bit_reg8(&this_uart->hw_reg->IER,ETBEI); /* Enable UART instance interrupt in Cortex-M3 NVIC. */ NVIC_EnableIRQ(this_uart->irqn); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_modemstatus_handler ( mss_uart_instance_t * this_uart, mss_uart_irq_handler_t handler ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(handler != INVALID_IRQ_HANDLER); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (handler != INVALID_IRQ_HANDLER)) { this_uart->modemsts_handler = handler; /* Clear any previously pended interrupts */ NVIC_ClearPendingIRQ(this_uart->irqn); /* Enable modem status interrupt. */ set_bit_reg8(&this_uart->hw_reg->IER,EDSSI); /* Enable UART instance interrupt in Cortex-M3 NVIC. */ NVIC_EnableIRQ(this_uart->irqn); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ size_t MSS_UART_fill_tx_fifo ( mss_uart_instance_t * this_uart, const uint8_t * tx_buffer, size_t tx_size ) { uint8_t status = 0u; size_t size_sent = 0u; ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(tx_buffer != ( (uint8_t *)0)); ASSERT(tx_size > 0); /* Fill the UART's Tx FIFO until the FIFO is full or the complete input * buffer has been written. */ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (tx_buffer != ((uint8_t *)0)) && (tx_size > 0u)) { status = this_uart->hw_reg->LSR; this_uart->status |= status; if(status & MSS_UART_THRE) { uint32_t fill_size = TX_FIFO_SIZE; if(tx_size < TX_FIFO_SIZE) { fill_size = tx_size; } /* Fill up FIFO */ for(size_sent = 0u; size_sent < fill_size; ++size_sent) { /* Send next character in the buffer. */ this_uart->hw_reg->THR = tx_buffer[size_sent]; } } } return size_sent; } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ uint8_t MSS_UART_get_rx_status ( mss_uart_instance_t * this_uart ) { uint8_t status = MSS_UART_INVALID_PARAM; ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /* * Extract UART receive error status. * Bit 1 - Overflow error status * Bit 2 - Parity error status * Bit 3 - Frame error status * Bit 4 - Break interrupt indicator * Bit 7 - FIFO data error status */ this_uart->status |= (this_uart->hw_reg->LSR); status = (this_uart->status & STATUS_ERROR_MASK); /* Clear the sticky status after reading */ this_uart->status = 0u; } return status; } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ uint8_t MSS_UART_get_modem_status ( mss_uart_instance_t * this_uart ) { uint8_t status = MSS_UART_INVALID_PARAM; ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /* * Extract UART modem status and place in lower bits of "status". * Bit 0 - Delta Clear to Send Indicator * Bit 1 - Delta Clear to Receive Indicator * Bit 2 - Trailing edge of Ring Indicator detector * Bit 3 - Delta Data Carrier Detect indicator * Bit 4 - Clear To Send * Bit 5 - Data Set Ready * Bit 6 - Ring Indicator * Bit 7 - Data Carrier Detect */ status = this_uart->hw_reg->MSR; } return status; } /***************************************************************************//** * MSS_UART_get_tx_status. * See mss_uart.h for details of how to use this function. */ uint8_t MSS_UART_get_tx_status ( mss_uart_instance_t * this_uart ) { uint8_t status = MSS_UART_TX_BUSY; ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /* Read the Line Status Register and update the sticky record. */ status = this_uart->hw_reg->LSR; this_uart->status |= status; /* * Extract the transmit status bits from the UART's Line Status Register. * Bit 5 - Transmitter Holding Register/FIFO Empty (THRE) status. (If = 1, TX FIFO is empty) * Bit 6 - Transmitter Empty (TEMT) status. (If = 1, both TX FIFO and shift register are empty) */ status &= (MSS_UART_THRE | MSS_UART_TEMT); } return status; } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_break ( mss_uart_instance_t * this_uart ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /* set break charecter on Tx line */ set_bit_reg8(&this_uart->hw_reg->LCR,SB); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_clear_break ( mss_uart_instance_t * this_uart ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /* remove break charecter from Tx line */ clear_bit_reg8(&this_uart->hw_reg->LCR,SB); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_pidpei_handler ( mss_uart_instance_t * this_uart, mss_uart_irq_handler_t handler ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(handler != INVALID_IRQ_HANDLER); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (handler != INVALID_IRQ_HANDLER)) { this_uart->pid_pei_handler = handler; /* Clear any previously pended interrupts */ NVIC_ClearPendingIRQ( this_uart->irqn ); /* Enable PID parity error interrupt. */ set_bit_reg8(&this_uart->hw_reg->IEM,EPID_PEI); /* Enable UART instance interrupt in Cortex-M3 NVIC. */ NVIC_EnableIRQ(this_uart->irqn); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_linbreak_handler ( mss_uart_instance_t * this_uart, mss_uart_irq_handler_t handler ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(handler != INVALID_IRQ_HANDLER); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (handler != INVALID_IRQ_HANDLER)) { this_uart->break_handler = handler; /* Clear any previously pended interrupts */ NVIC_ClearPendingIRQ( this_uart->irqn ); /* Enable LIN break detection interrupt. */ set_bit_reg8(&this_uart->hw_reg->IEM,ELINBI); /* Enable UART instance interrupt in Cortex-M3 NVIC. */ NVIC_EnableIRQ(this_uart->irqn); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_linsync_handler ( mss_uart_instance_t * this_uart, mss_uart_irq_handler_t handler ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(handler != INVALID_IRQ_HANDLER); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (handler != INVALID_IRQ_HANDLER)) { this_uart->sync_handler = handler; /* Clear any previously pended interrupts */ NVIC_ClearPendingIRQ( this_uart->irqn ); /* Enable LIN sync detection interrupt. */ set_bit_reg8(&this_uart->hw_reg->IEM,ELINSI); /* Enable UART instance interrupt in Cortex-M3 NVIC. */ NVIC_EnableIRQ(this_uart->irqn); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_nack_handler ( mss_uart_instance_t * this_uart, mss_uart_irq_handler_t handler ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(handler != INVALID_IRQ_HANDLER); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (handler != INVALID_IRQ_HANDLER)) { this_uart->nack_handler = handler; /* Clear any previously pended interrupts */ NVIC_ClearPendingIRQ( this_uart->irqn ); /* Enable LIN sync detection interrupt. */ set_bit_reg8(&this_uart->hw_reg->IEM,ENACKI); /* Enable UART instance interrupt in Cortex-M3 NVIC. */ NVIC_EnableIRQ(this_uart->irqn); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_rx_timeout_handler ( mss_uart_instance_t * this_uart, mss_uart_irq_handler_t handler ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(handler != INVALID_IRQ_HANDLER); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (handler != INVALID_IRQ_HANDLER)) { this_uart->rto_handler = handler; /* Clear any previously pended interrupts */ NVIC_ClearPendingIRQ( this_uart->irqn ); /* Enable receiver timeout interrupt. */ set_bit_reg8(&this_uart->hw_reg->IEM,ERTOI); /* Enable UART instance interrupt in Cortex-M3 NVIC. */ NVIC_EnableIRQ(this_uart->irqn); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_enable_half_duplex ( mss_uart_instance_t * this_uart ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /* enable single wire half-duplex mode */ set_bit_reg8(&this_uart->hw_reg->MM2,ESWM); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_disable_half_duplex ( mss_uart_instance_t * this_uart ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /* enable single wire half-duplex mode */ clear_bit_reg8(&this_uart->hw_reg->MM2,ESWM); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_rx_endian ( mss_uart_instance_t * this_uart, mss_uart_endian_t endian ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(MSS_UART_INVALID_ENDIAN > endian); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (MSS_UART_INVALID_ENDIAN > endian)) { /* Configure MSB first / LSB first for receiver */ ((MSS_UART_LITTLEEND == endian) ? (clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_RX)) : (set_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_RX))); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_tx_endian ( mss_uart_instance_t * this_uart, mss_uart_endian_t endian ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(MSS_UART_INVALID_ENDIAN > endian); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (MSS_UART_INVALID_ENDIAN > endian)) { /* Configure MSB first / LSB first for transmitter */ ((MSS_UART_LITTLEEND == endian) ? (clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_TX)) : (set_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_TX)) ) ; } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_filter_length ( mss_uart_instance_t * this_uart, mss_uart_filter_length_t length ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(MSS_UART_INVALID_FILTER_LENGTH > length); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (MSS_UART_INVALID_FILTER_LENGTH > length)) { /* Configure glitch filter length */ this_uart->hw_reg->GFR = (uint8_t)length; } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_enable_afm ( mss_uart_instance_t * this_uart ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /* Disable RX FIFO till address flag with correct address is received */ set_bit_reg8(&this_uart->hw_reg->MM2,EAFM); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_disable_afm ( mss_uart_instance_t * this_uart ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /* Enable RX FIFO irrespective of address flag and correct address is received */ clear_bit_reg8(&this_uart->hw_reg->MM2,EAFM); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_enable_afclear ( mss_uart_instance_t * this_uart ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /* Enable address flag clearing */ /* Disable RX FIFO till another address flag with correct address is received */ set_bit_reg8(&this_uart->hw_reg->MM2,EAFC); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_disable_afclear ( mss_uart_instance_t * this_uart ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /* Disable address flag clearing */ clear_bit_reg8(&this_uart->hw_reg->MM2,EAFC); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_enable_rx_timeout ( mss_uart_instance_t * this_uart, uint8_t timeout ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /* Load the receive timeout value */ this_uart->hw_reg->RTO = timeout; /*Enable receiver time-out */ set_bit_reg8(&this_uart->hw_reg->MM0,ERTO); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_disable_rx_timeout ( mss_uart_instance_t * this_uart ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /*Disable receiver time-out */ clear_bit_reg8(&this_uart->hw_reg->MM0,ERTO); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_enable_tx_time_guard ( mss_uart_instance_t * this_uart, uint8_t timeguard ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /* Load the transmitter time guard value */ this_uart->hw_reg->TTG = timeguard; /*Enable transmitter time guard */ set_bit_reg8(&this_uart->hw_reg->MM0,ETTG); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_disable_tx_time_guard ( mss_uart_instance_t * this_uart ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { /*Disable transmitter time guard */ clear_bit_reg8(&this_uart->hw_reg->MM0,ETTG); } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_address ( mss_uart_instance_t * this_uart, uint8_t address ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { this_uart->hw_reg->ADR = address; } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_ready_mode ( mss_uart_instance_t * this_uart, mss_uart_ready_mode_t mode ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(MSS_UART_INVALID_READY_MODE > mode); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (MSS_UART_INVALID_READY_MODE > mode ) ) { /* Configure mode 0 or mode 1 for TXRDY and RXRDY */ ((MSS_UART_READY_MODE0 == mode) ? clear_bit_reg8(&this_uart->hw_reg->FCR,RDYMODE) : set_bit_reg8(&this_uart->hw_reg->FCR,RDYMODE) ); } } /***************************************************************************//** * Configure baud divisors using fractional baud rate if possible. */ static void config_baud_divisors ( mss_uart_instance_t * this_uart, uint32_t baudrate ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { uint32_t baud_value; uint32_t baud_value_by_64; uint32_t baud_value_by_128; uint32_t fractional_baud_value; uint32_t pclk_freq; this_uart->baudrate = baudrate; /* Force the value of the CMSIS global variables holding the various system * clock frequencies to be updated. */ SystemCoreClockUpdate(); if(this_uart == &g_mss_uart0) { pclk_freq = g_FrequencyPCLK0; } else { pclk_freq = g_FrequencyPCLK1; } /* * Compute baud value based on requested baud rate and PCLK frequency. * The baud value is computed using the following equation: * baud_value = PCLK_Frequency / (baud_rate * 16) */ baud_value_by_128 = (8u * pclk_freq) / baudrate; baud_value_by_64 = baud_value_by_128 / 2u; baud_value = baud_value_by_64 / 64u; fractional_baud_value = baud_value_by_64 - (baud_value * 64u); fractional_baud_value += (baud_value_by_128 - (baud_value * 128u)) - (fractional_baud_value * 2u); /* Assert if integer baud value fits in 16-bit. */ ASSERT(baud_value <= UINT16_MAX); if(baud_value <= (uint32_t)UINT16_MAX) { if(baud_value > 1u) { /* * Use Frational baud rate divisors */ /* set divisor latch */ set_bit_reg8(&this_uart->hw_reg->LCR,DLAB); /* msb of baud value */ this_uart->hw_reg->DMR = (uint8_t)(baud_value >> 8); /* lsb of baud value */ this_uart->hw_reg->DLR = (uint8_t)baud_value; /* reset divisor latch */ clear_bit_reg8(&this_uart->hw_reg->LCR,DLAB); /* Enable Fractional baud rate */ set_bit_reg8(&this_uart->hw_reg->MM0,EFBR); /* Load the fractional baud rate register */ ASSERT(fractional_baud_value <= (uint32_t)UINT8_MAX); this_uart->hw_reg->DFR = (uint8_t)fractional_baud_value; } else { /* * Do NOT use Frational baud rate divisors. */ /* set divisor latch */ set_bit_reg8(&this_uart->hw_reg->LCR,DLAB); /* msb of baud value */ this_uart->hw_reg->DMR = (uint8_t)(baud_value >> 8u); /* lsb of baud value */ this_uart->hw_reg->DLR = (uint8_t)baud_value; /* reset divisor latch */ clear_bit_reg8(&this_uart->hw_reg->LCR,DLAB); /* Disable Fractional baud rate */ clear_bit_reg8(&this_uart->hw_reg->MM0,EFBR); } } } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ void MSS_UART_set_usart_mode ( mss_uart_instance_t * this_uart, mss_uart_usart_mode_t mode ) { ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(MSS_UART_INVALID_SYNC_MODE > mode); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (MSS_UART_INVALID_SYNC_MODE > mode)) { /* Nothing to do for the baudrate: operates at PCLK / 2 + glitch filter length */ /* Clear the ESYN bits 2:0 */ this_uart->hw_reg->MM0 &= ~SYNC_ASYNC_MODE_MASK; this_uart->hw_reg->MM0 |= (uint8_t)mode; } } /******************************************************************************* * Local Functions *******************************************************************************/ /******************************************************************************* * Global initialization for all modes */ static void global_init ( mss_uart_instance_t * this_uart, uint32_t baud_rate, uint8_t line_config ) { /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only * mss_uart_instance_t instances used to identify UART0 and UART1. */ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if(this_uart == &g_mss_uart0) { this_uart->hw_reg = UART0; this_uart->irqn = UART0_IRQn; /* reset UART0 */ SYSREG->SOFT_RST_CR |= SYSREG_MMUART0_SOFTRESET_MASK; /* Clear any previously pended UART0 interrupt */ NVIC_ClearPendingIRQ(UART0_IRQn); /* Take UART0 out of reset. */ SYSREG->SOFT_RST_CR &= ~SYSREG_MMUART0_SOFTRESET_MASK; } else { this_uart->hw_reg = UART1; this_uart->irqn = UART1_IRQn; /* Reset UART1 */ SYSREG->SOFT_RST_CR |= SYSREG_MMUART1_SOFTRESET_MASK; /* Clear any previously pended UART1 interrupt */ NVIC_ClearPendingIRQ(UART1_IRQn); /* Take UART1 out of reset. */ SYSREG->SOFT_RST_CR &= ~SYSREG_MMUART1_SOFTRESET_MASK; } /* disable interrupts */ this_uart->hw_reg->IER = 0u; /* FIFO configuration */ this_uart->hw_reg->FCR = (uint8_t)MSS_UART_FIFO_SINGLE_BYTE; /* clear receiver FIFO */ set_bit_reg8(&this_uart->hw_reg->FCR,CLEAR_RX_FIFO); /* clear transmitter FIFO */ set_bit_reg8(&this_uart->hw_reg->FCR,CLEAR_TX_FIFO); /* set default READY mode : Mode 0*/ /* enable RXRDYN and TXRDYN pins. The earlier FCR write to set the TX FIFO * trigger level inadvertently disabled the FCR_RXRDY_TXRDYN_EN bit. */ set_bit_reg8(&this_uart->hw_reg->FCR,RXRDY_TXRDYN_EN); /* disable loopback : local * remote */ clear_bit_reg8(&this_uart->hw_reg->MCR,LOOP); clear_bit_reg8(&this_uart->hw_reg->MCR,RLOOP); /* set default TX endian */ clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_TX); /* set default RX endian */ clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_RX); /* default AFM : disabled */ clear_bit_reg8(&this_uart->hw_reg->MM2,EAFM); /* disable TX time gaurd */ clear_bit_reg8(&this_uart->hw_reg->MM0,ETTG); /* set default RX timeout */ clear_bit_reg8(&this_uart->hw_reg->MM0,ERTO); /* disable fractional baud-rate */ clear_bit_reg8(&this_uart->hw_reg->MM0,EFBR); /* disable single wire mode */ clear_bit_reg8(&this_uart->hw_reg->MM2,ESWM); /* set filter to minimum value */ this_uart->hw_reg->GFR = 0u; /* set default TX time gaurd */ this_uart->hw_reg->TTG = 0u; /* set default RX timeout */ this_uart->hw_reg->RTO = 0u; /* * Configure baud rate divisors. This uses the frational baud rate divisor * where possible to provide the most accurate baud rat possible. */ config_baud_divisors(this_uart, baud_rate); /* set the line control register (bit length, stop bits, parity) */ this_uart->hw_reg->LCR = line_config; /* Instance setup */ this_uart->baudrate = baud_rate; this_uart->lineconfig = line_config; this_uart->tx_buff_size = TX_COMPLETE; this_uart->tx_buffer = (const uint8_t *)0; this_uart->tx_idx = 0u; /* Default handlers for MSS UART interrupts */ this_uart->rx_handler = NULL_HANDLER; this_uart->tx_handler = NULL_HANDLER; this_uart->linests_handler = NULL_HANDLER; this_uart->modemsts_handler = NULL_HANDLER; this_uart->rto_handler = NULL_HANDLER; this_uart->nack_handler = NULL_HANDLER; this_uart->pid_pei_handler = NULL_HANDLER; this_uart->break_handler = NULL_HANDLER; this_uart->sync_handler = NULL_HANDLER; /* Initialize the sticky status */ this_uart->status = 0u; } /***************************************************************************//** * Interrupt service routine triggered by any MSS UART interrupt. This routine * will call the handler function appropriate to the interrupt from the * handlers previously registered with the driver through calls to the * MSS_UART_set_*_handler() functions, or it will call the default_tx_handler() * function in response to transmit interrupts if MSS_UART_irq_tx() is used to * transmit data. */ static void MSS_UART_isr ( mss_uart_instance_t * this_uart ) { uint8_t iirf; ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) { iirf = this_uart->hw_reg->IIR & IIRF_MASK; switch (iirf) { case IIRF_MODEM_STATUS: /* Modem status interrupt */ { ASSERT(NULL_HANDLER != this_uart->modemsts_handler); if(NULL_HANDLER != this_uart->modemsts_handler) { (*(this_uart->modemsts_handler))(this_uart); } } break; case IIRF_THRE: /* Transmitter Holding Register Empty */ { ASSERT(NULL_HANDLER != this_uart->tx_handler); if(NULL_HANDLER != this_uart->tx_handler) { (*(this_uart->tx_handler))(this_uart); } } break; case IIRF_RX_DATA: /* Received Data Available */ case IIRF_DATA_TIMEOUT: /* Received Data Timed-out */ { ASSERT(NULL_HANDLER != this_uart->rx_handler); if(NULL_HANDLER != this_uart->rx_handler) { (*(this_uart->rx_handler))(this_uart); } } break; case IIRF_RX_LINE_STATUS: /* Line Status Interrupt */ { ASSERT(NULL_HANDLER != this_uart->linests_handler); if(NULL_HANDLER != this_uart->linests_handler) { (*(this_uart->linests_handler))(this_uart); } } break; case IIRF_MMI: { /* Identify multimode interrupts and handle */ /* Receiver time-out interrupt */ if(read_bit_reg8(&this_uart->hw_reg->IIM,ERTOI)) { ASSERT(NULL_HANDLER != this_uart->rto_handler); if(NULL_HANDLER != this_uart->rto_handler) { (*(this_uart->rto_handler))(this_uart); } } /* NACK interrupt */ if(read_bit_reg8(&this_uart->hw_reg->IIM,ENACKI)) { ASSERT(NULL_HANDLER != this_uart->nack_handler); if(NULL_HANDLER != this_uart->nack_handler) { (*(this_uart->nack_handler))(this_uart); } } /* PID parity error interrupt */ if(read_bit_reg8(&this_uart->hw_reg->IIM,EPID_PEI)) { ASSERT(NULL_HANDLER != this_uart->pid_pei_handler); if(NULL_HANDLER != this_uart->pid_pei_handler) { (*(this_uart->pid_pei_handler))(this_uart); } } /* LIN break detection interrupt */ if(read_bit_reg8(&this_uart->hw_reg->IIM,ELINBI)) { ASSERT(NULL_HANDLER != this_uart->break_handler); if(NULL_HANDLER != this_uart->break_handler) { (*(this_uart->break_handler))(this_uart); } } /* LIN Sync detection interrupt */ if(read_bit_reg8(&this_uart->hw_reg->IIM,ELINSI)) { ASSERT(NULL_HANDLER != this_uart->sync_handler); if(NULL_HANDLER != this_uart->sync_handler) { (*(this_uart->sync_handler))(this_uart); } } break; } default: { ASSERT(INVALID_INTERRUPT); } break; } } } /***************************************************************************//** * See mss_uart.h for details of how to use this function. */ static void default_tx_handler ( mss_uart_instance_t * this_uart ) { uint8_t status; ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)); ASSERT(( (uint8_t *)0 ) != this_uart->tx_buffer); ASSERT(0u < this_uart->tx_buff_size); if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) && (((uint8_t *)0 ) != this_uart->tx_buffer) && (0u < this_uart->tx_buff_size)) { /* Read the Line Status Register and update the sticky record. */ status = this_uart->hw_reg->LSR; this_uart->status |= status; /* * This function should only be called as a result of a THRE interrupt. * Verify that this is true before proceeding to transmit data. */ if(status & MSS_UART_THRE) { uint32_t i; uint32_t fill_size = TX_FIFO_SIZE; uint32_t tx_remain = this_uart->tx_buff_size - this_uart->tx_idx; /* Calculate the number of bytes to transmit. */ if(tx_remain < TX_FIFO_SIZE) { fill_size = tx_remain; } /* Fill the TX FIFO with the calculated the number of bytes. */ for(i = 0u; i < fill_size; ++i) { /* Send next character in the buffer. */ this_uart->hw_reg->THR = this_uart->tx_buffer[this_uart->tx_idx]; ++this_uart->tx_idx; } } /* Flag Tx as complete if all data has been pushed into the Tx FIFO. */ if(this_uart->tx_idx == this_uart->tx_buff_size) { this_uart->tx_buff_size = TX_COMPLETE; /* disables TX interrupt */ clear_bit_reg8(&this_uart->hw_reg->IER,ETBEI); } } } #ifdef __cplusplus } #endif