pwm.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /****************************************************************************
  2. * include/nuttx/timers/pwm.h
  3. *
  4. * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. #ifndef __INCLUDE_NUTTX_DRIVERS_PWM_H
  36. #define __INCLUDE_NUTTX_DRIVERS_PWM_H
  37. /* For the purposes of this driver, a PWM device is any device that generates
  38. * periodic output pulses s of controlled frequency and pulse width. Such a
  39. * device might be used, for example, to perform pulse-width modulated output or
  40. * frequency/pulse-count modulated output (such as might be needed to control
  41. * a stepper motor).
  42. *
  43. * The PWM driver is split into two parts:
  44. *
  45. * 1) An "upper half", generic driver that provides the common PWM interface
  46. * to application level code, and
  47. * 2) A "lower half", platform-specific driver that implements the low-level
  48. * timer controls to implement the PWM functionality.
  49. */
  50. /****************************************************************************
  51. * Included Files
  52. ****************************************************************************/
  53. #include <nuttx/config.h>
  54. #include <nuttx/compiler.h>
  55. #include <fixedmath.h>
  56. #include <nuttx/fs/ioctl.h>
  57. /****************************************************************************
  58. * Pre-processor Definitions
  59. ****************************************************************************/
  60. /* Configuration ************************************************************/
  61. /* CONFIG_PWM - Enables because PWM driver support
  62. * CONFIG_PWM_PULSECOUNT - Some hardware will support generation of a fixed
  63. * number of pulses. This might be used, for example to support a stepper
  64. * motor. If the hardware will support a fixed pulse count, then this
  65. * configuration should be set to enable the capability.
  66. * CONFIG_PWM_MULTICHAN - Enables support for multiple output channels per
  67. * timer. If selected, then CONFIG_PWM_NCHANNELS must be provided to
  68. * indicated the maximum number of supported PWM output channels.
  69. * CONFIG_DEBUG_PWM_INFO - This will generate output that can be use to
  70. * debug the PWM driver.
  71. */
  72. /* IOCTL Commands ***********************************************************/
  73. /* The PWM module uses a standard character driver framework. However, since
  74. * the PWM driver is a device control interface and not a data transfer
  75. * interface, the majority of the functionality is implemented in driver
  76. * ioctl calls. The PWM ioctl commands are listed below:
  77. *
  78. * PWMIOC_SETCHARACTERISTICS - Set the characteristics of the next pulsed
  79. * output. This command will neither start nor stop the pulsed output.
  80. * It will either setup the configuration that will be used when the
  81. * output is started; or it will change the characteristics of the pulsed
  82. * output on the fly if the timer is already started. This command will
  83. * set the PWM characteristics and return immediately.
  84. *
  85. * ioctl argument: A read-only reference to struct pwm_info_s that provides
  86. * the characteristics of the pulsed output.
  87. *
  88. * PWMIOC_GETCHARACTERISTICS - Get the currently selected characteristics of
  89. * the pulsed output (independent of whether the output is start or stopped).
  90. *
  91. * ioctl argument: A reference to struct pwm_info_s to receive the
  92. * characteristics of the pulsed output.
  93. *
  94. * PWMIOC_START - Start the pulsed output. The PWMIOC_SETCHARACTERISTICS
  95. * command must have previously been sent. If CONFIG_PWM_PULSECOUNT is
  96. * defined and the pulse count was configured to a non-zero value, then
  97. * this ioctl call will, by default, block until the programmed pulse count
  98. * completes. That default blocking behavior can be overridden by using
  99. * the O_NONBLOCK flag when the PWM driver is opened.
  100. *
  101. * ioctl argument: None
  102. *
  103. * PWMIOC_STOP - Stop the pulsed output. This command will stop the PWM
  104. * and return immediately.
  105. *
  106. * ioctl argument: None
  107. */
  108. #define PWMIOC_SETCHARACTERISTICS _PWMIOC(1)
  109. #define PWMIOC_GETCHARACTERISTICS _PWMIOC(2)
  110. #define PWMIOC_START _PWMIOC(3)
  111. #define PWMIOC_STOP _PWMIOC(4)
  112. /****************************************************************************
  113. * Public Types
  114. ****************************************************************************/
  115. /* If the PWM peripheral supports multiple output channels, then this
  116. * structure describes the output state on one channel.
  117. */
  118. #ifdef CONFIG_PWM_MULTICHAN
  119. struct pwm_chan_s
  120. {
  121. ub16_t duty;
  122. uint8_t channel;
  123. };
  124. #endif
  125. /* This structure describes the characteristics of the pulsed output */
  126. struct pwm_info_s
  127. {
  128. uint32_t frequency; /* Frequency of the pulse train */
  129. #ifdef CONFIG_PWM_MULTICHAN
  130. /* Per-channel output state */
  131. struct pwm_chan_s channels[CONFIG_PWM_NCHANNELS];
  132. #else
  133. ub16_t duty; /* Duty of the pulse train, "1"-to-"0" duration.
  134. * Maximum: 65535/65536 (0x0000ffff)
  135. * Minimum: 1/65536 (0x00000001) */
  136. # ifdef CONFIG_PWM_PULSECOUNT
  137. uint32_t count; /* The number of pulse to generate. 0 means to
  138. * generate an indefinite number of pulses */
  139. # endif
  140. #endif /* CONFIG_PWM_MULTICHAN */
  141. };
  142. /* This structure is a set a callback functions used to call from the upper-
  143. * half, generic PWM driver into lower-half, platform-specific logic that
  144. * supports the low-level timer outputs.
  145. */
  146. struct pwm_lowerhalf_s;
  147. struct pwm_ops_s
  148. {
  149. /* This method is called when the driver is opened. The lower half driver
  150. * should configure and initialize the device so that it is ready for use.
  151. * It should not, however, output pulses until the start method is called.
  152. */
  153. CODE int (*setup)(FAR struct pwm_lowerhalf_s *dev);
  154. /* This method is called when the driver is closed. The lower half driver
  155. * should stop pulsed output, free any resources, disable the timer hardware, and
  156. * put the system into the lowest possible power usage state
  157. */
  158. CODE int (*shutdown)(FAR struct pwm_lowerhalf_s *dev);
  159. /* (Re-)initialize the timer resources and start the pulsed output. The
  160. * start method should return an error if it cannot start the timer with
  161. * the given parameter (frequency, duty, or optionally pulse count)
  162. */
  163. #ifdef CONFIG_PWM_PULSECOUNT
  164. CODE int (*start)(FAR struct pwm_lowerhalf_s *dev,
  165. FAR const struct pwm_info_s *info,
  166. FAR void *handle);
  167. #else
  168. CODE int (*start)(FAR struct pwm_lowerhalf_s *dev,
  169. FAR const struct pwm_info_s *info);
  170. #endif
  171. /* Stop the pulsed output and reset the timer resources */
  172. CODE int (*stop)(FAR struct pwm_lowerhalf_s *dev);
  173. /* Lower-half logic may support platform-specific ioctl commands */
  174. CODE int (*ioctl)(FAR struct pwm_lowerhalf_s *dev,
  175. int cmd, unsigned long arg);
  176. };
  177. /* This structure is the generic form of state structure used by lower half
  178. * timer driver. This state structure is passed to the pwm driver when the
  179. * driver is initialized. Then, on subsequent callbacks into the lower half
  180. * timer logic, this structure is provided so that the timer logic can
  181. * maintain state information.
  182. *
  183. * Normally that timer logic will have its own, custom state structure
  184. * that is simply cast to struct pwm_lowerhalf_s. In order to perform such casts,
  185. * the initial fields of the custom state structure match the initial fields
  186. * of the following generic PWM state structure.
  187. */
  188. struct pwm_lowerhalf_s
  189. {
  190. /* The first field of this state structure must be a pointer to the PWM
  191. * callback structure:
  192. */
  193. FAR const struct pwm_ops_s *ops;
  194. /* The custom timer state structure may include additional fields after
  195. * the pointer to the PWM callback structure.
  196. */
  197. };
  198. /****************************************************************************
  199. * Public Data
  200. ****************************************************************************/
  201. /****************************************************************************
  202. * Public Function Prototypes
  203. ****************************************************************************/
  204. #ifdef __cplusplus
  205. #define EXTERN extern "C"
  206. extern "C"
  207. {
  208. #else
  209. #define EXTERN extern
  210. #endif
  211. /****************************************************************************
  212. * "Upper-Half" PWM Driver Interfaces
  213. ****************************************************************************/
  214. /****************************************************************************
  215. * Name: pwm_register
  216. *
  217. * Description:
  218. * This function binds an instance of a "lower half" timer driver with the
  219. * "upper half" PWM device and registers that device so that can be used
  220. * by application code.
  221. *
  222. * When this function is called, the "lower half" driver should be in the
  223. * reset state (as if the shutdown() method had already been called).
  224. *
  225. * Input Parameters:
  226. * path - The full path to the driver to be registers in the NuttX pseudo-
  227. * filesystem. The recommended convention is to name all PWM drivers
  228. * as "/dev/pwm0", "/dev/pwm1", etc. where the driver path differs only
  229. * in the "minor" number at the end of the device name.
  230. * dev - A pointer to an instance of lower half timer driver. This instance
  231. * is bound to the PWM driver and must persists as long as the driver
  232. * persists.
  233. *
  234. * Returned Value:
  235. * Zero on success; a negated errno value on failure.
  236. *
  237. ****************************************************************************/
  238. int pwm_register(FAR const char *path, FAR struct pwm_lowerhalf_s *dev);
  239. /****************************************************************************
  240. * Name: pwm_expired
  241. *
  242. * Description:
  243. * If CONFIG_PWM_PULSECOUNT is defined and the pulse count was configured
  244. * to a non-zero value, then the "upper half" driver will wait for the
  245. * pulse count to expire. The sequence of expected events is as follows:
  246. *
  247. * 1. The upper half driver calls the start method, providing the lower
  248. * half driver with the pulse train characteristics. If a fixed
  249. * number of pulses is required, the 'count' value will be nonzero.
  250. * 2. The lower half driver's start() method must verify that it can
  251. * support the request pulse train (frequency, duty, AND pulse count).
  252. * If it cannot, it should return an error. If the pulse count is
  253. * non-zero, it should set up the hardware for that number of pulses
  254. * and return success. NOTE: That is CONFIG_PWM_PULSECOUNT is
  255. * defined, the start() method receives an additional parameter
  256. * that must be used in this callback.
  257. * 3. When the start() method returns success, the upper half driver
  258. * will "sleep" until the pwm_expired method is called.
  259. * 4. When the lower half detects that the pulse count has expired
  260. * (probably through an interrupt), it must call the pwm_expired
  261. * interface using the handle that was previously passed to the
  262. * start() method
  263. *
  264. * Input Parameters:
  265. * handle - This is the handle that was provided to the lower-half
  266. * start() method.
  267. *
  268. * Returned Value:
  269. * None
  270. *
  271. * Assumptions:
  272. * This function may be called from an interrupt handler.
  273. *
  274. ****************************************************************************/
  275. #ifdef CONFIG_PWM_PULSECOUNT
  276. void pwm_expired(FAR void *handle);
  277. #endif
  278. /****************************************************************************
  279. * Platform-Independent "Lower-Half" PWM Driver Interfaces
  280. ****************************************************************************/
  281. #undef EXTERN
  282. #ifdef __cplusplus
  283. }
  284. #endif
  285. #endif /* __INCLUDE_NUTTX_DRIVERS_PWM_H */