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.

tm4c123gh6pm: IntMasterEnable() and PRIMASK - Are interrupts always enabled by default at system reset?

Part Number: TM4C123GH6PM

I just want to confirm, on the TM4C123 and TM4C129 parts, are interrupts enabled by default at system reset?

I ask because I come from other embedded platforms where interrupts are disabled by default and a global interrupt enable must be performed by software after other initialization is complete.

What prompts this question is that interrupts are being serviced even though code has not called IntMasterEnable(), so:

Is my understanding correct that the TivaWare function IntMasterEnable() sets PRIMASK to 0, which is already the case whether IntMasterEnable() is called or not because PRIMASK is 0 at power up?

Are there any other factors that enable or prevent the global servicing of interrupts? (besides PRIMASK and any individual interrupt enables)

And is there a rock solid way to prevent spurious peripheral interrupts occurring before software initialization is complete? I saw the sticky post on the TM4C forum which advises to first disable peripherals, however in the time between system reset and such code being called, C startup code including the C runtime library is being run, memory is zeroes, constructors are called, etc., and that leaves a window during which interrupts can occur anyway.

Thanks

  • twelve12pm said:
    What prompts this question is that interrupts are being serviced even though code has not called IntMasterEnable(),

    That's quite a good observation - firm & I have long so noted - yet it is clear that the, "interrupts are Disabled as default."     It is not logically sound to base such a claim upon the (apparent) "absence of execution" of the function "IntMasterEnable()" - your review of the code w/in that function should disclose the MCU Registers impacted.       Inspection of those registers then reveals the requirement for the call to that function - and/or the "necessity" to "make such a call."     (should there exist a function: "IntMasterDisable()" - and it has been called - then I suspect the call to your referenced function IS required...)

    In over ten years of use - firm/I have never noted those, "spurious peripheral interrupts occurring before software initialization is complete."     Many of our custom boards/implementations control (very) high power devices - and such "illegal - spurious interrupts" - would have (surely) been noted.      (or fate has been very kind to us...)

    Our experience has confirmed (to our & our clients' minds) that,  "Only after the peripheral interrupt has been specifically enabled" - and then properly triggered - may that specific interrupt launch...

  • We've had the VERY same issue during tests in the past! And yes, the results could have been quite "dangerous" if not fixed, and the behavior was a bit HARD TO DEBUG.

    So much that now ALL of our projects have interrupts disabled right after the clock setting:

    void main(void)
    {
        SystemUtilitiesInit(120000000); // Custom clock configurator
    
        MAP_IntMasterDisable();
        MAP_FPUEnable();
        MAP_FPULazyStackingEnable(); // Enable lazy stacking for interrupt handlers.

    I won't bother to research the "special" sequence of events that let the master int to remain alive, though. Just remember it happened!

    Bruno

  • It is my belief that poster Bruno - as his code surely reveals - speaks toward his results with a "different" MCU! (129x)

    Poster here & cb1 have described the operation & sensitivity of "4C123."

    If "results were quite dangerous" - as you report - why delay the call to "IntMasterDisable()?"

    it would prove (extremely) useful if you could "reproduce" such "Random, Interrupt firing code - without specifically enabling those peripheral interrupts - and that should be well w/in your capability as you MUST have documented such - as it was (just) reported as, "Quite Dangerous!"     (of course you'd document (anything) dangerous - would you not?)

  • May I ask why you do it after the clock setting and not before?
  • cb1_mobile said:

    yet it is clear that the, "interrupts are Disabled as default."

    Does the datasheet say that? Because at least the way I read it, it seems that the master interrupt is enabled by default (even if the individual peripheral interrupts are supposed to be disabled upon a System Reset, which is different than a Core Reset where they will happily remain enabled)

  • I believe that to be stated w/in Joseph Yiu's (ARM based) book and also noted upon ARM's site.

    If each/every interrupt was "primed & ready" - with NO "Gating/Controlling" interlock - upon "Power Up" (as both you & poster Bruno (appear) to believe) - havoc would result - would it not?

    As time & interest allow - I'll have staff search/find the "interrupt governing/enabling" statements from ARM.

    While anecdotal - "never" has the call to "IntMasterDisable()" been noted in (any) code example - provided by this vendor.     That's more than a "little" telling - is it not?

    As firm/I employ ARM MCUs from "four different vendors" - and have designed/built/test-verified and shipped in excess of 13K MCU based boards - "Never" have we noted "illegal entry into an ISR" - on any of our boards - from (any) ARM vendor...

    Dawns that, "IntMasterEnable()" (may) appear (camouflaged) w/in your, "Start-Up (or other) file."      Yet - that function-mechanism "alone" - should not prove "necessary & sufficient" to, "Prime all Interrupts for ready Launch!"

  • As stated previously - you raised a good point - and I present the following (culled this evening) from Joseph Yiu's book, "The Definitive Guide to the ARM Cortex - M3/M4."     I believe that the key extracts I've uncovered will answer the questions and confirm my earlier belief that, "Peripheral Interrupts are NOT (automatically) ENABLED" - when the MCU comes out of Reset.     It appears that the concept of, "Multiple, Interrupt Interlocks" work in tandem to prevent the (unwanted) generation of Peripheral Interrupts.   (again - as noted earlier)

    Yiu's book - Pg 30, 3.2.2 notes: "PRIMASK, FAULTMASK and BASEPRI registers are used to disable exceptions.    (interrupts)     The PRIMASK and BASEPRI registers are useful for temporarily disabling interrupts in timing-critical tasks."     A Table (3.2) is presented - and notes, "PRIMASK - a 1 bit register, when set - allows nonmaskable (NMI) interrupt and the hard fault exception - all other interrupts are masked.    The default value is "0" - which means that NO Masking is set.    

    Thus your findings - confirmed by my detailed search's failure to find, "IntMasterEnable()" w/in 4 different  projects!     I expanded my search to include CMSIS and ASM methods (to intercept writes to PRIMASK) as well - again, "none were found."      Thus - Yiu's description of PRIMASK'S (potential) enabling of interrupts proves (most) likely.     (all of my firm's code interrupted successfully - w/out (ever) having employed "IntMasterEnable().")

    Now - let's examine (my term - not in Yiu's book) "Multiple, Interrupt Interlocks."     These too must be properly configured for the Peripheral Interrupt signals to "fully propagate" from MCU pin to the NVIC Controller which launches the interrupt.      I present two examples - covering two different MCU peripherals (PWM & Timer) - in support of my belief.

    ROM_PWMIntEnable(PWM0_BASE, PWM_INT_GEN_0);
    ROM_IntEnable(INT_PWM0_0);

    ROM_TimerIntEnable(WTIMER0_BASE, TIMER_TIMA_TIMEOUT);
    ROM_IntEnable(INT_WTIMER0A);

    Note that the top call is linked to the specific Peripheral and to the type of interrupt.      (we may note this as "Peripheral_IntEnable().")      The 2nd call identifies & enables the specific interrupt mating to that Peripheral.

    Now - with that said/detailed - it is my belief that "If and only if" the following are all true will an, "Interrupt be launched."       (each of these 3 elements serve as an "Interrupt Gating" (AND Gate.))

    • PRIMASK must be "0"
    • the call to "Peripheral_IntEnable()" must have occurred
    • the call to "IntEnable()" must have occurred

    Thus revealed is a "Three Level" Interrupt Mechanism situated at: Processor Level (highest), Peripheral Level (middle), and Interrupt Source Level (lowest).

    The possible "defect" in this logic is the potential for the actions directed by both function calls to have "randomly"  occurred.     It should not be difficult to examine the associated registers and determine the likelihood of such "random, Perfect Storm" of bit settings - sufficient to launch an "illegal" interrupt.   

    Further probe of Yiu's book reveals another (particularly devilish) mechanism which may yield an "illegal" interrupt.      "Pending of an interrupt can happen even if the interrupt is disabled; the pended interrupt can then trigger the interrupt sequence when the enable is set later!     As a result, before enabling an interrupt, it could be useful to "check whether the pending register has been set!"   (you can clear the pending status before you enable that interrupt.)"       (highlights added by cb1)     Now - as the outside world signals (may) arrive prior to the "Full Enabling of Peripheral Interrupts" - this "pending of interrupts" may explain why poster Bruno noted "Danger."    (there exist API functions to check - and clear - such pending interrupts)

    In engineering school we were taught to, "Not rely upon "default behavior" - thus the regular & early use of "IntMasterDisable()" makes great sense.      However I remain (even more) convinced that my original assertion that, "Peripheral Interrupts are NOT (by default) FULLY Enabled" - even if "PRIMASK" defaults to "0" - has been proven correct.      (13K ARM MCUs (from multiple vendors) "in the field" (and ALL (only) legally interrupting) - add "real world fire-power" to that belief... 

  • Comes now that which I believe to be an especially efficient means to guard against (unwanted) interrupts.

    As shown here - the "SYSRESREQ" bit defaults to "0" upon emerging from Reset.      Writing a "1" to that bit - in "one fell swoop" - Resets the core AND all Peripherals - which should prove sufficient to prevent the generation of illegal interrupts...      This proves far superior to "Resetting multiple Peripherals - one at a time - and "hoping" that all were "remembered" and accepted the singular, sequential (thus slowed) cascade of Peripheral resets...

    Note that this operation is NOT the same as that brought about via, "IntMasterDisable()" - which in and of itself - appears NOT to be the "major safeguard" hoped for by some here.    Recall that interrupts may be "pended" - and thus when all interrupt levels are subsequently enabled (Processor, Peripheral, and Individual) - which (may) occur when "IntMasterEnable()" is later called - multiple interrupts (most pending) may together be enabled & unleashed!     The APINT Register - in conjunction w/"SYSRESREQ" - invoked just prior to the call to, "IntMasterEnable()" - appears to offer,  "the best & safest of all approaches!"    (achieving such "best/safest" by Resetting ALL Peripherals - which enables the invocation of  "IntMasterEnable()"  to be less, "Earth shattering!"     (i.e. all Peripheral & Individual Interrupts must (then) be properly and individually enabled - which insures freedom from a "Mass Launch" of multiple, "Pending" Interrupts!)

    This finding was gleaned from the "TM4C123" MCU manual - Pg 164, dated 12 June 2014.      (and that all triggered by an earlier, "deep dive" into Joseph Yiu's book - referenced earlier...)

  • twelve12pm said:
    cb1_mobile

    yet it is clear that the, "interrupts are Disabled as default."

    Does the datasheet say that?  

    Yes - while it takes a "bit of digging" I'm quite sure that it does!      Proof follows:       (a "true" yet augmented copy:  TM4C123 Manual,  12 June 2014, Pg 213)

    You must note: "Seven out of Eight" (standard Resets) ALL Reset the MCU's Peripherals - thus insuring that "Interrupts ARE Disabled as Default!"     (it is of course fair/proper to consider the multiple MCU Resets as the initiators of such "Default."   

    • Your opening post noted, "And is there a rock solid way to prevent spurious peripheral interrupts occurring before software initialization is complete?

    And ARM effectively anticipated such - the "Multiple Levels of Required Interrupt Enabling" indeed proves "solid."

    • That question was then followed w/the assertion: "the time between system reset and such code being called ... ...  and that leaves a window during which interrupts can occur anyway."

    And - as shown here - there is "NO SUCH Window" - that conclusion "avoids" mention - or full understanding - of the, "Multiple Levels of Required Interrupt Enabling" - which "shuts" (walls up) such window!

    As I wrote last evening - your finding of the "Master Processor Interrupt being "Enabled" - in and of itself - proves NOT SUFFICIENT to ENABLE any "Peripheral Interrupt."     Again - there is a "Three Level Peripheral Interrupt Interlock Mechanism" which properly gates "ALL such Peripheral Interrupts" - before they may be "reflected to the Master Processor Interrupt!"

  • @cb1_mobile, thanks for all your input. You've cleared up quite a bit for me here and I appreciate all the searching you've done. It sounds like I have to get my hands on a copy of Joseph Yiu's book, quickly!

    So we've learned:

    (1) PRIMASK is not the "global interrupt enable" that you'd find on other platforms, but rather is a "global interrupt disable" for implementing critical sections and the like. The distinction is important because now it makes sense that by default PRIMASK is not set and interrupts are not blocked.

    (2) The logic behind the need for two statements to enable a peripheral interrupt, like your example of ROM_PWMIntEnable() followed by ROM_IntEnable(), is to provide two levels of interrupt gating (PRIMASK is the third level), to prevent (or make extremely unlikely) the possibility of spurious interrupts.

    (3) Before enabling an interrupt, it is important to first clear the pending interrupt flag. (I suppose this should be true of any system.)

    I'm confused on the following point: You stated that setting SYSRESREQ in APINT would in one fell swoop reset the core and all peripherals. But I don't think you could do this in your startup code because resetting the core implies that the software would start executing from the beginning again, thus entering an endless loop where it never gets past the SYSRESREQ. It does seem, though, that this is how a "reboot" should be initiated from software, and not via VECTRESET which would leave the peripherals in a messed up state. I'll have to test this though.
  • My friend - I'd have thought that the depth, breadth & timeliness of pertinent findings would have met the standard of, "Verified Answer."

    I neither implied nor directed that, "setting SYSRESREQ in APINT" should be done w/in the start-up code. Instead - my belief is that such should occur "just prior" to the call to "IntMasterEnable()" and that is to follow an (earlier) call to "IntMasterDisable()." This method insures that the invocation of "IntMasterEnable()" will not FLOOD the processor w/interrupts - as each/every one will have to be (first) sequentially and "compound" enabled!
  • cb1_mobile said:

    My friend - I'd have thought that the depth, breadth & timeliness of pertinent findings would have met the standard of, "Verified Answer."

    Done.

    Thank you for taking the time and putting in so much effort to help a random stranger. I hadn't expected that my "simple" question would lead to so much research!

    cb1_mobile said:

    I neither implied nor directed that, "setting SYSRESREQ in APINT" should be done w/in the start-up code. Instead - my belief is that such should occur "just prior" to the call to "IntMasterEnable()" and that is to follow an (earlier) call to "IntMasterDisable()." This method insures that the invocation of "IntMasterEnable()" will not FLOOD the processor w/interrupts - as each/every one will have to be (first) sequentially and "compound" enabled!

    I think this will "reboot" the device. But I'll test it and let you know.
  • twelve12pm said:
    I think this will "reboot" the device. But I'll test it and let you know.

    That's pretty much guaranteed. If not there's a bug in the documentation I think.

    Robert

  • Thank you - much appreciated.     Note that you were thoughtful enough to "sense this issue" - and present your request skillfully - that's far from "random stranger!"    (more like "Tech friend - in the making...")

    And - you may be very much correct - a "reboot" may occur.    (yet - should not the MCU manual have "noted" such (momentous) a fact?)     [it was, "dead" silent!]
    I was attracted to the efficiency of that, "Single function call - able to Reset "all" Peripherals."     (which - to my mind - is far superior to the cascade of function calls required - to examine "all potentially enabled (especially interrupt pended) peripherals.")

    As time/biz demands allow - I'll review similar aspects as found upon "other" Cortex M4 & M7 devices my firm employs - and report...    

  • I think you've confused setting the SYSRESREQ bit with the software peripheral reset. The latter does not reset the core the former does according to the documentation.

    Robert
  • I don't think so - my objective was to, "Insure the reset of ALL Peripherals - ideally in ONE GO!" That WAS achieved!

    I've included a chart from the MCU manual (up 6-7 posts) which details....
  • cb1_mobile said:
    I don't think so - my objective was to, "Insure the reset of ALL Peripherals - ideally in ONE GO!" That WAS achieved!

    I've included a chart from the MCU manual (up 6-7 posts) which details....

    That's the table I'm referring to (also in my manual). It documents that SYSRESREQ resets the core (IE the micro is reset).

    Robert

  • Both you and the O.P. have (now) identified that fact. Yet - w/in the O.P.'s initial post - he expressed interest - if not concern - re (both) Core & Peripheral Resets. And the thrust of his issue was the fear that "illegal" interrupts were "likely."

    I have (properly) detailed that such illegal interrupts are "not" likely - and use of the "SYSRESREQ" bit w/in "APINT" - enables a Core & Peripheral Reset - which appeared of interest to our poster...
  • Yes, but you also suggested using SYSRESREQ during the init which would cause an infinite regress of resets.

    Robert

  • Yes - but do recall - I was "alone" in responding - presented many facts/findings - and this was "new knowledge" (still uncertain) for me as well...

    I did - repeatedly & correctly state - that such "spurious interrupts" would have to pass thru, "Three Levels of Interrupt Qualification" - thus the incidence of such  "spurious interrupts"   (our poster's care/concern)  was greatly diminished.

  • cb1_mobile said:

    Yes - but do recall - I was "alone" in responding - presented many facts/findings - and this was "new knowledge" (still uncertain) for me as well...

    I did - repeatedly & correctly state - that such "spurious interrupts" would have to pass thru, "Three Levels of Interrupt Qualification" - thus the incidence of such  "spurious interrupts"   (our poster's care/concern)  was greatly diminished.

    The spurious interrupt issue is laid to rest at this point thanks to the "three levels of interrupt gating" as explained by cb1_mobile. That cleared up much cloudiness in my mind surrounding this issue.
    I think the lesson here is this: The core is separate from the rest of the chip. Spurious interrupts will NOT be triggered after a normal power-up because both the core and the rest of the chip are coming out of reset simultaneously.
    But... if you restart the core by itself, without restarting the rest of the chip, you *could* get "spurious interrupts" (which in this discussion means: unexpected interrupts that occur before software startup/initialization). That's VECTRESET.
    So... if you want to "reboot" your micro, you should do it by means of a SYSRESREQ, NOT by a VECTRESET. That resets the whole chip, including core, peripherals, the whole shebang, and spurious interrupts won't occur.
    At least that's my understanding up to this point.
    I'm sure there are reasons why a VECTRESET might be desired. Perhaps there are circumstances where you want to restart the core while preserving state of peripherals (including interrupt gating) across a reboot. But determining how this is meant to be used will take more experience with these parts. To me, right now, a VECTRESET (or any reset of the core that doesn't also reset the rest of the chip) is something to be AVOIDED!!