![]() |
|
|||
File indexing completed on 2025-05-11 08:22:48
0001 /** 0002 * @file 0003 * 0004 * @ingroup arm_beagle 0005 * 0006 * @brief eQEP (enhanced Quadrature Encoder Pulse) support API. 0007 */ 0008 0009 /* 0010 * SPDX-License-Identifier: BSD-2-Clause 0011 * 0012 * Copyright (c) 2020, 2021 James Fitzsimons <james.fitzsimons@gmail.com> 0013 * 0014 * Redistribution and use in source and binary forms, with or without 0015 * modification, are permitted provided that the following conditions 0016 * are met: 0017 * 1. Redistributions of source code must retain the above copyright 0018 * notice, this list of conditions and the following disclaimer. 0019 * 2. Redistributions in binary form must reproduce the above copyright 0020 * notice, this list of conditions and the following disclaimer in the 0021 * documentation and/or other materials provided with the distribution. 0022 * 0023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 0024 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 0025 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 0026 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 0027 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 0028 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 0029 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 0030 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 0031 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 0032 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 0033 * POSSIBILITY OF SUCH DAMAGE. 0034 */ 0035 0036 /** 0037 * 0038 * For details of the Enhanced Quadrature Encoder Pulse (eQEP) Module refer to 0039 * page 2511 of the TI Technical Reference Manual 0040 * (https://www.ti.com/lit/ug/spruh73q/spruh73q.pdf) 0041 * 0042 * This driver supports using the QEP modules in Quadrature-clock Mode. 0043 * Direction-count Mode is not currently supported. Similarly the QEPI: Index 0044 * or Zero Marker and QEPS: Strobe Input pins are not currently supported. 0045 * 0046 * The mode can be any one of: 0047 * - Quadrature-count mode - For encoders that generate pulses 90 degrees 0048 * out of phase for determining direction and speed. 0049 * - Direction-count mode - for position encoders that provide direction and 0050 * clock outputs, instead of quadrature outputs. 0051 * - UP-count mode - The counter direction signal is hard-wired for up count 0052 * and the position counter is used to measure the frequency of the QEPA 0053 * input. 0054 * - DOWN-count mode - The counter direction signal is hard-wired for a down 0055 * count and the position counter is used to measure the frequency of the 0056 * QEPA input. 0057 * 0058 * When the eQEP module is configured in quadrature mode, the module 0059 * can either provide an absolute position, or a relative position. Absolute 0060 * simply increments or decrements depending on the direction. Relative 0061 * increments until the unit timer overflows at which point it latches the 0062 * position value, resets the position count to zero and starts again. 0063 */ 0064 0065 #ifndef LIBBSP_ARM_BEAGLE_QEP_H 0066 #define LIBBSP_ARM_BEAGLE_QEP_H 0067 0068 #ifdef __cplusplus 0069 extern "C" { 0070 #endif /* __cplusplus */ 0071 0072 #define AM335X_EQEP_REGS (0x00000180) 0073 #define AM335X_EQEP_0_REGS (AM335X_PWMSS0_MMAP_ADDR + AM335X_EQEP_REGS) 0074 #define AM335X_EQEP_1_REGS (AM335X_PWMSS1_MMAP_ADDR + AM335X_EQEP_REGS) 0075 #define AM335X_EQEP_2_REGS (AM335X_PWMSS2_MMAP_ADDR + AM335X_EQEP_REGS) 0076 0077 /* eQEP registers of the PWMSS modules - see page 1672 of the TRM for details */ 0078 #define AM335x_EQEP_QPOSCNT 0x0 /* eQEP Position Counter */ 0079 #define AM335x_EQEP_QPOSINIT 0x4 /* eQEP Position Counter Initialization */ 0080 #define AM335x_EQEP_QPOSMAX 0x8 /* eQEP Maximum Position Count */ 0081 #define AM335x_EQEP_QPOSCMP 0xC /* eQEP Position-Compare */ 0082 #define AM335x_EQEP_QPOSILAT 0x10 /* eQEP Index Position Latch */ 0083 #define AM335x_EQEP_QPOSSLAT 0x14 /* eQEP Strobe Position Latch */ 0084 #define AM335x_EQEP_QPOSLAT 0x18 /* eQEP Position Counter Latch */ 0085 #define AM335x_EQEP_QUTMR 0x1C /* eQEP Unit Timer */ 0086 #define AM335x_EQEP_QUPRD 0x20 /* eQEP Unit Period */ 0087 #define AM335x_EQEP_QWDTMR 0x24 /* eQEP Watchdog Timer */ 0088 #define AM335x_EQEP_QWDPRD 0x26 /* eQEP Watchdog Period */ 0089 #define AM335x_EQEP_QDECCTL 0x28 /* eQEP Decoder Control */ 0090 #define AM335x_EQEP_QEPCTL 0x2A /* eQEP Control */ 0091 #define AM335x_EQEP_QCAPCTL 0x2C /* eQEP Capture Control */ 0092 #define AM335x_EQEP_QPOSCTL 0x2E /* eQEP Position-Compare Control */ 0093 #define AM335x_EQEP_QEINT 0x30 /* eQEP Interrupt Enable */ 0094 #define AM335x_EQEP_QFLG 0x32 /* eQEP Interrupt Flag */ 0095 #define AM335x_EQEP_QCLR 0x34 /* eQEP Interrupt Clear */ 0096 #define AM335x_EQEP_QFRC 0x36 /* eQEP Interrupt Force */ 0097 #define AM335x_EQEP_QEPSTS 0x38 /* eQEP Status */ 0098 #define AM335x_EQEP_QCTMR 0x3A /* eQEP Capture Timer */ 0099 #define AM335x_EQEP_QCPRD 0x3C /* eQEP Capture Period */ 0100 #define AM335x_EQEP_QCTMRLAT 0x3E /* eQEP Capture Timer Latch */ 0101 #define AM335x_EQEP_QCPRDLAT 0x40 /* eQEP Capture Period Latch */ 0102 #define AM335x_EQEP_REVID 0x5C /* eQEP Revision ID */ 0103 0104 /* bitmasks for eQEP registers */ 0105 #define AM335x_EQEP_QEPCTL_UTE (1 << 1) 0106 #define AM335x_EQEP_QEPCTL_QCLM (1 << 2) 0107 #define AM335x_EQEP_QEPCTL_PHEN (1 << 3) 0108 #define AM335x_EQEP_QEPCTL_IEL (1 << 4) 0109 #define AM335x_EQEP_QEPCTL_SWI (1 << 7) 0110 #define AM335x_EQEP_QEPCTL_PCRM (3 << 12) 0111 #define AM335x_EQEP_QDECCTL_QSRC (3 << 14) 0112 #define AM335x_EQEP_QDECCTL_XCR (1 << 11) 0113 #define AM335x_EQEP_QDECCTL_SWAP (1 << 10) 0114 #define AM335x_EQEP_QDECCTL_IGATE (1 << 9) 0115 #define AM335x_EQEP_QDECCTL_QAP (1 << 8) 0116 #define AM335x_EQEP_QDECCTL_QBP (1 << 7) 0117 #define AM335x_EQEP_QDECCTL_QIP (1 << 6) 0118 #define AM335x_EQEP_QDECCTL_QSP (1 << 5) 0119 #define AM335x_EQEP_CLK_EN (1 << 4) 0120 #define AM335x_EQEP_QEINT_UTO (1 << 11) 0121 #define AM335x_EQEP_QFLG_UTO (1 << 11) 0122 #define AM335x_EQEP_QFLG_MASK 0x0FFF 0123 0124 /* The pin mux modes for the QEP input pins on the P8 and P9 headers */ 0125 #define BBB_P8_11_MUX_QEP 4 0126 #define BBB_P8_12_MUX_QEP 4 0127 #define BBB_P8_15_MUX_QEP 4 0128 #define BBB_P8_16_MUX_QEP 4 0129 #define BBB_P8_31_MUX_QEP 2 0130 #define BBB_P8_32_MUX_QEP 2 0131 #define BBB_P8_33_MUX_QEP 2 0132 #define BBB_P8_35_MUX_QEP 2 0133 #define BBB_P8_39_MUX_QEP 3 0134 #define BBB_P8_40_MUX_QEP 3 0135 #define BBB_P8_41_MUX_QEP 3 0136 #define BBB_P8_42_MUX_QEP 3 0137 #define BBB_P9_25_MUX_QEP 1 0138 #define BBB_P9_27_MUX_QEP 1 0139 #define BBB_P9_41_MUX_QEP 1 0140 #define BBB_P9_42_MUX_QEP 1 0141 0142 #define NANO_SEC_PER_SEC 1000000000 0143 /* This is the max clock rate for the EPWMSS module. See 15.1.2.2 of the TRM. 0144 * If the CPU was using dynamic scaling this could potentially be wrong */ 0145 #define SYSCLKOUT 100000000 0146 0147 /** 0148 * @brief The set of possible eQEP Position Counter Input Modes 0149 * 0150 * Enumerated type to define various modes for the eQEP module. The values 0151 * correspond to the values for the QSRC bits of the QDECCTL register. 0152 */ 0153 typedef enum { 0154 QUADRATURE_COUNT = 0, 0155 DIRECTION_COUNT, 0156 UP_COUNT, 0157 DOWN_COUNT 0158 } BBB_QEP_COUNT_MODE; 0159 0160 /** 0161 * @brief The set of possible modes for Quadrature decode 0162 * 0163 */ 0164 typedef enum { 0165 ABSOLUTE = 0, 0166 RELATIVE 0167 } BBB_QEP_QUADRATURE_MODE; 0168 0169 /** 0170 * @brief The set of possible eQEP input pins 0171 * 0172 */ 0173 typedef enum { 0174 BBB_P8_11_2B_IN, 0175 BBB_P8_12_2A_IN, 0176 BBB_P8_15_2_STROBE, 0177 BBB_P8_16_2_IDX, 0178 BBB_P8_31_1_IDX, 0179 BBB_P8_32_1_STROBE, 0180 BBB_P8_33_1B_IN, 0181 BBB_P8_35_1A_IN, 0182 BBB_P8_39_2_IDX, 0183 BBB_P8_40_2_STROBE, 0184 BBB_P8_41_2A_IN, 0185 BBB_P8_42_2B_IN, 0186 BBB_P9_25_0_STROBE, 0187 BBB_P9_27_0B_IN, 0188 BBB_P9_41_0_IDX, 0189 BBB_P9_42_0A_IN 0190 } bbb_qep_pin; 0191 0192 0193 /** 0194 * @brief This function definition is used to declare a callback function that 0195 * will be called by the interrupt handler of the QEP driver. In order for the 0196 * interrupt event to trigger the driver must be configured in RELATIVE mode 0197 * (using the beagle_qep_get_quadrature_mode function), and the unit timer must 0198 * have been configured (using the beagle_eqep_set_timer_period function). 0199 * 0200 * @param BBB_PWMSS This argument is provided to the user call back function so 0201 * that the user can tell which QEP module raised the interrupt. 0202 * 0203 * @param position The value of the position counter that was latched when the 0204 * unit timer raised this interrupt. This is the value that would be returned 0205 * by calling "beagle_qep_get_position". 0206 * 0207 * @param user This a pointer to a user provided data structure. The user sets 0208 * this pointer value when configuring the unit timer callback via the 0209 * beagle_eqep_set_timer_period function and it is returned here as an argument. 0210 * The driver does not touch this value. 0211 */ 0212 typedef void (*bbb_eqep_timer_callback)( 0213 BBB_PWMSS, 0214 uint32_t position, 0215 void* user 0216 ); 0217 0218 0219 /** 0220 * @brief This structure represents an eQEP module instance. The members 0221 * represent the configuration of a specific eQEP module. There are three 0222 * eQEP modules in the AM335x, one associated with each PWMSS unit. 0223 * @var bbb_eqep::pwmss_id The PWMSS unit this eQEP module belongs to. 0224 * @var bbb_eqep::mmio_base The base address for this eQEP modules registers 0225 * @var bbb_eqep::irq The IRQ vector for this eQEP module 0226 * @var bbb_eqep::timer_callback An optional user provided callback function 0227 * when the driver is configured in RELATIVE mode using the unit timer 0228 * @var bbb_eqep::user An optional pointer to user provided data that will be 0229 * handed to the callback function as an argument. 0230 * @var bbb_eqep::count_mode The count mode for this eQEP module. Defaults to 0231 * QUADRATURE. 0232 * @var bbb_eqep::quadrature_mode The mode for QUADRATURE operation. Defaults 0233 * to ABSOLUTE - will count up to overflow or until the user resets the 0234 * position. Can be set to RELATIVE which will trigger a call back of the unit 0235 * timer if configured. 0236 * @var bbb_eqep::invert_qa 1 to invert the A channel input, 0 to leave as is. 0237 * @var bbb_eqep::invert_qb 1 to invert the B channel input, 0 to leave as is. 0238 * @var bbb_eqep::invert_qi 1 to invert the INDEX input, 0 to leave as is. 0239 * @var bbb_eqep::invert_qs 1 to invert the STROBE input, 0 to leave as is. 0240 * @var bbb_eqep::swap_inputs 1 to swap the A and B channel inputs, 0 to leave 0241 * as is. 0242 * 0243 */ 0244 typedef struct { 0245 const BBB_PWMSS pwmss_id; 0246 const uint32_t mmio_base; 0247 const rtems_vector_number irq; 0248 bbb_eqep_timer_callback timer_callback; 0249 void* user; 0250 BBB_QEP_COUNT_MODE count_mode; 0251 BBB_QEP_QUADRATURE_MODE quadrature_mode; 0252 uint32_t invert_qa; 0253 uint32_t invert_qb; 0254 uint32_t invert_qi; 0255 uint32_t invert_qs; 0256 uint32_t swap_inputs; 0257 } bbb_eqep; 0258 0259 0260 /** 0261 * @brief Initialises the eQEP module of the specified PWMSS unit. This 0262 * configures the clocks, sets up the interrupt handler and unit timer, 0263 * The module is configured in Quadrature decode mode using 0264 * absolute position by default. 0265 * 0266 * @param pwmss_id The PWMSS module to configure the eQEP for. 0267 * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is 0268 * supplied. 0269 */ 0270 rtems_status_code beagle_qep_init(BBB_PWMSS pwmss_id); 0271 0272 /** 0273 * @brief Enables the eQEP module of the specified PWMSS unit. 0274 * 0275 * @param pwmss_id The PWMSS module which will have the eQEP function enabled. 0276 * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is 0277 * supplied. 0278 */ 0279 rtems_status_code beagle_qep_enable(BBB_PWMSS pwmss_id); 0280 0281 /** 0282 * @brief Disables the eQEP module of the specified PWMSS unit. 0283 * 0284 * @param pwmss_id The PWMSS module which will have the eQEP function disabled. 0285 * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is 0286 * supplied. 0287 */ 0288 rtems_status_code beagle_qep_disable(BBB_PWMSS pwmss_id); 0289 0290 /** 0291 * @brief Configures a given pin for use with the eQEP function of the supplied 0292 * PWMSS module. 0293 * 0294 * @param pin_no The P9 or P8 header pin to be configured for the eQEP function. 0295 * @param pwmss_id The PWMSS module which will have the eQEP function enabled. 0296 * @param pullup_enable If true then the internal pull up resistor on the 0297 * specified pin will be enabled, if false the pull down will be enabled. 0298 * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is 0299 * supplied. 0300 */ 0301 rtems_status_code beagle_qep_pinmux_setup( 0302 bbb_qep_pin pin_no, 0303 BBB_PWMSS pwmss_id, 0304 bool pullup_enable 0305 ); 0306 0307 /** 0308 * @brief Returns the current position value of the eQEP function for the 0309 * specified PWMSS module. 0310 * 0311 * @param pwmss_id Identifies which PWMSS module to return the eQEP position for 0312 * @return int32_t The current position value. 0313 */ 0314 int32_t beagle_qep_get_position(BBB_PWMSS pwmss_id); 0315 0316 /** 0317 * @brief Sets the initial position value of the eQEP function for the 0318 * specified PWMSS module. 0319 * 0320 * @param pwmss_id Identifies which PWMSS module to set the eQEP position for 0321 * @param position The value to initialise the position register with. 0322 * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is 0323 * supplied. 0324 */ 0325 rtems_status_code beagle_qep_set_position( 0326 BBB_PWMSS pwmss_id, 0327 uint32_t position 0328 ); 0329 0330 /** 0331 * @brief Sets the count mode for the eQEP module. 0332 * @param pwmss_id Identifies which PWMSS module to set the eQEP count mode for. 0333 * @param mode One of the above modes to configure the eQEP module for. 0334 * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is 0335 * supplied. 0336 */ 0337 rtems_status_code beagle_qep_set_count_mode( 0338 BBB_PWMSS pwmss_id, 0339 BBB_QEP_COUNT_MODE mode 0340 ); 0341 0342 /** 0343 * @brief Gets the currently configured count mode for the eQEP module. 0344 * @param pwmss_id Identifies which PWMSS module to set the eQEP count mode for. 0345 * @return An enum value representing the current count mode. 0346 */ 0347 BBB_QEP_COUNT_MODE beagle_qep_get_count_mode(BBB_PWMSS pwmss_id); 0348 0349 /** 0350 * @brief Returns the currently configured quadrature mode - either absolute, 0351 * or relative. 0352 * @param pwmss_id Identifies which PWMSS module to get the eQEP quadrature 0353 * mode for. 0354 * @return BBB_QEP_QUADRATURE_MODE The currently configured quadrature mode. 0355 */ 0356 BBB_QEP_QUADRATURE_MODE beagle_qep_get_quadrature_mode(BBB_PWMSS pwmss_id); 0357 0358 /** 0359 * @brief Sets the quadrature mode to either absolute or relative. 0360 * @param pwmss_id Identifies which PWMSS module to set the eQEP quadrature 0361 * mode for. 0362 * @param mode BBB_QEP_QUADRATURE_MODE Set the mode of the eQEP to either 0363 * absolute or relative. 0364 * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is 0365 * supplied. 0366 */ 0367 rtems_status_code beagle_qep_set_quadrature_mode( 0368 BBB_PWMSS pwmss_id, 0369 BBB_QEP_QUADRATURE_MODE mode 0370 ); 0371 0372 /** 0373 * @brief Returns the the currently configured unit timer period. 0374 * @param pwmss_id Identifies which PWMSS module to get the eQEP timer value for 0375 * @return uint32_t The current unit timer value in nanoseconds 0376 */ 0377 uint32_t beagle_eqep_get_timer_period(BBB_PWMSS pwmss_id); 0378 0379 /** 0380 * @brief Sets the unit timer period for the eQEP module. 0381 * 0 = off, greater than zero sets the period. 0382 * @param pwmss_id Identifies which PWMSS module to set the eQEP unit timer for. 0383 * @param period The value in nanoseconds to set the unit timer period to. 0384 * @param timer_callback This is the user provided callback function that will 0385 * be called by the interrupt event handler on expiry of the unit timer. The 0386 * user can provide NULL if they don't require a call back. 0387 * @param user This is a pointer to a user provided data structure that will be 0388 * handed back as an argument to the timer callback. The driver does not touch 0389 * this value. 0390 * @return RTEMS_SUCCESSFUL if ok, RTEMS_INVALID_ID if an invalid pwmss_id is 0391 * supplied. 0392 */ 0393 rtems_status_code beagle_eqep_set_timer_period( 0394 BBB_PWMSS pwmss_id, 0395 uint64_t period, 0396 bbb_eqep_timer_callback timer_callback, 0397 void* user 0398 ); 0399 0400 #ifdef __cplusplus 0401 } 0402 #endif /* __cplusplus */ 0403 0404 #endif /* LIBBSP_ARM_BEAGLE_QEP_H */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |