Ejemplo n.º 1
0
/** Find the common SERCOM shared by four pins
 *
 * Finds the common SERCOM index shared by four input pins.
 * If reversing the input argument order gives different result, it means, two SERCOMs share the pins
 * @param[in] pin1  First pin
 * @param[in] pin2  Second pin
 * @param[in] pin3  Third pin
 * @param[in] pin4  Fourth pin
 * @return          SERCOM index if found, else, NC
 */
uint32_t pinmap_find_sercom(PinName pin1, PinName pin2, PinName pin3, PinName pin4)
{
    int i;
    uint32_t sercom_index[4];
    uint32_t pin_com = NC;
    uint32_t pin_alt = NC;
    uint32_t count_com = 0;
    uint32_t count_alt = 0;

    sercom_index[0] = pinmap_merge_sercom(pin1, pin2);
    sercom_index[1] = pinmap_merge_sercom(pin3, pin3);
    sercom_index[2] = pinmap_merge_sercom(pin1, pin3);
    sercom_index[3] = pinmap_merge_sercom(pin2, pin4);


    for (i=0; i<4; i++) {
        if (sercom_index[i] != NC) {
            if (pin_com == NC) {
                pin_com = sercom_index[i];
                count_com++;
            } else if (pin_com == sercom_index[i]) {
                count_com++;
            } else if (pin_alt == NC) {
                pin_alt = sercom_index[i];
                count_alt++;
            } else if (pin_alt == sercom_index[i]) {
                count_alt++;
            } else {}
        }
    }
    return ((count_com >= count_alt) ? pin_com : pin_alt);
}
Ejemplo n.º 2
0
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
{
    /* Sanity check arguments */
    MBED_ASSERT(obj);
    uint32_t muxsetting = 0;
    uint32_t sercom_index = 0;

    pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] = rxflow;
    pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] = txflow;
    muxsetting = serial_find_mux_settings(obj);  // getting mux setting from pins
    sercom_index = pinmap_merge_sercom(pSERIAL_S(obj)->pins[USART_TX_INDEX], pSERIAL_S(obj)->pins[USART_RX_INDEX]);  // same variable sercom_index reused for optimization
    if (sercom_index == (uint32_t)NC) {
        /*expecting a valid value for sercom index*/
        return;
    }

    disable_usart(obj);

    /* Set configuration according to the config struct */
    pSERIAL_S(obj)->mux_setting = muxsetting;  // mux setting to be changed for configuring hardware control
    usart_set_config_default(obj);

    struct system_pinmux_config pin_conf;
    pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
    pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
    pin_conf.powersave    = false;

    for (uint8_t pad = 0; pad < 2; pad++) {  // setting for rx and tx
        uint32_t current_pin = pSERIAL_S(obj)->pins[pad];
        if (current_pin != (uint32_t)NC) {
            pin_conf.mux_position = pinmap_function_sercom((PinName)current_pin, sercom_index);
            if ((uint8_t)NC != pin_conf.mux_position) {
                system_pinmux_pin_set_config(current_pin, &pin_conf);
            }
        }
    }
    if((FlowControlRTS == type) || (FlowControlRTSCTS== type))  {
        if (pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] != NC) {
            pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_OUTPUT; // setting for rxflow
            pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_UP;
            pin_conf.mux_position = pinmap_function_sercom(pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] , sercom_index);
            if ((uint8_t)NC != pin_conf.mux_position) {
                system_pinmux_pin_set_config(pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX], &pin_conf);
            }
        }
    }
    if((FlowControlCTS == type) || (FlowControlRTSCTS== type)) {
        if (pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] != NC) {
            pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT; // setting for txflow
            pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_UP;
            pin_conf.mux_position = pinmap_function_sercom(pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] , sercom_index);
            if ((uint8_t)NC != pin_conf.mux_position) {
                system_pinmux_pin_set_config(pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX], &pin_conf);
            }
        }
    }
    enable_usart(obj);
}
Ejemplo n.º 3
0
void serial_break_clear(serial_t *obj)
{
    /* Sanity check arguments */
    MBED_ASSERT(obj);
    uint32_t sercom_index = pinmap_merge_sercom(pSERIAL_S(obj)->pins[USART_TX_INDEX], pSERIAL_S(obj)->pins[USART_RX_INDEX]);

    struct system_pinmux_config pin_conf;
    pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
    pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
    pin_conf.powersave    = false;

    if (pSERIAL_S(obj)->pins[USART_TX_INDEX] != NC) {
        pin_conf.mux_position = pinmap_function_sercom(pSERIAL_S(obj)->pins[USART_TX_INDEX], sercom_index);
        if ((uint8_t)NC != pin_conf.mux_position) {
            system_pinmux_pin_set_config(pSERIAL_S(obj)->pins[USART_TX_INDEX], &pin_conf);
        }
    }
}
Ejemplo n.º 4
0
uint32_t serial_find_mux_settings (serial_t *obj)
{
    /* Sanity check arguments */
    MBED_ASSERT(obj);
    uint32_t mux_setting = 0;
    uint32_t pinpad[4] = {0};
    uint8_t i = 0;
    uint32_t sercom_index = pinmap_merge_sercom(pSERIAL_S(obj)->pins[0], pSERIAL_S(obj)->pins[1]);

    for (i = 0; i < 4 ; i++) {
        pinpad[i] = pinmap_pad_sercom(pSERIAL_S(obj)->pins[i], sercom_index);
    }

    switch(pinpad[USART_RX_INDEX]) {
    case 0:
        mux_setting |= SERCOM_USART_CTRLA_RXPO(0);
        break;
    case 1:
        mux_setting |= SERCOM_USART_CTRLA_RXPO(1);
        break;
    case 2:
        mux_setting |= SERCOM_USART_CTRLA_RXPO(2);
        break;
    case 3:
        mux_setting |= SERCOM_USART_CTRLA_RXPO(3);
        break;
    }

    if ((pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] == NC) && (pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] == NC)) {
        if (pinpad[USART_TX_INDEX] == 0) {
            mux_setting |= SERCOM_USART_CTRLA_TXPO(0);
        } else if(pinpad[USART_TX_INDEX] == 2) {
            mux_setting |= SERCOM_USART_CTRLA_TXPO(1);
        } else {
        }
    } else { // for hardware flow control and uart // expecting the tx in pad 0, rts in pad2 and cts in pad 3
        if((pinpad[USART_TX_INDEX] == 0) && (pinpad[USART_RXFLOW_INDEX]/*rts pin*/ == 2) && (pinpad[USART_TXFLOW_INDEX] /*cts pin*/ == 3)) {
            mux_setting |= SERCOM_USART_CTRLA_TXPO(2);
        }
    }
    return mux_setting;
}
Ejemplo n.º 5
0
void serial_init(serial_t *obj, PinName tx, PinName rx)
{
    /* Sanity check arguments */
    MBED_ASSERT(obj);
    if (g_sys_init == 0) {
        system_init();
        g_sys_init = 1;
    }
    struct system_gclk_chan_config gclk_chan_conf;
    UARTName uart;
    uint32_t gclk_index;
    uint32_t pm_index;
    uint32_t sercom_index = 0;
    uint32_t muxsetting = 0;

    get_default_serial_values(obj);

    pSERIAL_S(obj)->pins[USART_TX_INDEX] = tx;
    pSERIAL_S(obj)->pins[USART_RX_INDEX] = rx;
    pSERIAL_S(obj)->pins[USART_RXFLOW_INDEX] = NC;
    pSERIAL_S(obj)->pins[USART_TXFLOW_INDEX] = NC;

    muxsetting = serial_find_mux_settings(obj);  // getting mux setting from pins
    sercom_index = pinmap_merge_sercom(tx, rx);  // same variable sercom_index reused for optimization
    if (sercom_index == (uint32_t)NC) {
        /*expecting a valid value for sercom index*/
        return;
    }
    sercom_index &= 0x0F;
    uart = (UARTName)pinmap_peripheral_sercom(NC, sercom_index);
    pUSART_S(obj) = (Sercom *)uart;

    /* Disable USART module */
    disable_usart(obj);

#if (SAML21) || (SAMC20) || (SAMC21)
#if (SAML21)
    if (sercom_index == 5) {
        pm_index     = MCLK_APBDMASK_SERCOM5_Pos;
        gclk_index   = SERCOM5_GCLK_ID_CORE;
    } else {
        pm_index     = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
        gclk_index   = sercom_index + SERCOM0_GCLK_ID_CORE;
    }
#else
    pm_index     = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
    gclk_index   = sercom_index + SERCOM0_GCLK_ID_CORE;
#endif
#else
    pm_index     = sercom_index + PM_APBCMASK_SERCOM0_Pos;
    gclk_index   = sercom_index + SERCOM0_GCLK_ID_CORE;
#endif

    if (_USART(obj).CTRLA.reg & SERCOM_USART_CTRLA_SWRST) {
        return;  /* The module is busy resetting itself */
    }

    if (_USART(obj).CTRLA.reg & SERCOM_USART_CTRLA_ENABLE) {
        return;    /* Check the module is enabled */
    }

    /* Turn on module in PM */
#if (SAML21)
    if (sercom_index == 5) {
        system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBD, 1 << pm_index);
    } else {
        system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
    }
#else
    system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
#endif

    /* Set up the GCLK for the module */
    gclk_chan_conf.source_generator = GCLK_GENERATOR_0;
    system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
    system_gclk_chan_enable(gclk_index);
    sercom_set_gclk_generator(GCLK_GENERATOR_0, false);

    pSERIAL_S(obj)->mux_setting = muxsetting;
    /* Set configuration according to the config struct */
    usart_set_config_default(obj);

    struct system_pinmux_config pin_conf;
    pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
    pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
    pin_conf.powersave    = false;

    /* Configure the SERCOM pins according to the user configuration */
    for (uint8_t pad = 0; pad < 4; pad++) {
        uint32_t current_pin = pSERIAL_S(obj)->pins[pad];
        if (current_pin != (uint32_t)NC) {
            pin_conf.mux_position = pinmap_function_sercom((PinName)current_pin, sercom_index);
            if ((uint8_t)NC != pin_conf.mux_position) {
                system_pinmux_pin_set_config(current_pin, &pin_conf);
            }
        }
    }

    if (uart == STDIO_UART) {
        stdio_uart_inited = 1;
        memcpy(&stdio_uart, obj, sizeof(serial_t));
    }
    /* Wait until synchronization is complete */
    usart_syncing(obj);

    /* Enable USART module */
    enable_usart(obj);
}