This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C129ENCPDT: QEI: Index interrupt not triggering

Part Number: TM4C129ENCPDT
Other Parts Discussed in Thread: TM4C123AH6PM,

Some time ago I made this post:

https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/607014

Which was essentially never answered.

I have a problem where the QEI index interrupt is never generated, i.e., QEIRIS.INTINDEX never becomes 1.

This is the stripped-down code to initialize QEI and service the interrupt:

void IsrQei0Handler(void)
{
	uint32_t Status;

	Status = MAP_QEIIntStatus(QEI0_BASE, true);
	MAP_QEIIntClear(QEI0_BASE, Status);

	if (Status & QEI_INTERROR) {
		// Handle QEI error
		// ...
	}

	if (Status & QEI_INTINDEX) {
		// Handle index pulse
		// ---> THIS CONDITION NEVER TRIGGERS <---
	}

	if (Status & QEI_INTDIR) {
		// Handle direction change
		// ...
	}
}


bool InitQei(void)
{
	if (!MAP_SysCtlPeripheralPresent(SYSCTL_PERIPH_QEI0))
		return false;

	// Reset and enable peripheral
	MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_QEI0);
	MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_QEI0);
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI0);
	while (MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_QEI0) != true) {
		// Wait for peripheral to activate
	}

	// Configure GPIO pins
	MAP_GPIOPinConfigure(GPIO_PL1_PHA0);
	MAP_GPIOPinConfigure(GPIO_PL2_PHB0);
	MAP_GPIOPinConfigure(GPIO_PL3_IDX0);

	MAP_GPIOPinTypeQEI(GPIO_PORTL_BASE, GPIO_PIN_1);
	MAP_GPIOPinTypeQEI(GPIO_PORTL_BASE, GPIO_PIN_2);
	MAP_GPIOPinTypeQEI(GPIO_PORTL_BASE, GPIO_PIN_3);

	// Configure QEI peripheral
	MAP_QEIConfigure(QEI0_BASE, QEI_CONFIG_CAPTURE_A_B | QEI_CONFIG_NO_RESET | QEI_CONFIG_QUADRATURE | QEI_CONFIG_NO_SWAP, 0xffffffff);
	MAP_QEIPositionSet(QEI0_BASE, 0);
	MAP_QEIVelocityConfigure(QEI0_BASE, QEI_VELDIV_1, Global.SysClockFreqHz / 100);
	MAP_QEIVelocityEnable(QEI0_BASE);
	MAP_QEIEnable(QEI0_BASE);
	MAP_QEIIntEnable(QEI0_BASE, (QEI_INTERROR | QEI_INTINDEX | QEI_INTDIR));
	MAP_IntPrioritySet(INT_QEI0, 0x20);
	MAP_IntEnable(INT_QEI0);

	return true;
}

The condition that does not trigger is Status == QEI_INTINDEX, as marked in a comment. 

I have verified that our quadrature encoders are indeed producing an index pulse as expected, and that the signal is routed to (and reaches) the correct MCU pin.

So I tested another way:

void IntGpioPortLHandler(void)
{
	uint32_t Status;

	Status = GPIOIntStatus(GPIO_PORTL_BASE, true);
	GPIOIntClear(GPIO_PORTL_BASE, Status);

	if (Status == GPIO_INT_PIN_3) {
		// This condition does trigger
		// ...
	}
}


bool InitQei(void)
{
	if (!MAP_SysCtlPeripheralPresent(SYSCTL_PERIPH_QEI0))
		return false;

	// Reset and enable peripheral
	MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_QEI0);
	MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_QEI0);
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI0);
	while (MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_QEI0) != true) {
		// Wait for peripheral to activate
	}

	// Configure GPIO pins
	MAP_GPIOPinConfigure(GPIO_PL1_PHA0);
	MAP_GPIOPinConfigure(GPIO_PL2_PHB0);

	MAP_GPIOPinTypeQEI(GPIO_PORTL_BASE, GPIO_PIN_1);
	MAP_GPIOPinTypeQEI(GPIO_PORTL_BASE, GPIO_PIN_2);

	// Configure QEI peripheral
	MAP_QEIConfigure(QEI0_BASE, QEI_CONFIG_CAPTURE_A_B | QEI_CONFIG_NO_RESET | QEI_CONFIG_QUADRATURE | QEI_CONFIG_NO_SWAP, 0xffffffff);
	MAP_QEIPositionSet(QEI0_BASE, 0);
	MAP_QEIVelocityConfigure(QEI0_BASE, QEI_VELDIV_1, Global.SysClockFreqHz / 100);
	MAP_QEIVelocityEnable(QEI0_BASE);
	MAP_QEIEnable(QEI0_BASE);
	MAP_QEIIntEnable(QEI0_BASE, (QEI_INTERROR | QEI_INTDIR));
	MAP_IntPrioritySet(INT_QEI0, 0x20);
	MAP_IntEnable(INT_QEI0);
	
	// Index pin interrupt
	MAP_GPIOIntClear(GPIO_PORTL_BASE, GPIO_INT_PIN_3);
	MAP_GPIOPinTypeGPIOInput(GPIO_PORTL_BASE, GPIO_PIN_3);
	MAP_GPIOIntTypeSet(GPIO_PORTL_BASE, GPIO_PIN_3, GPIO_RISING_EDGE);
	MAP_GPIOIntEnable(GPIO_PORTL_BASE, GPIO_INT_PIN_3);
	MAP_IntPrioritySet(INT_GPIOL, 0x20);
	MAP_IntEnable(INT_GPIOL);

	return true;
}

This second code initializes the QEI without the INDEX pin, then initializes the INDEX pin as a GPIO with interrupt on rising edge.

In this code, the GPIO interrupt does trigger when the quadrature encoder passes through the INDEX pulse.

Why does the QEI INDEX interrupt never trigger?

  • Hi twelve12pm,
    Can you do an experiment by changing to QEI_CONFIG_RESET_IDX instead of QEI_CONFIG_NO_RESET and let me know if that makes a difference on the index interrupt generation?
  • twelve12pm said:
    Why does the QEI INDEX interrupt never trigger?

    First a "Disclaimer" - neither firm nor I are "fans" of 129 family.     We deploy the 123 in several basic products (others' M7s in more advanced ones) - I'm basing this response upon what we've found to be true for the '123 - hoping this overlaps - in your favor.

    In a nutshell - my analysis differs from the vendor's...

    Your "Status = MAP_QEIIntStatus(QEI0_BASE, true);" in my opinion should employ "false" - for the final parameter.      Follows - my justification:  (detail of  QEIIntStatus() - from the TM4C API)

    Gets the current interrupt status.
    //!
    //! \param ui32Base is the base address of the quadrature encoder module.
    //! \param bMasked is false if the raw interrupt status is required (I believe this is what you require) and true (your choice) if the masked interrupt status is required.
    //!
    //! This function returns the interrupt status for the quadrature encoder module.   Either the raw interrupt status or the status of interrupts that are allowed to reflect to the processor can be returned.
    //!
    //! \return Returns the current interrupt status, enumerated as a bit field of
    //! \b QEI_INTERROR, \b QEI_INTDIR, \b QEI_INTTIMER, and \b QEI_INTINDEX.   (this is the "failing interrupt trigger")

    uint32_t
    QEIIntStatus(uint32_t ui32Base, bool bMasked)     //  Here I've presented the API's source code - for your (likely) troubling function:
    {
    // Check the arguments.
    //
    ASSERT((ui32Base == QEI0_BASE) || (ui32Base == QEI1_BASE));
    //
    // Return either the interrupt status or the raw interrupt status as requested

    //
    if(bMasked)
    {
    return(HWREG(ui32Base + QEI_O_ISC));    //  this return does NOT test QEI_O_RIS - which IS required - to cause a QEI_Index Interrupt!
    }
    else
    {
    return(HWREG(ui32Base + QEI_O_RIS));   //  this return performs such test!
    }
    }

    Now I've reviewed the QEI Registers w/in the '123 MCU - and 3 such QEI Registers prove key:  "QEIRIS, QEIISC, QEIINTEN."    The '123 requires that  "Bit_0" of (both) QEIRIS & QEIINTEN be set - to "promote the "QEI_INTINDEX" to the MCU's NVIC."      Now follows a "true copy" - directly from the '123 MCU Manual - fully supporting this requirement for causing such "Index-based Interrupt:"

    Your election of the "true" parameter - rather than "false" - (likely) prevents or otherwise mutes the "examination of  QEIRIS bit_0" - which as noted above - IS required to trigger the QEI Index Interrupt...

    Should this suggestion (based upon the "hoped for, even "expected") technical similarity between vendor's TM4C devices not succeed - at least a general, "Method or Path - leading to success" has been presented - and may be "modeled" - to accommodate (unwanted) variances between "MCU families."     (Ugh - especially those I2C "HARD Starboard!" shifts!)

  • Dear Charles,

    Thank you for your reply.

    I did the experiment, changed to QEI_CONFIG_RESET_IDX, and I can confirm that the INDEX interrupt is being generated now -- however the bad news is that we cannot use the QEI this way in our application, because it is resetting the position count to 0 each time the QEI passes through the index.

    Thoughts?
  • Dear cb1_mobile,

    Thank you for your reply and for explaining your / your firm's experiences.

    The 123 and 129 are very similar, but as we've discovered, different enough that you run into some "gotchas!" every so often. We discovered this because we are developing a product line with several board models using TM4C129ENCPDT and TM4C123AH6PM and we are developing one software codebase for the whole product line. So... very soon (hopefully later today) I will discover how the 123 behaves with respect to the QEI, and I'll let you know.

    In the meantime (still on the 129), per your suggestion, I have tried changing true to false in my call to QEIIntStatus(). Unfortunately that didn't seem to make any difference.

    Charles Tsai asked me to experiment with changing QEI_CONFIG_NO_RESET to QEI_CONFIG_RESET_IDX in my call to QEIConfigure().

    So I tried all four combinations of QEI_CONFIG_NO_RESET / QEI_CONFIG_RESET_IDX and true / false. Here is the resulting truth table:

    QEIConfigure()          QEIIntStatus()      QEI_INTINDEX triggered?
    -------------------------------------------------------------------
    QEI_CONFIG_NO_RESET     true                Nope
    QEI_CONFIG_NO_RESET     false               Nope
    QEI_CONFIG_RESET_IDX    true                Yes
    QEI_CONFIG_RESET_IDX    false               Yes
    

    In other words, it didn't make any difference whether I used true or false. Maybe this will be different on the 123; I'll let you know. Meanwhile...

    You said (and I agree) that 3 registers are key: QEIRIS, QEIISC, QEIINTEN. I am familiar with this system because most of the peripherals use it. Usually the registers have names ending in *RIS (Raw Interrupt Status), *MIS (Masked Interrupt Status), and *INTEN (Interrupt Enable). In the case of the QEI, the register that should have been named QEIMIS is named QEIISC for some reason. Perhaps that is some sort of clue? Or perhaps it was an oversight or a leftover from some legacy naming scheme? Who knows.

    If I had to explain how interrupts get triggered, generally speaking across different on-chip peripherals, my observation of behavior indicates something like the following: Some event causes a bit in a *RIS register to be set; this is ANDed with the corresponding bit in *INTEN, and the result placed in *MIS (or *ISC in the case of this QEI peripheral); the *MIS bits are ORed together, the result is ANDed with one bit in one of the NVIC EN* registers, and if 1 then the interrupt handler is triggered. In the interrupt handler, we can check either the raw status or the masked status.

    Your firm prefers to check the raw status.

    In all of our interrupt handlers, we have been checking the masked status. Here is our rationale for doing so: the raw status bits are set for all events regardless of whether these are events of interest. When we are not interested in an event, its raw status bit can just sit there in the set state indefinitely and be ignored. When we are interested in an event, our initialization / setup code deliberately sets that bit in the peripheral *INTEN register. This is required if we wish to get an interrupt. Then, this means that our event of interest must be reflected in the masked status bits. Are we mistaken? I will say that across quite a few interrupt handlers, this method has been working correctly and giving the intended results.

    Since you said that QEIRIS, QEIISC, QEIINTEN are key, I wanted to verify that bit 0 of QEIINTEN is in fact set -- that is, that the interrupt is actually enabled -- to rule out a software mistake. I compiled with QEI_CONFIG_NO_RESET, which is the configuration we want. I placed a breakpoint inside the interrupt handler and triggered the interrupt handler -- though I cannot trigger it with an INDEX pulse, so I triggered it by changing direction. Once stopped at the breakpoint I examined registers and I can confirm that bit 0 is in fact set (it is called QEI_INTEN_INDEX here):

    So I conclude that QEIRIS.INTINDEX is never set.

  • Hi twelve12pm,

     I have done some research on past posts. It looks like the index interrupt is tied to the position counter being reset by the detection of the index signal. If you want to decouple them my advice will be to use the GPIO interrupt on the index input which you have already tried and proved working. Please let me know if this is an acceptable solution.

  • Hello Charles,

    Thank you for taking time on a Sunday to research this.

    I was afraid you'd say that.

    Using the GPIO interrupt on the QEI Index input pin does work as I stated above -- however this causes a problem.

    We have another signal, unrelated to the QEI Index, which is serviced by a GPIO interrupt. That other signal is time-critical, hence it is the highest priority interrupt in the system and the only interrupt allowed to be at that priority. Each GPIO port has only one interrupt vector and hence one interrupt priority, etc.

    Unfortunately because we were expecting to use the QEI interrupt for handling the QEI Index signal, one of our board designs placed both of these signals on the same GPIO port.

    If it is not possible to get the Index interrupt to trigger (without resetting the position counter, of course), then as I see it we have two options:

    Option 1: Handle the index signal in that highest-priority interrupt. This may introduce additional latency and jitter to handling of the time-critical interrupt. That might be in acceptable limits but will require testing to find out.

    Option 2: Modify the board design to move our time-critical signal to a different GPIO port (preferably to a port that has per-pin interrupts). But before I ask for a re-spin, I'm eliminating other options.

    If you have any other thoughts, I'd love to hear them.

    Thanks again
  • Hi Twelve12pm,
    Do you have any other GPIOs that is currently not used and not in the same GPIO port as the time critical interrupt and can be repurposed for generating index interrupt? Of course this option will still require board level change. In your option 1, I think you can write your code in a way to prioritize the time critical interrupt. For example, if the interrupt is due to time-critical signal then process it inside the ISR. If it is due to the index interrupt then set a flag and immediately exit. Service the index interrupt in the main() based on the flag.
  • Hello Charles,

    As you point out, any re-routing of signals will require a board-level change. I will try to avoid that by prioritizing the time-critical interrupt as you suggest.

    Thanks for your help.
  • Hello 12squared,

    Great job - unusual to note "two outsiders" - willing to invest (reasonable) time/effort - in the creation of such detail.     Again - I focused upon the '123 as we've never used (nor cared for) the '129.     And - it did NOT seem "unreasonable" that any vendor would seek to "re-use" tech aspects/methods - already proven.    Further - it was doubted (ok - guessed) that the QEI Module would be "much enhanced."

    Now you write, "Your firm prefers to check the raw status."      And that's just NOT true!      I (uniquely) presented the "Source Code" for your QEI Status check function - and  that code revealed the requirement for the "Check of RIS Bit_0.     As I reviewed the QEI Registers - I noted those 3 - which clearly dominated the QEI Module's Interrupt Handling.     And - that RIS bit, "Had to be set" for the Index Interrupt to occur.    (my earlier post presented those facts via "true copy" - directly from the '123 manual.

    Now your/firm's method of handling general interrupts is (almost) identical to ours/mine.     Again - I seized upon the RIS test w/in QEI Status Check - upon discovering that RIS_Bit_0 was required - for the index interrupt to be propagated.     (and such STILL - seems reasonable)

    I'm in agreement that use of a "Parallel connection" to the QEI Index pin - AND to a separate GPIO - may prove best.     Yet - thinking further - since the QEI_Index pin (presently) provides,  "Little (pardon) NO Value" ... Why maintain that connection - at all?    If you can free - or find - such "free GPIO pin" - employ it as your QEI Index interrupt trigger!

    ***  Kindly note that I've "retreated" (at least somewhat) from (that) below.     The "next arriving post" (one down) details...

    I'm wondering also if your, "Chosen Divorce of the Index signal from position counter(s) inter-action - is "legal?"     My understanding (surely NO standard) is that the "index Signal" (usually) identifies a "Starting or Ending" Position.     Thus - your MCU's "zeroing" of position counters - may prove VALID!     Yet another (reasonably) standard use of  QEI Index is to record, "Number of Revolutions" - and that's been lost - thus the "QEI Design Crüe" should be hauled in for "interrogation."     And it is noted that the  "FREE GPIO pin" may ably provide such Revolution Counting.     (along w/other items of your desire)

    If time allows I'll have staff run tests upon 2 other/alien ARM MCUs  (M4 & M7) tomorrow - and report.      (may be late in the day as several here have "worked w/me - all day - today.")

  • Greetings,

    I'm still bothered by,  "Not having assisted in the resolution of this, "Failure of the Index Signal" to trigger the QEI Interrupt."     (Like you sense - this IS maddening!    And does NOT occur w/another's (180MHz M4!)      Arrived early today (pre-staff) to "dig deeper" - try to develop further insights.

    Earlier this morning I had the sense that the API QEI function (as suggested by friend Charles) was likely "flawed."    My (earlier) sense was that, "An Index Generated Interrupt "demanded" a Reset of the Position Counter" - and that's just  too "heavy handed" (like the banning of * LIKE *, here).     So - as the API's source code IS available - let's review:

    and:  " \b QEI_CONFIG_NO_RESET or \b QEI_CONFIG_RESET_IDX  specify if the position integrator should be reset when the index pulse is detected."     Thus - no such "heavy hand" was intended.   (such may have occurred - but it  was/is (unlikely) to be deliberate.)    Still of "grave concern" - this Position Reset (or not) "Should not be empowered to  "Enable/Disable"  the Index Interrupt!"    That's just  counter-intuitive - "wreaks" of  last ditch, implementation "hack" - does it not?     As a result - the proper "Index Generated Interrupt" is "held hostage" - and (as poster noted) this  impedes his "code freedom & progress!"

    Next - Did "you" do all that is required to, "Assist the QEI Index signal to Interrupt?"     And once more - arrives the API Source code - in answer:   (and indeed - you DID!)

    QEIIntEnable(uint32_t ui32Base, uint32_t ui32IntFlags)
    {
    //
    // Check the arguments.
    //
    ASSERT((ui32Base == QEI0_BASE) || (ui32Base == QEI1_BASE));
    //
    // Enable the specified interrupts.
    //
    HWREG(ui32Base + QEI_O_INTEN) |= ui32IntFlags;
    }

    and file qei.h notes:

    " Values that can be passed to QEIEnableInts, QEIDisableInts, and QEIClearInts     //  cb1 note:  the names of these functions were "butchered" here!   QEIIntEnable  is the proper name.

    // as the ui32IntFlags parameter, and returned by QEIGetIntStatus.
    //
    //*****************************************************************************
    #define QEI_INTERROR 0x00000008 // Phase error detected
    #define QEI_INTDIR 0x00000004 // Direction change
    #define QEI_INTTIMER 0x00000002 // Velocity timer expired
    #define QEI_INTINDEX 0x00000001 // Index pulse detected

    And "your code" quite properly - follows the API's specification.     "MAP_QEIIntEnable(QEI0_BASE, (QEI_INTERROR | QEI_INTINDEX | QEI_INTDIR));

    So - this much establishes that you've done, "All w/in the user's power" - to attempt to enable the QEI_INTINDEX...    (you have set Bit_0 w/in QEIINTEN - as required)

    ***   Why then does the signal arriving @ "Pin QEI_Index" ... NOT trigger the QEI Interrupt?      The QEI module employs a "Filter Function" - you don't appear to employ it - might it "default" to, "Too severe a level" - thus causing your "QEI Index" signal (assumed pulse) to be missed?     Surely this proves,  "W/in the Realm!"     (and your "quick/eased" generation of varying pulse widths - tests/confirms!)

    As my earlier "diagnostic post" noted - the "IntIndex Bits" (Bit 0)  of both QEI Registers: QEIINTEN & QEIRIS must be set - for the, "QEI Interrupt to trigger - via an "Index signal's arrival."     

    The issue then must resolve to the,  "Failure for "Bit_0" - w/in Register QEIRIS - to Set - OR - if that bit does set - a  "FAILURE w/in the QEI Module's interrupt mechanism!"

    It is suspected that "Bit_0" w/in Register "QEIRIS" is set by the arrival of a pulse on its corresponding pin.     12_squared has assured that such pulse DOES arrive - has the "Setting of RIS Bit_0" been noted - in direct response - to that  "QEI Index signal's"  arrival?

    [edit]   Another read of the 4C123 manual reveals (SO sadly) : "When RESMODE is clear, the positional counter is constrained to the range [0:M], where M is the programmable maximum value.     The index pulse is ignored  by the positional counter in this mode."       It thus appears that,  "Heavy Handedness" (earlier suspected) is alive/well - and you are "doomed" to employ (likely) another GPIO pin - to achieve the "highly sought" (and herein "teased") Index Interrupt!

    Should fortune smile - very brightly - you may be able to "Save your board" by employing that  same "QEI Index Pin" (instead) config'ed as a GPIO - Divorced from QEI   (thus willing/able to  interrupt!) - having  "escaped" big brother's sometimes (questionable /i.e. LIKE-less) hand  -  AND  w/out requiring ANY alterations to your pcb!       Which would prove superb - for you (and similarly becalmed, others!)   

  • cb1_mobile said:

    Hello 12squared,

    Great job - unusual to note "two outsiders" - willing to invest (reasonable) time/effort - in the creation of such detail.     Again - I focused upon the '123 as we've never used (nor cared for) the '129.     And - it did NOT seem "unreasonable" that any vendor would seek to "re-use" tech aspects/methods - already proven.    Further - it was doubted (ok - guessed) that the QEI Module would be "much enhanced."

    The '129 is really quite similar to the '123, excepting the expected differences between various MCU models, and some slightly larger differences such as the much improved uDMA. (The '123 really has just about the strangest mechanism I've ever seen for software to rendezvous with DMA completion; the '129 has a much more "sane" system. But that's a story for another day.) Oh, and the system clock. That is much improved, as well.

    We have both the '123 and the '129. Soon I will test the '123's QEI Index behavior, though as we both suspect, it will most likely give the same behavior. (I've gone through both datasheets side-by-side and it appears that other than section numbers, page numbers, and the like, this section of the datasheet is a verbatim copy between the two ICs. For example there do not appear to be any extra bits in any of the registers, meaning bits that are reserved in one part and valid in the other.)

    cb1_mobile said:

    Now you write, "Your firm prefers to check the raw status."      And that's just NOT true!

    Apologies for the misunderstanding.

    cb1_mobile said:

         I (uniquely) presented the "Source Code" for your QEI Status check function - and  that code revealed the requirement for the "Check of RIS Bit_0.     As I reviewed the QEI Registers - I noted those 3 - which clearly dominated the QEI Module's Interrupt Handling.     And - that RIS bit, "Had to be set" for the Index Interrupt to occur.    (my earlier post presented those facts via "true copy" - directly from the '123 manual.

    As we've both discovered, we can check that RIS bit all day but if it never gets set, it never gets set!

    cb1_mobile said:

    Now your/firm's method of handling general interrupts is (almost) identical to ours/mine.     Again - I seized upon the RIS test w/in QEI Status Check - upon discovering that RIS_Bit_0 was required - for the index interrupt to be propagated.     (and such STILL - seems reasonable)

    I'm in agreement that use of a "Parallel connection" to the QEI Index pin - AND to a separate GPIO - may prove best.     Yet - thinking further - since the QEI_Index pin (presently) provides,  "Little (pardon) NO Value" ... Why maintain that connection - at all?    If you can free - or find - such "free GPIO pin" - employ it as your QEI Index interrupt trigger!

    Here is what I'm thinking. It seems to me that unless one employs the Index pulse to reset the position counter at each revolution, the Index pulse doesn't serve any other purpose in this QEI implementation. Velocity capture uses a timer and does not appear to "look at" the Index pulse, for example. The position counter counts only the A and B channels. So I don't see any harm in annulling this unhappy marriage between the QEI and its Index signal. In fact if we do make a board-level change, I think I will leave the Index pin exactly where it is and move the other signal elsewhere. This way, in the unlikely event that we do want that Index pulse for the QEI in the future, there will be the option to configure it as such. In fact, until now I've assumed that in order to use the pin as a GPIO, it must be removed from peripheral control. But perhaps that is not the case? I will need to run some tests to determine if I can have my cake and eat it too, by letting the QEI have its Index signal while using the GPIO port to trigger an interrupt. Unfortunately I'd still have to move the other time-critical signal to a different GPIO port.

    cb1_mobile said:

    ***  Kindly note that I've "retreated" (at least somewhat) from (that) below.     The "next arriving post" (one down) details...

    I'm wondering also if your, "Chosen Divorce of the Index signal from position counter(s) inter-action - is "legal?"     My understanding (surely NO standard) is that the "index Signal" (usually) identifies a "Starting or Ending" Position.     Thus - your MCU's "zeroing" of position counters - may prove VALID!     Yet another (reasonably) standard use of  QEI Index is to record, "Number of Revolutions" - and that's been lost - thus the "QEI Design Crüe" should be hauled in for "interrogation."     And it is noted that the  "FREE GPIO pin" may ably provide such Revolution Counting.     (along w/other items of your desire)

    If time allows I'll have staff run tests upon 2 other/alien ARM MCUs  (M4 & M7) tomorrow - and report.      (may be late in the day as several here have "worked w/me - all day - today.")

    Given what we've learned about the SPI Crüe (namely, that no one knows who they are (or perhaps no one is talking)), I don't think anyone knows who the "QEI Design Crüe" is. They may have relocated... to a country with no extradition treaty :-p
  • cb1_mobile said:

    Greetings,

    I'm still bothered by,  "Not having assisted in the resolution of this, "Failure of the Index Signal" to trigger the QEI Interrupt."     (Like you sense - this IS maddening!    And does NOT occur w/another's (180MHz M4!)      Arrived early today (pre-staff) to "dig deeper" - try to develop further insights.

    Earlier this morning I had the sense that the API QEI function (as suggested by friend Charles) was likely "flawed."    My (earlier) sense was that, "An Index Generated Interrupt "demanded" a Reset of the Position Counter" - and that's just  too "heavy handed" (like the banning of * LIKE *, here).     So - as the API's source code IS available - let's review:

    and:  " \b QEI_CONFIG_NO_RESET or \b QEI_CONFIG_RESET_IDX  specify if the position integrator should be reset when the index pulse is detected."     Thus - no such "heavy hand" was intended.   (such may have occurred - but it  was/is (unlikely) to be deliberate.)    Still of "grave concern" - this Position Reset (or not) "Should not be empowered to  "Enable/Disable"  the Index Interrupt!"    That's just  counter-intuitive - "wreaks" of  last ditch, implementation "hack" - does it not?     As a result - the proper "Index Generated Interrupt" is "held hostage" - and (as poster noted) this  impedes his "code freedom & progress!"

    I agree -- the Position Reset should not hold the Index Interrupt hostage. I would say that rather than a "last ditch implementation hack" it was probably caused by the assumption that unless one is using the Index pulse to reset the position counter, one could have no other conceivable uses for such a thing! Until I came along.

    But then again I would like to draw your attention to something unrelated, but similar, from the datasheet...

    Here in exhibit "A" we have Register 10: QEI Raw Interrupt Status (QEIRIS), offset 0x024 ...

    And the bit I would like to discuss is not INTINDEX, but INTERROR:

    Note the "Note" which reads: "The INTERROR bit is only applicable when..."

    Now let us look at INTINDEX in that same register description...

    If, as we have discovered, lack of the Position Reset option blocks the possibility of receiving the INTINDEX, then might it not be prudent for the description to say so, in a similar note to that shown for INTERROR? I mean, just so that others don't run into this same issue in the future?

    cb1_mobile said:

    Next - Did "you" do all that is required to, "Assist the QEI Index signal to Interrupt?"     And once more - arrives the API Source code - in answer:   (and indeed - you DID!)

    " void

    QEIIntEnable(uint32_t ui32Base, uint32_t ui32IntFlags)
    {
    //
    // Check the arguments.
    //
    ASSERT((ui32Base == QEI0_BASE) || (ui32Base == QEI1_BASE));

    //
    // Enable the specified interrupts.
    //
    HWREG(ui32Base + QEI_O_INTEN) |= ui32IntFlags;
    }

    and file qei.h notes:

    " Values that can be passed to QEIEnableInts, QEIDisableInts, and QEIClearInts     //  cb1 note:  the names of these functions were "butchered" here!   QEIIntEnable  is the proper name.

    // as the ui32IntFlags parameter, and returned by QEIGetIntStatus.
    //
    //*****************************************************************************
    #define QEI_INTERROR 0x00000008 // Phase error detected
    #define QEI_INTDIR 0x00000004 // Direction change
    #define QEI_INTTIMER 0x00000002 // Velocity timer expired
    #define QEI_INTINDEX 0x00000001 // Index pulse detected

    And "your code" quite properly - follows the API's specification.     "MAP_QEIIntEnable(QEI0_BASE, (QEI_INTERROR | QEI_INTINDEX | QEI_INTDIR));

    So - this much establishes that you've done, "All w/in the user's power" - to attempt to enable the QEI_INTINDEX...    (you have set Bit_0 w/in QEIINTEN - as required)

    ***   Why then does the signal arriving @ "Pin QEI_Index" ... NOT trigger the QEI Interrupt?      The QEI module employs a "Filter Function" - you don't appear to employ it - might it "default" to, "Too severe a level" - thus causing your "QEI Index" signal (assumed pulse) to be missed?     Surely this proves,  "W/in the Realm!"     (and your "quick/eased" generation of varying pulse widths - tests/confirms!)

    As my earlier "diagnostic post" noted - the "IntIndex Bits" (Bit 0)  of both QEI Registers: QEIINTEN & QEIRIS must be set - for the, "QEI Interrupt to trigger - via an "Index signal's arrival."     

    The issue then must resolve to the,  "Failure for "Bit_0" - w/in Register QEIRIS - to Set - OR - if that bit does set - a  "FAILURE w/in the QEI Module's interrupt mechanism!"

    It is suspected that "Bit_0" w/in Register "QEIRIS" is set by the arrival of a pulse on its corresponding pin.     12_squared has assured that such pulse DOES arrive - has the "Setting of RIS Bit_0" been noted - in direct response - to that  "QEI Index signal's"  arrival?

    You bring up a very good point here. We are not using filtering at this time, but perhaps I should play with the filter settings. Maybe we will discover that by enabling the "unnecessary" (?!?!) filter, the Index signal starts coming through?
  • Thank you - most excellent - you go SO VERY far beyond those (multitudes) who present here w/"Does Not Work!"    (as if it is the forum's fault!)

    Kindly revisit the END of my (latest) past post - I've added an EDIT - which I believe "Best Resolves" your issue:

    • allows an interrupt to occur - upon the arrival of your "Index Pulse"
    • involves NO/ZERO alterations to your pcb!   (why I "earn" big bucks!)

    Simply configure "QEI_Index_pin" AWAY from the misbehaving/teasing,  QEI's "Non-functionality."     Instead - set it as GPIO Input - you've one extra interrupt to deal with - but NO/ZERO board changes.

    And indeed - your point re: lack of uniformity in presenting,  "Critical Detail" (as you so well noted w/in "INTERROR") signals that the tech writer was "tiring" and/or beloved "marketing" cracked their whip!    (and WE suffer!)

    Crack staff is "keywording" for "goose"...     Once you've applied/implemented - might you be so good as to award "Verified" - to one (even several) of my "manifestos?"      Mercî.

  • cb1_mobile said:

    Thank you - most excellent - you go SO VERY far beyond those (multitudes) who present here w/"Does Not Work!"    (as if it is the forum's fault!)

    Kindly revisit the END of my (latest) past post - I've added an EDIT - which I believe "Best Resolves" your issue:

    • allows an interrupt to occur - upon the arrival of your "Index Pulse"
    • involves NO/ZERO alterations to your pcb!   (why I "earn" big bucks!)

    Simply configure "QEI_Index_pin" AWAY from the misbehaving/teasing,  QEI's "Non-functionality."     Instead - set it as GPIO Input - you've one extra interrupt to deal with - but NO/ZERO board changes.

    And indeed - your point re: lack of uniformity in presenting,  "Critical Detail" (as you so well noted w/in "INTERROR") signals that the tech writer was "tiring" and/or beloved "marketing" cracked their whip!    (and WE suffer!)

    Crack staff is "keywording" for "goose"...     Once you've applied/implemented - might you be so good as to award "Verified" - to one (even several) of my "manifestos?"      Mercî.

    Here is said edit:

    cb1_mobile said:

    [edit]   Another read of the 4C123 manual reveals (SO sadly) : "When RESMODE is clear, the positional counter is constrained to the range [0:M], where M is the programmable maximum value.     The index pulse is ignored  by the positional counter in this mode."       It thus appears that,  "Heavy Handedness" (earlier suspected) is alive/well - and you are "doomed" to employ (likely) another GPIO pin - to achieve the "highly sought" (and herein "teased") Index Interrupt!

    Should fortune smile - very brightly - you may be able to "Save your board" by employing that  same "QEI Index Pin" (instead) config'ed as a GPIO - Divorced from QEI   (thus willing/able to  interrupt!) - having  "escaped" big brother's sometimes (questionable /i.e. LIKE-less) hand  -  AND  w/out requiring ANY alterations to your pcb!       Which would prove superb - for you (and similarly becalmed, others!)   

    Ah, so "The index pulse is ignored  by the positional counter in this mode" but why, oh, why could they not allow the Index interrupt through? I am sure I read that statement in the datasheet, but it did not raise a gigantic red flag in my mind because the positional counter and the auxiliary interrupts provided by the QEI are, in my mind, two separate and distinct things. I said, "Perfect! The Index pulse will have no effect on the positional counter, which is exactly what I want, and look! There's a convenient Index interrupt!"
    Perhaps a better statement would have been: "The index pulse is completely ignored by the QEI peripheral in this mode." And the missing note in the register bit description for the QEIRIS, QEIISC, and QEIINTEN registers would be helpful as well.
    By the way, if we cannot have a LIKE button, then I propose a DISLIKE button, so that when someone breaks the bad news that the MCU was not designed to fulfill some arcane purpose to which we attempt to put it, we would be able to hit that DISLIKE button and make our displeasure known! :-p
    The solution is as you say, but does (in our particular case) require a slight board level modification. The Index input is henceforth being used as a GPIO pin. This does not require any board level change as you point out. However, the issue requiring the board level change, which I was hoping to avoid and which is why I started this thread in the first place, is another unrelated input which is currently routed to the same GPIO port and which therefore suffers from sharing an interrupt vector and (more importantly) interrupt priority with the QEI Index input. I need the Index interrupt to be low(er) priority and I need that other unrelated input's interrupt to be the highest priority in the system, as it has specific latency/jitter requirements. Had the QEI peripheral supported triggering an index interrupt without requiring the heavy handed goosing of position counter, this would not be an issue and both signals could exist on the same GPIO port without bothering each other, because the other signal's high priority interrupt would come from the GPIO port peripheral, while the QEI Index signal's low(er) priority interrupt would come from the QEI peripheral. Alas, the QEI does not bend to my will. Therefore, while no board level change is required to handle the Index pin to my liking, a board level change IS required to take that other signal currently located on the same GPIO port and move it to a different GPIO port, so that my "New and Improved!" handling of QEI Index will not cause problems with this other unrelated signal.
    Any questions?
    I will now award the coveted green boxes.
  • In the immortal words of the "king" (but uttered here/now w/sincerity) "Thank you - thank you very much."

    While, "Resetting the position counter(s)" automatically - via the QEI's Index signal - may be (somewhat) standard - your (and my) expectation & desire - to receive such "QEI Index" Interrupt  "freely, and w/out restriction" has been muted!      Even worse - was not  "One short sentence - "buried" w/in over 23 pages of  "QEI detail" -  (somewhat) lacking?    (while "devouring" user time/effort!)

    Earlier you noted,  "the assumption that unless one is using the Index pulse to reset the position counter,  one could have no other conceivable uses for such a thing!    Until I came along!"    

    Yet - might other uses abound (even if not immediately recognized) - here?    As one (quick) example - might setting of,  "Position Counter to an extreme value" (such count almost "never" to be reached) nicely enable/enhance the "KNOWN Travel of a Linear Actuator?"     (which would be "lost" - if the index signal - ALWAYS & ONLY - caused such (undesired) position counter Reset!)

    It would be interesting to "learn of" your intended use - as well...

  • cb1_mobile said:

    In the immortal words of the "king" (but uttered here/now w/sincerity) "Thank you - thank you very much."

    While, "Resetting the position counter(s)" automatically - via the QEI's Index signal - may be (somewhat) standard - your (and my) expectation & desire - to receive such "QEI Index" Interrupt  "freely, and w/out restriction" has been muted!      Even worse - was not  "One short sentence - "buried" w/in over 23 pages of  "QEI detail" -  (somewhat) lacking?    (while "devouring" user time/effort!)

    Earlier you noted,  "the assumption that unless one is using the Index pulse to reset the position counter,  one could have no other conceivable uses for such a thing!    Until I came along!"    

    Yet - might other uses abound (even if not immediately recognized) - here?    As one (quick) example - might setting of,  "Position Counter to an extreme value" (such count almost "never" to be reached) nicely enable/enhance the "KNOWN Travel of a Linear Actuator?"     (which would be "lost" - if the index signal - ALWAYS & ONLY - caused such (undesired) position counter Reset!)

    It would be interesting to "learn of" your intended use - as well...

    We are using the QEI for position and velocity feedback. The QEI on TM4C is really quite nice. In addition to position and velocity feedback, it provides error detection and ability to swap the A and B signals. All of these were important factors for us because this eliminates quite a few high priced ICs. The only shortcoming we've encountered is that we are unable to get that Index interrupt, but given all the other wonders this QEI can do, that is a small inconvenience.