diff --git a/components/esp8266/driver/ledc.c b/components/esp8266/driver/ledc.c index 4b1ab64c..4220439e 100644 --- a/components/esp8266/driver/ledc.c +++ b/components/esp8266/driver/ledc.c @@ -51,7 +51,7 @@ typedef struct { uint32_t step_01duty; // 0.1 of the duty value uint32_t step_001duty; // 0.01 of the duty value uint32_t gpio_num;//gpio pins - int16_t phase; //init phase + float phase; //init phase int fade_time; // Time to duty by fade } ledc_obj_t; @@ -277,7 +277,7 @@ static void ledc_task(void* pvParameters) esp_err_t ledc_fade_func_install(int intr_alloc_flags) { - int16_t ledc_phase[LEDC_CHANNEL_MAX] = {0}; + float ledc_phase[LEDC_CHANNEL_MAX] = {0}; uint32_t ledc_duty[LEDC_CHANNEL_MAX] = {0}; uint32_t ledc_gpio_num[LEDC_CHANNEL_MAX] = {0}; diff --git a/components/esp8266/driver/pwm.c b/components/esp8266/driver/pwm.c index fe653624..df079d31 100644 --- a/components/esp8266/driver/pwm.c +++ b/components/esp8266/driver/pwm.c @@ -55,11 +55,11 @@ static const char *TAG = "pwm"; #define AHEAD_TICKS3 2 #define MAX_TICKS 10000000ul -#define PWM_VERSION "PWM v3.2" +#define PWM_VERSION "PWM v3.4" typedef struct { uint32_t duty; /*!< pwm duty for each channel */ - int16_t phase; /*!< pwm phase for each channel */ + float phase; /*!< pwm phase for each channel */ uint8_t io_num; /*!< pwm io_num for each channel */ } pwm_info_t; @@ -113,13 +113,13 @@ static void pwm_phase_init(void) for (i = 0; i < pwm_obj->channel_num; i++) { if (-180 < pwm_obj->pwm_info[i].phase && pwm_obj->pwm_info[i].phase < 0) { - time_delay = 0 - ((0 - pwm_obj->pwm_info[i].phase) * pwm_obj->depth / 360); + time_delay = (int32_t)(0 - ((0 - pwm_obj->pwm_info[i].phase) * pwm_obj->depth / 360.0)); } else if (pwm_obj->pwm_info[i].phase == 0) { continue; - } else if (180 > pwm_obj->pwm_info[i].phase && pwm_obj->pwm_info[i].phase > 0) { - time_delay = pwm_obj->pwm_info[i].phase * pwm_obj->depth / 360; + } else if (180 >= pwm_obj->pwm_info[i].phase && pwm_obj->pwm_info[i].phase > 0) { + time_delay = (int32_t)(pwm_obj->pwm_info[i].phase * pwm_obj->depth / 360.0); } else { - ESP_LOGE(TAG, "channel[%d] phase error %d, valid ramge from (-180,180)\n", i, pwm_obj->pwm_info[i].phase); + ESP_LOGE(TAG, "channel[%d] phase error %f, valid ramge from (-180,180]\n", i, pwm_obj->pwm_info[i].phase); continue; } @@ -224,7 +224,7 @@ esp_err_t pwm_set_period_duties(uint32_t period, uint32_t *duties) return ESP_OK; } -esp_err_t pwm_set_phase(uint8_t channel_num, int16_t phase) +esp_err_t pwm_set_phase(uint8_t channel_num, float phase) { PWM_CHECK(channel_num < pwm_obj->channel_num, "Channel num error", ESP_ERR_INVALID_ARG); @@ -233,7 +233,7 @@ esp_err_t pwm_set_phase(uint8_t channel_num, int16_t phase) return ESP_OK; } -esp_err_t pwm_set_phases(int16_t *phases) +esp_err_t pwm_set_phases(float *phases) { uint8_t i; PWM_CHECK(NULL != phases, "Pointer is empty", ESP_ERR_INVALID_ARG); @@ -246,7 +246,7 @@ esp_err_t pwm_set_phases(int16_t *phases) return ESP_OK; } -esp_err_t pwm_get_phase(uint8_t channel_num, uint16_t *phase_p) +esp_err_t pwm_get_phase(uint8_t channel_num, float *phase_p) { PWM_CHECK(channel_num < pwm_obj->channel_num, "Channel num error", ESP_ERR_INVALID_ARG); PWM_CHECK(NULL != phase_p, "Pointer is empty", ESP_ERR_INVALID_ARG); @@ -259,9 +259,7 @@ esp_err_t pwm_get_phase(uint8_t channel_num, uint16_t *phase_p) static void pwm_timer_enable(uint8_t enable) { if (0 == enable) { - ENTER_CRITICAL(); REG_WRITE(WDEVTSF0TIMER_ENA, REG_READ(WDEVTSF0TIMER_ENA) & (~WDEV_TSF0TIMER_ENA)); - EXIT_CRITICAL(); } else { REG_WRITE(WDEVTSF0TIMER_ENA, WDEV_TSF0TIMER_ENA); } @@ -310,14 +308,20 @@ static void IRAM_ATTR pwm_timer_intr_handler(void) pwm_obj->this_target = AHEAD_TICKS1 + AHEAD_TICKS3; } + REG_WRITE(WDEVSLEEP0_CONF, REG_READ(WDEVSLEEP0_CONF) & (~WDEV_TSFUP0_ENA)); + REG_WRITE(WDEVTSF0TIMER_ENA, REG_READ(WDEVTSF0TIMER_ENA) & (~WDEV_TSF0TIMER_ENA)); REG_WRITE(WDEVTSFSW0_LO, 0); //WARNING, pwm_obj->this_target - AHEAD_TICKS1 should be bigger than 2 REG_WRITE(WDEVTSF0_TIMER_LO, pwm_obj->this_target - AHEAD_TICKS1); REG_WRITE(WDEVTSF0TIMER_ENA, WDEV_TSF0TIMER_ENA); + REG_WRITE(WDEVSLEEP0_CONF, REG_READ(WDEVSLEEP0_CONF) | WDEV_TSFUP0_ENA); } static void pwm_timer_start(uint32_t period) { + ENTER_CRITICAL(); + REG_WRITE(WDEVSLEEP0_CONF, REG_READ(WDEVSLEEP0_CONF) & (~WDEV_TSFUP0_ENA)); + REG_WRITE(WDEVTSF0TIMER_ENA, REG_READ(WDEVTSF0TIMER_ENA) & (~WDEV_TSF0TIMER_ENA)); // suspend all task to void timer interrupt missed // TODO, do we need lock interrupt here, I think interrupt context will not take 1ms long // time low field to 0 @@ -334,8 +338,11 @@ static void pwm_timer_start(uint32_t period) pwm_obj->this_target = US_TO_TICKS(period); // WARNING: pwm_obj->this_target should bigger than AHEAD_TICKS1 REG_WRITE(WDEVTSF0_TIMER_LO, pwm_obj->this_target - AHEAD_TICKS1); - // enable timer + REG_WRITE(WDEVTSF0TIMER_ENA, WDEV_TSF0TIMER_ENA); + REG_WRITE(WDEVSLEEP0_CONF, REG_READ(WDEVSLEEP0_CONF) | WDEV_TSFUP0_ENA); + //enable timer pwm_timer_enable(1); + EXIT_CRITICAL(); } static void pwm_timer_register(void (*handle)(void)) @@ -573,7 +580,9 @@ esp_err_t pwm_stop(uint32_t stop_level_mask) { int16_t i = 0; + ENTER_CRITICAL(); pwm_timer_enable(0); + EXIT_CRITICAL(); uint32_t level_set = REG_READ(PERIPHS_GPIO_BASEADDR + GPIO_OUT_ADDRESS); for (i = 0; i < pwm_obj->channel_num; i++) { diff --git a/components/esp8266/include/driver/pwm.h b/components/esp8266/include/driver/pwm.h index c457ba91..75e236a0 100644 --- a/components/esp8266/include/driver/pwm.h +++ b/components/esp8266/include/driver/pwm.h @@ -145,13 +145,13 @@ esp_err_t pwm_set_duties(uint32_t *duties); * * @param channel_num PWM channel number * the channel_num cannot exceed the value initialized by pwm_init. - * @param phase The phase of this PWM channel, the phase range is (-180 ~ 180). + * @param phase The phase of this PWM channel, the phase range is (-180 ~ 180]. * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t pwm_set_phase(uint8_t channel_num, int16_t phase); +esp_err_t pwm_set_phase(uint8_t channel_num, float phase); /** * @brief Set the phase of all channels. @@ -164,7 +164,7 @@ esp_err_t pwm_set_phase(uint8_t channel_num, int16_t phase); * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t pwm_set_phases(int16_t *phases); +esp_err_t pwm_set_phases(float *phases); /** * @brief Get the phase of a PWM channel. @@ -177,7 +177,7 @@ esp_err_t pwm_set_phases(int16_t *phases); * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t pwm_get_phase(uint8_t channel_num, uint16_t *phase_p); +esp_err_t pwm_get_phase(uint8_t channel_num, float *phase_p); /** * @brief Set PWM period and duty of each PWM channel. diff --git a/components/esp8266/include/esp8266/eagle_soc.h b/components/esp8266/include/esp8266/eagle_soc.h index 97aab970..685fdf91 100644 --- a/components/esp8266/include/esp8266/eagle_soc.h +++ b/components/esp8266/include/esp8266/eagle_soc.h @@ -148,12 +148,14 @@ #define WDEVTSF0_TIME_LO 0x3ff21004 #define WDEVTSF0_TIME_HI 0x3ff21008 +#define WDEVSLEEP0_CONF 0x3ff21014 #define WDEVTSFSW0_LO 0x3ff21018 #define WDEVTSFSW0_HI 0x3ff2101C #define WDEVTSF0_TIMER_LO 0x3ff2109c #define WDEVTSF0_TIMER_HI 0x3ff210a0 #define WDEVTSF0TIMER_ENA 0x3ff21098 #define WDEV_TSF0TIMER_ENA BIT(31) +#define WDEV_TSFUP0_ENA BIT(31) //Watch dog reg {{ #define PERIPHS_WDT_BASEADDR 0x60000900 diff --git a/examples/peripherals/pwm/main/pwm_example_main.c b/examples/peripherals/pwm/main/pwm_example_main.c index e7f1df5d..c9e34cdb 100644 --- a/examples/peripherals/pwm/main/pwm_example_main.c +++ b/examples/peripherals/pwm/main/pwm_example_main.c @@ -49,14 +49,13 @@ uint32_t duties[4] = { }; // phase table, delay = (phase[x]/360)*PERIOD -int16_t phase[4] = { - 0, 0, 90, -90, +float phase[4] = { + 0, 0, 90.0, -90.0, }; void app_main() { pwm_init(PWM_PERIOD, duties, 4, pin_num); - pwm_set_channel_invert(0x1 << 0); pwm_set_phases(phase); pwm_start(); int16_t count = 0;