/** * @file sdrv_sent.c * @brief SemiDrive Sent driver source. * * @copyright Copyright (c) 2020 Semidrive Semiconductor. * All rights reserved. */ #include #include #include #include #include #include "sdrv_sent.h" #include "debug.h" #include "irq.h" #include "sdrv_etimer_lld.h" /* Global buffer for frame information. */ static sent_chan_frame_t g_frame_info[SDRV_SENT_CHAN_NUM]; /**************************Static Functions Start******************************/ /** * brief Sdrv sent channel id map to etimer channel id. * * param [in] sent_chan_id Sent channel id * param [out] etimer_cnt_id Sdrv etimer channel id */ static void sdrv_chanid_map(sdrv_sent_chanid_e sent_chan_id, sdrv_etimer_cnt_id_e *etimer_cnt_id); /** * brief Sdrv sent module initialize. * * param [in] ctrl Sdrv sent controller entity */ static void sdrv_sent_module_init(sdrv_sent_t *ctrl); /** * brief Sdrv sent module deinitialize. * * param [in] ctrl Sdrv sent controller entity */ static void sdrv_sent_module_deinit(sdrv_sent_t *ctrl); /** * brief Sdrv sent channel initialize. * * param [in] ctrl Sdrv sent controller entity * param [in] sent_chan_id Sent channel id */ static void sdrv_sent_channel_init(sdrv_sent_t *ctrl, sdrv_sent_chanid_e sent_chan_id); /** * brief Sdrv sent channel deinitialize. * * param [in] ctrl Sdrv sent controller entity * param [in] sent_chan_id Sent channel id */ static void sdrv_sent_channel_deinit(sdrv_sent_t *ctrl, sdrv_sent_chanid_e sent_chan_id); /** * brief Parse data to tick. * * param [in] data data in dma fifo. * param [in] actual_scaler sent channel actual scaler. * return The count of tick. */ static uint32_t sdrv_tick_parse(uint32_t data, uint32_t actual_scaler); /** * brief Check the configurations of sent. * * param [in] cfg Sdrv sent configurations. * return The configurations are valid or not. * - true : The configurations of sent are valid. * - false : The configurations of sent are unvalid. */ static bool sdrv_sent_config_check(sdrv_sent_config_t *cfg); /**************************Static Functions End********************************/ /** * @brief Sdrv sent controller initialization. * * This fuction initializes sent(etimer) module and channel and controller * entity status. * * @param [in] ctrl Sdrv sent controller. * @param [in] cfg Sdrv sent configurations. * @return The result of initializing sent. * - SDRV_STATUS_INVALID_PARAM : The input parameter contains a null * pointer. * - SDRV_STATUS_OK : Sent is initialized success. */ status_t sdrv_sent_init(sdrv_sent_t *ctrl, sdrv_sent_config_t *cfg) { /* Parameters are valid or not. */ if ((NULL == ctrl) || (!sdrv_sent_config_check(cfg))) { return SDRV_STATUS_INVALID_PARAM; } /* Sent module config and clock initialize. */ (void)memset(ctrl, 0, sizeof(sdrv_sent_t)); ctrl->base = cfg->base; ctrl->irq = cfg->irq; ctrl->chan_num = SDRV_SENT_CHAN_NUM; ctrl->clk_sel = cfg->clk_sel; ctrl->clk_freq = cfg->clk_freq; ctrl->clk_div = cfg->clk_div; /* Initialize sent(etimer) module . */ sdrv_sent_module_init(ctrl); ctrl->sent_sta = SENT_STATUS_INITED; /* Sent channel config and initialize. */ for (uint8_t i = 0; i < cfg->chan_cfg_num; ++i) { sdrv_sent_chanid_e chan_id = cfg->chan_cfg[i].chan_id; if (chan_id < SDRV_SENT_CHAN_NUM) { sdrv_sent_chan_t *sdrv_sent_chan = &ctrl->chan[chan_id]; sent_chan_frame_t *sent_chan_frame = &ctrl->chan[chan_id].frame_info; sdrv_sent_chan->chan_id = chan_id; sdrv_sent_chan->tickfreq = cfg->chan_cfg[i].tickfreq; sdrv_sent_chan->fifowml = cfg->chan_cfg[i].fifowml; sdrv_sent_chan->lowpulse_width = cfg->chan_cfg[i].lowpulse_width; sdrv_sent_chan->pause_pulse = cfg->chan_cfg[i].pause_pulse; sent_chan_frame->frame_format = cfg->chan_cfg[i].fast_chan; /* Set channel data information */ if (sent_chan_frame->frame_format == SENT_STANDARD_FORMAT) { sent_chan_frame->frame_dl = cfg->chan_cfg[i].data_bitnum; } else if (sent_chan_frame->frame_format == SENT_SINGLE_SECURE_FORMAT) { sent_chan_frame->frame_dl = SENT_SECURE_SENSOR_DATA_NIBBLE; } else if (sent_chan_frame->frame_format == SENT_HIGH_SPEED_FORMAT) { /* High speed format has 4 data nibbles, one data nibble has 3 * bit. */ sent_chan_frame->frame_dl = SENT_HIGH_SPEED_DATA_NIBBLE; } /* Calculate the expect scaler value */ if (0U != sdrv_sent_chan->tickfreq) { sdrv_sent_chan->expect_scaler = (ctrl->clk_freq / (ctrl->clk_div + 1)) / (sdrv_sent_chan->tickfreq); } /* Initialize sent channel. */ sdrv_sent_channel_init(ctrl, chan_id); sdrv_sent_chan->chan_sta = CHAN_STATUS_INITED; } } /* Enable sent and attach irq handler */ if (ctrl->irq > 0U) { irq_attach(ctrl->irq, sdrv_sent_irq_handle, ctrl); irq_enable(ctrl->irq); } return SDRV_STATUS_OK; } /** * @brief Sdrv sent controller deinitialization. * * This fuction deinitializes sent module. * * @param [in] ctrl Sdrv sent controller. * @return The result of deinitializing sent. * - SDRV_STATUS_INVALID_PARAM : The input parameter contains a null pointer. * - SDRV_STATUS_OK : Sent is deinitialized success. */ status_t sdrv_sent_deinit(sdrv_sent_t *ctrl) { /* Parameters are valid or not. */ if (NULL == ctrl) { return SDRV_STATUS_INVALID_PARAM; } /* Deinitialize sent module. */ if (SENT_STATUS_INITED == ctrl->sent_sta) { ctrl->sent_sta = SENT_STATUS_UNINIT; /* Disable sent irq handler */ if (ctrl->irq > 0U) { irq_disable(ctrl->irq); irq_detach(ctrl->irq); } sdrv_sent_module_deinit(ctrl); /* Deinitialize the sent channels. */ for (sdrv_sent_chanid_e chan_id = SDRV_SENT_HW_CPT_A; chan_id < ctrl->chan_num; ++chan_id) { if (CHAN_STATUS_UNINIT != ctrl->chan[chan_id].chan_sta) { ctrl->chan[chan_id].chan_sta = CHAN_STATUS_UNINIT; /* restore predivider */ ctrl->chan[chan_id].expect_scaler = 0U; ctrl->chan[chan_id].actual_scaler = 0U; ctrl->chan[chan_id].frame_info.frame_dl = 0U; sdrv_sent_channel_deinit(ctrl, chan_id); } } } return SDRV_STATUS_OK; } /** * @brief Sent set callback function * * @param[in] ctrl Sdrv sent controller. * @param[in] sent_chan_id Sent channel id * @param[in] callback Callback function * @param[in] userdata Callback user param * @return The result of initializing sent. * - SDRV_STATUS_INVALID_PARAM : The input parameter contains a null pointer. * - SDRV_STATUS_OK : Set callback function success. */ status_t sdrv_sent_set_callback(sdrv_sent_t *ctrl, sdrv_sent_chanid_e sent_chan_id, sdrv_sent_recv_cb_t callback, void *userdata) { /* Parameters are valid or not. */ if ((NULL == ctrl) || (sent_chan_id > SDRV_SENT_HW_CPT_D)) { return SDRV_STATUS_INVALID_PARAM; } ctrl->chan[sent_chan_id].frameover_cb = callback; ctrl->chan[sent_chan_id].userdata = userdata; return SDRV_STATUS_OK; } /** * @brief Sent starts to receive frames. * * Sent channel will receive frames after calling this function. * User could stop the sent channel by calling sdrv_sent_recv_stop(). * * @param[in] ctrl Sent controller * @param[in] sent_chan_id Sent channel id * @return The result of initializing sent. * - SDRV_STATUS_INVALID_PARAM : The input parameter contains a null pointer. * - SDRV_STATUS_FAIL : Sent module or channel is uninitialized. * - SDRV_STATUS_OK : Start sent channel success. */ status_t sdrv_sent_recv_start(sdrv_sent_t *ctrl, sdrv_sent_chanid_e sent_chan_id) { /* Parameters are valid or not. */ if ((NULL == ctrl) || (sent_chan_id > SDRV_SENT_HW_CPT_D)) { return SDRV_STATUS_INVALID_PARAM; } sdrv_sent_chan_t *sent_chan = &ctrl->chan[sent_chan_id]; if ((SENT_STATUS_UNINIT == ctrl->sent_sta) || (CHAN_STATUS_UNINIT == sent_chan->chan_sta)) { return SDRV_STATUS_FAIL; } /* Stop sent channel if the channel is running. */ if (CHAN_STATUS_RUNNING == sent_chan->chan_sta) { sdrv_sent_recv_stop(ctrl, sent_chan_id); } /* Initialize channel and frame status */ sent_chan->chan_sta = CHAN_STATUS_RUNNING; sent_chan->frame_info.cur_state = SENT_IDLE; sent_chan->frame_info.frame_err = SENT_OK; /* Clear fifo. */ sdrv_etimer_lld_clear_fifo(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id); /* Turn on dma request interrupt */ sdrv_etimer_lld_int_en(ctrl->base, ETMR_BM_INT_STA_EN_CHN_DMA_REQ(sent_chan_id), true); /* Enable capture module */ sdrv_etimer_lld_cpt_en(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id, true); return SDRV_STATUS_OK; } /** * @brief Sent stop recv frame * * Sent channel will receive frames after calling sdrv_sent_recv_start(). * User could stop the sent channel by calling this function. * * @param[in] ctrl Sent controller * @param[in] sent_chan_id Sent channel id * @return The result of initializing sent. * - SDRV_STATUS_INVALID_PARAM : The input parameter contains a null pointer. * - SDRV_STATUS_FAIL : Sent module or channel is uninitialized. * - SDRV_STATUS_OK : Stop sent channel success. */ status_t sdrv_sent_recv_stop(sdrv_sent_t *ctrl, sdrv_sent_chanid_e sent_chan_id) { /* Parameters are valid or not. */ if ((NULL == ctrl) || (sent_chan_id > SDRV_SENT_HW_CPT_D)) { return SDRV_STATUS_INVALID_PARAM; } sdrv_sent_chan_t *sent_chan = &ctrl->chan[sent_chan_id]; if ((SENT_STATUS_UNINIT == ctrl->sent_sta) || (CHAN_STATUS_UNINIT == sent_chan->chan_sta)) { return SDRV_STATUS_FAIL; } if (CHAN_STATUS_RUNNING == sent_chan->chan_sta) { /* Turn off dma request interrupt */ sdrv_etimer_lld_int_en( ctrl->base, ETMR_BM_INT_STA_EN_CHN_DMA_REQ(sent_chan_id), false); /* Disable capture module */ sdrv_etimer_lld_cpt_en(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id, false); sent_chan->chan_sta = CHAN_STATUS_STOPPED; sent_chan->frame_info.cur_state = SENT_IDLE; sent_chan->frame_info.frame_err = SENT_OK; } return SDRV_STATUS_OK; } /** * @brief Parse sent frame * * This function is used in the following two situations: * 1.Enter sent interrupt, * 2.The user actively calls function to parse the remaining data in fifo after * stopping channal. * * @param[in] ctrl Sent controller * @param[in] sent_chan_id Sent channel id * @return The result of initializing sent. * - SDRV_STATUS_INVALID_PARAM : The input parameter contains a null pointer. * - SDRV_STATUS_OK : Parse sent frame success. */ status_t sdrv_sent_parse_msg(sdrv_sent_t *ctrl, sdrv_sent_chanid_e sent_chan_id) { /* Parameters are valid or not. */ if ((NULL == ctrl) || (sent_chan_id > SDRV_SENT_HW_CPT_D)) { return SDRV_STATUS_INVALID_PARAM; } sdrv_sent_chan_t *sent_chan = &ctrl->chan[sent_chan_id]; sent_chan_frame_t *frame_info = &sent_chan->frame_info; /* If occurs fifo error, clear fifo. */ if ((0x01U << ((sent_chan_id * 8U) + 7U)) & sdrv_etimer_lld_get_fifo_sta(ctrl->base)) { /* Clear fifo. */ sdrv_etimer_lld_clear_fifo(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id); /* Updata frame status. */ frame_info->rx_index = 0U; frame_info->frame_err = SENT_OK; frame_info->cur_state = SENT_IDLE; } else { /* Get the length of data in dma fifo. */ uint32_t fifo_datanum = ETMR_GFV_FIFO_STA_FIFO_ENTRIES( sdrv_etimer_lld_get_fifo_sta(ctrl->base), sent_chan_id); /* Parse all data in dam fifo. */ for (uint32_t i = 0U; i < fifo_datanum; ++i) { /* Get the data from fifo. */ uint32_t fifo_data = sdrv_etimer_lld_get_fifo_val( ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id); /* Parse data according to the current frame state. */ switch (frame_info->cur_state) { case SENT_IDLE: { if (0U != sent_chan->expect_scaler) { /* Verificate the frequency of tick. */ uint32_t scaler10 = fifo_data * 10 / 56U; uint32_t err_range = scaler10 / (sent_chan->expect_scaler); if ((err_range >= 8U) && (err_range <= 12U)) { sent_chan->actual_scaler = (scaler10 % 10U) < 5 ? scaler10 / 10U : scaler10 / 10U + 1U; frame_info->frame_err = SENT_OK; frame_info->cur_state = SENT_SYNC; } } break; } case SENT_SYNC: { /* Parse data from fifo. */ uint32_t status_tick = sdrv_tick_parse(fifo_data, sent_chan->actual_scaler); /* Verificate tick count. */ if ((status_tick < 12U) || (status_tick > 27U)) { frame_info->frame_err |= SENT_STATUS_ERR; } /* Update status value */ frame_info->frame_sta = (status_tick - 12U); /* Updata frame status. */ frame_info->rx_index = 0U; frame_info->cur_state = SENT_DATA; break; } case SENT_DATA: { /* Parse data from fifo. */ uint32_t data_tick = sdrv_tick_parse(fifo_data, sent_chan->actual_scaler); /* Verificate tick count. */ if ((data_tick < 12U) || (data_tick > 27U)) { frame_info->frame_err |= SENT_DATA_ERR; } /* Data Value */ frame_info->rxframe[frame_info->rx_index % 6U] = (data_tick - 12U); ++frame_info->rx_index; if (frame_info->rx_index == sent_chan->frame_info.frame_dl) { frame_info->rx_index = 0U; frame_info->cur_state = SENT_CRC; } break; } case SENT_CRC: { /* Parse data from fifo. */ uint32_t crc_tick = sdrv_tick_parse(fifo_data, sent_chan->actual_scaler); /* Verificate tick count. */ if ((crc_tick < 12U) || (crc_tick > 27U)) { frame_info->frame_err |= SENT_CRC_ERR; } /* Check CRC value. */ uint8_t crc_calc = crc4_calculate( 5U, (unsigned char const *)frame_info->rxframe, frame_info->frame_dl); if (crc_calc != (crc_tick - 12U)) { frame_info->frame_err |= SENT_CRC_ERR; } /* Update frame crc value */ frame_info->frame_crc = crc_tick - 12U; memcpy(&g_frame_info[sent_chan_id], frame_info, sizeof(sent_chan_frame_t)); g_frame_info[sent_chan_id].frame_valid = true; /* Frame over if no pause pulse. */ if (sent_chan->pause_pulse == true) { frame_info->cur_state = SENT_PAUSE; } else { /* Call callback function and update frame's current state * to IDLE if frame over. */ frame_info->cur_state = SENT_IDLE; if (sent_chan->frameover_cb) { sent_chan->frameover_cb(ctrl, sent_chan_id, sent_chan->userdata); } frame_info->frame_err = SENT_OK; } break; } case SENT_PAUSE: { /* Call callback function and update frame's current state to * IDLE if frame over. */ frame_info->cur_state = SENT_IDLE; if (sent_chan->frameover_cb) { sent_chan->frameover_cb(ctrl, sent_chan_id, sent_chan->userdata); } frame_info->frame_err = SENT_OK; break; } default: break; } } } return SDRV_STATUS_OK; } /** * @brief Get sent frame info * * @param[in] ctrl Sent controller * @param[in] sent_chan_id Sent channel id * @param[out] frame_err Frame error code * @param[out] frame Frame information * @return The result of initializing sent. * - SDRV_STATUS_INVALID_PARAM : The input parameter contains a null pointer. * - SDRV_STATUS_FAIL : The state of channel is error or the frame is invalid. * - SDRV_STATUS_OK : Get sent frame success. */ status_t sdrv_sent_get_frame(sdrv_sent_t *ctrl, sdrv_sent_chanid_e sent_chan_id, uint32_t *frame_err, sent_chan_frame_t *frame) { /* Parameters are valid or not. */ if ((NULL == ctrl) || (NULL == frame_err) || (NULL == frame) || (sent_chan_id > SDRV_SENT_HW_CPT_D)) { return SDRV_STATUS_INVALID_PARAM; } sdrv_sent_chan_t *sent_chan = &ctrl->chan[sent_chan_id]; /* Check the channel status */ if (sent_chan->chan_sta != CHAN_STATUS_RUNNING) { return SDRV_STATUS_FAIL; } uint32_t ulCpsr = arch_irq_save(); /* Get frame data from sent global buffer. */ if (g_frame_info[sent_chan_id].frame_valid) { memcpy(frame, &g_frame_info[sent_chan_id], sizeof(sent_chan_frame_t)); *frame_err = g_frame_info[sent_chan_id].frame_err; g_frame_info[sent_chan_id].frame_valid = false; arch_irq_restore(ulCpsr); } else { arch_irq_restore(ulCpsr); return SDRV_STATUS_FAIL; } return SDRV_STATUS_OK; } /** * @brief Sdrv sent interrupt handler. * * @param [in] irq The irq number of uartx * @param [in] ctrl Sdrv sent controller */ int sdrv_sent_irq_handle(uint32_t irq, void *ctrl) { /* Parameters are valid or not. */ if (NULL == ctrl) { return -1; } sdrv_sent_t *sdrv_sent = (sdrv_sent_t *)ctrl; /* Get sent channel interrupt status. */ uint32_t sent_sta = sdrv_etimer_lld_get_int_status(sdrv_sent->base); /* Handle all channels interrupt. */ for (sdrv_sent_chanid_e id = SDRV_SENT_HW_CPT_A; id < SDRV_SENT_CHAN_NUM; ++id) { if (sent_sta & ETMR_BM_INT_STA_CHN_DMA_REQ(id)) { /* Parse the data in dma fifo. */ sdrv_sent_parse_msg(sdrv_sent, id); /* Clear the channel interrupt status. */ sdrv_etimer_lld_clear_int_status(sdrv_sent->base, ETMR_BM_INT_STA_CHN_DMA_REQ(id)); } } return 0; } /**************************Static Functions Start******************************/ /** * brief Sdrv sent channel id map to etimer channel id. * * param [in] sent_chan_id Sent channel id * param [out] etimer_cnt_id Sdrv etimer channel id */ static void sdrv_chanid_map(sdrv_sent_chanid_e sent_chan_id, sdrv_etimer_cnt_id_e *etimer_cnt_id) { /* Parameters are valid or not. */ if ((sent_chan_id > SDRV_SENT_HW_CPT_D) || (NULL == etimer_cnt_id)) { return; } /* Exchanging etimer channel number to sent channel number. */ *etimer_cnt_id = (sdrv_etimer_cnt_id_e)(sent_chan_id + 2U); } /** * brief Sdrv sent module initialize. * * param [in] ctrl Sdrv sent controller entity */ static void sdrv_sent_module_init(sdrv_sent_t *ctrl) { /* Parameters are valid or not. */ if (NULL == ctrl) { return; } /* Disable clock monitor. */ sdrv_etimer_lld_clk_mon_en(ctrl->base, false); /* Config clock. */ clk_set_t clk_set = {0U}; clk_set.src_clk_sel = (sdrv_etimer_clk_src_e)ctrl->clk_sel; clk_set.div_num = (uint32_t)ctrl->clk_div; sdrv_etimer_lld_clk_cfg(ctrl->base, &clk_set); /* Enable clock monitor. */ sdrv_etimer_lld_clk_mon_en(ctrl->base, true); } /** * brief Sdrv sent module deinitialize. * * param [in] ctrl Sdrv sent controller entity */ static void sdrv_sent_module_deinit(sdrv_sent_t *ctrl) { /* Parameters are valid or not. */ if (NULL == ctrl) { return; } /* Disable clock monitor. */ sdrv_etimer_lld_clk_mon_en(ctrl->base, false); /* Config clock. */ clk_set_t clk_set = {0U}; sdrv_etimer_lld_clk_cfg(ctrl->base, &clk_set); /* Enable clock monitor. */ sdrv_etimer_lld_clk_mon_en(ctrl->base, true); } /** * brief Sdrv sent channel initialize. * * param [in] ctrl Sdrv sent controller entity * param [in] sent_chan_id Sent channel id */ static void sdrv_sent_channel_init(sdrv_sent_t *ctrl, sdrv_sent_chanid_e sent_chan_id) { /* Parameters are valid or not. */ if ((NULL == ctrl) || (sent_chan_id > SDRV_SENT_HW_CPT_D)) { return; } sdrv_sent_chan_t *sdrv_sent_chan = &ctrl->chan[sent_chan_id]; sdrv_etimer_cnt_id_e etimer_cnt_id; sdrv_chanid_map(sent_chan_id, &etimer_cnt_id); /* Set timer counter ovf value 0xFFFFFFFFU */ sdrv_etimer_lld_cnt_ovf(ctrl->base, etimer_cnt_id, 0xFFFFFFFFU); /* Cnt will start when the first cpt event happen */ local_cnt_config_t sdrv_lcnt_cfg = {0U}; sdrv_lcnt_cfg.start_by_first_cpt = true; sdrv_etimer_lld_local_cnt_cfg(ctrl->base, etimer_cnt_id, &sdrv_lcnt_cfg); /* Reset the counter when the cpt0 event happen */ sdrv_etimer_lld_lcnt_cpt_clr_en(ctrl->base, etimer_cnt_id, SDRV_ETIMR_LCNT_CPT_0_CLR, true); /* Enable timer counter */ sdrv_etimer_lld_cnt_en(ctrl->base, etimer_cnt_id, true); /* Set the triggered edge as falling edge, set the local timer as capture * counter */ cpt_config_t sdrv_cpt_cfg; memset(&sdrv_cpt_cfg, 0, sizeof(cpt_config_t)); sdrv_cpt_cfg.cpt0_trig_mode = SDRV_ETIMR_CPT_FALL_EDGE; sdrv_cpt_cfg.cnt_sel = SDRV_ETIMR_CPT_LCNT; sdrv_etimer_lld_cpt_cfg(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id, &sdrv_cpt_cfg); sdrv_etimer_lld_cpt_config_set(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id); /* Set water mark level value */ sdrv_etimer_lld_dma_wml(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id, sdrv_sent_chan->fifowml); /* Set dma block as capture */ chn_etimer_dma_ctrl_t sdrv_dmactrl_cfg = {0U}; sdrv_dmactrl_cfg.block_sel = SDRV_ETIMR_CPT_BLOCK; sdrv_dmactrl_cfg.chn_en = 1U; sdrv_etimer_lld_dma_chn_cfg(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id, &sdrv_dmactrl_cfg); /* Enable capture filter. */ if (sdrv_sent_chan->filter_en) { flt_config_t filter_cfg; filter_cfg.flt_edge_sel = SDRV_ETIMR_FLT_NEGEEDGE; filter_cfg.neg_band_wid = 0U; filter_cfg.neg_band_wid = sdrv_sent_chan->filter_bandwidth; filter_cfg.sample_intval = sdrv_sent_chan->sample_interval; sdrv_etimer_lld_cpt_flt_cfg( ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id, &filter_cfg); sdrv_etimer_lld_cpt_flt_en(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id, true); } } /** * brief Sdrv sent channel deinitialize. * * param [in] ctrl Sdrv sent controller entity * param [in] sent_chan_id Sent channel id */ static void sdrv_sent_channel_deinit(sdrv_sent_t *ctrl, sdrv_sent_chanid_e sent_chan_id) { /* Parameters are valid or not. */ if ((NULL == ctrl) || (sent_chan_id > SDRV_SENT_HW_CPT_D)) { return; } sdrv_etimer_cnt_id_e etimer_cnt_id; sdrv_chanid_map(sent_chan_id, &etimer_cnt_id); /* Turn off dma req interrupt */ sdrv_etimer_lld_int_en(ctrl->base, ETMR_BM_INT_STA_EN_CHN_DMA_REQ(sent_chan_id), false); /* Disable cpt module */ sdrv_etimer_lld_cpt_en(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id, false); /* Restore timer counter overflow value 0 */ sdrv_etimer_lld_cnt_ovf(ctrl->base, etimer_cnt_id, 0U); /* Overflow will be updated to shadow register */ sdrv_etimer_lld_cnt_upd(ctrl->base, etimer_cnt_id, false, true); /* Restore the cnt cfg */ local_cnt_config_t sdrv_lcnt_cfg = {0U}; sdrv_lcnt_cfg.start_by_first_cpt = false; sdrv_etimer_lld_local_cnt_cfg(ctrl->base, etimer_cnt_id, &sdrv_lcnt_cfg); sdrv_etimer_lld_lcnt_cpt_clr_en(ctrl->base, etimer_cnt_id, SDRV_ETIMR_LCNT_CPT_0_CLR, false); /* Disable timer counter */ sdrv_etimer_lld_cnt_en(ctrl->base, etimer_cnt_id, false); /* Restore the triggered edge, restore the timer as capture counter */ cpt_config_t sdrv_cpt_cfg; memset(&sdrv_cpt_cfg, 0, sizeof(cpt_config_t)); sdrv_cpt_cfg.cpt0_trig_mode = SDRV_ETIMR_CPT_RISE_EDGE; sdrv_cpt_cfg.cnt_sel = SDRV_ETIMR_CPT_CNTG0; sdrv_etimer_lld_cpt_cfg(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id, &sdrv_cpt_cfg); sdrv_etimer_lld_cpt_config_set(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id); /* Restore water mark level value */ sdrv_etimer_lld_dma_wml(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id, 0U); /* Set dma block as default block */ chn_etimer_dma_ctrl_t sdrv_dmactrl_cfg = {0U}; sdrv_dmactrl_cfg.block_sel = SDRV_ETIMR_CMP_BLOCK; sdrv_dmactrl_cfg.chn_en = 0U; sdrv_etimer_lld_dma_chn_cfg(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id, &sdrv_dmactrl_cfg); /* Disable capture filter. */ sdrv_etimer_lld_cpt_flt_en(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id, false); /* Reset the channel count. */ sdrv_etimer_lld_sw_rst(ctrl->base, 1U << sent_chan_id); /* Clear fifo. */ sdrv_etimer_lld_clear_fifo(ctrl->base, (sdrv_etimer_chn_id_e)sent_chan_id); } /** * brief Parse data to tick. * * param [in] data data in dma fifo. * param [in] actual_scaler sent channel actual scaler. * return The count of tick. */ static uint32_t sdrv_tick_parse(uint32_t data, uint32_t actual_scaler) { /* Parameters are valid or not. */ if (0U == actual_scaler) { return 0U; } /* Round off the number of tick. */ uint32_t ticktimes10 = (data * 10U) / actual_scaler; return ((ticktimes10 % 10) < 5U) ? (ticktimes10 / 10U) : (ticktimes10 / 10U + 1U); } /** * brief Check the configurations of sent. * * param [in] cfg Sdrv sent configurations. * return The configurations are valid or not. * - true : The configurations of sent are valid. * - false : The configurations of sent are unvalid. */ static bool sdrv_sent_config_check(sdrv_sent_config_t *cfg) { /* Parameters are valid or not. */ if (NULL == cfg) { return false; } /* Check sent module configurations. */ if ((0U == cfg->base) || (0U == cfg->irq) || (0U == cfg->clk_freq) || (cfg->clk_div > 65534U) || (0U == cfg->chan_cfg_num)) { return false; } /* Check sent channel configurations. */ for (uint8_t i = 0; i < cfg->chan_cfg_num; ++i) { if ((0U == cfg->chan_cfg[i].tickfreq) || (cfg->chan_cfg[i].chan_id >= SDRV_SENT_CHAN_NUM) || (cfg->chan_cfg[i].data_bitnum > SENT_DATA_WIDTH_24_BIT) || (0U == cfg->chan_cfg[i].fifowml) || (cfg->chan_cfg[i].fifowml > 0X0FU) || (cfg->chan_cfg[i].lowpulse_width < 5U) || (cfg->chan_cfg[i].lowpulse_width > 12U) || ((cfg->chan_cfg[i].filter_en) && ((cfg->chan_cfg[i].filter_bandwidth < 2U) || (cfg->chan_cfg[i].filter_bandwidth > 17U)))) { return false; } /* Check sent channel expect_scaler. */ uint32_t expect_scaler = (cfg->clk_freq / (cfg->clk_div + 1U)) / (cfg->chan_cfg[i].tickfreq); if (0U == expect_scaler) { return false; } } return true; } /**************************Static Functions End********************************/