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 * 2015-08-31 heyuanjie87 first version 9 */ 10 11 #include <rtthread.h> 12 #include <rtdevice.h> 13 14 rt_inline rt_uint32_t timeout_calc(rt_hwtimer_t *timer, rt_hwtimerval_t *tv) 15 { 16 float overflow; 17 float timeout; 18 rt_uint32_t counter; 19 int i, index = 0; 20 float tv_sec; 21 float devi_min = 1; 22 float devi; 23 24 /* changed to second */ 25 overflow = timer->info->maxcnt/(float)timer->freq; 26 tv_sec = tv->sec + tv->usec/(float)1000000; 27 28 if (tv_sec < (1/(float)timer->freq)) 29 { 30 /* little timeout */ 31 i = 0; 32 timeout = 1/(float)timer->freq; 33 } 34 else 35 { 36 for (i = 1; i > 0; i ++) 37 { 38 timeout = tv_sec/i; 39 40 if (timeout <= overflow) 41 { 42 counter = timeout*timer->freq; 43 devi = tv_sec - (counter/(float)timer->freq)*i; 44 /* Minimum calculation error */ 45 if (devi > devi_min) 46 { 47 i = index; 48 timeout = tv_sec/i; 49 break; 50 } 51 else if (devi == 0) 52 { 53 break; 54 } 55 else if (devi < devi_min) 56 { 57 devi_min = devi; 58 index = i; 59 } 60 } 61 } 62 } 63 64 timer->cycles = i; 65 timer->reload = i; 66 timer->period_sec = timeout; 67 counter = timeout*timer->freq; 68 69 return counter; 70 } 71 72 static rt_err_t rt_hwtimer_init(struct rt_device *dev) 73 { 74 rt_err_t result = RT_EOK; 75 rt_hwtimer_t *timer; 76 77 timer = (rt_hwtimer_t *)dev; 78 /* try to change to 1MHz */ 79 if ((1000000 <= timer->info->maxfreq) && (1000000 >= timer->info->minfreq)) 80 { 81 timer->freq = 1000000; 82 } 83 else 84 { 85 timer->freq = timer->info->minfreq; 86 } 87 timer->mode = HWTIMER_MODE_ONESHOT; 88 timer->cycles = 0; 89 timer->overflow = 0; 90 91 if (timer->ops->init) 92 { 93 timer->ops->init(timer, 1); 94 } 95 else 96 { 97 result = -RT_ENOSYS; 98 } 99 100 return result; 101 } 102 103 static rt_err_t rt_hwtimer_open(struct rt_device *dev, rt_uint16_t oflag) 104 { 105 rt_err_t result = RT_EOK; 106 rt_hwtimer_t *timer; 107 108 timer = (rt_hwtimer_t *)dev; 109 if (timer->ops->control != RT_NULL) 110 { 111 timer->ops->control(timer, HWTIMER_CTRL_FREQ_SET, &timer->freq); 112 } 113 else 114 { 115 result = -RT_ENOSYS; 116 } 117 118 return result; 119 } 120 121 static rt_err_t rt_hwtimer_close(struct rt_device *dev) 122 { 123 rt_err_t result = RT_EOK; 124 rt_hwtimer_t *timer; 125 126 timer = (rt_hwtimer_t*)dev; 127 if (timer->ops->init != RT_NULL) 128 { 129 timer->ops->init(timer, 0); 130 } 131 else 132 { 133 result = -RT_ENOSYS; 134 } 135 136 dev->flag &= ~RT_DEVICE_FLAG_ACTIVATED; 137 dev->rx_indicate = RT_NULL; 138 139 return result; 140 } 141 142 static rt_size_t rt_hwtimer_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size) 143 { 144 rt_hwtimer_t *timer; 145 rt_hwtimerval_t tv; 146 rt_uint32_t cnt; 147 float t; 148 149 timer = (rt_hwtimer_t *)dev; 150 if (timer->ops->count_get == RT_NULL) 151 return 0; 152 153 cnt = timer->ops->count_get(timer); 154 if (timer->info->cntmode == HWTIMER_CNTMODE_DW) 155 { 156 cnt = (timer->freq * timer->period_sec) - cnt; 157 } 158 159 t = timer->overflow * timer->period_sec + cnt/(float)timer->freq; 160 tv.sec = t; 161 tv.usec = (t - tv.sec) * 1000000; 162 size = size > sizeof(tv)? sizeof(tv) : size; 163 rt_memcpy(buffer, &tv, size); 164 165 return size; 166 } 167 168 static rt_size_t rt_hwtimer_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size) 169 { 170 rt_uint32_t t; 171 rt_hwtimer_mode_t opm = HWTIMER_MODE_PERIOD; 172 rt_hwtimer_t *timer; 173 174 timer = (rt_hwtimer_t *)dev; 175 if ((timer->ops->start == RT_NULL) || (timer->ops->stop == RT_NULL)) 176 return 0; 177 178 if (size != sizeof(rt_hwtimerval_t)) 179 return 0; 180 181 timer->ops->stop(timer); 182 timer->overflow = 0; 183 184 t = timeout_calc(timer, (rt_hwtimerval_t*)buffer); 185 if ((timer->cycles <= 1) && (timer->mode == HWTIMER_MODE_ONESHOT)) 186 { 187 opm = HWTIMER_MODE_ONESHOT; 188 } 189 190 if (timer->ops->start(timer, t, opm) != RT_EOK) 191 size = 0; 192 193 return size; 194 } 195 196 static rt_err_t rt_hwtimer_control(struct rt_device *dev, int cmd, void *args) 197 { 198 rt_err_t result = RT_EOK; 199 rt_hwtimer_t *timer; 200 201 timer = (rt_hwtimer_t *)dev; 202 203 switch (cmd) 204 { 205 case HWTIMER_CTRL_STOP: 206 { 207 if (timer->ops->stop != RT_NULL) 208 { 209 timer->ops->stop(timer); 210 } 211 else 212 { 213 result = -RT_ENOSYS; 214 } 215 } 216 break; 217 case HWTIMER_CTRL_FREQ_SET: 218 { 219 rt_uint32_t *f; 220 221 if (args == RT_NULL) 222 { 223 result = -RT_EEMPTY; 224 break; 225 } 226 227 f = (rt_uint32_t*)args; 228 if ((*f > timer->info->maxfreq) || (*f < timer->info->minfreq)) 229 { 230 result = -RT_ERROR; 231 break; 232 } 233 234 if (timer->ops->control != RT_NULL) 235 { 236 result = timer->ops->control(timer, cmd, args); 237 if (result == RT_EOK) 238 { 239 timer->freq = *f; 240 } 241 } 242 else 243 { 244 result = -RT_ENOSYS; 245 } 246 } 247 break; 248 case HWTIMER_CTRL_INFO_GET: 249 { 250 if (args == RT_NULL) 251 { 252 result = -RT_EEMPTY; 253 break; 254 } 255 256 *((struct rt_hwtimer_info*)args) = *timer->info; 257 } 258 case HWTIMER_CTRL_MODE_SET: 259 { 260 rt_hwtimer_mode_t *m; 261 262 if (args == RT_NULL) 263 { 264 result = -RT_EEMPTY; 265 break; 266 } 267 268 m = (rt_hwtimer_mode_t*)args; 269 270 if ((*m != HWTIMER_MODE_ONESHOT) && (*m != HWTIMER_MODE_PERIOD)) 271 { 272 result = -RT_ERROR; 273 break; 274 } 275 276 timer->mode = *m; 277 } 278 break; 279 default: 280 { 281 result = -RT_ENOSYS; 282 } 283 break; 284 } 285 286 return result; 287 } 288 289 void rt_device_hwtimer_isr(rt_hwtimer_t *timer) 290 { 291 RT_ASSERT(timer != RT_NULL); 292 293 timer->overflow ++; 294 295 if (timer->cycles != 0) 296 { 297 timer->cycles --; 298 } 299 300 if (timer->cycles == 0) 301 { 302 timer->cycles = timer->reload; 303 304 if (timer->mode == HWTIMER_MODE_ONESHOT) 305 { 306 if (timer->ops->stop != RT_NULL) 307 { 308 timer->ops->stop(timer); 309 } 310 } 311 312 if (timer->parent.rx_indicate != RT_NULL) 313 { 314 timer->parent.rx_indicate(&timer->parent, sizeof(struct rt_hwtimerval)); 315 } 316 } 317 } 318 319 #ifdef RT_USING_DEVICE_OPS 320 const static struct rt_device_ops hwtimer_ops = 321 { 322 rt_hwtimer_init, 323 rt_hwtimer_open, 324 rt_hwtimer_close, 325 rt_hwtimer_read, 326 rt_hwtimer_write, 327 rt_hwtimer_control 328 }; 329 #endif 330 331 rt_err_t rt_device_hwtimer_register(rt_hwtimer_t *timer, const char *name, void *user_data) 332 { 333 struct rt_device *device; 334 335 RT_ASSERT(timer != RT_NULL); 336 RT_ASSERT(timer->ops != RT_NULL); 337 RT_ASSERT(timer->info != RT_NULL); 338 339 device = &(timer->parent); 340 341 device->type = RT_Device_Class_Timer; 342 device->rx_indicate = RT_NULL; 343 device->tx_complete = RT_NULL; 344 345 #ifdef RT_USING_DEVICE_OPS 346 device->ops = &hwtimer_ops; 347 #else 348 device->init = rt_hwtimer_init; 349 device->open = rt_hwtimer_open; 350 device->close = rt_hwtimer_close; 351 device->read = rt_hwtimer_read; 352 device->write = rt_hwtimer_write; 353 device->control = rt_hwtimer_control; 354 #endif 355 device->user_data = user_data; 356 357 return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); 358 } 359