On 21/8/20 8:01 pm, James Fitzsimons wrote: > --- > bsps/arm/beagle/headers.am | 2 + > bsps/arm/beagle/include/bsp/bbb-pwm.h | 11 - > bsps/arm/beagle/include/bsp/pwmss.h | 54 +++ > bsps/arm/beagle/include/bsp/qep.h | 331 ++++++++++++++++++ > bsps/arm/beagle/pwm/pwm.c | 64 +--- > bsps/arm/beagle/pwmss/pwmss.c | 64 ++++ > bsps/arm/beagle/qep/qep.c | 435 ++++++++++++++++++++++++ > c/src/lib/libbsp/arm/beagle/Makefile.am | 6 + > 8 files changed, 896 insertions(+), 71 deletions(-) > create mode 100644 bsps/arm/beagle/include/bsp/pwmss.h > create mode 100644 bsps/arm/beagle/include/bsp/qep.h > create mode 100644 bsps/arm/beagle/pwmss/pwmss.c > create mode 100644 bsps/arm/beagle/qep/qep.c > > diff --git a/bsps/arm/beagle/headers.am b/bsps/arm/beagle/headers.am > index 4dc35f2e2a..e4a746b2e1 100644 > --- a/bsps/arm/beagle/headers.am > +++ b/bsps/arm/beagle/headers.am > @@ -13,3 +13,5 @@ include_bsp_HEADERS += > ../../../../../../bsps/arm/beagle/include/bsp/beagleboneb > include_bsp_HEADERS += ../../../../../../bsps/arm/beagle/include/bsp/i2c.h > include_bsp_HEADERS += ../../../../../../bsps/arm/beagle/include/bsp/irq.h > include_bsp_HEADERS += ../../../../../../bsps/arm/beagle/include/bsp/spi.h > +include_bsp_HEADERS += ../../../../../../bsps/arm/beagle/include/bsp/qep.h > +include_bsp_HEADERS += ../../../../../../bsps/arm/beagle/include/bsp/pwmss.h > diff --git a/bsps/arm/beagle/include/bsp/bbb-pwm.h > b/bsps/arm/beagle/include/bsp/bbb-pwm.h > index cf5d6fe552..6fdba486be 100644 > --- a/bsps/arm/beagle/include/bsp/bbb-pwm.h > +++ b/bsps/arm/beagle/include/bsp/bbb-pwm.h > @@ -31,17 +31,6 @@ extern "C" { > #define BBB_CONTROL_CONF_GPMC_AD(n) (0x800 + (n * 4)) > #define BBB_CONTROL_CONF_LCD_DATA(n) (0x8a0 + (n * 4)) > > -/** > - * @brief The set of possible PWM subsystem module > - * > - * Enumerated type to define various instance of pwm module. > - */ > -typedef enum{ > - BBB_PWMSS0 = 0, > - BBB_PWMSS1, > - BBB_PWMSS2, > - BBB_PWMSS_COUNT > -}BBB_PWMSS; > > typedef enum{ > BBB_P8_13_2B = 3, > diff --git a/bsps/arm/beagle/include/bsp/pwmss.h > b/bsps/arm/beagle/include/bsp/pwmss.h > new file mode 100644 > index 0000000000..3a9dcbb70a > --- /dev/null > +++ b/bsps/arm/beagle/include/bsp/pwmss.h > @@ -0,0 +1,54 @@ > +/** > + * @file > + * > + * @ingroup arm_beagle > + * > + * @brief Shared PWMSS module functions used by PWM, eQEP and eCAP (when > added). > + */ > + > +/** > + * Copyright (c) 2020 James Fitzsimons <james.fitzsim...@gmail.com> > + * > + * The license and distribution terms for this file may be > + * found in the file LICENSE in this distribution or at > + * http://www.rtems.org/license/LICENSE. > + *. > + */ > + > +#ifndef LIBBSP_ARM_BEAGLE_PWMSS_H > +#define LIBBSP_ARM_BEAGLE_PWMSS_H > + > +#ifdef __cplusplus > +extern "C" { > +#endif /* __cplusplus */ > + > +/* The following definitions are bitmasks for the clk control registers for > + * the PWMSS module clocks. All three modules have the same clock control > + * hence the EPMSSx to signify these values are consistent across all > + * EPWMSS instances. */ > +#define AM335X_CM_PER_EPWMSSx_CLKCTRL_MODULEMODE_ENABLE (0x2u) > +#define AM335X_CM_PER_EPWMSSx_CLKCTRL_MODULEMODE (0x00000003u) > +#define AM335X_CM_PER_EPWMSSx_CLKCTRL_IDLEST_FUNC (0x0u) > +#define AM335X_CM_PER_EPWMSSx_CLKCTRL_IDLEST_SHIFT (0x00000010u) > +#define AM335X_CM_PER_EPWMSSx_CLKCTRL_IDLEST (0x00030000u) > + > +/** > + * @brief The set of possible PWM subsystem module > + * > + * Enumerated type to define various instance of pwm module. > + */ > +typedef enum { > + BBB_PWMSS0 = 0, > + BBB_PWMSS1, > + BBB_PWMSS2, > + BBB_PWMSS_COUNT > +} BBB_PWMSS; > + > + > +rtems_status_code pwmss_module_clk_config(BBB_PWMSS pwmss_id); > + > +#ifdef __cplusplus > +} > +#endif /* __cplusplus */ > + > +#endif /* LIBBSP_ARM_BEAGLE_PWMSS_H */ > diff --git a/bsps/arm/beagle/include/bsp/qep.h > b/bsps/arm/beagle/include/bsp/qep.h > new file mode 100644 > index 0000000000..671d9cca6c > --- /dev/null > +++ b/bsps/arm/beagle/include/bsp/qep.h > @@ -0,0 +1,331 @@ > +/** > + * @file > + * > + * @ingroup arm_beagle > + * > + * @brief eQEP (enhanced Quadrature Encoder Pulse) support API. > + */ > + > +/** > + * Copyright (c) 2020 James Fitzsimons <james.fitzsim...@gmail.com> > + * > + * The license and distribution terms for this file may be > + * found in the file LICENSE in this distribution or at > + * http://www.rtems.org/license/LICENSE. > + * > + * For details of the Enhanced Quadrature Encoder Pulse (eQEP) Module refer > to > + * page 2511 of the TI Technical Reference Manual > + * (https://www.ti.com/lit/ug/spruh73q/spruh73q.pdf) > + * > + * This driver supports using the QEP modules in Quadrature-clock Mode. > + * Direction-count Mode is not currently supported. Similarly the QEPI: Index > + * or Zero Marker and QEPS: Strobe Input pins are not currently supported. > + * > + * The mode can be any one of: > + * - Quadrature-count mode - For encoders that generate pulses 90 degrees > + * out of phase for determining direction and speed. > + * - Direction-count mode - for position encoders that provide direction and > + * clock outputs, instead of quadrature outputs. > + * - UP-count mode - The counter direction signal is hard-wired for up count > + * and the position counter is used to measure the frequency of the QEPA > + * input. > + * - DOWN-count mode - The counter direction signal is hard-wired for a down > + * count and the position counter is used to measure the frequency of > the > + * QEPA input. > + * > + * When the eQEP module is configured in quadrature mode, the module > + * can either provide an absolute position, or a relative position. Absolute > + * simply increments or decrements depending on the direction. Relative > + * increments until the unit timer overflows at which point it latches the > + * position value, resets the position count to zero and starts again. > + */ > + > +#ifndef LIBBSP_ARM_BEAGLE_QEP_H > +#define LIBBSP_ARM_BEAGLE_QEP_H > + > +#ifdef __cplusplus > +extern "C" { > +#endif /* __cplusplus */ > + > +#define AM335X_EQEP_REGS (0x00000180) > +#define AM335X_EQEP_0_REGS (AM335X_PWMSS0_MMAP_ADDR + > AM335X_EQEP_REGS) > +#define AM335X_EQEP_1_REGS (AM335X_PWMSS1_MMAP_ADDR + > AM335X_EQEP_REGS) > +#define AM335X_EQEP_2_REGS (AM335X_PWMSS2_MMAP_ADDR + > AM335X_EQEP_REGS) > + > +/* eQEP registers of the PWMSS modules - see page 1672 of the TRM for > details */ > +#define AM335x_EQEP_QPOSCNT 0x0 /* eQEP Position Counter */ > +#define AM335x_EQEP_QPOSINIT 0x4 /* eQEP Position Counter > Initialization */ > +#define AM335x_EQEP_QPOSMAX 0x8 /* eQEP Maximum Position Count */ > +#define AM335x_EQEP_QPOSCMP 0xC /* eQEP Position-Compare */ > +#define AM335x_EQEP_QPOSILAT 0x10 /* eQEP Index Position Latch */ > +#define AM335x_EQEP_QPOSSLAT 0x14 /* eQEP Strobe Position Latch */ > +#define AM335x_EQEP_QPOSLAT 0x18 /* eQEP Position Counter Latch */ > +#define AM335x_EQEP_QUTMR 0x1C /* eQEP Unit Timer */ > +#define AM335x_EQEP_QUPRD 0x20 /* eQEP Unit Period */ > +#define AM335x_EQEP_QWDTMR 0x24 /* eQEP Watchdog Timer */ > +#define AM335x_EQEP_QWDPRD 0x26 /* eQEP Watchdog Period */ > +#define AM335x_EQEP_QDECCTL 0x28 /* eQEP Decoder Control */ > +#define AM335x_EQEP_QEPCTL 0x2A /* eQEP Control */ > +#define AM335x_EQEP_QCAPCTL 0x2C /* eQEP Capture Control */ > +#define AM335x_EQEP_QPOSCTL 0x2E /* eQEP Position-Compare Control */ > +#define AM335x_EQEP_QEINT 0x30 /* eQEP Interrupt Enable */ > +#define AM335x_EQEP_QFLG 0x32 /* eQEP Interrupt Flag */ > +#define AM335x_EQEP_QCLR 0x34 /* eQEP Interrupt Clear */ > +#define AM335x_EQEP_QFRC 0x36 /* eQEP Interrupt Force */ > +#define AM335x_EQEP_QEPSTS 0x38 /* eQEP Status */ > +#define AM335x_EQEP_QCTMR 0x3A /* eQEP Capture Timer */ > +#define AM335x_EQEP_QCPRD 0x3C /* eQEP Capture Period */ > +#define AM335x_EQEP_QCTMRLAT 0x3E /* eQEP Capture Timer Latch */ > +#define AM335x_EQEP_QCPRDLAT 0x40 /* eQEP Capture Period Latch */ > +#define AM335x_EQEP_REVID 0x5C /* eQEP Revision ID */ > + > +/* bitmasks for eQEP registers */ > +#define AM335x_EQEP_QEPCTL_UTE (1 << 1) > +#define AM335x_EQEP_QEPCTL_QCLM (1 << 2) > +#define AM335x_EQEP_QEPCTL_PHEN (1 << 3) > +#define AM335x_EQEP_QEPCTL_IEL (1 << 4) > +#define AM335x_EQEP_QEPCTL_SWI (1 << 7) > +#define AM335x_EQEP_QEPCTL_PCRM (3 << 12) > +#define AM335x_EQEP_QDECCTL_QSRC (3 << 14) > +#define AM335x_EQEP_QDECCTL_XCR (1 << 11) > +#define AM335x_EQEP_QDECCTL_SWAP (1 << 10) > +#define AM335x_EQEP_QDECCTL_IGATE (1 << 9) > +#define AM335x_EQEP_QDECCTL_QAP (1 << 8) > +#define AM335x_EQEP_QDECCTL_QBP (1 << 7) > +#define AM335x_EQEP_QDECCTL_QIP (1 << 6) > +#define AM335x_EQEP_QDECCTL_QSP (1 << 5) > +#define AM335x_EQEP_CLK_EN (1 << 4) > +#define AM335x_EQEP_QEINT_UTO (1 << 11) > +#define AM335x_EQEP_QFLG_UTO (1 << 11) > +#define AM335x_EQEP_QFLG_MASK 0x0FFF > + > +/* The pin mux modes for the QEP input pins on the P8 and P9 headers */ > +#define BBB_P8_11_MUX_QEP 4 > +#define BBB_P8_12_MUX_QEP 4 > +#define BBB_P8_15_MUX_QEP 4 > +#define BBB_P8_16_MUX_QEP 4 > +#define BBB_P8_31_MUX_QEP 2 > +#define BBB_P8_32_MUX_QEP 2 > +#define BBB_P8_33_MUX_QEP 2 > +#define BBB_P8_35_MUX_QEP 2 > +#define BBB_P8_39_MUX_QEP 3 > +#define BBB_P8_40_MUX_QEP 3 > +#define BBB_P8_41_MUX_QEP 3 > +#define BBB_P8_42_MUX_QEP 3 > +#define BBB_P9_25_MUX_QEP 1 > +#define BBB_P9_27_MUX_QEP 1 > +#define BBB_P9_41_MUX_QEP 1 > +#define BBB_P9_42_MUX_QEP 1 > + > +#define NANO_SEC_PER_SEC 1000000000 > +/* This is the max clock rate for the EPWMSS module. See 15.1.2.2 of the TRM. > + * If the CPU was using dynamic scaling this could potentially be wrong */ > +#define SYSCLKOUT 100000000 > + > +/** > + * @brief The set of possible eQEP Position Counter Input Modes > + * > + * Enumerated type to define various modes for the eQEP module. The values > + * correspond to the values for the QSRC bits of the QDECCTL register. > + */ > +typedef enum { > + QUADRATURE_COUNT = 0, > + DIRECTION_COUNT, > + UP_COUNT, > + DOWN_COUNT > +} BBB_QEP_COUNT_MODE; > + > +/** > + * @brief The set of possible modes for Quadrature decode > + * > + */ > +typedef enum { > + ABSOLUTE = 0, > + RELATIVE > +} BBB_QEP_QUADRATURE_MODE; > + > +/** > + * @brief The set of possible eQEP input pins > + * > + */ > +typedef enum { > + BBB_P8_11_2B_IN, > + BBB_P8_12_2A_IN, > + BBB_P8_15_2_STROBE, > + BBB_P8_16_2_IDX, > + BBB_P8_31_1_IDX, > + BBB_P8_32_1_STROBE, > + BBB_P8_33_1B_IN, > + BBB_P8_35_1A_IN, > + BBB_P8_39_2_IDX, > + BBB_P8_40_2_STROBE, > + BBB_P8_41_2A_IN, > + BBB_P8_42_2B_IN, > + BBB_P9_25_0_STROBE, > + BBB_P9_27_0B_IN, > + BBB_P9_41_0_IDX, > + BBB_P9_42_0A_IN > +} bbb_qep_pin; > + > + > +typedef void (*bbb_eqep_timer_callback)(BBB_PWMSS);
What is BBB_PWMSS used for as an argument? Could a `void* user` be passed back? It helps if the interrupt provides a user specific data pointer. > + > + > +/** > + * @brief This structure represents an eQEP module instance. > + * > + * The members are closely modelled on the FDT structure. * > + */ > +typedef struct { > + const BBB_PWMSS pwmss_id; > + const uint32_t mmio_base; > + const rtems_vector_number irq; > + bbb_eqep_timer_callback timer_callback; Is this part of the FDT? I think some extra documentation here would be good to have. Can we have a `void* user;`? Thanks Chris > + BBB_QEP_COUNT_MODE count_mode; > + BBB_QEP_QUADRATURE_MODE quadrature_mode; > + uint32_t invert_qa; > + uint32_t invert_qb; > + uint32_t invert_qi; > + uint32_t invert_qs; > + uint32_t swap_inputs; > +} bbb_eqep; > + > + > +/** > + * @brief Initialises the eQEP module of the specified PWMSS unit. This > + * configures the clocks, sets up the interrupt handler and unit timer, > + * The module is configured in Quadrature decode mode using > + * absolute position by default. > + * > + * @param pwmss_id The PWMSS module to configure the eQEP for. > + * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is > + * supplied. > + */ > +rtems_status_code beagle_qep_init(BBB_PWMSS pwmss_id); > + > +/** > + * @brief Enables the eQEP module of the specified PWMSS unit. > + * > + * @param pwmss_id The PWMSS module which will have the eQEP function > enabled. > + * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is > + * supplied. > + */ > +rtems_status_code beagle_qep_enable(BBB_PWMSS pwmss_id); > + > +/** > + * @brief Disables the eQEP module of the specified PWMSS unit. > + * > + * @param pwmss_id The PWMSS module which will have the eQEP function > disabled. > + * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is > + * supplied. > + */ > +rtems_status_code beagle_qep_disable(BBB_PWMSS pwmss_id); > + > +/** > + * @brief Configures a given pin for use with the eQEP function of the > supplied > + * PWMSS module. > + * > + * @param pin_no The P9 or P8 header pin to be configured for the eQEP > function. > + * @param pwmss_id The PWMSS module which will have the eQEP function > enabled. > + * @param pullup_enable If true then the internal pull up resistor on the > + * specified pin will be enabled, if false the pull down will be enabled. > + * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is > + * supplied. > + */ > +rtems_status_code beagle_qep_pinmux_setup( > + bbb_qep_pin pin_no, > + BBB_PWMSS pwmss_id, > + bool pullup_enable > +); > + > +/** > + * @brief Returns the current position value of the eQEP function for the > + * specified PWMSS module. > + * > + * @param pwmss_id Identifies which PWMSS module to return the eQEP position > for > + * @return int32_t The current position value. > + */ > +int32_t beagle_qep_get_position(BBB_PWMSS pwmss_id); > + > +/** > + * @brief Sets the initial position value of the eQEP function for the > + * specified PWMSS module. > + * > + * @param pwmss_id Identifies which PWMSS module to set the eQEP position for > + * @param position The value to initialise the position register with. > + * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is > + * supplied. > + */ > +rtems_status_code beagle_qep_set_position( > + BBB_PWMSS pwmss_id, > + uint32_t position > +); > + > +/** > + * @brief Sets the count mode for the eQEP module. > + * @param pwmss_id Identifies which PWMSS module to set the eQEP count mode > for. > + * @param mode One of the above modes to configure the eQEP module for. > + * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is > + * supplied. > + */ > +rtems_status_code beagle_qep_set_count_mode( > + BBB_PWMSS pwmss_id, > + BBB_QEP_COUNT_MODE mode > +); > + > +/** > + * @brief Gets the currently configured count mode for the eQEP module. > + * @param pwmss_id Identifies which PWMSS module to set the eQEP count mode > for. > + * @return An enum value representing the current count mode. > + */ > +BBB_QEP_COUNT_MODE beagle_qep_get_count_mode(BBB_PWMSS pwmss_id); > + > +/** > + * @brief Returns the currently configured quadrature mode - either absolute, > + * or relative. > + * @param pwmss_id Identifies which PWMSS module to get the eQEP quadrature > + * mode for. > + * @return BBB_QEP_QUADRATURE_MODE The currently configured quadrature mode. > + */ > +BBB_QEP_QUADRATURE_MODE beagle_qep_get_quadrature_mode(BBB_PWMSS pwmss_id); > + > +/** > + * @brief Sets the quadrature mode to either absolute or relative. > + * @param pwmss_id Identifies which PWMSS module to set the eQEP quadrature > + * mode for. > + * @param mode BBB_QEP_QUADRATURE_MODE Set the mode of the eQEP to either > + * absolute or relative. > + * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is > + * supplied. > + */ > +rtems_status_code beagle_qep_set_quadrature_mode( > + BBB_PWMSS pwmss_id, > + BBB_QEP_QUADRATURE_MODE mode > +); > + > +/** > + * @brief Returns the the currently configured unit timer period. > + * @param pwmss_id Identifies which PWMSS module to get the eQEP timer value > for > + * @return uint32_t The current unit timer value in nanoseconds > + */ > +uint32_t beagle_eqep_get_timer_period(BBB_PWMSS pwmss_id); > + > +/** > + * @brief Sets the unit timer period for the eQEP module. > + * 0 = off, greater than zero sets the period. > + * @param pwmss_id Identifies which PWMSS module to set the eQEP unit timer > for. > + * @param period The value in nanoseconds to set the unit timer period to. > + * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is > + * supplied. > + */ > +rtems_status_code beagle_eqep_set_timer_period( > + BBB_PWMSS pwmss_id, > + uint64_t period, > + bbb_eqep_timer_callback timer_callback > +); > + > +#ifdef __cplusplus > +} > +#endif /* __cplusplus */ > + > +#endif /* LIBBSP_ARM_BEAGLE_QEP_H */ > diff --git a/bsps/arm/beagle/pwm/pwm.c b/bsps/arm/beagle/pwm/pwm.c > index 0bc5d125bf..4bd09293e8 100644 > --- a/bsps/arm/beagle/pwm/pwm.c > +++ b/bsps/arm/beagle/pwm/pwm.c > @@ -23,6 +23,7 @@ > #include <bsp/gpio.h> > #include <bsp/bbb-gpio.h> > #include <bsp.h> > +#include <bsp/pwmss.h> > #include <bsp/bbb-pwm.h> > #include <bsp/beagleboneblack.h> > > @@ -38,7 +39,7 @@ > * @param pwm_id It is the instance number of EPWM of pwm sub system. > * > * @return Base Address of respective pwm instant. > -*/ > + */ > static uint32_t select_pwm(BBB_PWMSS pwm_id) > { > uint32_t baseAddr=0; > @@ -102,9 +103,9 @@ bool beagle_pwm_pinmux_setup(bbb_pwm_pin_t pin_no, > BBB_PWMSS pwm_id) > } else if (pin_no == BBB_P8_36_1A) { > REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(10)) = > BBB_MUXMODE(BBB_P8_36_MUX_PWM); > } else if (pin_no == BBB_P9_14_1A) { > - REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(2)) = > BBB_MUXMODE(BBB_P9_14_MUX_PWM); > + REG(AM335X_PADCONF_BASE + AM335X_CONF_GPMC_A2) = > BBB_MUXMODE(BBB_P9_14_MUX_PWM); > } else if (pin_no == BBB_P9_16_1B) { > - REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(3)) = > BBB_MUXMODE(BBB_P9_16_MUX_PWM); > + REG(AM335X_PADCONF_BASE + AM335X_CONF_GPMC_A3) = > BBB_MUXMODE(BBB_P9_16_MUX_PWM); > } else { > is_valid = false; > } > @@ -181,63 +182,6 @@ static bool pwm_clock_enable(BBB_PWMSS pwm_id) > return status; > } > > -/** > - * @brief This function configures the L3 and L4_PER system clocks. > - * It also configures the system clocks for the specified ePWMSS > - * instance. > - * > - * @param pwmss_id The instance number of ePWMSS whose system clocks > - * have to be configured. > - * > - * 'pwmss_id' can take one of the following values: > - * (0 <= pwmss_id <= 2) > - * > - * @return True if successful > - * False if Unsuccessful > - */ > -static bool pwmss_module_clk_config(BBB_PWMSS pwmss_id) > -{ > - bool is_valid = true; > - > - if(pwmss_id == BBB_PWMSS0) { > - const uint32_t is_functional = AM335X_CM_PER_EPWMSS0_CLKCTRL_IDLEST_FUNC > << > - AM335X_CM_PER_EPWMSS0_CLKCTRL_IDLEST_SHIFT; > - const uint32_t clkctrl = AM335X_CM_PER_ADDR + > AM335X_CM_PER_EPWMSS0_CLKCTRL; > - const uint32_t idle_bits = AM335X_CM_PER_EPWMSS0_CLKCTRL_IDLEST; > - const uint32_t is_enable = > AM335X_CM_PER_EPWMSS0_CLKCTRL_MODULEMODE_ENABLE; > - const uint32_t module_mode = AM335X_CM_PER_EPWMSS0_CLKCTRL_MODULEMODE; > - > - REG(clkctrl) |= is_enable; > - while((REG(clkctrl) & module_mode) != is_enable); > - while((REG(clkctrl) & idle_bits) != is_functional); > - } > - else if(pwmss_id == BBB_PWMSS1) { > - const uint32_t is_functional = AM335X_CM_PER_EPWMSS1_CLKCTRL_IDLEST_FUNC > << > - AM335X_CM_PER_EPWMSS1_CLKCTRL_IDLEST_SHIFT; > - const uint32_t clkctrl = AM335X_CM_PER_ADDR + > AM335X_CM_PER_EPWMSS1_CLKCTRL; > - const uint32_t idle_bits = AM335X_CM_PER_EPWMSS1_CLKCTRL_IDLEST; > - const uint32_t is_enable = > AM335X_CM_PER_EPWMSS1_CLKCTRL_MODULEMODE_ENABLE; > - const uint32_t module_mode = AM335X_CM_PER_EPWMSS1_CLKCTRL_MODULEMODE; > - > - REG(clkctrl) |= is_enable; > - while((REG(clkctrl) & module_mode) != is_enable); > - while((REG(clkctrl) & idle_bits) != is_functional); > - } else if(pwmss_id == BBB_PWMSS2) { > - const uint32_t is_functional = AM335X_CM_PER_EPWMSS2_CLKCTRL_IDLEST_FUNC > << > - AM335X_CM_PER_EPWMSS2_CLKCTRL_IDLEST_SHIFT; > - const uint32_t clkctrl = AM335X_CM_PER_ADDR + > AM335X_CM_PER_EPWMSS2_CLKCTRL; > - const uint32_t idle_bits = AM335X_CM_PER_EPWMSS2_CLKCTRL_IDLEST; > - const uint32_t is_enable = > AM335X_CM_PER_EPWMSS2_CLKCTRL_MODULEMODE_ENABLE; > - const uint32_t module_mode = AM335X_CM_PER_EPWMSS2_CLKCTRL_MODULEMODE; > - > - REG(clkctrl) |= is_enable; > - while((REG(clkctrl) & module_mode) != is_enable); > - while((REG(clkctrl) & idle_bits) != is_functional); > - } else > - is_valid = false; > - return is_valid; > -} > - > bool beagle_pwm_init(BBB_PWMSS pwmss_id) > { > const bool id_is_valid = pwmss_id < BBB_PWMSS_COUNT; > diff --git a/bsps/arm/beagle/pwmss/pwmss.c b/bsps/arm/beagle/pwmss/pwmss.c > new file mode 100644 > index 0000000000..c4d36d8ae1 > --- /dev/null > +++ b/bsps/arm/beagle/pwmss/pwmss.c > @@ -0,0 +1,64 @@ > +/** > + * @file > + * > + * @ingroup arm_beagle > + * > + * @brief Support for eQEP for the BeagleBone Black. > + */ > + > +/** > + * Copyright (c) 2020 James Fitzsimons <james.fitzsim...@gmail.com> > + * > + * The license and distribution terms for this file may be > + * found in the file LICENSE in this distribution or at > + * http://www.rtems.org/license/LICENSE. > + */ > + > +#include <libcpu/am335x.h> > +#include <stdio.h> > +#include <bsp.h> > +#include <bsp/pwmss.h> > +#include <bsp/beagleboneblack.h> > + > + > +/** > + * @brief This function configures the L3 and L4_PER system clocks. > + * It also configures the system clocks for the specified ePWMSS > + * instance. > + * > + * @param pwmss_id The instance number of ePWMSS whose system clocks > + * have to be configured. > + * > + * 'pwmss_id' can take one of the following values: > + * (0 <= pwmss_id <= 2) > + * > + * @return True if successful > + * False if Unsuccessful > + */ > +rtems_status_code pwmss_module_clk_config(BBB_PWMSS pwmss_id) > +{ > + uint32_t clkctrl; > + > + /* calculate the address of the clock control register for the PWMSS > + * module we are configuring */ > + if(pwmss_id == BBB_PWMSS0) { > + clkctrl = AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS0_CLKCTRL; > + } else if(pwmss_id == BBB_PWMSS1) { > + clkctrl = AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS1_CLKCTRL; > + } else if(pwmss_id == BBB_PWMSS2) { > + clkctrl = AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS2_CLKCTRL; > + } > + > + /* when the module is functional the IDLEST bits (16 -17) of the > + * CM_PER_EPWMSSx_CLKCTRL register will be 0x0. */ > + const uint32_t is_functional = 0x0; > + const uint32_t idle_bits = AM335X_CM_PER_EPWMSSx_CLKCTRL_IDLEST; > + const uint32_t is_enable = > AM335X_CM_PER_EPWMSSx_CLKCTRL_MODULEMODE_ENABLE; > + const uint32_t module_mode = AM335X_CM_PER_EPWMSSx_CLKCTRL_MODULEMODE; > + > + REG(clkctrl) |= is_enable; > + while((REG(clkctrl) & module_mode) != is_enable); > + while((REG(clkctrl) & idle_bits) != is_functional); > + > + return RTEMS_SUCCESSFUL; > +} > diff --git a/bsps/arm/beagle/qep/qep.c b/bsps/arm/beagle/qep/qep.c > new file mode 100644 > index 0000000000..d0fc9fc6ba > --- /dev/null > +++ b/bsps/arm/beagle/qep/qep.c > @@ -0,0 +1,435 @@ > +/** > + * @file > + * > + * @ingroup arm_beagle > + * > + * @brief Support for eQEP for the BeagleBone Black. > + */ > + > +/** > + * Copyright (c) 2020 James Fitzsimons <james.fitzsim...@gmail.com> > + * > + * The license and distribution terms for this file may be > + * found in the file LICENSE in this distribution or at > + * http://www.rtems.org/license/LICENSE. > + */ > + > +#include <libcpu/am335x.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <bsp/gpio.h> > +#include <bsp/bbb-gpio.h> > +#include <bsp.h> > +#include <bsp/pwmss.h> > +#include <bsp/qep.h> > +#include <bsp/beagleboneblack.h> > + > + > +/** > + * @brief Represents all the PWMSS QEP modules and their default values. > + */ > +static bbb_eqep bbb_eqep_table[ BBB_PWMSS_COUNT ] = > +{ > + { > + .pwmss_id = BBB_PWMSS0, > + .mmio_base = AM335X_EQEP_0_REGS, > + .irq = AM335X_INT_eQEP0INT, > + .timer_callback = NULL, > + .count_mode = QUADRATURE_COUNT, > + .quadrature_mode = ABSOLUTE, > + .invert_qa = 0, > + .invert_qb = 0, > + .invert_qi = 0, > + .invert_qs = 0, > + .swap_inputs = 0 > + }, > + { > + .pwmss_id = BBB_PWMSS1, > + .mmio_base = AM335X_EQEP_1_REGS, > + .irq = AM335X_INT_eQEP1INT, > + .timer_callback = NULL, > + .count_mode = QUADRATURE_COUNT, > + .quadrature_mode = ABSOLUTE, > + .invert_qa = 0, > + .invert_qb = 0, > + .invert_qi = 0, > + .invert_qs = 0, > + .swap_inputs = 0 > + }, > + { > + .pwmss_id = BBB_PWMSS2, > + .mmio_base = AM335X_EQEP_2_REGS, > + .irq = AM335X_INT_eQEP2INT, > + .timer_callback = NULL, > + .count_mode = QUADRATURE_COUNT, > + .quadrature_mode = ABSOLUTE, > + .invert_qa = 0, > + .invert_qb = 0, > + .invert_qi = 0, > + .invert_qs = 0, > + .swap_inputs = 0 > + } > +}; > + > +/* eQEP Interrupt handler */ > +static void beagle_eqep_irq_handler(void *arg) > +{ > + uint16_t flags; > + bbb_eqep* eqep = arg; > + > + /* Use the interrupt register (QFLG) mask to determine what caused the > + * interrupt. */ > + flags = REG16(eqep->mmio_base + AM335x_EQEP_QFLG) & AM335x_EQEP_QFLG_MASK; > + /* Check the interrupt source to see if it was a unit timer overflow */ > + if (flags & AM335x_EQEP_QFLG_UTO && eqep->timer_callback != NULL) { > + /* Handle the unit timer overflow interrupt */ > + eqep->timer_callback(eqep->pwmss_id); > + } > + > + /* Clear interrupt flags (write back triggered flags to the clear > register) */ > + REG16(eqep->mmio_base + AM335x_EQEP_QCLR) = flags; > +} > + > +rtems_status_code beagle_qep_init(BBB_PWMSS pwmss_id) > +{ > + rtems_status_code sc; > + uint16_t qdecctl; > + > + if ( pwmss_id >= BBB_PWMSS_COUNT ) { > + return RTEMS_INVALID_ID; > + } > + bbb_eqep* eqep = &bbb_eqep_table[pwmss_id]; > + > + sc = pwmss_module_clk_config(eqep->pwmss_id); > + if (sc != RTEMS_SUCCESSFUL) { > + /* failed to successfully configure the PWMSS module clocks */ > + return sc; > + } > + > + /* This enables clock for EQEP module in PWMSS subsystem. */ > + REG(eqep->mmio_base + AM335X_PWMSS_CLKCONFIG) |= AM335x_EQEP_CLK_EN; > + > + /* Setup interrupt handler */ > + sc = rtems_interrupt_handler_install( > + eqep->irq, > + NULL, > + RTEMS_INTERRUPT_UNIQUE, > + (rtems_interrupt_handler)beagle_eqep_irq_handler, > + (void*)eqep > + ); > + > + /* The QDECCTL register configures the QEP Decoder module. We use it to > set */ > + /* the count mode, input inversion, channel swaps, unit timer interrupt > etc. */ > + qdecctl = 0; > + if (eqep->count_mode <= 3) { > + qdecctl |= eqep->count_mode << 14; > + > + /* If the count mode is UP_COUNT or DOWN_COUNT then only count on > + * the rising edge. QUADRATURE_COUNT and DIRECTION_COUNT count on > + * both edges. */ > + if (eqep->count_mode >= 2) { > + qdecctl |= AM335x_EQEP_QDECCTL_XCR; > + } > + } > + > + /* Should we swap the cha and chb inputs */ > + if (eqep->swap_inputs == 1) { > + qdecctl |= AM335x_EQEP_QDECCTL_SWAP; > + } > + /* Should we invert the qa input */ > + if (eqep->invert_qa == 1) { > + qdecctl |= AM335x_EQEP_QDECCTL_QAP; > + } > + /* Should we invert the qb input */ > + if (eqep->invert_qb == 1) { > + qdecctl |= AM335x_EQEP_QDECCTL_QBP; > + } > + /* Should we invert the index input */ > + if (eqep->invert_qi == 1) { > + qdecctl |= AM335x_EQEP_QDECCTL_QIP; > + > + } > + /* Should we invert the strobe input */ > + if (eqep->invert_qs == 1) { > + qdecctl |= AM335x_EQEP_QDECCTL_QSP; > + } > + > + /* Write the configured decoder control settings to the QDECCTL register */ > + REG16(eqep->mmio_base + AM335x_EQEP_QDECCTL) = qdecctl; > + /* Set the position counter initialisation register */ > + REG(eqep->mmio_base + AM335x_EQEP_QPOSINIT) = 0; > + /* initialise the maximum position counter value */ > + REG(eqep->mmio_base + AM335x_EQEP_QPOSMAX) = ~0; > + /* initialise the position counter register */ > + REG(eqep->mmio_base + AM335x_EQEP_QPOSCNT) = 0; > + /* Enable Unit Time Period interrupt. */ > + REG16(eqep->mmio_base + AM335x_EQEP_QEINT) |= AM335x_EQEP_QEINT_UTO; > + > + /* The following bitmasks enable the eQEP module with: > + * - the unit timer disabled > + * - will latch the value in QPOSLAT to QPOSCNT upon unit timer overflow > + * - will latch QPOSILAT on index signal. > + * - Software initialisation of position counter (will be set to 0 because > + * QPOSINIT = 0). > + */ > + uint32_t value = AM335x_EQEP_QEPCTL_QCLM | AM335x_EQEP_QEPCTL_IEL | > + AM335x_EQEP_QEPCTL_PHEN | AM335x_EQEP_QEPCTL_SWI; > + > + /* set the enable bit of the control register */ > + REG16(eqep->mmio_base + AM335x_EQEP_QEPCTL) = value; > + > + return RTEMS_SUCCESSFUL; > +} > + > +rtems_status_code beagle_qep_enable(BBB_PWMSS pwmss_id) > +{ > + if ( pwmss_id >= BBB_PWMSS_COUNT ) { > + return RTEMS_INVALID_ID; > + } > + const bbb_eqep* eqep = &bbb_eqep_table[pwmss_id]; > + /* set the enable bit of the control register */ > + REG16(eqep->mmio_base + AM335x_EQEP_QEPCTL) |= AM335x_EQEP_QEPCTL_PHEN; > + > + return RTEMS_SUCCESSFUL; > +} > + > +rtems_status_code beagle_qep_disable(BBB_PWMSS pwmss_id) > +{ > + if ( pwmss_id >= BBB_PWMSS_COUNT ) { > + return RTEMS_INVALID_ID; > + } > + const bbb_eqep* eqep = &bbb_eqep_table[pwmss_id]; > + /* clear the enable bit of the control register */ > + REG16(eqep->mmio_base + AM335x_EQEP_QEPCTL) &= ~AM335x_EQEP_QEPCTL_PHEN; > + > + return RTEMS_SUCCESSFUL; > +} > + > +rtems_status_code beagle_qep_pinmux_setup( > + bbb_qep_pin pin_no, > + BBB_PWMSS pwmss_id, > + bool pullup_enable > +) > +{ > + rtems_status_code result = RTEMS_SUCCESSFUL; > + if ( pwmss_id >= BBB_PWMSS_COUNT ) { > + return RTEMS_INVALID_ID; > + } > + /* enable internal pull up / pull down resistor in pull up mode, and set > the > + * pin as an input. */ > + uint32_t pin_mode = BBB_RXACTIVE; > + if ( pullup_enable ) { > + pin_mode |= BBB_PU_EN; > + } > + // The offsets from AM335X_PADCONF_BASE (44e10000) are named after the > mode0 mux for that pin. > + if(pwmss_id == BBB_PWMSS0) { > + if (pin_no == BBB_P9_25_0_STROBE) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_MCASP0_AHCLKX) = pin_mode | > BBB_MUXMODE(BBB_P9_25_MUX_QEP); > + } else if (pin_no == BBB_P9_27_0B_IN) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_MCASP0_FSR) = pin_mode | > BBB_MUXMODE(BBB_P9_27_MUX_QEP); > + } else if (pin_no == BBB_P9_41_0_IDX) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_MCASP0_AXR1) = pin_mode | > BBB_MUXMODE(BBB_P9_41_MUX_QEP); > + } else if (pin_no == BBB_P9_42_0A_IN) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_MCASP0_ACLKR) = pin_mode | > BBB_MUXMODE(BBB_P9_42_MUX_QEP); > + } else { > + result = RTEMS_INTERNAL_ERROR; > + } > + } else if (pwmss_id == BBB_PWMSS1) { > + if (pin_no == BBB_P8_31_1_IDX) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_LCD_DATA14) = pin_mode | > BBB_MUXMODE(BBB_P8_31_MUX_QEP); > + } else if (pin_no == BBB_P8_32_1_STROBE) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_LCD_DATA15) = pin_mode | > BBB_MUXMODE(BBB_P8_32_MUX_QEP); > + } else if (pin_no == BBB_P8_33_1B_IN) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_LCD_DATA13) = pin_mode | > BBB_MUXMODE(BBB_P8_33_MUX_QEP); > + } else if (pin_no == BBB_P8_35_1A_IN) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_LCD_DATA12) = pin_mode | > BBB_MUXMODE(BBB_P8_35_MUX_QEP); > + } else { > + result = RTEMS_INTERNAL_ERROR; > + } > + } else if (pwmss_id == BBB_PWMSS2) { > + if (pin_no == BBB_P8_11_2B_IN) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_GPMC_AD13) = pin_mode | > BBB_MUXMODE(BBB_P8_11_MUX_QEP); > + } else if (pin_no == BBB_P8_12_2A_IN) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_GPMC_AD12) = pin_mode | > BBB_MUXMODE(BBB_P8_12_MUX_QEP); > + } else if (pin_no == BBB_P8_15_2_STROBE) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_GPMC_AD15) = pin_mode | > BBB_MUXMODE(BBB_P8_15_MUX_QEP); > + } else if (pin_no == BBB_P8_16_2_IDX) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_GPMC_AD14) = pin_mode | > BBB_MUXMODE(BBB_P8_16_MUX_QEP); > + } else if (pin_no == BBB_P8_39_2_IDX) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_LCD_DATA6) = pin_mode | > BBB_MUXMODE(BBB_P8_39_MUX_QEP); > + } else if (pin_no == BBB_P8_40_2_STROBE) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_LCD_DATA7) = pin_mode | > BBB_MUXMODE(BBB_P8_40_MUX_QEP); > + } else if (pin_no == BBB_P8_41_2A_IN) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_LCD_DATA4) = pin_mode | > BBB_MUXMODE(BBB_P8_41_MUX_QEP); > + } else if (pin_no == BBB_P8_42_2B_IN) { > + REG(AM335X_PADCONF_BASE + AM335X_CONF_LCD_DATA5) = pin_mode | > BBB_MUXMODE(BBB_P8_42_MUX_QEP); > + } else { > + result = RTEMS_INTERNAL_ERROR; > + } > + } else { > + result = RTEMS_INTERNAL_ERROR; > + } > + return result; > +} > + > +int32_t beagle_qep_get_position(BBB_PWMSS pwmss_id) > +{ > + int32_t position = 0; > + if ( pwmss_id >= BBB_PWMSS_COUNT ) { > + return -1; > + } > + const bbb_eqep* eqep = &bbb_eqep_table[pwmss_id]; > + > + if (eqep->quadrature_mode == ABSOLUTE) { > + /* return the current value of the QPOSCNT register */ > + position = REG(eqep->mmio_base + AM335x_EQEP_QPOSCNT); > + } else if (eqep->quadrature_mode == RELATIVE) { > + /* return the latched value from the last unit timer interrupt */ > + position = REG(eqep->mmio_base + AM335x_EQEP_QPOSLAT); > + } > + > + return position; > +} > + > +rtems_status_code beagle_qep_set_position(BBB_PWMSS pwmss_id, uint32_t > position) > +{ > + if ( pwmss_id >= BBB_PWMSS_COUNT ) { > + return RTEMS_INVALID_ID; > + } > + const bbb_eqep* eqep = &bbb_eqep_table[pwmss_id]; > + /* setting the position only really makes sense in ABSOLUTE mode. */ > + if (eqep->quadrature_mode == ABSOLUTE) { > + REG(eqep->mmio_base + AM335x_EQEP_QPOSCNT) = position; > + } > + > + return RTEMS_SUCCESSFUL; > +} > + > +rtems_status_code beagle_qep_set_count_mode( > + BBB_PWMSS pwmss_id, > + BBB_QEP_COUNT_MODE mode > +) > +{ > + if ( pwmss_id >= BBB_PWMSS_COUNT ) { > + return RTEMS_INVALID_ID; > + } > + bbb_eqep* eqep = &bbb_eqep_table[pwmss_id]; > + eqep->count_mode = mode; > + > + return RTEMS_SUCCESSFUL; > +} > + > +BBB_QEP_COUNT_MODE beagle_qep_get_count_mode(BBB_PWMSS pwmss_id) > +{ > + if ( pwmss_id >= BBB_PWMSS_COUNT ) { > + return RTEMS_INVALID_ID; > + } > + const bbb_eqep* eqep = &bbb_eqep_table[pwmss_id]; > + > + return eqep->count_mode; > +} > + > +rtems_status_code beagle_qep_set_quadrature_mode( > + BBB_PWMSS pwmss_id, > + BBB_QEP_QUADRATURE_MODE mode > +) > +{ > + uint16_t qepctl; > + if ( pwmss_id >= BBB_PWMSS_COUNT ) { > + return RTEMS_INVALID_ID; > + } > + bbb_eqep* eqep = &bbb_eqep_table[pwmss_id]; > + > + qepctl = REG16(eqep->mmio_base + AM335x_EQEP_QEPCTL); > + > + if (mode == ABSOLUTE) { > + /* > + * Disable the unit timer position reset > + */ > + qepctl &= ~AM335x_EQEP_QEPCTL_PCRM; > + > + eqep->quadrature_mode = ABSOLUTE; > + } else if (mode == RELATIVE) { > + /* > + * enable the unit timer position reset > + */ > + qepctl |= AM335x_EQEP_QEPCTL_PCRM; > + > + eqep->quadrature_mode = RELATIVE; > + } > + > + REG16(eqep->mmio_base + AM335x_EQEP_QEPCTL) = qepctl; > + > + return RTEMS_SUCCESSFUL; > +} > + > +BBB_QEP_QUADRATURE_MODE beagle_qep_get_quadrature_mode(BBB_PWMSS pwmss_id) > +{ > + if ( pwmss_id >= BBB_PWMSS_COUNT ) { > + return -1; > + } > + const bbb_eqep* eqep = &bbb_eqep_table[pwmss_id]; > + > + return eqep->quadrature_mode; > +} > + > + > +/* Function to read the period of the unit time event timer */ > +uint32_t beagle_eqep_get_timer_period(BBB_PWMSS pwmss_id) > +{ > + uint64_t period; > + uint32_t timer_period; > + if ( pwmss_id >= BBB_PWMSS_COUNT ) { > + return -1; > + } > + const bbb_eqep* eqep = &bbb_eqep_table[pwmss_id]; > + > + /* Convert from counts per interrupt back into period_ns */ > + period = REG(eqep->mmio_base + AM335x_EQEP_QUPRD); > + period = period * NANO_SEC_PER_SEC; > + timer_period = (uint32_t)(period / SYSCLKOUT); > + > + return timer_period; > +} > + > +rtems_status_code beagle_eqep_set_timer_period( > + BBB_PWMSS pwmss_id, > + uint64_t period, > + bbb_eqep_timer_callback timer_callback > +) > +{ > + uint16_t qepctl; > + uint64_t tmp_period; > + uint32_t timer_period; > + if ( pwmss_id >= BBB_PWMSS_COUNT ) { > + return RTEMS_INVALID_ID; > + } > + bbb_eqep* eqep = &bbb_eqep_table[pwmss_id]; > + > + /* Disable the unit timer before modifying its period register */ > + qepctl = readw(eqep->mmio_base + AM335x_EQEP_QEPCTL); > + qepctl &= ~(AM335x_EQEP_QEPCTL_UTE | AM335x_EQEP_QEPCTL_QCLM); > + REG16(eqep->mmio_base + AM335x_EQEP_QEPCTL) = qepctl; > + > + /* Zero the unit timer counter register */ > + REG(eqep->mmio_base + AM335x_EQEP_QUTMR) = 0; > + > + /* If the timer is enabled (a non-zero period has been passed) */ > + if (period) { > + /* update the period */ > + tmp_period = period * SYSCLKOUT; > + timer_period = (uint32_t)(tmp_period / NANO_SEC_PER_SEC); > + REG(eqep->mmio_base + AM335x_EQEP_QUPRD) = timer_period; > + > + /* Enable unit timer, and latch QPOSLAT to QPOSCNT on timer expiration */ > + qepctl |= AM335x_EQEP_QEPCTL_UTE | AM335x_EQEP_QEPCTL_QCLM; > + REG16(eqep->mmio_base + AM335x_EQEP_QEPCTL) = qepctl; > + > + /* attach the unit timer interrupt handler if one has been supplied */ > + if (timer_callback != NULL) { > + eqep->timer_callback = timer_callback; > + } > + } > + > + return RTEMS_SUCCESSFUL; > +} > diff --git a/c/src/lib/libbsp/arm/beagle/Makefile.am > b/c/src/lib/libbsp/arm/beagle/Makefile.am > index e37472373c..c9492f41a1 100644 > --- a/c/src/lib/libbsp/arm/beagle/Makefile.am > +++ b/c/src/lib/libbsp/arm/beagle/Makefile.am > @@ -76,9 +76,15 @@ librtemsbsp_a_SOURCES += > ../../../../../../bsps/arm/beagle/spi/spi.c > # GPIO > librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/beagle/gpio/bbb-gpio.c > > +#pwmss shared > +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/beagle/pwmss/pwmss.c > + > #pwm > librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/beagle/pwm/pwm.c > > +#qep > +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/beagle/qep/qep.c > + > #RTC > librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/beagle/rtc/rtc.c > librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/rtc/rtc-support.c > _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel