-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
x-posted to alt.microcontrollers.8bit to see if anyone's out there
(yeah, it's OT for linux...)
Came out of a side discussion with Rudy Weiser (er, sorry if I typo'd
the name, should've written it down) where we started talking a bit
about programming microcontrollers, and some pitfalls we (I?) ran into
with Microchip's latest "1-series" ATTiny demo boards.
Code below is straight out of the Microchip provided "MPLABX" IDE, using
the debug / show disassembly features. For those more familiar with the
assembly, you probably know of a cleaner way to get it out, but, well, I
don't :). It's the "initial setup" that I do to the "PORT B" set of
pins -- on this particular demoboard, there is a LED attached to pin
"B5" (i.e. the 5th bit of the 8-bit register), and a button attached to
pin "B4". So, I'm setting pin 5 as an output, and pin 4 as an input,
and also enabling the pullup resistor inside the ATTiny to keep pin4 at
a "high" voltage (>2.1v) when the button is not depressed. This is to
keep the pin from "floating" (effectively, a "floating" pin is the
hardware equivalent of "undefined behavior" in your favorite programming
language).
- From here on out, it's just the code, and then pretty much me trying to
make sense of the assembly.
========================================================================
int main(void) {
PORTB_DIRSET |= (1<<PB5);
00DD E2E1 LDI R30, 0x21
00DE E0F4 LDI R31, 0x04
00DF 8180 LD R24, Z
00E0 6280 ORI R24, 0x20
00E1 8380 ST Z, R24
PORTB_DIRSET &= ~(1<<PB4);
00E2 8180 LD R24, Z
00E3 7E8F ANDI R24, 0xEF
00E4 8380 ST Z, R24
//int led=0;
//enable input pullup
PORTB_PIN4CTRL |= 0b00001000;
00E5 E3E4 LDI R30, 0x34
00E6 E0F4 LDI R31, 0x04
00E7 8180 LD R24, Z
00E8 6088 ORI R24, 0x08
00E9 8380 ST Z, R24
PORTB_OUT |= (1<<PB5); //Make sure the LED is off
00EA E2E4 LDI R30, 0x24
00EB E0F4 LDI R31, 0x04
00EC 8180 LD R24, Z
00ED 6280 ORI R24, 0x20
00EE 8380 ST Z, R24
}
========================================================================
Quick perusal of the datasheet says that the commands are
- LDI -> Load Immediate, Operands : Rd, k.
- LD -> Load indirect, Operands Rd, X.
- ST -> Store Indirect, Operands X, Rr.
- ORI -> Logical OR with Immediate, Operands Rd, K
- ANDI -> Logical AND with Immediate, Operands Rd, K
Operand definitions are:
- Rd -> Destination (sometimes source[1]) Register
- k -> address constant
- K -> constant data
- X -> Indirect Address Register (R27:R26)
- Z -> Indirect Address Register (R31:R30)
- Rr -> Source register
So, with this very small amount of knowledge, I think what's going on in
the initial pin setup is (the two "PORTB_DIRSET" commands)
00DD E2E1 LDI R30, 0x21
00DE E0F4 LDI R31, 0x04
00DF 8180 LD R24, Z
00E0 6280 ORI R24, 0x20
00E1 8380 ST Z, R24
Set the values of Register 30,31 to 0x21 and 0x04, respectively (aka
register Z).
Load the value from register index Z into R24
Logical OR (Immediate) the value in Register 24 and and constant 0x20
Store the value of R24 into the register index 'Z'
00E2 8180 LD R24, Z
00E3 7E8F ANDI R24, 0xEF
00E4 8380 ST Z, R24
Load the value from register Z back into R24
Bitwise AND (Immediate) the value in R24, and constant 0xEF
Store that result back into register Z
00E5 E3E4 LDI R30, 0x34
00E6 E0F4 LDI R31, 0x04
00E7 8180 LD R24, Z
00E8 6088 ORI R24, 0x08
00E9 8380 ST Z, R24
Set the values of Register 30,31 to 0x34 and 0x04, respectively (aka
register Z).
Load the value from register index Z into R24
Logical OR (Immediate) the value in Register 24 and and constant 0x08
Store the value of R24 back into register index Z
I guess that the preceding hex is the SRAM location where the command
is being stored, which is keeping us from clobbering our previous work,
maybe.
00EA E2E4 LDI R30, 0x24
00EB E0F4 LDI R31, 0x04
00EC 8180 LD R24, Z
00ED 6280 ORI R24, 0x20
00EE 8380 ST Z, R24
Set the values of Register 30,31 to 0x24 and 0x04, respectively (aka
register Z).
Load the value from register index Z into R24
Logical OR (Immediate) the value in Register 24 and and constant 0x20
Store the value of R24 back into register index Z
[1] According to the "AVR Instruction Set Manual" [2], 'Rd' is used when
a single (Direct) register is used with the operand. 'Rr' is used when
two registers are required, or you only need to READ a value. It's a
bit terse, and probably makes more sense to people familiar with
assembly.
[2]
http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf
-----BEGIN PGP SIGNATURE-----
iQEzBAEBCAAdFiEEBcqaUD8uEzVNxUrujhHd8xJ5ooEFAlxRk3QACgkQjhHd8xJ5
ooEZgQf/WBhsGPv7gmbAgIvW3Ol4BPE6v8G+2RhH++Ktca9evTs4mVANdlu7kU26
5P8lHc18NpOjiPMoWfGVIPrvVQDvqdemdf6ChpvMy9kZwlM8E+T+SYDuogMDwv8e
SXCWst1OzjCNdwpYsfM/MzAcarUQrAyJtxZQdWo1dVuOGtR4JLVMzYjaZQ1qJDN8
Nq2GJakn+XR6HBdIZauGE9m+5u1dKK2OHyBa3q2F0YyUbFOLH3uOCaVYVaXWYUWL
WYAlp6YFuzwk+28ToJrr0F7LK7OB2Z2nUeIyKI+WJfMdTeZMHa5XjQJ04OejojdP
hE1mJz6omwRTOzSnjX1TqcxjGNHKFQ==
=5obN
-----END PGP SIGNATURE-----
--
|_|O|_|
|_|_|O| Github:
https://github.com/dpurgert
|O|O|O| PGP: 05CA 9A50 3F2E 1335 4DC5 4AEE 8E11 DDF3 1279 A281