1 /* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2018-05-07 aozima the first version 9 */ 10 11 #include <string.h> 12 13 #include <drivers/rt_drv_pwm.h> 14 15 static rt_err_t _pwm_control(rt_device_t dev, int cmd, void *args) 16 { 17 rt_err_t result = RT_EOK; 18 struct rt_device_pwm *pwm = (struct rt_device_pwm *)dev; 19 20 if (pwm->ops->control) 21 { 22 result = pwm->ops->control(pwm, cmd, args); 23 } 24 25 return result; 26 } 27 28 29 /* 30 pos: channel 31 void *buffer: rt_uint32_t pulse[size] 32 size : number of pulse, only set to sizeof(rt_uint32_t). 33 */ 34 static rt_size_t _pwm_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) 35 { 36 rt_err_t result = RT_EOK; 37 struct rt_device_pwm *pwm = (struct rt_device_pwm *)dev; 38 rt_uint32_t *pulse = (rt_uint32_t *)buffer; 39 struct rt_pwm_configuration configuration = {0}; 40 41 configuration.channel = pos; 42 43 if (pwm->ops->control) 44 { 45 result = pwm->ops->control(pwm, PWM_CMD_GET, &configuration); 46 if (result != RT_EOK) 47 { 48 return 0; 49 } 50 51 *pulse = configuration.pulse; 52 } 53 54 return size; 55 } 56 57 /* 58 pos: channel 59 void *buffer: rt_uint32_t pulse[size] 60 size : number of pulse, only set to sizeof(rt_uint32_t). 61 */ 62 static rt_size_t _pwm_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) 63 { 64 rt_err_t result = RT_EOK; 65 struct rt_device_pwm *pwm = (struct rt_device_pwm *)dev; 66 rt_uint32_t *pulse = (rt_uint32_t *)buffer; 67 struct rt_pwm_configuration configuration = {0}; 68 69 configuration.channel = pos; 70 71 if (pwm->ops->control) 72 { 73 result = pwm->ops->control(pwm, PWM_CMD_GET, &configuration); 74 if (result != RT_EOK) 75 { 76 return 0; 77 } 78 79 configuration.pulse = *pulse; 80 81 result = pwm->ops->control(pwm, PWM_CMD_SET, &configuration); 82 if (result != RT_EOK) 83 { 84 return 0; 85 } 86 } 87 88 return size; 89 } 90 91 #ifdef RT_USING_DEVICE_OPS 92 static const struct rt_device_ops pwm_device_ops = 93 { 94 RT_NULL, 95 RT_NULL, 96 RT_NULL, 97 _pwm_read, 98 _pwm_write, 99 _pwm_control 100 }; 101 #endif /* RT_USING_DEVICE_OPS */ 102 103 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) 104 { 105 rt_err_t result = RT_EOK; 106 107 memset(device, 0, sizeof(struct rt_device_pwm)); 108 109 #ifdef RT_USING_DEVICE_OPS 110 device->parent.ops = &pwm_device_ops; 111 #else 112 device->parent.init = RT_NULL; 113 device->parent.open = RT_NULL; 114 device->parent.close = RT_NULL; 115 device->parent.read = _pwm_read; 116 device->parent.write = _pwm_write; 117 device->parent.control = _pwm_control; 118 #endif /* RT_USING_DEVICE_OPS */ 119 120 device->parent.type = RT_Device_Class_Miscellaneous; 121 device->ops = ops; 122 device->parent.user_data = (void *)user_data; 123 124 result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR); 125 126 return result; 127 } 128 129 rt_err_t rt_pwm_enable(struct rt_device_pwm *device, int channel) 130 { 131 rt_err_t result = RT_EOK; 132 struct rt_pwm_configuration configuration = {0}; 133 134 if (!device) 135 { 136 return -RT_EIO; 137 } 138 139 configuration.channel = channel; 140 result = rt_device_control(&device->parent, PWM_CMD_ENABLE, &configuration); 141 142 return result; 143 } 144 145 rt_err_t rt_pwm_disable(struct rt_device_pwm *device, int channel) 146 { 147 rt_err_t result = RT_EOK; 148 struct rt_pwm_configuration configuration = {0}; 149 150 if (!device) 151 { 152 return -RT_EIO; 153 } 154 155 configuration.channel = channel; 156 result = rt_device_control(&device->parent, PWM_CMD_DISABLE, &configuration); 157 158 return result; 159 } 160 161 rt_err_t rt_pwm_set(struct rt_device_pwm *device, int channel, rt_uint32_t period, rt_uint32_t pulse) 162 { 163 rt_err_t result = RT_EOK; 164 struct rt_pwm_configuration configuration = {0}; 165 166 if (!device) 167 { 168 return -RT_EIO; 169 } 170 171 configuration.channel = channel; 172 configuration.period = period; 173 configuration.pulse = pulse; 174 result = rt_device_control(&device->parent, PWM_CMD_SET, &configuration); 175 176 return result; 177 } 178 179 #ifdef RT_USING_FINSH 180 #include <finsh.h> 181 182 FINSH_FUNCTION_EXPORT_ALIAS(rt_pwm_enable, pwm_enable, enable pwm by channel.); 183 FINSH_FUNCTION_EXPORT_ALIAS(rt_pwm_set, pwm_set, set pwm.); 184 185 #ifdef FINSH_USING_MSH 186 static int pwm_enable(int argc, char **argv) 187 { 188 int result = 0; 189 struct rt_device_pwm *device = RT_NULL; 190 191 if (argc != 3) 192 { 193 rt_kprintf("Usage: pwm_enable pwm1 1\n"); 194 result = -RT_ERROR; 195 goto _exit; 196 } 197 198 device = (struct rt_device_pwm *)rt_device_find(argv[1]); 199 if (!device) 200 { 201 result = -RT_EIO; 202 goto _exit; 203 } 204 205 result = rt_pwm_enable(device, atoi(argv[2])); 206 207 _exit: 208 return result; 209 } 210 MSH_CMD_EXPORT(pwm_enable, pwm_enable pwm1 1); 211 212 static int pwm_disable(int argc, char **argv) 213 { 214 int result = 0; 215 struct rt_device_pwm *device = RT_NULL; 216 217 if (argc != 3) 218 { 219 rt_kprintf("Usage: pwm_enable pwm1 1\n"); 220 result = -RT_ERROR; 221 goto _exit; 222 } 223 224 device = (struct rt_device_pwm *)rt_device_find(argv[1]); 225 if (!device) 226 { 227 result = -RT_EIO; 228 goto _exit; 229 } 230 231 result = rt_pwm_disable(device, atoi(argv[2])); 232 233 _exit: 234 return result; 235 } 236 MSH_CMD_EXPORT(pwm_disable, pwm_disable pwm1 1); 237 238 static int pwm_set(int argc, char **argv) 239 { 240 int result = 0; 241 struct rt_device_pwm *device = RT_NULL; 242 243 if (argc != 5) 244 { 245 rt_kprintf("Usage: pwm_set pwm1 1 100 50\n"); 246 result = -RT_ERROR; 247 goto _exit; 248 } 249 250 device = (struct rt_device_pwm *)rt_device_find(argv[1]); 251 if (!device) 252 { 253 result = -RT_EIO; 254 goto _exit; 255 } 256 257 result = rt_pwm_set(device, atoi(argv[2]), atoi(argv[3]), atoi(argv[4])); 258 259 _exit: 260 return result; 261 } 262 MSH_CMD_EXPORT(pwm_set, pwm_set 1 100 50); 263 264 #endif /* FINSH_USING_MSH */ 265 #endif /* RT_USING_FINSH */ 266