diff --git a/bsp/tms320f28379d/.cproject b/bsp/tms320f28379d/.cproject index 3646eff869..4dcd4d64f1 100644 --- a/bsp/tms320f28379d/.cproject +++ b/bsp/tms320f28379d/.cproject @@ -15,9 +15,10 @@ - - - + @@ -109,61 +111,66 @@ - - @@ -187,9 +194,10 @@ - - - + @@ -285,31 +294,31 @@ - - diff --git a/bsp/tms320f28379d/.project b/bsp/tms320f28379d/.project index de881dbc77..d8178fe759 100644 --- a/bsp/tms320f28379d/.project +++ b/bsp/tms320f28379d/.project @@ -45,15 +45,20 @@ 2 PARENT-2-PROJECT_LOC/components/finsh - - DeviceDrivers/serial.c - 1 - PARENT-2-PROJECT_LOC/components/drivers/serial/serial.c - DeviceDrivers/ipc 2 PARENT-2-PROJECT_LOC/components/drivers/ipc + + DeviceDrivers/rt_drv_pwm.c + 1 + PARENT-2-PROJECT_LOC/components/drivers/misc/rt_drv_pwm.c + + + DeviceDrivers/serial.c + 1 + PARENT-2-PROJECT_LOC/components/drivers/serial/serial.c + diff --git a/bsp/tms320f28379d/2837x_RAM_lnk_cpu1.cmd b/bsp/tms320f28379d/2837x_RAM_lnk_cpu1.cmd index f84001e83d..5eae476e44 100644 --- a/bsp/tms320f28379d/2837x_RAM_lnk_cpu1.cmd +++ b/bsp/tms320f28379d/2837x_RAM_lnk_cpu1.cmd @@ -37,6 +37,11 @@ SECTIONS .reset : > RESET, PAGE = 0, TYPE = DSECT /* not used, */ .rti_fn.0.end : > RAMM1, PAGE = 1 .rti_fn.0 : > RAMM1, PAGE = 1 + .rti_fn.1 : > RAMM1, PAGE = 1 + .rti_fn.2 : > RAMM1, PAGE = 1 + .rti_fn.3 : > RAMM1, PAGE = 1 + .rti_fn.4 : > RAMM1, PAGE = 1 + .rti_fn.5 : > RAMM1, PAGE = 1 .rti_fn.1.end : > RAMM1, PAGE = 1 .rti_fn.6.end : > RAMM1, PAGE = 1 .rti_fn.6 : > RAMM1, PAGE = 1 diff --git a/bsp/tms320f28379d/drivers/config/pwm_config.h b/bsp/tms320f28379d/drivers/config/pwm_config.h new file mode 100644 index 0000000000..90b0b0bc63 --- /dev/null +++ b/bsp/tms320f28379d/drivers/config/pwm_config.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-09-21 yuqi created + */ + +#ifndef DRIVERS_CONFIG_PWM_CONFIG_H_ +#define DRIVERS_CONFIG_PWM_CONFIG_H_ +#include "F28x_Project.h" // Device Headerfile and Examples Include File +#include "F2837xD_epwm.h" +#include "rtthread.h" +#include "drv_config.h" + +#define BSP_USING_PWM1 +#define BSP_USING_PWM2 +#define BSP_USING_PWM3 +#define BSP_USING_PWM4 +#ifdef __cplusplus +extern "C" { +#endif +#ifdef BSP_USING_PWM1 + #ifndef PWM1_CONFIG + #define PWM1_CONFIG \ + { \ + .name = "pwm1", \ + .pwm_regs = &EPwm1Regs, \ + } + #endif +#endif +#ifdef BSP_USING_PWM2 + #ifndef PWM2_CONFIG + #define PWM2_CONFIG \ + { \ + .name = "pwm2", \ + .pwm_regs = &EPwm2Regs, \ + } + #endif +#endif +#ifdef BSP_USING_PWM3 + #ifndef PWM3_CONFIG + #define PWM3_CONFIG \ + { \ + .name = "pwm3", \ + .pwm_regs = &EPwm3Regs, \ + } + #endif +#endif +#ifdef BSP_USING_PWM4 + #ifndef PWM4_CONFIG + #define PWM4_CONFIG \ + { \ + .name = "pwm4", \ + .pwm_regs = &EPwm4Regs, \ + } + #endif +#endif +#define EPWM1_MAX_DB 0x03FF +#define EPWM2_MAX_DB 0x03FF +#define EPWM3_MAX_DB 0x03FF +#define EPWM1_MIN_DB 0 +#define EPWM2_MIN_DB 0 +#define EPWM3_MIN_DB 0 +#define DB_UP 1 +#define DB_DOWN 0 + +#define RT_HSPCLKDIV TB_DIV4 +#define RT_CLKDIV TB_DIV4 +#define RT_CTRMODE TB_COUNT_UPDOWN + +#define TZ_OFF 2 +#define TZ_ON 1 +#ifdef __cplusplus +} +#endif + + +#define RT_SHADOW_MODE CC_SHADOW +#define RT_LOAD_TIME CC_CTR_ZERO +#define RT_CTRMODE TB_COUNT_UPDOWN +#endif /* DRIVERS_CONFIG_PWM_CONFIG_H_ */ + diff --git a/bsp/tms320f28379d/drivers/drv_config.h b/bsp/tms320f28379d/drivers/drv_config.h new file mode 100644 index 0000000000..926bfc9ad9 --- /dev/null +++ b/bsp/tms320f28379d/drivers/drv_config.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-09-24 qiyu first version + */ + +#ifndef DRIVERS_DRV_CONFIG_H_ +#define DRIVERS_DRV_CONFIG_H_ + +#include "config/pwm_config.h" + +#endif /* DRIVERS_DRV_CONFIG_H_ */ diff --git a/bsp/tms320f28379d/drivers/drv_pwm.c b/bsp/tms320f28379d/drivers/drv_pwm.c new file mode 100644 index 0000000000..4db7f6b079 --- /dev/null +++ b/bsp/tms320f28379d/drivers/drv_pwm.c @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-09-24 qiyu first version + */ + +#include "rtdbg.h" +#include "drv_pwm.h" +#include "F2837xD_device.h" +#include "F28x_Project.h" /* Device Headerfile and Examples Include File */ +#include "drv_config.h" +#include "F2837xD_epwm.h" +/* + * for now, cpu rate is a fixed value, waiting to be modified to an auto-ajustable variable. +*/ + +rt_err_t rt_device_pwm_register(struct rt_device_pwm *device, const char *name, const struct rt_pwm_ops *ops, const void *user_data); + +#define CPU_FREQUENCY 200e6 +/* + * TODO unknown issue, according to the configuration, + * this division should be 2, + * while 2 is inconsistent with the measured result + */ +#define PWM_DIVISION 2 +#define CHANNEL_A 1 +#define CHANNEL_B 2 +#define UPDOWN 1 + +enum +{ +#ifdef BSP_USING_PWM1 + PWM1_INDEX, +#endif +#ifdef BSP_USING_PWM2 + PWM2_INDEX, +#endif +#ifdef BSP_USING_PWM3 + PWM3_INDEX, +#endif +#ifdef BSP_USING_PWM4 + PWM4_INDEX, +#endif +#ifdef BSP_USING_PWM5 + PWM5_INDEX, +#endif +#ifdef BSP_USING_PWM6 + PWM6_INDEX, +#endif +#ifdef BSP_USING_PWM7 + PWM7_INDEX, +#endif +#ifdef BSP_USING_PWM8 + PWM8_INDEX, +#endif +#ifdef BSP_USING_PWM9 + PWM9_INDEX, +#endif +#ifdef BSP_USING_PWM10 + PWM10_INDEX, +#endif +#ifdef BSP_USING_PWM11 + PWM11_INDEX, +#endif +#ifdef BSP_USING_PWM12 + PWM12_INDEX, +#endif +}; + +static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg); + +static struct rt_pwm_ops rt_pwm_ops = +{ + drv_pwm_control +}; + +static struct c28x_pwm c28x_pwm_obj[] = +{ +#ifdef BSP_USING_PWM1 + PWM1_CONFIG, +#endif + +#ifdef BSP_USING_PWM2 + PWM2_CONFIG, +#endif + +#ifdef BSP_USING_PWM3 + PWM3_CONFIG, +#endif + +#ifdef BSP_USING_PWM4 + PWM4_CONFIG, +#endif + +#ifdef BSP_USING_PWM5 + PWM5_CONFIG, +#endif + +#ifdef BSP_USING_PWM6 + PWM6_CONFIG, +#endif + +#ifdef BSP_USING_PWM7 + PWM7_CONFIG, +#endif + +#ifdef BSP_USING_PWM8 + PWM8_CONFIG, +#endif + +}; + +static rt_err_t drv_pwm_set(volatile struct EPWM_REGS *epwm,struct rt_pwm_configuration *configuration) +{ + if(epwm == RT_NULL) + { + return -RT_ERROR; + } + + + /* + * TODO Unknown problem + * the clock division configuration of PWM module is 1 + * however, the experiment result shows the division is 2 + */ + + /* Set the configuration of PWM according to the parameter*/ + rt_uint32_t prd = configuration->period/(1e9/(CPU_FREQUENCY/PWM_DIVISION))/2; + rt_uint32_t comp = prd*configuration->pulse/configuration->period; + rt_uint32_t dead_time = configuration->dead_time/(1e9/(CPU_FREQUENCY/PWM_DIVISION)); + rt_uint32_t phase = configuration->phase; + + epwm->TBPRD = prd; /* Set timer period*/ + epwm->TBCTR = 0x0000; /* Clear counter*/ + epwm->TBCTL.bit.CTRMODE = RT_CTRMODE; /* Count up*/ + epwm->TBCTL.bit.HSPCLKDIV = TB_DIV1; /* Clock ratio to SYSCLKOUT*/ + epwm->TBCTL.bit.CLKDIV = TB_DIV1; + epwm->CMPCTL.bit.SHDWAMODE = RT_SHADOW_MODE; /* Load registers every ZERO*/ + epwm->CMPCTL.bit.SHDWBMODE = RT_SHADOW_MODE; + epwm->CMPCTL.bit.LOADAMODE = RT_LOAD_TIME; + epwm->CMPCTL.bit.LOADBMODE = RT_LOAD_TIME; + /* Setup compare */ + if(configuration->channel == CHANNEL_A) + { + epwm->CMPA.bit.CMPA = comp; + }else + { + epwm->CMPB.bit.CMPB = comp; + } + + /* Set actions */ + epwm->AQCTLA.bit.CAU = AQ_CLEAR; /* Set PWMA on Zero*/ + epwm->AQCTLA.bit.CAD = AQ_SET; + epwm->AQCTLB.bit.CBU = AQ_CLEAR; /* Set PWMB on Zero*/ + epwm->AQCTLB.bit.CBD = AQ_SET; + + /* Active Low PWMs - Setup Deadband */ + /* TODO finish complementary setting */ + epwm->DBCTL.bit.POLSEL = DB_ACTV_HIC; + epwm->DBRED.bit.DBRED = dead_time; + epwm->DBFED.bit.DBFED = dead_time; + epwm->DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; + /* + if(configuration->complementary) + { + } + else + { + epwm->DBRED.bit.DBRED = 0; + epwm->DBFED.bit.DBFED = 0; + epwm->DBCTL.bit.POLSEL = DB_ACTV_HI; + epwm->DBCTL.bit.OUT_MODE = DB_DISABLE; + } + */ + + epwm->DBCTL.bit.IN_MODE = DBA_ALL; + /* if disable dead time, set dead_time to 0 */ + + epwm->ETSEL.bit.INTSEL = ET_CTR_ZERO; /* Select INT on Zero event */ + epwm->ETPS.bit.INTPRD = ET_1ST; /* Generate INT on 1st event */ + + if(phase<180) + { + epwm->TBPHS.bit.TBPHS = prd * phase/180; + epwm->TBCTL.bit.PHSDIR = 0; /* count up */ + }else + { + epwm->TBPHS.bit.TBPHS = prd-prd * (phase-180)/180; + epwm->TBCTL.bit.PHSDIR = 1; /* count up*/ + } + if(epwm == &EPwm1Regs) + { + epwm->TBCTL.bit.PHSEN = TB_DISABLE; /* Disable phase loading */ + epwm->TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; + }else + { + epwm->TBCTL.bit.PHSEN = TB_ENABLE; /* Disable phase loading */ + epwm->TBCTL.bit.SYNCOSEL = TB_SYNC_IN; + } + return RT_EOK; +} + +static rt_err_t drv_pwm_get(struct EPWM_REGS *epwm,struct rt_pwm_configuration *configuration) +{ + /* Retrieve the pwm configuration */ + if(epwm == RT_NULL) + { + return -RT_ERROR; + } + rt_uint32_t prd = epwm->TBPRD; + rt_uint32_t comp = epwm->CMPA.bit.CMPA; + if(UPDOWN) + { + /* if in updown mode, period in configuration has to be doubled */ + configuration->period = prd*(1e9/(CPU_FREQUENCY/PWM_DIVISION))*2; + } + else + { + configuration->period = prd*(1e9/(CPU_FREQUENCY/PWM_DIVISION)); + } + configuration->pulse = comp*configuration->period/prd; + return RT_EOK; +} + +static rt_err_t drv_pwm_set_period(struct EPWM_REGS *epwm, rt_uint32_t period) +{ + if(epwm == RT_NULL) + { + return -RT_ERROR; + } + rt_uint32_t prd = period/(1e9/(CPU_FREQUENCY/PWM_DIVISION))/2; + epwm->TBPRD = prd; /* Set timer period */ + return RT_EOK; +} + +static rt_err_t drv_pwm_set_pulse(struct EPWM_REGS *epwm, int channel, rt_uint32_t pulse) +{ + if(epwm == RT_NULL) + { + return -RT_ERROR; + } + rt_uint32_t comp = pulse/(1e9/(CPU_FREQUENCY/PWM_DIVISION)); + if(channel == CHANNEL_A) + { + epwm->CMPA.bit.CMPA = comp; /* set comparator value */ + }else + { + epwm->CMPB.bit.CMPB = comp; /* set comparator value */ + } + return RT_EOK; +} + +static rt_err_t drv_pwm_set_dead_time(struct EPWM_REGS *epwm, rt_uint32_t dead_time) +{ + if(epwm == RT_NULL) + { + return -RT_ERROR; + } + rt_uint32_t _dead_time = dead_time/(1e9/(CPU_FREQUENCY/PWM_DIVISION)); + epwm->DBRED.bit.DBRED = _dead_time; /* rising dead time */ + epwm->DBFED.bit.DBFED = _dead_time; /* falling dead time */ + return RT_EOK; +} + +static rt_err_t drv_pwm_set_phase(struct EPWM_REGS *epwm, rt_uint32_t phase) +{ + if(epwm == RT_NULL) + { + return -RT_ERROR; + } + if(phase<180) + { + epwm->TBPHS.bit.TBPHS = epwm->TBPRD * phase/180; + epwm->TBCTL.bit.PHSDIR = 0;/* count up */ + }else + { + epwm->TBPHS.bit.TBPHS = epwm->TBPRD-epwm->TBPRD * (phase-180)/180; + epwm->TBCTL.bit.PHSDIR = 1;/* count up */ + } + + return RT_EOK; +} + +static rt_err_t drv_pwm_enable_irq(volatile struct EPWM_REGS *epwm,rt_bool_t enable) +{ + if(epwm == RT_NULL) + { + return -RT_ERROR; + } + if(enable == RT_TRUE) + { + /* Interrupt setting */ + epwm->ETSEL.bit.INTEN = 1; /* Enable INT */ + }else{ + epwm->ETSEL.bit.INTEN = 0; /* Enable INT */ + } + return RT_EOK; +} + +static rt_err_t drv_pwm_enable(volatile struct EPWM_REGS *epwm,rt_bool_t enable) +{ + /* + * TODO + * Still not sure about how to stop PWM in C2000 + */ + if(epwm == RT_NULL) + { + return -RT_ERROR; + } + if(enable == RT_TRUE) + { + /* clear trip zone flag */ + EALLOW; + epwm->TZCLR.bit.OST = 1; + EDIS; + } + else + { + /* set trip zone flag */ + EALLOW; + epwm->TZFRC.bit.OST = 1; + EDIS; + } + return RT_EOK; +} + +static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg) +{ + struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg; + struct c28x_pwm *pwm = (struct c28x_pwm *)device->parent.user_data; + + switch (cmd) + { + case PWM_CMD_ENABLE: + return drv_pwm_enable((struct EPWM_REGS *)(pwm->pwm_regs), RT_TRUE); + case PWM_CMD_DISABLE: + return drv_pwm_enable((struct EPWM_REGS *)(pwm->pwm_regs), RT_FALSE); + case PWM_CMD_SET: + return drv_pwm_set((struct EPWM_REGS *)(pwm->pwm_regs), configuration); + case PWM_CMD_GET: + return drv_pwm_get((struct EPWM_REGS *)(pwm->pwm_regs), configuration); + case PWM_CMD_SET_PERIOD: + return drv_pwm_set_period((struct EPWM_REGS *)(pwm->pwm_regs), configuration->period); + case PWM_CMD_SET_PULSE: + return drv_pwm_set_pulse((struct EPWM_REGS *)(pwm->pwm_regs), configuration->channel,configuration->pulse); + case PWM_CMD_SET_DEAD_TIME: + return drv_pwm_set_dead_time((struct EPWM_REGS *)(pwm->pwm_regs), configuration->dead_time); + case PWM_CMD_SET_PHASE: + return drv_pwm_set_phase((struct EPWM_REGS *)(pwm->pwm_regs), configuration->phase); + case PWM_CMD_ENABLE_IRQ: + return drv_pwm_enable_irq((struct EPWM_REGS *)(pwm->pwm_regs), RT_TRUE); + case PWM_CMD_DISABLE_IRQ: + return drv_pwm_enable_irq((struct EPWM_REGS *)(pwm->pwm_regs), RT_FALSE); + default: + return RT_EINVAL; + } +} + +static void pwm_isr(struct rt_device_pwm *rt_pwm) +{ + struct c28x_pwm *pwm; + pwm = (struct c28x_pwm *)rt_pwm->parent.user_data; + PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; + pwm->pwm_regs->ETCLR.bit.INT = 1; +} + +#define EPWM_ISR_DEFINE(i) void EPWM##i##_Isr(){\ + rt_interrupt_enter(); \ + pwm_isr(&(c28x_pwm_obj[PWM##i##_INDEX].pwm_device)); \ + rt_interrupt_leave(); \ +} + +#ifdef BSP_USING_PWM1 +EPWM_ISR_DEFINE(1) +#endif + +void EPWM1_Isr(); + +static int c28x_hw_pwm_init(struct c28x_pwm *device) +{ + EALLOW; + /* Assigning ISR to PIE */ + PieVectTable.EPWM1_INT = &EPWM1_Isr; + /* ENABLE Interrupt */ + EDIS; + IER |= M_INT3; + rt_err_t result = 0; + + EALLOW; +#ifdef BSP_USING_PWM1 + GpioCtrlRegs.GPAPUD.all |= 5<<(1-1)*4; /* Disable pull-up on GPIO0 (EPWM1A) */ + GpioCtrlRegs.GPAMUX1.all|= 5<<(1-1)*4; /* Configure GPIO0 as EPWM1A */ + EPwm1Regs.TZCTL.bit.TZA = TZ_OFF; /* diable A when trip zone */ + EPwm1Regs.TZCTL.bit.TZB = TZ_OFF; /* diable B when trip zone */ +#endif +#ifdef BSP_USING_PWM2 + GpioCtrlRegs.GPAPUD.all |= 5<<(2-1)*4; /* Disable pull-up on GPIO0 (EPWM1A) */ + GpioCtrlRegs.GPAMUX1.all|= 5<<(2-1)*4; /* Configure GPIO0 as EPWM1A */ + EPwm2Regs.TZCTL.bit.TZA = TZ_OFF; /* diable A when trip zone */ + EPwm2Regs.TZCTL.bit.TZB = TZ_OFF; /* diable B when trip zone */ +#endif +#ifdef BSP_USING_PWM3 + GpioCtrlRegs.GPAPUD.all |= 5<<(3-1)*4; /* Disable pull-up on GPIO0 (EPWM1A) */ + GpioCtrlRegs.GPAMUX1.all|= 5<<(3-1)*4; /* Configure GPIO0 as EPWM1A */ + EPwm3Regs.TZCTL.bit.TZA = TZ_OFF; /* diable A when trip zone */ + EPwm3Regs.TZCTL.bit.TZB = TZ_OFF; /* diable B when trip zone */ +#endif +#ifdef BSP_USING_PWM4 + GpioCtrlRegs.GPAPUD.all |= 5<<(4-1)*4; /* Disable pull-up on GPIO0 (EPWM1A) */ + GpioCtrlRegs.GPAMUX1.all|= 5<<(4-1)*4; /* Configure GPIO0 as EPWM1A */ + EPwm4Regs.TZCTL.bit.TZA = TZ_OFF; /* diable A when trip zone */ + EPwm4Regs.TZCTL.bit.TZB = TZ_OFF; /* diable B when trip zone */ +#endif +#ifdef BSP_USING_PWM5 + GpioCtrlRegs.GPAPUD.all |= 5<<(5-1)*4; /* Disable pull-up on GPIO0 (EPWM1A) */ + GpioCtrlRegs.GPAMUX1.all|= 5<<(5-1)*4; /* Configure GPIO0 as EPWM1A */ + EPwm5Regs.TZCTL.bit.TZA = TZ_OFF; /* diable A when trip zone */ + EPwm5Regs.TZCTL.bit.TZB = TZ_OFF; /* diable B when trip zone */ +#endif + EDIS; + + return result; +} + +int c28x_pwm_init(void) +{ + int i = 0; + int result = RT_EOK; + + for (i = 0; i < sizeof(c28x_pwm_obj) / sizeof(c28x_pwm_obj[0]); i++) + { + /* pwm init */ + if (c28x_hw_pwm_init(&c28x_pwm_obj[i]) != RT_EOK) + { + LOG_E("%s init failed", c28x_pwm_obj[i].name); + result = -RT_ERROR; + return result; + } + else + { + LOG_D("%s init success", c28x_pwm_obj[i].name); + + /* register pwm device */ + if (rt_device_pwm_register(&c28x_pwm_obj[i].pwm_device, c28x_pwm_obj[i].name, &rt_pwm_ops, &c28x_pwm_obj[i]) == RT_EOK) + { + LOG_D("%s register success", c28x_pwm_obj[i].name); + } + else + { + LOG_E("%s register failed", c28x_pwm_obj[i].name); + result = -RT_ERROR; + } + } + } + struct rt_pwm_configuration config_tmp1 = + { + .channel = CHANNEL_A, + .period = 10000, + .pulse = 5000, + .dead_time = 100, + .phase = 0, + .complementary = RT_TRUE + }; + drv_pwm_set(c28x_pwm_obj[0].pwm_regs,&config_tmp1); + config_tmp1.phase = 180; + drv_pwm_set(c28x_pwm_obj[1].pwm_regs,&config_tmp1); + config_tmp1.phase = 90; + drv_pwm_set(c28x_pwm_obj[2].pwm_regs,&config_tmp1); + config_tmp1.phase = 270; + drv_pwm_set(c28x_pwm_obj[3].pwm_regs,&config_tmp1); + return result; + +} +INIT_DEVICE_EXPORT(c28x_pwm_init); diff --git a/bsp/tms320f28379d/drivers/drv_pwm.h b/bsp/tms320f28379d/drivers/drv_pwm.h new file mode 100644 index 0000000000..a91ee7a7d9 --- /dev/null +++ b/bsp/tms320f28379d/drivers/drv_pwm.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-09-24 qiyu first version + */ + +#ifndef DRIVERS_DRV_PWM_H_ +#define DRIVERS_DRV_PWM_H_ +#include +#include "rtdevice.h" + +struct c28x_pwm +{ + struct rt_device_pwm pwm_device; + volatile struct EPWM_REGS *pwm_regs; + const char *name; +}; + +int c28x_pwm_init(void); + +#endif /* DRIVERS_DRV_PWM_H_ */ diff --git a/bsp/tms320f28379d/rtconfig.h b/bsp/tms320f28379d/rtconfig.h index ce045ed9ce..5c94c07763 100644 --- a/bsp/tms320f28379d/rtconfig.h +++ b/bsp/tms320f28379d/rtconfig.h @@ -77,6 +77,7 @@ #define RT_USING_SERIAL_V1 #define RT_SERIAL_RB_BUFSZ 64 #define RT_USING_PIN +#define RT_USING_PWM /* Using USB */ diff --git a/components/drivers/include/drivers/rt_drv_pwm.h b/components/drivers/include/drivers/rt_drv_pwm.h index 1338d43ee8..fa7de61b29 100644 --- a/components/drivers/include/drivers/rt_drv_pwm.h +++ b/components/drivers/include/drivers/rt_drv_pwm.h @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2018-05-07 aozima the first version + * 2022-09-24 yuqi add phase and dead time configuration */ #ifndef __DRV_PWM_H_INCLUDE__ @@ -21,13 +22,18 @@ #define PWMN_CMD_DISABLE (RT_DEVICE_CTRL_BASE(PWM) + 5) #define PWM_CMD_SET_PERIOD (RT_DEVICE_CTRL_BASE(PWM) + 6) #define PWM_CMD_SET_PULSE (RT_DEVICE_CTRL_BASE(PWM) + 7) +#define PWM_CMD_SET_DEAD_TIME (RT_DEVICE_CTRL_BASE(PWM) + 8) +#define PWM_CMD_SET_PHASE (RT_DEVICE_CTRL_BASE(PWM) + 9) +#define PWM_CMD_ENABLE_IRQ (RT_DEVICE_CTRL_BASE(PWM) + 10) +#define PWM_CMD_DISABLE_IRQ (RT_DEVICE_CTRL_BASE(PWM) + 11) struct rt_pwm_configuration { rt_uint32_t channel; /* 0 ~ n or 0 ~ -n, which depends on specific MCU requirements */ rt_uint32_t period; /* unit:ns 1ns~4.29s:1Ghz~0.23hz */ rt_uint32_t pulse; /* unit:ns (pulse<=period) */ - + rt_uint32_t dead_time; /* unit:ns */ + rt_uint32_t phase; /*unit: degree, 0~360, which is the phase of pwm output, */ /* * RT_TRUE : The channel of pwm is complememtary. * RT_FALSE : The channel of pwm is nomal. @@ -54,5 +60,7 @@ rt_err_t rt_pwm_disable(struct rt_device_pwm *device, int channel); rt_err_t rt_pwm_set(struct rt_device_pwm *device, int channel, rt_uint32_t period, rt_uint32_t pulse); rt_err_t rt_pwm_set_period(struct rt_device_pwm *device, int channel, rt_uint32_t period); rt_err_t rt_pwm_set_pulse(struct rt_device_pwm *device, int channel, rt_uint32_t pulse); +rt_err_t rt_pwm_set_dead_time(struct rt_device_pwm *device, int channel, rt_uint32_t dead_time); +rt_err_t rt_pwm_set_phase(struct rt_device_pwm *device, int channel, rt_uint32_t phase); #endif /* __DRV_PWM_H_INCLUDE__ */ diff --git a/components/drivers/misc/rt_drv_pwm.c b/components/drivers/misc/rt_drv_pwm.c index 23a3283de4..7cc01e4e1a 100644 --- a/components/drivers/misc/rt_drv_pwm.c +++ b/components/drivers/misc/rt_drv_pwm.c @@ -9,6 +9,7 @@ * 2022-05-14 Stanley Lwin add pwm function * 2022-07-25 liYony fix complementary outputs and add usage information in finsh * 2022-08-31 liYony Add complementary output section to framework for management + * 2022-09-24 qiyu Add dead-time and phase configuration */ #include @@ -247,6 +248,40 @@ rt_err_t rt_pwm_set_pulse(struct rt_device_pwm *device, int channel, rt_uint32_t return result; } +rt_err_t rt_pwm_set_dead_time(struct rt_device_pwm *device, int channel, rt_uint32_t dead_time) +{ + rt_err_t result = RT_EOK; + struct rt_pwm_configuration configuration = {0}; + + if (!device) + { + return -RT_EIO; + } + + configuration.channel = (channel > 0) ? (channel) : (-channel); + configuration.dead_time = dead_time; + result = rt_device_control(&device->parent, PWM_CMD_SET_DEAD_TIME, &configuration); + + return result; +} + + +rt_err_t rt_pwm_set_phase(struct rt_device_pwm *device, int channel, rt_uint32_t phase) +{ + rt_err_t result = RT_EOK; + struct rt_pwm_configuration configuration = {0}; + + if (!device) + { + return -RT_EIO; + } + + configuration.channel = (channel > 0) ? (channel) : (-channel); + configuration.phase = phase; + result = rt_device_control(&device->parent, PWM_CMD_SET_PHASE, &configuration); + + return result; +} rt_err_t rt_pwm_get(struct rt_device_pwm *device, struct rt_pwm_configuration *cfg) { rt_err_t result = RT_EOK; @@ -342,7 +377,7 @@ static int pwm(int argc, char **argv) if(argc == 5) { result = rt_pwm_set(pwm_device, atoi(argv[2]), atoi(argv[3]), atoi(argv[4])); - rt_kprintf("pwm info set on %s at channel %d\n",pwm_device,atoi(argv[2])); + rt_kprintf("pwm info set on %s at channel %d\n",pwm_device,(rt_base_t)atoi(argv[2])); } else { @@ -350,22 +385,48 @@ static int pwm(int argc, char **argv) rt_kprintf("Usage: pwm set \n"); } } - + else if(!strcmp(argv[1], "phase")) + { + if(argc == 4) + { + result = rt_pwm_set_phase(pwm_device, atoi(argv[2]),atoi(argv[3])); + result_str = (result == RT_EOK) ? "success" : "failure"; + rt_kprintf("%s phase is set %d \n", pwm_device->parent.parent.name, (rt_base_t)atoi(argv[3])); + } + } + else if(!strcmp(argv[1], "dead_time")) + { + if(argc == 4) + { + result = rt_pwm_set_dead_time(pwm_device, atoi(argv[2]),atoi(argv[3])); + result_str = (result == RT_EOK) ? "success" : "failure"; + rt_kprintf("%s dead_time is set %d \n", pwm_device->parent.parent.name, (rt_base_t)atoi(argv[3])); + } + } else { - rt_kprintf("pwm get - get pwm channel info\n"); + rt_kprintf("Usage: \n"); + rt_kprintf("pwm probe - probe pwm by name\n"); + rt_kprintf("pwm enable - enable pwm channel\n"); + rt_kprintf("pwm disable - disable pwm channel\n"); + rt_kprintf("pwm get - get pwm channel info\n"); + rt_kprintf("pwm set - set pwm channel info\n"); + rt_kprintf("pwm phase - set pwm phase\n"); + rt_kprintf("pwm dead_time - set pwm dead time\n"); + result = - RT_ERROR; } } } else { rt_kprintf("Usage: \n"); - rt_kprintf("pwm probe - probe pwm by name\n"); - rt_kprintf("pwm enable - enable pwm channel\n"); - rt_kprintf("pwm disable - disable pwm channel\n"); - rt_kprintf("pwm get - get pwm channel info\n"); - rt_kprintf("pwm set - set pwm channel info\n"); - + rt_kprintf("pwm probe - probe pwm by name\n"); + rt_kprintf("pwm enable - enable pwm channel\n"); + rt_kprintf("pwm disable - disable pwm channel\n"); + rt_kprintf("pwm get - get pwm channel info\n"); + rt_kprintf("pwm set - set pwm channel info\n"); + rt_kprintf("pwm phase - set pwm phase\n"); + rt_kprintf("pwm dead_time - set pwm dead time\n"); result = - RT_ERROR; }