#include "drv_pwm.h" #include #include #include #include "hw_memmap.h" #include "pwm.h" #include "sysctl.h" #ifdef RT_USING_PWM #include "pwm_config.h" #include "tm4c123_config.h" #define LOG_TAG "drv.pwm" #include enum { #ifdef BSP_USING_PWM0 PWM0_INDEX, #endif #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 }; static struct tm4c123_pwm_config pwm_config[] = { #ifdef BSP_USING_PWM0 PWM0_CONFIG, #endif #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 }; static struct tm4c123_pwm pwm_obj[sizeof(pwm_config) / sizeof(pwm_config[0])] = {0}; static rt_err_t tm4c123_pwm_control(struct rt_device_pwm *device, int cmd, void *arg); static struct rt_pwm_ops drv_ops = { tm4c123_pwm_control }; static rt_err_t drv_pwm_enable(char* name, struct rt_pwm_configuration *configuration, rt_bool_t enable) { /* Converts the channel number to the channel number of Hal library */ int num = name[3]-0x30; if (!enable) { if( num<=3 ) { PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT<<(num*2+(configuration->channel-1)), false); } else { PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT<<((num%4)*2+(configuration->channel-1)), false); } } else { if( num<=3 ) { PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT<<(num*2+(configuration->channel-1)), true); } else { PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT<<((num%4)*2+(configuration->channel-1)), true); } } return RT_EOK; } static rt_err_t drv_pwm_get(char* name, struct rt_pwm_configuration *configuration) { switch(name[3]) { case '0': configuration->period = PWMGenPeriodGet(PWM0_BASE, PWM_GEN_0); configuration->pulse= PWMPulseWidthGet(PWM0_BASE, PWM_OUT_0+(uint32_t)(configuration->channel-1)); break; case '1': configuration->period = PWMGenPeriodGet(PWM0_BASE, PWM_GEN_1); configuration->pulse= PWMPulseWidthGet(PWM0_BASE, PWM_OUT_2+(uint32_t)(configuration->channel-1)); break; case '2': configuration->period = PWMGenPeriodGet(PWM0_BASE, PWM_GEN_2); configuration->pulse= PWMPulseWidthGet(PWM0_BASE, PWM_OUT_4+(uint32_t)(configuration->channel-1)); break; case '3': configuration->period = PWMGenPeriodGet(PWM0_BASE, PWM_GEN_3); configuration->pulse= PWMPulseWidthGet(PWM0_BASE, PWM_OUT_6+(uint32_t)(configuration->channel-1)); break; case '4': configuration->period = PWMGenPeriodGet(PWM1_BASE, PWM_GEN_0); configuration->pulse= PWMPulseWidthGet(PWM1_BASE, PWM_OUT_0+(uint32_t)(configuration->channel-1)); break; case '5': configuration->period = PWMGenPeriodGet(PWM1_BASE, PWM_GEN_1); configuration->pulse= PWMPulseWidthGet(PWM1_BASE, PWM_OUT_2+(uint32_t)(configuration->channel-1)); break; case '6': configuration->period = PWMGenPeriodGet(PWM1_BASE, PWM_GEN_2); configuration->pulse= PWMPulseWidthGet(PWM1_BASE, PWM_OUT_4+(uint32_t)(configuration->channel-1)); break; case '7': configuration->period = PWMGenPeriodGet(PWM1_BASE, PWM_GEN_3); configuration->pulse= PWMPulseWidthGet(PWM1_BASE, PWM_OUT_6+(uint32_t)(configuration->channel-1)); break; default: break; } return RT_EOK; } static rt_err_t drv_pwm_set(char *name, struct rt_pwm_configuration *configuration) { uint32_t sysPwmClock = SysCtlPWMClockGet(); switch(name[3]) { case '0': PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, configuration->period/1000*(sysPwmClock/1000000)); // t(s)/(1/f) = ticks ns/1000/1000000 PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0+(uint32_t)(configuration->channel-1),configuration->pulse/1000*(sysPwmClock/1000000)); PWMGenEnable(PWM0_BASE, PWM_GEN_0); break; case '1': PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, configuration->period/1000*(sysPwmClock/1000000)); PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0+(uint32_t)(configuration->channel-1),configuration->pulse/1000*(sysPwmClock/1000000)); PWMGenEnable(PWM0_BASE, PWM_GEN_1); break; case '2': PWMGenPeriodSet(PWM0_BASE, PWM_GEN_2, configuration->period/1000*(sysPwmClock/1000000)); PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0+(uint32_t)(configuration->channel-1),configuration->pulse/1000*(sysPwmClock/1000000)); PWMGenEnable(PWM0_BASE, PWM_GEN_2); break; case '3': PWMGenPeriodSet(PWM0_BASE, PWM_GEN_3, configuration->period/1000*(sysPwmClock/1000000)); PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0+(uint32_t)(configuration->channel-1),configuration->pulse/1000*(sysPwmClock/1000000)); PWMGenEnable(PWM0_BASE, PWM_GEN_3); break; case '4': PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, configuration->period/1000*(sysPwmClock/1000000)); PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0+(uint32_t)(configuration->channel-1),configuration->pulse/1000*(sysPwmClock/1000000)); PWMGenEnable(PWM1_BASE, PWM_GEN_0); break; case '5': PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, configuration->period/1000*(sysPwmClock/1000000)); PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2+(uint32_t)(configuration->channel-1),configuration->pulse/1000*(sysPwmClock/1000000)); PWMGenEnable(PWM1_BASE, PWM_GEN_1); break; case '6': PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, configuration->period/1000*(sysPwmClock/1000000)); PWMPulseWidthSet(PWM1_BASE, PWM_OUT_4+(uint32_t)(configuration->channel-1),configuration->pulse/1000*(sysPwmClock/1000000)); PWMGenEnable(PWM1_BASE, PWM_GEN_2); break; case '7': PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, configuration->period/1000*(sysPwmClock/1000000)); PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6+(uint32_t)(configuration->channel-1),configuration->pulse/1000*(sysPwmClock/1000000)); PWMGenEnable(PWM1_BASE, PWM_GEN_3); break; default: break; } return RT_EOK; } static rt_err_t tm4c123_pwm_control(struct rt_device_pwm *device, int cmd, void *arg) { struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg; switch (cmd) { case PWM_CMD_ENABLE: return drv_pwm_enable(device->parent.parent.name, configuration, RT_TRUE); case PWM_CMD_DISABLE: return drv_pwm_enable(device->parent.parent.name, configuration, RT_FALSE); case PWM_CMD_SET: return drv_pwm_set(device->parent.parent.name, configuration); case PWM_CMD_GET: return drv_pwm_get(device->parent.parent.name, configuration); default: return RT_EINVAL; } } static rt_err_t tm4c123_hw_pwm_init(struct tm4c123_pwm *device) { rt_err_t result = RT_EOK; RT_ASSERT(device != RT_NULL); pwm_hw_config(); switch( device->config->name[3]) { case '0': PWMGenConfigure(PWM0_BASE, PWM_GEN_0, device->config->counterMode | device->config->syncMode); break; case '1': PWMGenConfigure(PWM0_BASE, PWM_GEN_1, device->config->counterMode | device->config->syncMode); break; case '2': PWMGenConfigure(PWM0_BASE, PWM_GEN_2, device->config->counterMode | device->config->syncMode); break; case '3': PWMGenConfigure(PWM0_BASE, PWM_GEN_3, device->config->counterMode | device->config->syncMode); break; case '4': PWMGenConfigure(PWM1_BASE, PWM_GEN_0, device->config->counterMode | device->config->syncMode); break; case '5': PWMGenConfigure(PWM1_BASE, PWM_GEN_1, device->config->counterMode | device->config->syncMode); break; case '6': PWMGenConfigure(PWM1_BASE, PWM_GEN_2, device->config->counterMode | device->config->syncMode); break; case '7': PWMGenConfigure(PWM1_BASE, PWM_GEN_3, device->config->counterMode | device->config->syncMode); break; default: LOG_E("%s PWMGenConfigure failed", device->config->name); result = -RT_ERROR; return result; } return result; } int rt_hw_pwm_init(void) { int i = 0; rt_size_t obj_num = sizeof(pwm_obj) / sizeof(struct tm4c123_pwm); rt_err_t result = RT_EOK; for(i=0 ; i< obj_num;i++) { pwm_obj[i].config = &pwm_config[i]; pwm_obj[i].pwm_device.ops = &drv_ops; /*pwm_init*/ if(tm4c123_hw_pwm_init(&pwm_obj[i])!= RT_EOK) { LOG_E("%s init failed", pwm_obj[i].config->name); result = -RT_ERROR; return result; } else { LOG_D("%s init success", pwm_obj[i].config->name); /* register pwm device */ if (rt_device_pwm_register(&pwm_obj[i].pwm_device, pwm_obj[i].config->name, &drv_ops,RT_NULL) == RT_EOK) { LOG_D("%s register success", pwm_obj[i].config->name); } else { LOG_E("%s register failed", pwm_obj[i].config->name); result = -RT_ERROR; } } } return result; } #endif