diff --git a/freertos/cvitek/driver/pwm/CMakeLists.txt b/freertos/cvitek/driver/pwm/CMakeLists.txt new file mode 100644 index 0000000000..16768b30cd --- /dev/null +++ b/freertos/cvitek/driver/pwm/CMakeLists.txt @@ -0,0 +1,11 @@ +file(GLOB _SOURCES "src/*.c") +file(GLOB _HEADERS "include/*.h") + +include_directories(include) +include_directories(${CMAKE_INSTALL_INC_PREFIX}/arch) +include_directories(${CMAKE_INSTALL_INC_PREFIX}/common) +include_directories(${CMAKE_INSTALL_INC_PREFIX}/kernel) + +add_library(pwm OBJECT ${_SOURCES}) + +install(FILES ${_HEADERS} DESTINATION include/driver/pwm) diff --git a/freertos/cvitek/hal/cv181x/pwm/drv_pwm.h b/freertos/cvitek/driver/pwm/include/pwm.h similarity index 54% rename from freertos/cvitek/hal/cv181x/pwm/drv_pwm.h rename to freertos/cvitek/driver/pwm/include/pwm.h index 6312824519..5019fc89b0 100644 --- a/freertos/cvitek/hal/cv181x/pwm/drv_pwm.h +++ b/freertos/cvitek/driver/pwm/include/pwm.h @@ -1,277 +1,194 @@ -#ifndef __DRV_PWM_H__ -#define __DRV_PWM_H__ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define __IM volatile const /*! Defines 'read only' structure member permissions */ -#define __OM volatile /*! Defines 'write only' structure member permissions */ -#define __IOM volatile /*! Defines 'read / write' structure member permissions */ - -#define CVI_PWM0_BASE 0x03060000 -#define CVI_PWM1_BASE 0x03061000 -#define CVI_PWM2_BASE 0x03062000 -#define CVI_PWM3_BASE 0x03063000 -#define PWM_MAX_CH 3 - -typedef enum { - PWM_CHANNEL_0 = 0U, - PWM_CHANNEL_1, - PWM_CHANNEL_2, - PWM_CHANNEL_3, - PWM_CHANNEL_4, - PWM_CHANNEL_5, - PWM_CHANNEL_6, - PWM_CHANNEL_7, - PWM_CHANNEL_8, - PWM_CHANNEL_9, - PWM_CHANNEL_10, - PWM_CHANNEL_11, - PWM_CHANNEL_12, - PWM_CHANNEL_13, - PWM_CHANNEL_14, - PWM_CHANNEL_15, - PWM_CHANNEL_NUM -} cvi_pwm_channel_t; - - -struct cvi_pwm_regs_t { - uint32_t HLPERIOD0; - uint32_t PERIOD0; - uint32_t HLPERIOD1; - uint32_t PERIOD1; - uint32_t HLPERIOD2; - uint32_t PERIOD2; - uint32_t HLPERIOD3; - uint32_t PERIOD3; - uint32_t CAP_FREQNUM; - uint32_t CAP_FREQDATA; - uint32_t POLARITY; - uint32_t PWMSTART; - uint32_t PWMDONE; - uint32_t PWMUPDATE; - uint32_t PCOUNT0; - uint32_t PCOUNT1; - uint32_t PCOUNT2; - uint32_t PCOUNT3; - uint32_t PULSECOUNT0; - uint32_t PULSECOUNT1; - uint32_t PULSECOUNT2; - uint32_t PULSECOUNT3; - uint32_t SHIFTCOUNT0; - uint32_t SHIFTCOUNT1; - uint32_t SHIFTCOUNT2; - uint32_t SHIFTCOUNT3; - uint32_t SHIFTSTART; - uint32_t CAP_FREQEN; - uint32_t CAP_FREQDONE_NUM; - uint32_t PWM_OE; -}; - - -static struct cvi_pwm_regs_t cv182x_pwm_reg = { - .HLPERIOD0 = 0x0, - .PERIOD0 = 0x4, - .HLPERIOD1 = 0x8, - .PERIOD1 = 0xc, - .HLPERIOD2 = 0x10, - .PERIOD2 = 0x14, - .HLPERIOD3 = 0x18, - .PERIOD3 = 0x1c, - .CAP_FREQNUM = 0x20, - .CAP_FREQDATA = 0x24, - .POLARITY = 0x40, - .PWMSTART = 0x44, - .PWMDONE = 0x48, - .PWMUPDATE = 0x4c, - .PCOUNT0 = 0x50, - .PCOUNT1 = 0x54, - .PCOUNT2 = 0x58, - .PCOUNT3 = 0x5c, - .PULSECOUNT0 = 0x60, - .PULSECOUNT1 = 0x64, - .PULSECOUNT2 = 0x68, - .PULSECOUNT3 = 0x6c, - .SHIFTCOUNT0 = 0x80, - .SHIFTCOUNT1 = 0x84, - .SHIFTCOUNT2 = 0x88, - .SHIFTCOUNT3 = 0x8c, - .SHIFTSTART = 0x90, - .CAP_FREQEN = 0x9c, - .CAP_FREQDONE_NUM = 0xC0, - .PWM_OE = 0xd0, -}; - -struct pwm_configuration { - uint32_t channel; - uint32_t period; - uint32_t pulse; -}; - -static struct cvi_pwm_regs_t *cvi_pwm_reg = &cv182x_pwm_reg; - -#define PWM_HLPERIOD0(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->HLPERIOD0)) -#define PWM_PERIOD0(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->PERIOD0)) -#define PWM_HLPERIOD1(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->HLPERIOD1)) -#define PWM_PERIOD1(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->PERIOD1)) -#define PWM_HLPERIOD2(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->HLPERIOD2)) -#define PWM_PERIOD2(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->PERIOD2)) -#define PWM_HLPERIOD3(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->HLPERIOD3)) -#define PWM_PERIOD3(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->PERIOD3)) -#define PWM_HLPERIODX(reg_base, _ch_) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->HLPERIOD0 + (_ch_ << 3))) -#define PWM_PERIODX(reg_base, _ch_) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->PERIOD0 * (1 + (_ch_ << 1)))) - -#define CAP_FREQNUM(reg_base, _ch_) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->CAP_FREQNUM + _ch_ * 8)) -#define CAP_FREQDATA(reg_base, _ch_) *((__IM uint32_t *)(reg_base + cvi_pwm_reg->CAP_FREQDATA + _ch_ * 8)) - -#define PWM_POLARITY(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->POLARITY)) -#define PWM_PWMSTART(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->PWMSTART)) -#define PWM_PWMDONE(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->PWMDONE)) -#define PWM_PWMUPDATE(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->PWMUPDATE)) - -#define PWM_PCOUNT0(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->PCOUNT0)) -#define PWM_PCOUNT1(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->PCOUNT1)) -#define PWM_PCOUNT2(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->PCOUNT2)) -#define PWM_PCOUNT3(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->PCOUNT3)) - -#define PWM_PULSECOUNT0(reg_base) *((__IM uint32_t *)(reg_base + cvi_pwm_reg->PULSECOUNT0)) -#define PWM_PULSECOUNT1(reg_base) *((__IM uint32_t *)(reg_base + cvi_pwm_reg->PULSECOUNT1)) -#define PWM_PULSECOUNT2(reg_base) *((__IM uint32_t *)(reg_base + cvi_pwm_reg->PULSECOUNT2)) -#define PWM_PULSECOUNT3(reg_base) *((__IM uint32_t *)(reg_base + cvi_pwm_reg->PULSECOUNT3)) - -#define PWM_SHIFTCOUNT0(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->SHIFTCOUNT0)) -#define PWM_SHIFTCOUNT1(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->SHIFTCOUNT1)) -#define PWM_SHIFTCOUNT2(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->SHIFTCOUNT2)) -#define PWM_SHIFTCOUNT3(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->SHIFTCOUNT3)) -#define PWM_SHIFTSTART(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->SHIFTSTART)) - -#define CAP_FREQEN(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->CAP_FREQEN)) -#define CAP_FREQDONE_NUM(reg_base, _ch_) *((__IM uint32_t *)(reg_base + cvi_pwm_reg->CAP_FREQDONE_NUM + _ch_ * 4)) - -#define PWM_PWM_OE(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg->PWM_OE)) - - -/*! PWM Configure Register, offset: 0x00 */ -#define CVI_PWM_HIGH_PERIOD_Pos (0U) -#define CVI_PWM_HIGH_PERIOD_Msk (0xffffffff) - -#define CVI_PWM_PERIOD_Pos (0U) -#define CVI_PWM_PERIOD_Msk (0xffffffff) - -#define CVI_PWM_POLARITY_CH_Pos(_ch_) (_ch_) -#define CVI_PWM_POLARITY_CH_Msk(_ch_) (1U << CVI_PWM_POLARITY_CH_Pos(_ch_)) -#define CVI_PWM_POLARITY_CH_HIGH(_ch_) CVI_PWM_POLARITY_CH_Msk(_ch_) - -#define CVI_PWM_START_CH_Pos(_ch_) (_ch_) -#define CVI_PWM_START_CH_Msk(_ch_) (1U << CVI_PWM_START_CH_Pos(_ch_)) -#define CVI_PWM_START_CH_EN(_ch_) CVI_PWM_START_CH_Msk(_ch_) - -#define CVI_PWM_OUTPUT_CH_Pos(_ch_) (_ch_) -#define CVI_PWM_OUTPUT_CH_Msk(_ch_) (1U << CVI_PWM_OUTPUT_CH_Pos(_ch_)) -#define CVI_PWM_OUTPUT_CH_EN(_ch_) CVI_PWM_OUTPUT_CH_Msk(_ch_) - -#define CVI_CAP_FREQNUM_CH_Pos (0U) -#define CVI_CAP_FREQNUM_CH_Msk (0xffffffff) - -#define CVI_CAP_FREQEN_Pos(_ch_) (_ch_) -#define CVI_CAP_FREQEN_Msk(_ch_) (1U << CVI_CAP_FREQEN_Pos(_ch_)) -#define CVI_CAP_FREQEN(_ch_) CVI_CAP_FREQEN_Msk(_ch_) - -#define CVI_CAP_FREQDONE_NUM_Poa (0U) -#define CVI_CAP_FREQDONE_NUM_Msk (0xffffffff) - -#define CVI_CAP_FREQDATA_pos (0U) -#define CVI_CAP_FREQDATA_msk (0xffffffff) - -static inline void cvi_pwm_set_high_period_ch(unsigned long reg_base, uint32_t ch, unsigned long long value) -{ - PWM_HLPERIODX(reg_base, ch) = value; -} - -static inline unsigned long long cvi_pwm_get_high_period_ch(unsigned long reg_base, uint32_t ch) -{ - return PWM_HLPERIODX(reg_base, ch); -} - -static inline void cvi_pwm_set_period_ch(unsigned long reg_base, uint32_t ch, unsigned long long value) -{ - PWM_PERIODX(reg_base, ch) = value; -} - -static inline unsigned long long cvi_pwm_get_period_ch(unsigned long reg_base, uint32_t ch) -{ - return PWM_PERIODX(reg_base, ch); -} - -static inline void cvi_pwm_set_polarity_high_ch(unsigned long reg_base, uint32_t ch) -{ - PWM_POLARITY(reg_base) |= CVI_PWM_POLARITY_CH_HIGH(ch); -} - -static inline void cvi_pwm_set_polarity_low_ch(unsigned long reg_base, uint32_t ch) -{ - PWM_POLARITY(reg_base) &= ~CVI_PWM_POLARITY_CH_HIGH(ch); -} - -static inline uint32_t cvi_pwm_get_polarity(unsigned long reg_base, uint32_t ch) -{ - return (PWM_POLARITY(reg_base) & CVI_PWM_POLARITY_CH_Msk(ch)); -} - -static inline void cvi_pwm_start_en_ch(unsigned long reg_base, uint32_t ch) -{ - PWM_PWMSTART(reg_base) |= CVI_PWM_START_CH_EN(ch); -} - -static inline void cvi_pwm_start_dis_ch(unsigned long reg_base, uint32_t ch) -{ - PWM_PWMSTART(reg_base) &= ~CVI_PWM_START_CH_EN(ch); -} - -static inline void cvi_pwm_output_en_ch(unsigned long reg_base, uint32_t ch) -{ - PWM_PWM_OE(reg_base) |= CVI_PWM_OUTPUT_CH_EN(ch); -} - -static inline void cvi_pwm_input_en_ch(unsigned long reg_base, uint32_t ch) -{ - PWM_PWM_OE(reg_base) &= ~CVI_PWM_OUTPUT_CH_EN(ch); -} - -static inline void cvi_cap_set_freqnum_ch(unsigned long reg_base, uint32_t ch, uint32_t value) -{ - CAP_FREQNUM(reg_base, ch) = value; -} - -static inline void cvi_cap_freq_en_ch(unsigned long reg_base, uint32_t ch) -{ - CAP_FREQEN(reg_base) |= CVI_CAP_FREQEN(ch); -} - -static inline void cvi_cap_freq_dis_ch(unsigned long reg_base, uint32_t ch) -{ - CAP_FREQEN(reg_base) &= ~CVI_CAP_FREQEN(ch); -} - -static inline uint32_t cvi_cap_get_freq_done_num_ch(unsigned long reg_base, uint32_t ch) -{ - return CAP_FREQDONE_NUM(reg_base, ch); -} - -static inline uint32_t cvi_cap_get_freq_data_ch(unsigned long reg_base, uint32_t ch) -{ - return CAP_FREQDATA(reg_base, ch); -} - -#ifdef __cplusplus -} -#endif - -void pwm_init(uint8_t pwm_id, struct pwm_configuration *cfg); - -#endif +#ifndef __PWM_H__ +#define __PWM_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +#define CVI_PWM0_BASE 0x03060000 +#define CVI_PWM1_BASE 0x03061000 +#define CVI_PWM2_BASE 0x03062000 +#define CVI_PWM3_BASE 0x03063000 +#define PWM_MAX_CH 3 + +typedef enum { + PWM_CHANNEL_0 = 0U, + PWM_CHANNEL_1, + PWM_CHANNEL_2, + PWM_CHANNEL_3, + PWM_CHANNEL_4, + PWM_CHANNEL_5, + PWM_CHANNEL_6, + PWM_CHANNEL_7, + PWM_CHANNEL_8, + PWM_CHANNEL_9, + PWM_CHANNEL_10, + PWM_CHANNEL_11, + PWM_CHANNEL_12, + PWM_CHANNEL_13, + PWM_CHANNEL_14, + PWM_CHANNEL_15, + PWM_CHANNEL_NUM +} cvi_pwm_channel_t; + + +typedef struct{ + uint32_t HLPERIOD0; + uint32_t PERIOD0; + uint32_t HLPERIOD1; + uint32_t PERIOD1; + uint32_t HLPERIOD2; + uint32_t PERIOD2; + uint32_t HLPERIOD3; + uint32_t PERIOD3; + uint32_t CAP_FREQNUM; + uint32_t CAP_FREQDATA; + uint32_t POLARITY; + uint32_t PWMSTART; + uint32_t PWMDONE; + uint32_t PWMUPDATE; + uint32_t PCOUNT0; + uint32_t PCOUNT1; + uint32_t PCOUNT2; + uint32_t PCOUNT3; + uint32_t PULSECOUNT0; + uint32_t PULSECOUNT1; + uint32_t PULSECOUNT2; + uint32_t PULSECOUNT3; + uint32_t SHIFTCOUNT0; + uint32_t SHIFTCOUNT1; + uint32_t SHIFTCOUNT2; + uint32_t SHIFTCOUNT3; + uint32_t SHIFTSTART; + uint32_t CAP_FREQEN; + uint32_t CAP_FREQDONE_NUM; + uint32_t PWM_OE; +} cvi_pwm_regs_typedef; + +typedef struct cvi_pwm_dev +{ + const char *name; + uint32_t reg_base; +} cvi_pwm_dev_typedef; + +extern cvi_pwm_regs_typedef cvi_pwm_reg; +extern cvi_pwm_dev_typedef cvi_pwm[]; + +#define PWM_HLPERIOD0(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.HLPERIOD0)) +#define PWM_PERIOD0(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.PERIOD0)) +#define PWM_HLPERIOD1(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.HLPERIOD1)) +#define PWM_PERIOD1(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.PERIOD1)) +#define PWM_HLPERIOD2(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.HLPERIOD2)) +#define PWM_PERIOD2(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.PERIOD2)) +#define PWM_HLPERIOD3(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.HLPERIOD3)) +#define PWM_PERIOD3(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.PERIOD3)) +#define PWM_HLPERIODX(reg_base, _ch_) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.HLPERIOD0 + (_ch_ << 3))) +#define PWM_PERIODX(reg_base, _ch_) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.PERIOD0 * (1 + (_ch_ << 1)))) + +#define CAP_FREQNUM(reg_base, _ch_) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.CAP_FREQNUM + _ch_ * 8)) +#define CAP_FREQDATA(reg_base, _ch_) *((__IM uint32_t *)(reg_base + cvi_pwm_reg.CAP_FREQDATA + _ch_ * 8)) + +#define PWM_POLARITY(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.POLARITY)) +#define PWM_PWMSTART(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.PWMSTART)) +#define PWM_PWMDONE(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.PWMDONE)) +#define PWM_PWMUPDATE(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.PWMUPDATE)) + +#define PWM_PCOUNT0(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.PCOUNT0)) +#define PWM_PCOUNT1(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.PCOUNT1)) +#define PWM_PCOUNT2(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.PCOUNT2)) +#define PWM_PCOUNT3(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.PCOUNT3)) + +#define PWM_PULSECOUNT0(reg_base) *((__IM uint32_t *)(reg_base + cvi_pwm_reg.PULSECOUNT0)) +#define PWM_PULSECOUNT1(reg_base) *((__IM uint32_t *)(reg_base + cvi_pwm_reg.PULSECOUNT1)) +#define PWM_PULSECOUNT2(reg_base) *((__IM uint32_t *)(reg_base + cvi_pwm_reg.PULSECOUNT2)) +#define PWM_PULSECOUNT3(reg_base) *((__IM uint32_t *)(reg_base + cvi_pwm_reg.PULSECOUNT3)) + +#define PWM_SHIFTCOUNT0(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.SHIFTCOUNT0)) +#define PWM_SHIFTCOUNT1(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.SHIFTCOUNT1)) +#define PWM_SHIFTCOUNT2(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.SHIFTCOUNT2)) +#define PWM_SHIFTCOUNT3(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.SHIFTCOUNT3)) +#define PWM_SHIFTSTART(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.SHIFTSTART)) + +#define CAP_FREQEN(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.CAP_FREQEN)) +#define CAP_FREQDONE_NUM(reg_base, _ch_) *((__IM uint32_t *)(reg_base + cvi_pwm_reg.CAP_FREQDONE_NUM + _ch_ * 4)) + +#define PWM_PWM_OE(reg_base) *((__IOM uint32_t *)(reg_base + cvi_pwm_reg.PWM_OE)) + + +/*! PWM Configure Register, offset: 0x00 */ +#define CVI_PWM_HIGH_PERIOD_Pos (0U) +#define CVI_PWM_HIGH_PERIOD_Msk (0xffffffff) + +#define CVI_PWM_PERIOD_Pos (0U) +#define CVI_PWM_PERIOD_Msk (0xffffffff) + +#define CVI_PWM_POLARITY_CH_Pos(_ch_) (_ch_) +#define CVI_PWM_POLARITY_CH_Msk(_ch_) (1U << CVI_PWM_POLARITY_CH_Pos(_ch_)) +#define CVI_PWM_POLARITY_CH_HIGH(_ch_) CVI_PWM_POLARITY_CH_Msk(_ch_) + +#define CVI_PWM_MODE_CH_Pos(_ch_) (_ch_) +#define CVI_PWM_MODE_CH_Msk(_ch_) (1U << (CVI_PWM_MODE_CH_Pos(_ch_) + 8)) +#define CVI_PWM_MODE_CH_HIGH(_ch_) CVI_PWM_MODE_CH_Msk(_ch_) + +#define CVI_PWM_START_CH_Pos(_ch_) (_ch_) +#define CVI_PWM_START_CH_Msk(_ch_) (1U << CVI_PWM_START_CH_Pos(_ch_)) +#define CVI_PWM_START_CH_EN(_ch_) CVI_PWM_START_CH_Msk(_ch_) + +#define CVI_PWM_DONE_CH_Pos(_ch_) (_ch_) +#define CVI_PWM_DONE_CH_Msk(_ch_) (1U << CVI_PWM_DONE_CH_Pos(_ch_)) +#define CVI_PWM_DONE_CH_EN(_ch_) CVI_PWM_DONE_CH_Msk(_ch_) + +#define CVI_PWM_UPDATE_CH_Pos(_ch_) (_ch_) +#define CVI_PWM_UPDATE_CH_Msk(_ch_) (1U << CVI_PWM_UPDATE_CH_Pos(_ch_)) +#define CVI_PWM_UPDATE_CH_EN(_ch_) CVI_PWM_UPDATE_CH_Msk(_ch_) + +#define CVI_PWM_OUTPUT_CH_Pos(_ch_) (_ch_) +#define CVI_PWM_OUTPUT_CH_Msk(_ch_) (1U << CVI_PWM_OUTPUT_CH_Pos(_ch_)) +#define CVI_PWM_OUTPUT_CH_EN(_ch_) CVI_PWM_OUTPUT_CH_Msk(_ch_) + +#define CVI_CAP_FREQNUM_CH_Pos (0U) +#define CVI_CAP_FREQNUM_CH_Msk (0xffffffff) + +#define CVI_CAP_FREQEN_Pos(_ch_) (_ch_) +#define CVI_CAP_FREQEN_Msk(_ch_) (1U << CVI_CAP_FREQEN_Pos(_ch_)) +#define CVI_CAP_FREQEN(_ch_) CVI_CAP_FREQEN_Msk(_ch_) + +#define CVI_CAP_FREQDONE_NUM_Poa (0U) +#define CVI_CAP_FREQDONE_NUM_Msk (0xffffffff) + +#define CVI_CAP_FREQDATA_pos (0U) +#define CVI_CAP_FREQDATA_msk (0xffffffff) + +#ifdef __cplusplus +} +#endif + +void cvi_pwm_set_high_period_ch(unsigned long reg_base, uint32_t ch, unsigned long long value); +unsigned long long cvi_pwm_get_high_period_ch(unsigned long reg_base, uint32_t ch); +void cvi_pwm_set_period_ch(unsigned long reg_base, uint32_t ch, unsigned long long value); +unsigned long long cvi_pwm_get_period_ch(unsigned long reg_base, uint32_t ch); +void cvi_pwm_set_polarity_high_ch(unsigned long reg_base, uint32_t ch); +void cvi_pwm_set_polarity_low_ch(unsigned long reg_base, uint32_t ch); +uint32_t cvi_pwm_get_polarity(unsigned long reg_base, uint32_t ch); +void cvi_pwm_set_pwm_mode_ch(unsigned long reg_base, uint32_t ch, uint8_t mode); +void cvi_pwm_start_en_ch(unsigned long reg_base, uint32_t ch); +void cvi_pwm_start_dis_ch(unsigned long reg_base, uint32_t ch); +void cvi_pwm_update_ch(unsigned long reg_base, uint32_t ch); +void cvi_pwm_pcount_ch(unsigned long reg_base, uint32_t ch, uint32_t value); +void cvi_pwm_output_en_ch(unsigned long reg_base, uint32_t ch); +void cvi_pwm_input_en_ch(unsigned long reg_base, uint32_t ch); +void cvi_cap_set_freqnum_ch(unsigned long reg_base, uint32_t ch, uint32_t value); +void cvi_cap_freq_en_ch(unsigned long reg_base, uint32_t ch); +void cvi_cap_freq_dis_ch(unsigned long reg_base, uint32_t ch); +uint32_t cvi_cap_get_freq_done_num_ch(unsigned long reg_base, uint32_t ch); +uint32_t cvi_cap_get_freq_data_ch(unsigned long reg_base, uint32_t ch); + +#endif diff --git a/freertos/cvitek/driver/pwm/src/pwm.c b/freertos/cvitek/driver/pwm/src/pwm.c new file mode 100644 index 0000000000..93e3eb0844 --- /dev/null +++ b/freertos/cvitek/driver/pwm/src/pwm.c @@ -0,0 +1,171 @@ +#include +#include +#include "pwm.h" + +cvi_pwm_dev_typedef cvi_pwm[] = +{ + { + .name = "pwm0", + .reg_base = CVI_PWM0_BASE, + }, + { + .name = "pwm1", + .reg_base = CVI_PWM1_BASE, + }, + { + .name = "pwm2", + .reg_base = CVI_PWM2_BASE, + }, + { + .name = "pwm3", + .reg_base = CVI_PWM3_BASE, + }, +}; + +cvi_pwm_regs_typedef cvi_pwm_reg = { + .HLPERIOD0 = 0x0, + .PERIOD0 = 0x4, + .HLPERIOD1 = 0x8, + .PERIOD1 = 0xc, + .HLPERIOD2 = 0x10, + .PERIOD2 = 0x14, + .HLPERIOD3 = 0x18, + .PERIOD3 = 0x1c, + .CAP_FREQNUM = 0x20, + .CAP_FREQDATA = 0x24, + .POLARITY = 0x40, + .PWMSTART = 0x44, + .PWMDONE = 0x48, + .PWMUPDATE = 0x4c, + .PCOUNT0 = 0x50, + .PCOUNT1 = 0x54, + .PCOUNT2 = 0x58, + .PCOUNT3 = 0x5c, + .PULSECOUNT0 = 0x60, + .PULSECOUNT1 = 0x64, + .PULSECOUNT2 = 0x68, + .PULSECOUNT3 = 0x6c, + .SHIFTCOUNT0 = 0x80, + .SHIFTCOUNT1 = 0x84, + .SHIFTCOUNT2 = 0x88, + .SHIFTCOUNT3 = 0x8c, + .SHIFTSTART = 0x90, + .CAP_FREQEN = 0x9c, + .CAP_FREQDONE_NUM = 0xC0, + .PWM_OE = 0xd0, +}; + +void cvi_pwm_set_high_period_ch(unsigned long reg_base, uint32_t ch, unsigned long long value) +{ + PWM_HLPERIODX(reg_base, ch) = value; +} + +unsigned long long cvi_pwm_get_high_period_ch(unsigned long reg_base, uint32_t ch) +{ + return PWM_HLPERIODX(reg_base, ch); +} + +void cvi_pwm_set_period_ch(unsigned long reg_base, uint32_t ch, unsigned long long value) +{ + PWM_PERIODX(reg_base, ch) = value; +} + +unsigned long long cvi_pwm_get_period_ch(unsigned long reg_base, uint32_t ch) +{ + return PWM_PERIODX(reg_base, ch); +} + +void cvi_pwm_set_polarity_high_ch(unsigned long reg_base, uint32_t ch) +{ + PWM_POLARITY(reg_base) |= CVI_PWM_POLARITY_CH_HIGH(ch); +} + +void cvi_pwm_set_polarity_low_ch(unsigned long reg_base, uint32_t ch) +{ + PWM_POLARITY(reg_base) &= ~CVI_PWM_POLARITY_CH_HIGH(ch); +} + +uint32_t cvi_pwm_get_polarity(unsigned long reg_base, uint32_t ch) +{ + return (PWM_POLARITY(reg_base) & CVI_PWM_POLARITY_CH_Msk(ch)); +} + +void cvi_pwm_set_pwm_mode_ch(unsigned long reg_base, uint32_t ch, uint8_t mode) +{ + if(mode) + PWM_POLARITY(reg_base) |= CVI_PWM_MODE_CH_HIGH(ch); + else + PWM_POLARITY(reg_base) &= ~CVI_PWM_MODE_CH_HIGH(ch); +} + +void cvi_pwm_start_en_ch(unsigned long reg_base, uint32_t ch) +{ + PWM_PWMSTART(reg_base) |= CVI_PWM_START_CH_EN(ch); +} + +void cvi_pwm_start_dis_ch(unsigned long reg_base, uint32_t ch) +{ + PWM_PWMSTART(reg_base) &= ~CVI_PWM_START_CH_EN(ch); +} + +void cvi_pwm_update_ch(unsigned long reg_base, uint32_t ch) +{ + PWM_PWMUPDATE(reg_base) |= CVI_PWM_UPDATE_CH_EN(ch); + PWM_PWMUPDATE(reg_base) &= ~CVI_PWM_UPDATE_CH_EN(ch); +} + +void cvi_pwm_pcount_ch(unsigned long reg_base, uint32_t ch, uint32_t value) +{ + switch (ch) + { + case PWM_CHANNEL_0: + PWM_PCOUNT0(reg_base) = value; + break; + case PWM_CHANNEL_1: + PWM_PCOUNT1(reg_base) = value; + break; + case PWM_CHANNEL_2: + PWM_PCOUNT2(reg_base) = value; + break; + case PWM_CHANNEL_3: + PWM_PCOUNT3(reg_base) = value; + break; + default: + break; + } +} + +void cvi_pwm_output_en_ch(unsigned long reg_base, uint32_t ch) +{ + PWM_PWM_OE(reg_base) |= CVI_PWM_OUTPUT_CH_EN(ch); +} + +void cvi_pwm_input_en_ch(unsigned long reg_base, uint32_t ch) +{ + PWM_PWM_OE(reg_base) &= ~CVI_PWM_OUTPUT_CH_EN(ch); +} + +void cvi_cap_set_freqnum_ch(unsigned long reg_base, uint32_t ch, uint32_t value) +{ + CAP_FREQNUM(reg_base, ch) = value; +} + +void cvi_cap_freq_en_ch(unsigned long reg_base, uint32_t ch) +{ + CAP_FREQEN(reg_base) |= CVI_CAP_FREQEN(ch); +} + +void cvi_cap_freq_dis_ch(unsigned long reg_base, uint32_t ch) +{ + CAP_FREQEN(reg_base) &= ~CVI_CAP_FREQEN(ch); +} + +uint32_t cvi_cap_get_freq_done_num_ch(unsigned long reg_base, uint32_t ch) +{ + return CAP_FREQDONE_NUM(reg_base, ch); +} + +uint32_t cvi_cap_get_freq_data_ch(unsigned long reg_base, uint32_t ch) +{ + return CAP_FREQDATA(reg_base, ch); +} diff --git a/freertos/cvitek/hal/cv180x/pwm b/freertos/cvitek/hal/cv180x/pwm new file mode 120000 index 0000000000..f22d411451 --- /dev/null +++ b/freertos/cvitek/hal/cv180x/pwm @@ -0,0 +1 @@ +../cv181x/pwm \ No newline at end of file diff --git a/freertos/cvitek/hal/cv181x/pwm/CMakeLists.txt b/freertos/cvitek/hal/cv181x/pwm/CMakeLists.txt new file mode 100644 index 0000000000..6cbace8b5e --- /dev/null +++ b/freertos/cvitek/hal/cv181x/pwm/CMakeLists.txt @@ -0,0 +1,14 @@ +file(GLOB _SOURCES "src/*.c") +file(GLOB _HEADERS "include/*.h") + +include_directories(include) +include_directories(../config) +include_directories(${TOP_DIR}/driver/pwm/include) + +include_directories(${CMAKE_INSTALL_INC_PREFIX}/arch) +include_directories(${CMAKE_INSTALL_INC_PREFIX}/common) +include_directories(${CMAKE_INSTALL_INC_PREFIX}/kernel) + +add_library(halpwm OBJECT ${_SOURCES}) + +install(FILES ${_HEADERS} DESTINATION include/hal/pwm) diff --git a/freertos/cvitek/hal/cv181x/pwm/drv_pwm.c b/freertos/cvitek/hal/cv181x/pwm/drv_pwm.c deleted file mode 100644 index c91507ad4b..0000000000 --- a/freertos/cvitek/hal/cv181x/pwm/drv_pwm.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -// #include "FreeRTOS.h" -// #include "task.h" -// #include "semphr.h" -#include "drv_pwm.h" - - -struct cvi_pwm_dev -{ - const char *name; - uint32_t reg_base; -}; - -static const uint64_t count_unit = 100000000; // 100M count per second -static const uint64_t NSEC_COUNT = 1000000000; // ns - -static void cvi_pwm_set_config(uint32_t reg_base, struct pwm_configuration *cfg) -{ - uint64_t duty_clk, period_clk; - - cvi_pwm_set_polarity_high_ch(reg_base, (cfg->channel & PWM_MAX_CH)); - - duty_clk = (cfg->pulse * count_unit) / NSEC_COUNT; - cvi_pwm_set_high_period_ch(reg_base, (cfg->channel & PWM_MAX_CH), duty_clk); - - period_clk = (cfg->period * count_unit) / NSEC_COUNT; - cvi_pwm_set_period_ch(reg_base, (cfg->channel & PWM_MAX_CH), period_clk); - - cvi_pwm_output_en_ch(reg_base, cfg->channel & PWM_MAX_CH); -} - -// 定义 PWM 设备 -static struct cvi_pwm_dev cvi_pwm[] = -{ - { - .name = "pwm0", - .reg_base = CVI_PWM0_BASE, - }, - { - .name = "pwm1", - .reg_base = CVI_PWM1_BASE, - }, - { - .name = "pwm2", - .reg_base = CVI_PWM2_BASE, - }, - { - .name = "pwm3", - .reg_base = CVI_PWM3_BASE, - }, -}; - -void pwm_init(uint8_t pwm_id, struct pwm_configuration *cfg) -{ - cvi_pwm_set_config(cvi_pwm[pwm_id].reg_base, cfg); -} diff --git a/freertos/cvitek/hal/cv181x/pwm/include/hal_pwm.h b/freertos/cvitek/hal/cv181x/pwm/include/hal_pwm.h new file mode 100644 index 0000000000..f5d882d65e --- /dev/null +++ b/freertos/cvitek/hal/cv181x/pwm/include/hal_pwm.h @@ -0,0 +1,41 @@ +#ifndef __DRV_PWM_H__ +#define __DRV_PWM_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PWM_ID_0 0 +#define PWM_ID_1 1 +#define PWM_ID_2 2 +#define PWM_ID_3 3 + +#define PWM_CHANNEL_0 0 +#define PWM_CHANNEL_1 1 +#define PWM_CHANNEL_2 2 +#define PWM_CHANNEL_3 3 + +typedef struct{ + uint8_t pwm_id; + uint32_t channel; + uint32_t period; + uint32_t pulse; +} pwm_configuration_t; + + +#ifdef __cplusplus +} +#endif + +void pwm_init(pwm_configuration_t *cfg); +void pwm_set_output_cfg(pwm_configuration_t *cfg); +void pwm_continuous_start(pwm_configuration_t *cfg); +void pwm_pulse_cnt_start(pwm_configuration_t *cfg, uint32_t cnt); +bool pwm_pulse_cnt_done(pwm_configuration_t *cfg); +void pwm_stop(pwm_configuration_t *cfg); + +#endif diff --git a/freertos/cvitek/hal/cv181x/pwm/src/hal_pwm.c b/freertos/cvitek/hal/cv181x/pwm/src/hal_pwm.c new file mode 100644 index 0000000000..b56a1ef3e0 --- /dev/null +++ b/freertos/cvitek/hal/cv181x/pwm/src/hal_pwm.c @@ -0,0 +1,70 @@ +#include +#include +#include "pwm.h" +#include "hal_pwm.h" + +const uint64_t count_unit = 100000000; // 100M count per second +const uint64_t NSEC_COUNT = 1000000000; // ns + +//设定 PWM 输出 +void pwm_init(pwm_configuration_t *cfg) +{ + uint32_t reg_base = cvi_pwm[cfg -> pwm_id].reg_base; + uint64_t duty_clk, period_clk; + + cvi_pwm_set_polarity_high_ch(reg_base, (cfg->channel & PWM_MAX_CH)); + + duty_clk = (cfg->pulse * count_unit) / NSEC_COUNT; + cvi_pwm_set_high_period_ch(reg_base, (cfg->channel & PWM_MAX_CH), duty_clk); + + period_clk = (cfg->period * count_unit) / NSEC_COUNT; + cvi_pwm_set_period_ch(reg_base, (cfg->channel & PWM_MAX_CH), period_clk); + + cvi_pwm_output_en_ch(reg_base, cfg->channel & PWM_MAX_CH); +} + +//设定 PWM 输出参数 +void pwm_set_output_cfg(pwm_configuration_t *cfg) +{ + uint64_t duty_clk, period_clk; + + duty_clk = (cfg->pulse * count_unit) / NSEC_COUNT; + cvi_pwm_set_high_period_ch(cvi_pwm[cfg -> pwm_id].reg_base, (cfg->channel & PWM_MAX_CH), duty_clk); + + period_clk = (cfg->period * count_unit) / NSEC_COUNT; + cvi_pwm_set_period_ch(cvi_pwm[cfg -> pwm_id].reg_base, (cfg->channel & PWM_MAX_CH), period_clk); + + if(PWM_PWMSTART(cvi_pwm[cfg -> pwm_id].reg_base) &= CVI_PWM_START_CH_EN(cfg->channel & PWM_MAX_CH)) + cvi_pwm_update_ch(cvi_pwm[cfg -> pwm_id].reg_base, (cfg->channel & PWM_MAX_CH)); +} + +//启动 PWM 连续输出模式 +void pwm_continuous_start(pwm_configuration_t *cfg) +{ + cvi_pwm_set_pwm_mode_ch(cvi_pwm[cfg -> pwm_id].reg_base, cfg->channel & PWM_MAX_CH, 0); + + cvi_pwm_start_en_ch(cvi_pwm[cfg -> pwm_id].reg_base, cfg->channel & PWM_MAX_CH); +} + +//启动 PWM 固定脉冲个数输出模式 +void pwm_pulse_cnt_start(pwm_configuration_t *cfg, uint32_t cnt) +{ + cvi_pwm_start_dis_ch(cvi_pwm[cfg -> pwm_id].reg_base, cfg->channel & PWM_MAX_CH); + + cvi_pwm_set_pwm_mode_ch(cvi_pwm[cfg -> pwm_id].reg_base, cfg->channel & PWM_MAX_CH, 1); + cvi_pwm_pcount_ch(cvi_pwm[cfg -> pwm_id].reg_base, cfg->channel & PWM_MAX_CH, cnt); + + cvi_pwm_start_en_ch(cvi_pwm[cfg -> pwm_id].reg_base, cfg->channel & PWM_MAX_CH); +} + +//查看固定脉冲个数输出模式下 PWM 是否输出完成 +bool pwm_pulse_cnt_done(pwm_configuration_t *cfg) +{ + return (PWM_PWMDONE(cvi_pwm[cfg -> pwm_id].reg_base) &= CVI_PWM_DONE_CH_EN(cfg->channel & PWM_MAX_CH)) ? true : false; +} + +//停止 PWM 输出 +void pwm_stop(pwm_configuration_t *cfg) +{ + cvi_pwm_start_dis_ch(cvi_pwm[cfg -> pwm_id].reg_base, cfg->channel & PWM_MAX_CH); +}