int pop_buffer( unsigned char* head, unsigned char** tail, unsigned char* buff, unsigned char* data, int max_len ) { unsigned char* local_tail; unsigned char* local_head = head; int cnt = 0; BSP_CRITICAL_STATEMENT( local_tail = *tail ); /* if the buffer is empty or no data requested */ if( local_tail == local_head || max_len <= 0 ) return 0; /* indicate so */ do /* retrieve the data from the buffer */ { if( local_tail == buff + RX_TX_BUFFER_SIZE ) /* if wrapping around */ local_tail = buff; /* reset pointer */ *data++ = *local_tail++; /* copy data from buffer */ /* while the user needs more data and there is data left in the fifo */ } while( ++cnt < max_len && local_tail != local_head ); BSP_CRITICAL_STATEMENT( *tail = local_tail ); /* update reference value */ return cnt; /* return number of characters retrieved from the buffer */ }
bool push_buffer( unsigned char** head, unsigned char* tail, unsigned char* buff, unsigned char* data, int len ) { unsigned char* local_head; unsigned char* local_tail = tail; BSP_CRITICAL_STATEMENT( local_head = *head ); /* if no room in the buffer */ if( buffer_free_space( local_head, local_tail ) < len ) return false; /* indicate failure to enqueue message */ /* there is room for the data, put in the buffer */ do /* put the data in the buffer */ { if( local_head == buff + RX_TX_BUFFER_SIZE ) /* if wrapping around */ local_head = buff; /* reset pointer */ *local_head++ = *data++; /* copy over this byte of data */ } while( --len > 0 ); /* copy all the data to the buffer */ BSP_CRITICAL_STATEMENT( *head = local_head ); /* update reference value */ return true; }
/****************************************************************************** * @fn uart_rx_irq * * @brief RX interrupt service routine * * input parameters * * output parameters * * @return */ void uart_rx_irq( void ) { uart_put_rx_data_type handler; /* read in the received data, this will clear the interrupt also */ unsigned char c = UART_RECEIVE( UART_NUMBER_1, UART1_LOCATION ); BSP_CRITICAL_STATEMENT( handler = uart_rx_handler ); if( handler != NULL ) /* if a handler exists to receive data */ if( ( *handler)( c ) == false ) /* if the user is done receiveing */ /* indicate the receiver is available */ BSP_CRITICAL_STATEMENT( uart_rx_handler = NULL ); return; }
// the isr's... static void uart_tx_irq( void ) { unsigned char c; { uart_get_tx_data_type handler; BSP_CRITICAL_STATEMENT( handler = uart_tx_handler ); // if not currently in suspend mode and a handler exists if( uart_tx_suspend == false && handler != NULL ) { if( (*handler)( &c ) != false ) // if data available, reset the interrupt { UART_SEND( UART_NUMBER, UART_LOCATION, c ); // send the byte } else // if no data suspend transmission { uart_tx_message_suspend( handler ); UART_IRQ_FLAG_SET( UART_NUMBER, UART_LOCATION, TX ); } } else { bspIState_t istate; BSP_ENTER_CRITICAL_SECTION( istate ); // if we are in suspended mode or we just sent an xon or xoff character // while transmits were disabled or the message has been completely sent, // then simply disable irq's so we don't get stuck in an infinite loop UART_IRQ_DISABLE( UART_NUMBER, UART_LOCATION, TX ); UART_IRQ_FLAG_SET( UART_NUMBER, UART_LOCATION, TX ); BSP_EXIT_CRITICAL_SECTION( istate ); } } return; }
bool tx0_handler( unsigned char* c ) { bool status; unsigned char* head; /* get current state of head pointer */ BSP_CRITICAL_STATEMENT( head = tx0_head ); /* get data off of the transmit buffer */ pop_buffer( head, &tx0_tail, tx0_buff, c, 1 ); /* check status of buffer */ BSP_CRITICAL_STATEMENT( status = tx0_head != tx0_tail ); return status; /* indicate if this is the last byte in the buffer */ }
static void uart_rx_irq( void ) { uart_put_rx_data_type handler; // read in the received data, this will clear the interrupt also unsigned char c = UART_RECEIVE( UART_NUMBER, UART_LOCATION ); BSP_CRITICAL_STATEMENT( handler = uart_rx_handler ); if( handler != NULL ) // if a handler exists to receive data if( ( *handler)( c ) == false ) // if the user is suspending uart_rx_message_suspend( handler ); return; }
bool tx0_send( const void* data, size_t len ) { bool status; unsigned char* tail; /* get current state of tail pointer */ BSP_CRITICAL_STATEMENT( tail = tx0_tail ); /* put data into transmit buffer */ status = push_buffer( &tx0_head, tail, tx0_buff, (unsigned char*)data, len ); if( status != false ) /* if data was put in the buffer properly */ uart0_tx_message( tx0_handler ); /* notify the irq that data is ready to send */ return status; /* return status */ }
/****************************************************************************** * @fn uart1_tx_irq * * @brief TX interrupt service routine * * input parameters * * output parameters * * @return */ void uart0_tx_irq( void ) { unsigned char c; uart_get_tx_data_type handler; BSP_CRITICAL_STATEMENT( handler = uart0_tx_handler ); /* if a handler exists */ if( handler != NULL ) { if( (*handler)( &c ) != false ) /* if this is not the last byte to send */ { bspIState_t intState; BSP_ENTER_CRITICAL_SECTION( intState ); /* only reset the interrupt flag if we have additional data to send * that way, if we are done then the interrupt is still pending and * will be immediately entered upon re-enabling it.*/ UART_IRQ_FLAG_CLR( UART_NUMBER_0, UART0_LOCATION, TX ); /* eset the interrupt */ BSP_EXIT_CRITICAL_SECTION( intState ); } else { bspIState_t intState; BSP_ENTER_CRITICAL_SECTION( intState ); /* we're done sending data. since we left the interrupt pending, * disable it so we don't re-enter the isr. the interrupt will be * re-enabled when there is another message to send. */ UART_IRQ_DISABLE( UART_NUMBER_0, UART0_LOCATION, TX ); /* no more data to send, reset the handler to flag not busy */ uart0_tx_handler = NULL; BSP_EXIT_CRITICAL_SECTION( intState ); } UART_SEND( UART_NUMBER_0, UART0_LOCATION, c ); /* send the byte */ } else /* if no handler exists?!?!?!? */ /* something went wrong, disable interrupts so we don't get stuck here */ UART_IRQ_DISABLE( UART_NUMBER_0, UART0_LOCATION, TX ); return; }
bool rx_handler( unsigned char c ) { unsigned char* tail; /* get current state of tail pointer */ BSP_CRITICAL_STATEMENT( tail = rx_tail ); /* put data onto the receive buffer */ push_buffer( &rx_head, tail, rx_buff, &c, 1 ); #if( defined UART_HARDWARE_HANDSHAKE_IN_SOFTWARE ) /* if we need to hold off the remote transmitter */ if( rx_peek( ) >= RX_TX_BUFFER_THROTTLE_LIMIT ) UART_ASSERT_RTS( UART_RTS_ASSERTED ); /* assert the RTS line */ #endif return true; /* always accept data received from the uart */ }
int rx_receive( void* data, int max_len ) { int cnt; unsigned char* head; /* get current state of head pointer */ BSP_CRITICAL_STATEMENT( head = rx_head ); /* retrieve data from buffer */ cnt = pop_buffer( head, &rx_tail, rx_buff, data, max_len ); #if( defined UART_HARDWARE_HANDSHAKE_IN_SOFTWARE ) /* if we need to hold off the remote transmitter */ if( rx_peek( ) < RX_TX_BUFFER_THROTTLE_LIMIT ) UART_ASSERT_RTS( UART_RTS_DEASSERTED ); /* deassert the RTS line */ #endif return cnt; /* indicate the number of bytes retrieved from the buffer */ }