#16 Interrupts Part-1: What are interrupts, and how they work

Поделиться
HTML-код
  • Опубликовано: 1 авг 2024
  • In this lesson, I'll finally tackle the subject of interrupts. Today, you will learn what interrupts are, and how they work.
    ------
    Resources:
    Companion web page for this video course:
    www.state-machine.com/quickstart
    GitHub repository for projects for this video course:
    github.com/QuantumLeaps/moder...
    Transcript of this lesson:
    www.state-machine.com/course/...
    Music credits:
    The background music comes from:
    www.bensound.com/royalty-free...
  • НаукаНаука

Комментарии • 90

  • @StateMachineCOM
    @StateMachineCOM  9 лет назад +38

    The Modern Embedded Systems Programming course has reached a very "round" milestone of 0x10 lessons. This milestone lesson provides an introduction to the very interesting subject of interrupts.

    • @jasurbekkhodjaev3728
      @jasurbekkhodjaev3728 9 лет назад +3

      Thank you very much for your efforts, I really enjoy your courses.

    • @silviu6229
      @silviu6229 5 лет назад

      You are awesome. Thank you very much.

    • @MuhammadAli-id2un
      @MuhammadAli-id2un Год назад

      Thank you a milllion times for your efforts Miro. You are a gem

  • @Sonex1542
    @Sonex1542 9 лет назад +5

    Thank you so much for putting these lessons on the inter tubes. This information is extremely valuable and very well explained. As a systems designer, I only wish I could work with you on a daily basis.

  • @krish2nasa
    @krish2nasa 7 лет назад +9

    Absolutely neat! I wish I could have taken these kind of lessons a long time ago. Thank you very much Samek

  • @embeddedprogramming9661
    @embeddedprogramming9661 5 лет назад +1

    Very comprehensive lesson. Finally somebody which explains the entire interrupt system form a practical perspective. I found out about interrupts the hard way:)) (just from a datasheet)

  • @adithyashankar6562
    @adithyashankar6562 4 года назад +1

    Crystal clear explanation. Thanks for your efforts

  • @MohammedNoureldin
    @MohammedNoureldin 9 лет назад +4

    Finally!! Thanks alot, I will watch it immediatly, and as always, waiting for the next one :) Thanks alot again

  • @iotsharingdotcom22
    @iotsharingdotcom22 Год назад +1

    the most excellent course. 10000000000 x thanks

  • @EngMazen
    @EngMazen 9 лет назад

    Yes it is very well explained , keep up and do not forget we are waiting for the next adventure :)

  • @philipgraybill811
    @philipgraybill811 3 года назад

    Fantastic! Thank you so much for these videos!

  • @04mfjoyce
    @04mfjoyce 2 года назад

    Great lesson, thank you very much!

  • @4four20twenty
    @4four20twenty 9 лет назад +3

    Your videos are awesome man thanks a lot

  • @davorjuric1609
    @davorjuric1609 9 лет назад

    Thank you dr. Samek! Davor

  • @glimmervoid1983
    @glimmervoid1983 4 года назад

    You are amazing, full stop.

  • @MohamedIbrahim-xi7vr
    @MohamedIbrahim-xi7vr 8 лет назад

    Amazing.. Thank you sir

  • @alexcipriani6003
    @alexcipriani6003 3 года назад

    this is amazing..thanks

  • @EOCORTES
    @EOCORTES 9 лет назад +3

    Hi Miro
    We were waiting since February, but never mind, do not forget us

  • @brettolson2605
    @brettolson2605 2 года назад +3

    These lessons are phenomenal, thanks Miro! When I added the inline function "__enable_interrupt();" line to my main.c, I received an Linker error stating no definition for "__enable_interrupt". I fixed the error by adding #include "Intrinisics.h". I'm using IAR 9.20.4. But interestingly, I opened Miro's workspace and did not need the include statement. Curious as to what workspace setting would be causing my error.

    • @StateMachineCOM
      @StateMachineCOM  2 года назад +2

      I'm glad that you like the lessons. The IAR header file is actually included at the top of main.c (at least in the project accompanying this lesson #16). The facility "__enable_interrupt()" is interesting, because it is a so-called "intrinsic" function that does not expand to a function call. Instead, the compiler expands it in-line thus avoiding the function call (and return) overhead. You can of course verify that by checking the disassembly in the debugger. When the header file is missing, the compiler does not recognize "__enable_interrupt()" and so it generates a regular function call to it. Then the linker tries to find this "function" and fails. --MMS

    • @brettolson2605
      @brettolson2605 2 года назад

      @@StateMachineCOM Thanks for the explanation! I was trying not to use any of your files as I went through the lessons; And yes, I now see the after checking your github. Thanks so much for continuing to respond and support others questions for these lessons!

  • @jamesmaxwell381
    @jamesmaxwell381 6 лет назад +1

    Thanks. I'm experiencing the same problem of @AbdulSattar. When I comment out `__enable_interrupt()`, the code still works and blinks like that PRIMASK is cleared by default. Why is this happening?

  • @mohamedoueslati462
    @mohamedoueslati462 6 лет назад

    Mr Miro do you recommand a book to well understand the start-up code and unterrrupts ?

  • @abdo199199
    @abdo199199 8 лет назад

    HI nice tutorials, but I have a question, I am using my own header file for the registers definition, so when I use an interrupt I need a file to be able to use the handler functions (ISR) and I am unable to use the IAR core files because they are compatible only with the IAR lm4f120h5qr.h file, what can I do now ?

  • @faizanqureshi9837
    @faizanqureshi9837 9 лет назад +3

    Finally new update.

  • @04mfjoyce
    @04mfjoyce 2 года назад

    Dr. Samek, thank you again for your lessons. I am interested in inspecting the __enable_interrupt() function. I would think it can be found in one of the .a files in the IAR Workbench arm/lib directory. I saw your example the other day of the ielfdump.exe tool for inspecting .o files. Is there a good way to find / inspect the contents of .a files? Or am I going in the wrong direction? Thank you very much for your time!

    • @StateMachineCOM
      @StateMachineCOM  2 года назад +1

      Actually no. The special functions like __enable_interrupt()/__disable_interrupt() cannot be found in any library. This is because they are *inlined*, meaning that the compiler inserts the code for such functions directly at the place of use. This means that the function does not exist as a separate entity. Such "inlining" of functions eliminates the function call overhead (branching into some code and branching back), because in that case the overhead is larger than the actual work to be done. Now, if you want to inspect the function __enable_interrupt(), the only way is to see the disassembly. For that, you can set a breakpoint at the function and run the code. When the breakpoint is hit, just see the disassembly. You will see something like "CPSIE I", and not "BL __enable_interrupt". --MMS

  • @ahmedbardiny9888
    @ahmedbardiny9888 Год назад

    When I used the simulator the Interrupt doesn't fire at all, any suggestions?

  • @MultiNova100
    @MultiNova100 6 лет назад

    Hi, Miro! Could you explain why the interrupt stack has to be 8-byte aligned? What are the constraints exactly that led to this requirement? What would happen if we don't align it? Thanks. E

    • @StateMachineCOM
      @StateMachineCOM  6 лет назад +1

      As mentioned in the video, the exception entry is highly optimized in the Cortex-M CPU and takes only some 12 cycles. It's very fast, if you consider that 8 registers are copied to the stack memory during those cycles. But the price for this speed is that the stack pointer must be aligned at 8-byte boundary. If the stack were not aligned, the hardware would add an extra "aligner" word to make it so (see the "aligner" in the exception stack frame in the TivaC data sheet).

  • @rolandoaguilera3114
    @rolandoaguilera3114 7 лет назад

    At 8min 48s, why the delay function doesnt get invoked on the disassembly view? Thanks!!!

    • @StateMachineCOM
      @StateMachineCOM  7 лет назад +1

      The delay() function *gets* called! You don't see it, because the debugger stops only at a breakpoint at the top of the loop. Please note that the delay incurred by the delay() function is only 1/2 second, which is about the time between hitting the breakpoint. --MMS

  • @user-fb2pf4tn5d
    @user-fb2pf4tn5d 11 месяцев назад +1

    I noticed that the SysTick_Handler is getting called even without __enable_interrupt(). Could this be because primask is cleared by default in the new Tiva C Series launchpad ?

    • @StateMachineCOM
      @StateMachineCOM  11 месяцев назад +2

      Actually, the ARM Cortex-M CPU comes out of hardware reset with PRIMASK cleared. The __enable_interrupt() call is just a precaution in case the startup code, some library code, or your own code happens to disable interrupts. In that case, an interrupt-driven application like the project for this lesson will appear completely "dead". For that reason, it is just safer to explicitly (re)enable interrupts to be sure. I hope this makes sense to you. --MMS

  • @michaelokeefe5949
    @michaelokeefe5949 3 года назад +1

    Just a heads up, after adding the __enable_interrupt() function to clear the PRIMASK register, my code would not link properly in IAR.
    After looking in the help section, I found out the header file "intrinsics.h" must be included to use __enable_interrupt(). Once I included
    the header file it compiled and linked properly.

    • @StateMachineCOM
      @StateMachineCOM  3 года назад +1

      Hi Michael. Thanks for watching. The system header files like , , and "tm4c_cmsis.h" *are* included in main.c. I don't know how you could miss this. Please check the project downloads at state-machine.com/quickstart

    • @michaelokeefe5949
      @michaelokeefe5949 3 года назад +1

      @@StateMachineCOM Ahh, I believe that's where the confusion was. I didn't have in my main.c file because I copied the code from the previous project to start project 16 instead of downloading from the website. Thank you for the response and the phenomenal work you do with this channel. Your content has been of great value to me as my computer science curriculum does not delve deeply into embedded systems.

  • @ABDULSATTARM
    @ABDULSATTARM 8 лет назад +1

    Dear Miro Samek,Today I downloaded this lesson (lesson 0x10) from state-machine.com. and run code it worked as expected. In the last of this presentation you said that final touch is to globally enable interrupt by clearing PRIMASK register. For this IAR EW provide intrinsic function __enable_interrupt(). But interesting thing is that I deleted that function and recompile and burn to tiva Launchpad, and interrupt is still firing without this function, would you please explain how is this happening. I tried to solve this mystery but could not. Thanks,Abdul Sattar

    • @MuhammadAbdullah-cj6nx
      @MuhammadAbdullah-cj6nx 4 года назад

      May be because you forgot to clear the flag...well its been 3 years now.!!!! you probably know it now anyways!

  • @johnmarkbatabat5408
    @johnmarkbatabat5408 4 года назад

    Hi. Thank you so much for this tutorial. Since the last lesson (lesson 15), I wasn't able to successfully flash a program to my launchpad anymore. Do you think I have done something wrong? Or is my launchpad already damaged?

    • @StateMachineCOM
      @StateMachineCOM  4 года назад

      Your TivaC board might be "locked up", but you can recover it. Please visit the companion web-page to this video course at www.state-machine.com/quickstart/ , where you will find the Application Note "Troubleshooting TivaC LaunchPad". This AppNote describes how to recover your locked-up TivaC LaunchPad. --MMS

    • @johnmarkbatabat5408
      @johnmarkbatabat5408 4 года назад

      @@StateMachineCOM wow. Thank you so much. That was cool troubleshooting indeed. More power.

  • @lemon6521
    @lemon6521 3 года назад

    I hadn't run the code on the board for a bit but decided to at the end of this lesson. When I did, the LED was blinking between blue and both blue and red, like it had been set up to do in previous lessons. Turns out this was because the LED_BLUE bit had never been cleared. It carried its value despite the board being off for a full day. Goes to show you can't assume initial values will be 0 (at least for AHB it seems). This makes me wonder though, would it be good practice to, for example, explicitly set LED_BLUE and LED_GREEN to 0 in your code if you're trying to only blink the red LED, so that you can avoid unexpected behavior?

    • @StateMachineCOM
      @StateMachineCOM  3 года назад

      This is strange and I would first check your code. But yes, it is considered a good practice to explicitly set or clear the GPIO lines to the desired initial state right after configuring them. --MMS

    • @04mfjoyce
      @04mfjoyce 2 года назад

      I had the same issue. I ended up resetting the board using the troubleshooting guide, and this seems to have done the trick...

  • @davorjuric1609
    @davorjuric1609 9 лет назад

    When configuring the SysTick why didn't you use the bitwise operators? Also in turning on the LED_BLUE before the delay loop you dont use them, but when toggling the LED_RED you use them (I understand why they are required for toggling). I am a bit confused on when to use them and when not.

    • @StateMachineCOM
      @StateMachineCOM  9 лет назад

      Davor Juric
      SysTick has only three registers (LOAD, VAL, and CTRL) and I was sure that they were not shared with the rest of the application, so they were simply written-to.
      The turning of LED on and off was done without the need to read the previous state of the LED, because you know that you want to turn it on or off.
      But toggling LED is fundamentally different. You want to change the current *state* of the LED, so you don't know if you want to turn it on or off. You want to toggle, so you must read the current state of the LED. Hence the use of the ^= bit-wise operator.

    • @davorjuric1609
      @davorjuric1609 9 лет назад

      Quantum Leaps, LLC I see. Thank you!

  • @bascik
    @bascik 9 лет назад +1

    If there is any way I can contribute for your excellent work please let me know!!! will you talk about PWM any time soon??

    • @StateMachineCOM
      @StateMachineCOM  9 лет назад +5

      *****
      I hope I will talk about PWM some day, but for now I still have a lot to cover about interrupts, race conditions, critical sections, context switch, etc. All of this leads directly to real-time kernels, for which I also received a lot of requests.
      As far as PWM is concerned, for now I would highly recommend this article:
      www.barrgroup.com/Embedded-Systems/How-To/PWM-Pulse-Width-Modulation
      --MMS

    • @bascik
      @bascik 9 лет назад +1

      Quantum Leaps, LLC Thank you!!

  • @davidk7212
    @davidk7212 6 лет назад +2

    In which file can I find the definition of __enable_interrupt()?

    • @StateMachineCOM
      @StateMachineCOM  6 лет назад +5

      The intrinsic function __enable_interrupt() is defined in the IAR file . This file is included indirectly through the following include chain: tm4c_cmsis.h -> core_cm4.h -> core_cmFunc.h -> cmsis_iar.h -> intrinsics.h. --MMS

    • @davidk7212
      @davidk7212 6 лет назад

      Thank you very much!

    • @krzysztofhuptys8104
      @krzysztofhuptys8104 6 лет назад +5

      I'm using IAR v. 8.30.1. I copied the entire 'lesson16' folder from the url you provide. I ran the workspace.eww file. Even though "tm4c_cmsis.h" is included, I still had to manualy include "intrinsics.h" because otherwise the function __enable_interrupts() was 'declared implicitly' and I received the compiler error.

  • @sharuns917
    @sharuns917 2 месяца назад

    what is the equivalent of the __enable_interrupt() in GNU ? For example when I am using say CCS instead of IAR ?

    • @sharuns917
      @sharuns917 2 месяца назад

      Found it in the video #19, we can use __enable_irq(); Thanks for moving the course to GNU!

    • @StateMachineCOM
      @StateMachineCOM  2 месяца назад +1

      In GNU-ARM you can use __disable_irq()/__enable_irq() (see also stm32f4-discovery.net/2015/06/how-to-properly-enabledisable-interrupts-in-arm-cortex-m/ ) --MMS

  • @km4hr
    @km4hr 7 лет назад

    The "__enable_interrupt()" function is specific to IAR? Is there a generic way to do this? Seems like something everyone needs to do. Is this series of videos funded by IAR?

    • @StateMachineCOM
      @StateMachineCOM  7 лет назад +3

      Yes, the __enable_interrupt() function is specific to the IAR compiler and other compilers for ARM might call this operation differently. For example, in lesson #19 I switch to the GNU-ARM compiler, where this function is called __enable_irq(). Both these intrinsic functions end up generating the same machine instruction "CPSIE i". In the future lesson 21 (still under development) I will demonstrate how to accomplish such operations generically. No: this video course is not funded by IAR. Why are you oozing so much negativity? --MMS

    • @keithevans6450
      @keithevans6450 7 лет назад

      Actually it's a great feature of this course that Miro changes development tools in #19 and walks through the impact on the project. He also provides the source code for his QP framework online if you want to take a look at that and see how he supports a wide variety of tools and devices.

    • @StateMachineCOM
      @StateMachineCOM  7 лет назад +3

      I plan to introduce the QP framework in the new group of upcoming lessons. This new group will cover topics like: foreground/background architecture, Real-Time Operating System (RTOS), object-oriented programming (yes, we will see how virtual functions work!), event-driven programming, state machines, and automatic code generation. The new lessons are coming soon. Stay tuned!

  • @High_Altitude_Observer
    @High_Altitude_Observer 9 лет назад

    Dr. Samek, the interrupt handler must be in a separate file because it's similar to a normal function in C? I tried to keep the interrupt handlers prototypes in a separate file and the handler itself in the main.c function and got a very strange error: Error[Pe065]: expected a ";" The problem is that this error points to the end of the definition and before the start "{", like this:
    here ------------>|
    void SysTick_Handler(void) { GPIOF_AHB->DATA ^= 0x04; }
    This seems to be a cryptic error. Defining an interrupt handler in main.c causes the function to be called twice?
    Thanks.

    • @StateMachineCOM
      @StateMachineCOM  9 лет назад +1

      High Altitude Observer
      Interrupt handlers are regular C functions in ARM Cortex-M. You can define these functions anywhere you like. You could put them in main.c or in any other module, such as bsp.c. The prototypes of all interrupt handlers are provided in the TM4C123GH6PM.h header file, so you should include this header in the module with the definition(s) of any interrupt handlers.
      I'm not sure why you get this error, but I would strongly recommend that you start with the working project provided with this lesson. Only after you make sure that you can build and run this project, I would apply any changes.

    • @High_Altitude_Observer
      @High_Altitude_Observer 9 лет назад

      Quantum Leaps, LLC
      Thank you very much for your response.

    • @HeliosFire9ll
      @HeliosFire9ll 8 лет назад

      +Quantum Leaps, LLC
      So what I'm reading here is that you can define your own interrupt handler without CMSIS? Because the key issues I'm having trouble with is how would the Interrupt call Systick_Handler? There seems to be no connection especially when you can define your own interrupt handler.

    • @StateMachineCOM
      @StateMachineCOM  8 лет назад +1

      +Helios Fire The connection is there. When the SysTick interrupt occurs, the hardware will jump to the address at offset 15 from the beginning of the vector table. You can place an address to your own function there. The only requirement of CMSIS is that you call this function SysTick_Handler. But you could just as well call it Fred (in which case you will not be compliant with CMSIS).

    • @HeliosFire9ll
      @HeliosFire9ll 8 лет назад

      OK, it's making a little bit more sense. But I have to add the function inside the CMSIS vector table first? I can call it "Fred", or "Cat" alsong as its in at offset 15 of the vector table in CMSIS?

  • @somefreedomfries
    @somefreedomfries 7 лет назад

    Has anyone tried to implement the IRQ for either of the pushbuttons? I have been trying to do it but I have had no success. I configured GPIOF as follows:
    SYSCTL->RCGC2 |= 0x20; // Disable clock gating of GPIOF
    SYSCTL->GPIOHSCTL |= 0x20; // Enable high speed bus
    GPIOF_HS->LOCK |= GPIO_KEY; // Unlock GPIOF
    GPIOF_HS->CR |= 0xFF; // Enable GPIOF commits
    GPIOF_HS->PUR |= 0x11; // Set GPIOF push button pins to pull-up
    GPIOF_HS->DIR |= 0x0E; // Set GPIOF LED pins to output
    GPIOF_HS->DEN |= 0x1F; // Set GPIOF pins to digital enabled
    // Configure interrupt for push buttons
    __enable_interrupt();
    __NVIC_SetPriority(30, 1);
    GPIOF_HS->IM &= 0x00; // Mask all GPIOF interrupts, preventing iterupts
    GPIOF_HS->IS |= 0x11; // Configure GPIOF push button pins for low level detection
    GPIOF_HS->IM |= 0x11; // Un-mask GPIOF push button interrupts, enabling them
    As far as I can tell this should enable the GPIOF IRQ when either of the push buttons is pressed, but when I set a break point to my handler function:
    void GPIOPortF_IRQHandler(void)
    {
    while(!GPIOF_HS->DATA_Bits[0x1] || !GPIOF_HS->DATA_Bits[0x10])
    {
    GPIOF_HS->DATA_Bits[LED_W] = LED_ON;
    printf("On
    ");
    }
    }
    The IRQ never executes. Any ideas?

    • @StateMachineCOM
      @StateMachineCOM  7 лет назад

      The GPIO interrupt handling will be shown in the new upcoming lesson #21 about foreground/background systems. --MMS

  • @manoranjanachary7330
    @manoranjanachary7330 7 лет назад

    can u solve this problem ??
    Design 8051 based system to count total number of persons getting-in and
    going-out with a single door through INT0 and INT1 and display the number of
    people in the Hall on P1. While generate 100KHz, 250KHz and 375KHz on P2.0,
    P2.1 and P2.2 respectively and transmitting persons info via UART at 4800bps.

  • @vinayakvader6176
    @vinayakvader6176 4 года назад

    In the video sound is low please increase sound level

  • @santoshshivgan6275
    @santoshshivgan6275 9 лет назад

    nic

  • @putinscat1208
    @putinscat1208 8 лет назад

    If a hardware interrupt occurs, does this pause the timer? Also, can the timer be used to do context switches to mimic threaded behavior? Any chance you will do a video on that?

    • @StateMachineCOM
      @StateMachineCOM  8 лет назад

      +Putins Cat The SysTick timer is not paused when interrupts occur. However, when the SysTick interrupt itself occurs, the SysTick counter is re-set to the original pre-programmed value. Regarding context switches, almost any interrupt can trigger them. I plan to talk about RTOS kernels and context switches in the future.

    • @putinscat1208
      @putinscat1208 8 лет назад

      Quantum Leaps, LLC Is this dangerous?
      asm("movs r10,#0");
      asm("ldr r11,[r10]");
      asm("mov sp,r11");
      asm("ldr r11,[r10,#4]");
      asm("bx r11");
      I am simulating an ARM with the IAR. During an interrupt, I want to handle it, and then call these instructions. I believe they restart ( clear the stack and then end up at the beginning of main ). Now my problem is, how can I initialize something just the first time and not during each reset? Should I put some secret value in some memory address? Is there a startup routine before main? Thanks.

    • @putinscat1208
      @putinscat1208 8 лет назад

      Quantum Leaps, LLC I was watching lesson 13. What I need is a way to clear the stack and go back to main I guess. While my code does this, it seems like if I follow lesson 13, my code will do a complete reset. I couldn't get the program to jump to main. Do you know the command that would allow that??
      This is for a robot about to go over a cliff situation. I need its behavior to restart instead of jumping back to whatever it was doing before interrupt. But, I don't want to rerun initialization code.

    • @StateMachineCOM
      @StateMachineCOM  8 лет назад

      +Putins Cat If you wish to reset the ARM Cortex-M CPU, the recommended way is to call the CMSIS function: NVIC_SystemReset().

    • @putinscat1208
      @putinscat1208 8 лет назад

      Quantum Leaps, LLC I do and I don't. I want to start main() over, but I don't want to reinitialize everything necessarily. I need to come back to a known state after an interrupt. How do you handle that typically?