Files
test/drivers/source/sent/sdrv_sent.c
2025-11-07 20:19:23 +08:00

806 lines
29 KiB
C

/**
* @file sdrv_sent.c
* @brief SemiDrive Sent driver source.
*
* @copyright Copyright (c) 2020 Semidrive Semiconductor.
* All rights reserved.
*/
#include <checksum/crc4.h>
#include <compiler.h>
#include <math.h>
#include <string.h>
#include <types.h>
#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********************************/