Beispiel #1
0
void serial_init(SerialInstance* instance, bool isGlobal)
{
  if (instance->_Mapping != 0 || Instances[instance->_Mapping] != NULL)
    throw(AlreadyInitException, "Serial Instance already initialised");
  if (MapIndex > SUPPORTED_INSTANCES)
    throw(InitialisationException, "Maximum number of serial instances established");

  Instances[MapIndex] = instance;
  instance->_Mapping = MapIndex;

  if (isGlobal || GlobalInstance == NULL)
    serial_set_global(instance);

  // Configure GPIO
  gpio_init_af(instance->GPIOX, GPIOMode_AltFunction, GPIOOutputType_PushPull, GPIOSpeed_80MHz_100MHz, GPIOResistor_PullUp, instance->TxPin, GPIOAFMapping_USART1_3);
  gpio_init_af(instance->GPIOX, GPIOMode_AltFunction, GPIOOutputType_PushPull, GPIOSpeed_80MHz_100MHz, GPIOResistor_PullUp, instance->RxPin, GPIOAFMapping_USART1_3);

  USARTInstance Usart = {0};
  Usart.PeripheralMapping = MapIndex;
  Usart.Control1.UsartEnable = true;
  Usart.Control1.TransmitEnable = true;
  Usart.Control1.ReceiveEnable = true;
  Usart.Control1.ReceiveNotEmptyInterruptEnable = true;
  Usart.Control1.WordLength = USARTWordLength_8bit;
  Usart.Control2.StopBits   = USARTStopBits_1;
  Usart.BaudRate = instance->Baudrate;
  Usart.USARTX = instance->USARTX;
  Usart.InterruptPriority = instance->Priority;
  Usart.OnReceiveNotEmpty = &serial_readbyte_isr;
  instance->_Usart = Usart;
  usart_init(&instance->_Usart);

  MapIndex++;
}
Beispiel #2
0
static void _pin_config(gpio_t scl, gpio_t sda)
{
    /* toggle pins to reset analog filter -> see datasheet */
    /* set as output */
    gpio_init(scl, GPIO_DIR_OUT, GPIO_NOPULL);
    gpio_init(sda, GPIO_DIR_OUT, GPIO_NOPULL);
    /* run through toggling sequence */
    gpio_set(scl);
    gpio_set(sda);
    gpio_clear(sda);
    gpio_clear(scl);
    gpio_set(scl);
    gpio_set(sda);
    /* configure the pins alternate function */
    gpio_init_af(scl, GPIO_AF_OUT_OD);
    gpio_init_af(sda, GPIO_AF_OUT_OD);
}
Beispiel #3
0
uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res)
{
    uint32_t bus_clk = periph_apb_clk(pwm_config[pwm].bus);

    /* verify parameters */
    assert((pwm < PWM_NUMOF) && ((freq * res) < bus_clk));

    /* power on the used timer */
    pwm_poweron(pwm);
    /* reset configuration and CC channels */
    dev(pwm)->CR1 = 0;
    dev(pwm)->CR2 = 0;
    for (int i = 0; i < TIMER_CHAN; i++) {
        dev(pwm)->CCR[i] = 0;
    }

    /* configure the used pins */
    unsigned i = 0;
    while ((i < TIMER_CHAN) && (pwm_config[pwm].chan[i].pin != GPIO_UNDEF)) {
        gpio_init(pwm_config[pwm].chan[i].pin, GPIO_OUT);
        gpio_init_af(pwm_config[pwm].chan[i].pin, pwm_config[pwm].af);
        i++;
    }

    /* configure the PWM frequency and resolution by setting the auto-reload
     * and prescaler registers */
    dev(pwm)->PSC = (bus_clk / (res * freq)) - 1;
    dev(pwm)->ARR = res - 1;

    /* set PWM mode */
    switch (mode) {
        case PWM_LEFT:
            dev(pwm)->CCMR1 = CCMR_LEFT;
            dev(pwm)->CCMR2 = CCMR_LEFT;
            break;
        case PWM_RIGHT:
            dev(pwm)->CCMR1 = CCMR_RIGHT;
            dev(pwm)->CCMR2 = CCMR_RIGHT;
            break;
        case PWM_CENTER:
            dev(pwm)->CCMR1 = 0;
            dev(pwm)->CCMR2 = 0;
            dev(pwm)->CR1 |= (TIM_CR1_CMS_0 | TIM_CR1_CMS_1);
            break;
    }

    /* enable PWM outputs and start PWM generation */
#ifdef TIM_BDTR_MOE
    dev(pwm)->BDTR = TIM_BDTR_MOE;
#endif
    dev(pwm)->CCER = (TIM_CCER_CC1E | TIM_CCER_CC2E |
                      TIM_CCER_CC3E | TIM_CCER_CC4E);
    dev(pwm)->CR1 |= TIM_CR1_CEN;

    /* return the actual used PWM frequency */
    return (bus_clk / (res * (dev(pwm)->PSC + 1)));
}
Beispiel #4
0
int i2c_init_master(i2c_t dev, i2c_speed_t speed)
{
    int ccr;

    if ((unsigned int)dev >= I2C_NUMOF) {
        return -1;
    }

    /* read speed configuration */
    switch (speed) {
        case I2C_SPEED_NORMAL:
            ccr = I2C_APBCLK / 200000;
            break;

        case I2C_SPEED_FAST:
            ccr = I2C_APBCLK / 800000;
            break;

        default:
            return -2;
    }
    I2C_TypeDef *i2c = i2c_config[dev].dev;

    /* enable I2C clock */
    i2c_poweron(dev);

    /* set IRQn priority */
    NVIC_SetPriority(i2c_config[dev].er_irqn, I2C_IRQ_PRIO);

    /* enable IRQn */
    NVIC_EnableIRQ(i2c_config[dev].er_irqn);

    /* configure pins */
    gpio_init(i2c_config[dev].scl, GPIO_DIR_OUT, GPIO_PULLUP);
    gpio_init_af(i2c_config[dev].scl, i2c_config[dev].af);
    gpio_init(i2c_config[dev].sda, GPIO_DIR_OUT, GPIO_PULLUP);
    gpio_init_af(i2c_config[dev].sda, i2c_config[dev].af);

    /* configure device */
    _i2c_init(i2c, ccr);

    return 0;
}
Beispiel #5
0
static inline void uart_init_pins(uart_t uart, uart_rx_cb_t rx_cb)
{
     /* 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
}
Beispiel #6
0
int spi_conf_pins(spi_t dev)
{
    gpio_t mosi, miso, clk;

    switch(dev) {
#ifdef SPI_0_EN
        case SPI_0:
            clk = SPI_0_CLK_PIN;
            mosi = SPI_0_MOSI_PIN;
            miso = SPI_0_MISO_PIN;
            break;
#endif
        default:
            return -1;
    }

    /* configure pins for alternate function input (MISO) or output (MOSI, CLK) */
    gpio_init_af(clk, GPIO_AF_OUT_PP);
    gpio_init_af(mosi, GPIO_AF_OUT_PP);
    gpio_init(miso, GPIO_DIR_IN, GPIO_NOPULL);
    return 0;
}
Beispiel #7
0
int uart_init_blocking(uart_t uart, uint32_t baudrate)
{
    USART_TypeDef *dev;
    uint32_t bus_freq;
    gpio_t rx_pin, tx_pin;
    float divider;
    uint16_t mantissa;
    uint8_t fraction;

    /* enable UART and port clocks and select devices */
    switch (uart) {
#if UART_0_EN
        case UART_0:
            dev = UART_0_DEV;
            rx_pin = UART_0_RX_PIN;
            tx_pin = UART_0_TX_PIN;
            bus_freq = UART_0_BUS_FREQ;
            /* enable clocks */
            UART_0_CLKEN();
            break;
#endif
#if UART_1_EN
        case UART_1:
            dev = UART_1_DEV;
            tx_pin = UART_1_TX_PIN;
            rx_pin = UART_1_RX_PIN;
            bus_freq = UART_1_BUS_FREQ;
            /* enable clocks */
            UART_1_CLKEN();
            break;
#endif
        default:
            return -2;
    }
    /* configure RX and TX pin */
    gpio_init_af(tx_pin, GPIO_AF_OUT_PP);
    gpio_init(rx_pin, GPIO_DIR_IN, GPIO_NOPULL);

    /* configure UART to mode 8N1 with given baudrate */
    divider = ((float)bus_freq) / (16 * baudrate);
    mantissa = (uint16_t)floorf(divider);
    fraction = (uint8_t)floorf((divider - mantissa) * 16);
    dev->BRR = 0;
    dev->BRR |= ((mantissa & 0x0fff) << 4) | (0x0f & fraction);

    /* enable receive and transmit mode */
    dev->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
    return 0;
}
Beispiel #8
0
void i2c_init(i2c_t dev)
{
    assert(dev < I2C_NUMOF);

    DEBUG("[i2c] init: initializing device\n");
    mutex_init(&locks[dev]);

    I2C_TypeDef *i2c = i2c_config[dev].dev;

    periph_clk_en(i2c_config[dev].bus, i2c_config[dev].rcc_mask);

    NVIC_SetPriority(i2c_config[dev].irqn, I2C_IRQ_PRIO);
    NVIC_EnableIRQ(i2c_config[dev].irqn);

#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3)
    /* Set I2CSW bits to enable I2C clock source */
    RCC->CFGR3 |= i2c_config[dev].rcc_sw_mask;
#endif

    DEBUG("[i2c] init: configuring pins\n");
    /* configure pins */
    gpio_init(i2c_config[dev].scl_pin, GPIO_OD_PU);
    gpio_init_af(i2c_config[dev].scl_pin, i2c_config[dev].scl_af);
    gpio_init(i2c_config[dev].sda_pin, GPIO_OD_PU);
    gpio_init_af(i2c_config[dev].sda_pin, i2c_config[dev].sda_af);

    DEBUG("[i2c] init: configuring device\n");
    /* set the timing register value from predefined values */
    i2c_timing_param_t tp = timing_params[i2c_config[dev].speed];
    uint32_t timing = (( (uint32_t)tp.presc << I2C_TIMINGR_PRESC_Pos) |
                       ( (uint32_t)tp.scldel << I2C_TIMINGR_SCLDEL_Pos) |
                       ( (uint32_t)tp.sdadel << I2C_TIMINGR_SDADEL_Pos) |
                       ( (uint16_t)tp.sclh << I2C_TIMINGR_SCLH_Pos) |
                       tp.scll);
    _i2c_init(i2c, timing);
}
Beispiel #9
0
Datei: uart.c Projekt: JMR-b/RIOT
static int init_base(uart_t uart, uint32_t baudrate)
{
    USART_TypeDef *dev = 0;
    gpio_t tx_pin = 0;
    gpio_t rx_pin = 0;
    gpio_af_t af = 0;
    float clk = 0;
    uint16_t mantissa;
    uint8_t fraction;

    switch (uart) {
#if UART_0_EN
        case UART_0:
            dev = UART_0_DEV;
            clk = UART_0_CLK;
            tx_pin = UART_0_TX_PIN;
            rx_pin = UART_0_RX_PIN;
            af = UART_0_AF;
            UART_0_CLKEN();
            break;
#endif
#if UART_1_EN
        case UART_1:
            dev = UART_1_DEV;
            clk = UART_1_CLK;
            tx_pin = UART_1_TX_PIN;
            rx_pin = UART_1_RX_PIN;
            af = UART_1_AF;
            UART_1_CLKEN();
            break;
#endif
#if UART_2_EN
        case UART_2:
            dev = UART_2_DEV;
            clk = UART_2_CLK;
            tx_pin = UART_2_TX_PIN;
            rx_pin = UART_2_RX_PIN;
            af = UART_2_AF;
            UART_2_CLKEN();
            break;
#endif
        default:
            return -1;
    }

    /* uart_configure RX and TX pins, set pin to use alternative function mode */
    gpio_init(tx_pin, GPIO_DIR_OUT, GPIO_NOPULL);
    gpio_init_af(tx_pin, af);
    gpio_init(rx_pin, GPIO_DIR_IN, GPIO_NOPULL);
    gpio_init_af(rx_pin, af);

    /* uart_configure UART to mode 8N1 with given baudrate */
    clk /= baudrate;
    mantissa = (uint16_t)(clk / 16);
    fraction = (uint8_t)(clk - (mantissa * 16));
    dev->BRR = ((mantissa & 0x0fff) << 4) | (0x0f & fraction);

    /* enable receive and transmit mode */
    dev->CR3 = 0;
    dev->CR2 = 0;
    dev->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;

    return 0;
}
Beispiel #10
0
static int init_base(uart_t uart, uint32_t baudrate)
{
    cc2538_uart_t *u = NULL;

    switch (uart) {
#if UART_0_EN
        case UART_0:
            u = UART_0_DEV;
            gpio_init_af(UART_0_RX_PIN, UART0_RXD, GPIO_IN);
            gpio_init_af(UART_0_TX_PIN, UART0_TXD, GPIO_OUT);
            break;
#endif
#if UART_1_EN
        case UART_1:
            u = UART_1_DEV;
            gpio_init_af(UART_1_RX_PIN, UART1_RXD, GPIO_IN);
            gpio_init_af(UART_1_TX_PIN, UART1_TXD, GPIO_OUT);
            break;
#endif

        default:
            (void)u;
            return UART_NODEV;
    }

#if UART_0_EN || UART_1_EN
    /* Enable clock for the UART while Running, in Sleep and Deep Sleep */
    unsigned int uart_num = ( (uintptr_t)u - (uintptr_t)UART0 ) / 0x1000;
    SYS_CTRL_RCGCUART |= (1 << uart_num);
    SYS_CTRL_SCGCUART |= (1 << uart_num);
    SYS_CTRL_DCGCUART |= (1 << uart_num);

    /* Make sure the UART is disabled before trying to configure it */
    u->cc2538_uart_ctl.CTL = 0;

    /* Run on SYS_DIV */
    u->CC = 0;

    /* On the CC2538, hardware flow control is supported only on UART1 */
    if (u == UART1) {
#ifdef UART_1_RTS_PIN
        gpio_init_af(UART_1_RTS_PIN, UART1_RTS, GPIO_OUT);
        u->cc2538_uart_ctl.CTLbits.RTSEN = 1;
#endif

#ifdef UART_1_CTS_PIN
        gpio_init_af(UART_1_CTS_PIN, UART1_CTS, GPIO_IN);
        u->cc2538_uart_ctl.CTLbits.CTSEN = 1;
#endif
    }

    /* Enable clock for the UART while Running, in Sleep and Deep Sleep */
    uart_num = ( (uintptr_t)u - (uintptr_t)UART0 ) / 0x1000;
    SYS_CTRL_RCGCUART |= (1 << uart_num);
    SYS_CTRL_SCGCUART |= (1 << uart_num);
    SYS_CTRL_DCGCUART |= (1 << uart_num);

    /*
     * UART Interrupt Masks:
     * Acknowledge RX and RX Timeout
     * Acknowledge Framing, Overrun and Break Errors
     */
    u->cc2538_uart_im.IM = 0;
    u->cc2538_uart_im.IMbits.RXIM = 1; /**< UART receive interrupt mask */
    u->cc2538_uart_im.IMbits.RTIM = 1; /**< UART receive time-out interrupt mask */
    u->cc2538_uart_im.IMbits.OEIM = 1; /**< UART overrun error interrupt mask */
    u->cc2538_uart_im.IMbits.BEIM = 1; /**< UART break error interrupt mask */
    u->cc2538_uart_im.IMbits.FEIM = 1; /**< UART framing error interrupt mask */

    /* Set FIFO interrupt levels: */
    u->cc2538_uart_ifls.IFLSbits.RXIFLSEL = FIFO_LEVEL_4_8TH; /**< MCU default */
    u->cc2538_uart_ifls.IFLSbits.TXIFLSEL = FIFO_LEVEL_4_8TH; /**< MCU default */

    u->cc2538_uart_ctl.CTLbits.RXE = 1;
    u->cc2538_uart_ctl.CTLbits.TXE = 1;
    u->cc2538_uart_ctl.CTLbits.HSE = UART_CTL_HSE_VALUE;

    /* Set the divisor for the baud rate generator */
    uint32_t divisor = sys_clock_freq();
    divisor <<= UART_CTL_HSE_VALUE + 2;
    divisor += baudrate / 2; /**< Avoid a rounding error */
    divisor /= baudrate;
    u->IBRD = divisor >> DIVFRAC_NUM_BITS;
    u->FBRD = divisor & DIVFRAC_MASK;

    /* Configure line control for 8-bit, no parity, 1 stop bit and enable  */
    u->cc2538_uart_lcrh.LCRH = (WLEN_8_BITS << 5) | FEN;

    /* UART Enable */
    u->cc2538_uart_ctl.CTLbits.UARTEN = 1;

    return UART_OK;
#endif /* UART_0_EN || UART_1_EN */
}
Beispiel #11
0
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 UART_USE_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 */
    periph_clk_en(uart_config[uart].bus, uart_config[uart].rcc_mask);

    /* 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 UART_USE_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;
}
Beispiel #13
0
void i2c_init(i2c_t dev)
{
    assert(dev < I2C_NUMOF);

    mutex_init(&locks[dev]);

    I2C_TypeDef *i2c = i2c_config[dev].dev;

    assert(i2c != NULL);

    uint32_t ccr;
    /* read speed configuration */
    switch (i2c_config[dev].speed) {
        case I2C_SPEED_LOW:
            /* 10Kbit/s */
            ccr = i2c_config[dev].clk / 20000;
            break;

        case I2C_SPEED_NORMAL:
            /* 100Kbit/s */
            ccr = i2c_config[dev].clk / 200000;
            break;

        case I2C_SPEED_FAST:
            ccr = i2c_config[dev].clk / 800000;
            break;

        default:
            return;
    }

    periph_clk_en(i2c_config[dev].bus, i2c_config[dev].rcc_mask);
    NVIC_SetPriority(i2c_config[dev].irqn, I2C_IRQ_PRIO);
    NVIC_EnableIRQ(i2c_config[dev].irqn);

    /* configure pins */
    gpio_init(i2c_config[dev].scl_pin, GPIO_OD_PU);
    gpio_init(i2c_config[dev].sda_pin, GPIO_OD_PU);
#ifdef CPU_FAM_STM32F1
    /* This is needed in case the remapped pins are used */
    if (i2c_config[dev].scl_pin == GPIO_PIN(PORT_B, 8) ||
        i2c_config[dev].sda_pin == GPIO_PIN(PORT_B, 9)) {
        /* The remapping periph clock must first be enabled */
        RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
        /* Then the remap can occur */
        AFIO->MAPR |= AFIO_MAPR_I2C1_REMAP;
    }
    gpio_init_af(i2c_config[dev].scl_pin, GPIO_AF_OUT_OD);
    gpio_init_af(i2c_config[dev].sda_pin, GPIO_AF_OUT_OD);
#else
    gpio_init_af(i2c_config[dev].scl_pin, i2c_config[dev].scl_af);
    gpio_init_af(i2c_config[dev].sda_pin, i2c_config[dev].sda_af);
#endif

    /* configure device */
    _i2c_init(i2c, i2c_config[dev].clk, ccr);

#if defined(CPU_FAM_STM32F4)
    /* make sure the analog filters don't hang -> see errata sheet 2.14.7 */
    if (i2c->SR2 & I2C_SR2_BUSY) {
        /* disable peripheral */
        i2c->CR1 &= ~I2C_CR1_PE;
        /* toggle both pins to reset analog filter */
        gpio_init(i2c_config[dev].scl_pin, GPIO_OD);
        gpio_init(i2c_config[dev].sda_pin, GPIO_OD);
        gpio_set(i2c_config[dev].sda_pin);
        gpio_set(i2c_config[dev].scl_pin);
        gpio_clear(i2c_config[dev].sda_pin);
        gpio_clear(i2c_config[dev].scl_pin);
        gpio_set(i2c_config[dev].sda_pin);
        gpio_set(i2c_config[dev].scl_pin);
        /* reset pins for alternate function */
        gpio_init(i2c_config[dev].scl_pin, GPIO_OD_PU);
        gpio_init(i2c_config[dev].sda_pin, GPIO_OD_PU);
        gpio_init_af(i2c_config[dev].scl_pin, i2c_config[dev].scl_af);
        gpio_init_af(i2c_config[dev].sda_pin, i2c_config[dev].sda_af);
        /* make peripheral soft reset */
        i2c->CR1 |= I2C_CR1_SWRST;
        i2c->CR1 &= ~I2C_CR1_SWRST;
        /* enable device */
        _i2c_init(i2c, i2c_config[dev].clk, ccr);
    }
#endif
}