예제 #1
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;
}
예제 #2
0
파일: uart.c 프로젝트: ChuckM/libcpa
/*
 * Common USART/UART transmit and receive interrupts are
 * collated to here. Each serial port simply redirects to here
 * while passing in its BASE address in peripheral space and the
 * channel # it has been assigned. The channel number mapping is
 * established at initialization time.
 */
void
common_usart_isr(uint32_t usart, int channel) {
    if (USART_SR(usart) & USART_SR_RXNE) {
        recv_buf[channel][nxt_recv_ndx[channel]] = USART_DR(usart);
        nxt_recv_ndx[channel] = (nxt_recv_ndx[channel] + 1) % UART_BUF_SIZE;
    }
    if (USART_SR(usart) & USART_SR_TXE) {
        if (nxt_xmit_ndx[channel] == cur_xmit_ndx[channel]) {
            usart_disable_tx_interrupt(usart);  // nothing to send
        } else {
            USART_DR(usart) = xmit_buf[channel][cur_xmit_ndx[channel]];
            cur_xmit_ndx[channel] = (cur_xmit_ndx[channel] + 1) % UART_BUF_SIZE;
        }
    }
}
예제 #3
0
/* For interrupt handling we add a new function which is called
 * when recieve interrupts happen. The name (usart1_isr) is created
 * by the irq.json file in libopencm3 calling this interrupt for
 * USART2 'usart2', adding the suffix '_isr', and then weakly binding
 * it to the 'do nothing' interrupt function in vec.c.
 *
 * By defining it in this file the linker will override that weak
 * binding and instead bind it here, but you have to get the name
 * right or it won't work. And you'll wonder where your interrupts
 * are going.
 */
void usart1_isr(void)
{
	uint32_t	reg;
	int			i;

	do {
		reg = USART_SR(CONSOLE_UART);
		if (reg & USART_SR_RXNE) {
			recv_buf[recv_ndx_nxt] = USART_DR(CONSOLE_UART);
#ifdef RESET_ON_CTRLC
			/*
			 * This bit of code will jump to the ResetHandler if you
			 * hit ^C
			 */
			if (recv_buf[recv_ndx_nxt] == '\003') {
				scb_reset_system();
				return; /* never actually reached */
			}
#endif
			/* Check for "overrun" */
			i = (recv_ndx_nxt + 1) % RECV_BUF_SIZE;
			if (i != recv_ndx_cur) {
				recv_ndx_nxt = i;
			}
		}
	/* can read back-to-back interrupts */
	} while ((reg & USART_SR_RXNE) != 0);
}
예제 #4
0
파일: util.c 프로젝트: ChuckM/bb-lcd
/*
 * uart_putc(char c)
 *
 * Write a character the uart (Blocking). This does what it says,
 * puts out a character to the serial port. If one is in the process
 * of being sent it waits until it finishes then puts this one out.
 */
void
uart_putc(char c) {
    while (!(USART_SR(USART6) & USART_SR_TXE)) {
        __asm__("NOP");
    }
    USART_DR(USART6) = (uint16_t)(c & 0xff);
}
예제 #5
0
/*
 * console_putc(char c)
 *
 * Send the character 'c' to the USART, wait for the USART
 * transmit buffer to be empty first.
 */
void console_putc(char c)
{
	uint32_t	reg;
	do {
		reg = USART_SR(CONSOLE_UART);
	} while ((reg & USART_SR_TXE) == 0);
	USART_DR(CONSOLE_UART) = (uint16_t) c & 0xff;
}
예제 #6
0
bool send_byte(u8 byte)
{
	if(USART_SR(USART) & USART_SR_TXE)
	{
		USART_DR(USART) =  byte;
		return true;
	}
	return false;
}
예제 #7
0
static bool put_console_char(int8_t c)
{
    int timeout_cnt = 100; /* allow 100msec for USART busy timeout*/
    bool ret_stat = false;

    do
    {
        /* check Tx register ready transmissiion */
        if(USART_SR(USART3_BASE) & USART_SR_TXE)
        {
            USART_DR(USART3_BASE) = c;
            ret_stat = true;
            break;
        }

        delay_ms(1);   /* 1 ms sampling */
    }
    while(--timeout_cnt);

    return(ret_stat);
}
예제 #8
0
파일: uart.c 프로젝트: goebish/deviation
u8 UART_Send(u8 *data, u16 len) {
    if (busy) return 1;
    busy = 1;

    DMA_stream_reset(USART_DMA);

    dma_set_peripheral_address(USART_DMA.dma, USART_DMA.stream, (u32) &USART_DR(UART_CFG.uart));  /* send data to the USART data register */
    dma_set_memory_address(USART_DMA.dma, USART_DMA.stream, (u32) data);
    dma_set_number_of_data(USART_DMA.dma, USART_DMA.stream, len);
    dma_set_read_from_memory(USART_DMA.dma, USART_DMA.stream);                     /* direction is from memory to usart */
    dma_enable_memory_increment_mode(USART_DMA.dma, USART_DMA.stream);             /* memory pointer increments, peripheral no */
    dma_set_peripheral_size(USART_DMA.dma, USART_DMA.stream, DMA_SxCR_PSIZE_8BIT);  /* USART_DR is 8bit wide in this mode */
    dma_set_memory_size(USART_DMA.dma, USART_DMA.stream, DMA_SxCR_MSIZE_8BIT);      /* destination memory is also 8 bit wide */
    dma_set_priority(USART_DMA.dma, USART_DMA.stream, DMA_CCR_PL_LOW);
    dma_enable_transfer_complete_interrupt(USART_DMA.dma, USART_DMA.stream);
    DMA_channel_select(USART_DMA);

    DMA_enable_stream(USART_DMA);    /* dma ready to go */
    usart_enable_tx_dma(UART_CFG.uart);

    return 0;
}
예제 #9
0
/*
 * get_console_input() - Gets a character from serial port
 *
 * INPUT
 *     - read_char: load pointer with received char data
 * OUTPUT
 *     true/false update status
 */
static bool get_console_input(char *read_char)
{
    int timeout_cnt = 100; /* allow 100msec for USART busy timeout*/
    bool ret_stat = false;

    do
    {
        /* check Rx register ready for read*/
        if(USART_SR(USART3_BASE) & USART_SR_RXNE)
        {
            /* data received */
            *read_char = USART_DR(USART3_BASE);
            ret_stat = true;
            break;
        }

        delay_ms(1);   /* 1 ms sampling */
    }
    while(--timeout_cnt);

    return (ret_stat);
}
예제 #10
0
/* For interrupt handling we add a new function which is called
 * when receive interrupts happen. The name (usart1_isr) is created
 * by the irq.json file in libopencm3 calling this interrupt for
 * USART1 'usart1', adding the suffix '_isr', and then weakly binding
 * it to the 'do nothing' interrupt function in vec.c.
 *
 * By defining it in this file the linker will override that weak
 * binding and instead bind it here, but you have to get the name
 * right or it won't work. And you'll wonder where your interrupts
 * are going.
 */
void usart1_isr(void)
{
	uint32_t	reg;
	int			i;

	do {
		reg = USART_SR(CONSOLE_UART);
		if (reg & USART_SR_RXNE) {
			recv_buf[recv_ndx_nxt] = USART_DR(CONSOLE_UART);
#ifdef RESET_ON_CTRLC
			/* Check for "reset" */
			if (recv_buf[recv_ndx_nxt] == '\003') {
				scb_reset_system();
			}
#endif
			/* Check for "overrun" */
			i = (recv_ndx_nxt + 1) % RECV_BUF_SIZE;
			if (i != recv_ndx_cur) {
				recv_ndx_nxt = i;
			}
		}
	} while ((reg & USART_SR_RXNE) != 0);
				/* can read back-to-back interrupts */
}
예제 #11
0
static void console_putc(char c)
{
    while (!(USART_SR(CONSOLE_UART) & USART_SR_TXE))
        continue;
    USART_DR(CONSOLE_UART) = (uint8_t)c;
}
예제 #12
0
u16 usart_recv(u32 usart)
{
	/* Receive data. */
	return USART_DR(usart) & USART_DR_MASK;
}
예제 #13
0
void usart_send(u32 usart, u16 data)
{
	/* Send data. */
	USART_DR(usart) = (data & USART_DR_MASK);
}
예제 #14
0
	OPTL_INLINE
	uint8_t read()
	{
		return USART_DR(base) & USART_DR_MASK;
	}
예제 #15
0
	OPTL_INLINE
	void write(uint8_t ch)
	{
		USART_DR(base) = ch & USART_DR_MASK;
	}
예제 #16
0
void usart_send(uint32_t usart, uint16_t data)
{
	/* Send data. */
	USART_DR(usart) = (data & USART_DR_MASK);
}
예제 #17
0
파일: uart.c 프로젝트: ChuckM/libcpa
/*
 * uart_init(tx pin, rx pin, baudrate);
 *
 * Initialize a UART that will talk on the tx/rx pin pair at a given baudrate
 * Curently only 8n1 format, no-hw flow control, only.
 *
 * Returns channel unumber (0 - MAX_UART_CHANNELS) or -1 on error
 */
int
uart_init(enum GPIO_PORT_PIN tx, enum GPIO_PORT_PIN rx, int baudrate) {
    uint32_t my_uart = uart_pin_map(tx, USART);
    int i;

    if (uart_pin_map(rx, USART) != my_uart) {
        /* Both pins are not connected to same serial port */
        return -1;
    }
    if (nxt_channel >= MAX_UART_CHANNELS) {
        /* Need more channel configured */
        return -2;
    }
    if (my_uart == 0) {
        /* neither pin connects to a USART? */
        return -3;
    }

    /* Enable Clock for the USART/UART involved */
    rcc_peripheral_enable_clock((uint32_t *)uart_pin_map(tx, APB_REG),
                                uart_pin_map(tx, APB_ENA));

    /* Enable Clock for the GPIOs we are using */
    gpio_enable_clock(tx);
    gpio_enable_clock(rx);

    /* GPIO pins */

    /* Both AF Mode */
    gpio_mode_setup(gpio_base(tx), GPIO_MODE_AF, GPIO_PUPD_NONE, gpio_bit(tx));
    gpio_mode_setup(gpio_base(rx), GPIO_MODE_AF, GPIO_PUPD_NONE, gpio_bit(rx));
    gpio_set_af(gpio_base(tx), uart_pin_map(tx, AF), gpio_bit(tx));
    gpio_set_af(gpio_base(rx), uart_pin_map(rx, AF), gpio_bit(rx));

    /* Transmit pin set to an output */
    gpio_set_output_options(gpio_base(tx), GPIO_OTYPE_PP,
        GPIO_OSPEED_25MHZ, gpio_bit(tx));


    /* Set up UART parameters */
    usart_set_baudrate(my_uart, baudrate);
    usart_set_databits(my_uart, 8);
    usart_set_stopbits(my_uart, USART_STOPBITS_1);
    usart_set_mode(my_uart, USART_MODE_TX_RX);
    usart_set_parity(my_uart, USART_PARITY_NONE);
    usart_set_flow_control(my_uart, USART_FLOWCONTROL_NONE);
    usart_enable(my_uart);

    nxt_recv_ndx[nxt_channel] = cur_recv_ndx[nxt_channel] = 0;
    nxt_xmit_ndx[nxt_channel] = cur_xmit_ndx[nxt_channel] = 0;
    /*
     * This was done to try to get it to run under GDB with the Black
     * Magic debug probe but it didn't have any effect (interrupts
     * are still masked)
     */
    nvic_set_priority(uart_pin_map(tx, IRQ), 0); // highest priority
    nvic_enable_irq(uart_pin_map(tx, IRQ));
    USART_DR(my_uart) = 0;
    usart_enable_rx_interrupt(my_uart);

    /* Now create two mappings, channel => usart, and usart => channel */
    channel_to_uart_map[nxt_channel] = my_uart;
    for (i = 0; i < NUARTS; i++) {
        if (UART_MAP[i] == my_uart) {
            uart_to_channel_map[i] = nxt_channel;
            break;
        }
    }
    nxt_channel++;
    return (nxt_channel - 1);
}
예제 #18
0
uint16_t usart_recv(uint32_t usart)
{
	return USART_DR(usart) & 0xff;
}
예제 #19
0
파일: util.c 프로젝트: ChuckM/bb-lcd
/*
 * If we hit this ISR it is because we got a received character
 * interrupt from the UART.
 */
void usart6_isr() {
    recv_buf[buf_ndx++] = USART_DR(USART2);
    buf_ndx %= RECV_BUFSIZE;
}
예제 #20
0
/*
 * uart_putc
 *
 * This pushes a character into the transmit buffer for
 * the channel and turns on TX interrupts (which will fire
 * because initially the register will be empty.) If the
 * ISR sends out the last character it turns off the transmit
 * interrupt flag, so that it won't keep firing on an empty
 * transmit buffer.
 */
void
uart_putc(char c) {

	while ((USART_SR(USART1) & USART_SR_TXE) == 0);
	USART_DR(USART1) = c;
}
예제 #21
0
uint16_t usart_recv(uint32_t usart)
{
	/* Receive data. */
	return USART_DR(usart) & USART_DR_MASK;
}
예제 #22
0
/** Setup the USART for transmission with DMA.
 * This function sets up the DMA controller and additional USART parameters for
 * DMA transmit. The USART must already be configured for normal operation.
 *
 * \param s The USART DMA state structure.
 * \oaram usart The USART base address.
 * \param dma The DMA controller base address.
 * \param stream The DMA stream number to use.
 * \param channel The DMA channel to use. The stream and channel must
 *                correspond to a USART RX channel.
 */
void usart_tx_dma_setup(usart_tx_dma_state* s, u32 usart,
                        u32 dma, u8 stream, u8 channel)
{
    s->dma = dma;
    s->usart = usart;
    s->stream = stream;
    s->channel = channel;

    s->byte_counter = 0;
    s->last_byte_ticks = chTimeNow();

    /* Enable clock to DMA peripheral. */
    if (dma == DMA1)
        RCC_AHB1ENR |= RCC_AHB1ENR_DMA1EN;
    else if (dma == DMA2)
        RCC_AHB1ENR |= RCC_AHB1ENR_DMA2EN;

    /* Enable TX DMA on the USART. */
    usart_enable_tx_dma(usart);

    /* Make sure stream is disabled to start. */
    DMA_SCR(dma, stream) &= ~DMA_SxCR_EN;

    /* Configure the DMA controller. */
    DMA_SCR(dma, stream) = 0;
    DMA_SCR(dma, stream) =
        /* Error interrupts. */
        DMA_SxCR_DMEIE | DMA_SxCR_TEIE |
        /* Transfer complete interrupt. */
        DMA_SxCR_TCIE |
        DMA_SxCR_DIR_MEM_TO_PERIPHERAL |
        /* Increment the memory address after each transfer. */
        DMA_SxCR_MINC |
        /* 4 bytes written to the FIFO from memory at a time */
        DMA_SxCR_MBURST_INCR4 |
        /* 8 bit transfers from USART peripheral. */
        DMA_SxCR_PSIZE_8BIT |
        /* and to memory. */
        DMA_SxCR_MSIZE_8BIT |
        /* TODO: what priority level is necessary? */
        /* Very high priority. */
        DMA_SxCR_PL_VERY_HIGH |
        /* The channel selects which request line will trigger a transfer.
         * (see CD00225773.pdf Table 23). */
        DMA_SxCR_CHSEL(channel);

    /* For now, don't transfer any number of datas
     * (will be set in the initiating function). */
    DMA_SNDTR(dma, stream) = 0;

    /* DMA into the USART data register... */
    DMA_SPAR(dma, stream) = &USART_DR(usart);
    /* ...from the TX buffer. */
    DMA_SM0AR(dma, stream) = s->buff;

    /* TODO: Investigate more about the best FIFO settings. */
    DMA_SFCR(dma, stream) =
        DMA_SxFCR_DMDIS |         /* Enable DMA stream FIFO. */
        DMA_SxFCR_FTH_2_4_FULL |  /* Trigger level 2/4 full. */
        DMA_SxFCR_FEIE;           /* Enable FIFO error interrupt. */

    s->wr = s->rd = 0;  /* Buffer is empty to begin with. */

    /* Enable DMA interrupts for this stream with the NVIC. */
    if (dma == DMA1)
        nvicEnableVector(dma_irq_lookup[0][stream],
                         CORTEX_PRIORITY_MASK(USART_DMA_ISR_PRIORITY));
    else if (dma == DMA2)
        nvicEnableVector(dma_irq_lookup[1][stream],
                         CORTEX_PRIORITY_MASK(USART_DMA_ISR_PRIORITY));
}
예제 #23
0
/** Setup the USART for receive with DMA.
 * This function sets up the DMA controller and additional USART parameters for
 * DMA receive. The USART must already be configured for normal operation.
 *
 * \param s The USART DMA state structure.
 * \oaram usart The USART base address.
 * \param dma The DMA controller base address.
 * \param stream The DMA stream number to use.
 * \param channel The DMA channel to use. The stream and channel must
 *                correspond to a USART RX channel.
 */
void usart_rx_dma_setup(usart_rx_dma_state* s, u32 usart,
                        u32 dma, u8 stream, u8 channel)
{
  s->dma = dma;
  s->usart = usart;
  s->stream = stream;
  s->channel = channel;
  chBSemInit(&s->ready_sem, TRUE);

  s->byte_counter = 0;
  s->last_byte_ticks = chTimeNow();

  /* Enable clock to DMA peripheral. */
  if (dma == DMA1)
    RCC_AHB1ENR |= RCC_AHB1ENR_DMA1EN;
  else if (dma == DMA2)
    RCC_AHB1ENR |= RCC_AHB1ENR_DMA2EN;

  /* Enable RX DMA on the USART. */
  usart_enable_rx_dma(usart);

  /* Make sure stream is disabled to start. */
  DMA_SCR(dma, stream) &= ~DMA_SxCR_EN;

  /* RM0090 - 9.3.17 : Supposed to wait until enable bit reads '0' before we
   * write to registers. */
  while (DMA_SCR(dma, stream) & DMA_SxCR_EN) ;

  /* RM0090 - 9.3.17 : Supposed to clear any interrupts in DMA status register
   * before we reconfigure registers. */
  dma_clear_interrupt_flags(dma, stream, DMA_ISR_FLAGS);

  /* Configure the DMA controller. */
  DMA_SCR(dma, stream) = 0;
  DMA_SCR(dma, stream) =
    /* Error interrupts. */
    DMA_SxCR_DMEIE | DMA_SxCR_TEIE |
    /* Transfer complete interrupt. */
    DMA_SxCR_TCIE |
    /* Enable circular buffer mode. */
    DMA_SxCR_CIRC |
    DMA_SxCR_DIR_PERIPHERAL_TO_MEM |
    /* Increment the memory address after each transfer. */
    DMA_SxCR_MINC |
    /* 8 bit transfers from USART peripheral. */
    DMA_SxCR_PSIZE_8BIT |
    /* and to memory. */
    DMA_SxCR_MSIZE_8BIT |
    /* Low priority. */
    DMA_SxCR_PL_LOW |
    /* The channel selects which request line will trigger a transfer.
     * (see CD00225773.pdf Table 23). */
    DMA_SxCR_CHSEL(channel);

  /* Transfer up to the length of the buffer. */
  DMA_SNDTR(dma, stream) = USART_RX_BUFFER_LEN;

  /* DMA from the USART data register... */
  DMA_SPAR(dma, stream) = &USART_DR(usart);
  /* ...to the RX buffer. */
  DMA_SM0AR(dma, stream) = s->buff;

  /* Buffer is empty to begin with. */
  s->rd = 0;
  s->rd_wraps = s->wr_wraps = 0;

  /* Enable DMA interrupts for this stream with the NVIC. */
  if (dma == DMA1)
    nvicEnableVector(dma_irq_lookup[0][stream],
        CORTEX_PRIORITY_MASK(USART_DMA_ISR_PRIORITY));
  else if (dma == DMA2)
    nvicEnableVector(dma_irq_lookup[1][stream],
        CORTEX_PRIORITY_MASK(USART_DMA_ISR_PRIORITY));

  /* These reads clear error flags before enabling DMA */
  (void)USART_SR(usart);
  (void)USART_DR(usart);

  /* Enable the DMA channel. */
  DMA_SCR(dma, stream) |= DMA_SxCR_EN;
}
예제 #24
0
void usart_send(uint32_t usart, uint16_t data)
{
	USART_DR(usart) = data;
}