source: rtems/bsps/arm/lpc176x/pwm/pwmout.c @ e945b049

5
Last change on this file since e945b049 was e945b049, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 25, 2018 at 8:43:38 AM

bsp/lpc176x: Move source files to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100755
File size: 5.8 KB
Line 
1/**
2 * @file pwmout.c
3 *
4 * @ingroup lpc176x
5 *
6 * @brief PWM-Out controller for the mbed lpc1768 board.
7 */
8
9/*
10 * Copyright (c) 2014 Taller Technologies.
11 *
12 * @author  Diaz Marcos (marcos.diaz@tallertechnologies.com)
13 *
14 * The license and distribution terms for this file may be
15 * found in the file LICENSE in this distribution or at
16 * http://www.rtems.org/license/LICENSE.
17 */
18
19#include <rtems/status-checks.h>
20#include <bsp/pwmout.h>
21#include <bsp/pwmout-defs.h>
22
23/**
24 * @brief The low level device.
25 */
26static lpc176x_pwm_device *const pwm_device =
27  (lpc176x_pwm_device *) PWM1_BASE_ADDR;
28
29/**
30 * @brief The possible output pins for each PWM output.
31 */
32static const lpc176x_pwm_pin pwm_pins[ PWM_OUTPUT_NUMBER ][ PWM_NUMBER_OF_PINS
33] =
34{
35  { { 50u, LPC176X_PIN_FUNCTION_10 }, { 64u, LPC176X_PIN_FUNCTION_01 } },
36  { { 52u, LPC176X_PIN_FUNCTION_10 }, { 65u, LPC176X_PIN_FUNCTION_01 } },
37  { { 53u, LPC176X_PIN_FUNCTION_10 }, { 66u, LPC176X_PIN_FUNCTION_01 } },
38  { { 55u, LPC176X_PIN_FUNCTION_10 }, { 67u, LPC176X_PIN_FUNCTION_01 } },
39  { { 56u, LPC176X_PIN_FUNCTION_10 }, { 68u, LPC176X_PIN_FUNCTION_01 } },
40  { { 58u, LPC176X_PIN_FUNCTION_10 }, { 69u, LPC176X_PIN_FUNCTION_01 } },
41};
42
43/**
44 * @brief The pointers to the low level match registers for each PWM output.
45 */
46static volatile uint32_t *const pwm_match[ PWM_OUTPUT_NUMBER ] = {
47  &PWM1MR1,
48  &PWM1MR2,
49  &PWM1MR3,
50  &PWM1MR4,
51  &PWM1MR5,
52  &PWM1MR6
53};
54
55/**
56 * @brief Checks if a pin number is valid for the given PWM,
57 *  and sets the corresponding pin function for that pin.
58 *
59 * @param pin_number The pin number to search.
60 * @param pwm In which PWM search for the pin number.
61 * @param pin_function If the pin number is found, here we return
62 *  the pin function for that pin number.
63 * @return True if found, false otherwise.
64 */
65static inline bool is_found_in_this_pwm(
66  const lpc176x_pin_number       pin_number,
67  const lpc176x_pwm_number    pwm,
68  lpc176x_pin_function *const pin_function
69)
70{
71  lpc176x_pwm_pin_number pnumber = PWM_FIRST_PIN;
72  bool                   found = false;
73
74  while (!found && ( pnumber < PWM_NUMBER_OF_PINS ))
75  {
76    if ( pwm_pins[ pwm ][ pnumber ].pin_number == pin_number ) {
77      found = true;
78      *pin_function = pwm_pins[ pwm ][ pnumber ].pin_function;
79    }/*else implies that the pin number was not found. Keep looking.*/
80    ++pnumber;
81  }
82  return found;
83}
84
85/**
86 * @brief Checks if a pin number is valid for any PWM,
87 *  and sets the corresponding pin function for that pin.
88 *
89 * @param pin_number The pin number to search.
90 * @param pwm If is found here we return in which PWM was found.
91 * @param pin_function If the pin number is found the pin function
92 *  for this pin number one will be returned.
93 * @return True if found, false otherwise.
94 */
95static bool is_valid_pin_number(
96  const lpc176x_pin_number       pin_number,
97  lpc176x_pwm_number *const   pwm,
98  lpc176x_pin_function *const pin_function
99)
100{
101  bool               found = false;
102  lpc176x_pwm_number pwm_local = PWMO_1;
103  while(!found && ( pwm_local < PWM_OUTPUT_NUMBER ))
104  {
105    if ( is_found_in_this_pwm( pin_number, pwm_local, pin_function ) ) {
106      *pwm = pwm_local;
107      found = true;
108    } /*else implies that the pin number was not found. Keep looking.*/
109    ++pwm_local;
110  }
111
112  return found;
113}
114
115/**
116 * @brief Sets the period for the given PWM.
117 *
118 * @param pwm The PWM output in which the period will be set.
119 * @param period The period to set.
120 */
121static void set_period(
122  const lpc176x_pwm_number   pwm,
123  const lpc176x_microseconds period
124)
125{
126  pwm_device->TCR = PWM_TCR_RESET;
127  pwm_device->MR0 = period * PWM_PRESCALER_USECOND;
128  pwm_device->LER |= PWM_LER_LATCH_MATCH_0;
129  pwm_device->TCR = PWM_TCR_PWM | PWM_TCR_ENABLE;
130}
131
132/**
133 * @brief Sets the pulsewidth for the given PWM.
134 *
135 * @param pwm The PWM output in which the pulsewidth will be set.
136 * @param pwidth The pulse width to set.
137 */
138static void set_pulsewidth(
139  const lpc176x_pwm_number pwm,
140  lpc176x_microseconds     pwidth
141)
142{
143  pwidth *= PWM_PRESCALER_USECOND;
144
145  if ( pwm_device->MR0 == pwidth ) {
146    ++pwidth;
147  } /* Not the same as the period, do nothing.*/
148
149  *( pwm_match[ pwm ] ) = pwidth;
150  pwm_device->LER |= PWM_LER_LATCH( pwm );
151}
152
153rtems_status_code pwm_init( const lpc176x_pin_number pin_number )
154{
155  rtems_status_code    sc = RTEMS_INVALID_NUMBER;
156  lpc176x_pin_function pin_function;
157  lpc176x_pwm_number   pwm;
158
159  if ( is_valid_pin_number( pin_number, &pwm, &pin_function ) ) {
160    sc = lpc176x_module_enable( LPC176X_MODULE_PWM_1,
161      LPC176X_MODULE_PCLK_DEFAULT );
162    RTEMS_CHECK_SC( sc, "enable pwm module" );
163
164    pwm_device->PR = 0;
165    pwm_device->MCR = PWM_MCR_RESET_ON_MATCH0;
166    pwm_device->PCR |= PWM_PCR_ENABLE_PWM( pwm );
167
168    set_period( pwm, PWM_DEFAULT_PERIOD );
169    set_pulsewidth( pwm, PWM_DEFAULT_PULSEWIDTH );
170
171    lpc176x_pin_select( pin_number, pin_function );
172  } /* else implies that the pin number is not valid.
173     So, a RTEMS_INVALID_NUMBER will be returned.*/
174
175  return sc;
176}
177
178rtems_status_code pwm_period(
179  const lpc176x_pin_number    pin_number,
180  const lpc176x_microseconds period
181)
182{
183  rtems_status_code    sc = RTEMS_INVALID_NUMBER;
184  lpc176x_pin_function pin_function;
185  lpc176x_pwm_number   pwm;
186
187  if ( is_valid_pin_number( pin_number, &pwm, &pin_function ) ) {
188    sc = RTEMS_SUCCESSFUL;
189    set_period( pwm, period );
190  } /* else implies that the pin number is not valid.
191     So, a RTEMS_INVALID_NUMBER will be returned.*/
192
193  return sc;
194}
195
196rtems_status_code pwm_pulsewidth(
197  const lpc176x_pin_number    pin_number,
198  const lpc176x_microseconds pwidth
199)
200{
201  rtems_status_code    sc = RTEMS_INVALID_NUMBER;
202  lpc176x_pin_function pin_function;
203  lpc176x_pwm_number   pwm;
204
205  if ( is_valid_pin_number( pin_number, &pwm, &pin_function ) ) {
206    sc = RTEMS_SUCCESSFUL;
207    set_pulsewidth( pwm, pwidth );
208  } /* Else wrong pin_number return RTEMS_INVALID_NUMBER*/
209
210  return sc;
211}
Note: See TracBrowser for help on using the repository browser.