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.

TM4C1294NCPDT: How to globally disable/enable interrupts?

Part Number: TM4C1294NCPDT


I found this question that is very close to mine, but it is locked and the answers didn't help me. So I've decided to make a new question.

I'd like to know (in C [DRM] or assembly) how to:

    - store the old Global Interrupt State

    - disable interrupts

    - restore the old Global Interrupt State back.

I come from the AVR world, where we do that saving SREG, clearing a bit and restoring SREG back. And that's all. But I didn't find out how to do the same on ARM Cortex M4F.

One answer in the thread I've linked talk about a driverlib's function: IntMasterDisable. I've tried to look at the code but I know very little about ARM assembly right now.

  • Look into the CMOS files. There should be a __disable_irq() and __enable_irq() routines. Or sim/rim

    In general, you shouldn't disable irq.

  • Danny F said:
    Look into the CMOS files.

    Or NOT!       Due to the (early) hour - poster (likely) intended the  API files.     (included w/TWare)

    In addition the, "Peripheral Driver Library User Guide" provides GREAT (and usually required) DETAIL - which often proves of immense help...

    He makes an excellent point that your, "Disabling Interrupts" must be,  "very well thought" - and employed (just) briefly & sparingly...

  • What are the CMOS files?
  • In the Peripheral Driver Library User Guide I found IntMasterDisable() and IntMasterEnable(). None of these functions is what I want.
  • Is it possible that, "What you seek" demands (somewhat) better (amplified) description. ARM has substantially automated "Interrupt Management" - which achieves minimal "latency" (12 cycles) - while enabling Interrupt Service Routines to be coded (entirely) in "C."

    With your being new to ARM - and your "Forum Search" unsatisfying - might a "deeper read" of the MCU's manual - or even ARM documents - cast a brighter/better light - upon your objective...

    It is (strongly) suspected that "ARM expertise" exceeded that of the limited "AVR world" - and that the developers of vendor's API - included "most all" Interrupt Functions - especially those deemed "necessary."
  • After reading a lot of pages in the datasheet I finally found out the register (and the bit) I need to change (I guess).
    It's the FAULTMASK bit in the FAULTMASK register. This bit is the equivalent of a Global Enable/Disable Interrupts switch.
    Please let me know if I'm really right, so I can mark this thread as resolved.
  • Do it like this:

    	bool DoNotReenable;
    
    	DoNotReenable = IntMasterDisable();
    
    	... do stuff here with interrupts off ...
    
    	if (DoNotReenable == false) {
    		IntMasterEnable();
    	}
    

  • I just noticed that you want direct register manipulation. I doubt if that would have any performance benefit over calling IntMasterDisable() ... IntMasterEnable() and furthermore I prefer easy-to-understand C APIs for maintainability, but if you insist, the answer is in the implementation of IntMasterEnable() and IntMasterDisable():

    //*****************************************************************************
    //
    //! Enables the processor interrupt.
    //!
    //! This function allows the processor to respond to interrupts.  This function
    //! does not affect the set of interrupts enabled in the interrupt controller;
    //! it just gates the single interrupt from the controller to the processor.
    //!
    //! \b Example: Enable interrupts to the processor.
    //!
    //! \verbatim
    //! //
    //! // Enable interrupts to the processor.
    //! //
    //! IntMasterEnable();
    //!
    //! \endverbatim
    //!
    //! \return Returns \b true if interrupts were disabled when the function was
    //! called or \b false if they were initially enabled.
    //
    //*****************************************************************************
    bool
    IntMasterEnable(void)
    {
        //
        // Enable processor interrupts.
        //
        return(CPUcpsie());
    }
    
    //*****************************************************************************
    //
    //! Disables the processor interrupt.
    //!
    //! This function prevents the processor from receiving interrupts.  This
    //! function does not affect the set of interrupts enabled in the interrupt
    //! controller; it just gates the single interrupt from the controller to the
    //! processor.
    //!
    //! \note Previously, this function had no return value.  As such, it was
    //! possible to include <tt>interrupt.h</tt> and call this function without
    //! having included <tt>hw_types.h</tt>.  Now that the return is a
    //! <tt>bool</tt>, a compiler error occurs in this case.  The solution
    //! is to include <tt>hw_types.h</tt> before including <tt>interrupt.h</tt>.
    //!
    //! \b Example: Disable interrupts to the processor.
    //!
    //! \verbatim
    //! //
    //! // Disable interrupts to the processor.
    //! //
    //! IntMasterDisable();
    //!
    //! \endverbatim
    //!
    //! \return Returns \b true if interrupts were already disabled when the
    //! function was called or \b false if they were initially enabled.
    //
    //*****************************************************************************
    bool
    IntMasterDisable(void)
    {
        //
        // Disable processor interrupts.
        //
        return(CPUcpsid());
    }
    

    And looking at CPUcpsie() and CPUcpsid() in C:\ti\TivaWare_C_Series-2.1.4.178\driverlib\cpu.c if you installed TivaWare to the default location, these are implemented in assembly. You can call these directly but I suggest just sticking with the TivaWare APIs for self-documented code and maintainability.

  • I'm sorry if I'm annoying you guys with my preference of DRM over TivaWare. I like TivaWare and I agree it is the correct resource one should use when writing production code. But I'm very interested in understanding how the processor works and how things works underneath TivaWare. I'm learning how to write code for Tiva C microcontrollers, but I'm also learning how they works.

    If I should be asking these questions on another forum, please tell me.
  • First, thank you for starting a new thread. When a thread has not been active for over a month it is closed. If additional questions come up, the proper thing to do is exactly what you did, create a new thread with a link to the old thread.

    I am not sure why IntMasterDisable() and IntMasterEnable() are not doing what you want. (You may need to clarify.) If you have a critical section of code that cannot be interrupted, a call to IntMasterDisable() disables all programmable interrupts and returns TRUE if interrupts were already disabled, FALSE if they were previously enabled. After the section of critical code, you call IntMasterEnable() if you need to re-enable the interrupts. IntMasterEnable() also returns TRUE if interrupts were disabled when this was called.

    If you want to see under the hood, page 96 of the TM4C1294NCPDT datasheet describes the PRIMASK register. These functions simply read and write to this Cortex-M4 register. If you need to read this register without writing it, there is a "function" uint32_t CPUprimask(void), in the driver library file cpu.c that returns the value of the PRIMASK register.

    There is additional information about the exception architecture of the TM4C1294 in section 2.5 of the datasheet.

  • The answer has been provided to you and you just need to follow through. Take a look at core_cmfunc.h in the cmsis pack.