enum status_code events_add_hook(struct events_resource *resource, struct events_hook *hook) { struct events_hook *tmp_hook = NULL; /* Associate the hook with the resource */ hook->resource = resource; /* Check if this is the first hook in the list */ if (_events_inst.hook_list == NULL) { _events_inst.hook_list = hook; } else { tmp_hook = _events_inst.hook_list; /* Find the first free place in the list */ while (tmp_hook->next != NULL) { tmp_hook = tmp_hook->next; } /* Put the hook into the next free place in the list */ tmp_hook->next = hook; } /* Check if interrupts from the EVSYS module is enabled in the interrupt controller */ if (!system_interrupt_is_enabled(SYSTEM_INTERRUPT_MODULE_EVSYS)) { system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_EVSYS); } return STATUS_OK; }
int main(void) { system_init(); //! [main_1] //! [critical_section_start] system_interrupt_enter_critical_section(); //! [critical_section_start] //! [do_critical_code] if (is_ready == true) { /* Do something in response to the global shared flag */ is_ready = false; } //! [do_critical_code] //! [critical_section_end] system_interrupt_leave_critical_section(); //! [critical_section_end] //! [main_1] //! [main_2] //! [module_int_enable] system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_RTC); //! [module_int_enable] //! [global_int_enable] system_interrupt_enable_global(); //! [global_int_enable] //! [main_2] while (true) { /* Infinite loop */ } }
/** * \brief Initializes a hardware I2S module instance * * Enables the clock and initialize the I2S module. * * \param[in,out] module_inst Pointer to the software module instance struct * \param[in] hw Pointer to the TCC hardware module * * \return Status of the initialization procedure. * * \retval STATUS_OK The module was initialized successfully * \retval STATUS_BUSY Hardware module was busy when the * initialization procedure was attempted * \retval STATUS_ERR_DENIED Hardware module was already enabled */ enum status_code i2s_init( struct i2s_module *const module_inst, I2s *hw) { Assert(module_inst); Assert(hw); /* Enable the user interface clock in the PM */ system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_I2S); /* Status check */ uint32_t ctrla; ctrla = module_inst->hw->CTRLA.reg; if (ctrla & I2S_CTRLA_ENABLE) { if (ctrla & (I2S_CTRLA_SEREN1 | I2S_CTRLA_SEREN0 | I2S_CTRLA_CKEN1 | I2S_CTRLA_CKEN0)) { return STATUS_BUSY; } else { return STATUS_ERR_DENIED; } } /* Initialize module */ module_inst->hw = hw; /* Initialize serializers */ #if I2S_CALLBACK_MODE == true int i, j; for (i = 0; i < 2; i ++) { for (j = 0; j < I2S_SERIALIZER_CALLBACK_N; j ++) { module_inst->serializer[i].callback[j] = NULL; } module_inst->serializer[i].registered_callback_mask = 0; module_inst->serializer[i].enabled_callback_mask = 0; module_inst->serializer[i].job_buffer = NULL; module_inst->serializer[i].job_status = STATUS_OK; module_inst->serializer[i].requested_words = 0; module_inst->serializer[i].transferred_words = 0; module_inst->serializer[i].mode = I2S_SERIALIZER_RECEIVE; module_inst->serializer[i].data_size = I2S_DATA_SIZE_32BIT; } _i2s_instances[0] = module_inst; system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_I2S); #endif return STATUS_OK; }
void _system_extint_init(void) { Eic *const eics[EIC_INST_NUM] = EIC_INSTS; /* Turn on the digital interface clock */ system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBA, MCLK_APBAMASK_EIC); #if (EXTINT_CLOCK_SELECTION == EXTINT_CLK_GCLK) /* Configure the generic clock for the module and enable it */ struct system_gclk_chan_config gclk_chan_conf; system_gclk_chan_get_config_defaults(&gclk_chan_conf); gclk_chan_conf.source_generator = EXTINT_CLOCK_SOURCE; system_gclk_chan_set_config(EIC_GCLK_ID, &gclk_chan_conf); /* Enable the clock anyway, since when needed it will be requested * by External Interrupt driver */ system_gclk_chan_enable(EIC_GCLK_ID); #endif /* Reset all EIC hardware modules. */ for (uint32_t i = 0; i < EIC_INST_NUM; i++) { eics[i]->CTRLA.reg |= EIC_CTRLA_SWRST; } while (extint_is_syncing()) { /* Wait for all hardware modules to complete synchronization */ } #if (EXTINT_CLOCK_SELECTION == EXTINT_CLK_GCLK) for (uint32_t i = 0; i < EIC_INST_NUM; i++) { eics[i]->CTRLA.bit.CKSEL = EXTINT_CLK_GCLK; } #else for (uint32_t i = 0; i < EIC_INST_NUM; i++) { eics[i]->CTRLA.bit.CKSEL = EXTINT_CLK_ULP32K; } #endif /* Reset the software module */ #if EXTINT_CALLBACK_MODE == true /* Clear callback registration table */ for (uint8_t j = 0; j < EIC_NUMBER_OF_INTERRUPTS; j++) { _extint_dev.callbacks[j] = NULL; } system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_EIC); #endif /* Enables the driver for further use */ _extint_enable(); }
/** * \brief Enable the SERCOM SPI module * * This function must be called after \ref spi_master_vec_init() before a * transfer can be started. * * \param[in,out] module Driver instance to operate on. */ void spi_master_vec_enable(const struct spi_master_vec_module *const module) { Assert(module); Assert(module->sercom); SercomSpi *const spi_hw = &(module->sercom->SPI); spi_hw->INTENCLR.reg = SERCOM_SPI_INTFLAG_DRE | SERCOM_SPI_INTFLAG_RXC | SERCOM_SPI_INTFLAG_TXC; _spi_master_vec_wait_for_sync(spi_hw); spi_hw->CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE; system_interrupt_enable(_sercom_get_interrupt_vector(module->sercom)); }
/** * \brief Disables callback * * Disables the callback function registered by the \ref * tcc_register_callback, and the callback will not be called from the * interrupt routine. The function will also disable the appropriate * interrupts. * * \param[in] module Pointer to TCC software instance struct * \param[in] callback_type Callback type given by an enum */ void tcc_disable_callback( struct tcc_module *const module, const enum tcc_callback callback_type) { /* Sanity check arguments */ Assert(module); Assert(module->hw); /* Disable interrupts for this TCC module */ system_interrupt_enable(_tcc_interrupt_get_interrupt_vector( _tcc_get_inst_index(module->hw))); /* Disable channel or other callbacks */ module->enable_callback_mask &= ~_tcc_intflag[callback_type]; module->hw->INTENCLR.reg = _tcc_intflag[callback_type]; }
/** * \brief Enables asynchronous callback generation for a given type. * * Enables asynchronous callbacks for a given callback type. This must be * called before an external interrupt channel will generate callback events. * * \param[in] type Type of callback function to enable * * \return Status of the callback enable operation. * \retval STATUS_OK The callback was enabled successfully * \retval STATUS_ERR_INVALID_ARG If an invalid callback type was supplied */ enum status_code wdt_enable_callback( const enum wdt_callback type) { Wdt *const WDT_module = WDT; switch (type) { case WDT_CALLBACK_EARLY_WARNING: WDT_module->INTENSET.reg = WDT_INTENSET_EW; system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_WDT); return STATUS_OK; default: Assert(false); return STATUS_ERR_INVALID_ARG; } }
/** * \brief Convert a specific number digital data to analog through DAC. * * This function will perform a conversion of specific number of digital data. * The conversion should be event-triggered, the data will be written to DATABUF * and transferred to the DATA register and converted when a Start Conversion * Event is issued. * Conversion data must be right or left adjusted according to configuration * settings. * \note To be event triggered, the enable_start_on_event must be * enabled in the configuration. * * \param[in] module_inst Pointer to the DAC software device struct * \param[in] channel DAC channel to write to * \param[in] buffer Pointer to the digital data write buffer to be converted * \param[in] length Size of the write buffer * * \return Status of the operation. * \retval STATUS_OK If the data was written * \retval STATUS_ERR_UNSUPPORTED_DEV If a callback that requires event driven * mode was specified with a DAC instance * configured in non-event mode * \retval STATUS_BUSY The DAC is busy to accept new job */ enum status_code dac_chan_write_buffer_job( struct dac_module *const module_inst, const enum dac_channel channel, uint16_t *buffer, uint32_t length) { /* Sanity check arguments */ Assert(module_inst); Assert(module_inst->hw); Assert(buffer); UNUSED(channel); Dac *const dac_module = module_inst->hw; /* DAC interrupts require it to be driven by events to work, fail if in * unbuffered (polled) mode */ if (module_inst->start_on_event == false) { return STATUS_ERR_UNSUPPORTED_DEV; } if(module_inst->remaining_conversions != 0 || module_inst->job_status == STATUS_BUSY){ return STATUS_BUSY; } /* Wait until the synchronization is complete */ while (dac_is_syncing(module_inst)) { }; module_inst->job_status = STATUS_BUSY; module_inst->remaining_conversions = length; module_inst->job_buffer = buffer; module_inst->transferred_conversions = 0; /* Enable interrupt */ system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_DAC); dac_module->INTFLAG.reg = DAC_INTFLAG_UNDERRUN | DAC_INTFLAG_EMPTY; dac_module->INTENSET.reg = DAC_INTENSET_UNDERRUN | DAC_INTENSET_EMPTY; return STATUS_OK; }
/** * \brief Enables the RTC module. * * Enables the RTC module once it has been configured, ready for use. Most * module configuration parameters cannot be altered while the module is enabled. * * \param[in,out] module RTC hardware module */ void rtc_count_enable(struct rtc_module *const module) { /* Sanity check arguments */ Assert(module); Assert(module->hw); Rtc *const rtc_module = module->hw; #if RTC_COUNT_ASYNC == true system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_RTC); #endif while (rtc_count_is_syncing(module)) { /* Wait for synchronization */ } /* Enable RTC module. */ rtc_module->MODE0.CTRL.reg |= RTC_MODE0_CTRL_ENABLE; }
/** * \brief Registers a callback * * Registers a callback function which is implemented by the user. * * \note The callback must be enabled by \ref trng_enable_callback, * in order for the interrupt handler to call it when the conditions for the * callback type is met. * * \param[in] module Pointer to TC software instance struct * \param[in] callback_func Pointer to callback function * \param[in] callback_type Callback type given by an enum * * \retval STATUS_OK The function exited successfully */ enum status_code trng_register_callback( struct trng_module *const module, trng_callback_t callback_func, const enum trng_callback callback_type) { /* Sanity check arguments */ Assert(module); Assert(callback_func); /* Register callback function */ module->callback[callback_type] = callback_func; /* Set the bit corresponding to the callback_type */ module->register_callback_mask |= (1 << callback_type); /* Enable interrupt for this TRNG module */ system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_TRNG); return STATUS_OK; }
/** * \brief Enable the SERCOM SPI module * * This function must be called after \ref spi_master_vec_init() before a * transfer can be started. * * \param[in,out] module Driver instance to operate on. */ void spi_master_vec_enable(const struct spi_master_vec_module *const module) { Assert(module); Assert(module->sercom); SercomSpi *const spi_hw = &(module->sercom->SPI); spi_hw->INTENCLR.reg = SERCOM_SPI_INTFLAG_DRE | SERCOM_SPI_INTFLAG_RXC | SERCOM_SPI_INTFLAG_TXC; # ifdef FEATURE_SPI_SYNC_SCHEME_VERSION_2 while (spi_hw->STATUS.reg) { /* Intentionally left empty */ } # else while (spi_hw->STATUS.reg & SERCOM_SPI_STATUS_SYNCBUSY) { /* Intentionally left empty */ } # endif spi_hw->CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE; system_interrupt_enable(_sercom_get_interrupt_vector(module->sercom)); }