int uart_init_blocking(uart_t uart, uint32_t baudrate) { /* Calculate the BAUD value */ uint64_t temp1 = ((16 * ((uint64_t)baudrate)) << 32); uint64_t ratio = _long_division(temp1 , UART_0_REF_F); uint64_t scale = ((uint64_t)1 << 32) - ratio; uint64_t baud_calculated = (65536 * scale) >> 32; switch (uart) { #if UART_0_EN case UART_0: /* Enable the peripheral channel */ GCLK->PCHCTRL[SERCOM3_GCLK_ID_CORE].reg |= GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK0; while (!(GCLK->PCHCTRL[SERCOM3_GCLK_ID_CORE].reg & GCLK_PCHCTRL_CHEN)) { /* Wait for clock synchronization */ } MCLK->APBCMASK.reg |= MCLK_APBCMASK_SERCOM3; /* configure PINS to input/output*/ UART_0_PORT.DIRSET.reg = (1 << UART_0_TX_PIN); /* tx's direction is output */ UART_0_PORT.PINCFG[UART_0_RX_PIN % 32].bit.INEN = true; /* buffer rx pin's value */ /* enable PMUX for pins and set to config C. */ UART_0_PORT.WRCONFIG.reg = PORT_WRCONFIG_WRPINCFG \ | PORT_WRCONFIG_WRPMUX \ | PORT_WRCONFIG_PMUX(0x2) \ | PORT_WRCONFIG_PMUXEN \ | UART_0_PINS; UART_0_DEV.CTRLA.bit.ENABLE = 0; //Disable to write, need to sync tho while(UART_0_DEV.SYNCBUSY.bit.ENABLE); /* set to LSB, asynchronous mode without parity, PAD0 Tx, PAD1 Rx, * 16x over-sampling, internal clk */ UART_0_DEV.CTRLA.reg = SERCOM_USART_CTRLA_DORD \ | SERCOM_USART_CTRLA_FORM(0x0) \ | SERCOM_USART_CTRLA_SAMPA(0x0) \ | SERCOM_USART_CTRLA_TXPO(0x0) \ | SERCOM_USART_CTRLA_RXPO(0x1) \ | SERCOM_USART_CTRLA_SAMPR(0x0) \ | SERCOM_USART_CTRLA_MODE(0x1) \ | (UART_0_RUNSTDBY ? SERCOM_USART_CTRLA_RUNSTDBY : 0); /* Set baud rate */ UART_0_DEV.BAUD.bit.BAUD = baud_calculated; /* enable receiver and transmitter, one stop bit*/ UART_0_DEV.CTRLB.reg = (SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); while(UART_0_DEV.SYNCBUSY.bit.CTRLB); break; #endif } uart_poweron(uart); return 0; }
int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) { assert(uart < UART_NUMOF); /* save ISR context */ isr_ctx[uart].rx_cb = rx_cb; isr_ctx[uart].arg = arg; isr_ctx[uart].data_mask = 0xFF; uart_init_pins(uart, rx_cb); /* enable the clock */ uart_poweron(uart); /* reset UART configuration -> defaults to 8N1 mode */ dev(uart)->CR1 = 0; dev(uart)->CR2 = 0; dev(uart)->CR3 = 0; #if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L4) switch (uart_config[uart].type) { case STM32_USART: uart_init_usart(uart, baudrate); break; #ifdef MODULE_PERIPH_LPUART case STM32_LPUART: uart_init_lpuart(uart, baudrate); break; #endif default: return UART_NODEV; } #else uart_init_usart(uart, baudrate); #endif /* enable RX interrupt if applicable */ if (rx_cb) { NVIC_EnableIRQ(uart_config[uart].irqn); dev(uart)->CR1 = (USART_CR1_UE | USART_CR1_TE | RXENABLE); } else { dev(uart)->CR1 = (USART_CR1_UE | USART_CR1_TE); } #ifdef MODULE_STM32_PERIPH_UART_HW_FC if (uart_config[uart].cts_pin != GPIO_UNDEF) { /* configure hardware flow control */ dev(uart)->CR3 = (USART_CR3_RTSE | USART_CR3_CTSE); } #endif return UART_OK; }
int uart_init_blocking(uart_t uart, uint32_t baudrate) { uint32_t baud = ((((uint32_t)CLOCK_CORECLOCK * 10) / baudrate) / 16); switch (uart) { #if UART_0_EN case UART_0: /* Turn on power manager for sercom */ PM->APBCMASK.reg |= PM_APBCMASK_SERCOM0; /* configure GCLK0 to feed sercom0 */; GCLK->CLKCTRL.reg = (uint16_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | (SERCOM0_GCLK_ID_CORE << GCLK_CLKCTRL_ID_Pos))); while (GCLK->STATUS.bit.SYNCBUSY); /* configure PINS to input/output*/ UART_0_PORT.DIRSET.reg = (1 << UART_0_TX_PIN); /* tx's direction is output */ UART_0_PORT.PINCFG[UART_0_RX_PIN % 32].bit.INEN = true; /* buffer rx pin's value */ /* enable PMUX for pins and set to config D. See spec p. 12 */ UART_0_PORT.WRCONFIG.reg = PORT_WRCONFIG_WRPINCFG \ | PORT_WRCONFIG_WRPMUX \ | PORT_WRCONFIG_PMUX(0x3) \ | PORT_WRCONFIG_PMUXEN \ | UART_0_PINS; UART_0_DEV.CTRLA.bit.ENABLE = 0; //Disable to write, need to sync tho while(UART_0_DEV.SYNCBUSY.bit.ENABLE); /* set to LSB, asynchronous mode without parity, PAD0 Tx, PAD1 Rx, * 16x over-sampling, internal clk */ UART_0_DEV.CTRLA.reg = SERCOM_USART_CTRLA_DORD \ | SERCOM_USART_CTRLA_RXPO(0x1) \ | SERCOM_USART_CTRLA_SAMPR(0x1) \ | SERCOM_USART_CTRLA_MODE_USART_INT_CLK; UART_0_DEV.BAUD.FRAC.FP = (baud % 10); UART_0_DEV.BAUD.FRAC.BAUD = (baud / 10); /* enable receiver and transmitter, one stop bit*/ UART_0_DEV.CTRLB.reg = (SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); while(UART_0_DEV.SYNCBUSY.bit.CTRLB); break; #endif } uart_poweron(uart); return 0; }
int uart_init(uart_t dev, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) { USART_TypeDef *uart; /* check if device is valid and get base register address */ if (dev >= UART_NUMOF) { return UART_NODEV; } uart = _uart(dev); /* save interrupt callback context */ isr_ctx[dev].rx_cb = rx_cb; isr_ctx[dev].arg = arg; /* power on the device */ uart_poweron(dev); /* put device in asynchronous mode @ 16x oversampling (default UART) */ uart->CTRL = 0; /* configure to default 8N1 configuration */ uart->FRAME = (USART_FRAME_STOPBITS_ONE | USART_FRAME_DATABITS_EIGHT); /* configure the baudrate - this looks more complicated than it is, we just * multiply the HFPERCLK with 32 to cut down on rounding error when doing * the division afterwards... */ uart->CLKDIV = (((CLOCK_HFPERCLK << 5) / (16 * baudrate) - 32) << 3); /* configure the pins */ gpio_init(uart_config[dev].tx_pin, GPIO_OUT); if (rx_cb) { gpio_init(uart_config[dev].rx_pin, GPIO_IN); uart->ROUTE = ((uart_config[dev].loc << _USART_ROUTE_LOCATION_SHIFT) | USART_ROUTE_RXPEN | USART_ROUTE_TXPEN); } else { uart->ROUTE = ((uart_config[dev].loc << _USART_ROUTE_LOCATION_SHIFT) | USART_ROUTE_TXPEN); } if (rx_cb) { /* enable RX interrupt */ NVIC_EnableIRQ(uart_config[dev].irq); NVIC_EnableIRQ(uart_config[dev].irq + 1); uart->IEN |= USART_IEN_RXDATAV; /* enable receiver and transmitter */ uart->CMD = USART_CMD_TXEN | USART_CMD_RXEN; } else { uart->CMD = USART_CMD_TXEN; } return UART_OK; }
int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) { Uart *dev; /* make sure given device is valid */ if (uart >= UART_NUMOF) { return UART_NODEV; } /* get base register */ dev = uart_config[uart].dev; /* register callback */ ctx[uart].rx_cb = rx_cb; ctx[uart].arg = arg; /* enable clock */ uart_poweron(uart); /* configure pins TODO: optimize once GPIO refactoring is merged */ uart_config[uart].rx_port->PIO_PDR = (1 << uart_config[uart].rx_pin); uart_config[uart].rx_port->PIO_ABSR &= ~(1 << uart_config[uart].rx_pin); uart_config[uart].tx_port->PIO_ABSR |= (uart_config[uart].mux << uart_config[uart].rx_pin); uart_config[uart].tx_port->PIO_PDR = (1 << uart_config[uart].tx_pin); uart_config[uart].tx_port->PIO_ABSR &= ~(1 << uart_config[uart].tx_pin); uart_config[uart].tx_port->PIO_ABSR |= (uart_config[uart].mux << uart_config[uart].tx_pin); /* configure baud rate and set mode to 8N1 */ dev->UART_BRGR = (CLOCK_CORECLOCK / (16 * baudrate)); dev->UART_MR = UART_MR_PAR_NO | US_MR_CHRL_8_BIT; dev->UART_CR = UART_CR_RXEN | UART_CR_TXEN | UART_CR_RSTSTA; /* enable RX interrupt */ NVIC_EnableIRQ(uart_config[uart].irqn); dev->UART_IER = UART_IER_RXRDY; return UART_OK; }
static int init_base(uart_t uart, uint32_t baudrate) { uint32_t baud; SercomUsart *dev; if ((unsigned int)uart >= UART_NUMOF) { return -1; } /* get the devices base register */ dev = _uart(uart); /* calculate baudrate */ baud = ((((uint32_t)CLOCK_CORECLOCK * 10) / baudrate) / 16); /* enable sync and async clocks */ uart_poweron(uart); /* configure pins */ gpio_init(uart_config[uart].rx_pin, GPIO_IN); gpio_init_mux(uart_config[uart].rx_pin, uart_config[uart].mux); gpio_init(uart_config[uart].tx_pin, GPIO_OUT); gpio_init_mux(uart_config[uart].tx_pin, uart_config[uart].mux); /* reset the UART device */ dev->CTRLA.reg = SERCOM_USART_CTRLA_SWRST; while (dev->SYNCBUSY.reg & SERCOM_USART_SYNCBUSY_SWRST) {} /* set asynchronous mode w/o parity, LSB first, TX and RX pad as specified * by the board in the periph_conf.h, x16 sampling and use internal clock */ dev->CTRLA.reg = (SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_SAMPR(0x1) | SERCOM_USART_CTRLA_TXPO(uart_config[uart].tx_pad) | SERCOM_USART_CTRLA_RXPO(uart_config[uart].rx_pad) | SERCOM_USART_CTRLA_MODE_USART_INT_CLK); /* set baudrate */ dev->BAUD.FRAC.FP = (baud % 10); dev->BAUD.FRAC.BAUD = (baud / 10); /* enable receiver and transmitter, use 1 stop bit */ dev->CTRLB.reg = (SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); while (dev->SYNCBUSY.reg & SERCOM_USART_SYNCBUSY_CTRLB) {} /* finally, enable the device */ dev->CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE; return 0; }
int uart_init_blocking(uart_t uart, uint32_t baudrate) { uint32_t baud; SercomUsart *dev; if (uart < 0 || uart >= UART_NUMOF) { return -1; } /* get the devices base register */ dev = _uart(uart); /* calculate baudrate */ baud = ((((uint32_t)CLOCK_CORECLOCK * 10) / baudrate) / 16); /* enable sync and async clocks */ uart_poweron(uart); /* configure pins */ gpio_init(uart_config[uart].rx_pin, GPIO_DIR_IN, GPIO_NOPULL); gpio_init_mux(uart_config[uart].rx_pin, uart_config[uart].mux); gpio_init(uart_config[uart].tx_pin, GPIO_DIR_OUT, GPIO_NOPULL); gpio_init_mux(uart_config[uart].tx_pin, uart_config[uart].mux); /* reset the UART device */ dev->CTRLA.reg = SERCOM_USART_CTRLA_SWRST; while (dev->SYNCBUSY.reg & SERCOM_USART_SYNCBUSY_SWRST); /* set asynchronous mode w/o parity, LSB first, PAD0 to TX, PAD1 to RX and * use internal clock */ dev->CTRLA.reg = (SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_RXPO(0x1) | SERCOM_USART_CTRLA_SAMPR(0x1) | SERCOM_USART_CTRLA_MODE_USART_INT_CLK); /* set baudrate */ dev->BAUD.FRAC.FP = (baud % 10); dev->BAUD.FRAC.BAUD = (baud / 10); /* enable receiver and transmitter, use 1 stop bit */ dev->CTRLB.reg = (SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN); while (dev->SYNCBUSY.reg & SERCOM_USART_SYNCBUSY_CTRLB); /* finally, enable the device */ dev->CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE; return 0; }
void at_dev_poweron(at_dev_t *dev) { uart_poweron(dev->uart); }
int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) { USART_TypeDef *dev; DMA_Stream_TypeDef *stream; float divider; uint16_t mantissa; uint8_t fraction; /* check if given UART device does exist */ if ((unsigned int)uart >= UART_NUMOF) { return -1; } /* get UART base address */ dev = _dev(uart); /* remember callback addresses and argument */ uart_ctx[uart].rx_cb = rx_cb; uart_ctx[uart].arg = arg; /* init TX lock and DMA synchronization mutex */ mutex_init(&_tx_lock[uart]); mutex_init(&_tx_dma_sync[uart]); mutex_lock(&_tx_dma_sync[uart]); /* configure pins */ gpio_init(uart_config[uart].rx_pin, GPIO_IN); gpio_init(uart_config[uart].tx_pin, GPIO_OUT); gpio_init_af(uart_config[uart].rx_pin, uart_config[uart].af); gpio_init_af(uart_config[uart].tx_pin, uart_config[uart].af); /* enable UART clock */ uart_poweron(uart); /* calculate and set baudrate */ if (uart_config[uart].bus == APB1) { divider = CLOCK_APB1 / (16 * baudrate); } else { divider = CLOCK_APB2 / (16 * baudrate); } mantissa = (uint16_t)divider; fraction = (uint8_t)((divider - mantissa) * 16); dev->BRR = ((mantissa & 0x0fff) << 4) | (0x0f & fraction); /* configure UART to 8N1 and enable receive and transmit mode */ dev->CR3 = USART_CR3_DMAT; dev->CR2 = 0; dev->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; /* configure the DMA stream for transmission */ dma_poweron(uart_config[uart].dma_stream); stream = dma_stream(uart_config[uart].dma_stream); stream->CR = ((uart_config[uart].dma_chan << 25) | DMA_SxCR_PL_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_TCIE); stream->PAR = (uint32_t)&(dev->DR); stream->FCR = 0; /* enable global and receive interrupts */ NVIC_EnableIRQ(uart_config[uart].irqn); dma_isr_enable(uart_config[uart].dma_stream); dev->CR1 |= USART_CR1_RXNEIE; return 0; }
int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) { uint16_t mantissa; uint8_t fraction; uint32_t clk; assert(uart < UART_NUMOF); /* save ISR context */ isr_ctx[uart].rx_cb = rx_cb; isr_ctx[uart].arg = arg; /* configure TX pin */ gpio_init(uart_config[uart].tx_pin, GPIO_OUT); /* set TX pin high to avoid garbage during further initialization */ gpio_set(uart_config[uart].tx_pin); #ifdef CPU_FAM_STM32F1 gpio_init_af(uart_config[uart].tx_pin, GPIO_AF_OUT_PP); #else gpio_init_af(uart_config[uart].tx_pin, uart_config[uart].tx_af); #endif /* configure RX pin */ if (rx_cb) { gpio_init(uart_config[uart].rx_pin, GPIO_IN); #ifndef CPU_FAM_STM32F1 gpio_init_af(uart_config[uart].rx_pin, uart_config[uart].rx_af); #endif } #ifdef MODULE_STM32_PERIPH_UART_HW_FC if (uart_config[uart].cts_pin != GPIO_UNDEF) { gpio_init(uart_config[uart].cts_pin, GPIO_IN); gpio_init(uart_config[uart].rts_pin, GPIO_OUT); #ifdef CPU_FAM_STM32F1 gpio_init_af(uart_config[uart].rts_pin, GPIO_AF_OUT_PP); #else gpio_init_af(uart_config[uart].cts_pin, uart_config[uart].cts_af); gpio_init_af(uart_config[uart].rts_pin, uart_config[uart].rts_af); #endif } #endif /* enable the clock */ uart_poweron(uart); /* reset UART configuration -> defaults to 8N1 mode */ dev(uart)->CR1 = 0; dev(uart)->CR2 = 0; dev(uart)->CR3 = 0; /* calculate and apply baudrate */ clk = periph_apb_clk(uart_config[uart].bus) / baudrate; mantissa = (uint16_t)(clk / 16); fraction = (uint8_t)(clk - (mantissa * 16)); dev(uart)->BRR = ((mantissa & 0x0fff) << 4) | (fraction & 0x0f); /* enable RX interrupt if applicable */ if (rx_cb) { NVIC_EnableIRQ(uart_config[uart].irqn); dev(uart)->CR1 = (USART_CR1_UE | USART_CR1_TE | RXENABLE); } else { dev(uart)->CR1 = (USART_CR1_UE | USART_CR1_TE); } #ifdef MODULE_STM32_PERIPH_UART_HW_FC if (uart_config[uart].cts_pin != GPIO_UNDEF) { /* configure hardware flow control */ dev(uart)->CR3 = (USART_CR3_RTSE | USART_CR3_CTSE); } #endif return UART_OK; }