1557 lines
53 KiB
C
1557 lines
53 KiB
C
/**
|
|
* @file sdrv_etimer.c
|
|
* @brief Semidrive ETIMER driver source file.
|
|
*
|
|
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <types.h>
|
|
|
|
#include "sdrv_etimer.h"
|
|
#include "clock_ip.h"
|
|
#include "bits.h"
|
|
#include "debug.h"
|
|
#include "irq.h"
|
|
#include "regs_base.h"
|
|
|
|
#define EXTRA_FMT "sdrv_etimer:"
|
|
#define SDRV_ETIMER_ERR(format, ...) \
|
|
ssdk_printf(SSDK_ERR, EXTRA_FMT format, ##__VA_ARGS__)
|
|
#define SDRV_ETIMER_WARN(format, ...) \
|
|
ssdk_printf(SSDK_WARNING, EXTRA_FMT format, ##__VA_ARGS__)
|
|
#define SDRV_ETIMER_INFO(format, ...) \
|
|
ssdk_printf(SSDK_INFO, EXTRA_FMT format, ##__VA_ARGS__)
|
|
|
|
/**
|
|
* @brief sdrv etimer ns transfer to val.
|
|
*
|
|
* @param[in] clk src clk
|
|
* @param[in] ns time val
|
|
* @param[in] div src clk divider
|
|
* @return ns_to_val
|
|
*/
|
|
static inline uint32_t sdrv_etimer_ns_to_val(uint32_t clk, uint32_t ns, uint32_t div)
|
|
{
|
|
uint32_t clk_cnt_per_ms = (clk / (div + 1)) / 1000;
|
|
uint32_t ns_to_val = (uint32_t)((uint64_t)ns * clk_cnt_per_ms / 1000000);
|
|
return ns_to_val;
|
|
}
|
|
|
|
/**
|
|
* @brief sdrv etimer ns transfer to val .
|
|
*
|
|
* @param[in] clk src clk
|
|
* @param[in] ns time val
|
|
* @param[in] div src clk divider
|
|
* @return ns_to_val
|
|
*/
|
|
static inline uint32_t sdrv_etimer_ns_to_val_1(uint32_t clk, uint32_t ns, uint32_t div)
|
|
{
|
|
uint32_t clk_cnt_per_ms = (clk / (div + 1)) / 1000;
|
|
uint32_t ns_to_val = (uint32_t)((uint64_t)ns * clk_cnt_per_ms / 1000000);
|
|
uint32_t ns_to_val_1 = ns_to_val - 1;
|
|
return ns_to_val_1;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief sdrv etimer val transfer to ns.
|
|
*
|
|
* @param[in] clk src clk
|
|
* @param[in] ns time val
|
|
* @param[in] div src clk divider
|
|
* @return val_to_ns
|
|
*/
|
|
static inline uint32_t sdrv_etimer_val_to_ns(uint32_t clk, uint32_t val, uint32_t div)
|
|
{
|
|
uint32_t clk_cnt_per_ms = (clk / (div + 1)) / 1000;
|
|
uint32_t val_to_ns = (uint32_t)((uint64_t)val * 1000000 / clk_cnt_per_ms);
|
|
return val_to_ns;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief sdrv etimer irq handle function
|
|
*
|
|
* @param[in] irq irq id
|
|
* @param[in] arg irq arg
|
|
*/
|
|
static int sdrv_etimer_irq_handle(uint32_t irq, void *arg)
|
|
{
|
|
/* capture channel ctrl */
|
|
sdrv_etimer_controller_t *pst_etimer_controller = arg;
|
|
sdrv_etimer_t *sdrv_etimer_cpt_chn_a =
|
|
pst_etimer_controller->etimer_bank[SDRV_ETIMR_CHN_A];
|
|
sdrv_etimer_t *sdrv_etimer_cpt_chn_b =
|
|
pst_etimer_controller->etimer_bank[SDRV_ETIMR_CHN_B];
|
|
sdrv_etimer_t *sdrv_etimer_cpt_chn_c =
|
|
pst_etimer_controller->etimer_bank[SDRV_ETIMR_CHN_C];
|
|
sdrv_etimer_t *sdrv_etimer_cpt_chn_d =
|
|
pst_etimer_controller->etimer_bank[SDRV_ETIMR_CHN_D];
|
|
/* compare channel ctrl */
|
|
sdrv_etimer_t *sdrv_etimer_cmp_chn_a =
|
|
pst_etimer_controller->etimer_bank[SDRV_ETIMR_CHN_A + 4];
|
|
sdrv_etimer_t *sdrv_etimer_cmp_chn_b =
|
|
pst_etimer_controller->etimer_bank[SDRV_ETIMR_CHN_B + 4];
|
|
sdrv_etimer_t *sdrv_etimer_cmp_chn_c =
|
|
pst_etimer_controller->etimer_bank[SDRV_ETIMR_CHN_C + 4];
|
|
sdrv_etimer_t *sdrv_etimer_cmp_chn_d =
|
|
pst_etimer_controller->etimer_bank[SDRV_ETIMR_CHN_D + 4];
|
|
volatile uint32_t int_sta = 0;
|
|
int_sta = sdrv_etimer_lld_get_int_status(pst_etimer_controller->base);
|
|
uint32_t clr_int_sta = 0;
|
|
|
|
if (int_sta & ETMR_BM_INT_STA_CPT(SDRV_ETIMR_CHN_A)) {
|
|
clr_int_sta = int_sta & ETMR_BM_INT_STA_CPT(SDRV_ETIMR_CHN_A);
|
|
sdrv_etimer_lld_clear_int_status(pst_etimer_controller->base,
|
|
clr_int_sta);
|
|
|
|
if (sdrv_etimer_cpt_chn_a->mode == ETIMER_PWM_CAPTURE) {
|
|
sdrv_etimer_cpt_chn_a->cpt_read_flag = false;
|
|
}
|
|
|
|
if ((sdrv_etimer_cpt_chn_a != NULL) &&
|
|
(sdrv_etimer_cpt_chn_a->callback)) {
|
|
sdrv_etimer_cpt_chn_a->callback(sdrv_etimer_cpt_chn_a->arg);
|
|
}
|
|
}
|
|
|
|
if (int_sta & ETMR_BM_INT_STA_CMP(SDRV_ETIMR_CHN_A)) {
|
|
clr_int_sta = int_sta & ETMR_BM_INT_STA_CMP(SDRV_ETIMR_CHN_A);
|
|
sdrv_etimer_lld_clear_int_status(pst_etimer_controller->base,
|
|
clr_int_sta);
|
|
|
|
if ((sdrv_etimer_cmp_chn_a != NULL) &&
|
|
(sdrv_etimer_cmp_chn_a->callback)) {
|
|
sdrv_etimer_cmp_chn_a->callback(sdrv_etimer_cmp_chn_a->arg);
|
|
}
|
|
}
|
|
|
|
if (int_sta & ETMR_BM_INT_STA_CPT(SDRV_ETIMR_CHN_B)) {
|
|
clr_int_sta = int_sta & ETMR_BM_INT_STA_CPT(SDRV_ETIMR_CHN_B);
|
|
sdrv_etimer_lld_clear_int_status(pst_etimer_controller->base,
|
|
clr_int_sta);
|
|
|
|
if (sdrv_etimer_cpt_chn_b->mode == ETIMER_PWM_CAPTURE) {
|
|
sdrv_etimer_cpt_chn_b->cpt_read_flag = false;
|
|
}
|
|
|
|
if ((sdrv_etimer_cpt_chn_b != NULL) &&
|
|
(sdrv_etimer_cpt_chn_b->callback)) {
|
|
sdrv_etimer_cpt_chn_b->callback(sdrv_etimer_cpt_chn_b->arg);
|
|
}
|
|
}
|
|
|
|
if (int_sta & ETMR_BM_INT_STA_CMP(SDRV_ETIMR_CHN_B)) {
|
|
clr_int_sta = int_sta & ETMR_BM_INT_STA_CMP(SDRV_ETIMR_CHN_B);
|
|
sdrv_etimer_lld_clear_int_status(pst_etimer_controller->base,
|
|
clr_int_sta);
|
|
|
|
if ((sdrv_etimer_cmp_chn_b != NULL) &&
|
|
(sdrv_etimer_cmp_chn_b->callback)) {
|
|
sdrv_etimer_cmp_chn_b->callback(sdrv_etimer_cmp_chn_b->arg);
|
|
}
|
|
}
|
|
|
|
if (int_sta & ETMR_BM_INT_STA_CPT(SDRV_ETIMR_CHN_C)) {
|
|
clr_int_sta = int_sta & ETMR_BM_INT_STA_CPT(SDRV_ETIMR_CHN_C);
|
|
sdrv_etimer_lld_clear_int_status(pst_etimer_controller->base,
|
|
clr_int_sta);
|
|
|
|
if (sdrv_etimer_cpt_chn_c->mode == ETIMER_PWM_CAPTURE) {
|
|
sdrv_etimer_cpt_chn_c->cpt_read_flag = false;
|
|
}
|
|
|
|
if ((sdrv_etimer_cpt_chn_c != NULL) &&
|
|
(sdrv_etimer_cpt_chn_c->callback)) {
|
|
sdrv_etimer_cpt_chn_c->callback(sdrv_etimer_cpt_chn_c->arg);
|
|
}
|
|
}
|
|
|
|
if (int_sta & ETMR_BM_INT_STA_CMP(SDRV_ETIMR_CHN_C)) {
|
|
clr_int_sta = int_sta & ETMR_BM_INT_STA_CMP(SDRV_ETIMR_CHN_C);
|
|
sdrv_etimer_lld_clear_int_status(pst_etimer_controller->base,
|
|
clr_int_sta);
|
|
|
|
if ((sdrv_etimer_cmp_chn_c != NULL) &&
|
|
(sdrv_etimer_cmp_chn_c->callback)) {
|
|
sdrv_etimer_cmp_chn_c->callback(sdrv_etimer_cmp_chn_c->arg);
|
|
}
|
|
}
|
|
|
|
if (int_sta & ETMR_BM_INT_STA_CPT(SDRV_ETIMR_CHN_D)) {
|
|
clr_int_sta = int_sta & ETMR_BM_INT_STA_CPT(SDRV_ETIMR_CHN_D);
|
|
sdrv_etimer_lld_clear_int_status(pst_etimer_controller->base,
|
|
clr_int_sta);
|
|
|
|
if (sdrv_etimer_cpt_chn_d->mode == ETIMER_PWM_CAPTURE) {
|
|
sdrv_etimer_cpt_chn_d->cpt_read_flag = false;
|
|
}
|
|
|
|
if ((sdrv_etimer_cpt_chn_d != NULL) &&
|
|
(sdrv_etimer_cpt_chn_d->callback)) {
|
|
sdrv_etimer_cpt_chn_d->callback(sdrv_etimer_cpt_chn_d->arg);
|
|
}
|
|
}
|
|
|
|
if (int_sta & ETMR_BM_INT_STA_CMP(SDRV_ETIMR_CHN_D)) {
|
|
clr_int_sta = int_sta & ETMR_BM_INT_STA_CMP(SDRV_ETIMR_CHN_D);
|
|
sdrv_etimer_lld_clear_int_status(pst_etimer_controller->base,
|
|
clr_int_sta);
|
|
|
|
if ((sdrv_etimer_cmp_chn_d != NULL) &&
|
|
(sdrv_etimer_cmp_chn_d->callback)) {
|
|
sdrv_etimer_cmp_chn_d->callback(sdrv_etimer_cmp_chn_d->arg);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief sdrv etimer timer ovf irq handle function
|
|
*
|
|
* @param[in] irq irq id
|
|
* @param[in] arg irq arg
|
|
*/
|
|
static int sdrv_etimer_timer_ovf_irq_handle(uint32_t irq, void *arg)
|
|
{
|
|
sdrv_etimer_controller_t *pst_etimer_tmr = arg;
|
|
sdrv_etimer_t *sdrv_etimer_cnt_g0 =
|
|
pst_etimer_tmr->cnt_bank[ETIMR_BASIC_TMR_G0];
|
|
sdrv_etimer_t *sdrv_etimer_cnt_g1 =
|
|
pst_etimer_tmr->cnt_bank[ETIMR_BASIC_TMR_G1];
|
|
volatile uint32_t int_sta = 0;
|
|
int_sta = sdrv_etimer_lld_get_int_status(pst_etimer_tmr->base);
|
|
uint32_t clr_int_sta = 0;
|
|
|
|
if (int_sta & ETMR_BM_INT_STA_CNT_OVF(ETIMR_BASIC_TMR_G0)) {
|
|
clr_int_sta = int_sta & ETMR_BM_INT_STA_CNT_OVF(ETIMR_BASIC_TMR_G0);
|
|
sdrv_etimer_lld_clear_int_status(pst_etimer_tmr->base, clr_int_sta);
|
|
|
|
if ((sdrv_etimer_cnt_g0 != NULL) && (sdrv_etimer_cnt_g0->callback)) {
|
|
sdrv_etimer_cnt_g0->callback(sdrv_etimer_cnt_g0->arg);
|
|
}
|
|
}
|
|
|
|
if (int_sta & ETMR_BM_INT_STA_CNT_OVF(ETIMR_BASIC_TMR_G1)) {
|
|
clr_int_sta = int_sta & ETMR_BM_INT_STA_CNT_OVF(ETIMR_BASIC_TMR_G1);
|
|
sdrv_etimer_lld_clear_int_status(pst_etimer_tmr->base, clr_int_sta);
|
|
|
|
if ((sdrv_etimer_cnt_g1 != NULL) && (sdrv_etimer_cnt_g1->callback)) {
|
|
sdrv_etimer_cnt_g1->callback(sdrv_etimer_cnt_g1->arg);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief check etimer clk set status and int set
|
|
*
|
|
* @param[in] etmr: etimer ctrl instance
|
|
* @param[in] etimer_module etimer module id
|
|
*/
|
|
static bool sdrv_etimer_clk_int_set(sdrv_etimer_t *etmr)
|
|
{
|
|
sdrv_etimer_controller_t *ctrl = etmr->controller;
|
|
ASSERT(ctrl != NULL);
|
|
|
|
/* check etimer clk set */
|
|
if (ctrl->clk_set_flag == false) {
|
|
clk_set_t clk_config;
|
|
|
|
if (etmr->use_multicpt) {
|
|
clk_config.src_clk_sel = SDRV_ETIMR_AHF_CLK;
|
|
}
|
|
else {
|
|
clk_config.src_clk_sel = etmr->clk_src;
|
|
}
|
|
|
|
clk_config.div_num = etmr->clk_div;
|
|
sdrv_etimer_lld_clk_mon_en(etmr->base, false);
|
|
sdrv_etimer_lld_clk_cfg(etmr->base, &clk_config);
|
|
sdrv_etimer_lld_clk_mon_en(etmr->base, true);
|
|
ctrl->clk_set_flag = true;
|
|
ctrl->etimer_clk_src = etmr->clk_src;
|
|
ctrl->etimer_clk_div = etmr->clk_div;
|
|
}
|
|
else {
|
|
/* The timer function needs to set the clock source consistent with the
|
|
* configured clock source */
|
|
if ((etmr->mode == ETIMER_TIMER_FUNC) && (etmr->clk_src != ctrl->etimer_clk_src)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ((ctrl->int_init_flag == false) && (etmr->use_multicpt == false)) {
|
|
/* clear all int status */
|
|
sdrv_etimer_lld_int_enable(etmr->base, 0x0);
|
|
sdrv_etimer_lld_clear_int_status(etmr->base, 0xFFFFFFFF);
|
|
ctrl->int_init_flag = true;
|
|
}
|
|
|
|
if (etmr->mode == ETIMER_PWM_CAPTURE) {
|
|
/* pwm capture function always enable irq */
|
|
sdrv_etimer_lld_int_en(etmr->base, ETMR_BM_INT_STA_EN_CPT(etmr->channel), true);
|
|
}
|
|
|
|
/* check etimer int set */
|
|
if (etmr->int_en == true) {
|
|
if (etmr->mode == ETIMER_PWM_GENERATE) {
|
|
sdrv_etimer_lld_int_en(etmr->base, ETMR_BM_INT_STA_EN_CMP(etmr->channel), true);
|
|
}
|
|
else if (etmr->mode == ETIMER_TIMER_FUNC) {
|
|
sdrv_etimer_lld_int_en(etmr->base, ETMR_BM_INT_STA_EN_CNT_OVF(etmr->config.cnt_cfg->tmr_id), true);
|
|
}
|
|
else if (etmr->mode == ETIMER_ICU_FUNC) {
|
|
sdrv_etimer_lld_int_en(etmr->base, ETMR_BM_INT_STA_EN_CPT(etmr->channel), true);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief etimer setup callback funciton
|
|
*
|
|
* @param[in] etmr: etimer ctrl instance
|
|
* @param[in] callback: user callback function
|
|
* @return succeed:0 fail:other
|
|
*/
|
|
uint8_t sdrv_etimer_set_callback(sdrv_etimer_t *etmr, etimer_callback callback,
|
|
void *arg)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
etmr->callback = callback;
|
|
etmr->arg = arg;
|
|
return 0;
|
|
}
|
|
|
|
/* etimer timer function */
|
|
|
|
/**
|
|
* @brief etimer timer init
|
|
*
|
|
* @param[in] etmr: etimer ctrl instance
|
|
* @param[in] cnt_cfg: timer counter config
|
|
*/
|
|
status_t sdrv_etimer_timer_init(sdrv_etimer_t *etmr,
|
|
sdrv_etimer_basic_cnt_cfg_t *cnt_cfg)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_controller_t *ctrl = etmr->controller;
|
|
ASSERT(ctrl != NULL);
|
|
sdrv_etimer_basic_cnt_id_t cnt_sel = cnt_cfg->tmr_id;
|
|
|
|
/* chcek the timer status */
|
|
if ((etmr->mode != ETIMER_TIMER_FUNC) ||
|
|
(etmr->crtl_sta != ETIMER_CHAN_UNINIT) || (ctrl->g0_mode != G0_IDLE)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
etmr->clk_src = cnt_cfg->clk_sel;
|
|
etmr->clk_div = cnt_cfg->clk_div;
|
|
etmr->config.cnt_cfg = cnt_cfg;
|
|
bool ret = sdrv_etimer_clk_int_set(etmr);
|
|
|
|
if (ret == false) {
|
|
/* The timer function needs to set the clock source consistent with the
|
|
* configured clock source */
|
|
return SDRV_STATUS_FAIL;
|
|
}
|
|
|
|
etmr->config.cnt_per_ms =
|
|
(cnt_cfg->clk_frq / (cnt_cfg->clk_div + 1)) / 1000;
|
|
basic_cnt_config_t basic_cnt_config;
|
|
memset(&basic_cnt_config, 0, sizeof(basic_cnt_config));
|
|
/* set cnt consective mode */
|
|
basic_cnt_config.ce_en = true;
|
|
basic_cnt_config.con_mode = cnt_cfg->con_mode;
|
|
sdrv_etimer_lld_basic_cnt_cfg(etmr->base, (sdrv_etimer_cnt_id_e)cnt_sel, &basic_cnt_config);
|
|
|
|
if (cnt_sel == ETIMR_BASIC_TMR_G0) {
|
|
ctrl->g0_mode = G0_FOR_TIMER;
|
|
}
|
|
|
|
ctrl->base = etmr->base;
|
|
ctrl->cnt_bank[cnt_sel] = etmr;
|
|
etmr->crtl_sta = ETIMER_CHAN_INIT;
|
|
|
|
/* register the irq */
|
|
if (etmr->irq > 0) {
|
|
irq_attach(etmr->irq, sdrv_etimer_timer_ovf_irq_handle, ctrl);
|
|
irq_enable(etmr->irq);
|
|
}
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief etimer timer start (us)
|
|
*
|
|
* @param[in] etmr: etimer ctrl instance
|
|
* @param[in] time_out: timer timeout value
|
|
*/
|
|
status_t sdrv_etimer_timer_start(sdrv_etimer_t *etmr, uint32_t time_out)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_basic_cnt_id_t cnt_sel = etmr->config.cnt_cfg->tmr_id;
|
|
|
|
/* chcek the timer status */
|
|
if ((etmr->mode != ETIMER_TIMER_FUNC) ||
|
|
(etmr->crtl_sta == ETIMER_CHAN_UNINIT) || time_out == 0) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
/* reset the counter to 0 */
|
|
sdrv_etimer_lld_cnt_frc_rld(etmr->base, (sdrv_etimer_cnt_id_e)cnt_sel);
|
|
etmr->config.time_out = time_out;
|
|
/* set the counter ovf value */
|
|
uint32_t ovf_val = (uint32_t)(((uint64_t)time_out * etmr->config.cnt_per_ms) / 1000);
|
|
sdrv_etimer_lld_cnt_ovf(etmr->base, (sdrv_etimer_cnt_id_e)cnt_sel, ovf_val);
|
|
/* enable the counter */
|
|
sdrv_etimer_lld_cnt_en(etmr->base, (sdrv_etimer_cnt_id_e)cnt_sel, true);
|
|
etmr->crtl_sta = ETIMER_CHAN_RUNNING;
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief etimer timer stop
|
|
*
|
|
* @param[in] etmr: etimer ctrl instance
|
|
*/
|
|
status_t sdrv_etimer_timer_stop(sdrv_etimer_t *etmr)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_basic_cnt_id_t cnt_sel = etmr->config.cnt_cfg->tmr_id;
|
|
|
|
/* chcek the timer status */
|
|
if ((etmr->mode != ETIMER_TIMER_FUNC) ||
|
|
(etmr->crtl_sta == ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
/* disable the counter */
|
|
sdrv_etimer_lld_cnt_en(etmr->base, (sdrv_etimer_cnt_id_e)cnt_sel, false);
|
|
etmr->crtl_sta = ETIMER_CHAN_STOP;
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief etimer timer get current time val (us)
|
|
*
|
|
* @param[in] etmr: etimer ctrl instance
|
|
* @return current time val
|
|
*/
|
|
uint32_t sdrv_etimer_timer_get_current_time(sdrv_etimer_t *etmr)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_basic_cnt_id_t cnt_sel = etmr->config.cnt_cfg->tmr_id;
|
|
|
|
/* chcek the timer status */
|
|
if ((etmr->mode != ETIMER_TIMER_FUNC) ||
|
|
(etmr->crtl_sta != ETIMER_CHAN_RUNNING)) {
|
|
return 0;
|
|
}
|
|
|
|
uint32_t cnt_val = sdrv_etimer_lld_get_cnt_value(etmr->base, (sdrv_etimer_cnt_id_e)cnt_sel);
|
|
uint32_t ret = 0;
|
|
|
|
if (etmr->config.cnt_per_ms == 0) {
|
|
ret = 0;
|
|
}
|
|
else {
|
|
ret = (uint32_t)((uint64_t)cnt_val * 1000 / (etmr->config.cnt_per_ms));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* capture function */
|
|
|
|
/**
|
|
* @brief init etimer capture chan.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
*/
|
|
status_t sdrv_etimer_capture_init(sdrv_etimer_t *etmr)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_controller_t *ctrl = etmr->controller;
|
|
ASSERT(ctrl != NULL);
|
|
sdrv_etimer_chn_id_e cpt_chn = etmr->channel;
|
|
|
|
if ((etmr->mode != ETIMER_PWM_CAPTURE) ||
|
|
(etmr->crtl_sta != ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
sdrv_etimer_clk_int_set(etmr);
|
|
cpt_config_t cpt_config;
|
|
local_cnt_config_t local_cnt_config;
|
|
memset(&cpt_config, 0, sizeof(cpt_config));
|
|
memset(&local_cnt_config, 0, sizeof(local_cnt_config));
|
|
/* capture cnt config */
|
|
sdrv_etimer_cnt_id_e cpt_cnt_sel = (sdrv_etimer_cnt_id_e)(cpt_chn + 2);
|
|
local_cnt_config.cpt1_clr_en = true;
|
|
local_cnt_config.start_by_first_cpt = true;
|
|
sdrv_etimer_lld_local_cnt_cfg(etmr->base, cpt_cnt_sel, &local_cnt_config);
|
|
/* cpt_config */
|
|
cpt_config.cnt_sel = SDRV_ETIMR_CPT_LCNT;
|
|
cpt_config.con_mode = SDRV_ETIMR_CPT_CONSECTIVE;
|
|
cpt_config.dual_mode = SDRV_ETIMR_CPT_CPT0_CPT1;
|
|
cpt_config.cpt1_trig_mode = SDRV_ETIMR_CPT_RISE_EDGE;
|
|
cpt_config.cpt0_trig_mode = SDRV_ETIMR_CPT_FALL_EDGE;
|
|
sdrv_etimer_lld_cpt_cfg(etmr->base, cpt_chn, &cpt_config);
|
|
sdrv_etimer_lld_cpt_config_set(etmr->base, cpt_chn);
|
|
|
|
ctrl->base = etmr->base;
|
|
ctrl->etimer_bank[cpt_chn] = etmr;
|
|
etmr->crtl_sta = ETIMER_CHAN_INIT;
|
|
etmr->cpt_read_flag = true;
|
|
|
|
if (etmr->irq > 0) {
|
|
irq_attach(etmr->irq, sdrv_etimer_irq_handle, ctrl);
|
|
irq_enable(etmr->irq);
|
|
}
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief start etimer capture chan.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
*/
|
|
status_t sdrv_etimer_capture_start(sdrv_etimer_t *etmr)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_chn_id_e cpt_chn = etmr->channel;
|
|
|
|
if ((etmr->mode != ETIMER_PWM_CAPTURE) ||
|
|
(etmr->crtl_sta == ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
sdrv_etimer_cnt_id_e cpt_cnt_sel = (sdrv_etimer_cnt_id_e)(cpt_chn + 2);
|
|
/* reset the counter to 0 */
|
|
sdrv_etimer_lld_cnt_frc_rld(etmr->base, cpt_cnt_sel);
|
|
sdrv_etimer_lld_cpt_en(etmr->base, cpt_chn, true);
|
|
sdrv_etimer_lld_cnt_en(etmr->base, cpt_cnt_sel, true);
|
|
etmr->crtl_sta = ETIMER_CHAN_RUNNING;
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief stop etimer capture chan.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
*/
|
|
status_t sdrv_etimer_capture_stop(sdrv_etimer_t *etmr)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_chn_id_e cpt_chn = etmr->channel;
|
|
|
|
if ((etmr->mode != ETIMER_PWM_CAPTURE) ||
|
|
(etmr->crtl_sta == ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
sdrv_etimer_cnt_id_e cpt_cnt_sel = (sdrv_etimer_cnt_id_e)(cpt_chn + 2);
|
|
sdrv_etimer_lld_cpt_en(etmr->base, cpt_chn, false);
|
|
sdrv_etimer_lld_cnt_en(etmr->base, cpt_cnt_sel, false);
|
|
etmr->crtl_sta = ETIMER_CHAN_STOP;
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief etimer capture pwm signal.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
* @param[in] state pwm duty and period
|
|
*/
|
|
status_t sdrv_etimer_capture_pwm(sdrv_etimer_t *etmr,
|
|
sdrv_etimer_pwm_state_t *state)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
ASSERT(state != NULL);
|
|
sdrv_etimer_controller_t *ctrl = etmr->controller;
|
|
ASSERT(ctrl != NULL);
|
|
sdrv_etimer_chn_id_e cpt_chn = etmr->channel;
|
|
|
|
if ((etmr->mode != ETIMER_PWM_CAPTURE) ||
|
|
(etmr->crtl_sta != ETIMER_CHAN_RUNNING)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
uint32_t duty_val = 0;
|
|
uint32_t period_val = 0;
|
|
uint32_t clk_freq = 0;
|
|
/* all etimer use same src clk */
|
|
if (ctrl->etimer_clk_src == SDRV_ETIMR_AHF_CLK) {
|
|
clk_freq = sdrv_ckgen_get_rate(CLK_NODE(g_ckgen_ip_xtrg));
|
|
} else if (ctrl->etimer_clk_src == SDRV_ETIMR_LP_CLK) {
|
|
/* LP_CLK : 24M */
|
|
clk_freq = 24000000;
|
|
} else {
|
|
clk_freq = sdrv_ckgen_get_rate(CLK_NODE(g_ckgen_ip_etmr1));
|
|
}
|
|
if (etmr->cpt_read_flag == false) {
|
|
uint32_t duty_cnt = sdrv_etimer_lld_get_cpt0_cnt0(etmr->base, cpt_chn);
|
|
uint32_t period_cnt =
|
|
sdrv_etimer_lld_get_cpt1_cnt0(etmr->base, cpt_chn);
|
|
duty_val = sdrv_etimer_val_to_ns(clk_freq, duty_cnt, ctrl->etimer_clk_div);
|
|
period_val = sdrv_etimer_val_to_ns(clk_freq, period_cnt, ctrl->etimer_clk_div);
|
|
etmr->cpt_read_flag = true;
|
|
}
|
|
|
|
state->duty1 = duty_val;
|
|
state->period = period_val;
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief etimer pwm set initial putput status.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
* @param[in] cmp0_init etimer cmp0 initial out status
|
|
* @param[in] cmp1_init etimer cmp1 initial out status
|
|
*/
|
|
status_t sdrv_etimer_compare_pwm_initial_out_status(sdrv_etimer_t *etmr,
|
|
bool cmp0_init, bool cmp1_init)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_chn_id_e cmp_chn = etmr->channel;
|
|
|
|
if (etmr->mode != ETIMER_PWM_GENERATE) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
etimer_cmp_init_status_t cmp_init_sta;
|
|
memset(&cmp_init_sta, 0, sizeof(cmp_init_sta));
|
|
cmp_init_sta.init_status_x0 = cmp0_init;
|
|
cmp_init_sta.init_status_x1 = cmp1_init;
|
|
sdrv_etimer_lld_cmp_init_status(etmr->base, cmp_chn, &cmp_init_sta);
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief etimer pwm state config.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
* @param[in] cmp_cfg etimer cmp common config
|
|
* @param[in] state pwm duty and period
|
|
*/
|
|
status_t sdrv_etimer_compare_pwm_config(sdrv_etimer_t *etmr,
|
|
sdrv_etimer_cmp_cfg_t *cmp_cfg,
|
|
const sdrv_etimer_pwm_state_t *state)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
ASSERT(cmp_cfg != NULL);
|
|
ASSERT(state != NULL);
|
|
sdrv_etimer_controller_t *ctrl = etmr->controller;
|
|
ASSERT(ctrl != NULL);
|
|
sdrv_etimer_chn_id_e cmp_chn = etmr->channel;
|
|
|
|
/* check pwm signal value */
|
|
if ((state->duty1) > (state->period) ||
|
|
(state->duty2) > (state->period)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
if ((etmr->mode != ETIMER_PWM_GENERATE) ||
|
|
(etmr->crtl_sta != ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
if (etmr->use_g0_cnt == true) {
|
|
if (ctrl->g0_mode == G0_FOR_TIMER) {
|
|
/* g0 is used for timer */
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
else if (ctrl->g0_mode == G0_FOR_PWM_GEN) {
|
|
if (state->period != ctrl->g0_period) {
|
|
/* g0 is used but the period is different */
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
}
|
|
}
|
|
|
|
sdrv_etimer_clk_int_set(etmr);
|
|
cmp_config_t cmp_config;
|
|
etimer_cmp_event_mode_t cmp_event_mode;
|
|
memset(&cmp_config, 0, sizeof(cmp_config));
|
|
sdrv_etimer_cnt_id_e cmp_cnt_sel;
|
|
|
|
if (etmr->use_g0_cnt == true) {
|
|
cmp_config.cnt_sel = SDRV_ETIMR_CMP_CNT_G0;
|
|
cmp_cnt_sel = SDRV_ETIMR_CNT_G0;
|
|
}
|
|
else {
|
|
cmp_config.cnt_sel = SDRV_ETIMR_CMP_LCNT;
|
|
cmp_cnt_sel = (sdrv_etimer_cnt_id_e)(cmp_chn + 2);
|
|
}
|
|
uint32_t clk_freq = 0;
|
|
/* all etimer use same src clk */
|
|
if (ctrl->etimer_clk_src == SDRV_ETIMR_AHF_CLK) {
|
|
clk_freq = sdrv_ckgen_get_rate(CLK_NODE(g_ckgen_ip_xtrg));
|
|
} else if (ctrl->etimer_clk_src == SDRV_ETIMR_LP_CLK) {
|
|
/* LP_CLK : 24M */
|
|
clk_freq = 24000000;
|
|
} else {
|
|
clk_freq = sdrv_ckgen_get_rate(CLK_NODE(g_ckgen_ip_etmr1));
|
|
}
|
|
uint32_t period_cnt = 0;
|
|
uint32_t duty_cnt1 = 0;
|
|
uint32_t duty_cnt2 = 0;
|
|
uint32_t dual_period_cnt_left1 = 0;
|
|
uint32_t dual_period_cnt_right1 = 0;
|
|
uint32_t dual_period_cnt_left2 = 0;
|
|
uint32_t dual_period_cnt_right2 = 0;
|
|
#if CONFIG_E3L
|
|
|
|
if (etmr->center_align_mode == true) {
|
|
period_cnt =
|
|
sdrv_etimer_ns_to_val_1(clk_freq, state->period, ctrl->etimer_clk_div) / 2 - 1;
|
|
}
|
|
else {
|
|
#endif
|
|
period_cnt = sdrv_etimer_ns_to_val_1(clk_freq, state->period, ctrl->etimer_clk_div);
|
|
#if CONFIG_E3L
|
|
}
|
|
|
|
#endif
|
|
#if CONFIG_E3L
|
|
|
|
if (etmr->center_align_mode == true || etmr->fre_double_flag == true) {
|
|
/* in double fre mode, dual_period_cnt_right1 set a useless value */
|
|
duty_cnt1 = sdrv_etimer_ns_to_val(clk_freq, (state->duty1) / 2, ctrl->etimer_clk_div);
|
|
dual_period_cnt_left1 = period_cnt + 1 - duty_cnt1;
|
|
dual_period_cnt_right1 = period_cnt - 1;
|
|
}
|
|
else {
|
|
#endif
|
|
duty_cnt1 = sdrv_etimer_ns_to_val(clk_freq, state->duty1, ctrl->etimer_clk_div);
|
|
dual_period_cnt_left1 = (period_cnt + 1) / 2 - duty_cnt1 / 2;
|
|
dual_period_cnt_right1 = (period_cnt + 1) / 2 + duty_cnt1 / 2;
|
|
#if CONFIG_E3L
|
|
}
|
|
|
|
#endif
|
|
duty_cnt2 = sdrv_etimer_ns_to_val(clk_freq, state->duty2, ctrl->etimer_clk_div);
|
|
dual_period_cnt_left2 = (period_cnt + 1) / 2 - duty_cnt2 / 2;
|
|
dual_period_cnt_right2 = (period_cnt + 1) / 2 + duty_cnt2 / 2;
|
|
|
|
cmp_config.out_mode = cmp_cfg->chnl_out_mode;
|
|
cmp_config.con_mode = cmp_cfg->con_mode;
|
|
cmp_config.cmp_mode = cmp_cfg->cmp_mode;
|
|
/* cmp cnt cfg */
|
|
sdrv_etimer_lld_cnt_ovf(etmr->base, cmp_cnt_sel, period_cnt);
|
|
/* pwm cfg -- cmp config */
|
|
cmp_event_mode.cmp_0_ovf_out = SDRV_ETIMR_KEEP;
|
|
cmp_event_mode.cmp_1_ovf_out = SDRV_ETIMR_KEEP;
|
|
#if CONFIG_E3L
|
|
|
|
/* if use center_align_mode , cmp_mode use dual mode only */
|
|
if (etmr->center_align_mode == true) {
|
|
/* in center_align_mode situation, initial status need to set to low
|
|
* level */
|
|
etimer_cmp_init_status_t cmp_init_sta;
|
|
memset(&cmp_init_sta, 0, sizeof(cmp_init_sta));
|
|
cmp_init_sta.init_status_x0 = false;
|
|
cmp_init_sta.init_status_x1 = false;
|
|
sdrv_etimer_lld_cmp_init_status(etmr->base, cmp_chn, &cmp_init_sta);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_00,
|
|
dual_period_cnt_left1);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_01,
|
|
dual_period_cnt_right1);
|
|
|
|
if (etmr->fre_double_flag == true) {
|
|
cmp_event_mode.cmp_00_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
cmp_event_mode.cmp_01_out = SDRV_ETIMR_KEEP;
|
|
}
|
|
else {
|
|
cmp_event_mode.cmp_00_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
cmp_event_mode.cmp_01_out = SDRV_ETIMR_LEVEL_LOW;
|
|
}
|
|
|
|
if (state->duty1 == 0) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_00,
|
|
(period_cnt + 1) / 2);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_01,
|
|
(period_cnt + 1) / 2);
|
|
cmp_event_mode.cmp_00_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
cmp_event_mode.cmp_01_out = SDRV_ETIMR_LEVEL_LOW;
|
|
}
|
|
else if (state->duty1 == state->period) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_00,
|
|
(period_cnt + 1) / 2);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_01,
|
|
(period_cnt + 1) / 2);
|
|
cmp_event_mode.cmp_00_out = SDRV_ETIMR_LEVEL_LOW;
|
|
cmp_event_mode.cmp_01_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
}
|
|
|
|
if (cmp_cfg->chnl_out_mode == SDRV_ETIMR_CMP_OUT_CMP0_CMP1) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_10,
|
|
dual_period_cnt_left2);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_11,
|
|
dual_period_cnt_right2);
|
|
cmp_event_mode.cmp_10_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
cmp_event_mode.cmp_11_out = SDRV_ETIMR_LEVEL_LOW;
|
|
|
|
if (state->duty2 == (state->period) / 2) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_10,
|
|
(period_cnt + 1) / 2);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_11,
|
|
(period_cnt + 1) / 2);
|
|
cmp_event_mode.cmp_10_out = SDRV_ETIMR_LEVEL_LOW;
|
|
cmp_event_mode.cmp_11_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
#endif
|
|
|
|
if (cmp_cfg->cmp_mode == SDRV_ETIMR_CMP_SINGLE) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_00,
|
|
duty_cnt1);
|
|
cmp_event_mode.cmp_00_out = SDRV_ETIMR_LEVEL_LOW;
|
|
cmp_event_mode.cmp_0_ovf_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
|
|
if (cmp_cfg->chnl_out_mode == SDRV_ETIMR_CMP_OUT_CMP0_CMP1) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_10,
|
|
duty_cnt2);
|
|
cmp_event_mode.cmp_10_out = SDRV_ETIMR_LEVEL_LOW;
|
|
cmp_event_mode.cmp_1_ovf_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
}
|
|
}
|
|
else if (cmp_cfg->cmp_mode == SDRV_ETIMR_CMP_DUAL) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_00,
|
|
dual_period_cnt_left1);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_01,
|
|
dual_period_cnt_right1);
|
|
cmp_event_mode.cmp_00_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
cmp_event_mode.cmp_01_out = SDRV_ETIMR_LEVEL_LOW;
|
|
|
|
if (cmp_cfg->chnl_out_mode == SDRV_ETIMR_CMP_OUT_CMP0_CMP1) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_10,
|
|
dual_period_cnt_left2);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_11,
|
|
dual_period_cnt_right2);
|
|
cmp_event_mode.cmp_10_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
cmp_event_mode.cmp_11_out = SDRV_ETIMR_LEVEL_LOW;
|
|
}
|
|
}
|
|
|
|
#if CONFIG_E3L
|
|
}
|
|
|
|
#endif
|
|
sdrv_etimer_lld_cmp_val_upd(etmr->base, cmp_chn);
|
|
sdrv_etimer_lld_out_mode(etmr->base, cmp_chn, &cmp_event_mode);
|
|
|
|
#if CONFIG_E3L
|
|
|
|
if (etmr->center_align_mode == true) {
|
|
if (etmr->use_g0_cnt == true) {
|
|
basic_cnt_config_t basic_cnt_cfg;
|
|
memset(&basic_cnt_cfg, 0, sizeof(basic_cnt_cfg));
|
|
basic_cnt_cfg.ovf_rst_dis = true;
|
|
sdrv_etimer_lld_basic_cnt_cfg(etmr->base, cmp_cnt_sel,
|
|
&basic_cnt_cfg);
|
|
}
|
|
else {
|
|
local_cnt_config_t local_cnt_cfg;
|
|
memset(&local_cnt_cfg, 0, sizeof(local_cnt_cfg));
|
|
local_cnt_cfg.ovf_rst_dis = true;
|
|
sdrv_etimer_lld_local_cnt_cfg(etmr->base, cmp_cnt_sel,
|
|
&local_cnt_cfg);
|
|
}
|
|
|
|
sdrv_etimer_lld_cnt_center_align_en(etmr->base, cmp_cnt_sel, true);
|
|
sdrv_etimer_lld_cmp_center_align_en(etmr->base, cmp_chn, true);
|
|
}
|
|
|
|
#endif
|
|
sdrv_etimer_lld_cmp_cfg(etmr->base, cmp_chn, &cmp_config);
|
|
sdrv_etimer_lld_cmp_config_set(etmr->base, cmp_chn);
|
|
|
|
ctrl->base = etmr->base;
|
|
|
|
if (etmr->use_g0_cnt == true) {
|
|
ctrl->g0_mode = G0_FOR_PWM_GEN;
|
|
ctrl->g0_period = state->period;
|
|
}
|
|
|
|
ctrl->etimer_bank[cmp_chn + 4] = etmr;
|
|
|
|
if ((cmp_cfg->cmp_mode == SDRV_ETIMR_CMP_SINGLE) ||
|
|
(cmp_cfg->cmp_mode == SDRV_ETIMR_CMP_DUAL)) {
|
|
etmr->crtl_sta = ETIMER_CHAN_INIT;
|
|
}
|
|
|
|
if ((etmr->irq > 0) && (etmr->int_en == true) ) {
|
|
irq_attach(etmr->irq, sdrv_etimer_irq_handle, ctrl);
|
|
irq_enable(etmr->irq);
|
|
}
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief etimer pwm config update.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
* @param[in] cmp_cfg etimer cmp common config
|
|
* @param[in] state pwm duty and period
|
|
*/
|
|
status_t sdrv_etimer_compare_pwm_config_update(sdrv_etimer_t *etmr,
|
|
sdrv_etimer_cmp_cfg_t *cmp_cfg,
|
|
const sdrv_etimer_pwm_state_t *state)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
ASSERT(cmp_cfg != NULL);
|
|
ASSERT(state != NULL);
|
|
sdrv_etimer_controller_t *ctrl = etmr->controller;
|
|
ASSERT(ctrl != NULL);
|
|
sdrv_etimer_chn_id_e cmp_chn = etmr->channel;
|
|
|
|
/* check pwm signal value */
|
|
if ((state->duty1) > (state->period) ||
|
|
(state->duty2) > (state->period)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
if ((etmr->mode != ETIMER_PWM_GENERATE) ||
|
|
(etmr->crtl_sta == ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
/* clear fifo first */
|
|
sdrv_etimer_lld_clear_fifo(etmr->base, cmp_chn);
|
|
cmp_config_t cmp_config;
|
|
etimer_cmp_event_mode_t cmp_event_mode;
|
|
memset(&cmp_config, 0, sizeof(cmp_config));
|
|
sdrv_etimer_cnt_id_e cmp_cnt_sel;
|
|
|
|
if (etmr->use_g0_cnt == true) {
|
|
cmp_config.cnt_sel = SDRV_ETIMR_CMP_CNT_G0;
|
|
cmp_cnt_sel = SDRV_ETIMR_CNT_G0;
|
|
}
|
|
else {
|
|
cmp_config.cnt_sel = SDRV_ETIMR_CMP_LCNT;
|
|
cmp_cnt_sel = (sdrv_etimer_cnt_id_e)(cmp_chn + 2);
|
|
}
|
|
uint32_t clk_freq = 0;
|
|
/* all etimer use same src clk */
|
|
if (ctrl->etimer_clk_src == SDRV_ETIMR_AHF_CLK) {
|
|
clk_freq = sdrv_ckgen_get_rate(CLK_NODE(g_ckgen_ip_xtrg));
|
|
} else if (ctrl->etimer_clk_src == SDRV_ETIMR_LP_CLK) {
|
|
/* LP_CLK : 24M */
|
|
clk_freq = 24000000;
|
|
} else {
|
|
clk_freq = sdrv_ckgen_get_rate(CLK_NODE(g_ckgen_ip_etmr1));
|
|
}
|
|
uint32_t period_cnt = 0;
|
|
uint32_t duty_cnt1 = 0;
|
|
uint32_t duty_cnt2 = 0;
|
|
uint32_t dual_period_cnt_left1 = 0;
|
|
uint32_t dual_period_cnt_right1 = 0;
|
|
uint32_t dual_period_cnt_left2 = 0;
|
|
uint32_t dual_period_cnt_right2 = 0;
|
|
#if CONFIG_E3L
|
|
|
|
if (etmr->center_align_mode == true) {
|
|
period_cnt =
|
|
sdrv_etimer_ns_to_val_1(clk_freq, state->period, ctrl->etimer_clk_div) / 2 - 1;
|
|
}
|
|
else {
|
|
#endif
|
|
period_cnt = sdrv_etimer_ns_to_val_1(clk_freq, state->period, ctrl->etimer_clk_div);
|
|
#if CONFIG_E3L
|
|
}
|
|
|
|
#endif
|
|
#if CONFIG_E3L
|
|
|
|
if (etmr->center_align_mode == true || etmr->fre_double_flag == true) {
|
|
/* in double fre mode, dual_period_cnt_right1 set a useless value */
|
|
duty_cnt1 = sdrv_etimer_ns_to_val(clk_freq, (state->duty1) / 2, ctrl->etimer_clk_div);
|
|
dual_period_cnt_left1 = period_cnt + 1 - duty_cnt1;
|
|
dual_period_cnt_right1 = period_cnt - 1;
|
|
}
|
|
else {
|
|
#endif
|
|
duty_cnt1 = sdrv_etimer_ns_to_val(clk_freq, state->duty1, ctrl->etimer_clk_div);
|
|
dual_period_cnt_left1 = (period_cnt + 1) / 2 - duty_cnt1 / 2;
|
|
dual_period_cnt_right1 = (period_cnt + 1) / 2 + duty_cnt1 / 2;
|
|
#if CONFIG_E3L
|
|
}
|
|
|
|
#endif
|
|
duty_cnt2 = sdrv_etimer_ns_to_val(clk_freq, state->duty2, ctrl->etimer_clk_div);
|
|
dual_period_cnt_left2 = (period_cnt + 1) / 2 - duty_cnt2 / 2;
|
|
dual_period_cnt_right2 = (period_cnt + 1) / 2 + duty_cnt2 / 2;
|
|
|
|
cmp_config.out_mode = cmp_cfg->chnl_out_mode;
|
|
cmp_config.con_mode = cmp_cfg->con_mode;
|
|
cmp_config.cmp_mode = cmp_cfg->cmp_mode;
|
|
/* cmp cnt cfg */
|
|
sdrv_etimer_lld_cnt_ovf(etmr->base, cmp_cnt_sel, period_cnt);
|
|
/* pwm cfg -- cmp config */
|
|
cmp_event_mode.cmp_0_ovf_out = SDRV_ETIMR_KEEP;
|
|
cmp_event_mode.cmp_1_ovf_out = SDRV_ETIMR_KEEP;
|
|
#if CONFIG_E3L
|
|
|
|
/* if use center_align_mode , cmp_mode use dual mode only */
|
|
if (etmr->center_align_mode == true) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_00,
|
|
dual_period_cnt_left1);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_01,
|
|
dual_period_cnt_right1);
|
|
|
|
if (etmr->fre_double_flag == true) {
|
|
cmp_event_mode.cmp_00_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
cmp_event_mode.cmp_01_out = SDRV_ETIMR_KEEP;
|
|
}
|
|
else {
|
|
cmp_event_mode.cmp_00_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
cmp_event_mode.cmp_01_out = SDRV_ETIMR_LEVEL_LOW;
|
|
}
|
|
|
|
if (state->duty1 == 0) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_00,
|
|
(period_cnt + 1) / 2);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_01,
|
|
(period_cnt + 1) / 2);
|
|
cmp_event_mode.cmp_00_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
cmp_event_mode.cmp_01_out = SDRV_ETIMR_LEVEL_LOW;
|
|
}
|
|
else if (state->duty1 == state->period) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_00,
|
|
(period_cnt + 1) / 2);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_01,
|
|
(period_cnt + 1) / 2);
|
|
cmp_event_mode.cmp_00_out = SDRV_ETIMR_LEVEL_LOW;
|
|
cmp_event_mode.cmp_01_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
}
|
|
|
|
if (cmp_cfg->chnl_out_mode == SDRV_ETIMR_CMP_OUT_CMP0_CMP1) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_10,
|
|
dual_period_cnt_left2);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_11,
|
|
dual_period_cnt_right2);
|
|
cmp_event_mode.cmp_10_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
cmp_event_mode.cmp_11_out = SDRV_ETIMR_LEVEL_LOW;
|
|
}
|
|
|
|
if (state->duty2 == (state->period) / 2) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_10,
|
|
(period_cnt + 1) / 2);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_11,
|
|
(period_cnt + 1) / 2);
|
|
cmp_event_mode.cmp_10_out = SDRV_ETIMR_LEVEL_LOW;
|
|
cmp_event_mode.cmp_11_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
}
|
|
}
|
|
else {
|
|
#endif
|
|
|
|
if (cmp_cfg->cmp_mode == SDRV_ETIMR_CMP_SINGLE) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_00,
|
|
duty_cnt1);
|
|
cmp_event_mode.cmp_00_out = SDRV_ETIMR_LEVEL_LOW;
|
|
cmp_event_mode.cmp_0_ovf_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
|
|
if (cmp_cfg->chnl_out_mode == SDRV_ETIMR_CMP_OUT_CMP0_CMP1) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_10,
|
|
duty_cnt2);
|
|
cmp_event_mode.cmp_10_out = SDRV_ETIMR_LEVEL_LOW;
|
|
cmp_event_mode.cmp_1_ovf_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
}
|
|
}
|
|
else if (cmp_cfg->cmp_mode == SDRV_ETIMR_CMP_DUAL) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_00,
|
|
dual_period_cnt_left1);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_01,
|
|
dual_period_cnt_right1);
|
|
cmp_event_mode.cmp_00_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
cmp_event_mode.cmp_01_out = SDRV_ETIMR_LEVEL_LOW;
|
|
|
|
if (cmp_cfg->chnl_out_mode == SDRV_ETIMR_CMP_OUT_CMP0_CMP1) {
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_10,
|
|
dual_period_cnt_left2);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_11,
|
|
dual_period_cnt_right2);
|
|
cmp_event_mode.cmp_10_out = SDRV_ETIMR_LEVEL_HIGH;
|
|
cmp_event_mode.cmp_11_out = SDRV_ETIMR_LEVEL_LOW;
|
|
}
|
|
}
|
|
|
|
#if CONFIG_E3L
|
|
}
|
|
|
|
#endif
|
|
|
|
if (etmr->use_g0_cnt == true) {
|
|
ctrl->g0_period = state->period;
|
|
}
|
|
|
|
sdrv_etimer_lld_cmp_val_upd(etmr->base, cmp_chn);
|
|
sdrv_etimer_lld_out_mode(etmr->base, cmp_chn, &cmp_event_mode);
|
|
sdrv_etimer_lld_cmp_cfg(etmr->base, cmp_chn, &cmp_config);
|
|
sdrv_etimer_lld_cmp_config_set(etmr->base, cmp_chn);
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief configure etimer pwm output dma enable (dma_en must after pwm config)
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
* @param[in] wml water mark level (range : 1-15)
|
|
*/
|
|
status_t sdrv_etimer_compare_pwm_dma_en(sdrv_etimer_t *etmr, uint16_t wml)
|
|
{
|
|
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_controller_t *ctrl = etmr->controller;
|
|
ASSERT(ctrl != NULL);
|
|
sdrv_etimer_chn_id_e cmp_chn = etmr->channel;
|
|
|
|
if ((etmr->mode != ETIMER_PWM_GENERATE) ||
|
|
(etmr->crtl_sta == ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
/* water mark level (range : 1-15) */
|
|
if ((wml == 0) || (wml > 0xF)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
/* set dma wml */
|
|
sdrv_etimer_lld_dma_wml(etmr->base, cmp_chn, wml);
|
|
chn_etimer_dma_ctrl_t dma_config;
|
|
memset(&dma_config, 0, sizeof(dma_config));
|
|
/* select dma block */
|
|
dma_config.block_sel = SDRV_ETIMR_CMP_BLOCK;
|
|
/* enable dma */
|
|
dma_config.chn_en = 1;
|
|
sdrv_etimer_lld_dma_chn_cfg(etmr->base, cmp_chn, &dma_config);
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief configure multi compare mode.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
* @param[in] multi_cmp etimer multi cmp config
|
|
*/
|
|
status_t sdrv_etimer_compare_multi_mode(sdrv_etimer_t *etmr,
|
|
sdrv_etimer_multi_cmp_val_t *multi_cmp)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_controller_t *ctrl = etmr->controller;
|
|
ASSERT(ctrl != NULL);
|
|
sdrv_etimer_chn_id_e cmp_chn = etmr->channel;
|
|
|
|
if ((etmr->mode != ETIMER_PWM_GENERATE) ||
|
|
(etmr->crtl_sta != ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
/* pwm config api first */
|
|
sdrv_etimer_cmp_mode_e cmp_mode =
|
|
(sdrv_etimer_cmp_mode_e)sdrv_etimer_lld_get_cmp_mode(etmr->base,
|
|
cmp_chn);
|
|
|
|
if (cmp_mode != SDRV_ETIMR_CMP_MULTI) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
uint32_t clk_freq = 0;
|
|
/* all etimer use same src clk */
|
|
if (ctrl->etimer_clk_src == SDRV_ETIMR_AHF_CLK) {
|
|
clk_freq = sdrv_ckgen_get_rate(CLK_NODE(g_ckgen_ip_xtrg));
|
|
} else if (ctrl->etimer_clk_src == SDRV_ETIMR_LP_CLK) {
|
|
/* LP_CLK : 24M */
|
|
clk_freq = 24000000;
|
|
} else {
|
|
clk_freq = sdrv_ckgen_get_rate(CLK_NODE(g_ckgen_ip_etmr1));
|
|
}
|
|
uint32_t cmp00_cnt =
|
|
sdrv_etimer_ns_to_val(clk_freq, multi_cmp->cmp00_val, ctrl->etimer_clk_div);
|
|
uint32_t cmp01_cnt =
|
|
sdrv_etimer_ns_to_val(clk_freq, multi_cmp->cmp01_val, ctrl->etimer_clk_div);
|
|
uint32_t cmp10_cnt =
|
|
sdrv_etimer_ns_to_val(clk_freq, multi_cmp->cmp10_val, ctrl->etimer_clk_div);
|
|
uint32_t cmp11_cnt =
|
|
sdrv_etimer_ns_to_val(clk_freq, multi_cmp->cmp11_val, ctrl->etimer_clk_div);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_00, cmp00_cnt);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_01, cmp01_cnt);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_10, cmp10_cnt);
|
|
sdrv_etimer_lld_cmp_val(etmr->base, cmp_chn, SDRV_ETIMR_CMP_11, cmp11_cnt);
|
|
|
|
etmr->crtl_sta = ETIMER_CHAN_INIT;
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief start to generate etimer pwm signal.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
*/
|
|
status_t sdrv_etimer_compare_pwm_start(sdrv_etimer_t *etmr)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_chn_id_e cmp_chn = etmr->channel;
|
|
|
|
if ((etmr->mode != ETIMER_PWM_GENERATE) ||
|
|
(etmr->crtl_sta == ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
sdrv_etimer_cnt_id_e cmp_cnt_sel;
|
|
|
|
if (etmr->use_g0_cnt == true) {
|
|
cmp_cnt_sel = SDRV_ETIMR_CNT_G0;
|
|
}
|
|
else {
|
|
cmp_cnt_sel = (sdrv_etimer_cnt_id_e)(cmp_chn + 2);
|
|
}
|
|
|
|
/* reset the counter to 0 */
|
|
sdrv_etimer_lld_cnt_frc_rld(etmr->base, cmp_cnt_sel);
|
|
sdrv_etimer_lld_cmp_en(etmr->base, cmp_chn, true);
|
|
sdrv_etimer_lld_cnt_en(etmr->base, cmp_cnt_sel, true);
|
|
etmr->crtl_sta = ETIMER_CHAN_RUNNING;
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief stop to generate etimer pwm signal.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
*/
|
|
status_t sdrv_etimer_compare_pwm_stop(sdrv_etimer_t *etmr)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_chn_id_e cmp_chn = etmr->channel;
|
|
|
|
if ((etmr->mode != ETIMER_PWM_GENERATE) ||
|
|
(etmr->crtl_sta == ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
sdrv_etimer_cnt_id_e cmp_cnt_sel;
|
|
|
|
if (etmr->use_g0_cnt == true) {
|
|
cmp_cnt_sel = SDRV_ETIMR_CNT_G0;
|
|
}
|
|
else {
|
|
cmp_cnt_sel = (sdrv_etimer_cnt_id_e)(cmp_chn + 2);
|
|
}
|
|
|
|
sdrv_etimer_lld_cmp_en(etmr->base, cmp_chn, false);
|
|
sdrv_etimer_lld_cnt_en(etmr->base, cmp_cnt_sel, false);
|
|
etmr->crtl_sta = ETIMER_CHAN_STOP;
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief etimer quad config.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
* @param[in] quad_ctrl etimer quad config
|
|
*/
|
|
status_t sdrv_etimer_quad_config(sdrv_etimer_t *etmr, quad_ctrl_t *quad_ctrl)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_chn_id_e cpt_chn = etmr->channel;
|
|
|
|
if (cpt_chn != SDRV_ETIMR_CHN_A) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
if ((etmr->mode != ETIMER_PWM_OTHERS) ||
|
|
(etmr->crtl_sta != ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
sdrv_etimer_lld_cpt_quad_ctrl(etmr->base, quad_ctrl);
|
|
sdrv_etimer_lld_lcnt_sig_en(etmr->base, SDRV_ETIMR_LCNT_A, true);
|
|
sdrv_etimer_lld_cpt_quad_en(etmr->base, true);
|
|
etmr->crtl_sta = ETIMER_CHAN_INIT;
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief start etimer config.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
*/
|
|
status_t sdrv_etimer_quad_start(sdrv_etimer_t *etmr)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_chn_id_e cpt_chn = etmr->channel;
|
|
|
|
if (cpt_chn != SDRV_ETIMR_CHN_A) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
if ((etmr->mode != ETIMER_PWM_OTHERS) ||
|
|
(etmr->crtl_sta == ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
sdrv_etimer_lld_cpt_en(etmr->base, SDRV_ETIMR_CHN_A, true);
|
|
sdrv_etimer_lld_cnt_en(etmr->base, SDRV_ETIMR_LCNT_A, true);
|
|
etmr->crtl_sta = ETIMER_CHAN_RUNNING;
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief stop etimer quad.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
*/
|
|
status_t sdrv_etimer_quad_stop(sdrv_etimer_t *etmr)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_chn_id_e cpt_chn = etmr->channel;
|
|
|
|
if (cpt_chn != SDRV_ETIMR_CHN_A) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
if ((etmr->mode != ETIMER_PWM_OTHERS) ||
|
|
(etmr->crtl_sta == ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
sdrv_etimer_lld_cpt_en(etmr->base, SDRV_ETIMR_CHN_A, false);
|
|
sdrv_etimer_lld_cnt_en(etmr->base, SDRV_ETIMR_LCNT_A, false);
|
|
etmr->crtl_sta = ETIMER_CHAN_STOP;
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief get quad dir signal status
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
*/
|
|
bool sdrv_etimer_quad_dir_up(sdrv_etimer_t *etmr)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
uint32_t sig_sta = sdrv_etimer_lld_get_sig_status(etmr->base);
|
|
bool dir_up = false;
|
|
|
|
/* bit 17 : cpt_a_dir */
|
|
if (sig_sta & (0x1U << 17)) {
|
|
dir_up = false;
|
|
}
|
|
else {
|
|
dir_up = true;
|
|
}
|
|
|
|
return dir_up;
|
|
}
|
|
|
|
/**
|
|
* @brief configure etimer filter config
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
* @param[in] filter_cfg filter_cfg
|
|
*/
|
|
status_t sdrv_etimer_filter_config(sdrv_etimer_t *etmr, flt_config_t *filter_cfg)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_chn_id_e cpt_chn = etmr->channel;
|
|
|
|
/* filter function is used to quad or capture */
|
|
if ((etmr->mode != ETIMER_PWM_OTHERS) &&
|
|
(etmr->mode != ETIMER_PWM_CAPTURE)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
sdrv_etimer_lld_cpt_flt_cfg(etmr->base, cpt_chn, filter_cfg);
|
|
sdrv_etimer_lld_cpt_flt_en(etmr->base, cpt_chn, true);
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/* icu function */
|
|
/**
|
|
* @brief configure etimer icu config
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
* @param[in] edge_sel capture edge select
|
|
*/
|
|
status_t sdrv_etimer_icu_config(sdrv_etimer_t *etmr,
|
|
sdrv_etimer_cpt_trig_mode_e edge_sel)
|
|
{
|
|
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_controller_t *ctrl = etmr->controller;
|
|
ASSERT(ctrl != NULL);
|
|
sdrv_etimer_chn_id_e cpt_chn = etmr->channel;
|
|
|
|
if ((etmr->mode != ETIMER_ICU_FUNC) ||
|
|
(etmr->crtl_sta != ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
sdrv_etimer_clk_int_set(etmr);
|
|
/* clear fifo first */
|
|
sdrv_etimer_lld_clear_fifo(etmr->base, cpt_chn);
|
|
cpt_config_t cpt_config;
|
|
local_cnt_config_t local_cnt_config;
|
|
memset(&cpt_config, 0, sizeof(cpt_config));
|
|
memset(&local_cnt_config, 0, sizeof(local_cnt_config));
|
|
/* capture cnt config */
|
|
sdrv_etimer_cnt_id_e cpt_cnt_sel = (sdrv_etimer_cnt_id_e)(cpt_chn + 2);
|
|
/* set local cnt ovf val 0xFFFFFFFF */
|
|
sdrv_etimer_lld_cnt_ovf(etmr->base, cpt_cnt_sel, 0xFFFFFFFF);
|
|
local_cnt_config.no_stop_mode = true;
|
|
sdrv_etimer_lld_local_cnt_cfg(etmr->base, cpt_cnt_sel, &local_cnt_config);
|
|
/* cpt_config */
|
|
cpt_config.cnt_sel = SDRV_ETIMR_CPT_LCNT;
|
|
cpt_config.con_mode = SDRV_ETIMR_CPT_CONSECTIVE;
|
|
cpt_config.dual_mode = SDRV_ETIMR_CPT_CPT0;
|
|
cpt_config.cpt0_trig_mode = edge_sel;
|
|
sdrv_etimer_lld_cpt_cfg(etmr->base, cpt_chn, &cpt_config);
|
|
sdrv_etimer_lld_cpt_config_set(etmr->base, cpt_chn);
|
|
|
|
ctrl->base = etmr->base;
|
|
ctrl->etimer_bank[cpt_chn] = etmr;
|
|
etmr->crtl_sta = ETIMER_CHAN_INIT;
|
|
|
|
if (etmr->irq > 0) {
|
|
irq_attach(etmr->irq, sdrv_etimer_irq_handle, ctrl);
|
|
irq_enable(etmr->irq);
|
|
}
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief configure etimer icu dma enable (dma_en must after icu config)
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
* @param[in] wml water mark level (range : 1-15)
|
|
*/
|
|
status_t sdrv_etimer_icu_dma_en(sdrv_etimer_t *etmr, uint16_t wml)
|
|
{
|
|
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_controller_t *ctrl = etmr->controller;
|
|
ASSERT(ctrl != NULL);
|
|
sdrv_etimer_chn_id_e cpt_chn = etmr->channel;
|
|
|
|
if ((etmr->mode != ETIMER_ICU_FUNC) ||
|
|
(etmr->crtl_sta == ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
/* water mark level (range : 1-15) */
|
|
if ((wml == 0) || (wml > 0xF)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
/* dma mode don't need cpt interrupt */
|
|
sdrv_etimer_lld_int_en(etmr->base, ETMR_BM_INT_STA_EN_CPT(etmr->channel),
|
|
false);
|
|
/* set dma wml */
|
|
sdrv_etimer_lld_dma_wml(etmr->base, cpt_chn, wml);
|
|
chn_etimer_dma_ctrl_t dma_config;
|
|
memset(&dma_config, 0, sizeof(dma_config));
|
|
/* select dma block */
|
|
dma_config.block_sel = SDRV_ETIMR_CPT_BLOCK;
|
|
/* enable dma */
|
|
dma_config.chn_en = 1;
|
|
sdrv_etimer_lld_dma_chn_cfg(etmr->base, cpt_chn, &dma_config);
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief start etimer icu chan.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
*/
|
|
status_t sdrv_etimer_icu_start(sdrv_etimer_t *etmr)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_chn_id_e cpt_chn = etmr->channel;
|
|
sdrv_etimer_cnt_id_e cpt_cnt_sel = (sdrv_etimer_cnt_id_e)(cpt_chn + 2);
|
|
|
|
if ((etmr->mode != ETIMER_ICU_FUNC) ||
|
|
(etmr->crtl_sta == ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
/* reset the counter to 0 */
|
|
sdrv_etimer_lld_cnt_frc_rld(etmr->base, cpt_cnt_sel);
|
|
sdrv_etimer_lld_cpt_en(etmr->base, cpt_chn, true);
|
|
sdrv_etimer_lld_cnt_en(etmr->base, cpt_cnt_sel, true);
|
|
etmr->crtl_sta = ETIMER_CHAN_RUNNING;
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief stop etimer icu chan.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
*/
|
|
status_t sdrv_etimer_icu_stop(sdrv_etimer_t *etmr)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_chn_id_e cpt_chn = etmr->channel;
|
|
sdrv_etimer_cnt_id_e cpt_cnt_sel = (sdrv_etimer_cnt_id_e)(cpt_chn + 2);
|
|
|
|
if ((etmr->mode != ETIMER_ICU_FUNC) ||
|
|
(etmr->crtl_sta == ETIMER_CHAN_UNINIT)) {
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
sdrv_etimer_lld_cnt_en(etmr->base, cpt_cnt_sel, false);
|
|
sdrv_etimer_lld_cpt_en(etmr->base, cpt_chn, false);
|
|
etmr->crtl_sta = ETIMER_CHAN_STOP;
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief stop etimer icu get capture timestamp.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
* @return cpt_val : capture val
|
|
*/
|
|
uint32_t sdrv_etimer_icu_get_cnt_val(sdrv_etimer_t *etmr)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_chn_id_e cpt_chn = etmr->channel;
|
|
|
|
if (etmr->mode != ETIMER_ICU_FUNC) {
|
|
return 0;
|
|
}
|
|
|
|
uint32_t cpt_val = sdrv_etimer_lld_get_cpt0_cnt0(etmr->base, cpt_chn);
|
|
return cpt_val;
|
|
}
|
|
|
|
/**
|
|
* @brief stop etimer icu get channel level status.
|
|
*
|
|
* @param[in] etmr etimer ctrl instance
|
|
* @return high level : true low level : false
|
|
*/
|
|
bool sdrv_etimer_icu_get_level(sdrv_etimer_t *etmr)
|
|
{
|
|
ASSERT(etmr != NULL);
|
|
sdrv_etimer_chn_id_e cpt_chn = etmr->channel;
|
|
uint32_t sig_sta = sdrv_etimer_lld_get_sig_status(etmr->base);
|
|
bool level_sta = false;
|
|
|
|
/* bit 16/20/24/28 : capture a/b/c/d signal status */
|
|
if (sig_sta & (0x1 << (16 + (0x4 * cpt_chn)))) {
|
|
level_sta = true;
|
|
}
|
|
|
|
return level_sta;
|
|
} |