1 /*
2  * Copyright (c) 2015-2019, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*! ============================================================================
33  *  @file       PWMTimerCC32XX.h
34  *
35  *  @brief      PWM driver implementation using CC32XX General Purpose Timers.
36  *
37  *  The PWM header file should be included in an application as follows:
38  *  @code
39  *  #include <ti/drivers/PWM.h>
40  *  #include <ti/drivers/pwm/PWMTimerCC32XX.h>
41  *  @endcode
42  *
43  *  Refer to @ref PWM.h for a complete description of the PWM
44  *  driver APIs provided and examples of their use.
45  *
46  *  ## Overview #
47  *  This driver configures a CC32XX General Purpose Timer (GPT) in PWM mode.
48  *  When in PWM mode, each GPT is divided into 2 PWM outputs.  This driver
49  *  manages each output as an independent PWM instance.  The timer is
50  *  automatically configured in count-down mode using the system clock as
51  *  the source.
52  *
53  *  The timers operate at the system clock frequency (80 MHz). So each timer
54  *  tick is 12.5 ns. The period and duty registers are 16 bits wide; thus
55  *  8-bit prescalars are used to extend period and duty registers.  The
56  *  maximum value supported is 16777215 timer counts ((2^24) - 1) or
57  *  209715 microseconds.  Updates to a PWM's period or duty will occur
58  *  instantaneously (GPT peripherals do not have shadow registers).
59  *
60  *  When stopped, the driver will configure the pin in GPIO mode & set the
61  *  output to the PWM_IdleLevel specified in the params used during open.  Users
62  *  need be aware that while PIN 19 can be used for PWM it is not GPIO capable,
63  *  so it cannot be set to the PWM_IdleLevel.  Output voltage will be PWM output
64  *  at the moment it is stopped.
65  *
66  *  Finally, when this driver is opened, it automatically changes the
67  *  PWM pin's parking configuration (used when entering low power modes) to
68  *  correspond with the PWM_IDLE_LEVEL set in the PWM_params.  However, this
69  *  setting is not reverted once the driver is closed, it is the users
70  *  responsibility to change the parking configuration if necessary.
71  *
72  *  ### CC32xx PWM Driver Configuration #
73  *
74  *  In order to use the PWM APIs, the application is required
75  *  to define 4 configuration items in the application ti_drivers_config.c file:
76  *
77  *  1.  An array of PWMTimerCC32XX_Object elements, which will be used by
78  *  by the driver to maintain instance state.
79  *  Below is an example PWMTimerCC32XX_Object array appropriate for the CC3220SF LaunchPad
80  *  board:
81  *  @code
82  *    #include <ti/drivers/PWM.h>
83  *    #include <ti/drivers/pwm/PWMTimerCC32XX.h>
84  *
85  *    PWMTimerCC32XX_Object pwmTimerCC3220SObjects[CC3220SF_LAUNCHXL_PWMCOUNT];
86  *  @endcode
87  *
88  *  2.  An array of PWMTimerCC32XX_HWAttrsV2 elements that defines which
89  *  pin will be used by the corresponding PWM instance
90  *  (see @ref pwmPinIdentifiersCC32XX).
91  *  Below is an example PWMTimerCC32XX_HWAttrsV2 array appropriate for the CC3220SF LaunchPad
92  *  board:
93  *  @code
94  *    const PWMTimerCC32XX_HWAttrsV2 pwmTimerCC3220SHWAttrs[CC3220SF_LAUNCHXL_PWMCOUNT] = {
95  *        {
96  *            .pwmPin = PWMTimerCC32XX_PIN_01
97  *        },
98  *        {
99  *            .pwmPin = PWMTimerCC32XX_PIN_02
100  *        }
101  *    };
102  *  @endcode
103  *
104  *  3.  An array of @ref PWM_Config elements, one for each PWM instance. Each
105  *  element of this array identifies the device-specific API function table,
106  *  the device specific PWM object instance, and the device specific Hardware
107  *  Attributes to be used for each PWM channel.
108  *  Below is an example @ref PWM_Config array appropriate for the CC3220SF LaunchPad
109  *  board:
110  *  @code
111  *    const PWM_Config PWM_config[CC3220SF_LAUNCHXL_PWMCOUNT] = {
112  *        {
113  *            .fxnTablePtr = &PWMTimerCC32XX_fxnTable,
114  *            .object = &pwmTimerCC3220SObjects[CC3220SF_LAUNCHXL_PWM6],
115  *            .hwAttrs = &pwmTimerCC3220SHWAttrs[CC3220SF_LAUNCHXL_PWM6]
116  *        },
117  *        {
118  *            .fxnTablePtr = &PWMTimerCC32XX_fxnTable,
119  *            .object = &pwmTimerCC3220SObjects[CC3220SF_LAUNCHXL_PWM7],
120  *            .hwAttrs = &pwmTimerCC3220SHWAttrs[CC3220SF_LAUNCHXL_PWM7]
121  *        }
122  *    };
123  *  @endcode
124  *
125  *  4.  A global variable, PWM_count, that informs the driver how many PWM
126  *  instances are defined:
127  *  @code
128  *    const uint_least8_t PWM_count = CC3220SF_LAUNCHXL_PWMCOUNT;
129  *  @endcode
130  *
131  * ### Power Management #
132  * The TI-RTOS power management framework will try to put the device into the most
133  * power efficient mode whenever possible. Please see the technical reference
134  * manual for further details on each power mode.
135  *
136  *  The PWMTimerCC32XX driver explicitly sets a power constraint when the
137  *  PWM is running to prevent LPDS.
138  *  The following statements are valid:
139  *    - After PWM_open():  Clocks are enabled to the timer resource and the
140  *                         configured pwmPin. The device is still allowed
141  *                         to enter LPDS.
142  *    - After PWM_start(): LPDS is disabled when PWM is running.
143  *    - After PWM_stop():  Conditions are equal as for after PWM_open
144  *    - After PWM_close(): The underlying GPTimer is turned off, and the clocks
145  *                         to the timer and pin are disabled..
146  *
147  * =============================================================================
148  */
149 
150 #ifndef ti_driver_pwm_PWMTimerCC32XX__include
151 #define ti_driver_pwm_PWMTimerCC32XX__include
152 
153 #include <stdbool.h>
154 #include <ti/drivers/Power.h>
155 #include <ti/drivers/PWM.h>
156 
157 #ifdef __cplusplus
158 extern "C" {
159 #endif
160 
161 /*! \cond */
162 /*
163  *  PWMTimer port/pin defines for pin configuration.
164  *
165  *  The timer id (0, 1, 2, or 3) is stored in bits 31 - 28
166  *  The timer half (0 = A, 1 = B) is stored in bits 27 - 24
167  *  The GPIO port (0, 1, 2, or 3) is stored in bits 23 - 20
168  *  The GPIO pin index within the port (0 - 7) is stored in bits 19 - 16
169  *  The pin mode is stored in bits 11 - 8
170  *  The pin number is stored in bits 7 - 0
171  *
172  *
173  *    31 - 28     27 - 24      23 - 20        19 - 16       11 - 8   7 - 0
174  *  -----------------------------------------------------------------------
175  *  | Timer id | Timer half | GPIO port | GPIO pin index | pin mode | pin |
176  *  -----------------------------------------------------------------------
177  *
178  *  The CC32XX has fixed GPIO assignments and pin modes for a given pin.
179  *  A PWM pin mode for a given pin has a fixed timer/timer-half.
180  */
181 #define PWMTimerCC32XX_T0A  (0x00 << 24)
182 #define PWMTimerCC32XX_T0B  (0x01 << 24)
183 #define PWMTimerCC32XX_T1A  (0x10 << 24)
184 #define PWMTimerCC32XX_T1B  (0x11 << 24)
185 #define PWMTimerCC32XX_T2A  (0x20 << 24)
186 #define PWMTimerCC32XX_T2B  (0x21 << 24)
187 #define PWMTimerCC32XX_T3A  (0x30 << 24)
188 #define PWMTimerCC32XX_T3B  (0x31 << 24)
189 
190 #define PWMTimerCC32XX_GPIO9   (0x11 << 16)
191 #define PWMTimerCC32XX_GPIO10  (0x12 << 16)
192 #define PWMTimerCC32XX_GPIO11  (0x13 << 16)
193 #define PWMTimerCC32XX_GPIO24  (0x30 << 16)
194 #define PWMTimerCC32XX_GPIO25  (0x31 << 16)
195 
196 #define PWMTimerCC32XX_GPIONONE  (0xFF << 16)
197 /*! \endcond */
198 
199 /*!
200  *  \defgroup pwmPinIdentifiersCC32XX PWMTimerCC32XX_HWAttrs 'pwmPin' field options
201  *  @{
202  */
203 /*!
204  *  @name PIN 01, GPIO10, uses Timer3A for PWM.
205  *  @{
206  */
207 #define PWMTimerCC32XX_PIN_01  (PWMTimerCC32XX_T3A | PWMTimerCC32XX_GPIO10 | 0x0300) /*!< @hideinitializer */
208 /*! @} */
209 /*!
210  *  @name PIN 02, GPIO11, uses Timer3B for PWM.
211  *  @{
212  */
213 #define PWMTimerCC32XX_PIN_02  (PWMTimerCC32XX_T3B | PWMTimerCC32XX_GPIO11 | 0x0301) /*!< @hideinitializer */
214 /*! @} */
215 /*!
216  *  @name PIN 17, GPIO24, uses Timer0A for PWM.
217  *  @{
218  */
219 #define PWMTimerCC32XX_PIN_17  (PWMTimerCC32XX_T0A | PWMTimerCC32XX_GPIO24 | 0x0510) /*!< @hideinitializer */
220 /*! @} */
221 /*!
222  *  @name PIN 19, uses Timer1B for PWM.
223  *  @{
224  */
225 #define PWMTimerCC32XX_PIN_19  (PWMTimerCC32XX_T1B | PWMTimerCC32XX_GPIONONE | 0x0812) /*!< @hideinitializer */
226 /*! @} */
227 /*!
228  *  @name PIN 21, GPIO25, uses Timer1A for PWM.
229  *  @{
230  */
231 #define PWMTimerCC32XX_PIN_21  (PWMTimerCC32XX_T1A | PWMTimerCC32XX_GPIO25 | 0x0914) /*!< @hideinitializer */
232 /*! @} */
233 /*!
234  *  @name PIN 64, GPIO9, uses Timer2B for PWM.
235  *  @{
236  */
237 #define PWMTimerCC32XX_PIN_64  (PWMTimerCC32XX_T2B | PWMTimerCC32XX_GPIO9 | 0x033F)  /*!< @hideinitializer */
238 /*! @} */
239 /*! @} */
240 
241 /**
242  *  @addtogroup PWM_STATUS
243  *  PWMTimerCC32XX_STATUS_* macros are command codes only defined in the
244  *  PWMTimerCC32XX.h driver implementation and need to:
245  *  @code
246  *  #include <ti/drivers/pwm/PWMTimerCC32XX.h>
247  *  @endcode
248  *  @{
249  */
250 
251 /* Add PWMTimerCC32XX_STATUS_* macros here */
252 
253 /** @}*/
254 
255 /**
256  *  @addtogroup PWM_CMD
257  *  PWMTimerCC32XX_CMD_* macros are command codes only defined in the
258  *  PWMTimerCC32XX.h driver implementation and need to:
259  *  @code
260  *  #include <ti/drivers/pwm/PWMTimerCC32XX.h>
261  *  @endcode
262  *  @{
263  */
264 
265 /* Add PWMTimerCC32XX_CMD_* macros here */
266 
267 /** @}*/
268 
269 /* PWM function table pointer */
270 extern const PWM_FxnTable PWMTimerCC32XX_fxnTable;
271 
272 /*!
273  *  @brief  PWMTimerCC32XX Hardware attributes
274  *
275  *  The 'pwmPin' field identifies which physical pin to use for a
276  *  particular PWM channel as well as the corresponding Timer resource used
277  *  to source the PWM signal. The encoded pin identifier macros for
278  *  initializing the 'pwmPin' field must be selected from the
279  *  @ref pwmPinIdentifiersCC32XX macros.
280  *
281  *  A sample structure is shown below:
282  *  @code
283  *  const PWMTimerCC32XX_HWAttrsV2 pwmTimerCC32XXHWAttrs[] = {
284  *      {
285  *          .pwmPin = PWMTimerCC32XX_PIN_01,
286  *      },
287  *      {
288  *          .pwmPin = PWMTimerCC32XX_PIN_02,
289  *      }
290  *  };
291  *  @endcode
292  */
293 typedef struct {
294     uint32_t pwmPin;                    /*!< Pin to output PWM signal on
295                                              (see @ref pwmPinIdentifiersCC32XX) */
296 } PWMTimerCC32XX_HWAttrsV2;
297 
298 /*!
299  *  @brief  PWMTimerCC32XX Object
300  *
301  *  The application must not access any member variables of this structure!
302  */
303 typedef struct {
304     Power_NotifyObj  postNotify;
305     uint32_t         duty;              /* Current duty cycle in Duty_Unites */
306     uint32_t         period;            /* Current period PERIOD_Units */
307     PWM_Duty_Units   dutyUnits;         /* Current duty cycle unit */
308     PWM_Period_Units periodUnits;       /* Current period unit */
309     PWM_IdleLevel    idleLevel;         /* PWM idle level when stopped / not started */
310     bool             pwmStarted;        /* Used to gate Power_set/releaseConstraint() calls */
311     bool             isOpen;            /* open flag used to check if PWM is opened */
312 } PWMTimerCC32XX_Object;
313 
314 #ifdef __cplusplus
315 }
316 #endif
317 
318 #endif /* ti_driver_pwm_PWMTimerCC32XX__include */
319