aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md107
1 files changed, 107 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..575493b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,107 @@
+# AVR assembly programming
+This is a repo containing my attempts at programming in AVR assembly
+
+I want the every byte of macihne code executed by my processor to be written by
+myself, so no libraries, no definitions, no nothing.
+
+### DISCLAIMER
+Please have a sense of humor and don't take the jokes in this
+README seriously.
+
+### WARNING
+ChatGPT and any other genAI, as of 2025-09-05, can NOT write proper
+AVR assembly. And I doubt they'll learn any time soon. Try it for yourself,
+maybe you'll get something working if they write it completely from scratch,
+but as for debugging, you are on your own. Use debugging tools mentioned below.
+
+Examples of generative AI being completely useless include: them trying to
+persuade me that I've used the wrong interrupt vector address, mixing up
+`out`/`sts` and `in`/`lds` instructions, mixing up addresses of IO registers,
+writing/reading data from wrong registers (like mixing up `TIMSK`/`TIFR`,
+`PINx/PORTx`), not knowing how to actually compile the code and so much more,
+not unserstanding how timers work and so on. Save yourself some time, don't use
+genAI.
+
+## How can I use it?
+Firstly, as an example of how to program in assembly for
+AVR. I am not responsible for the quality though :silly:. My only source is
+datasheets.
+
+Secondly, there is a really useful [Makefile](Makefile) that you can copy to use
+with your own projects. Most variables do not need to be changed there, maybe
+just the `MCUPATH`. Name a file `something.s`, and then run `make
+TARGET=something` to build, or `make TARGET=something flash` to upload your
+code to the arduino. You can set the `TARGET` as an environment variable to
+aviod typing it in each invokation of `make`.
+
+Thirdly, for debugging. Run `make TARGET=something sim`, then run `avr-gdb
+something`, when inside of it, type `target remote :1234` and you're good to go.
+`make sim` automatically detects wheher the simulation is already running and
+forks to background, so to rerun the simulation, just type `make sim` again: it
+will rebuild the file, and you won't even have to restart gdb (it will preserve
+breakpoints), just retype the `target remote :1234` command. I find this
+workflow satisfying, and it does not exhaust my arduino flash memory by
+flashing the program every 30 seconds there. I think I will add a debugging
+guide as well...
+
+## Dependencies
+### Software
+* `make`
+* avr toolchain (`avr-as`, `avr-ld`, `avr-objcopy`, `avr-objdump`)
+* `avrdude` (flash tool)
+* For debugging: `avr-gdb` + `simavr` (or `qemu-system-avr`, but I had problems
+ with it)
+
+Not that you don't actually need `avr-libc` or `avr-gcc` to build assembly.
+### Hardware
+* an ARDUINO UNO board, or any other AVR-based microcontroller if you change
+ the variables in Makefile. Note that most of the variables can be changed
+ from the environment.
+* wirez
+* rizz
+
+### Dependency installation
+* Arch linux: `# pacman -S avr-binutils avrdude`. For C development, you also
+ need to install `avr-gcc` and `avr-libc`. For debugging, `avr-gdb` and
+ `simavr` [\[AUR\]](https://aur.archlinux.org/packages/simavr)
+ [\[CLONE\]](https://aur.archlinux.org/simavr.git)
+* Any other non-superior distro: read the fucking manual
+
+## Why?
+- to have fun.
+
+## Useful resources
+* [ATMega328p datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf)
+* [AVR instruction manual](https://ww1.microchip.com/downloads/en/DeviceDoc/AVR-Instruction-Set-Manual-DS40002198A.pdf)
+* [AVR130: Setup and use of AVR Timers](https://ww1.microchip.com/downloads/en/Appnotes/Atmel-2505-Setup-and-Use-of-AVR-Timers_ApplicationNote_AVR130.pdf)
+* [Arduino UNO R3 info](https://docs.arduino.cc/hardware/uno-rev3/), [PINOUT](https://docs.arduino.cc/resources/pinouts/A000066-full-pinout.pdf)
+
+## Read this if you are going into it blind
+This section contains some of the pain that I've gone through while doing this
+programming journey. If you don't want to make same mistakes, please take your
+time to read it.
+
+0. AVR interrupt addresses from datasheet are not the same ones you specify in
+ assembly! <br>
+ For example, TIMER1 COMPA (timer 1 compare A match) has address
+ `0x0016` in the datasheet, but in assembly you have to align it like this:
+ ```asm
+ .org 0x002C: jmp timer1_int
+ ```
+ Why? Because they probably refer to "instruction address", not to "memory
+ address". Is it said anywhere? No. Can you figure it out by compiling
+ corresponding C code and looking at disassembly? Yes, but you will spend 5
+ hours trying to understand why your interrupt is not working.
+0. Don't forget to link your file after compiling! <br>
+ This would have not been a problem on a processor that has an OS, because
+ the file just wouldn't run unless you link it. But here you're using
+ `objcopy`. That means that ALL jumps and calls will be broken in your
+ assembly. I thought that this was a bug for so long, dont be like me.
+0. I've said this before, but don't ever try to use AI, or even worse, vibe
+ code the microcontroller. It's just not going to work, you will loose time
+ instead of saving it. You can vibecode a crappy website in react only because
+ there is so much training data for it. But almost entirety of AVR programming
+ is done in C++, thanks to fucking nobody. But I mean, it is a good thing that
+ AI can't comprehend assembly. It means you'll have more fun exploring the old
+ fashined way ;)
+0. I will add entries to this list as I go...