Details
About the Instructor
Uri is a maker who loves voiding warranties; Currently building AVR8js, an open-source AVR simulator in JavaScript and working on "The Skull", an ATtiny85 reverse engineering puzzle.
Course Overview
You have probably used Arduino Uno, and know how to program it with C++. You may have also seen/written code that interfaces directly with the hardware registers of the ATmega328p chip (PORTB
, TCNT0
, etc.). But if you really want to dive deep, understanding the AVR architecture is key.
This course will take you on a journey to explore the internals of the AVR architecture. We'll learn the AVR assembly language, look at the different peripherals and the registers that control their behavior, and get very intimate with the ATmega328p datasheet.
By the end of the course, you'll have hands-on experience with writing AVR assembly code, as well as understanding and reverse engineering the code generated by the compiler. You will be able to use your skills to solve CTF riddles, write cryptic code-golf programs, and whatnot.
You DON'T Need an Expensive Debugger
Usually, learning about the internals of a microcontroller requires specific hardware that connects to the debug interface of this microcontroller. However, in this course, we're going to cheat and use AVR8js, and open-source AVR emulator. We'll learn how to connect to it with GDB and probe the internals as the machine code is executing.
Software Requirements
Modern web browser (Chrome, Firefox, etc.). We'll use the online simulator at https://wokwi.com.
Optional: Node.js + avr-gdb for interfacing with GDB (instructions will be provided prior to the relevant class).
Prerequisites / Resources
- Bitwise Math
- You should be fluent in Arduino programming
- Basic understanding of electronics (e.g. you should know what is an LED and how to properly wire it to an Arduino board).
- Document with all the links/resources shared during the classes
Syllabus
Class 1 - We'll learn how the memory space is organized, explore the I/O space and the register space, become friends with the ATmega328P datasheet, and see how our C code can interact with the on-chip peripherals (such as GPIO) by directly accessing the hardware registers.
Class 2 - We'll get our hands dirty with Assembly code and learn how to use it in our Arduino code. We'll go over the basics of AVR assembly: working with registers, the program counter, performing arithmetic operations and their effect on the status register, and using the asm statement to include inline assembly in our code.
Class 3 - We'll get deeper into AVR assembly, covering topics such as: the stack pointer, branches and method calls, the interrupt vector, conditional instructions, and data transfer instructions.
Class 4 - Let's take a look under the hood! We'll take a look at the source code of the Arduino's Wiring library, and then learn how to see the assembly code produced by the Arduino compiler using avr-objdump
, and start practicing reading AVR assembly code and understanding it.
Class 5 - We'll get even more hands-on AVR assembly experience by writing a complete program from scratch, learning how to set up and utilize the built-in AVR Timer peripherals.
Final Project - You'll write a Pong game, from scratch, in AVR assembly. Details: https://hackaday.io/project/177609-avr-pong-in-assembly
This is going to be fun. And intense. 🙀
Files
ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061B.pdfDatasheet for the ATmega328PAdobe Portable Document Format - 31.78 MB - 01/27/2021 at 23:13 |
|
|
Course Classes
Collapse
-
Class 1
Lutetium • 01/07/2021 at 19:37 • 0 commentsClass 1 - We'll learn how the memory space is organized, explore the I/O space and the register space, become friends with the ATmega328P datasheet, and see how our C code can interact with the on-chip peripherals (such as GPIO) by directly accessing the hardware registers.
Class 1 Video:
The document with all the links/resources from the class: https://link.wokwi.com/avr-class
-
Class 2
Lutetium • 01/07/2021 at 19:38 • 0 commentsClass 2 - We'll get our hands dirty with Assembly code and learn how to use it in our Arduino code. We'll go over the basics of AVR assembly: working with registers, the program counter, performing arithmetic operations and their effect on the status register, and using the asm statement to include inline assembly in our code.
Class 2 Video:
-
Class 3
Lutetium • 01/07/2021 at 19:38 • 0 commentsClass 3 - We'll get deeper into AVR assembly, covering topics such as: the stack pointer, branches and method calls, the interrupt vector, conditional instructions, and data transfer instructions.
Class 3 Video:
-
Class 4
Lutetium • 01/07/2021 at 19:39 • 0 commentsClass 4 - Let's take a look under the hood! We'll take a look at the source code of the Arduino's Wiring library, and then learn how to see the assembly code produced by the Arduino compiler using
avr-objdump
, and start practicing reading AVR assembly code and understanding it.Class 4 Video:
-
Class 5
Lutetium • 01/07/2021 at 19:40 • 5 commentsClass 5 - We'll get even more hands-on AVR assembly experience by writing a complete program from scratch, learning how to set up and utilize the built-in AVR Timer peripherals.
Final Project Instructions - please tag your project with AVRPong
(For those who would like a Certificate of Completion from HackadayU, this must be completed by March 31st, 2021).Class 5 Video:
Build Instructions
Collapse
-
1Defining ISRs (Interrupt Service Routines) in AVR Assembly
If you want to use interrupts in your Assembly code, you need to define the interrupt vectors in your code. Luckily, this is done by the linker for you. All you need to do is to give your ISR a specific name, by defining a global label.
For instance, the following code defines the handle for external interrupt 0 (INT0), that can be triggered by pin 2 of Arduino (PD2):
.global INT0_vect INT0_vect: ; your code here reti
You can find the complete list of interrupt handler names in the avr-libc manual, under the section named "Choosing the vector: Interrupt vector names". Not all the vectors are applicable for Arduino Uno: look for "ATmega328P" in "Applicable for device" column to know which vectors are relevant (you can also consult the datasheet).
-
2How to write your ISRs:
1. Your ISR must preserve the values of any registers it uses. Otherwise, it may affect the program coding in unexpected ways. Usually, you'd
push
all the registers that you use at the beginning, andpop
them before returning.2. The ISR should also preserve the value of
SREG
, where the flags are. This is done by copying it to a general purpose register (whose value was already saved to stack), then pushing it into the stack, e.g.:in r0, SREG push r0
and then restore it before:
pop r0 out SREG, r0
This can be omitted if you don't use any instructions that modify the flags. For instance, if you use the ISR to just toggle a GPIO pin and nothing more. I'd still recommend to include this, just in case someone adds some instructions that modify the flags in the future.
3. Using
reti
instead ofret
. That's the same as ret, but it also re-enables interrupts. otherwise, you'd return to the program with interrupts disabled.Note: I recommend to take a look at the assembly code generated by the compiler for ISRs that you create in C. You can open the INT0 Example project and look at the generated assembly code by pressing "F1" in the editor and selecting "View Compiled Assembly Code Listing", go to the "sketch.lst" tab and search for "INT0_vect".
Enjoy this course?
ShareDiscussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
Nice, You have discuss everthy fine. But I want to learn website designing because I have to design just like https://besttechi.com/best-monitors-for-triple-monitor-setup/ for my business. So kindly mention the website designing course url here so I can easily reach out it.