Stop Wasting Time, Use AVR Timer Interrupts | Baremetal AVR Programming Tutorial

Поділитися
Вставка
  • Опубліковано 25 лис 2024

КОМЕНТАРІ • 90

  • @proxy1035
    @proxy1035 2 роки тому +17

    6:55 "ISR" is the "Interrupt Service Routine", ie the code that runs when the CPU gets an Interrupt.
    what you meant there is called an "IRQ" which is the "Interrupt Request" signal that goes to the CPU and causes it to run the ISR (if interrupts are enabled).

  • @nimcompoo
    @nimcompoo 2 роки тому +20

    Your videos are extremely helpful and educational. I can not express my appreciation for your work in words. Thank you very much. I have a small request, if it is possible please archive your twitch streams on youtube.

  • @aajpeter
    @aajpeter 2 роки тому +12

    As a convenience and to exemplify the behavior of the timer:
    LEDHZ = 1
    TCNT = 65535 - (F_CPU/1024)/LEDHZ

  • @stuartmcconnachie
    @stuartmcconnachie 2 роки тому +15

    Really you should use OCR1A and OCR1B registers for the timer value and set CTC mode for timer 1, rather than setting TCNT1=0 in the ISR.
    That will get the hardware to reset the timer to zero for you immediately it matches the programmed OCR value. As your code stands there is some latency between the interrupt being triggered and your ISR getting called, so you will not have “exactly” 15KHz (or whatever frequency division of the CPU clock you are aiming for). Worse, if other interrupts preempt your service routine, you will also introduce drift with a manual reset.

    • @alexloktionoff6833
      @alexloktionoff6833 Рік тому

      So if i want precise /*let's say for a watch*/ 1ms implementation i need to setup pre-scaler for 64 16000/64 and then implement s/w pre-scaler for 250 for exact 1ms, but it will load uC 250 times harder! Or setup pre-scaler for 1024 but then adjust, i.e. jump over every Nth tick. Do you have a good article/video about it?

    • @B1CL0PS
      @B1CL0PS Рік тому

      @@alexloktionoff6833 This video goes into a little more detail on using CTC mode (which should cause less drift ) ua-cam.com/video/cAui6116XKc/v-deo.html

  • @Frost_Byte_Tech
    @Frost_Byte_Tech 2 роки тому +5

    I'm a full stack developer who did embedded systems as well in varsity and enjoyed it, however due to the nature of my work I haven't been writing much C since college but this channel has gotten me practicing again and my skills have level up 10 fold..Thank you so much for your A - Grade content 🔥🔥keep it up and I'll keep recommending you 🙏 also can we get some esp8266 mesh network projects?

  • @CooperDuper3000
    @CooperDuper3000 2 роки тому +3

    Great Video, but i think you should always mention or show the specific part in the manual where you get the needen port and interrupt specifications from, its very hard to follow these low level stuff otherwise for beginners. Reading the documentation in the video would also teach your audience how to read these docs properly. Which is a higly needed skill to have if you are programming bare metal stuff.

  • @gregtasi
    @gregtasi 2 роки тому +3

    I was just searching for this for a school project! Great timing!

  • @henokvanni3831
    @henokvanni3831 2 роки тому +6

    i didn't know your channel, but i instantly loved the fact that you started the video saying: "low level GANG".

  • @ZenoTasedro
    @ZenoTasedro 2 роки тому +1

    Oh damn, your makefile... I recall taking some massive makefile for raw AVR programming and distilling it down to a nice hand written makefile like that and it was so much cleaner. But I lost that thing years ago and didn't want to recreate it 🤣, very glad to see you have a MUCH nicer starting place

    • @Henry-sv3wv
      @Henry-sv3wv Рік тому +1

      i would add phony but that's it.

    • @thebatchicle3429
      @thebatchicle3429 9 місяців тому

      @@Henry-sv3wv .PHONY: is a GNU extension. Not all Make implementations support it

  • @Awkwardzana
    @Awkwardzana 2 роки тому +10

    I don't know why I'm watching this, I have no clue what's even going on lol

  • @cornevanzyl5880
    @cornevanzyl5880 2 роки тому

    Wow reminds me of my university days learning how to program a Microchip in assembly.

  • @ljaworski88
    @ljaworski88 2 роки тому +1

    You can also use the CTC modes and set the OCR1A or IC(i forgot the rest of the register name) and use their corresponding ISRs to do this task without fussing around with the timer counter itself.

  • @vegansynths7757
    @vegansynths7757 2 роки тому +42

    Thanks for this. Can you please do this same thing with another processor, say an SAMD21 or RP2040? I have used up all 6 ISRs on the 328P and need more, but can't understand the datasheets of the Cortex M0+ processor.

    • @kayakMike1000
      @kayakMike1000 2 роки тому +5

      Yeah, took me a few weeks to figure this out. You can make a career outta the stuff you're trying to learn, keep it up! These cortex-m cores have dozens of hardware interrupts.

    • @norbertsmallegange6331
      @norbertsmallegange6331 5 місяців тому

      You need more than 6 isr???
      I am curious , why not possible? You CAN have more imho

    • @VivekYadav-ds8oz
      @VivekYadav-ds8oz 2 місяці тому +1

      At the expense of some delay, you can implement a tree of software ISRs. Like there's 1 ISR that gets called on multiple IRQs. And then you (somehow) switch on which interrupt was actually triggered, and call the function appropriately.

  • @duality4y
    @duality4y 2 роки тому

    i always learned to do it with timer compare that way you dont have to do the subtract but its just a different way of doing the same thing :)

  • @WistrelChianti
    @WistrelChianti 2 роки тому

    Thanks I have some code I did ages back using the timer registers but I don't think I understood what I was doing as well as I do now with your explanation. Still... it did at least work!

  • @alejandrojara7303
    @alejandrojara7303 3 місяці тому

    another way to the same would be to use the output compare registers and then listen for an Output Compare Match interrupt instead of listening for the overflow of the counter.

  • @好多鱼-l4n
    @好多鱼-l4n 2 роки тому

    Cool baremental programming technique! I think one the pros of interrupt-driven is power save, maybe you can upload another video to explain it.

  • @PASTRAMIKick
    @PASTRAMIKick 2 роки тому

    I used to program the 2560 in the old AVR Studio, its simulator was pretty good and useful, but nowadays I do prefer to program it like this.

  • @ruffrecords
    @ruffrecords 2 роки тому +3

    It would be worth including a comment about how the interrupt flag gets cleared. In many micros you have to do it explicitly but I am guessing the Atmel clears it automatically when you reload the timer. A common mistake used to be forgetting to clear the interrupt flag.

    • @NormanNodDunbar
      @NormanNodDunbar 2 роки тому +1

      The AVR automatically clears interrupt flags when the ISR is executed. You only need to manually cler them if you are not using interrupts.
      Cheers,
      Norm.

    • @NormanNodDunbar
      @NormanNodDunbar 2 роки тому +1

      Another common mistake is forgetting to clear the interrupt flag before enabling interrupts.
      If the stimulus to trigger the interrupt is detected by the hardware, the flag will be set and will remain set even if the stimulus goes away. When interrupts are subsequently enabled, the ISR will trigger even though the interrupt stimulus is no longer present.
      Cheers,
      Norm.

  • @SaliyaRuchiranga
    @SaliyaRuchiranga 2 роки тому

    great tutorial, hope to see more like this !!

  • @KkkKkk-re9il
    @KkkKkk-re9il Рік тому +1

    You should have also put the CPU into one of the sleep states to conserve power.

  • @TokyoScarab
    @TokyoScarab Рік тому

    Great vid, but I did notice one problem, the Egyptian Braces in your int main :P

  • @NormanNodDunbar
    @NormanNodDunbar 2 роки тому +4

    Instead of XORing PORTB, PIN5 to toggle, just write a 1 to PINB5. That will toggle for you.
    Cheers,
    Norm.

    • @7alfatech860
      @7alfatech860 2 роки тому

      Quite so. Though that may be an Atmel quirk? His code appears easier to understand.

    • @NormanNodDunbar
      @NormanNodDunbar 2 роки тому +4

      @@7alfatech860 yes indeed, it's Atmel. Input pins use the PORT register to enable pull ups, output pins use PIN register to toggle. It's all in the data sheet.
      Cheers,
      Norm.

    • @PASTRAMIKick
      @PASTRAMIKick 2 роки тому +3

      yeah the Atmel datasheets are really good, super thorough, detailed and easy to read as well.

  • @querela92
    @querela92 2 роки тому +5

    Nice, easy to understand. I would still suggest adding more comments about the register assignments for easy lookup but the video is short enough to rewind.
    Wouldn't it make sense to also use a macro since we were the same code twice for TCNT1?
    (In the end both the compiler might precompute the constants into a single value so this would only be for the human reader.)
    On the other hand, the TCNT1 assignment in main() is basically setting the first delay. Can we just set it to 65535, as basically an almost zero delay to just not worry about it? Or is there a chance that the timer will tick "too fast" in the background if there is more setup code in main() before the sei() call, so the initial value will overflow and need to increment the total amount before the first "interrupt routine" is being run?

  • @diegopinilla3431
    @diegopinilla3431 2 роки тому

    Nice video, keep it up!

  • @wm8123
    @wm8123 2 роки тому

    Instead flooding the CPU with "push" and "pop" with using interrupts, you should start coding in a sequential multitasking style. Using a few interrupts is no deal for most conditions. But using interrupts for every single task you have ends up in wasting very very much time executing "push"s and "pop"s. Just have a look at the assembly output from the compiler.
    You are right, sleeping the CPU with delay() is waste of time, but using interrupts as a global task worker results in a lot of time waste as well.

  • @deokureta108
    @deokureta108 2 роки тому +1

    Hello this was a very informative video but i would like to know if there is any difference between bare metal AVR C an CMSIS in the case of ARM processor?

  • @emoutraspalavras-marloncou4459
    @emoutraspalavras-marloncou4459 2 роки тому

    thank you so much. if I want to have three timers so what part of the code will repeat? i suppose I would have to change 1 with 2 and 3 in TCNT... and also an ISR should be set for every timer. could you make a bare metal programming video on I2C and another on U(S) ART for the Arduino chip?

  • @johndraper8197
    @johndraper8197 2 роки тому

    Like to see the same type of info for ESP32 boards

  • @edgeeffect
    @edgeeffect 2 роки тому +1

    Bear... metal (laughs)
    I do that infinite loop as `loop: rjmp loop` .... always want to "dare" C programmers to use a goto. ;)

  • @joseph9915
    @joseph9915 2 роки тому +1

    Thanks for the helpful video.
    2 things I had to google:
    Do CS10,CS11&CS12 change a lot for different avr chips? Else wouldn't TCCR1B = 0b101; be clearer? maybe that is just me.
    Is using _BV() to show different methods to do the same thing or would (1

    • @LowLevelTV
      @LowLevelTV  2 роки тому +1

      They may be the same value across boards, but you want to avoid using magic numbers like that in the event there IS a change and now your code isn’t portable.
      Also using defines makes your code more readable.

    • @Henry-sv3wv
      @Henry-sv3wv Рік тому

      i just grep -r CS10 *
      in avr/include
      to see that CS10 is bit 0 on all chips
      ---> tested the rest, bit positions are the same

  • @MikeNugget
    @MikeNugget 2 роки тому

    Buildroot & Flutter app tutorial, please 🙂

  • @SWAGCOWVIDEO
    @SWAGCOWVIDEO 2 роки тому +1

    If you had something like a TL866 chip programmer and the 328p was removable, could you just dump the hex file directly onto the microcontroller?

    • @Henry-sv3wv
      @Henry-sv3wv 2 роки тому +1

      It's not an (e)eprom, so not the TL866.
      But you can get a dedicated progger.
      cheap ones are based on usbasp.
      there is also an arduino sketch to turn an arduino into an isp prog device.
      avr isp --> AVR In System Programmer
      (using ISP you don't need to remove the avr out of the circuit)
      (you also use avrdude for flashing)
      more expensive: AVR HV-Programmer
      (to rescue a chip from wrong fuse settings (like if you disable reset pin to gain extra IO you can't program it anymore with isp --> bricked without HV Programmer to change fuse settings)

    • @SWAGCOWVIDEO
      @SWAGCOWVIDEO 2 роки тому

      @@Henry-sv3wv Good to know - thanks

  • @duality4y
    @duality4y 2 роки тому

    would it be possible to explain this for arm ?

  • @eFeXuy
    @eFeXuy 2 роки тому

    When I wrote my space invaders rip-off on the AT328 I got a stable framerate by using this interrupt by putting at the end of the frame loop a _while(variable){ }; variable=1;_ and then in the interrupt I set variable=0, so I would just loop there until the interrupt kicks in.
    I don't know if that's the best way to do it tho.

    • @williamdrum9899
      @williamdrum9899 2 роки тому

      That's the same way I do it actually. I don't think there really are any better methods that aren't specific to any particular CPU

  • @ME-rv1pw
    @ME-rv1pw 2 роки тому +1

    Is there a reason you use _BV() sometimes but not other times?

  • @asolovets
    @asolovets Рік тому

    Is it possible to put the CPU to sleep instead of spinning an infinite loop?

  • @EmbeddedEnigma
    @EmbeddedEnigma 2 роки тому +1

    after using stm32, AVR just feels so underwhelming in every thing :P

    • @Henry-sv3wv
      @Henry-sv3wv 2 роки тому +1

      i just miss more RAM to have more fun with AVR

  • @firedawn
    @firedawn 2 роки тому +1

    Your github repository seems to be missing some code in main() ;-)

  • @foxfyre3600
    @foxfyre3600 2 роки тому +1

    I didn't know it was on 16-bit overflow condition, I thought the timers counted down and on zero the ISR was called. Thanks for this!

  • @cernejr
    @cernejr 2 роки тому

    I am having trouble with flashing the code using avrdude: avrdude: stk500_recv(): programmer is not responding. I am on Linux Mint, 64 bit.

    • @cernejr
      @cernejr 2 роки тому

      Arduino IDE also could not upload. I bought a Mega, that one works fine with Arduino IDE. Tomorrow I plan to try this tutorial using the Mega.

    • @canuckprogressive.3435
      @canuckprogressive.3435 Рік тому +1

      @@cernejr Arduino IDE won't work on my Linux Mint either. It installed but when I click on it the window just flashes onto the screen for an instant. Good thing I did a dual boot so I can go into my old Win7 install and use it from there. I never use Arduino code but just type AVR C into Arduino IDE.

    • @Henry-sv3wv
      @Henry-sv3wv Рік тому

      sudo avrdude -v -p atmega328p -c arduino -P /dev/ttyUSB0 -b 115200 -D -U flash:w:firmware.hex:i

    • @Henry-sv3wv
      @Henry-sv3wv Рік тому

      (if you use an arduino or 328p with installed arduino bootloader)
      else some other command with usbasp over isp or whatever you use

  • @shvideo1
    @shvideo1 Рік тому

    What increments TCNT1?

  • @Handelsbilanzdefizit
    @Handelsbilanzdefizit 2 роки тому

    How to compile Rust for Risc-V?

    • @Henry-sv3wv
      @Henry-sv3wv 2 роки тому +1

      you have to hit trees with a rock first and get some stuff to compile a base in rust. then you can attak other players.

  • @JordyDevrixOfficial
    @JordyDevrixOfficial Рік тому +1

    You lost me at 8:57 I don't get how that becomes a second

    • @Henry-sv3wv
      @Henry-sv3wv Рік тому +2

      He set timer clock= F_CPU/1024 = 15625 Hz
      That means after 15625 clocks one second of time passed.
      Timer1 is a 16bit counter and it will overflow to zero after count value: 65535 (2^16-1) (and then cause the enabled overflow interrupt)
      So if you preload the counter value to
      counter_MAX_VALUE+1-clock_counts_for_a_second_passed:
      65535+1-15625 = 2^16 - 15625 = 2^16 - (F_CPU/1024) it will overflow
      after a second. ( and i think we need to add +1 to make it right because overflow from 65535 to 0 will also consume a clk of time )
      he did make a "one off" error i think

    • @JordyDevrixOfficial
      @JordyDevrixOfficial Рік тому

      @@Henry-sv3wv yo thanks alot mate 👍

  • @SamMcClear
    @SamMcClear 25 днів тому

    Has anyone had any luck getting avr dude running in wsl ?

  • @zapiton
    @zapiton 2 роки тому

    I need deeper knowledge about atmega 328p

    • @NormanNodDunbar
      @NormanNodDunbar 2 роки тому +2

      The data sheet has everything you'll ever need, but it's a difficult read!
      Arduino Software Internals is a good book, by Norman Dunbar 😉, and explains both the Arduino Software and how it works, the ATmega328 hardware, timers, etc, and how the software talks to the hardware.
      It comes highly recommended by Ralph S Bacon on his You Tube channel.
      Cheers,
      Norm.

    • @zapiton
      @zapiton 2 роки тому +1

      @@NormanNodDunbar ty, I'll read it. I mean channel is called low level learning, but in this video compiler is used. compilers r too easy😅 how about writing code in hex redactor?
      ofc, I'm kidding, but in every joke there is a part of truth😅

    • @canuckprogressive.3435
      @canuckprogressive.3435 Рік тому +1

      If you are still struggling try Human Hardrive YT channel.

  • @ArthurTucker
    @ArthurTucker 2 роки тому

    Is your Sublime Text Unregistered?? 🧐

  • @ugagnskraake
    @ugagnskraake 2 роки тому

    Should it be "by using Arduino Timer Interrupts"?

    • @canuckprogressive.3435
      @canuckprogressive.3435 Рік тому +1

      Not really. This is pure avr C programing without the dumbed down Arduino code.

    • @Henry-sv3wv
      @Henry-sv3wv Рік тому

      there are different arduino boards, but the hardware timer of the physical microcontroller chip is providing the timer interrupt and uno does have the ATmega328 mcu

  • @metamud8686
    @metamud8686 2 роки тому

    great, now go to sleep() instead of while(1) nop'ing

  • @doodocina
    @doodocina Місяць тому

    stop wasting time - stop using avr 😂😂😂

  • @pokemettilp8872
    @pokemettilp8872 2 роки тому

    Second