riscv/esp32c3: Add ESP32-C3 LEDC(PWM) driver
This commit is contained in:
parent
b5ee9b673c
commit
beed26b6bf
@ -178,6 +178,11 @@ config ESP32C3_SPI
|
|||||||
bool
|
bool
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config ESP32C3_LEDC
|
||||||
|
bool "LEDC (PWM)"
|
||||||
|
default n
|
||||||
|
select PWM
|
||||||
|
|
||||||
config ESP32C3_GPIO_IRQ
|
config ESP32C3_GPIO_IRQ
|
||||||
bool "GPIO pin interrupts"
|
bool "GPIO pin interrupts"
|
||||||
default n
|
default n
|
||||||
@ -418,6 +423,71 @@ config ESP32C3_FREERUN
|
|||||||
endmenu # Timer/counter Configuration
|
endmenu # Timer/counter Configuration
|
||||||
endif # ESP32C3_TIMER
|
endif # ESP32C3_TIMER
|
||||||
|
|
||||||
|
menu "LEDC configuration"
|
||||||
|
depends on ESP32C3_LEDC
|
||||||
|
|
||||||
|
menuconfig ESP32C3_LEDC_TIM0
|
||||||
|
bool "Timer 0"
|
||||||
|
default n
|
||||||
|
|
||||||
|
if ESP32C3_LEDC_TIM0
|
||||||
|
|
||||||
|
config ESP32C3_LEDC_TIM0_CHANNELS
|
||||||
|
int "Number of Timer 0 channels"
|
||||||
|
default 2
|
||||||
|
|
||||||
|
endif # ESP32C3_LEDC_TIM0
|
||||||
|
|
||||||
|
menuconfig ESP32C3_LEDC_TIM1
|
||||||
|
bool "Timer 1"
|
||||||
|
default n
|
||||||
|
|
||||||
|
if ESP32C3_LEDC_TIM1
|
||||||
|
|
||||||
|
config ESP32C3_LEDC_TIM1_CHANNELS
|
||||||
|
int "Number of Timer 1 channels"
|
||||||
|
default 2
|
||||||
|
|
||||||
|
endif # ESP32C3_LEDC_TIM1
|
||||||
|
|
||||||
|
menuconfig ESP32C3_LEDC_TIM2
|
||||||
|
bool "Timer 2"
|
||||||
|
default n
|
||||||
|
|
||||||
|
if ESP32C3_LEDC_TIM2
|
||||||
|
|
||||||
|
config ESP32C3_LEDC_TIM2_CHANNELS
|
||||||
|
int "Number of Timer 2 channels"
|
||||||
|
default 2
|
||||||
|
|
||||||
|
endif # ESP32C3_LEDC_TIM2
|
||||||
|
|
||||||
|
config ESP32C3_LEDC_CHANNEL0_PIN
|
||||||
|
int "Channel 0 pin"
|
||||||
|
default 2
|
||||||
|
|
||||||
|
config ESP32C3_LEDC_CHANNEL1_PIN
|
||||||
|
int "Channel 1 pin"
|
||||||
|
default 3
|
||||||
|
|
||||||
|
config ESP32C3_LEDC_CHANNEL2_PIN
|
||||||
|
int "Channel 2 pin"
|
||||||
|
default 4
|
||||||
|
|
||||||
|
config ESP32C3_LEDC_CHANNEL3_PIN
|
||||||
|
int "Channel 3 pin"
|
||||||
|
default 5
|
||||||
|
|
||||||
|
config ESP32C3_LEDC_CHANNEL4_PIN
|
||||||
|
int "Channel 4 pin"
|
||||||
|
default 6
|
||||||
|
|
||||||
|
config ESP32C3_LEDC_CHANNEL5_PIN
|
||||||
|
int "Channel 5 pin"
|
||||||
|
default 7
|
||||||
|
|
||||||
|
endmenu # LEDC configuration
|
||||||
|
|
||||||
menu "Wi-Fi configuration"
|
menu "Wi-Fi configuration"
|
||||||
depends on ESP32C3_WIRELESS
|
depends on ESP32C3_WIRELESS
|
||||||
|
|
||||||
|
@ -121,6 +121,10 @@ endif
|
|||||||
|
|
||||||
CHIP_CSRCS += esp32c3_rtc.c
|
CHIP_CSRCS += esp32c3_rtc.c
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_ESP32C3_LEDC),y)
|
||||||
|
CHIP_CSRCS += esp32c3_ledc.c
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_ESP32C3_WIRELESS),y)
|
ifeq ($(CONFIG_ESP32C3_WIRELESS),y)
|
||||||
WIRELESS_DRV_UNPACK = esp-wireless-drivers-3rdparty
|
WIRELESS_DRV_UNPACK = esp-wireless-drivers-3rdparty
|
||||||
WIRELESS_DRV_ID = 2b53111
|
WIRELESS_DRV_ID = 2b53111
|
||||||
|
776
arch/risc-v/src/esp32c3/esp32c3_ledc.c
Normal file
776
arch/risc-v/src/esp32c3/esp32c3_ledc.c
Normal file
@ -0,0 +1,776 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* arch/risc-v/src/esp32c3/esp32c3_ledc.c
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "esp32c3.h"
|
||||||
|
#include "esp32c3_clockconfig.h"
|
||||||
|
#include "esp32c3_gpio.h"
|
||||||
|
#include "esp32c3_ledc.h"
|
||||||
|
|
||||||
|
#include "riscv_arch.h"
|
||||||
|
#include "hardware/esp32c3_ledc.h"
|
||||||
|
#include "hardware/esp32c3_system.h"
|
||||||
|
#include "hardware/esp32c3_gpio_sigmap.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* LEDC total timers */
|
||||||
|
|
||||||
|
#define LEDC_TIMERS (3)
|
||||||
|
|
||||||
|
/* LEDC total channels */
|
||||||
|
|
||||||
|
#if defined(CONFIG_PWM_NCHANNELS) && CONFIG_PWM_NCHANNELS > 1
|
||||||
|
# define LEDC_CHANNELS (6)
|
||||||
|
#else
|
||||||
|
# define LEDC_CHANNELS (3)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* LEDC timer0 channels and offset */
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32C3_LEDC_TIM0
|
||||||
|
# if defined(CONFIG_PWM_NCHANNELS) && CONFIG_PWM_NCHANNELS > 1
|
||||||
|
# define LEDC_TIM0_CHANS CONFIG_ESP32C3_LEDC_TIM0_CHANNELS
|
||||||
|
# else
|
||||||
|
# define LEDC_TIM0_CHANS (1)
|
||||||
|
# endif
|
||||||
|
# define LEDC_TIM0_CHANS_OFF (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* LEDC timer1 channels and offset */
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32C3_LEDC_TIM1
|
||||||
|
# if defined(CONFIG_PWM_NCHANNELS) && CONFIG_PWM_NCHANNELS > 1
|
||||||
|
# define LEDC_TIM1_CHANS CONFIG_ESP32C3_LEDC_TIM1_CHANNELS
|
||||||
|
# else
|
||||||
|
# define LEDC_TIM1_CHANS (1)
|
||||||
|
# endif
|
||||||
|
# define LEDC_TIM1_CHANS_OFF (LEDC_TIM0_CHANS_OFF + LEDC_TIM0_CHANS)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* LEDC timer2 channels and offset */
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32C3_LEDC_TIM2
|
||||||
|
# if defined(CONFIG_PWM_NCHANNELS) && CONFIG_PWM_NCHANNELS > 1
|
||||||
|
# define LEDC_TIM2_CHANS CONFIG_ESP32C3_LEDC_TIM2_CHANNELS
|
||||||
|
# else
|
||||||
|
# define LEDC_TIM2_CHANS (1)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# define LEDC_TIM2_CHANS_OFF (LEDC_TIM1_CHANS_OFF + LEDC_TIM1_CHANS)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* LEDC clock resource */
|
||||||
|
|
||||||
|
#define LEDC_CLK_RES (1) /* APB clock */
|
||||||
|
|
||||||
|
/* LEDC timer max reload */
|
||||||
|
|
||||||
|
#define LEDC_RELOAD_MAX (16384) /* 2^14 */
|
||||||
|
|
||||||
|
/* LEDC timer max clock divider parameter */
|
||||||
|
|
||||||
|
#define LEDC_CLKDIV_MAX (1024) /* 2^10 */
|
||||||
|
|
||||||
|
/* LEDC timer registers mapping */
|
||||||
|
|
||||||
|
#define LEDC_TIMER_REG(r, n) ((r) + (n) * (LEDC_TIMER1_CONF_REG - \
|
||||||
|
LEDC_TIMER2_CONF_REG))
|
||||||
|
|
||||||
|
/* LEDC timer channel registers mapping */
|
||||||
|
|
||||||
|
#define LEDC_CHAN_REG(r, n) ((r) + (n) * (LEDC_CH0_CONF0_REG - \
|
||||||
|
LEDC_CH1_CONF0_REG))
|
||||||
|
|
||||||
|
#define SET_TIMER_BITS(t, r, b) setbits(b, LEDC_TIMER_REG(r, (t)->num));
|
||||||
|
#define SET_TIMER_REG(t, r, v) putreg32(v, LEDC_TIMER_REG(r, (t)->num));
|
||||||
|
|
||||||
|
#define SET_CHAN_BITS(c, r, b) setbits(b, LEDC_CHAN_REG(r, (c)->num));
|
||||||
|
#define SET_CHAN_REG(c, r, v) putreg32(v, LEDC_CHAN_REG(r, (c)->num));
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
|
# define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* LEDC timer channel configuration */
|
||||||
|
|
||||||
|
struct esp32c3_ledc_chan_s
|
||||||
|
{
|
||||||
|
const uint8_t num; /* Timer channel ID */
|
||||||
|
const uint8_t pin; /* Timer channel GPIO pin number */
|
||||||
|
|
||||||
|
uint16_t duty; /* Timer channel current duty */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This structure represents the state of one LEDC timer */
|
||||||
|
|
||||||
|
struct esp32c3_ledc_s
|
||||||
|
{
|
||||||
|
const struct pwm_ops_s *ops; /* PWM operations */
|
||||||
|
|
||||||
|
const uint8_t num; /* Timer ID */
|
||||||
|
|
||||||
|
const uint8_t channels; /* Timer channels number */
|
||||||
|
struct esp32c3_ledc_chan_s *chans; /* Timer channels pointer */
|
||||||
|
|
||||||
|
uint32_t frequency; /* Timer current frequency */
|
||||||
|
uint32_t reload; /* Timer current reload */
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Function Prototypes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int pwm_setup(struct pwm_lowerhalf_s *dev);
|
||||||
|
static int pwm_shutdown(struct pwm_lowerhalf_s *dev);
|
||||||
|
static int pwm_start(struct pwm_lowerhalf_s *dev,
|
||||||
|
const struct pwm_info_s *info);
|
||||||
|
static int pwm_stop(struct pwm_lowerhalf_s *dev);
|
||||||
|
static int pwm_ioctl(struct pwm_lowerhalf_s *dev, int cmd,
|
||||||
|
unsigned long arg);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* LEDC PWM operations */
|
||||||
|
|
||||||
|
static const struct pwm_ops_s g_pwmops =
|
||||||
|
{
|
||||||
|
.setup = pwm_setup,
|
||||||
|
.shutdown = pwm_shutdown,
|
||||||
|
.start = pwm_start,
|
||||||
|
.stop = pwm_stop,
|
||||||
|
.ioctl = pwm_ioctl
|
||||||
|
};
|
||||||
|
|
||||||
|
/* LEDC channels table */
|
||||||
|
|
||||||
|
static struct esp32c3_ledc_chan_s g_ledc_chans[LEDC_CHANNELS] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.num = 0,
|
||||||
|
.pin = CONFIG_ESP32C3_LEDC_CHANNEL0_PIN
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
.num = 1,
|
||||||
|
.pin = CONFIG_ESP32C3_LEDC_CHANNEL1_PIN
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
.num = 2,
|
||||||
|
.pin = CONFIG_ESP32C3_LEDC_CHANNEL2_PIN
|
||||||
|
},
|
||||||
|
|
||||||
|
#if LEDC_CHANNELS > 3
|
||||||
|
{
|
||||||
|
.num = 3,
|
||||||
|
.pin = CONFIG_ESP32C3_LEDC_CHANNEL3_PIN
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
.num = 4,
|
||||||
|
.pin = CONFIG_ESP32C3_LEDC_CHANNEL4_PIN
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
.num = 5,
|
||||||
|
.pin = CONFIG_ESP32C3_LEDC_CHANNEL5_PIN
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/* LEDC timer0 private data */
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32C3_LEDC_TIM0
|
||||||
|
static struct esp32c3_ledc_s g_pwm0dev =
|
||||||
|
{
|
||||||
|
.ops = &g_pwmops,
|
||||||
|
.num = 0,
|
||||||
|
.channels = LEDC_TIM0_CHANS,
|
||||||
|
.chans = &g_ledc_chans[LEDC_TIM0_CHANS_OFF]
|
||||||
|
};
|
||||||
|
#endif /* CONFIG_ESP32C3_LEDC_TIM0 */
|
||||||
|
|
||||||
|
/* LEDC timer1 private data */
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32C3_LEDC_TIM1
|
||||||
|
static struct esp32c3_ledc_s g_pwm1dev =
|
||||||
|
{
|
||||||
|
.ops = &g_pwmops,
|
||||||
|
.num = 1,
|
||||||
|
.channels = LEDC_TIM1_CHANS,
|
||||||
|
.chans = &g_ledc_chans[LEDC_TIM1_CHANS_OFF]
|
||||||
|
};
|
||||||
|
#endif /* CONFIG_ESP32C3_LEDC_TIM1 */
|
||||||
|
|
||||||
|
/* LEDC timer2 private data */
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32C3_LEDC_TIM2
|
||||||
|
static struct esp32c3_ledc_s g_pwm2dev =
|
||||||
|
{
|
||||||
|
.ops = &g_pwmops,
|
||||||
|
.num = 2,
|
||||||
|
.channels = LEDC_TIM2_CHANS,
|
||||||
|
.chans = &g_ledc_chans[LEDC_TIM2_CHANS_OFF]
|
||||||
|
};
|
||||||
|
#endif /* CONFIG_ESP32C3_LEDC_TIM2 */
|
||||||
|
|
||||||
|
/* Clock reference count */
|
||||||
|
|
||||||
|
static uint32_t g_clk_ref;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: ledc_enable_clk
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Enable LEDC clock.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* NOne
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void ledc_enable_clk(void)
|
||||||
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
if (!g_clk_ref)
|
||||||
|
{
|
||||||
|
setbits(SYSTEM_LEDC_CLK_EN, SYSTEM_PERIP_CLK_EN0_REG);
|
||||||
|
resetbits(SYSTEM_LEDC_RST, SYSTEM_PERIP_RST_EN0_REG);
|
||||||
|
|
||||||
|
putreg32(LEDC_CLK_RES, LEDC_CONF_REG);
|
||||||
|
|
||||||
|
pwminfo("Enable ledc clock\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clk_ref++;
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: ledc_disable_clk
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Disable LEDC clock.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* NOne
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void ledc_disable_clk(void)
|
||||||
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
g_clk_ref--;
|
||||||
|
|
||||||
|
if (!g_clk_ref)
|
||||||
|
{
|
||||||
|
pwminfo("Disable ledc clock\n");
|
||||||
|
|
||||||
|
setbits(SYSTEM_LEDC_RST, SYSTEM_PERIP_RST_EN0_REG);
|
||||||
|
resetbits(SYSTEM_LEDC_CLK_EN, SYSTEM_PERIP_CLK_EN0_REG);
|
||||||
|
}
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: setup_timer
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Setup LEDC timer frequency and reload.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* priv - A reference to the LEDC timer state structure
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void setup_timer(struct esp32c3_ledc_s *priv)
|
||||||
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
uint32_t regval;
|
||||||
|
uint32_t reload;
|
||||||
|
uint32_t prescaler;
|
||||||
|
uint32_t shift = 1;
|
||||||
|
uint64_t pwmclk = esp32c3_clk_apb_freq();
|
||||||
|
|
||||||
|
/* Reset timer */
|
||||||
|
|
||||||
|
SET_TIMER_BITS(priv, LEDC_TIMER0_CONF_REG, LEDC_TIMER0_RST);
|
||||||
|
|
||||||
|
/* Calculate optimal values for the timer prescaler and for the timer
|
||||||
|
* modulo register. If' frequency' is the desired frequency, then
|
||||||
|
*
|
||||||
|
* tpmclk = pwmclk / presc
|
||||||
|
* frequency = tpmclk / reload
|
||||||
|
*
|
||||||
|
* ==>
|
||||||
|
*
|
||||||
|
* reload = pwmclk / presc / frequency
|
||||||
|
*
|
||||||
|
* In ESP32-C3, there are 4 clock resources for PWM:
|
||||||
|
*
|
||||||
|
* 1. APB clock (80 MHz)
|
||||||
|
* 2. RTC clock (8 MHz)
|
||||||
|
* 3. XTAL clock (depends on hardware, generally is 40 MHz)
|
||||||
|
* 4. REF clock (this is APB clock divided, generally is 1 MHz)
|
||||||
|
*
|
||||||
|
* We mostly use APB clock generally.
|
||||||
|
*
|
||||||
|
* There are many solutions to this, but the best solution will be the one
|
||||||
|
* that has the largest reload value and the smallest prescaler value.
|
||||||
|
* That is the solution that should give us the most accuracy in the timer
|
||||||
|
* control. Subject to:
|
||||||
|
*
|
||||||
|
* 2 <= presc <= 2^14(16,384)
|
||||||
|
* 1 <= clkdiv <= 2^10
|
||||||
|
*
|
||||||
|
* clkdiv has 8-bit decimal precision, so
|
||||||
|
* clkdiv = pwmclk * 256 / 16384 / frequency would be optimal.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* pwmclk = 80 MHz
|
||||||
|
* frequency = 100 Hz
|
||||||
|
*
|
||||||
|
* presc = 80,000,000 * 256 / 16,384 / 100
|
||||||
|
* = 12,500
|
||||||
|
* timclk = 80,000,000 / (12,500 / 256)
|
||||||
|
* = 1,638,400
|
||||||
|
* counter = 1,638,400 / 100
|
||||||
|
* = 16,384
|
||||||
|
* = 2^14
|
||||||
|
* shift = 14
|
||||||
|
*/
|
||||||
|
|
||||||
|
reload = (pwmclk * 256 / priv->frequency + LEDC_CLKDIV_MAX) /
|
||||||
|
LEDC_CLKDIV_MAX;
|
||||||
|
if (reload == 0)
|
||||||
|
{
|
||||||
|
reload = 1;
|
||||||
|
}
|
||||||
|
else if (reload > LEDC_RELOAD_MAX)
|
||||||
|
{
|
||||||
|
reload = LEDC_RELOAD_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int c = 2; c <= LEDC_RELOAD_MAX; c *= 2)
|
||||||
|
{
|
||||||
|
if (c * 2 > reload)
|
||||||
|
{
|
||||||
|
reload = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
shift++;
|
||||||
|
}
|
||||||
|
|
||||||
|
prescaler = pwmclk * 256 / reload / priv->frequency;
|
||||||
|
|
||||||
|
pwminfo("PWM timer%" PRIu8 " frequency=%0.4f reload=%" PRIu32 " shift=%" \
|
||||||
|
PRIu32 " prescaler=%0.4f\n",
|
||||||
|
priv->num, (float)pwmclk / reload / ((float)prescaler / 256),
|
||||||
|
reload, shift, (float)prescaler / 256);
|
||||||
|
|
||||||
|
/* Store reload for channel duty */
|
||||||
|
|
||||||
|
priv->reload = reload;
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
/* Set timer clock divide and reload */
|
||||||
|
|
||||||
|
regval = (shift << LEDC_TIMER0_DUTY_RES_S) |
|
||||||
|
(prescaler << LEDC_CLK_DIV_TIMER0_S);
|
||||||
|
SET_TIMER_REG(priv, LEDC_TIMER0_CONF_REG, regval);
|
||||||
|
|
||||||
|
/* Update clock divide and reload to hardware */
|
||||||
|
|
||||||
|
SET_TIMER_BITS(priv, LEDC_TIMER0_CONF_REG, LEDC_TIMER0_PARA_UP);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: setup_channel
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Setup LEDC timer channel duty.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* priv - A reference to the LEDC timer state structure
|
||||||
|
* cn - Timer channel number
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void setup_channel(struct esp32c3_ledc_s *priv, int cn)
|
||||||
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
uint32_t regval;
|
||||||
|
struct esp32c3_ledc_chan_s *chan = &priv->chans[cn];
|
||||||
|
|
||||||
|
/* Duty cycle:
|
||||||
|
*
|
||||||
|
* duty cycle = duty / 65536 * reload (fractional value)
|
||||||
|
*/
|
||||||
|
|
||||||
|
regval = b16toi(chan->duty * priv->reload + b16HALF);
|
||||||
|
|
||||||
|
pwminfo("channel=%" PRIu8 " duty=%" PRIu16 "(%0.4f) regval=%" PRIu32 \
|
||||||
|
" reload=%" PRIu32 "\n",
|
||||||
|
chan->num, chan->duty, (float)chan->duty / UINT16_MAX,
|
||||||
|
regval, priv->reload);
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
/* Reset config 0 & 1 registers */
|
||||||
|
|
||||||
|
SET_CHAN_REG(chan, LEDC_CH0_CONF0_REG, 0);
|
||||||
|
SET_CHAN_REG(chan, LEDC_CH0_CONF1_REG, 0);
|
||||||
|
|
||||||
|
/* Set pulse phase 0 */
|
||||||
|
|
||||||
|
SET_CHAN_REG(chan, LEDC_CH0_HPOINT_REG, 0);
|
||||||
|
|
||||||
|
/* Duty register uses bits [18:4] */
|
||||||
|
|
||||||
|
SET_CHAN_REG(chan, LEDC_CH0_DUTY_REG, regval << 4);
|
||||||
|
|
||||||
|
/* Start GPIO output */
|
||||||
|
|
||||||
|
SET_CHAN_BITS(chan, LEDC_CH0_CONF0_REG, LEDC_SIG_OUT_EN_CH0);
|
||||||
|
|
||||||
|
/* Start Duty counter */
|
||||||
|
|
||||||
|
SET_CHAN_BITS(chan, LEDC_CH0_CONF1_REG, LEDC_DUTY_START_CH0);
|
||||||
|
|
||||||
|
/* Update duty and phase to hardware */
|
||||||
|
|
||||||
|
SET_CHAN_BITS(chan, LEDC_CH0_CONF0_REG, LEDC_PARA_UP_CH0);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: pwm_setup
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This method is called when the driver is opened. The lower half driver
|
||||||
|
* should configure and initialize the device so that it is ready for use.
|
||||||
|
* It should not, however, output pulses until the start method is called.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* dev - A reference to the lower half PWM driver state structure
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero on success; a negated errno value on failure
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int pwm_setup(struct pwm_lowerhalf_s *dev)
|
||||||
|
{
|
||||||
|
struct esp32c3_ledc_s *priv = (struct esp32c3_ledc_s *)dev;
|
||||||
|
|
||||||
|
pwminfo("PWM timer%d\n", priv->num);
|
||||||
|
|
||||||
|
ledc_enable_clk();
|
||||||
|
|
||||||
|
/* Setup channel GPIO pins */
|
||||||
|
|
||||||
|
for (int i = 0; i < priv->channels; i++)
|
||||||
|
{
|
||||||
|
pwminfo("channel%d --> pin%d\n", priv->chans[i].num,
|
||||||
|
priv->chans[i].pin);
|
||||||
|
|
||||||
|
esp32c3_configgpio(priv->chans[i].pin, OUTPUT | PULLUP);
|
||||||
|
esp32c3_gpio_matrix_out(priv->chans[i].pin,
|
||||||
|
LEDC_LS_SIG_OUT0_IDX + priv->chans[i].num,
|
||||||
|
0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: pwm_shutdown
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This method is called when the driver is closed. The lower half driver
|
||||||
|
* stop pulsed output, free any resources, disable the timer hardware, and
|
||||||
|
* put the system into the lowest possible power usage state
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* dev - A reference to the lower half PWM driver state structure
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero on success; a negated errno value on failure
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int pwm_shutdown(struct pwm_lowerhalf_s *dev)
|
||||||
|
{
|
||||||
|
struct esp32c3_ledc_s *priv = (struct esp32c3_ledc_s *)dev;
|
||||||
|
#ifdef CONFIG_PWM_NCHANNELS
|
||||||
|
int channels = MIN(priv->channels, CONFIG_PWM_NCHANNELS);
|
||||||
|
#else
|
||||||
|
int channels = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Stop timer */
|
||||||
|
|
||||||
|
pwm_stop(dev);
|
||||||
|
|
||||||
|
/* Clear timer and channel configuration */
|
||||||
|
|
||||||
|
priv->frequency = 0;
|
||||||
|
priv->reload = 0;
|
||||||
|
for (int i = 0; i < channels; i++)
|
||||||
|
{
|
||||||
|
priv->chans[i].duty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ledc_disable_clk();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: pwm_start
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* (Re-)initialize the timer resources and start the pulsed output
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* dev - A reference to the lower half PWM driver state structure
|
||||||
|
* info - A reference to the characteristics of the pulsed output
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero on success; a negated errno value on failure
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int pwm_start(struct pwm_lowerhalf_s *dev,
|
||||||
|
const struct pwm_info_s *info)
|
||||||
|
{
|
||||||
|
struct esp32c3_ledc_s *priv = (struct esp32c3_ledc_s *)dev;
|
||||||
|
#ifdef CONFIG_PWM_NCHANNELS
|
||||||
|
int channels = MIN(priv->channels, CONFIG_PWM_NCHANNELS);
|
||||||
|
#else
|
||||||
|
int channels = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pwminfo("PWM timer%d\n", priv->num);
|
||||||
|
|
||||||
|
/* Update timer with given PWM timer frequency */
|
||||||
|
|
||||||
|
if (priv->frequency != info->frequency)
|
||||||
|
{
|
||||||
|
priv->frequency = info->frequency;
|
||||||
|
setup_timer(priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update timer with given PWM channel duty */
|
||||||
|
|
||||||
|
for (int i = 0; i < channels; i++)
|
||||||
|
{
|
||||||
|
if (priv->chans[i].duty != info[i].duty)
|
||||||
|
{
|
||||||
|
priv->chans[i].duty = info[i].duty;
|
||||||
|
setup_channel(priv, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: pwm_stop
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Stop the pulsed output and reset the timer resources.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* dev - A reference to the lower half PWM driver state structure
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero on success; a negated errno value on failure
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int pwm_stop(struct pwm_lowerhalf_s *dev)
|
||||||
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
struct esp32c3_ledc_s *priv = (struct esp32c3_ledc_s *)dev;
|
||||||
|
|
||||||
|
pwminfo("PWM timer%d\n", priv->num);
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
/* Stop timer */
|
||||||
|
|
||||||
|
SET_TIMER_BITS(priv, LEDC_TIMER0_CONF_REG, LEDC_TIMER0_PAUSE);
|
||||||
|
|
||||||
|
/* Reset timer */
|
||||||
|
|
||||||
|
SET_TIMER_BITS(priv, LEDC_TIMER0_CONF_REG, LEDC_TIMER0_RST);
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: pwm_ioctl
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Lower-half logic may support platform-specific ioctl commands
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* dev - A reference to the lower half PWM driver state structure
|
||||||
|
* cmd - The ioctl command
|
||||||
|
* arg - The argument accompanying the ioctl command
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero on success; a negated errno value on failure
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int pwm_ioctl(struct pwm_lowerhalf_s *dev, int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_DEBUG_PWM_INFO
|
||||||
|
struct esp32c3_ledc_s *priv = (struct esp32c3_ledc_s *)dev;
|
||||||
|
|
||||||
|
pwminfo("PWM timer%d\n", priv->num);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return -ENOTTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: esp32c3_ledc_init
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Initialize one LEDC timer for use with the upper_level PWM driver.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* timer - A number identifying the timer use.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* On success, a pointer to the ESP32-C3 LEDC lower half PWM driver is
|
||||||
|
* returned. NULL is returned on any failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct pwm_lowerhalf_s *esp32c3_ledc_init(int timer)
|
||||||
|
{
|
||||||
|
struct esp32c3_ledc_s *lower = NULL;
|
||||||
|
|
||||||
|
pwminfo("TIM%u\n", timer);
|
||||||
|
|
||||||
|
switch (timer)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_ESP32C3_LEDC_TIM0
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
lower = &g_pwm0dev;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32C3_LEDC_TIM1
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
lower = &g_pwm1dev;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32C3_LEDC_TIM2
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
lower = &g_pwm2dev;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32C3_LEDC_TIM3
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
lower = &g_pwm3dev;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
pwmerr("ERROR: No such timer configured %d\n", timer);
|
||||||
|
lower = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (struct pwm_lowerhalf_s *)lower;
|
||||||
|
}
|
52
arch/risc-v/src/esp32c3/esp32c3_ledc.h
Normal file
52
arch/risc-v/src/esp32c3/esp32c3_ledc.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* arch/risc-v/src/esp32c3/esp32c3_ledc.h
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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 __ARCH_RISCV_SRC_ESP32C3_ESP32C3_LEDC_H
|
||||||
|
#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_LEDC_H
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
#include <nuttx/timers/pwm.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: esp32c3_ledc_init
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Initialize one LEDC timer for use with the upper_level PWM driver.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* timer - A number identifying the timer use.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* On success, a pointer to the ESP32-C3 LEDC lower half PWM driver is
|
||||||
|
* returned. NULL is returned on any failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct pwm_lowerhalf_s *esp32c3_ledc_init(int timer);
|
||||||
|
|
||||||
|
#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_LEDC_H */
|
2742
arch/risc-v/src/esp32c3/hardware/esp32c3_ledc.h
Normal file
2742
arch/risc-v/src/esp32c3/hardware/esp32c3_ledc.h
Normal file
File diff suppressed because it is too large
Load Diff
47
boards/risc-v/esp32c3/esp32c3-devkit/configs/pwm/defconfig
Normal file
47
boards/risc-v/esp32c3/esp32c3-devkit/configs/pwm/defconfig
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#
|
||||||
|
# This file is autogenerated: PLEASE DO NOT EDIT IT.
|
||||||
|
#
|
||||||
|
# You can use "make menuconfig" to make any modifications to the installed .config file.
|
||||||
|
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
|
||||||
|
# modifications.
|
||||||
|
#
|
||||||
|
# CONFIG_NSH_ARGCAT is not set
|
||||||
|
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
|
||||||
|
# CONFIG_NSH_CMDPARMS is not set
|
||||||
|
CONFIG_ARCH="risc-v"
|
||||||
|
CONFIG_ARCH_BOARD="esp32c3-devkit"
|
||||||
|
CONFIG_ARCH_BOARD_ESP32C3_DEVKIT=y
|
||||||
|
CONFIG_ARCH_CHIP="esp32c3"
|
||||||
|
CONFIG_ARCH_CHIP_ESP32C3=y
|
||||||
|
CONFIG_ARCH_CHIP_ESP32C3WROOM02=y
|
||||||
|
CONFIG_ARCH_INTERRUPTSTACK=1536
|
||||||
|
CONFIG_ARCH_RISCV=y
|
||||||
|
CONFIG_ARCH_STACKDUMP=y
|
||||||
|
CONFIG_BOARD_LOOPSPERMSEC=15000
|
||||||
|
CONFIG_BUILTIN=y
|
||||||
|
CONFIG_DEV_ZERO=y
|
||||||
|
CONFIG_ESP32C3_LEDC=y
|
||||||
|
CONFIG_ESP32C3_LEDC_TIM0=y
|
||||||
|
CONFIG_EXAMPLES_PWM=y
|
||||||
|
CONFIG_FS_PROCFS=y
|
||||||
|
CONFIG_IDLETHREAD_STACKSIZE=2048
|
||||||
|
CONFIG_INTELHEX_BINARY=y
|
||||||
|
CONFIG_LIBC_PERROR_STDOUT=y
|
||||||
|
CONFIG_LIBC_STRERROR=y
|
||||||
|
CONFIG_MAX_TASKS=8
|
||||||
|
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
|
||||||
|
CONFIG_NSH_ARCHINIT=y
|
||||||
|
CONFIG_NSH_BUILTIN_APPS=y
|
||||||
|
CONFIG_NSH_FILEIOSIZE=512
|
||||||
|
CONFIG_NSH_READLINE=y
|
||||||
|
CONFIG_NSH_STRERROR=y
|
||||||
|
CONFIG_PREALLOC_TIMERS=0
|
||||||
|
CONFIG_RAW_BINARY=y
|
||||||
|
CONFIG_RR_INTERVAL=200
|
||||||
|
CONFIG_SCHED_WAITPID=y
|
||||||
|
CONFIG_START_DAY=29
|
||||||
|
CONFIG_START_MONTH=11
|
||||||
|
CONFIG_START_YEAR=2019
|
||||||
|
CONFIG_SYSTEM_NSH=y
|
||||||
|
CONFIG_UART0_SERIAL_CONSOLE=y
|
||||||
|
CONFIG_USER_ENTRYPOINT="nsh_main"
|
@ -66,6 +66,10 @@ ifeq ($(CONFIG_ONESHOT),y)
|
|||||||
CSRCS += esp32c3_oneshot.c
|
CSRCS += esp32c3_oneshot.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_PWM),y)
|
||||||
|
CSRCS += esp32c3_ledc.c
|
||||||
|
endif
|
||||||
|
|
||||||
SCRIPTIN = $(SCRIPTDIR)$(DELIM)esp32c3.template.ld
|
SCRIPTIN = $(SCRIPTDIR)$(DELIM)esp32c3.template.ld
|
||||||
SCRIPTOUT = $(SCRIPTDIR)$(DELIM)esp32c3_out.ld
|
SCRIPTOUT = $(SCRIPTDIR)$(DELIM)esp32c3_out.ld
|
||||||
|
|
||||||
|
@ -181,5 +181,17 @@ int board_bmp180_initialize(int devno, int busno);
|
|||||||
int esp32c3_spiflash_init(void);
|
int esp32c3_spiflash_init(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: esp32c3_ledc_setup
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Initialize LEDC PWM and register the PWM device.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32C3_LEDC
|
||||||
|
int esp32c3_pwm_setup(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
#endif /* __BOARDS_RISCV_ESP32C3_ESP32C3_DEVKIT_SRC_ESP32C3_DEVKIT_H */
|
#endif /* __BOARDS_RISCV_ESP32C3_ESP32C3_DEVKIT_SRC_ESP32C3_DEVKIT_H */
|
||||||
|
@ -283,6 +283,14 @@ int esp32c3_bringup(void)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32C3_LEDC
|
||||||
|
ret = esp32c3_pwm_setup();
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "ERROR: esp32c3_pwm_setup() failed: %d\n", ret);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_ESP32C3_LEDC */
|
||||||
|
|
||||||
/* If we got here then perhaps not all initialization was successful, but
|
/* If we got here then perhaps not all initialization was successful, but
|
||||||
* at least enough succeeded to bring-up NSH with perhaps reduced
|
* at least enough succeeded to bring-up NSH with perhaps reduced
|
||||||
* capabilities.
|
* capabilities.
|
||||||
|
116
boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_ledc.c
Normal file
116
boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_ledc.c
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_ledc.c
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include <nuttx/board.h>
|
||||||
|
#include <nuttx/timers/pwm.h>
|
||||||
|
|
||||||
|
#include <arch/board/board.h>
|
||||||
|
|
||||||
|
#include "chip.h"
|
||||||
|
#include "esp32c3_ledc.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: esp32c3_pwm_setup
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Initialize LEDC PWM and register the PWM device.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int esp32c3_pwm_setup(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct pwm_lowerhalf_s *pwm;
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32C3_LEDC_TIM0
|
||||||
|
pwm = esp32c3_ledc_init(0);
|
||||||
|
if (!pwm)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "ERROR: Failed to get the LEDC PWM 0 lower half\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register the PWM driver at "/dev/pwm0" */
|
||||||
|
|
||||||
|
ret = pwm_register("/dev/pwm0", pwm);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "ERROR: pwm_register failed: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32C3_LEDC_TIM1
|
||||||
|
pwm = esp32c3_ledc_init(1);
|
||||||
|
if (!pwm)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "ERROR: Failed to get the LEDC PWM 1 lower half\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register the PWM driver at "/dev/pwm1" */
|
||||||
|
|
||||||
|
ret = pwm_register("/dev/pwm1", pwm);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "ERROR: pwm_register failed: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32C3_LEDC_TIM2
|
||||||
|
pwm = esp32c3_ledc_init(2);
|
||||||
|
if (!pwm)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "ERROR: Failed to get the LEDC PWM 2 lower half\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register the PWM driver at "/dev/pwm2" */
|
||||||
|
|
||||||
|
ret = pwm_register("/dev/pwm2", pwm);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "ERROR: pwm_register failed: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user