void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) { MBED_ASSERT(obj); Eic *const eic = _extint_get_eic_from_channel(obj->ch); if (enable) { if (event == IRQ_RISE) { obj->irqmask |= IRQ_RISE_POSITION; } else if (event == IRQ_FALL) { obj->irqmask |= IRQ_FALL_POSITION; } eic->INTENSET.reg = (1UL << obj->ch); } else { if (event == IRQ_RISE) { obj->irqmask &= ~IRQ_RISE_POSITION; } else if (event == IRQ_FALL) { obj->irqmask &= ~IRQ_FALL_POSITION; } } if (obj->irqmask == (IRQ_RISE_POSITION | IRQ_FALL_POSITION)) { pEXT_CONF(obj).detection_criteria = EXTINT_DETECT_BOTH; } else if (obj->irqmask == IRQ_RISE_POSITION) { pEXT_CONF(obj).detection_criteria = EXTINT_DETECT_RISING; } else if (obj->irqmask == IRQ_FALL_POSITION) { pEXT_CONF(obj).detection_criteria = EXTINT_DETECT_FALLING; } else { pEXT_CONF(obj).detection_criteria = EXTINT_DETECT_NONE; eic->INTENCLR.reg = (1UL << obj->ch); } extint_chan_set_config(obj->ch, &pEXT_CONF(obj)); }
/*---------------------------------------------------------------------------*/ void button_sensor_init(void) { struct extint_chan_conf config_extint_chan; struct port_config pin_conf; port_get_config_defaults(&pin_conf); pin_conf.direction = PORT_PIN_DIR_INPUT; pin_conf.input_pull = PORT_PIN_PULL_UP; port_pin_set_config(BUTTON_0_PIN, &pin_conf); // extint_enable(); extint_chan_get_config_defaults(&config_extint_chan); config_extint_chan.gpio_pin = BUTTON_0_EIC_PIN; config_extint_chan.gpio_pin_mux = BUTTON_0_EIC_MUX; config_extint_chan.gpio_pin_pull = EXTINT_PULL_UP; config_extint_chan.detection_criteria = EXTINT_DETECT_FALLING; // config_extint_chan.detection_criteria = EXTINT_DETECT_BOTH; extint_chan_set_config(BUTTON_0_EIC_LINE, &config_extint_chan); extint_register_callback((extint_callback_t)extint_detection_callback, BUTTON_0_EIC_LINE, EXTINT_CALLBACK_TYPE_DETECT); extint_chan_enable_callback(BUTTON_0_EIC_LINE, EXTINT_CALLBACK_TYPE_DETECT); timer_set(&debouncetimer, 0); system_interrupt_enable_global(); /* on by default */ button_sensor_configure(0, 1); }
/** * \internal * \brief Test for external interrupt detection by polling. * * This test changes the logic level of PB05 from high to low * so that the external interrupt channel detects the edge. * * Detection is tested for both rising and falling edges. * * \param test Current test case. */ static void run_extint_polled_mode_test(const struct test_case *test) { /* Testing the falling edge detection */ /* Generate falling edge */ port_pin_set_output_level(GPIO_TEST_PIN_EXTINT, false); /* Wait for the pin level to stabilize */ delay_ms(1); result = extint_chan_is_detected(EIC_TEST_CHANNEL); test_assert_true(test, result, "External interrupt falling edge detection by polling failed"); extint_chan_clear_detected(EIC_TEST_CHANNEL); /* Testing the rising edge detection */ result = false; eic_conf.detection_criteria = EXTINT_DETECT_RISING; extint_chan_set_config(EIC_TEST_CHANNEL, &eic_conf); /* Generate rising edge */ port_pin_set_output_level(GPIO_TEST_PIN_EXTINT, true); /* Wait for the pin level to stabilize */ delay_ms(1); result = extint_chan_is_detected(EIC_TEST_CHANNEL); test_assert_true(test, result, "External interrupt rising edge detection by polling failed"); extint_chan_clear_detected(EIC_TEST_CHANNEL); }
/*============================================================================== hal_extIntInit() =============================================================================*/ uint8_t hal_extIntInit( en_targetExtInt_t e_intSource, pfn_intCallb_t pfn_intCallback ) { int8_t c_ret = 0; if( pfn_intCallback != NULL ) { switch( e_intSource ) { case E_TARGET_RADIO_INT: //! [setup_init] //extint_enable(); //! [conf_channel] //! [setup_1] extint_chan_get_config_defaults( &( radio_extInt.st_chan ) ); //! [setup_1] //! [setup_2] radio_extInt.st_chan.gpio_pin = radio_extInt.l_pin; //EXT1_IRQ_PIN; radio_extInt.st_chan.gpio_pin_mux = radio_extInt.l_pinMux; //MUX_PB04A_EIC_EXTINT4; radio_extInt.st_chan.gpio_pin_pull = radio_extInt.c_pinPull; //EXTINT_PULL_DOWN; radio_extInt.st_chan.detection_criteria = radio_extInt.c_detCrit; //EXTINT_DETECT_RISING; //! [setup_2] //! [setup_3] extint_chan_set_config( (uint8_t)radio_extInt.l_line, &( radio_extInt.st_chan ) ); //! [setup_3] _radio_callback = pfn_intCallback; //! [setup_4] extint_register_callback( (extint_callback_t)_isr_radio_callback, (uint8_t)radio_extInt.l_line, EXTINT_CALLBACK_TYPE_DETECT ); //! [setup_4] //! [setup_5] extint_chan_enable_callback( (uint8_t)radio_extInt.l_line, //EXT1_IRQ_INPUT, EXTINT_CALLBACK_TYPE_DETECT ); //! [setup_6] //! [conf_channel] //! [setup_init] system_interrupt_enable_global(); c_ret = 1; break; case E_TARGET_USART_INT: break; default: break; } } return c_ret; } /* hal_extIntInit() */
/** * \internal * \brief Cleanup function for callback mode test. * * This function disables the callback & external interrupt channel. * * \param test Current test case. */ static void cleanup_extint_callback_mode_test(const struct test_case *test) { eic_conf.detection_criteria = EXTINT_DETECT_NONE; extint_chan_set_config(EIC_TEST_CHANNEL, &eic_conf); /* Unregister and disable the callback function */ extint_unregister_callback(extint_user_callback, EIC_TEST_CHANNEL, EXTINT_CALLBACK_TYPE_DETECT); extint_chan_disable_callback(EIC_TEST_CHANNEL, EXTINT_CALLBACK_TYPE_DETECT); }
/** Configures the External Interrupt Controller to detect changes in the board * button state. */ static void configure_extint(void) { struct extint_chan_conf eint_chan_conf; extint_chan_get_config_defaults(&eint_chan_conf); eint_chan_conf.gpio_pin = BUTTON_0_EIC_PIN; eint_chan_conf.gpio_pin_mux = BUTTON_0_EIC_MUX; eint_chan_conf.detection_criteria = EXTINT_DETECT_BOTH; eint_chan_conf.filter_input_signal = true; extint_chan_set_config(BUTTON_0_EIC_LINE, &eint_chan_conf); }
void configure_extint_channel(void) { struct extint_chan_conf config_extint_chan; extint_chan_get_config_defaults(&config_extint_chan); config_extint_chan.gpio_pin = PIN_PA02A_EIC_EXTINT2; config_extint_chan.gpio_pin_mux = PINMUX_PA02A_EIC_EXTINT2; config_extint_chan.gpio_pin_pull = EXTINT_PULL_DOWN; config_extint_chan.detection_criteria = EXTINT_DETECT_FALLING; extint_chan_set_config(2, &config_extint_chan); }
void cph_deca_init_gpio(void) { struct extint_chan_conf config_chan; extint_chan_get_config_defaults(&config_chan); config_chan.gpio_pin = DW_IRQ_PIN; config_chan.gpio_pin_mux = DW_IRQ_PIN_MUX; config_chan.gpio_pin_pull = DW_IRQ_PIN_PULL; config_chan.detection_criteria = DW_IRQ_PIN_DETECT; extint_chan_set_config(DW_IRQ_LINE, &config_chan); extint_register_callback(cph_deca_isr, DW_IRQ_LINE, EXTINT_CALLBACK_TYPE_DETECT); }
/** * \internal * \brief Setup function for polled mode test. * * This function sets up the GPIO pin and the external interrupt channel. * * \param test Current test case. */ static void setup_extint_polled_mode_test(const struct test_case *test) { /* Configure the GPIO pin */ port_get_config_defaults(&pin_conf); pin_conf.direction = PORT_PIN_DIR_OUTPUT; pin_conf.input_pull = PORT_PIN_PULL_NONE; port_pin_set_config(GPIO_TEST_PIN_EXTINT, &pin_conf); port_pin_set_output_level(GPIO_TEST_PIN_EXTINT, true); /* Configure the external interrupt channel */ extint_chan_get_config_defaults(&eic_conf); eic_conf.gpio_pin = EIC_TEST_PIN; eic_conf.gpio_pin_mux = EIC_TEST_PIN_MUX; eic_conf.gpio_pin_pull = EXTINT_PULL_UP; eic_conf.detection_criteria = EXTINT_DETECT_FALLING; extint_chan_set_config(EIC_TEST_CHANNEL, &eic_conf); }
static void configure_eic(void) { struct extint_chan_conf config_extint_chan; extint_chan_get_config_defaults(&config_extint_chan); config_extint_chan.gpio_pin = PIN_PA11A_EIC_EXTINT11; config_extint_chan.gpio_pin_mux = PINMUX_PA11A_EIC_EXTINT11; config_extint_chan.gpio_pin_pull = EXTINT_PULL_DOWN; config_extint_chan.detection_criteria = EXTINT_DETECT_HIGH; extint_chan_set_config(11 , &config_extint_chan); struct extint_events conf_extint_event; memset(&conf_extint_event, 0, sizeof(struct extint_events)); conf_extint_event.generate_event_on_detect[11] = true; extint_enable_events(&conf_extint_event); }
void config_wind_speed() { struct extint_chan_conf wind_speed_chan; extint_chan_get_config_defaults(&wind_speed_chan); wind_speed_chan.gpio_pin = WIND_SPEED_INTERRUPT_PIN; wind_speed_chan.gpio_pin_mux = WIND_SPEED_INTERRUPT_MUX; wind_speed_chan.gpio_pin_pull = EXTINT_PULL_UP; wind_speed_chan.detection_criteria = EXTINT_DETECT_RISING; extint_chan_set_config(WIND_SPEED_INTERRUPT_LINE, &wind_speed_chan); extint_register_callback(wind_click_handle, WIND_SPEED_INTERRUPT_LINE, EXTINT_CALLBACK_TYPE_DETECT); extint_chan_enable_callback(WIND_SPEED_INTERRUPT_LINE, EXTINT_CALLBACK_TYPE_DETECT); return; }
WEATHER_ERR_T config_rain_guage() { struct extint_chan_conf rain_extint_chan; extint_chan_get_config_defaults(&rain_extint_chan); rain_extint_chan.gpio_pin = RAIN_INTERRUPT_PIN; rain_extint_chan.gpio_pin_mux = RAIN_INTERRUPT_MUX; rain_extint_chan.gpio_pin_pull = EXTINT_PULL_UP; rain_extint_chan.detection_criteria = EXTINT_DETECT_RISING; extint_chan_set_config(RAIN_INTERRUPT_LINE, &rain_extint_chan); extint_register_callback(rain_click_handle, RAIN_INTERRUPT_LINE, EXTINT_CALLBACK_TYPE_DETECT); extint_chan_enable_callback(RAIN_INTERRUPT_LINE, EXTINT_CALLBACK_TYPE_DETECT); return W_ERR_NONE; }
/** * \brief Initializes and enables interrupt pin change */ static void ui_enable_asynchronous_interrupt(void) { /* Initialize EIC for button wakeup */ struct extint_chan_conf eint_chan_conf; extint_chan_get_config_defaults(&eint_chan_conf); eint_chan_conf.gpio_pin = BUTTON_0_EIC_PIN; eint_chan_conf.gpio_pin_mux = BUTTON_0_EIC_MUX; eint_chan_conf.detection_criteria = EXTINT_DETECT_FALLING; eint_chan_conf.filter_input_signal = true; extint_chan_set_config(BUTTON_0_EIC_LINE, &eint_chan_conf); extint_register_callback(UI_WAKEUP_HANDLER, BUTTON_0_EIC_LINE, EXTINT_CALLBACK_TYPE_DETECT); extint_chan_clear_detected(BUTTON_0_EIC_LINE); extint_chan_enable_callback(BUTTON_0_EIC_LINE, EXTINT_CALLBACK_TYPE_DETECT); }
/* * @fn nm_bsp_register_isr * @brief Register interrupt service routine * @param[IN] pfIsr * Pointer to ISR handler */ void nm_bsp_register_isr(tpfNmBspIsr pfIsr) { struct extint_chan_conf config_extint_chan; gpfIsr = pfIsr; extint_chan_get_config_defaults(&config_extint_chan); config_extint_chan.gpio_pin = CONF_WINC_SPI_INT_PIN; config_extint_chan.gpio_pin_mux = CONF_WINC_SPI_INT_MUX; config_extint_chan.gpio_pin_pull = EXTINT_PULL_UP; config_extint_chan.detection_criteria = EXTINT_DETECT_FALLING; extint_chan_set_config(CONF_WINC_SPI_INT_EIC, &config_extint_chan); extint_register_callback(chip_isr, CONF_WINC_SPI_INT_EIC, EXTINT_CALLBACK_TYPE_DETECT); extint_chan_enable_callback(CONF_WINC_SPI_INT_EIC, EXTINT_CALLBACK_TYPE_DETECT); }
//! [config_eic] static void configure_eic(void) { //! [eic_chan_setup] //! [eic_setup_1] struct extint_chan_conf config; //! [eic_setup_1] //! [eic_setup_2] extint_chan_get_config_defaults(&config); //! [eic_setup_2] //! [eic_setup_3] config.filter_input_signal = true; config.detection_criteria = EXTINT_DETECT_BOTH; config.gpio_pin = CONF_FAULT_EIC_PIN; config.gpio_pin_mux = CONF_FAULT_EIC_PIN_MUX; //! [eic_setup_3] //! [eic_setup_4] extint_chan_set_config(CONF_FAULT_EIC_LINE, &config); //! [eic_setup_4] //! [eic_chan_setup] //! [eic_event_setup] //! [eic_event_setup_1] struct extint_events events; memset(&events, 0, sizeof(struct extint_events)); //! [eic_event_setup_1] //! [eic_event_setup_2] events.generate_event_on_detect[CONF_FAULT_EIC_LINE] = true; //! [eic_event_setup_2] //! [eic_event_setup_3] extint_enable_events(&events); //! [eic_event_setup_3] //! [eic_event_setup] //! [eic_callback_setup] //! [eic_callback_setup_1] extint_register_callback(eic_callback_to_clear_halt, CONF_FAULT_EIC_LINE, EXTINT_CALLBACK_TYPE_DETECT); //! [eic_callback_setup_1] //! [eic_callback_setup_2] extint_chan_enable_callback(CONF_FAULT_EIC_LINE, EXTINT_CALLBACK_TYPE_DETECT); //! [eic_callback_setup_2] //! [eic_callback_setup] }
void ui_init(void) { struct extint_chan_conf config_extint_chan; extint_chan_get_config_defaults(&config_extint_chan); config_extint_chan.gpio_pin = BUTTON_0_EIC_PIN; config_extint_chan.gpio_pin_mux = BUTTON_0_EIC_MUX; config_extint_chan.gpio_pin_pull = EXTINT_PULL_UP; config_extint_chan.filter_input_signal = true; config_extint_chan.detection_criteria = EXTINT_DETECT_FALLING; extint_chan_set_config(BUTTON_0_EIC_LINE, &config_extint_chan); extint_register_callback(ui_wakeup_handler, BUTTON_0_EIC_LINE, EXTINT_CALLBACK_TYPE_DETECT); extint_chan_enable_callback(BUTTON_0_EIC_LINE,EXTINT_CALLBACK_TYPE_DETECT); /* Initialize LEDs */ LED_On(LED_0_PIN); }
/** * USB ID pin configuration */ static void usb_id_config(void) { struct extint_chan_conf eint_chan_conf; extint_chan_get_config_defaults(&eint_chan_conf); eint_chan_conf.gpio_pin = USB_ID_PIN; eint_chan_conf.gpio_pin_mux = USB_ID_EIC_MUX; eint_chan_conf.detection_criteria = EXTINT_DETECT_BOTH; eint_chan_conf.filter_input_signal = true; extint_chan_disable_callback(USB_ID_EIC_LINE, EXTINT_CALLBACK_TYPE_DETECT); extint_chan_set_config(USB_ID_EIC_LINE, &eint_chan_conf); extint_register_callback(usb_id_handler, USB_ID_EIC_LINE, EXTINT_CALLBACK_TYPE_DETECT); extint_chan_enable_callback(USB_ID_EIC_LINE, EXTINT_CALLBACK_TYPE_DETECT); }
//! [setup] void configure_extint_channel(void) { //! [setup_1] struct extint_chan_conf config_extint_chan; //! [setup_1] //! [setup_2] extint_chan_get_config_defaults(&config_extint_chan); //! [setup_2] //! [setup_3] config_extint_chan.gpio_pin = BUTTON_0_EIC_PIN; config_extint_chan.gpio_pin_mux = BUTTON_0_EIC_MUX; config_extint_chan.gpio_pin_pull = EXTINT_PULL_UP; config_extint_chan.detection_criteria = EXTINT_DETECT_BOTH; //! [setup_3] //! [setup_4] extint_chan_set_config(BUTTON_0_EIC_LINE, &config_extint_chan); //! [setup_4] }
void configurationPPS(void){ struct extint_chan_conf eint_chan_conf; extint_chan_get_config_defaults(&eint_chan_conf); // put the button as EXTINT eint_chan_conf.gpio_pin = PIN_PA28A_EIC_EXTINT8; eint_chan_conf.gpio_pin_mux = MUX_PA28A_EIC_EXTINT8; /** Detect rising signal edges */ eint_chan_conf.detection_criteria = EXTINT_DETECT_RISING; eint_chan_conf.filter_input_signal = false; extint_chan_set_config(8, &eint_chan_conf); //configuration callback extint_register_callback(ppsISR,8,EXTINT_CALLBACK_TYPE_DETECT); //activation callback extint_chan_enable_callback(8,EXTINT_CALLBACK_TYPE_DETECT); pin_state=false; }
/** * \brief Configure the INTN interrupt. * * \param p_handler callback pointer to use when INTN interrupt raises. */ void configure_intn(void (*p_handler) (void)) { struct extint_chan_conf eic_conf; /* Configure the external interrupt channel. */ extint_chan_get_config_defaults(&eic_conf); eic_conf.gpio_pin = KSZ8851SNL_INTN_EIC_PIN; eic_conf.gpio_pin_mux = KSZ8851SNL_INTN_EIC_PIN_MUX; eic_conf.gpio_pin_pull = EXTINT_PULL_UP; eic_conf.detection_criteria = EXTINT_DETECT_FALLING; eic_conf.filter_input_signal = true; extint_chan_set_config(KSZ8851SNL_INTN_EIC_CHANNEL, &eic_conf); /* Register and enable the callback function. */ extint_register_callback(p_handler, KSZ8851SNL_INTN_EIC_CHANNEL, EXTINT_CALLBACK_TYPE_DETECT); extint_chan_enable_callback(KSZ8851SNL_INTN_EIC_CHANNEL, EXTINT_CALLBACK_TYPE_DETECT); }
static int button_sensor_configure(int type, int value) { struct extint_chan_conf config_extint_chan; extint_chan_get_config_defaults(&config_extint_chan); config_extint_chan.gpio_pin = BUTTON_0_EIC_PIN; config_extint_chan.gpio_pin_mux = BUTTON_0_EIC_MUX; config_extint_chan.gpio_pin_pull = EXTINT_PULL_UP; if(value == 1) { /* Enable the sensor */ config_extint_chan.detection_criteria = EXTINT_DETECT_FALLING; //config_extint_chan.detection_criteria = EXTINT_DETECT_BOTH; enabled = 1; } else { /* Disable the sensor */ config_extint_chan.detection_criteria = EXTINT_DETECT_NONE; enabled = 0; } extint_chan_set_config(BUTTON_0_EIC_LINE, &config_extint_chan); return 0; }
/** * \internal * \brief Test for external interrupt detection using callback. * * This test changes the logic level of PB05 from high to low * so that the external interrupt channel detects the edge * and calls the callback function. * * Detection is tested for both rising and falling edges. * * \param test Current test case. */ static void run_extint_callback_mode_test(const struct test_case *test) { uint16_t timeout_cycles; /* Testing the falling edge detection */ interrupt_flag = false; timeout_cycles = 100; port_pin_set_output_level(GPIO_TEST_PIN_EXTINT, false); do { timeout_cycles--; if (interrupt_flag) { break; } } while (timeout_cycles != 0); test_assert_true(test, timeout_cycles > 0, "Timeout in interrupt detection"); test_assert_true(test, interrupt_flag, "External interrupt falling edge detection failed"); /* Testing the rising edge detection */ eic_conf.detection_criteria = EXTINT_DETECT_RISING; extint_chan_set_config(EIC_TEST_CHANNEL, &eic_conf); interrupt_flag = false; timeout_cycles = 100; port_pin_set_output_level(GPIO_TEST_PIN_EXTINT, true); do { timeout_cycles--; if (interrupt_flag) { break; } } while (timeout_cycles != 0); test_assert_true(test, timeout_cycles > 0, "Timeout in interrupt detection"); test_assert_true(test, interrupt_flag, "External interrupt rising edge detection failed"); }
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) { MBED_ASSERT(obj); if (pin == NC) return -1; IRQn_Type irq_n = (IRQn_Type)0; uint32_t vector = 0; int int_channel = 0; irq_handler = handler; // assuming the usage of these apis in mbed layer only obj->pin = pin; extint_chan_get_config_defaults(&pEXT_CONF(obj)); pEXT_CONF(obj).gpio_pin = (uint32_t)pin; pEXT_CONF(obj).gpio_pin_mux = 0; // mux setting for ext int is 0 pEXT_CONF(obj).gpio_pin_pull = EXTINT_PULL_UP; pEXT_CONF(obj).detection_criteria = EXTINT_DETECT_NONE; int_channel = pinmap_find_peripheral(pin, PinMap_EXTINT); if (int_channel == NC) { return -1; } extint_chan_set_config(int_channel, &pEXT_CONF(obj)); ext_int_pins[int_channel] = pin; irq_n = EIC_IRQn; vector = (uint32_t)gpio_irq; NVIC_SetVector(irq_n, vector); NVIC_EnableIRQ(irq_n); obj->ch = int_channel; channel_ids[int_channel] = id; obj->irqmask = 0; return 0; }
/*---------------------------------------------------------------------------*/ static void configure_button(void) { /* Set buttons as inputs */ struct port_config pin_conf; port_get_config_defaults(&pin_conf); pin_conf.direction = PORT_PIN_DIR_INPUT; pin_conf.input_pull = PORT_PIN_PULL_UP; port_pin_set_config(BUTTON_0_PIN, &pin_conf); /* Configure interrupt */ struct extint_chan_conf config_extint_chan; extint_chan_get_config_defaults(&config_extint_chan); config_extint_chan.gpio_pin = BUTTON_0_EIC_PIN; config_extint_chan.gpio_pin_mux = BUTTON_0_EIC_MUX; config_extint_chan.gpio_pin_pull = EXTINT_PULL_UP; config_extint_chan.detection_criteria = EXTINT_DETECT_BOTH; extint_chan_set_config(BUTTON_0_EIC_LINE, &config_extint_chan); /* Register interrupt callbacks */ extint_register_callback(extint_detection_callback, BUTTON_0_EIC_LINE, EXTINT_CALLBACK_TYPE_DETECT); }
/** * \internal * \brief Test capture and compare * * This test uses TCC0 as a PWM generator (compare function). TCC1 will be set * to capture the signal from TCC0 to test the capture functionality. * * \param test Current test case. */ static void run_capture_and_compare_test(const struct test_case *test) { test_assert_true(test, tcc_init_success == true, "TCC initialization failed, skipping test"); test_assert_true(test, callback_function_entered == 1, "The callback test has failed, skipping test"); /* Configure TCC module for PWM generation */ tcc_reset(&tcc_test0_module); tcc_get_config_defaults(&tcc_test0_config, CONF_TEST_TCC0); tcc_test0_config.counter.period = 0x03FF; tcc_test0_config.compare.wave_generation = TCC_WAVE_GENERATION_SINGLE_SLOPE_PWM; tcc_test0_config.compare.match[TCC_MATCH_CAPTURE_CHANNEL_0] = 0x01FF; /* Calculate the theoretical PWM frequency & duty */ uint32_t frequency_output, duty_output; frequency_output = system_clock_source_get_hz(SYSTEM_CLOCK_SOURCE_OSC8M) / (0x03FF+1); /* This value is depend on the WaveGeneration Mode */ duty_output = (uint32_t)(tcc_test0_config.compare.match[TCC_MATCH_CAPTURE_CHANNEL_0] * 100) / tcc_test0_config.counter.period; tcc_test0_config.pins.enable_wave_out_pin[TCC_MATCH_CAPTURE_CHANNEL_0] = true; tcc_test0_config.pins.wave_out_pin[TCC_MATCH_CAPTURE_CHANNEL_0] = CONF_TEST_PIN_OUT; tcc_test0_config.pins.wave_out_pin_mux[TCC_MATCH_CAPTURE_CHANNEL_0] = CONF_TEST_PIN_MUX; tcc_init(&tcc_test0_module, CONF_TEST_TCC0, &tcc_test0_config); tcc_register_callback(&tcc_test0_module, tcc_callback_function, TCC_CALLBACK_CHANNEL_0); tcc_enable_callback(&tcc_test0_module, TCC_CALLBACK_CHANNEL_0); /* Configure TCC module for capture */ tcc_reset(&tcc_test1_module); tcc_get_config_defaults(&tcc_test1_config, CONF_TEST_TCC1); tcc_test1_config.counter.period = 0xFFFF; tcc_test1_config.counter.clock_prescaler = TCC_CLOCK_PRESCALER_DIV1; tcc_test1_config.capture.channel_function[CONF_CAPTURE_CHAN_0] = TCC_CHANNEL_FUNCTION_CAPTURE; tcc_test1_config.capture.channel_function[CONF_CAPTURE_CHAN_1] = TCC_CHANNEL_FUNCTION_CAPTURE; tcc_init(&tcc_test1_module, CONF_TEST_TCC1, &tcc_test1_config); struct tcc_events tcc_events = { .on_input_event_perform_action[1] = true, .input_config[1].modify_action = true, .input_config[1].action = TCC_EVENT_ACTION_PERIOD_PULSE_WIDTH_CAPTURE }; tcc_enable_events(&tcc_test1_module, &tcc_events); /* Configure external interrupt controller */ struct extint_chan_conf extint_chan_config; extint_chan_config.gpio_pin = CONF_EIC_PIN; extint_chan_config.gpio_pin_mux = CONF_EIC_MUX; extint_chan_config.gpio_pin_pull = EXTINT_PULL_UP; extint_chan_config.wake_if_sleeping = false; extint_chan_config.filter_input_signal = false; extint_chan_config.detection_criteria = EXTINT_DETECT_HIGH; extint_chan_set_config(CONF_EIC_CHAN, &extint_chan_config); /* Configure external interrupt module to be event generator */ struct extint_events extint_event_conf; extint_event_conf.generate_event_on_detect[CONF_EIC_CHAN] = true; extint_enable_events(&extint_event_conf); /* Configure event system */ struct events_resource event_res; /* Configure channel */ struct events_config config; events_get_config_defaults(&config); config.generator = CONF_EVENT_GENERATOR_ID; config.edge_detect = EVENTS_EDGE_DETECT_NONE; config.path = EVENTS_PATH_ASYNCHRONOUS; events_allocate(&event_res, &config); /* Configure user */ events_attach_user(&event_res, CONF_EVENT_USED_ID); /* Enable TCC modules */ tcc_enable(&tcc_test1_module); tcc_enable(&tcc_test0_module); uint16_t period_after_capture = 0; uint16_t pulse_width_after_capture = 0; uint32_t capture_frequency = 0; uint32_t capture_duty = 0; while (callback_function_entered < 4) { period_after_capture = tcc_get_capture_value(&tcc_test1_module, TCC_MATCH_CAPTURE_CHANNEL_0); pulse_width_after_capture = tcc_get_capture_value(&tcc_test1_module, TCC_MATCH_CAPTURE_CHANNEL_1); } if(period_after_capture != 0) { capture_frequency = system_clock_source_get_hz(SYSTEM_CLOCK_SOURCE_OSC8M) / period_after_capture; capture_duty = (uint32_t)(pulse_width_after_capture) * 100 / period_after_capture; } test_assert_true(test, (capture_frequency <= (frequency_output * (100 + CONF_TEST_TOLERANCE) / 100)) && \ (capture_frequency >= (frequency_output * (100 - CONF_TEST_TOLERANCE) / 100)) && \ (capture_duty <= (duty_output * (100 + CONF_TEST_TOLERANCE) / 100)) && \ (capture_duty >= (duty_output * (100 - CONF_TEST_TOLERANCE) / 100)) \ ,"The result of Capture is wrong, captured frequency: %ldHz, captured duty: %ld%%", capture_frequency, capture_duty ); } /** * \internal * \brief Test Recoverable Fault (FAULTn) * * This test uses TCC0 as a PWM generator (compare function). * EXTINT will be used to route fault input to TCC0. * * \param test Current test case. */ static void run_faultn_test(const struct test_case *test) { test_assert_true(test, tcc_init_success == true, "TCC initialization failed, skipping test"); /* Configure TCC module for PWM generation with fault */ tcc_reset(&tcc_test0_module); tcc_get_config_defaults(&tcc_test0_config, CONF_TEST_TCC0); tcc_test0_config.counter.period = 0x03FF; tcc_test0_config.compare.wave_generation = TCC_WAVE_GENERATION_SINGLE_SLOPE_PWM; tcc_test0_config.compare.match[TCC_MATCH_CAPTURE_CHANNEL_0] = 0x01FF; tcc_test0_config.wave_ext.recoverable_fault[TCC_MATCH_CAPTURE_CHANNEL_0].source = TCC_FAULT_SOURCE_ENABLE; tcc_test0_config.wave_ext.recoverable_fault[TCC_MATCH_CAPTURE_CHANNEL_0].halt_action = TCC_FAULT_HALT_ACTION_SW_HALT; tcc_init(&tcc_test0_module, CONF_TEST_TCC0, &tcc_test0_config); /* Configure TCC events for recoverable fault input */ struct tcc_events tcc_test_events; memset(&tcc_test_events, 0, sizeof(struct tcc_events)); tcc_test_events.on_event_perform_channel_action[TCC_MATCH_CAPTURE_CHANNEL_0] = true; tcc_enable_events(&tcc_test0_module, &tcc_test_events); tcc_enable(&tcc_test0_module); /* Configure IO pin to generate fault */ struct port_config config_pin; port_get_config_defaults(&config_pin); config_pin.direction = PORT_PIN_DIR_OUTPUT; port_pin_set_config(CONF_TEST_PIN_OUT, &config_pin); port_pin_set_output_level(CONF_TEST_PIN_OUT, true); /* Configure EIC to capture fault input */ struct extint_chan_conf config; extint_chan_get_config_defaults(&config); config.filter_input_signal = true; config.detection_criteria = EXTINT_DETECT_BOTH; config.gpio_pin = CONF_EIC_PIN; config.gpio_pin_mux = CONF_EIC_MUX; extint_chan_set_config(CONF_EIC_CHAN, &config); struct extint_events extint_test_events; memset(&extint_test_events, 0, sizeof(struct extint_events)); extint_test_events.generate_event_on_detect[CONF_EIC_CHAN] = true; extint_enable_events(&extint_test_events); /* Configure EVENTs to route fault input */ struct events_resource event_resource; struct events_config event_config; events_get_config_defaults(&event_config); event_config.generator = CONF_EVENT_GENERATOR_ID; event_config.path = EVENTS_PATH_ASYNCHRONOUS; events_allocate(&event_resource, &event_config); events_attach_user(&event_resource, CONF_EVENT_USER_ID_FAULTn); /* Clear halt status */ tcc_clear_status(&tcc_test0_module, TCC_STATUS_RECOVERABLE_FAULT_PRESENT(0) | TCC_STATUS_RECOVERABLE_FAULT_OCCUR(0)); uint32_t test_val1 = tcc_get_count_value(&tcc_test0_module); uint32_t test_val2 = tcc_get_count_value(&tcc_test0_module); /* Check TCC is running */ test_assert_true(test, test_val1 != test_val2, "The counter failed to stop on recoverable fault"); /* Set fault */ port_pin_set_output_level(CONF_TEST_PIN_OUT, false); /* Check fault state */ test_assert_true(test, TCC_STATUS_RECOVERABLE_FAULT_OCCUR(0) & tcc_get_status(&tcc_test0_module), "The counter failed to detect recoverable fault"); /* Check TCC is running */ test_val1 = tcc_get_count_value(&tcc_test0_module); test_val2 = tcc_get_count_value(&tcc_test0_module); test_assert_true(test, test_val1 == test_val2, "The counter failed to stop on recoverable fault"); }
/** * \internal * \brief Test Non-Recoverable Fault (FAULTx) * * This test uses TCC0 as a PWM generator (compare function). * EXTINT will be used to route fault input to TCC0. * * \param test Current test case. */ static void run_faultx_test(const struct test_case *test) { test_assert_true(test, tcc_init_success == true, "TCC initialization failed, skipping test"); /* Configure TCC module for PWM generation with fault */ tcc_reset(&tcc_test0_module); tcc_get_config_defaults(&tcc_test0_config, CONF_TEST_TCC0); tcc_test0_config.counter.period = 0x03FF; tcc_test0_config.compare.wave_generation = TCC_WAVE_GENERATION_SINGLE_SLOPE_PWM; tcc_test0_config.compare.match[TCC_MATCH_CAPTURE_CHANNEL_0] = 0x01FF; tcc_test0_config.wave_ext.non_recoverable_fault[TCC_WAVE_OUTPUT_0].output = TCC_FAULT_STATE_OUTPUT_1; tcc_init(&tcc_test0_module, CONF_TEST_TCC0, &tcc_test0_config); /* Configure TCC events for non-recoverable fault input */ struct tcc_events tcc_test_events; memset(&tcc_test_events, 0, sizeof(struct tcc_events)); tcc_test_events.on_input_event_perform_action[0] = true; tcc_test_events.input_config[0].modify_action = true; tcc_test_events.input_config[0].action = TCC_EVENT_ACTION_NON_RECOVERABLE_FAULT; tcc_enable_events(&tcc_test0_module, &tcc_test_events); tcc_enable(&tcc_test0_module); /* Configure IO pin to generate fault */ struct port_config config_pin; port_get_config_defaults(&config_pin); config_pin.direction = PORT_PIN_DIR_OUTPUT; port_pin_set_config(CONF_TEST_PIN_OUT, &config_pin); port_pin_set_output_level(CONF_TEST_PIN_OUT, true); /* Configure EIC to capture fault input */ struct extint_chan_conf config; extint_chan_get_config_defaults(&config); config.filter_input_signal = true; config.detection_criteria = EXTINT_DETECT_BOTH; config.gpio_pin = CONF_EIC_PIN; config.gpio_pin_mux = CONF_EIC_MUX; extint_chan_set_config(CONF_EIC_CHAN, &config); struct extint_events extint_test_events; memset(&extint_test_events, 0, sizeof(struct extint_events)); extint_test_events.generate_event_on_detect[CONF_EIC_CHAN] = true; extint_enable_events(&extint_test_events); /* Configure EVENTs to route fault input */ struct events_resource event_resource; struct events_config event_config; events_get_config_defaults(&event_config); event_config.generator = CONF_EVENT_GENERATOR_ID; event_config.path = EVENTS_PATH_ASYNCHRONOUS; events_allocate(&event_resource, &event_config); events_attach_user(&event_resource, CONF_EVENT_USER_ID_FAULTx); /* Clear halt status */ tcc_clear_status(&tcc_test0_module, TCC_STATUS_NON_RECOVERABLE_FAULT_PRESENT(0) | TCC_STATUS_NON_RECOVERABLE_FAULT_OCCUR(0)); uint32_t test_val1 = tcc_get_count_value(&tcc_test0_module); uint32_t test_val2 = tcc_get_count_value(&tcc_test0_module); /* Check TCC is running */ test_assert_true(test, test_val1 != test_val2, "The counter failed to stop on non-recoverable fault"); /* Set fault */ port_pin_set_output_level(CONF_TEST_PIN_OUT, false); /* Check fault state */ test_assert_true(test, TCC_STATUS_NON_RECOVERABLE_FAULT_OCCUR(0) & tcc_get_status(&tcc_test0_module), "The counter failed to detect non-recoverable fault"); /* Check TCC is running */ test_val1 = tcc_get_count_value(&tcc_test0_module); test_val2 = tcc_get_count_value(&tcc_test0_module); test_assert_true(test, test_val1 == test_val2, "The counter failed to stop on non-recoverable fault"); }
/** * \internal * \brief Test capture and compare * * This test uses TC module 0 as a PWM generator (compare function). * TC module 1 will be set to capture the signal from TC module 0 to test the capture * functionality. * * \param test Current test case. */ static void run_16bit_capture_and_compare_test(const struct test_case *test) { test_assert_true(test, tc_init_success == true, "TC initialization failed, skipping test"); test_assert_true(test, callback_function_entered == 1, "The callback test has failed, skipping test"); /* Configure 16-bit TC module for PWM generation */ tc_reset(&tc_test0_module); tc_get_config_defaults(&tc_test0_config); tc_test0_config.wave_generation = TC_WAVE_GENERATION_MATCH_PWM; tc_test0_config.counter_16_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_0] = 0x03FF; tc_test0_config.counter_16_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_1] = 0x01FF; /* Calculate the theoretical PWM frequency & duty */ uint32_t frequency_output, duty_output; frequency_output = system_clock_source_get_hz(SYSTEM_CLOCK_SOURCE_OSC8M)/ (0x03FF+1); /* This value is depend on the WaveGeneration Mode */ duty_output = (uint32_t)(tc_test0_config.counter_16_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_1]) * 100 \ / tc_test0_config.counter_16_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_0]; tc_test0_config.pwm_channel[TC_COMPARE_CAPTURE_CHANNEL_1].enabled = true; tc_test0_config.pwm_channel[TC_COMPARE_CAPTURE_CHANNEL_1].pin_out = CONF_TEST_PIN_OUT; tc_test0_config.pwm_channel[TC_COMPARE_CAPTURE_CHANNEL_1].pin_mux = CONF_TEST_PIN_MUX; tc_init(&tc_test0_module, CONF_TEST_TC0, &tc_test0_config); tc_register_callback(&tc_test0_module, tc_callback_function, TC_CALLBACK_CC_CHANNEL0); tc_enable_callback(&tc_test0_module, TC_CALLBACK_CC_CHANNEL0); /* Configure 16-bit TC module for capture */ tc_reset(&tc_test1_module); tc_get_config_defaults(&tc_test1_config); tc_test1_config.clock_prescaler = TC_CLOCK_PRESCALER_DIV1; tc_test1_config.enable_capture_on_channel[CONF_CAPTURE_CHAN_0] = true; tc_test1_config.enable_capture_on_channel[CONF_CAPTURE_CHAN_1] = true; tc_init(&tc_test1_module, CONF_TEST_TC1, &tc_test1_config); struct tc_events tc_events = { .on_event_perform_action = true, .event_action = TC_EVENT_ACTION_PPW,}; tc_enable_events(&tc_test1_module, &tc_events); /* Configure external interrupt controller */ struct extint_chan_conf extint_chan_config; extint_chan_config.gpio_pin = CONF_EIC_PIN; extint_chan_config.gpio_pin_mux = CONF_EIC_MUX; extint_chan_config.gpio_pin_pull = EXTINT_PULL_UP; extint_chan_config.wake_if_sleeping = false; extint_chan_config.filter_input_signal = false; extint_chan_config.detection_criteria = EXTINT_DETECT_HIGH; extint_chan_set_config(0, &extint_chan_config); /* Configure external interrupt module to be event generator */ struct extint_events extint_event_conf; extint_event_conf.generate_event_on_detect[0] = true; extint_enable_events(&extint_event_conf); /* Configure event system */ struct events_resource event_res; /* Configure channel */ struct events_config config; events_get_config_defaults(&config); config.generator = CONF_EVENT_GENERATOR_ID; config.edge_detect = EVENTS_EDGE_DETECT_NONE; config.path = EVENTS_PATH_ASYNCHRONOUS; events_allocate(&event_res, &config); /* Configure user */ events_attach_user(&event_res, CONF_EVENT_USED_ID); /* Enable TC modules */ tc_enable(&tc_test1_module); tc_enable(&tc_test0_module); uint16_t period_after_capture = 0; uint16_t pulse_width_after_capture = 0; uint32_t capture_frequency = 0; uint32_t capture_duty = 0; while (callback_function_entered < 4) { period_after_capture = tc_get_capture_value(&tc_test1_module, TC_COMPARE_CAPTURE_CHANNEL_0); pulse_width_after_capture = tc_get_capture_value(&tc_test1_module, TC_COMPARE_CAPTURE_CHANNEL_1); } if(period_after_capture != 0) { capture_frequency = system_clock_source_get_hz(SYSTEM_CLOCK_SOURCE_OSC8M)/ period_after_capture; capture_duty = (uint32_t)(pulse_width_after_capture) * 100 / period_after_capture; } test_assert_true(test, (capture_frequency <= (frequency_output * (100 + CONF_TEST_TOLERANCE) / 100)) && \ (capture_frequency >= (frequency_output * (100 - CONF_TEST_TOLERANCE) / 100)) && \ (capture_duty <= (duty_output * (100 + CONF_TEST_TOLERANCE) / 100)) && \ (capture_duty >= (duty_output * (100 - CONF_TEST_TOLERANCE) / 100)) \ ,"The result of Capture is wrong, captured frequency: %ldHz, captured duty: %ld%%", capture_frequency, capture_duty ); } /** * \brief Initialize the USART for unit test * * Initializes the SERCOM USART used for sending the unit test status to the * computer via the EDBG CDC gateway. */ static void cdc_uart_init(void) { struct usart_config usart_conf; /* Configure USART for unit test output */ usart_get_config_defaults(&usart_conf); usart_conf.mux_setting = CONF_STDIO_MUX_SETTING; usart_conf.pinmux_pad0 = CONF_STDIO_PINMUX_PAD0; usart_conf.pinmux_pad1 = CONF_STDIO_PINMUX_PAD1; usart_conf.pinmux_pad2 = CONF_STDIO_PINMUX_PAD2; usart_conf.pinmux_pad3 = CONF_STDIO_PINMUX_PAD3; usart_conf.baudrate = CONF_STDIO_BAUDRATE; stdio_serial_init(&cdc_uart_module, CONF_STDIO_USART, &usart_conf); usart_enable(&cdc_uart_module); } /** * \brief Run TC unit tests * * Initializes the system and serial output, then sets up the TC unit test * suite and runs it. */ int main(void) { system_init(); cdc_uart_init(); /* Define Test Cases */ DEFINE_TEST_CASE(init_test, NULL, run_init_test, NULL, "Initialize tc_xmodules"); DEFINE_TEST_CASE(basic_functionality_test, NULL, run_basic_functionality_test, NULL, "test start stop and getters and setters"); DEFINE_TEST_CASE(callback_test, NULL, run_callback_test, NULL, "test callback API"); DEFINE_TEST_CASE(reset_32bit_master_test, NULL, run_reset_32bit_master_test, NULL, "Setup, reset and reinitialize TC modules of a 32-bit TC"); DEFINE_TEST_CASE(capture_and_compare_test, NULL, run_16bit_capture_and_compare_test, NULL, "Test capture and compare"); /* Put test case addresses in an array */ DEFINE_TEST_ARRAY(tc_tests) = { &init_test, &basic_functionality_test, &callback_test, &reset_32bit_master_test, &capture_and_compare_test, }; /* Define the test suite */ DEFINE_TEST_SUITE(tc_suite, tc_tests, "SAM TC driver test suite"); /* Run all tests in the suite*/ test_suite_run(&tc_suite); tc_reset(&tc_test0_module); tc_reset(&tc_test1_module); while (true) { /* Intentionally left empty */ } }
/** * \internal * \brief Cleanup function for polled mode test. * * This function disables the external interrupt channel. * * \param test Current test case. */ static void cleanup_extint_polled_mode_test(const struct test_case *test) { eic_conf.detection_criteria = EXTINT_DETECT_NONE; extint_chan_set_config(EIC_TEST_CHANNEL, &eic_conf); }