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

  Рет қаралды 43,883

Low Level Learning

Low Level Learning

2 жыл бұрын

Programming embedded systems is difficult. You need to make the most out of the limited processing power you have. The worst thing you could do is waste precious processing cycles by sleeping, waiting for an event to occur. Instead, you should be using INTERRUPTS. Interrupts are a great way for a device to be pre-empted and ran when an event or timer triggers.
In this video, I'll teach you how to write code that produces a timer interrupt, in baremetal AVR C, without using the Arduino API or libraries.
🔥🔥🔥 SOCIALS 🔥🔥🔥
Low Level Merch!: www.linktr.ee/lowlevellearning
Follow me on Twitter: / lowlevellearni1
Follow me on Twitch: / lowlevellearning
Join me on Discord!: / discord
Code from this video: github.com/lowlevellearning/a...
Register Documentation: onlinedocs.microchip.com/pr/G...

Пікірлер: 94
@proxy1035
@proxy1035 2 жыл бұрын
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).
@aajpeter
@aajpeter 2 жыл бұрын
As a convenience and to exemplify the behavior of the timer: LEDHZ = 1 TCNT = 65535 - (F_CPU/1024)/LEDHZ
@nimcompoo
@nimcompoo 2 жыл бұрын
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.
@LowLevelLearning
@LowLevelLearning 2 жыл бұрын
Glad you like them!
@vegansynths7757
@vegansynths7757 2 жыл бұрын
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 жыл бұрын
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 Ай бұрын
You need more than 6 isr??? I am curious , why not possible? You CAN have more imho
@henokvanni3831
@henokvanni3831 2 жыл бұрын
i didn't know your channel, but i instantly loved the fact that you started the video saying: "low level GANG".
@LowLevelLearning
@LowLevelLearning 2 жыл бұрын
🤓
@Frost_Byte_Tech
@Frost_Byte_Tech 2 жыл бұрын
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?
@gregtasi
@gregtasi 2 жыл бұрын
I was just searching for this for a school project! Great timing!
@LowLevelLearning
@LowLevelLearning 2 жыл бұрын
I got you!
@foxfyre3600
@foxfyre3600 2 жыл бұрын
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!
@stuartmcconnachie
@stuartmcconnachie 2 жыл бұрын
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 11 ай бұрын
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 10 ай бұрын
@@alexloktionoff6833 This video goes into a little more detail on using CTC mode (which should cause less drift ) kzfaq.info/get/bejne/maelnJlilpy8e5c.html
@ljaworski88
@ljaworski88 2 жыл бұрын
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.
@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!
@deokureta108
@deokureta108 2 жыл бұрын
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?
@CooperDuper3000
@CooperDuper3000 Жыл бұрын
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.
@user-st7io9kd9h
@user-st7io9kd9h 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.
@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?
@SaliyaRuchiranga
@SaliyaRuchiranga 2 жыл бұрын
great tutorial, hope to see more like this !!
@cornevanzyl5880
@cornevanzyl5880 2 жыл бұрын
Wow reminds me of my university days learning how to program a Microchip in assembly.
@ZenoTasedro
@ZenoTasedro 2 жыл бұрын
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 Жыл бұрын
i would add phony but that's it.
@thebatchicle3429
@thebatchicle3429 5 ай бұрын
@@Henry-sv3wv .PHONY: is a GNU extension. Not all Make implementations support it
@lis6502
@lis6502 2 жыл бұрын
Being raised on 6502 and watching SEI for actually enabling interrupts makes me feel dizzy a bit ;p But video is as clear as it could be, guess that anyone who understands bitwise C operators and concept of interrupt handler will take benefit from this video, thanks!
@williamdrum9899
@williamdrum9899 2 жыл бұрын
Same here haha. I actually prefer 6502 to C for the most part since it lets me do what I want 100% of the time (though admittedly C is very good at writing complex equations that would be awful in assembly)
@klaus2t703
@klaus2t703 2 жыл бұрын
@@williamdrum9899 You compare apples to oranges. 6502 is a microcontroller, while C is a language. You can combine 6502 with C and ASM and you can combine AVR with C and ASM. I´m also from the 6502 era, but an AVR is way more powerful, rich of periferals...
@Henry-sv3wv
@Henry-sv3wv 2 жыл бұрын
coming from arduino trying to learn c64 stuff irritates me that sei is supposed to turn it off -.- i prefer c
@williamdrum9899
@williamdrum9899 2 жыл бұрын
I meant ASM when I said 6502 my bad
@williamdrum9899
@williamdrum9899 2 жыл бұрын
Is arduino an ARM cpu? I don't remember if ARM even has a dedicated SEI/CLI. Pretty sure it doesn't (from what I remember about the GBA you had to write to a hardware port)
@LemmeAsk
@LemmeAsk 2 жыл бұрын
I don't know why I'm watching this, I have no clue what's even going on lol
@norbertsmallegange6331
@norbertsmallegange6331 Ай бұрын
Then you should start coding
@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 :)
@duality4y
@duality4y 2 жыл бұрын
would it be possible to explain this for arm ?
@diegopinilla3431
@diegopinilla3431 2 жыл бұрын
Nice video, keep it up!
@asolovets
@asolovets Жыл бұрын
Is it possible to put the CPU to sleep instead of spinning an infinite loop?
@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
@TokyoScarab
@TokyoScarab 11 ай бұрын
Great vid, but I did notice one problem, the Egyptian Braces in your int main :P
@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.
@querela92
@querela92 2 жыл бұрын
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?
@SWAGCOWVIDEO
@SWAGCOWVIDEO 2 жыл бұрын
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 жыл бұрын
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
@josephchamness9915
@josephchamness9915 2 жыл бұрын
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
@LowLevelLearning
@LowLevelLearning 2 жыл бұрын
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
@ME-rv1pw
@ME-rv1pw Жыл бұрын
Is there a reason you use _BV() sometimes but not other times?
@LowLevelLearning
@LowLevelLearning Жыл бұрын
I am forget
@Handelsbilanzdefizit
@Handelsbilanzdefizit 2 жыл бұрын
How to compile Rust for Risc-V?
@Henry-sv3wv
@Henry-sv3wv 2 жыл бұрын
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.
@ruffrecords
@ruffrecords 2 жыл бұрын
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 жыл бұрын
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 жыл бұрын
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.
@KkkKkk-re9il
@KkkKkk-re9il Жыл бұрын
You should have also put the CPU into one of the sleep states to conserve power.
@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 Жыл бұрын
@@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?
@LowLevelLearning
@LowLevelLearning Жыл бұрын
Internal timer hardware.
@NormanNodDunbar
@NormanNodDunbar 2 жыл бұрын
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 жыл бұрын
@@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 жыл бұрын
yeah the Atmel datasheets are really good, super thorough, detailed and easy to read as well.
@johndraper8197
@johndraper8197 2 жыл бұрын
Like to see the same type of info for ESP32 boards
@MikeNugget
@MikeNugget 2 жыл бұрын
Buildroot & Flutter app tutorial, please 🙂
@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.
@firedawn
@firedawn Жыл бұрын
Your github repository seems to be missing some code in main() ;-)
@edgeeffect
@edgeeffect 2 жыл бұрын
Bear... metal (laughs) I do that infinite loop as `loop: rjmp loop` .... always want to "dare" C programmers to use a goto. ;)
@ArthurTucker
@ArthurTucker 2 жыл бұрын
Is your Sublime Text Unregistered?? 🧐
@EmbeddedEnigma
@EmbeddedEnigma 2 жыл бұрын
after using stm32, AVR just feels so underwhelming in every thing :P
@Henry-sv3wv
@Henry-sv3wv 2 жыл бұрын
i just miss more RAM to have more fun with AVR
@zapiton
@zapiton 2 жыл бұрын
I need deeper knowledge about atmega 328p
@NormanNodDunbar
@NormanNodDunbar 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 жыл бұрын
@@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 Жыл бұрын
If you are still struggling try Human Hardrive YT channel.
@ugagnskraake
@ugagnskraake 2 жыл бұрын
Should it be "by using Arduino Timer Interrupts"?
@canuckprogressive.3435
@canuckprogressive.3435 Жыл бұрын
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
@JordyDevrixOfficial
@JordyDevrixOfficial Жыл бұрын
You lost me at 8:57 I don't get how that becomes a second
@Henry-sv3wv
@Henry-sv3wv Жыл бұрын
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 👍
@metamud8686
@metamud8686 Жыл бұрын
great, now go to sleep() instead of while(1) nop'ing
@pokemettilp8872
@pokemettilp8872 2 жыл бұрын
Second
rust runs on EVERYTHING (no operating system, just Rust)
18:10
Low Level Learning
Рет қаралды 350 М.
Timer Interrupt ISR + Examples | Arduino101 | Set Registers & Modes
16:13
KINDNESS ALWAYS COME BACK
00:59
dednahype
Рет қаралды 163 МЛН
THEY made a RAINBOW M&M 🤩😳 LeoNata family #shorts
00:49
LeoNata Family
Рет қаралды 42 МЛН
Alex hid in the closet #shorts
00:14
Mihdens
Рет қаралды 8 МЛН
you will never ask about pointers again after watching this video
8:03
Low Level Learning
Рет қаралды 2,1 МЛН
Bare-Metal MCU #9 - Review; ATTiny85 from scratch
14:25
Mitch Davis
Рет қаралды 65 М.
Program, Interrupted - Computerphile
6:41
Computerphile
Рет қаралды 126 М.
Bare-Metal MCU #1 - Intro to registers
13:10
Mitch Davis
Рет қаралды 69 М.
This is the BEST Board to Learn RISC-V Assembly.
17:52
Low Level Learning
Рет қаралды 83 М.
Pin Change Interruptions ISR | PCINT | Arduino101
14:19
Electronoobs
Рет қаралды 56 М.
Premature Optimization
12:39
CodeAesthetic
Рет қаралды 774 М.
Что делать если в телефон попала вода?
0:17
Лена Тропоцел
Рет қаралды 982 М.
Easy Art with AR Drawing App - Step by step for Beginners
0:27
Melli Art School
Рет қаралды 15 МЛН