Пример #1
0
//-----------------------------------------------------------------------------
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;
}
Пример #2
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 {
      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);
  }
}
Пример #3
0
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;
}
Пример #4
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);
  }
Пример #5
0
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;
}
Пример #6
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;
}
Пример #7
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));
    }
}
Пример #8
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;
}