Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:03

0001 /**
0002  * @file
0003  *
0004  * @ingroup RTEMSBSPsARMLPC176X
0005  *
0006  * @brief PWM-Out controller for the mbed lpc1768 board.
0007  */
0008 
0009 /*
0010  * Copyright (c) 2014 Taller Technologies.
0011  *
0012  * @author  Diaz Marcos (marcos.diaz@tallertechnologies.com)
0013  *
0014  * The license and distribution terms for this file may be
0015  * found in the file LICENSE in this distribution or at
0016  * http://www.rtems.org/license/LICENSE.
0017  */
0018 
0019 #include <rtems/status-checks.h>
0020 #include <bsp/pwmout.h>
0021 #include <bsp/pwmout-defs.h>
0022 
0023 /**
0024  * @brief The low level device.
0025  */
0026 static lpc176x_pwm_device *const pwm_device =
0027   (lpc176x_pwm_device *) PWM1_BASE_ADDR;
0028 
0029 /**
0030  * @brief The possible output pins for each PWM output.
0031  */
0032 static const lpc176x_pwm_pin pwm_pins[ PWM_OUTPUT_NUMBER ][ PWM_NUMBER_OF_PINS
0033 ] =
0034 {
0035   { { 50u, LPC176X_PIN_FUNCTION_10 }, { 64u, LPC176X_PIN_FUNCTION_01 } },
0036   { { 52u, LPC176X_PIN_FUNCTION_10 }, { 65u, LPC176X_PIN_FUNCTION_01 } },
0037   { { 53u, LPC176X_PIN_FUNCTION_10 }, { 66u, LPC176X_PIN_FUNCTION_01 } },
0038   { { 55u, LPC176X_PIN_FUNCTION_10 }, { 67u, LPC176X_PIN_FUNCTION_01 } },
0039   { { 56u, LPC176X_PIN_FUNCTION_10 }, { 68u, LPC176X_PIN_FUNCTION_01 } },
0040   { { 58u, LPC176X_PIN_FUNCTION_10 }, { 69u, LPC176X_PIN_FUNCTION_01 } },
0041 };
0042 
0043 /**
0044  * @brief The pointers to the low level match registers for each PWM output.
0045  */
0046 static volatile uint32_t *const pwm_match[ PWM_OUTPUT_NUMBER ] = {
0047   &PWM1MR1,
0048   &PWM1MR2,
0049   &PWM1MR3,
0050   &PWM1MR4,
0051   &PWM1MR5,
0052   &PWM1MR6
0053 };
0054 
0055 /**
0056  * @brief Checks if a pin number is valid for the given PWM,
0057  *  and sets the corresponding pin function for that pin.
0058  *
0059  * @param pin_number The pin number to search.
0060  * @param pwm In which PWM search for the pin number.
0061  * @param pin_function If the pin number is found, here we return
0062  *  the pin function for that pin number.
0063  * @return True if found, false otherwise.
0064  */
0065 static inline bool is_found_in_this_pwm(
0066   const lpc176x_pin_number       pin_number,
0067   const lpc176x_pwm_number    pwm,
0068   lpc176x_pin_function *const pin_function
0069 )
0070 {
0071   lpc176x_pwm_pin_number pnumber = PWM_FIRST_PIN;
0072   bool                   found = false;
0073 
0074   while (!found && ( pnumber < PWM_NUMBER_OF_PINS ))
0075   {
0076     if ( pwm_pins[ pwm ][ pnumber ].pin_number == pin_number ) {
0077       found = true;
0078       *pin_function = pwm_pins[ pwm ][ pnumber ].pin_function;
0079     }/*else implies that the pin number was not found. Keep looking.*/
0080     ++pnumber;
0081   }
0082   return found;
0083 }
0084 
0085 /**
0086  * @brief Checks if a pin number is valid for any PWM,
0087  *  and sets the corresponding pin function for that pin.
0088  *
0089  * @param pin_number The pin number to search.
0090  * @param pwm If is found here we return in which PWM was found.
0091  * @param pin_function If the pin number is found the pin function
0092  *  for this pin number one will be returned.
0093  * @return True if found, false otherwise.
0094  */
0095 static bool is_valid_pin_number(
0096   const lpc176x_pin_number       pin_number,
0097   lpc176x_pwm_number *const   pwm,
0098   lpc176x_pin_function *const pin_function
0099 )
0100 {
0101   bool               found = false;
0102   lpc176x_pwm_number pwm_local = PWMO_1;
0103   while(!found && ( pwm_local < PWM_OUTPUT_NUMBER ))
0104   {
0105     if ( is_found_in_this_pwm( pin_number, pwm_local, pin_function ) ) {
0106       *pwm = pwm_local;
0107       found = true;
0108     } /*else implies that the pin number was not found. Keep looking.*/
0109     ++pwm_local;
0110   }
0111 
0112   return found;
0113 }
0114 
0115 /**
0116  * @brief Sets the period for the given PWM.
0117  *
0118  * @param pwm The PWM output in which the period will be set.
0119  * @param period The period to set.
0120  */
0121 static void set_period(
0122   const lpc176x_pwm_number   pwm,
0123   const lpc176x_microseconds period
0124 )
0125 {
0126   pwm_device->TCR = PWM_TCR_RESET;
0127   pwm_device->MR0 = period * PWM_PRESCALER_USECOND;
0128   pwm_device->LER |= PWM_LER_LATCH_MATCH_0;
0129   pwm_device->TCR = PWM_TCR_PWM | PWM_TCR_ENABLE;
0130 }
0131 
0132 /**
0133  * @brief Sets the pulsewidth for the given PWM.
0134  *
0135  * @param pwm The PWM output in which the pulsewidth will be set.
0136  * @param pwidth The pulse width to set.
0137  */
0138 static void set_pulsewidth(
0139   const lpc176x_pwm_number pwm,
0140   lpc176x_microseconds     pwidth
0141 )
0142 {
0143   pwidth *= PWM_PRESCALER_USECOND;
0144 
0145   if ( pwm_device->MR0 == pwidth ) {
0146     ++pwidth;
0147   } /* Not the same as the period, do nothing.*/
0148 
0149   *( pwm_match[ pwm ] ) = pwidth;
0150   pwm_device->LER |= PWM_LER_LATCH( pwm );
0151 }
0152 
0153 rtems_status_code pwm_init( const lpc176x_pin_number pin_number )
0154 {
0155   rtems_status_code    sc = RTEMS_INVALID_NUMBER;
0156   lpc176x_pin_function pin_function;
0157   lpc176x_pwm_number   pwm;
0158 
0159   if ( is_valid_pin_number( pin_number, &pwm, &pin_function ) ) {
0160     sc = lpc176x_module_enable( LPC176X_MODULE_PWM_1,
0161       LPC176X_MODULE_PCLK_DEFAULT );
0162     RTEMS_CHECK_SC( sc, "enable pwm module" );
0163 
0164     pwm_device->PR = 0;
0165     pwm_device->MCR = PWM_MCR_RESET_ON_MATCH0;
0166     pwm_device->PCR |= PWM_PCR_ENABLE_PWM( pwm );
0167 
0168     set_period( pwm, PWM_DEFAULT_PERIOD );
0169     set_pulsewidth( pwm, PWM_DEFAULT_PULSEWIDTH );
0170 
0171     lpc176x_pin_select( pin_number, pin_function );
0172   } /* else implies that the pin number is not valid.
0173      So, a RTEMS_INVALID_NUMBER will be returned.*/
0174 
0175   return sc;
0176 }
0177 
0178 rtems_status_code pwm_period(
0179   const lpc176x_pin_number    pin_number,
0180   const lpc176x_microseconds period
0181 )
0182 {
0183   rtems_status_code    sc = RTEMS_INVALID_NUMBER;
0184   lpc176x_pin_function pin_function;
0185   lpc176x_pwm_number   pwm;
0186 
0187   if ( is_valid_pin_number( pin_number, &pwm, &pin_function ) ) {
0188     sc = RTEMS_SUCCESSFUL;
0189     set_period( pwm, period );
0190   } /* else implies that the pin number is not valid.
0191      So, a RTEMS_INVALID_NUMBER will be returned.*/
0192 
0193   return sc;
0194 }
0195 
0196 rtems_status_code pwm_pulsewidth(
0197   const lpc176x_pin_number    pin_number,
0198   const lpc176x_microseconds pwidth
0199 )
0200 {
0201   rtems_status_code    sc = RTEMS_INVALID_NUMBER;
0202   lpc176x_pin_function pin_function;
0203   lpc176x_pwm_number   pwm;
0204 
0205   if ( is_valid_pin_number( pin_number, &pwm, &pin_function ) ) {
0206     sc = RTEMS_SUCCESSFUL;
0207     set_pulsewidth( pwm, pwidth );
0208   } /* Else wrong pin_number return RTEMS_INVALID_NUMBER*/
0209 
0210   return sc;
0211 }