summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/arm/lpc176x/pwmout/pwmout.c
diff options
context:
space:
mode:
authorMartin Galvan <martin.galvan@tallertechnologies.com>2015-03-11 16:57:23 -0300
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-03-20 09:16:07 +0100
commit7b35a36fb16491dbdb98106ab39d35b8d19598e5 (patch)
treea5c23a33c3316623fa5fa5129f6669147f249bb0 /c/src/lib/libbsp/arm/lpc176x/pwmout/pwmout.c
parentscore: Fix _Thread_Change_priority() (diff)
downloadrtems-7b35a36fb16491dbdb98106ab39d35b8d19598e5.tar.bz2
Add CAN, PWM, ADC and UART1/2/3 support to the LPC176x BSP.
This patch adds support for the following devices to the LPC176x BSP: * CAN * PWM * ADC It also adds the probe routines for UART1/2/3 to the console_device_table in console-config.c, and enables UART1 in configure.ac.
Diffstat (limited to '')
-rwxr-xr-xc/src/lib/libbsp/arm/lpc176x/pwmout/pwmout.c210
1 files changed, 210 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/arm/lpc176x/pwmout/pwmout.c b/c/src/lib/libbsp/arm/lpc176x/pwmout/pwmout.c
new file mode 100755
index 0000000000..a3683869a5
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc176x/pwmout/pwmout.c
@@ -0,0 +1,210 @@
+/**
+ * @file pwmout.c
+ *
+ * @ingroup lpc176x
+ *
+ * @brief PWM-Out controller for the mbed lpc1768 board.
+ */
+
+/*
+ * Copyright (c) 2014 Taller Technologies.
+ *
+ * @author Diaz Marcos (marcos.diaz@tallertechnologies.com)
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <rtems/status-checks.h>
+#include <bsp/pwmout.h>
+#include <bsp/pwmout-defs.h>
+
+/**
+ * @brief The low level device.
+ */
+static lpc176x_pwm_device *const pwm_device = PWM1_BASE_ADDR;
+
+/**
+ * @brief The possible output pins for each PWM output.
+ */
+static const lpc176x_pwm_pin pwm_pins[ PWM_OUTPUT_NUMBER ][ PWM_NUMBER_OF_PINS
+] =
+{
+ { { 50u, LPC176X_PIN_FUNCTION_10 }, { 64u, LPC176X_PIN_FUNCTION_01 } },
+ { { 52u, LPC176X_PIN_FUNCTION_10 }, { 65u, LPC176X_PIN_FUNCTION_01 } },
+ { { 53u, LPC176X_PIN_FUNCTION_10 }, { 66u, LPC176X_PIN_FUNCTION_01 } },
+ { { 55u, LPC176X_PIN_FUNCTION_10 }, { 67u, LPC176X_PIN_FUNCTION_01 } },
+ { { 56u, LPC176X_PIN_FUNCTION_10 }, { 68u, LPC176X_PIN_FUNCTION_01 } },
+ { { 58u, LPC176X_PIN_FUNCTION_10 }, { 69u, LPC176X_PIN_FUNCTION_01 } },
+};
+
+/**
+ * @brief The pointers to the low level match registers for each PWM output.
+ */
+static volatile uint32_t *const pwm_match[ PWM_OUTPUT_NUMBER ] = {
+ &PWM1MR1,
+ &PWM1MR2,
+ &PWM1MR3,
+ &PWM1MR4,
+ &PWM1MR5,
+ &PWM1MR6
+};
+
+/**
+ * @brief Checks if a pin number is valid for the given PWM,
+ * and sets the corresponding pin function for that pin.
+ *
+ * @param pin_number The pin number to search.
+ * @param pwm In which PWM search for the pin number.
+ * @param pin_function If the pin number is found, here we return
+ * the pin function for that pin number.
+ * @return True if found, false otherwise.
+ */
+static inline bool is_found_in_this_pwm(
+ const lpc176x_pin_number pin_number,
+ const lpc176x_pwm_number pwm,
+ lpc176x_pin_function *const pin_function
+)
+{
+ lpc176x_pwm_pin_number pnumber = PWM_FIRST_PIN;
+ bool found = false;
+
+ while (!found && ( pnumber < PWM_NUMBER_OF_PINS ))
+ {
+ if ( pwm_pins[ pwm ][ pnumber ].pin_number == pin_number ) {
+ found = true;
+ *pin_function = pwm_pins[ pwm ][ pnumber ].pin_function;
+ }/*else implies that the pin number was not found. Keep looking.*/
+ ++pnumber;
+ }
+ return found;
+}
+
+/**
+ * @brief Checks if a pin number is valid for any PWM,
+ * and sets the corresponding pin function for that pin.
+ *
+ * @param pin_number The pin number to search.
+ * @param pwm If is found here we return in which PWM was found.
+ * @param pin_function If the pin number is found the pin function
+ * for this pin number one will be returned.
+ * @return True if found, false otherwise.
+ */
+static bool is_valid_pin_number(
+ const lpc176x_pin_number pin_number,
+ lpc176x_pwm_number *const pwm,
+ lpc176x_pin_function *const pin_function
+)
+{
+ bool found = false;
+ lpc176x_pwm_number pwm_local = PWMO_1;
+ while(!found && ( pwm_local < PWM_OUTPUT_NUMBER ))
+ {
+ if ( is_found_in_this_pwm( pin_number, pwm_local, pin_function ) ) {
+ *pwm = pwm_local;
+ found = true;
+ } /*else implies that the pin number was not found. Keep looking.*/
+ ++pwm_local;
+ }
+
+ return found;
+}
+
+/**
+ * @brief Sets the period for the given PWM.
+ *
+ * @param pwm The PWM output in which the period will be set.
+ * @param period The period to set.
+ */
+static void set_period(
+ const lpc176x_pwm_number pwm,
+ const lpc176x_microseconds period
+)
+{
+ pwm_device->TCR = PWM_TCR_RESET;
+ pwm_device->MR0 = period * PWM_PRESCALER_USECOND;
+ pwm_device->LER |= PWM_LER_LATCH_MATCH_0;
+ pwm_device->TCR = PWM_TCR_PWM | PWM_TCR_ENABLE;
+}
+
+/**
+ * @brief Sets the pulsewidth for the given PWM.
+ *
+ * @param pwm The PWM output in which the pulsewidth will be set.
+ * @param pwidth The pulse width to set.
+ */
+static void set_pulsewidth(
+ const lpc176x_pwm_number pwm,
+ lpc176x_microseconds pwidth
+)
+{
+ pwidth *= PWM_PRESCALER_USECOND;
+
+ if ( pwm_device->MR0 == pwidth ) {
+ ++pwidth;
+ } /* Not the same as the period, do nothing.*/
+
+ *( pwm_match[ pwm ] ) = pwidth;
+ pwm_device->LER |= PWM_LER_LATCH( pwm );
+}
+
+rtems_status_code pwm_init( const lpc176x_pin_number pin_number )
+{
+ rtems_status_code sc = RTEMS_INVALID_NUMBER;
+ lpc176x_pin_function pin_function;
+ lpc176x_pwm_number pwm;
+
+ if ( is_valid_pin_number( pin_number, &pwm, &pin_function ) ) {
+ sc = lpc176x_module_enable( LPC176X_MODULE_PWM_1,
+ LPC176X_MODULE_PCLK_DEFAULT );
+ RTEMS_CHECK_SC( sc, "enable pwm module" );
+
+ pwm_device->PR = 0;
+ pwm_device->MCR = PWM_MCR_RESET_ON_MATCH0;
+ pwm_device->PCR |= PWM_PCR_ENABLE_PWM( pwm );
+
+ set_period( pwm, PWM_DEFAULT_PERIOD );
+ set_pulsewidth( pwm, PWM_DEFAULT_PULSEWIDTH );
+
+ lpc176x_pin_select( pin_number, pin_function );
+ } /* else implies that the pin number is not valid.
+ So, a RTEMS_INVALID_NUMBER will be returned.*/
+
+ return sc;
+}
+
+rtems_status_code pwm_period(
+ const lpc176x_pin_number pin_number,
+ const lpc176x_microseconds period
+)
+{
+ rtems_status_code sc = RTEMS_INVALID_NUMBER;
+ lpc176x_pin_function pin_function;
+ lpc176x_pwm_number pwm;
+
+ if ( is_valid_pin_number( pin_number, &pwm, &pin_function ) ) {
+ sc = RTEMS_SUCCESSFUL;
+ set_period( pwm, period );
+ } /* else implies that the pin number is not valid.
+ So, a RTEMS_INVALID_NUMBER will be returned.*/
+
+ return sc;
+}
+
+rtems_status_code pwm_pulsewidth(
+ const lpc176x_pin_number pin_number,
+ const lpc176x_microseconds pwidth
+)
+{
+ rtems_status_code sc = RTEMS_INVALID_NUMBER;
+ lpc176x_pin_function pin_function;
+ lpc176x_pwm_number pwm;
+
+ if ( is_valid_pin_number( pin_number, &pwm, &pin_function ) ) {
+ sc = RTEMS_SUCCESSFUL;
+ set_pulsewidth( pwm, pwidth );
+ } /* Else wrong pin_number return RTEMS_INVALID_NUMBER*/
+
+ return sc;
+}