Using Kanda STK200-X to play around with the Atmel AVR microcontroller. Currently using ATMega16A, which has an internal 1MHz crystal oscillator, but can be outfitted with external clocks of up to 16 MHz. The default supplied with STK200-X is a 8 MHz clock.
The best match for this in Microchip Studio is ATmega16L-8PU
for 8 MHz clock in PDIP40 footprint, or ATmega16-16PU
for 16 MHz clock.
Lots of new terminology to pick up, including:
This subreddit is a pretty good consolidated resource!
https://www.reddit.com/r/AskElectronics/wiki/soldering/
For soldering, previously was using 225 degC for heating, but this means the board takes a long time to heat up. Tried using 350 degC, and worked like a charm. Notably:
Also remember that lead-free does not mean the smoke dissipated is healthy...
FPGA:
Theory:
Simulators:
Toolchains:
atprogram
: Comes with Microchip Studio, best used for Windowsavra
: Stand-in replacement for Linux/macOSsimavr
: Simulator
.\avrisp-u.exe "C:\...\LED Flash.asmproj"
AVRdude
This looks like a fairly nice resource: https://github.com/kitspace/awesome-electronics
Note that my background is some basic electronics (digital/analog), a bit of C (memory allocation).
The datasheet shall become my bible. A useful guide is also the Kanda training kit.
Memories are where program and data is stored, in particular there are three such locations:
Note that this chip uses the Harvard architecture, so the 16-bit instruction bus is separate from the 8-bit data bus (the latter implies an 8-bit microcontroller).
The overview page on the datasheet gives a nice summary:
The rest of the details is kinda lost on me.
The main control flow is determined by the Program Control (PC), which holds the address of program memory being executed. Typical flow:
SRAM in AVR is contiguous, with the following address space - 32 bytes general purpose working registers, 64 bytes I/O registers, then 1024 bytes internal data SRAM. Illustrated below:
Address space (value) | Register, if any | Section |
---|---|---|
0x45F (1119) | Internal data | |
... | ||
... | ||
... | ||
0x0061 (97) | ||
0x0060 (96) | ||
0x005F (95) | 0x3F | IO registers |
... | ... | |
0x0021 (33) | 0x01 | |
0x0020 (32) | 0x00 | |
0x001F (31) | R31 | General-purpose registers |
... | ... | |
0x0001 (1) | R1 | |
0x0000 (0) | R0 |
Instruction sets?
Basic Boolean logic applies, using AND
, OR
, COM
(complement/NOT), EOR
(exclusive OR). For registers R16 to R31, there exists an alternative ANDI
and ORI
, not sure what this means.
Using Microchip Studio 7, then passing $(ProjectDir)$(ProjectFileName)
as arguments to AVRISP-U software will automatically load it into the ISP.
Assembly code used is here:
; Comments are prefixed with ';', '//', or wrapped '/*...*/' ; Spaces between variables are ignored ; Include directive similar to C ; This library for ATMega16 .include "m16def.inc" ; Label registers for easy reference using define .def TEMP=r16 ; temporary (scratch) register .def ON=r23 ; store value for LED on .def OFF=r24 ; store value for LED off .def coarse=r17 ; delay subroutine, has largest effect .def medium=r18 ; delay subroutine, has medium effect .def fine=r19 ; delay subroutine, has smallesteffect .cseg ; indicates this is code and to be stored in Flash .org 0 ; switch to address 0x00 (reset address)... rjmp INIT ; ...and add jump instruction to label INIT .org 0x60 ; switch to address 0x60 (padding for interrupt vectors)... INIT: ; ...and add location of label INIT ; Up to this point is typically the same assembly boilerplate ; Now we define the stack space by populating SPH (Stack Pointer High byte) ; and SPL with the high and low address boundaries respectively. ; Since we cannot write directly to Special Function Registers (SFR) ; nor to bottom 16 registers (R0 to R15), we first load the required ; value into a register between R16 and R31 inclusive. ; ; The end of SRAM is defined in the header file as RAMEND, ; which corresponds to 0x045f for ATmega16. This is a 16-bit ; address, so we write both the high and low bytes, where ; LOW(0x045f) == 0x5f and HIGH(0x045f) == 0x04 ; Set Stack Pointer to top of SRAM ldi TEMP, LOW(RAMEND) ; (load intermediate value) out SPL, TEMP ; (write to SFR) ldi TEMP, HIGH(RAMEND) out SPH, TEMP ; Set all pins in Port B as output (instead of input) ldi TEMP, 0xff out DDRB, TEMP ; data direction register for Port B ; Load 1s into all pins in Port B ; Dependent on electronic wiring - here it switches LEDs off out PORTB, TEMP ; Store off and on values for LED ldi OFF, 0xff ldi ON, 0x00 MAIN: rcall DELAY ; do (relative) call to subroutine out PORTB, ON ; switch LED ON rcall DELAY out PORTB, OFF ; switch LED OFF rjmp MAIN ; repeat main loop DELAY: ldi coarse, 0x07 delay1: ldi medium, 0xff delay2: ldi fine, 0xff delay3: dec fine brne delay3 ; skips only if previous decrement goes to zero dec medium brne delay2 dec coarse brne delay1 ret
Note a couple of additional comments:
ORG
is an abbreviation for origin, which sets the assembler location counter, so that absolute addresses can be defined (e.g. for defining interrupt vectors at fixed addresses, or introduce padding / generate specific alignment. Source.RCALL
is a 1-byte call instruction, as opposed to CALL
which is 2-bytes. The efficiency gain from using RCALL
is minimal when running code in chips with larger address spaces, e.g. ATmega128. avr-gcc
itself may not have implemented this either.BRNE
checks for a Z
flag in the AVR status register (page 9), which will be set if there is a zero result in an arithmetic or logic operation, including DEC
.The subsequent tutorials seem to just introduce other instructions. Worth looking at the decompiled program and the nature of instruction sets instead.
On modern PCs, the program counter is more associated with the instruction itself (due to different branches, etc) than in the chip. See this answer.
The corresponding Flash program written to the chip corresponds to:
prog 0x0000 5f c0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x0010 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x0020 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x0030 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x0040 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x0050 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x0060 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x0070 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x0080 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x0090 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x00A0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x00B0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x00C0 0f e5 0d bf 04 e0 0e bf 0f ef 07 bb 08 bb 8f ef prog 0x00D0 70 e0 04 d0 78 bb 02 d0 88 bb fb cf 17 e0 2f ef prog 0x00E0 3f ef 3a 95 f1 f7 2a 95 d9 f7 1a 95 c1 f7 08 95 prog 0x00F0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x0100 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x0110 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x0120 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x0130 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff prog 0x0140 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ...
while that of the SRAM is:
data 0x0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 data 0x0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 data 0x0020 00 f8 fe ff 00 00 00 00 00 00 00 20 00 00 00 00 data 0x0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 data 0x0040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 data 0x0050 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 data 0x0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 data 0x0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 data 0x0080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... data 0x045F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00