316 lines
8.8 KiB
C
316 lines
8.8 KiB
C
|
/*
|
||
|
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
|
||
|
*
|
||
|
* 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.
|
||
|
*/
|
||
|
|
||
|
/******************************************************************************
|
||
|
* @file ck_pwm.c
|
||
|
* @brief CSI Source File for PWM Driver
|
||
|
* @version V1.0
|
||
|
* @date 02. June 2017
|
||
|
******************************************************************************/
|
||
|
#include "ck_pwm.h"
|
||
|
#include "drv_pwm.h"
|
||
|
#include "soc.h"
|
||
|
|
||
|
#define ERR_PWM(errno) (CSI_DRV_ERRNO_PWM_BASE | errno)
|
||
|
|
||
|
#define PWM_NULL_PARAM_CHK(para) \
|
||
|
do { \
|
||
|
if (para == NULL) { \
|
||
|
return ERR_PWM(EDRV_PARAMETER); \
|
||
|
} \
|
||
|
} while (0)
|
||
|
|
||
|
typedef struct {
|
||
|
uint32_t base;
|
||
|
uint32_t irq;
|
||
|
uint32_t ch_num;
|
||
|
} ck_pwm_priv_t;
|
||
|
|
||
|
static ck_pwm_priv_t pwm_instance[CONFIG_PWM_NUM];
|
||
|
|
||
|
int32_t __attribute__((weak)) target_pwm_init(pin_t pwm_pin, uint32_t *ch_num, uint32_t *base, uint32_t *irq)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
\brief Initialize PWM Interface. 1. Initializes the resources needed for the PWM interface 2.registers event callback function
|
||
|
\param[in] pwm pin of gpio
|
||
|
\return handle pwm handle to operate.
|
||
|
*/
|
||
|
pwm_handle_t drv_pwm_initialize(pin_t pwm_pin)
|
||
|
{
|
||
|
uint32_t base = 0u;
|
||
|
uint32_t irq = 0u;
|
||
|
uint32_t ch_num = 0u;
|
||
|
|
||
|
int32_t idx = target_pwm_init(pwm_pin, &ch_num, &base, &irq);
|
||
|
|
||
|
if (idx < 0 || idx >= CONFIG_PWM_NUM) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
ck_pwm_priv_t *pwm_priv = &pwm_instance[idx];
|
||
|
|
||
|
pwm_priv->base = base;
|
||
|
pwm_priv->irq = irq;
|
||
|
pwm_priv->ch_num = ch_num;
|
||
|
|
||
|
return pwm_priv;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
\brief De-initialize PWM Interface. stops operation and releases the software resources used by the interface
|
||
|
\param[in] handle pwm handle to operate.
|
||
|
\return \ref execution_status
|
||
|
*/
|
||
|
int32_t drv_pwm_uninitialize(pwm_handle_t handle)
|
||
|
{
|
||
|
PWM_NULL_PARAM_CHK(handle);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
\brief config pwm mode.
|
||
|
\param[in] handle pwm handle to operate.
|
||
|
\param[in] sysclk configured system clock.
|
||
|
\param[in] period_us the PWM period in us
|
||
|
\param[in] duty the PMW duty. ( 0 - 10000 represents 0% - 100% ,other values are invalid)
|
||
|
\return \ref execution_status
|
||
|
*/
|
||
|
int32_t drv_pwm_config(pwm_handle_t handle, uint32_t sysclk, uint32_t period_us, uint32_t duty)
|
||
|
{
|
||
|
if (handle == NULL || duty > 10000) {
|
||
|
return ERR_PWM(EDRV_PARAMETER);
|
||
|
}
|
||
|
|
||
|
ck_pwm_priv_t *pwm_priv = handle;
|
||
|
uint32_t chn = pwm_priv->ch_num;
|
||
|
|
||
|
uint32_t counter = (sysclk / 1000000 * period_us);
|
||
|
|
||
|
if (counter >= 0xffff) {
|
||
|
return ERR_PWM(EDRV_PARAMETER);
|
||
|
}
|
||
|
|
||
|
uint32_t data_width;
|
||
|
|
||
|
data_width = (uint32_t)((counter * duty / 10000));
|
||
|
|
||
|
ck_pwm_reg_t *addr = (ck_pwm_reg_t *)(pwm_priv->base);
|
||
|
uint32_t ctl_tmp = addr->PWMCTL;
|
||
|
uint32_t temp;
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH0 || chn == CKENUM_PWM_CH1) {
|
||
|
ctl_tmp &= 0xfffffffe;
|
||
|
addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP;
|
||
|
|
||
|
temp = addr->PWM01LOAD;
|
||
|
temp &= 0xffff0000;
|
||
|
addr->PWM01LOAD = temp | counter;
|
||
|
|
||
|
temp = addr->PWM0CMP;
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH0) {
|
||
|
temp &= 0xffff0000;
|
||
|
addr->PWM0CMP = temp | data_width;
|
||
|
} else {
|
||
|
temp &= 0x0000ffff;
|
||
|
addr->PWM0CMP = temp | data_width << 16;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH2 || chn == CKENUM_PWM_CH3) {
|
||
|
ctl_tmp &= 0xfffffffd;
|
||
|
addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP << 1;
|
||
|
|
||
|
temp = addr->PWM01LOAD;
|
||
|
temp &= 0x0000ffff;
|
||
|
addr->PWM01LOAD = temp | counter << 16 ;
|
||
|
|
||
|
temp = addr->PWM1CMP;
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH2) {
|
||
|
temp &= 0xffff0000;
|
||
|
addr->PWM1CMP = temp | data_width;
|
||
|
} else {
|
||
|
temp &= 0x0000ffff;
|
||
|
addr->PWM1CMP = temp | data_width << 16;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH4 || chn == CKENUM_PWM_CH5) {
|
||
|
ctl_tmp &= 0xfffffffb;
|
||
|
addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP << 2;
|
||
|
|
||
|
temp = addr->PWM23LOAD;
|
||
|
temp &= 0xffff0000;
|
||
|
addr->PWM23LOAD = temp | counter;
|
||
|
|
||
|
temp = addr->PWM2CMP;
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH4) {
|
||
|
temp &= 0xffff0000;
|
||
|
addr->PWM2CMP = temp | data_width;
|
||
|
} else {
|
||
|
temp &= 0x0000ffff;
|
||
|
addr->PWM2CMP = temp | data_width << 16;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH6 || chn == CKENUM_PWM_CH7) {
|
||
|
ctl_tmp &= 0xfffffff7;
|
||
|
addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP << 3;
|
||
|
|
||
|
temp = addr->PWM23LOAD;
|
||
|
temp &= 0x0000ffff;
|
||
|
addr->PWM23LOAD = temp | counter << 16 ;
|
||
|
|
||
|
temp = addr->PWM3CMP;
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH6) {
|
||
|
temp &= 0xffff0000;
|
||
|
addr->PWM3CMP = temp | data_width;
|
||
|
} else {
|
||
|
temp &= 0x0000ffff;
|
||
|
addr->PWM3CMP = temp | data_width << 16;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH8 || chn == CKENUM_PWM_CH9) {
|
||
|
ctl_tmp &= 0xffffffef;
|
||
|
addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP << 4;
|
||
|
|
||
|
temp = addr->PWM45LOAD;
|
||
|
temp &= 0xffff0000;
|
||
|
addr->PWM45LOAD = temp | counter ;
|
||
|
|
||
|
temp = addr->PWM4CMP;
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH8) {
|
||
|
temp &= 0xffff0000;
|
||
|
addr->PWM4CMP = temp | data_width;
|
||
|
} else {
|
||
|
temp &= 0x0000ffff;
|
||
|
addr->PWM4CMP = temp | data_width << 16;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH10 || chn == CKENUM_PWM_CH11) {
|
||
|
ctl_tmp &= 0xffffffdf;
|
||
|
addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP << 5;
|
||
|
|
||
|
temp = addr->PWM45LOAD;
|
||
|
temp &= 0x0000ffff;
|
||
|
addr->PWM45LOAD = temp | counter << 16 ;
|
||
|
|
||
|
temp = addr->PWM5CMP;
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH10) {
|
||
|
temp &= 0xffff0000;
|
||
|
addr->PWM5CMP = temp | data_width;
|
||
|
} else {
|
||
|
temp &= 0x0000ffff;
|
||
|
addr->PWM5CMP = temp | data_width << 16;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
\brief start generate pwm signal.
|
||
|
\param[in] handle pwm handle to operate.
|
||
|
\param[in] pwm channel number.
|
||
|
\return \ref execution_status
|
||
|
*/
|
||
|
int32_t drv_pwm_start(pwm_handle_t handle)
|
||
|
{
|
||
|
PWM_NULL_PARAM_CHK(handle);
|
||
|
|
||
|
ck_pwm_priv_t *pwm_priv = handle;
|
||
|
ck_pwm_reg_t *addr = (ck_pwm_reg_t *)(pwm_priv->base);
|
||
|
uint32_t chn = pwm_priv->ch_num;
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH0 || chn == CKENUM_PWM_CH1) {
|
||
|
addr->PWMCFG |= 0x00000003; /* PWM0 output enable */
|
||
|
}
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH2 || chn == CKENUM_PWM_CH3) {
|
||
|
addr->PWMCFG |= 0x0000000C; /* PWM1 output enable */
|
||
|
}
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH4 || chn == CKENUM_PWM_CH5) {
|
||
|
addr->PWMCFG |= 0x00000030; /* PWM2 output enable */
|
||
|
}
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH6 || chn == CKENUM_PWM_CH7) {
|
||
|
addr->PWMCFG |= 0x000000C0; /* PWM3 output enable */
|
||
|
}
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH8 || chn == CKENUM_PWM_CH9) {
|
||
|
addr->PWMCFG |= 0x00000300; /* PWM4 output enable */
|
||
|
}
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH10 || chn == CKENUM_PWM_CH11) {
|
||
|
addr->PWMCFG |= 0x00000C00; /* PWM5 output enable */
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
\brief Stop generate pwm signal.
|
||
|
\param[in] handle pwm handle to operate.
|
||
|
\return \ref execution_status
|
||
|
*/
|
||
|
int32_t drv_pwm_stop(pwm_handle_t handle)
|
||
|
{
|
||
|
PWM_NULL_PARAM_CHK(handle);
|
||
|
|
||
|
ck_pwm_priv_t *pwm_priv = handle;
|
||
|
ck_pwm_reg_t *addr = (ck_pwm_reg_t *)(pwm_priv->base);
|
||
|
uint32_t chn = pwm_priv->ch_num;
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH0 || chn == CKENUM_PWM_CH1) {
|
||
|
addr->PWMCFG &= ~0x00000003; /* PWM0 output disable */
|
||
|
}
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH2 || chn == CKENUM_PWM_CH3) {
|
||
|
addr->PWMCFG &= ~0x0000000C; /* PWM1 output disable */
|
||
|
}
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH4 || chn == CKENUM_PWM_CH5) {
|
||
|
addr->PWMCFG &= ~0x00000030; /* PWM2 output disable */
|
||
|
}
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH6 || chn == CKENUM_PWM_CH7) {
|
||
|
addr->PWMCFG &= ~0x000000C0; /* PWM3 output disable */
|
||
|
}
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH8 || chn == CKENUM_PWM_CH9) {
|
||
|
addr->PWMCFG &= ~0x00000300; /* PWM4 output disable */
|
||
|
}
|
||
|
|
||
|
if (chn == CKENUM_PWM_CH10 || chn == CKENUM_PWM_CH11) {
|
||
|
addr->PWMCFG &= ~0x00000C00; /* PWM5 output disable */
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|