Exemple #1
0
/* Find out what interrupted and get or send data as appropriate */
void MB_USART_ISR(void)
{
    /* Check if we were called because of RXNE. */
    if (((USART_CR1(MB_USART) & USART_CR1_RXNEIE) != 0) && ((USART_SR(MB_USART) & USART_SR_RXNE) != 0))
    {
        pxMBFrameCBByteReceived();
    }
    /* Check if we were called because of TXE. */
    if (((USART_CR1(MB_USART) & USART_CR1_TXEIE) != 0) && ((USART_SR(MB_USART) & USART_SR_TXE) != 0))
    {
        pxMBFrameCBTransmitterEmpty();
        /* Check if we need to disable transmitter*/
        if(!txen)
        {
            USART_SR (MB_USART) &= ~USART_SR_TC;   /* Clear TC flag*/
            USART_CR1(MB_USART) |= USART_CR1_TCIE; /* Enable transfer complite interrupt*/
        }
    }
    /* Disable transmitter on transfer comlite*/
    if (((USART_CR1(MB_USART) & USART_CR1_TCIE) != 0) && ((USART_SR(MB_USART) & USART_SR_TC) != 0))
    {
        USART_CR1(MB_USART) &= ~USART_CR1_TCIE;/* Disble transfer complite interrupt*/
        USART_SR (MB_USART) &= ~USART_SR_TC;   /* Clear TC flag*/
        /* Disable transmitter*/
        gpio_clear(MB_USART_TXEN_PORT, MB_USART_TXEN_PIN);
    }
}
Exemple #2
0
void DBG_USART_ISR(void)
{
    /* Check if we were called because of RXNE. */
    if (((USART_CR1(DBG_USART) & USART_CR1_RXNEIE) != 0) && ((USART_SR(DBG_USART) & USART_SR_RXNE) != 0))
    {
        usart_data = usart_recv(DBG_USART);
        if( !dbg_fifo_write_byte( &usart_rx_buf, usart_data ) )
        {
            usart_disable_rx_interrupt(DBG_USART);
        }
    }
    /* Check if we were called because of TXE. */
    if (((USART_CR1(DBG_USART) & USART_CR1_TXEIE) != 0) && ((USART_SR(DBG_USART) & USART_SR_TXE) != 0))
    {
        /* Put data into the transmit register. */
        if( dbg_fifo_read_byte( &usart_tx_buf, &usart_data ) )
        {
            usart_send(DBG_USART, usart_data);
        }
        else
        {
            /* Disable the TXE interrupt as we don't need it anymore. */
            usart_disable_tx_interrupt(DBG_USART);
        }
    }
}
Exemple #3
0
	OPTL_NOINLINE
	void init()
	{
		clk::enable();
		rxpin::clock::enable();
		txpin::clock::enable();

		rxpin::init_alternate(afnum::af);
		txpin::init_alternate(afnum::af);

		rxpin::driver_pushpull();
		txpin::driver_pushpull();

		USART_BRR(base) = ((2 * cpuclock) + baudrate) / (2 * baudrate);
		USART_CR1(base) &= ~USART_CR1_M; /* 8 data bits */
		USART_CR1(base) = (USART_CR1(base) & ~USART_PARITY_MASK) |
				   USART_PARITY_NONE;
		USART_CR2(base) = (USART_CR2(base) & ~USART_CR2_STOPBITS_MASK) |
				   USART_STOPBITS_1;
		USART_CR3(base) = (USART_CR3(base) & ~USART_FLOWCONTROL_MASK) |
				   USART_FLOWCONTROL_NONE;

		USART_CR1(base) = (USART_CR1(base) & ~USART_MODE_MASK) |
				   USART_MODE_TX_RX;

	}
void usart2_isr(void)
{
	/* Check if we were called because of RXNE. */
	if (((USART_CR1(USART2) & USART_CR1_RXNEIE) != 0) &&
	    ((USART_SR(USART2) & USART_SR_RXNE) != 0)) {

		/* Indicate that we got data. */
		gpio_toggle(GPIOA, GPIO8);

		/* Retrieve the data from the peripheral. */
		ring_write_ch(&output_ring, usart_recv(USART2));

		/* Enable transmit interrupt so it sends back the data. */
		USART_CR1(USART2) |= USART_CR1_TXEIE;
	}

	/* Check if we were called because of TXE. */
	if (((USART_CR1(USART2) & USART_CR1_TXEIE) != 0) &&
	    ((USART_SR(USART2) & USART_SR_TXE) != 0)) {

		int32_t data;

		data = ring_read_ch(&output_ring, NULL);

		if (data == -1) {
			/* Disable the TXE interrupt, it's no longer needed. */
			USART_CR1(USART2) &= ~USART_CR1_TXEIE;
		} else {
			/* Put data into the transmit register. */
			usart_send(USART2, data);
		}
	}
}
Exemple #5
0
void usart1_isr(void)
{
    unsigned char c;

	/* Check if we were called because of RXNE. */
	if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) &&
        ((USART_SR(USART1) & USART_SR_RXNE) != 0) &&
        (!serial_rb_full(&srx))) {
        c = serial_recv();
        serial_rb_write(&srx, c);
	}
	/* Check if we were called because of TXE. */
	else if (((USART_CR1(USART1) & USART_CR1_TXEIE) != 0) &&
             ((USART_SR(USART1) & USART_SR_TXE) != 0)) {

        if(!serial_rb_empty(&stx)) {
            serial_send(serial_rb_read(&stx));
        }
        else {
            /* Disable the TXE interrupt, it's no longer needed. */
            USART_CR1(USART1) &= ~USART_CR1_TXEIE;
        }
	}
	else {
        c = serial_recv();
	}
}
Exemple #6
0
void usart1_isr(void)
{
	u8 ch;

	//if Receive interrupt
	if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) &&
			((USART_SR(USART1) & USART_SR_RXNE) != 0))
	{
		ch=usart_recv(USART1);
		buffer_put(&u1rx, ch);
	}

	if (((USART_CR1(USART1) & USART_CR1_TXEIE) != 0) &&
			((USART_SR(USART1) & USART_SR_TXE) != 0))
	{
		if (buffer_get(&u1tx, &ch) == SUCCESS)
		{
			//if char read from buffer
			usart_send(USART1, ch);
		}
		else	//if buffer empty
		{

			//disable Transmit Data Register empty interrupt
			usart_disable_tx_interrupt(USART1);
		}
	}
}
Exemple #7
0
void usart_set_databits(u32 usart, u32 bits)
{
	if (bits == 8)
		USART_CR1(usart) &= ~USART_CR1_M; /* 8 data bits */
	else
		USART_CR1(usart) |= USART_CR1_M;  /* 9 data bits */
}
Exemple #8
0
void UART_IRQHandler(struct CB_UART* pctl)
{
	/* Receive */
	if ((USART_SR(pctl->iuart) & USART_SR_RXNE) != 0) // Receive reg loaded?
	{  // Here, receive interrupt flag is on. 
		*pctl->rxbuff_in = USART_DR(pctl->iuart);// Read and store char

		/* Advance pointers to line buffers and array of counts and reset when end reached */	
		pctl->rxbuff_in = rxbuff_adv(pctl, pctl->rxbuff_in);	// Advance pointers common routine
	}

	/* Transmit */
	if ( (USART_CR1(pctl->iuart) & USART_CR1_TXEIE) != 0)
	{  // Here, yes.  Transmit interrupts are enabled so check if a tx interrupt
		if ( (USART_SR(pctl->iuart) & USART_SR_TXE) != 0) // Transmit register empty?
		{ // Here, yes.
			USART_DR(pctl->iuart) = *pctl->txbuff_out;// Send next char, step pointer

			/* Advance output pointer */
			pctl->txbuff_out = txbuff_adv(pctl, pctl->txbuff_out);

			/* Was the last byte loaded the last to send? */		
			if (pctl->txbuff_out == pctl->txbuff_in)
			{ // Here yes. 
				USART_CR1(pctl->iuart) &= ~USART_CR1_TXEIE;		// Disable Tx interrupt	
			}	
		}
	}
	return;
}
void usart1_isr(void)
{
	static uint8_t data = 'A';

	/* Check if we were called because of RXNE. */
	if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) &&
		((USART_SR(USART1) & USART_SR_RXNE) != 0)) {
		/* Indicate that we got data. */
		gpio_toggle(GPIOA, GPIO6);

		/* Retrieve the data from the peripheral. */
		data = usart_recv(USART1);

		/* Enable transmit interrupt so it sends back the data. */
		USART_CR1(USART1) |= USART_CR1_TXEIE;
	}

	/* Check if we were called because of TXE. */
	if (((USART_CR1(USART1) & USART_CR1_TXEIE) != 0) &&
		((USART_SR(USART1) & USART_SR_TXE) != 0)) {
		/* Indicate that we are sending out data. */
		gpio_toggle(GPIOA, GPIO7);

		/* Put data into the transmit register. */
		usart_send(USART1, data);

		/* Disable the TXE interrupt as we don't need it anymore. */
		USART_CR1(USART1) &= ~USART_CR1_TXEIE;
	}
}
Exemple #10
0
void usart2_isr(void)
{
	static u8 data = 'A';

	/* Check if we were called because of RXNE. */
	if (((USART_CR1(USART2) & USART_CR1_RXNEIE) != 0) &&
	    ((USART_SR(USART2) & USART_SR_RXNE) != 0)) {

		/* Indicate that we got data. */
		gpio_toggle(GPIOD, GPIO12);

		/* Retrieve the data from the peripheral. */
		data = usart_recv(USART2);

		/* Enable transmit interrupt so it sends back the data. */
		usart_enable_tx_interrupt(USART2);
	}

	/* Check if we were called because of TXE. */
	if (((USART_CR1(USART2) & USART_CR1_TXEIE) != 0) &&
	    ((USART_SR(USART2) & USART_SR_TXE) != 0)) {

		/* Put data into the transmit register. */
		usart_send(USART2, data);

		/* Disable the TXE interrupt as we don't need it anymore. */
		usart_disable_tx_interrupt(USART2);
	}
}
Exemple #11
0
void usart_set_databits(uint32_t usart, uint32_t bits)
{
	if (bits == 8) {
		USART_CR1(usart) &= ~USART_CR1_M; /* 8 data bits */
	} else {
		USART_CR1(usart) |= USART_CR1_M;  /* 9 data bits */
	}
}
Exemple #12
0
void usart_set_mode(uint32_t usart, uint32_t mode)
{
	uint32_t reg32;

	reg32 = USART_CR1(usart);
	reg32 = (reg32 & ~USART_MODE_MASK) | mode;
	USART_CR1(usart) = reg32;
}
Exemple #13
0
void usart_set_parity(uint32_t usart, uint32_t parity)
{
	uint32_t reg32;

	reg32 = USART_CR1(usart);
	reg32 = (reg32 & ~USART_PARITY_MASK) | parity;
	USART_CR1(usart) = reg32;
}
Exemple #14
0
void usart_set_parity(u32 usart, u32 parity)
{
	u32 reg32;

	reg32 = USART_CR1(usart);
	reg32 = (reg32 & ~USART_PARITY_MASK) | parity;
	USART_CR1(usart) = reg32;
}
Exemple #15
0
void usart_set_mode(u32 usart, u32 mode)
{
	u32 reg32;

	reg32 = USART_CR1(usart);
	reg32 = (reg32 & ~USART_MODE_MASK) | mode;
	USART_CR1(usart) = reg32;
}
Exemple #16
0
/*******************************************************************************
 * void bsp_uart_send_int(struct CB_UART* pctl);
 * @brief	: If uart tx is idle, and not dma driven, start tx
 * @param	: pctl = pointer uart control block
 * @return	: 
*******************************************************************************/
void bsp_uart_send_int(struct CB_UART* pctl)
{
	if (pctl->flag != 1) return;	// Return not interrupt drive & initialized

	if ((USART_CR1(pctl->iuart) & USART_CR1_TXEIE) != 0) // Already enabled?
		return;

	USART_CR1(pctl->iuart) |= USART_CR1_TXEIE ;	// Enable interrupt
	return;
}
static void usart_setup(void)
{
	/* Enable the USART1 interrupt. */
	nvic_enable_irq(NVIC_USART1_IRQ);

	/* Enable USART1 pin software remapping. */
	AFIO_MAPR |= AFIO_MAPR_USART1_REMAP;

	/* Setup GPIO pin GPIO_USART1_RE_TX on GPIO port B for transmit. */
	gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ,
		      GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_RE_TX);

	/* Setup GPIO pin GPIO_USART1_RE_RX on GPIO port B for receive. */
	gpio_set_mode(GPIOB, GPIO_MODE_INPUT,
		      GPIO_CNF_INPUT_FLOAT, GPIO_USART1_RE_RX);

	/* Setup UART parameters. */
	usart_set_baudrate(USART1, 230400);
	usart_set_databits(USART1, 8);
	usart_set_stopbits(USART1, USART_STOPBITS_1);
	usart_set_parity(USART1, USART_PARITY_NONE);
	usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);
	usart_set_mode(USART1, USART_MODE_TX_RX);

	/* Enable USART1 Receive interrupt. */
	USART_CR1(USART1) |= USART_CR1_RXNEIE;

	/* Finally enable the USART. */
	usart_enable(USART1);
}
Exemple #18
0
int _write_r (struct _reent *r, int fd, char * ptr, int len)
{  
    (void)r;
    if(fd==1 || fd==2) {
        int index;

        if (0 == (USART_CR1(USART1) & USART_CR1_UE))
            return len; //Don't send if USART is disabled

        for(index=0; index<len; index++) {
            if (ptr[index] == '\n') {
                usart_send_blocking(USART1,'\r');
            }  
            usart_send_blocking(USART1, ptr[index]);
        }    
        return len;
    } else if(fd>2) {
        if(file_open[fd-3]) {
#ifdef MEDIA_DRIVE
            _drive_num = fd == 3 ? 0 : 1;
#endif
            WORD bytes_written;
            pf_switchfile(&fat[fd-3]);
            int res=pf_write(ptr, len, &bytes_written);
            dbgprintf("_write_r: len %d, bytes_written %d, result %d\r\n",len, bytes_written, res);
            if(res==FR_OK) return bytes_written;
        }
    }
    errno=EINVAL;
    return -1;
}
static void usart_setup(void)
{
	/* Initialize output ring buffer. */
	ring_init(&output_ring, output_ring_buffer, BUFFER_SIZE);

	/* Enable the USART2 interrupt. */
	nvic_enable_irq(NVIC_USART2_IRQ);

	/* Setup GPIO pin GPIO_USART2_TX on GPIO port A for transmit. */
	gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
		      GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);

	/* Setup GPIO pin GPIO_USART2_RX on GPIO port A for receive. */
	gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
		      GPIO_CNF_INPUT_FLOAT, GPIO_USART2_RX);

	/* Setup UART parameters. */
	usart_set_baudrate(USART2, 230400);
	usart_set_databits(USART2, 8);
	usart_set_stopbits(USART2, USART_STOPBITS_1);
	usart_set_parity(USART2, USART_PARITY_NONE);
	usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
	usart_set_mode(USART2, USART_MODE_TX_RX);

	/* Enable USART2 Receive interrupt. */
	USART_CR1(USART2) |= USART_CR1_RXNEIE;

	/* Finally enable the USART. */
	usart_enable(USART2);
}
Exemple #20
0
// put byte into Tx buffer
void fill_uart_buff(uint32_t UART, uint8_t byte) {
    UART_buff *curbuff;
    uint8_t bufidx = 0, endidx;
    if(!(USART_CR1(UART) & USART_CR1_UE)) return; // UART disabled
    USART_CR1(UART) &= ~USART_CR1_TXEIE; // disable TX interrupt while buffer filling
    while ((USART_SR(UART) & USART_SR_TXE) == 0); // wait until last byte send
    switch(UART) {
    case USART1:
        bufidx = 0;
        break;
    case USART2:
        bufidx = 1;
        break;
    default: // error - return
        return;
    }
    curbuff = &TX_buffer[bufidx];
    bufidx = curbuff->start; // start of data in buffer
    endidx = curbuff->end; // end of data
    curbuff->buf[endidx++] = byte; // put byte into buffer
    // now check indexes
    if(endidx != bufidx && endidx != UART_BUF_DATA_SIZE) { // all OK - there's enough place for data
        (curbuff->end)++; // just increment index in buffer
    } else { // dangerous situation: possible overflow
        if(endidx == UART_BUF_DATA_SIZE) { // end of buffer
            if(bufidx != 0) { // no overflow
                curbuff->end = 0;
                goto end_of_fn;
            }
        }
        // overflow: purge all data
        bufidx = curbuff->start; // refresh data index
        for(endidx = bufidx; endidx < UART_BUF_DATA_SIZE; endidx++) // first data porion
            usart_send(UART, curbuff->buf[endidx]);
        for(endidx = 0; endidx < bufidx; endidx++) // rest of data
            usart_send(UART, curbuff->buf[endidx]);
        curbuff->start = 0;
        curbuff->end = 0;
        return;
    }
end_of_fn:
    // enable interrupts to send data from buffer
    USART_CR1(UART) |= USART_CR1_TXEIE;
}
void Serial_stm32::irq_handler(void)
{
    uint8_t data = 0;

    // Check if we were called because of RXNE
    if (((USART_CR1(config_.device) & USART_CR1_RXNEIE) != 0) &&
            ((USART_SR(config_.device)  & USART_SR_RXNE)    != 0))
    {

        // Retrieve the data from the peripheral
        data = usart_recv(config_.device);
        rx_buffer_.put_lossy(data);

        // Enable transmit interrupt so it sends back the data
        usart_enable_tx_interrupt(config_.device);
    }

    // Check if we were called because of TXE
    if (((USART_CR1(config_.device) & USART_CR1_TXEIE) != 0) &&
            ((USART_SR(config_.device)  & USART_SR_TXE)    != 0))
    {
        if (tx_buffer_.readable() > 0)
        {
            // Get data from output buffer
            tx_buffer_.get(data);

            // Put data into the transmit register
            usart_send(config_.device, data);
        }
        else
        {
            // Disable the TXE interrupt as we don't need it anymore
            usart_disable_tx_interrupt(config_.device);
        }
    }

    // Call callback function if attached
    if (irq_callback != 0)
    {
        irq_callback(this);
    }
}
Exemple #22
0
void usart2_isr(void)
{
 
	
	/* Check if we were called because of RXNE. */
	if (((USART_CR1(USART2) & USART_CR1_RXNEIE) != 0) &&
	    ((USART_SR(USART2) & USART_SR_RXNE) != 0)) {

      serial_rxint();
	}

	/* Check if we were called because of TXE. */
	if (((USART_CR1(USART2) & USART_CR1_TXEIE) != 0) &&
	    ((USART_SR(USART2) & USART_SR_TXE) != 0)) {

      serial_txint();
  }

 
}
void client_server_serialirq_init(void)
{
     serial_rb_init(&srx, &(srx_buf[0]), YWASP_SERIAL_RX_BUF);
     serial_rb_init(&stx, &(stx_buf[0]), YWASP_SERIAL_TX_BUF);

     /* Enable the USART1 interrupt. */
     nvic_enable_irq(NVIC_USART1_IRQ);

     /* Enable USART1 Receive interrupt. */
     USART_CR1(USART1) |= USART_CR1_RXNEIE;
}
Exemple #24
0
bool usart_get_interrupt_source(u32 usart, u32 flag)
{
u32 flag_set = (USART_SR(usart) & flag);
/* IDLE, RXNE, TC, TXE interrupts */
	if ((flag >= USART_SR_IDLE) && (flag <= USART_SR_TXE))
		return ((flag_set & USART_CR1(usart)) != 0);
/* Overrun error */
	else if (flag == USART_SR_ORE)
		return (flag_set && (USART_CR3(usart) & USART_CR3_CTSIE));
	return (false);
}
Exemple #25
0
void
usart_uninit(int usart, int irq) {
  /* Disable the IRQ. */
  nvic_disable_irq(irq);

  /* Disable the USART. */
  usart_disable(usart);

  /* Disable usart Receive interrupt. */
  USART_CR1(usart) &= ~USART_CR1_RXNEIE;
}
Exemple #26
0
void uart_periph_set_baudrate(struct uart_periph *p, uint32_t baud)
{
  p->baudrate = baud;

  /* Configure USART baudrate */
  usart_set_baudrate((uint32_t)p->reg_addr, baud);

  /* Disable Idle Line interrupt */
  USART_CR1((uint32_t)p->reg_addr) &= ~USART_CR1_IDLEIE;

  /* Disable LIN break detection interrupt */
  USART_CR2((uint32_t)p->reg_addr) &= ~USART_CR2_LBDIE;

  /* Enable USART1 Receive interrupts */
  USART_CR1((uint32_t)p->reg_addr) |= USART_CR1_RXNEIE;

  /* Enable the USART */
  usart_enable((uint32_t)p->reg_addr);

}
void uart_periph_set_baudrate(struct uart_periph* p, uint32_t baud) {

  /* Configure USART */
  usart_set_baudrate((u32)p->reg_addr, baud);
  usart_set_databits((u32)p->reg_addr, 8);
  usart_set_stopbits((u32)p->reg_addr, USART_STOPBITS_1);
  usart_set_parity((u32)p->reg_addr, USART_PARITY_NONE);

  /* Disable Idle Line interrupt */
  USART_CR1((u32)p->reg_addr) &= ~USART_CR1_IDLEIE;

  /* Disable LIN break detection interrupt */
  USART_CR2((u32)p->reg_addr) &= ~USART_CR2_LBDIE;

  /* Enable USART1 Receive interrupts */
  USART_CR1((u32)p->reg_addr) |= USART_CR1_RXNEIE;

  /* Enable the USART */
  usart_enable((u32)p->reg_addr);

}
Exemple #28
0
inline uint8_t
usart_respond_isr(int usart) {
  static uint8_t data = 'A';
  /* Check if we were called because of RXNE. */
  if (((USART_CR1(usart) & USART_CR1_RXNEIE) != 0) &&
      ((USART_SR(usart) & USART_SR_RXNE) != 0)) {
    /* Retrieve the data from the peripheral. */
    data = usart_recv(usart);
    /* Enable transmit interrupt so it sends back the data. */
    USART_CR1(usart) |= USART_CR1_TXEIE;
  }
  /* Check if we were called because of TXE. */
  if (((USART_CR1(usart) & USART_CR1_TXEIE) != 0) &&
      ((USART_SR(usart) & USART_SR_TXE) != 0)) {
    /* Put data into the transmit register. */
    usart_send(usart, data);
    /* Disable the TXE interrupt as we don't need it anymore. */
    USART_CR1(usart) &= ~USART_CR1_TXEIE;
  }
  return data;
}
Exemple #29
0
int main(void)
{
	int i;

	clock_init();
	gpio_init();
	serial_init(9600);
	serirq_init();
	nrf_init();
	nrf_configure_sb();

	prx.size 	= PL_SIZE;
	ptx.size 	= PL_SIZE;

	while (1) {
        ptx.data[0] = 0;

        while(!serial_rb_empty(&srx) && ptx.data[0] < (PL_SIZE - 1)) {
			ptx.data[ptx.data[0] + 1] = serial_rb_read(&srx);
			ptx.data[0]++;
        }

        if(ptx.data[0] > 0) {
#ifdef MSP430
			P1OUT |= RXTX_LED;
#else
            gpio_set(GPIOC, TX_LED);
#endif
            // switch to PTX for sending out data ...
            nrf_set_mode_ptx();

            nrf_send_blocking(&ptx);

            nrf_set_mode_prx();
        }

        if(nrf_receive(&prx) != 0 && prx.data[0] > 0) {
            if(!serial_rb_full(&stx)) {
                for(i = 0; i < prx.data[0]; i++) serial_rb_write(&stx, prx.data[i + 1]);
#ifdef MSP430
				P1OUT |= RXTX_LED;
				IE2 |= UCA0TXIE;
#else
             	gpio_set(GPIOC, RX_LED);
               	USART_CR1(USART1) |= USART_CR1_TXEIE;
#endif
            }
    	}
	}

	return 0;
}
void uart_transmit(struct uart_periph* p, uint8_t data ) {

  uint16_t temp = (p->tx_insert_idx + 1) % UART_TX_BUFFER_SIZE;

  if (temp == p->tx_extract_idx)
    return;                          // no room

  USART_CR1((u32)p->reg_addr) &= ~USART_CR1_TXEIE; // Disable TX interrupt

  // check if in process of sending data
  if (p->tx_running) { // yes, add to queue
    p->tx_buf[p->tx_insert_idx] = data;
    p->tx_insert_idx = temp;
  }
  else { // no, set running flag and write to output register
    p->tx_running = TRUE;
    usart_send((u32)p->reg_addr, data);
  }

  USART_CR1((u32)p->reg_addr) |= USART_CR1_TXEIE; // Enable TX interrupt

}