diff --git a/t3_os/armino/middleware/driver/pwm/v1px/pwm_driver.c b/t3_os/armino/middleware/driver/pwm/v1px/pwm_driver.c index ee0f10fe..7a9d5c06 100755 --- a/t3_os/armino/middleware/driver/pwm/v1px/pwm_driver.c +++ b/t3_os/armino/middleware/driver/pwm/v1px/pwm_driver.c @@ -208,6 +208,7 @@ static void pwm_chan_init_common(pwm_chan_t sw_ch) { pwm_id_t id; pwm_ch_t hw_ch; + uint32_t soft_reset = 0; pwm_sw_ch_to_hw_id_ch(sw_ch, &id, &hw_ch); s_pwm[id].chan_init_bits |= BIT(hw_ch); @@ -225,6 +226,10 @@ static void pwm_chan_init_common(pwm_chan_t sw_ch) } pwm_chan_init_gpio(sw_ch); + soft_reset = pwm_hal_get_cg_reset_soft_reset(&s_pwm[id].hal); + if (0 == soft_reset) { + pwm_hal_set_cg_reset_soft_reset(&s_pwm[id].hal, 1); + } } static void pwm_chan_deinit_common(pwm_chan_t sw_ch) @@ -546,6 +551,7 @@ bk_err_t bk_pwm_init(pwm_chan_t sw_ch, const pwm_init_config_t *config) pwm_sw_ch_to_hw_id_ch(sw_ch, &id, &hw_ch); PWM_RETURN_ON_INVALID_CHAN(hw_ch); + PWM_PM_CHECK_RESTORE(id); if (!pwm_driver_duty_is_valid(config->period_cycle, config->duty_cycle, config->duty2_cycle, config->duty3_cycle)) @@ -730,6 +736,7 @@ bk_err_t bk_pwm_set_period_duty(pwm_chan_t sw_ch, pwm_period_duty_config_t *conf config->duty2_cycle, config->duty3_cycle)) return BK_ERR_PWM_PERIOD_DUTY; + PWM_PM_CHECK_RESTORE(id); pwm_hal_set_new_config_way(&s_pwm[id].hal, hw_ch, 1); /* duty ratio is 0% */ @@ -1101,21 +1108,24 @@ static void pwm_group_init_with_any_channel(const pwm_group_init_config_t *confi { pwm_id_t id1, id2; pwm_ch_t hw_ch1, hw_ch2; - pwm_period_duty_config_t pwm_config; + pwm_period_duty_config_t pwm_config = {0}; pwm_sw_ch_to_hw_id_ch(config->chan1, &id1, &hw_ch1); pwm_sw_ch_to_hw_id_ch(config->chan2, &id2, &hw_ch2); + pwm_config.psc = 0; pwm_config.period_cycle = config->period_cycle; pwm_config.duty_cycle = config->chan1_duty_cycle; pwm_config.duty2_cycle = 0; pwm_config.duty3_cycle = 0; + pwm_hal_set_new_config_way(&s_pwm[id1].hal, hw_ch1, 0); pwm_set_channel_config(config->chan1, &pwm_config); pwm_hal_set_flip_mode(&s_pwm[id1].hal, hw_ch1, 3); pwm_hal_set_init_signal_high(&s_pwm[id1].hal, hw_ch1); pwm_config.duty_cycle = config->chan1_duty_cycle + dead_cycle; pwm_config.duty2_cycle = config->chan2_duty_cycle + pwm_config.duty_cycle; + pwm_hal_set_new_config_way(&s_pwm[id2].hal, hw_ch2, 0); pwm_set_channel_config(config->chan2, &pwm_config); pwm_hal_set_flip_mode(&s_pwm[id2].hal, hw_ch2, 1); pwm_hal_set_init_signal_low(&s_pwm[id2].hal, hw_ch2); @@ -1127,6 +1137,8 @@ bk_err_t bk_pwm_group_init(const pwm_group_init_config_t *config, pwm_group_t *g { PWM_RETURN_ON_NOT_INIT(); BK_RETURN_ON_NULL(group); + PWM_PM_CHECK_RESTORE(PWM_ID_0); + PWM_PM_CHECK_RESTORE(PWM_ID_1); uint32_t dead_cycle = 0; int ret; @@ -1139,13 +1151,17 @@ bk_err_t bk_pwm_group_init(const pwm_group_init_config_t *config, pwm_group_t *g return ret; } - dead_cycle = (config->period_cycle - config->chan1_duty_cycle - config->chan2_duty_cycle) >> 1; + pwm_chan_init_common(config->chan1); pwm_chan_init_common(config->chan2); if (pwm_chan_is_default_group(config->chan1, config->chan2)) { PWM_LOGI("use hardware default group\r\n"); - pwm_group_output_mode_config(config, 25, dead_cycle); + if (dead_cycle >= 0x400) { + PWM_LOGE("pwm_group_validate_dead_cycle, dead_cycle:%d\r\n", dead_cycle); + return BK_ERR_PWM_GROUP_DUTY; + } + pwm_group_output_mode_config(config, 0, dead_cycle); } else { PWM_LOGI("configure channels into group mode manually\r\n"); pwm_group_init_with_any_channel(config, dead_cycle); @@ -1231,6 +1247,8 @@ bk_err_t bk_pwm_group_set_config(pwm_group_t group, const pwm_group_config_t *co if (!pwm_group_is_existed(group)) { return BK_ERR_PWM_GROUP_NOT_EXIST; } + PWM_PM_CHECK_RESTORE(PWM_ID_0); + PWM_PM_CHECK_RESTORE(PWM_ID_1); pwm_id_t id1, id2; pwm_ch_t hw_ch1, hw_ch2; diff --git a/tuyaos/tuya_os_adapter/src/driver/tkl_pwm.c b/tuyaos/tuya_os_adapter/src/driver/tkl_pwm.c index 4ce008b5..91009dfd 100755 --- a/tuyaos/tuya_os_adapter/src/driver/tkl_pwm.c +++ b/tuyaos/tuya_os_adapter/src/driver/tkl_pwm.c @@ -2,8 +2,13 @@ #include #include +#define TUYA_PWM_ID_MAX 5 #define __PWM_FREQ2PERIOD(x) ((unsigned int)((26000000.0/x))) +static pwm_group_t pwm_group = PWM_GROUP_ID_INVALID; +static TUYA_PWM_BASE_CFG_T pwm_cfg[TUYA_PWM_ID_MAX] = {{0}}; +static TUYA_PWM_NUM_E mult_chid[2] = {0}; + pwm_chan_t ty_to_bk_pwm(TUYA_PWM_NUM_E ch_id) { pwm_chan_t pwm = PWM_ID_MAX; @@ -45,6 +50,11 @@ OPERATE_RET tkl_pwm_init(TUYA_PWM_NUM_E ch_id, CONST TUYA_PWM_BASE_CFG_T *cfg) pwm_chan_t pwm_port; pwm_init_config_t config = {0}; + if(ch_id >= TUYA_PWM_ID_MAX) { + return OPRT_COM_ERROR; + } + + memcpy(&pwm_cfg[ch_id], cfg, sizeof(TUYA_PWM_BASE_CFG_T)); period = __PWM_FREQ2PERIOD(cfg->frequency); duty = (unsigned int)(cfg->duty / 10000.0 * period); if(cfg->duty && duty == 0) { @@ -57,7 +67,6 @@ OPERATE_RET tkl_pwm_init(TUYA_PWM_NUM_E ch_id, CONST TUYA_PWM_BASE_CFG_T *cfg) config.duty3_cycle = 0; pwm_port = ty_to_bk_pwm(ch_id); - if(bk_pwm_init(pwm_port, &config)) return OPRT_COM_ERROR; @@ -65,11 +74,9 @@ OPERATE_RET tkl_pwm_init(TUYA_PWM_NUM_E ch_id, CONST TUYA_PWM_BASE_CFG_T *cfg) case TUYA_PWM_NEGATIVE: bk_pwm_set_init_signal_low(pwm_port); break; - case TUYA_PWM_POSITIVE: bk_pwm_set_init_signal_high(pwm_port); break; - default: return OPRT_COM_ERROR; break; @@ -89,8 +96,14 @@ OPERATE_RET tkl_pwm_deinit(TUYA_PWM_NUM_E ch_id) { pwm_chan_t pwm_port; + if(ch_id >= TUYA_PWM_ID_MAX) { + return OPRT_COM_ERROR; + } + pwm_port = ty_to_bk_pwm(ch_id); bk_pwm_deinit(pwm_port); + + memset(&pwm_cfg[ch_id], 0, sizeof(TUYA_PWM_BASE_CFG_T)); return OPRT_OK; } @@ -105,6 +118,10 @@ OPERATE_RET tkl_pwm_start(TUYA_PWM_NUM_E ch_id) { pwm_chan_t pwm_port; + if(ch_id >= TUYA_PWM_ID_MAX) { + return OPRT_COM_ERROR; + } + pwm_port = ty_to_bk_pwm(ch_id); bk_pwm_start(pwm_port); @@ -122,12 +139,236 @@ OPERATE_RET tkl_pwm_stop(TUYA_PWM_NUM_E ch_id) { pwm_chan_t pwm_port; + if(ch_id >= TUYA_PWM_ID_MAX) { + return OPRT_COM_ERROR; + } + pwm_port = ty_to_bk_pwm(ch_id); bk_pwm_stop(pwm_port); return OPRT_OK; } +/** + * @brief pwm duty set + * + * @param[in] ch_id: pwm channal id, id index starts at 0 + * @param[in] duty: pwm duty cycle + * + * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h + */ +OPERATE_RET tkl_pwm_duty_set(TUYA_PWM_NUM_E ch_id, UINT32_T duty) +{ + unsigned int period; + unsigned int curr_duty; + pwm_chan_t pwm_port; + pwm_period_duty_config_t config = {0}; + + if(ch_id >= TUYA_PWM_ID_MAX) { + return OPRT_COM_ERROR; + } + + if(duty == pwm_cfg[ch_id].duty) { + return OPRT_OK; + } + + period = __PWM_FREQ2PERIOD(pwm_cfg[ch_id].frequency); + curr_duty = (unsigned int)(duty / 10000.0 * period); + if(pwm_cfg[ch_id].duty && curr_duty == 0) { + curr_duty = 1; + } + + config.period_cycle = period; + config.duty_cycle = curr_duty; + config.duty2_cycle = 0; + config.duty3_cycle = 0; + + pwm_port = ty_to_bk_pwm(ch_id); + if(bk_pwm_set_period_duty(pwm_port, &config)) { + return OPRT_COM_ERROR; + } + + pwm_cfg[ch_id].duty = duty; + + return OPRT_OK; +} + +/** + * @brief pwm frequency set + * + * @param[in] ch_id: pwm channal id, id index starts at 0 + * @param[in] frequency: pwm frequency + * + * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h + */ +OPERATE_RET tkl_pwm_frequency_set(TUYA_PWM_NUM_E ch_id, UINT32_T frequency) +{ + unsigned int period; + unsigned int curr_duty; + pwm_chan_t pwm_port; + pwm_period_duty_config_t config = {0}; + + if(ch_id >= TUYA_PWM_ID_MAX) { + return OPRT_COM_ERROR; + } + + if(frequency == pwm_cfg[ch_id].frequency) { + return OPRT_OK; + } + + period = __PWM_FREQ2PERIOD(frequency); + curr_duty = (unsigned int)(pwm_cfg[ch_id].duty / 10000.0 * period); + if(pwm_cfg[ch_id].duty && curr_duty == 0) { + curr_duty = 1; + } + + config.period_cycle = period; + config.duty_cycle = curr_duty; + config.duty2_cycle = 0; + config.duty3_cycle = 0; + + pwm_port = ty_to_bk_pwm(ch_id); + if(bk_pwm_set_period_duty(pwm_port, &config)) { + return OPRT_COM_ERROR; + } + + pwm_cfg[ch_id].frequency = frequency; + + return OPRT_OK; +} + +/** + * @brief pwm polarity set + * + * @param[in] ch_id: pwm channal id, id index starts at 0 + * @param[in] polarity: pwm polarity + * + * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h + */ +OPERATE_RET tkl_pwm_polarity_set(TUYA_PWM_NUM_E ch_id, TUYA_PWM_POLARITY_E polarity) +{ + pwm_chan_t pwm_port; + + if (ch_id >= TUYA_PWM_ID_MAX) { + return OPRT_INVALID_PARM; + } + + pwm_port = ty_to_bk_pwm(ch_id); + switch (polarity) { + case TUYA_PWM_NEGATIVE: + bk_pwm_set_init_signal_low(pwm_port); + break; + + case TUYA_PWM_POSITIVE: + bk_pwm_set_init_signal_high(pwm_port); + break; + + default: + return OPRT_COM_ERROR; + break; + } + + return OPRT_NOT_SUPPORTED; +} + +/** + * @brief multiple pwm channel start + * + * @param[in] ch_id: pwm channal id list + * @param[in] num : num of pwm channal to start + * + * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h + */ +OPERATE_RET tkl_pwm_multichannel_start(TUYA_PWM_NUM_E *ch_id, UINT8_T num) +{ + unsigned int period; + unsigned int duty[2] = {0}; + + if(num != 2) { + bk_printf("pwm param num is not 2 !!!"); + return OPRT_COM_ERROR; + } + + if (ch_id[0] >= TUYA_PWM_ID_MAX || ch_id[1] >= TUYA_PWM_ID_MAX) { + return OPRT_INVALID_PARM; + } + + if(PWM_GROUP_ID_INVALID == pwm_group) { + pwm_group_init_config_t group_init_cfg; + + mult_chid[0] = ch_id[0]; + mult_chid[1] = ch_id[1]; + + if(pwm_cfg[ch_id[0]].frequency != pwm_cfg[ch_id[1]].frequency) { + bk_printf("frequency is diff !!!"); + return OPRT_COM_ERROR; + } + period = __PWM_FREQ2PERIOD(pwm_cfg[ch_id[0]].frequency); + duty[0] = (unsigned int)(pwm_cfg[ch_id[0]].duty / 10000.0 * period); + if(pwm_cfg[ch_id[0]].duty && duty[0] == 0) { + duty[0] = 1; + } + duty[1] = (unsigned int)(pwm_cfg[ch_id[1]].duty / 10000.0 * period); + if(pwm_cfg[ch_id[1]].duty && duty[1] == 0) { + duty[1] = 1; + } + + group_init_cfg.chan1 = ty_to_bk_pwm(ch_id[0]); + group_init_cfg.chan2 = ty_to_bk_pwm(ch_id[1]); + group_init_cfg.period_cycle = period; + group_init_cfg.chan1_duty_cycle = duty[0]; + group_init_cfg.chan2_duty_cycle = duty[1]; + //bk_printf("chan1:%d, chan2:%d, period_cycle:%d, chan1_duty_cycle:%d, chan2_duty_cycle:%d\r\n", + // group_init_cfg.chan1, group_init_cfg.chan2, group_init_cfg.period_cycle, group_init_cfg.chan1_duty_cycle, group_init_cfg.chan2_duty_cycle); + + bk_pwm_group_init(&group_init_cfg, &pwm_group); + bk_pwm_group_start(pwm_group); + } else { + pwm_group_config_t group_cfg; + + if(pwm_cfg[ch_id[0]].frequency != pwm_cfg[ch_id[1]].frequency) { + bk_printf("frequency is diff !!!"); + return OPRT_COM_ERROR; + } + period = __PWM_FREQ2PERIOD(pwm_cfg[ch_id[0]].frequency); + duty[0] = (unsigned int)(pwm_cfg[ch_id[0]].duty / 10000.0 * period); + if(pwm_cfg[ch_id[0]].duty && duty[0] == 0) { + duty[0] = 1; + } + duty[1] = (unsigned int)(pwm_cfg[ch_id[1]].duty / 10000.0 * period); + if(pwm_cfg[ch_id[1]].duty && duty[1] == 0) { + duty[1] = 1; + } + + group_cfg.period_cycle = period; + group_cfg.chan1_duty_cycle = duty[0]; + group_cfg.chan2_duty_cycle = duty[1]; + bk_pwm_group_set_config(pwm_group, &group_cfg); + } + + return OPRT_OK; +} + +/** + * @brief multiple pwm channel stop + * + * @param[in] ch_id: pwm channal id list + * @param[in] num : num of pwm channal to stop + * + * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h + */ +OPERATE_RET tkl_pwm_multichannel_stop(TUYA_PWM_NUM_E *ch_id, UINT8_T num) +{ + if (ch_id[0] != mult_chid[0] || ch_id[1] != mult_chid[1]) { + return OPRT_INVALID_PARM; + } + + bk_pwm_group_stop(pwm_group); + + return OPRT_OK; +} + + /** * @brief set pwm info * @@ -143,9 +384,19 @@ OPERATE_RET tkl_pwm_info_set(TUYA_PWM_NUM_E ch_id, CONST TUYA_PWM_BASE_CFG_T *in pwm_chan_t pwm_port; pwm_period_duty_config_t config = {0}; + if (ch_id >= TUYA_PWM_ID_MAX) { + return OPRT_INVALID_PARM; + } + + memcpy(&pwm_cfg[ch_id], info, sizeof(TUYA_PWM_BASE_CFG_T)); + if(PWM_GROUP_ID_INVALID != pwm_group) { + if(ch_id == mult_chid[0] || ch_id == mult_chid[1]) { + return OPRT_OK; + } + } + period = __PWM_FREQ2PERIOD(info->frequency); duty = (unsigned int)(info->duty / 10000.0 * period); - if(info->duty && duty == 0) { duty = 1; } @@ -156,7 +407,6 @@ OPERATE_RET tkl_pwm_info_set(TUYA_PWM_NUM_E ch_id, CONST TUYA_PWM_BASE_CFG_T *in config.duty3_cycle = 0; pwm_port = ty_to_bk_pwm(ch_id); - if(bk_pwm_set_period_duty(pwm_port, &config)) return OPRT_COM_ERROR; @@ -187,7 +437,12 @@ OPERATE_RET tkl_pwm_info_set(TUYA_PWM_NUM_E ch_id, CONST TUYA_PWM_BASE_CFG_T *in */ OPERATE_RET tkl_pwm_info_get(TUYA_PWM_NUM_E ch_id, TUYA_PWM_BASE_CFG_T *info) { - //pwm_chan_t pwm_port; - //pwm_port = ty_to_bk_pwm(ch_id); + if (ch_id >= TUYA_PWM_ID_MAX) { + return OPRT_INVALID_PARM; + } + + info->duty = pwm_cfg[ch_id].duty; + info->frequency = pwm_cfg[ch_id].frequency; + info->polarity = pwm_cfg[ch_id].polarity; return OPRT_NOT_SUPPORTED; }