//----------------------------------------------------------------------------- static void uart_init(uint32_t baud) { HAL_GPIO_UART_TX_out(); HAL_GPIO_UART_TX_pmuxen(HAL_GPIO_PMUX_D); HAL_GPIO_UART_RX_in(); HAL_GPIO_UART_RX_pmuxen(HAL_GPIO_PMUX_D); MCLK->APBBMASK.reg |= MCLK_APBBMASK_SERCOM2; GCLK->PCHCTRL[SERCOM2_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN(0) | GCLK_PCHCTRL_CHEN; while (0 == (GCLK->PCHCTRL[SERCOM2_GCLK_ID_CORE].reg & GCLK_PCHCTRL_CHEN)); SERCOM2->USART.CTRLA.reg = SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_MODE(1/*INT_CLK*/) | SERCOM_USART_CTRLA_RXPO(1/*PAD1*/) | SERCOM_USART_CTRLA_TXPO(0/*PAD0*/) | SERCOM_USART_CTRLA_SAMPR(1); SERCOM2->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_CHSIZE(0/*8 bits*/); #define BAUD_VAL (F_CPU / (16 * baud)) #define FP_VAL ((F_CPU / baud - 16 * BAUD_VAL) / 2) SERCOM2->USART.BAUD.reg = SERCOM_USART_BAUD_FRACFP_BAUD(BAUD_VAL) | SERCOM_USART_BAUD_FRACFP_FP(FP_VAL); SERCOM2->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE; }
/* ========================= * ===== Sercom UART * ========================= */ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate) { initClockNVIC(); resetUART(); //Setting the CTRLA register sercom->USART.CTRLA.reg = SERCOM_USART_CTRLA_MODE(mode) | SERCOM_USART_CTRLA_SAMPR(sampleRate); //Setting the Interrupt register sercom->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC | //Received complete SERCOM_USART_INTENSET_ERROR; //All others errors if ( mode == UART_INT_CLOCK ) { uint16_t sampleRateValue; if (sampleRate == SAMPLE_RATE_x16) { sampleRateValue = 16; } else { sampleRateValue = 8; } // Asynchronous fractional mode (Table 24-2 in datasheet) // BAUD = fref / (sampleRateValue * fbaud) // (multiply by 8, to calculate fractional piece) uint32_t baudTimes8 = (SystemCoreClock * 8) / (sampleRateValue * baudrate); sercom->USART.BAUD.FRAC.FP = (baudTimes8 % 8); sercom->USART.BAUD.FRAC.BAUD = (baudTimes8 / 8); } }
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; }
/* ========================= * ===== Sercom UART * ========================= */ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate) { #if (SAML21) // On the SAML21, SERCOM5 is on PD0, which is a low power domain on a different bridge than the other SERCOMs. // SERCOM5 does not support SAMPLE_RATE_x8 or SAMPLE_RATE_x3. if (sercom == SERCOM5) { sampleRate = SAMPLE_RATE_x16; } #endif initClockNVIC(); resetUART(); //Setting the CTRLA register sercom->USART.CTRLA.reg = SERCOM_USART_CTRLA_MODE(mode) | SERCOM_USART_CTRLA_SAMPR(sampleRate); //Setting the Interrupt register sercom->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC | //Received complete SERCOM_USART_INTENSET_ERROR; //All others errors if ( mode == UART_INT_CLOCK ) { uint16_t sampleRateValue; if (sampleRate == SAMPLE_RATE_x16) { sampleRateValue = 16; } else { sampleRateValue = 8; } #if 0 // Asynchronous arithmetic mode // 65535 * ( 1 - sampleRateValue * baudrate / SercomClock); // 65535 - 65535 * (sampleRateValue * baudrate / SercomClock)); // sercom->USART.BAUD.reg = 65535.0f * ( 1.0f - (float)(sampleRateValue) * (float)(baudrate) / (float)(SercomCoreClock)); // this pulls in 3KB of floating point math code // make numerator much larger than denominator so result is integer (avoid floating point). uint64_t numerator = ((sampleRateValue * (uint64_t)baudrate) << 32); // 32 bits of shifting ensures no loss of precision. uint64_t ratio = divide64(numerator, SercomClock); uint64_t scale = ((uint64_t)1 << 32) - ratio; uint64_t baudValue = (65536 * scale) >> 32; sercom->USART.BAUD.reg = baudValue; #endif // Asynchronous fractional mode (Table 24-2 in datasheet) // BAUD = fref / (sampleRateValue * fbaud) // (multiply by 8, to calculate fractional piece) uint32_t baudTimes8 = (SercomClock * 8) / (sampleRateValue * baudrate); sercom->USART.BAUD.FRAC.FP = (baudTimes8 % 8); sercom->USART.BAUD.FRAC.BAUD = (baudTimes8 / 8); }
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; }
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; }
/* ========================= * ===== Sercom UART * ========================= */ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate) { initClockNVIC(); resetUART(); //Setting the CTRLA register sercom->USART.CTRLA.reg = SERCOM_USART_CTRLA_MODE(mode) | SERCOM_USART_CTRLA_SAMPR(sampleRate); //Setting the Interrupt register sercom->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC | //Received complete SERCOM_USART_INTENSET_ERROR; //All others errors if ( mode == UART_INT_CLOCK ) { uint16_t sampleRateValue ; if ( sampleRate == SAMPLE_RATE_x16 ) { sampleRateValue = 16 ; } else { if ( sampleRate == SAMPLE_RATE_x8 ) { sampleRateValue = 8 ; } else { sampleRateValue = 3 ; } } // Asynchronous arithmetic mode // 65535 * ( 1 - sampleRateValue * baudrate / SystemCoreClock); // 65535 - 65535 * (sampleRateValue * baudrate / SystemCoreClock)); sercom->USART.BAUD.reg = 65535.0f * ( 1.0f - (float)(sampleRateValue) * (float)(baudrate) / (float)(SystemCoreClock)); } }
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; }