From e523a2532a4515205e517a740b07e50ed1dd251a Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Wed, 28 Sep 2016 23:20:34 +0800 Subject: [PATCH] Modify LEDC driver 1. configure LEDC timer saparately 2. add peripher_crtl.c/.h To enable the peripheral modules, we have to set/clear the control register in dport_reg.h. These bits are disabled by default and they are all in a same register, so we need to add a lock on that. 3. add include esp_err.h in gpio.h --- components/driver/include/driver/gpio.h | 2 +- components/driver/include/driver/ledc.h | 126 ++++++++----- .../driver/include/driver/periph_ctrl.h | 70 ++++++++ components/driver/ledc.c | 120 +++++++------ components/driver/periph_ctrl.c | 170 ++++++++++++++++++ 5 files changed, 383 insertions(+), 105 deletions(-) create mode 100644 components/driver/include/driver/periph_ctrl.h create mode 100644 components/driver/periph_ctrl.c diff --git a/components/driver/include/driver/gpio.h b/components/driver/include/driver/gpio.h index 862d4e592..9b47c88e6 100644 --- a/components/driver/include/driver/gpio.h +++ b/components/driver/include/driver/gpio.h @@ -14,7 +14,7 @@ #ifndef _DRIVER_GPIO_H_ #define _DRIVER_GPIO_H_ - +#include "esp_err.h" #include #include "soc/gpio_reg.h" #include "soc/gpio_struct.h" diff --git a/components/driver/include/driver/ledc.h b/components/driver/include/driver/ledc.h index 3e3d3740d..79a6c7f9f 100644 --- a/components/driver/include/driver/ledc.h +++ b/components/driver/include/driver/ledc.h @@ -20,6 +20,7 @@ #include "soc/ledc_reg.h" #include "soc/ledc_struct.h" #include "driver/gpio.h" +#include "driver/periph_ctrl.h" #ifdef __cplusplus extern "C" { @@ -51,10 +52,10 @@ typedef enum { } ledc_clk_src_t; typedef enum { - LEDC_TIMER0 = 0, /*LEDC source timer TIMER0 */ - LEDC_TIMER1, /*LEDC source timer TIMER1 */ - LEDC_TIMER2, /*LEDC source timer TIMER2 */ - LEDC_TIMER3, /*LEDC source timer TIMER3 */ + LEDC_TIMER_0 = 0, /*LEDC source timer TIMER0 */ + LEDC_TIMER_1, /*LEDC source timer TIMER1 */ + LEDC_TIMER_2, /*LEDC source timer TIMER2 */ + LEDC_TIMER_3, /*LEDC source timer TIMER3 */ } ledc_timer_t; typedef enum { @@ -77,40 +78,57 @@ typedef enum { LEDC_TIMER_15_BIT = 15, /*LEDC PWM depth 15Bit */ } ledc_timer_bit_t; -typedef struct ledc_channel_t_config { +typedef struct { int gpio_num; /*the LEDC output gpio_num, if you want to use gpio16, gpio_num = 16*/ ledc_mode_t speed_mode; /*LEDC speed speed_mode, high-speed mode or low-speed mode*/ ledc_channel_t channel; /*LEDC channel(0 - 7)*/ ledc_intr_type_t intr_type; /*configure interrupt, Fade interrupt enable or Fade interrupt disable*/ - ledc_timer_t timer_sel; /*Select the timer source of channel (0 - 3)*/ - uint32_t freq_hz; /*LEDC channel frequency(Hz)*/ + ledc_timer_t timer_sel; /*Select the timer source of channel (0 - 3)*/ uint32_t duty; /*LEDC channel duty, the duty range is [0, (2**bit_num) - 1], */ +} ledc_channel_config_t; + +typedef struct { + ledc_mode_t speed_mode; /*LEDC speed speed_mode, high-speed mode or low-speed mode*/ ledc_timer_bit_t bit_num; /*LEDC channel duty depth*/ -} ledc_config_t; + ledc_timer_t timer_num; /*The timer source of channel (0 - 3)*/ + uint32_t freq_hz; /*LEDC timer frequency(Hz)*/ +} ledc_timer_config_t; + /** - * @brief LEDC common configuration + * @brief LEDC channel configuration * - * User this Function, configure LEDC with the given channel/output gpio_num/interrupt/source timer/frequency(Hz)/LEDC depth + * User this Function, configure LEDC channel with the given channel/output gpio_num/interrupt/source timer/frequency(Hz)/LEDC depth * - * @param[in] ledc_config_t - * ledc_config_t.speed_mode : LEDC speed speed_mode - * ledc_config_t.gpio_num : LEDC output gpio_num, if you want to use gpio16, ledc_config_t.gpio_num = 16 - * ledc_config_t.channel : LEDC channel(0 - 7) - * ledc_config_t.intr_type : configure interrupt, Fade interrupt enable or Fade interrupt disable - * ledc_config_t.timer_sel : Select the timer source of channel (0 - 3) - * When different channel, select same timer, their freq_hz and bit_num must be the same - * ledc_config_t.freq_hz : LEDC channel frequency(Hz), - * When different channel, select same time, their freq_hz and bit_num must be same - * ledc_config_t.duty : LEDC channel duty, the duty range is [0, (2**bit_num) - 1], - * ledc_config_t.bit_num : LEDC channel duty depth - * When different channel, select same time, their freq_hz and bit_num must be same + * @param[in] ledc_channel_config_t + * ledc_channel_config_t.speed_mode : LEDC speed speed_mode + * ledc_channel_config_t.gpio_num : LEDC output gpio_num, if you want to use gpio16, ledc_channel_config_t.gpio_num = 16 + * ledc_channel_config_t.channel : LEDC channel(0 - 7) + * ledc_channel_config_t.intr_type : configure interrupt, Fade interrupt enable or Fade interrupt disable + * ledc_channel_config_t.timer_sel : Select the timer source of channel (0 - 3), high speed channel must bind with high speed timer. + * ledc_channel_config_t.duty : LEDC channel duty, the duty range is [0, (2**timer_bit_num) - 1], + * @return ESP_OK: success + * ESP_ERR_INVALID_ARG: parameter error + * + */ +esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf); + +/** + * @brief LEDC timer configuration + * + * User this Function, configure LEDC timer with the given source timer/frequency(Hz)/bit_num + * + * @param[in] ledc_timer_config_t + * ledc_timer_config_t.speed_mode : LEDC speed speed_mode + * ledc_timer_config_t.timer_num : Select the timer source of channel (0 - 3) + * ledc_timer_config_t.freq_hz : LEDC channel frequency(Hz), + * ledc_timer_config_t.bit_num : LEDC channel duty depth * @return ESP_OK: success * ESP_ERR_INVALID_ARG: parameter error * ESP_FAIL: Can not find a proper pre-divider number base on the given frequency and the current bit_num. * */ -esp_err_t ledc_config(ledc_config_t* ledc_conf); +esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf); /** * @brief LEDC update channel parameters @@ -120,13 +138,13 @@ esp_err_t ledc_config(ledc_config_t* ledc_conf); * * @param[in] speed_mode : select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version * - * @param[in] channel : LEDC channel(0-7) + * @param[in] channel : LEDC channel(0-7), select from ledc_channel_t * * @return ESP_OK: success * ESP_ERR_INVALID_ARG: parameter error * */ -esp_err_t ledc_update(ledc_mode_t speed_mode, ledc_channel_t channel); +esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel); /** * @brief LEDC stop @@ -135,7 +153,7 @@ esp_err_t ledc_update(ledc_mode_t speed_mode, ledc_channel_t channel); * * @param[in] speed_mode : select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version * - * @param[in] channel : LEDC channel(0-7) + * @param[in] channel : LEDC channel(0-7), select from ledc_channel_t * * @return ESP_OK: success * ESP_ERR_INVALID_ARG: parameter error @@ -149,7 +167,7 @@ esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idl * * @param[in] speed_mode : select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version * - * @param[in] timer_num : LEDC timer index(0-3) + * @param[in] timer_num : LEDC timer index(0-3), select from ledc_timer_t * * @param[in] freq_hz : set the LEDC frequency * @@ -164,7 +182,7 @@ esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t * * @param[in] speed_mode : select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version * - * @param[in] timer_num : LEDC timer index(0-3) + * @param[in] timer_num : LEDC timer index(0-3), select from ledc_timer_t * * @return 0 : error * others : current LEDC frequency @@ -175,11 +193,11 @@ uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num); /** * @brief LEDC set duty * - * Set LEDC duty, After the function calls the ledc_update function, the function can take effect. + * Set LEDC duty, After the function calls the ledc_update_duty function, the function can take effect. * * @param[in] speed_mode : select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version * - * @param[in] channel : LEDC channel(0-7) + * @param[in] channel : LEDC channel(0-7), select from ledc_channel_t * * @param[in] duty : set the LEDC duty, the duty range is [0, (2**bit_num) - 1] * @@ -193,7 +211,7 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t * * @param[in] speed_mode : select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version * - * @param[in] channel : LEDC channel(0-7) + * @param[in] channel : LEDC channel(0-7), select from ledc_channel_t * * * @return -1: parameter error @@ -205,11 +223,11 @@ int ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel); /** * @brief LEDC set gradient * - * Set LEDC gradient, After the function calls the ledc_update function, the function can take effect. + * Set LEDC gradient, After the function calls the ledc_update_duty function, the function can take effect. * * @param[in] speed_mode : select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version * - * @param[in] channel : LEDC channel(0-7) + * @param[in] channel : LEDC channel(0-7), select from ledc_channel_t * * @param[in] duty : set the start of the gradient duty, the duty range is [0, (2**bit_num) - 1] * @@ -233,10 +251,10 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, uint32_t channel, uint32_t duty, * Users should know that which CPU is running and then pick a INUM that is not used by system. * We can find the information of INUM and interrupt level in soc.h. * TODO: to move INUM options to menu_config - * @parameter uint32_t ledc_intr_num : LEDC interrupt number, check the info in soc.h, and please see the core-isa.h for more details - * @parameter void (* fn)(void* ) : interrupt handler function. + * @param[in] uint32_t ledc_intr_num : LEDC interrupt number, check the info in soc.h, and please see the core-isa.h for more details + * @param[in] void (* fn)(void* ) : interrupt handler function. * Note that the handler function MUST be defined with attribution of "IRAM_ATTR". - * @parameter void * arg : parameter for handler function + * @param[in] void * arg : parameter for handler function * * @return ESP_OK : success ; * ESP_ERR_INVALID_ARG : function ptr error. @@ -260,14 +278,14 @@ esp_err_t ledc_isr_register(uint32_t ledc_intr_num, void (*fn)(void*), void * ar * other value: current LEDC duty * */ -esp_err_t ledc_timer_config(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t div_num, uint32_t bit_num, ledc_clk_src_t clk_src); +esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t div_num, uint32_t bit_num, ledc_clk_src_t clk_src); /** * @brief reset LEDC timer * * @param[in] speed_mode : select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version * - * @param[in] timer_sel : LEDC timer index(0-3) + * @param[in] timer_sel : LEDC timer index(0-3), select from ledc_timer_t * * * @return ESP_ERR_INVALID_ARG: parameter error @@ -281,7 +299,7 @@ esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel); * * @param[in] speed_mode : select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version * - * @param[in] timer_sel : LEDC timer index(0-3) + * @param[in] timer_sel : LEDC timer index(0-3), select from ledc_timer_t * * * @return ESP_ERR_INVALID_ARG: parameter error @@ -295,7 +313,7 @@ esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, uint32_t timer_sel); * * @param[in] speed_mode : select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version * - * @param[in] timer_sel : LEDC timer index(0-3) + * @param[in] timer_sel : LEDC timer index(0-3), select from ledc_timer_t * * * @return ESP_ERR_INVALID_ARG: parameter error @@ -309,9 +327,9 @@ esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel); * * @param[in] speed_mode : select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version * - * @param[in] channel : LEDC channel index(0-7) + * @param[in] channel : LEDC channel index(0-7), select from ledc_channel_t * - * @param[in] timer_idx : LEDC timer index(0-3) + * @param[in] timer_idx : LEDC timer index(0-3), select from ledc_timer_t * * * @return ESP_ERR_INVALID_ARG: parameter error @@ -324,22 +342,34 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint * * * ----------------EXAMPLE OF LEDC SETTING --------------------- - * ledc_config_t ledc_conf = { + * //1. enable LEDC + * periph_module_enable(PERIPH_LEDC_MODULE); //enable LEDC module, or you can not set any register of it. + * + * //2. set LEDC timer + * ledc_timer_config_t timer_conf = { + * .bit_num = LEDC_TIMER_12_BIT, //set timer counter bit number + * .freq_hz = 1000, //set frequency of pwm, here, 1000Hz + * .speed_mode = LEDC_HIGH_SPEED_MODE //timer mode, + * .timer_num = LEDC_TIMER_0, //timer number + * }; + * ledc_timer_config(&timer_conf); //setup timer. + * + * //3. set LEDC channel + * ledc_channel_config_t ledc_conf = { * .channel = LEDC_CHANNEL_0; //set LEDC channel 0 * .duty = 1000; //set the duty for initialization.(duty range is 0 ~ ((2**bit_num)-1) - * .freq_hz = 1000; //set frequency, e.g., 1KHz * .gpio_num = 16; //GPIO number * .intr_type = LEDC_INTR_FADE_END; //GPIO INTR TYPE, as an example, we enable fade_end interrupt here. - * .bit_num = LEDC_TIMER_12_BIT; //set bit_num, (duty range is 0 ~ ((2**bit_num)-1) * .speed_mode = LEDC_HIGH_SPEED_MODE; //set LEDC mode, from ledc_mode_t - * .timer_sel = LEDC_TIMER0; //set LEDC timer source, if different channel use one timer, the frequency and bit_num of these channels should be the same + * .timer_sel = LEDC_TIMER_0; //set LEDC timer source, if different channel use one timer, the frequency and bit_num of these channels should be the same * } - * ledc_config(&ledc_conf); //setup the configuration + * ledc_channel_config(&ledc_conf); //setup the configuration + * * ----------------EXAMPLE OF SETTING DUTY --- ----------------- * uint32_t ledc_channel = LEDC_CHANNEL_0; //LEDC channel(0-73) * uint32_t duty = 2000; //duty range is 0 ~ ((2**bit_num)-1) * LEDC_set_duty(LEDC_HIGH_SPEED_MODE, ledc_channel, duty); //set speed mode, channel, and duty. - * ledc_update(LEDC_HIGH_SPEED_MODE, ledc_channel); //after set duty, we need to call ledc_update to update the settings. + * ledc_update_duty(LEDC_HIGH_SPEED_MODE, ledc_channel); //after set duty, we need to call ledc_update_duty to update the settings. * * * ----------------EXAMPLE OF LEDC INTERRUPT ------------------ diff --git a/components/driver/include/driver/periph_ctrl.h b/components/driver/include/driver/periph_ctrl.h new file mode 100644 index 000000000..3faa347b5 --- /dev/null +++ b/components/driver/include/driver/periph_ctrl.h @@ -0,0 +1,70 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _DRIVER_PERIPH_CTRL_H_ +#define _DRIVER_PERIPH_CTRL_H_ +#include "esp_err.h" +#include "soc/soc.h" +#include "soc/dport_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PERIPH_LEDC_MODULE = 0, + PERIPH_UART0_MODULE, + PERIPH_UART1_MODULE, + PERIPH_UART2_MODULE, + PERIPH_I2C0_MODULE, + PERIPH_I2C1_MODULE, + PERIPH_I2S0_MODULE, + PERIPH_I2S1_MODULE, + PERIPH_TIMG0_MODULE, + PERIPH_TIMG1_MODULE, + PERIPH_PWM0_MODULE, + PERIPH_PWM1_MODULE, + PERIPH_PWM2_MODULE, + PERIPH_PWM3_MODULE, + PERIPH_UHCI0_MODULE, + PERIPH_UHCI1_MODULE, +} periph_module_t; + +/** + * @brief enable peripheral module + * + * @param[in] periph : Peripheral module name + * + * + * @return NULL + * + */ +void periph_module_enable(periph_module_t periph); + +/** + * @brief disable peripheral module + * + * @param[in] periph : Peripheral module name + * + * + * @return NULL + * + */ +void periph_module_disable(periph_module_t periph); + +#ifdef __cplusplus +} +#endif + +#endif /* _DRIVER_PERIPH_CTRL_H_ */ diff --git a/components/driver/ledc.c b/components/driver/ledc.c index 3fd0f27af..386c93dfa 100644 --- a/components/driver/ledc.c +++ b/components/driver/ledc.c @@ -16,7 +16,6 @@ #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/xtensa_api.h" -#include "soc/dport_reg.h" #include "soc/gpio_sig_map.h" #include "driver/ledc.h" @@ -84,14 +83,14 @@ static bool ledc_is_valid_mode(uint32_t mode) static bool ledc_is_valid_timer(int timer) { - if(timer > LEDC_TIMER3) { + if(timer > LEDC_TIMER_3) { LEDC_ERROR("LEDC TIMER ERR: %d\n", timer); return false; } return true; } -esp_err_t ledc_timer_config(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t div_num, uint32_t bit_num, ledc_clk_src_t clk_src) +esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t div_num, uint32_t bit_num, ledc_clk_src_t clk_src) { if(!ledc_is_valid_mode(speed_mode)) { return ESP_ERR_INVALID_ARG; @@ -103,7 +102,7 @@ esp_err_t ledc_timer_config(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint LEDC.timer_group[speed_mode].timer[timer_sel].conf.div_num = div_num; LEDC.timer_group[speed_mode].timer[timer_sel].conf.tick_sel = clk_src; LEDC.timer_group[speed_mode].timer[timer_sel].conf.bit_num = bit_num; - if(speed_mode == LEDC_HIGH_SPEED_MODE) { + if(speed_mode != LEDC_HIGH_SPEED_MODE) { LEDC.timer_group[speed_mode].timer[timer_sel].conf.low_speed_update = 1; } portEXIT_CRITICAL(&ledc_spinlock); @@ -213,45 +212,28 @@ esp_err_t ledc_isr_register(uint32_t ledc_intr_num, void (*fn)(void*), void * ar return ESP_OK; } -esp_err_t ledc_config(ledc_config_t* ledc_conf) +esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf) { - SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_LEDC_CLK_EN); - CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_LEDC_RST); + int freq_hz = timer_conf->freq_hz; + int bit_num = timer_conf->bit_num; + int timer_num = timer_conf->timer_num; + int speed_mode = timer_conf->speed_mode; - uint32_t speed_mode = ledc_conf->speed_mode; - uint32_t gpio_num = ledc_conf->gpio_num; - uint32_t ledc_channel = ledc_conf->channel; - uint32_t freq_hz = ledc_conf->freq_hz; - uint32_t timer_select = ledc_conf->timer_sel; - uint32_t bit_num = ledc_conf->bit_num; - uint32_t intr_type = ledc_conf->intr_type; - uint32_t duty = ledc_conf->duty; - uint32_t div_param = 0; - uint32_t precision = 0; - int timer_clk_src = 0; - - if(!ledc_is_valid_channel(ledc_channel)) { - return ESP_ERR_INVALID_ARG; - } if(!ledc_is_valid_mode(speed_mode)) { return ESP_ERR_INVALID_ARG; } - if(!GPIO_IS_VALID_OUTPUT_GPIO(gpio_num)) { - LEDC_ERROR("GPIO number error: IO%d\n ", gpio_num); - return ESP_ERR_INVALID_ARG; - } if(freq_hz == 0 || bit_num == 0 || bit_num > LEDC_TIMER_15_BIT) { - LEDC_ERROR("freq_hz=%u bit_num=%u\n", div_param, bit_num); + LEDC_ERROR("freq_hz=%u bit_num=%u\n", freq_hz, bit_num); return ESP_ERR_INVALID_ARG; } - if(timer_select > LEDC_TIMER3) { - LEDC_ERROR("Time Select %u\n", timer_select); + if(timer_num > LEDC_TIMER_3) { + LEDC_ERROR("Time Select %u\n", timer_num); return ESP_ERR_INVALID_ARG; } - portENTER_CRITICAL(&ledc_spinlock); esp_err_t ret = ESP_OK; - precision = (0x1 << bit_num); //2**depth - div_param = ((uint64_t) LEDC_APB_CLK_HZ << 8) / freq_hz / precision; //8bit fragment + uint32_t precision = (0x1 << bit_num); //2**depth + uint64_t div_param = ((uint64_t) LEDC_APB_CLK_HZ << 8) / freq_hz / precision; //8bit fragment + int timer_clk_src; /*Fail ,because the div_num overflow or too small*/ if(div_param <= 256 || div_param > LEDC_DIV_NUM_HSTIMER0_V) { //REF TICK /*Selet the reference tick*/ @@ -264,33 +246,59 @@ esp_err_t ledc_config(ledc_config_t* ledc_conf) } else { //APB TICK timer_clk_src = LEDC_APB_CLK; } - //1. set timer parameters - // timer settings decide the clk of counter and the period of PWM - ledc_timer_config(speed_mode, timer_select, div_param, bit_num, timer_clk_src); - // reset timer. - ledc_timer_rst(speed_mode, timer_select); - //2. set channel parameters - // channel parameters decide how the waveform looks like in one period - // set channel duty, duty range is (0 ~ ((2 ** bit_num) - 1)) - ledc_set_duty(speed_mode, ledc_channel, duty); - //update duty settings - ledc_update(speed_mode, ledc_channel); - //3. bind the channel with the timer - ledc_bind_channel_timer(speed_mode, ledc_channel, timer_select); - //4. set interrupt type - ledc_enable_intr_type(speed_mode, ledc_channel, intr_type); - LEDC_INFO("LEDC_PWM CHANNEL %1u|GPIO %02u|FreHz %05u|Duty %04u|Depth %04u|Time %01u|SourceClk %01u|Divparam %u\n", - ledc_channel, gpio_num, freq_hz, duty, bit_num, timer_select, timer_clk_src, div_param - ); - /*5. set LEDC signal in gpio matrix*/ - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO); - gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT); - gpio_matrix_out(gpio_num, LEDC_HS_SIG_OUT0_IDX + ledc_channel, 0, 0); - portEXIT_CRITICAL(&ledc_spinlock); + /*set timer parameters*/ + /*timer settings decide the clk of counter and the period of PWM*/ + ledc_timer_set(speed_mode, timer_num, div_param, bit_num, timer_clk_src); + /* reset timer.*/ + ledc_timer_rst(speed_mode, timer_num); return ret; } -esp_err_t ledc_update(ledc_mode_t speed_mode, ledc_channel_t channel) +esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf) +{ + uint32_t speed_mode = ledc_conf->speed_mode; + uint32_t gpio_num = ledc_conf->gpio_num; + uint32_t ledc_channel = ledc_conf->channel; + uint32_t timer_select = ledc_conf->timer_sel; + uint32_t intr_type = ledc_conf->intr_type; + uint32_t duty = ledc_conf->duty; + + if(!ledc_is_valid_channel(ledc_channel)) { + return ESP_ERR_INVALID_ARG; + } + if(!ledc_is_valid_mode(speed_mode)) { + return ESP_ERR_INVALID_ARG; + } + if(!GPIO_IS_VALID_OUTPUT_GPIO(gpio_num)) { + LEDC_ERROR("GPIO number error: IO%d\n ", gpio_num); + return ESP_ERR_INVALID_ARG; + } + if(timer_select > LEDC_TIMER_3) { + LEDC_ERROR("Time Select %u\n", timer_select); + return ESP_ERR_INVALID_ARG; + } + esp_err_t ret = ESP_OK; + /*set channel parameters*/ + /* channel parameters decide how the waveform looks like in one period*/ + /* set channel duty, duty range is (0 ~ ((2 ** bit_num) - 1))*/ + ledc_set_duty(speed_mode, ledc_channel, duty); + /*update duty settings*/ + ledc_update_duty(speed_mode, ledc_channel); + /*bind the channel with the timer*/ + ledc_bind_channel_timer(speed_mode, ledc_channel, timer_select); + /*set interrupt type*/ + ledc_enable_intr_type(speed_mode, ledc_channel, intr_type); + LEDC_INFO("LEDC_PWM CHANNEL %1u|GPIO %02u|Duty %04u|Time %01u\n", + ledc_channel, gpio_num, duty, timer_select + ); + /*set LEDC signal in gpio matrix*/ + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO); + gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT); + gpio_matrix_out(gpio_num, LEDC_HS_SIG_OUT0_IDX + ledc_channel, 0, 0); + return ret; +} + +esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel) { if(!ledc_is_valid_mode(speed_mode)) { return ESP_ERR_INVALID_ARG; diff --git a/components/driver/periph_ctrl.c b/components/driver/periph_ctrl.c new file mode 100644 index 000000000..df1abbf55 --- /dev/null +++ b/components/driver/periph_ctrl.c @@ -0,0 +1,170 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include "esp_intr.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/xtensa_api.h" +#include "soc/dport_reg.h" +#include "driver/periph_ctrl.h" + +static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED; + +void periph_module_enable(periph_module_t periph) +{ + portENTER_CRITICAL(&periph_spinlock); + switch(periph) { + case PERIPH_LEDC_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_LEDC_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_LEDC_RST); + break; + case PERIPH_UART0_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST); + break; + case PERIPH_UART1_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART1_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST); + break; + case PERIPH_UART2_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART2_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART2_RST); + break; + case PERIPH_I2C0_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2C_EXT0_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2C_EXT0_RST); + break; + case PERIPH_I2C1_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2C_EXT1_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2C_EXT1_RST); + break; + case PERIPH_I2S0_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); + break; + case PERIPH_I2S1_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST); + break; + case PERIPH_TIMG0_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_TIMERGROUP_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_TIMERGROUP_RST); + break; + case PERIPH_TIMG1_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_TIMERGROUP1_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_TIMERGROUP1_RST); + break; + case PERIPH_PWM0_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM0_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM0_RST); + break; + case PERIPH_PWM1_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM1_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM1_RST); + break; + case PERIPH_PWM2_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM2_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM2_RST); + break; + case PERIPH_PWM3_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM3_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM3_RST); + break; + case PERIPH_UHCI0_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UHCI0_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UHCI0_RST); + break; + case PERIPH_UHCI1_MODULE: + SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UHCI1_CLK_EN); + CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UHCI1_RST); + break; + default: + break; + } + portENTER_CRITICAL(&periph_spinlock); +} + +void periph_module_disable(periph_module_t periph) +{ + portENTER_CRITICAL(&periph_spinlock); + switch(periph) { + case PERIPH_LEDC_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_LEDC_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_LEDC_RST); + break; + case PERIPH_UART0_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST); + break; + case PERIPH_UART1_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART1_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST); + break; + case PERIPH_UART2_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UART2_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART2_RST); + break; + case PERIPH_I2C0_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2C_EXT0_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2C_EXT0_RST); + break; + case PERIPH_I2C1_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2C_EXT0_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2C_EXT1_RST); + break; + case PERIPH_I2S0_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); + break; + case PERIPH_I2S1_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S1_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S1_RST); + break; + case PERIPH_TIMG0_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_TIMERGROUP_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_TIMERGROUP_RST); + break; + case PERIPH_TIMG1_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_TIMERGROUP1_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_TIMERGROUP1_RST); + break; + case PERIPH_PWM0_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM0_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM0_RST); + break; + case PERIPH_PWM1_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM1_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM1_RST); + break; + case PERIPH_PWM2_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM2_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM2_RST); + break; + case PERIPH_PWM3_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_PWM3_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_PWM3_RST); + break; + case PERIPH_UHCI0_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UHCI0_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UHCI0_RST); + break; + case PERIPH_UHCI1_MODULE: + CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_UHCI1_CLK_EN); + SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UHCI1_RST); + break; + default: + break; + } + portENTER_CRITICAL(&periph_spinlock); +}