Exemple #1
0
void spi_init_pins(spi_t bus)
{
    gpio_init(spi_config[bus].clk, GPIO_OUT);
    gpio_init(spi_config[bus].mosi, GPIO_OUT);
    gpio_init(spi_config[bus].miso, GPIO_IN);
    gpio_init_mux(spi_config[bus].clk, spi_config[bus].mux);
    gpio_init_mux(spi_config[bus].mosi, spi_config[bus].mux);
    gpio_init_mux(spi_config[bus].miso, spi_config[bus].mux);
}
Exemple #2
0
void spi_init_pins(spi_t bus)
{
    gpio_init(spi_config[bus].miso_pin, GPIO_IN);
    gpio_init(spi_config[bus].mosi_pin, GPIO_OUT);
    gpio_init(spi_config[bus].clk_pin, GPIO_OUT);
    gpio_init_mux(spi_config[bus].miso_pin, spi_config[bus].miso_mux);
    gpio_init_mux(spi_config[bus].mosi_pin, spi_config[bus].mosi_mux);
    gpio_init_mux(spi_config[bus].clk_pin, spi_config[bus].clk_mux);
}
uint32_t pwm_init(pwm_t dev, pwm_mode_t mode, uint32_t freq, uint16_t res)
{
    uint8_t prescaler;
    int scale = 1;
    uint32_t f_real;

    if ((unsigned int)dev >= PWM_NUMOF) {
        return 0;
    }

    /* calculate the closest possible clock presacler */
    prescaler = get_prescaler(CLOCK_CORECLOCK / (freq * res), &scale);
    if (prescaler == 0xff) {
        return 0;
    }
    f_real = (CLOCK_CORECLOCK / (scale * res));

    /* configure the used pins */
    for (int i = 0; i < PWM_MAX_CHANNELS; i++) {
        if (pwm_config[dev].chan[i].pin != GPIO_UNDEF) {
            gpio_init(pwm_config[dev].chan[i].pin, GPIO_OUT);
            gpio_init_mux(pwm_config[dev].chan[i].pin, pwm_config[dev].chan[i].mux);
        }
    }

    /* power on the device */
    poweron(dev);

    /* reset TCC module */
    _tcc(dev)->CTRLA.reg = TCC_CTRLA_SWRST;
    while (_tcc(dev)->SYNCBUSY.reg & TCC_SYNCBUSY_SWRST) {}
    /* set PWM mode */
    switch (mode) {
        case PWM_LEFT:
            _tcc(dev)->CTRLBCLR.reg = TCC_CTRLBCLR_DIR;     /* count up */
            break;
        case PWM_RIGHT:
            _tcc(dev)->CTRLBSET.reg = TCC_CTRLBSET_DIR;     /* count down */
            break;
        case PWM_CENTER:        /* currently not supported */
        default:
            return 0;
    }
    while (_tcc(dev)->SYNCBUSY.reg & TCC_SYNCBUSY_CTRLB) {}

    /* configure the TCC device */
    _tcc(dev)->CTRLA.reg = (TCC_CTRLA_PRESCSYNC_GCLK_Val
                            | TCC_CTRLA_PRESCALER(prescaler));
    /* select the waveform generation mode -> normal PWM */
    _tcc(dev)->WAVE.reg = (TCC_WAVE_WAVEGEN_NPWM);
    while (_tcc(dev)->SYNCBUSY.reg & TCC_SYNCBUSY_WAVE) {}
    /* set the selected period */
    _tcc(dev)->PER.reg = (res - 1);
    while (_tcc(dev)->SYNCBUSY.reg & TCC_SYNCBUSY_PER) {}
    /* start PWM operation */
    _tcc(dev)->CTRLA.reg |= (TCC_CTRLA_ENABLE);
    /* return the actual frequency the PWM is running at */
    return f_real;
}
Exemple #4
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;
}
Exemple #5
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;
}
Exemple #6
0
int gpio_init(gpio_t pin, gpio_dir_t dir, gpio_pp_t pullup)
{
    (void) dir;
    unsigned _pin = pin & 31;
    unsigned port = pin >> 5;

    FIO_PORT_t *_port = &FIO_PORTS[port];

    /* set mask */
    _port->MASK = ~(0x1<<_pin);

    /* set direction */
    _port->DIR = ~0;

    /* set pullup/pulldown **/
    PINMODE[pin>>4] |= pullup << (_pin*2);

    gpio_init_mux(pin, 0);

    return 0;
}
Exemple #7
0
int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed)
{
    SercomSpi* spi_dev = spi[dev].dev;

    uint8_t   dopo = 0;
    uint8_t   dipo = 0;
    uint8_t   cpha = 0;
    uint8_t   cpol = 0;
    uint32_t  f_baud = 0;

    switch(speed)
    {
        case SPI_SPEED_100KHZ:
            f_baud = 100000;
            break;
        case SPI_SPEED_400KHZ:
            f_baud = 400000;
            break;
        case SPI_SPEED_1MHZ:
            f_baud = 1000000;
            break;
        case SPI_SPEED_5MHZ:
            return -1;
        case SPI_SPEED_10MHZ:
            return -1;
    }

    switch(conf)
    {
        case SPI_CONF_FIRST_RISING: /**< first data bit is transacted on the first rising SCK edge */
            cpha = 0;
            cpol = 0;
            break;
        case SPI_CONF_SECOND_RISING:/**< first data bit is transacted on the second rising SCK edge */
            cpha = 1;
            cpol = 0;
            break;
        case SPI_CONF_FIRST_FALLING:/**< first data bit is transacted on the first falling SCK edge */
            cpha = 0;
            cpol = 1;
            break;
        case SPI_CONF_SECOND_FALLING:/**< first data bit is transacted on the second falling SCK edge */
            cpha = 1;
            cpol = 1;
            break;
    }

    /* Enable sercom4 in power manager */
    MCLK->APBCMASK.reg |= spi[dev].mclk;

    /* Setup clock */
    GCLK->PCHCTRL[ spi[dev].gclk_id ].reg =
        GCLK_PCHCTRL_CHEN |
        GCLK_PCHCTRL_GEN_GCLK0;

    while (!(GCLK->PCHCTRL[spi[dev].gclk_id].reg & GCLK_PCHCTRL_CHEN));

    /* SCLK+MOSI = output */
    gpio_init(spi[dev].sclk.pin, GPIO_DIR_OUT, GPIO_NOPULL);
    gpio_init(spi[dev].mosi.pin, GPIO_DIR_OUT, GPIO_NOPULL);
    /* MISO = input */
    gpio_init(spi[dev].miso.pin, GPIO_DIR_IN, GPIO_PULLUP);

    /*
     * Set alternate funcion (PMUX) for our ports.
     */
    gpio_init_mux(spi[dev].sclk.pin, spi[dev].sclk.pmux);
    gpio_init_mux(spi[dev].miso.pin, spi[dev].miso.pmux);
    gpio_init_mux(spi[dev].mosi.pin, spi[dev].mosi.pmux);

    /* pin pad mapping */
    dipo = spi[dev].dipo;
    dopo = spi[dev].dopo;

    /* Disable spi to write config */
    spi_dev->CTRLA.bit.ENABLE = 0;
    while (spi_dev->SYNCBUSY.reg);

    /* setup baud */
    spi_dev->BAUD.bit.BAUD = (uint8_t) (((uint32_t) GCLK_REF) / (2 * f_baud) - 1); /* Syncronous mode*/

    spi_dev->CTRLA.reg |= SERCOM_SPI_CTRLA_MODE(0x3) /* 0x2 = slave 0x3 = master */
                          |  (SERCOM_SPI_CTRLA_DOPO(dopo))
                          |  (SERCOM_SPI_CTRLA_DIPO(dipo))
                          |  (cpha << SERCOM_SPI_CTRLA_CPHA_Pos)
                          |  (cpol << SERCOM_SPI_CTRLA_CPOL_Pos);

    while (spi_dev->SYNCBUSY.reg);
    spi_dev->CTRLB.reg = (SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN);
    while(spi_dev->SYNCBUSY.reg);
    spi_poweron(dev);
    return 0;
}
Exemple #8
0
void i2c_init(i2c_t dev)
{
    uint32_t timeout_counter = 0;
    int32_t tmp_baud;

    assert(dev < I2C_NUMOF);
    /* Initialize mutex */
    mutex_init(&locks[dev]);
    /* DISABLE I2C MASTER */
    _i2c_poweroff(dev);

    /* Reset I2C */
    bus(dev)->CTRLA.reg = SERCOM_I2CM_CTRLA_SWRST;
    while (bus(dev)->SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_MASK) {}

    /* Turn on power manager for sercom */
    sercom_clk_en(bus(dev));

    /* I2C using CLK GEN 0 */
    sercom_set_gen(bus(dev),i2c_config[dev].gclk_src);

    /* Check if module is enabled. */
    if (bus(dev)->CTRLA.reg & SERCOM_I2CM_CTRLA_ENABLE) {
        DEBUG("STATUS_ERR_DENIED\n");
        return;
    }
    /* Check if reset is in progress. */
    if (bus(dev)->CTRLA.reg & SERCOM_I2CM_CTRLA_SWRST) {
        DEBUG("STATUS_BUSY\n");
        return;
    }

    /************ SERCOM PAD0 - SDA and SERCOM PAD1 - SCL *************/
    gpio_init_mux(i2c_config[dev].sda_pin, i2c_config[dev].mux);
    gpio_init_mux(i2c_config[dev].scl_pin, i2c_config[dev].mux);

    /* I2C CONFIGURATION */
    while (bus(dev)->SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_MASK) {}

    /* Set sercom module to operate in I2C master mode and run in Standby
    if user requests it */
    bus(dev)->CTRLA.reg = SERCOM_I2CM_CTRLA_MODE_I2C_MASTER |
                          ((i2c_config[dev].flags & I2C_FLAG_RUN_STANDBY) ?
                           SERCOM_I2CM_CTRLA_RUNSTDBY : 0);

    /* Enable Smart Mode (ACK is sent when DATA.DATA is read) */
    bus(dev)->CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN;

    /* Find and set baudrate. Read speed configuration. Set transfer
     * speed: SERCOM_I2CM_CTRLA_SPEED(0): Standard-mode (Sm) up to 100
     * kHz and Fast-mode (Fm) up to 400 kHz */
    switch (i2c_config[dev].speed) {
        case I2C_SPEED_NORMAL:
        case I2C_SPEED_FAST:
            bus(dev)->CTRLA.reg |= SERCOM_I2CM_CTRLA_SPEED(0);
            break;
        case I2C_SPEED_HIGH:
            bus(dev)->CTRLA.reg |= SERCOM_I2CM_CTRLA_SPEED(2);
            break;
        default:
            DEBUG("BAD BAUDRATE\n");
            return;
    }
    /* Get the baudrate */
    tmp_baud = (int32_t)(((CLOCK_CORECLOCK +
               (2 * (i2c_config[dev].speed)) - 1) /
               (2 * (i2c_config[dev].speed))) -
               (i2c_config[dev].speed == I2C_SPEED_HIGH ? 1 : 5));
    /* Ensure baudrate is within limits */
    if (tmp_baud < 255 && tmp_baud > 0) {
        bus(dev)->BAUD.reg = SERCOM_I2CM_BAUD_BAUD(tmp_baud);
    }
    /* ENABLE I2C MASTER */
    _i2c_poweron(dev);

    /* Start timeout if bus state is unknown. */
    while ((bus(dev)->STATUS.reg &
          SERCOM_I2CM_STATUS_BUSSTATE_Msk) == BUSSTATE_UNKNOWN) {
        if (timeout_counter++ >= SAMD21_I2C_TIMEOUT) {
            /* Timeout, force bus state to idle. */
            bus(dev)->STATUS.reg = BUSSTATE_IDLE;
        }
    }
}