Hi,
Does anyone have any feedback on this book or can suggest an alternative resource for learning AVR Assembler. I have very limited experience in assembler so need to basics as well as the AVR Specifics, this book seems to cover both.
Duane B
Hi,
Does anyone have any feedback on this book or can suggest an alternative resource for learning AVR Assembler. I have very limited experience in assembler so need to basics as well as the AVR Specifics, this book seems to cover both.
Duane B
Hi,
It looks good, I have downloaded the PDF and will have plenty of time to read through it next week when I am stuck on a plane again.
Thanks
Duane B
Hi,
I have just used the suggestions in this thread to look at the disassembled code for a sketch, its very interesting to see just how much goes on some functions, digitalRead is doing an awful lot to protect the user from themselves, I will be avoiding it in ISRs from now on.
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1193790150
I know this isn't news to many members, and a lot of the code is branching so only a fraction of it will be executed, but its still a bit of a wow for me to see just how much is going on in digital read -
int digitalRead(uint8_t pin)
{
uint8_t timer = digitalPinToTimer(pin);
10f2: 68 2f mov r22, r24
10f4: 70 e0 ldi r23, 0x00 ; 0
10f6: cb 01 movw r24, r22
10f8: 82 55 subi r24, 0x52 ; 82
10fa: 9f 4f sbci r25, 0xFF ; 255
10fc: fc 01 movw r30, r24
10fe: 24 91 lpm r18, Z+
uint8_t bit = digitalPinToBitMask(pin);
1100: cb 01 movw r24, r22
1102: 86 56 subi r24, 0x66 ; 102
1104: 9f 4f sbci r25, 0xFF ; 255
1106: fc 01 movw r30, r24
1108: 44 91 lpm r20, Z+
uint8_t port = digitalPinToPort(pin);
110a: 6a 57 subi r22, 0x7A ; 122
110c: 7f 4f sbci r23, 0xFF ; 255
110e: fb 01 movw r30, r22
1110: 94 91 lpm r25, Z+
if (port == NOT_A_PIN) return LOW;
1112: 99 23 and r25, r25
1114: 19 f4 brne .+6 ; 0x111c <digitalRead+0x2a>
1116: 20 e0 ldi r18, 0x00 ; 0
1118: 30 e0 ldi r19, 0x00 ; 0
111a: 3c c0 rjmp .+120 ; 0x1194 <digitalRead+0xa2>
// If the pin that support PWM output, we need to turn it off
// before getting a digital reading.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
111c: 22 23 and r18, r18
111e: 51 f1 breq .+84 ; 0x1174 <digitalRead+0x82>
//
//static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline));
//static inline void turnOffPWM(uint8_t timer)
static void turnOffPWM(uint8_t timer)
{
switch (timer)
1120: 23 30 cpi r18, 0x03 ; 3
1122: 71 f0 breq .+28 ; 0x1140 <digitalRead+0x4e>
1124: 24 30 cpi r18, 0x04 ; 4
1126: 28 f4 brcc .+10 ; 0x1132 <digitalRead+0x40>
1128: 21 30 cpi r18, 0x01 ; 1
112a: a1 f0 breq .+40 ; 0x1154 <digitalRead+0x62>
112c: 22 30 cpi r18, 0x02 ; 2
112e: 11 f5 brne .+68 ; 0x1174 <digitalRead+0x82>
1130: 14 c0 rjmp .+40 ; 0x115a <digitalRead+0x68>
1132: 26 30 cpi r18, 0x06 ; 6
1134: b1 f0 breq .+44 ; 0x1162 <digitalRead+0x70>
1136: 27 30 cpi r18, 0x07 ; 7
1138: c1 f0 breq .+48 ; 0x116a <digitalRead+0x78>
113a: 24 30 cpi r18, 0x04 ; 4
113c: d9 f4 brne .+54 ; 0x1174 <digitalRead+0x82>
113e: 04 c0 rjmp .+8 ; 0x1148 <digitalRead+0x56>
{
#if defined(TCCR1A) && defined(COM1A1)
case TIMER1A: cbi(TCCR1A, COM1A1); break;
1140: 80 91 80 00 lds r24, 0x0080
1144: 8f 77 andi r24, 0x7F ; 127
1146: 03 c0 rjmp .+6 ; 0x114e <digitalRead+0x5c>
#endif
#if defined(TCCR1A) && defined(COM1B1)
case TIMER1B: cbi(TCCR1A, COM1B1); break;
1148: 80 91 80 00 lds r24, 0x0080
114c: 8f 7d andi r24, 0xDF ; 223
114e: 80 93 80 00 sts 0x0080, r24
1152: 10 c0 rjmp .+32 ; 0x1174 <digitalRead+0x82>
#if defined(TCCR2) && defined(COM21)
case TIMER2: cbi(TCCR2, COM21); break;
#endif
#if defined(TCCR0A) && defined(COM0A1)
case TIMER0A: cbi(TCCR0A, COM0A1); break;
1154: 84 b5 in r24, 0x24 ; 36
1156: 8f 77 andi r24, 0x7F ; 127
1158: 02 c0 rjmp .+4 ; 0x115e <digitalRead+0x6c>
#endif
#if defined(TIMER0B) && defined(COM0B1)
case TIMER0B: cbi(TCCR0A, COM0B1); break;
115a: 84 b5 in r24, 0x24 ; 36
115c: 8f 7d andi r24, 0xDF ; 223
115e: 84 bd out 0x24, r24 ; 36
1160: 09 c0 rjmp .+18 ; 0x1174 <digitalRead+0x82>
#endif
#if defined(TCCR2A) && defined(COM2A1)
case TIMER2A: cbi(TCCR2A, COM2A1); break;
1162: 80 91 b0 00 lds r24, 0x00B0
1166: 8f 77 andi r24, 0x7F ; 127
1168: 03 c0 rjmp .+6 ; 0x1170 <digitalRead+0x7e>
#endif
#if defined(TCCR2A) && defined(COM2B1)
case TIMER2B: cbi(TCCR2A, COM2B1); break;
116a: 80 91 b0 00 lds r24, 0x00B0
116e: 8f 7d andi r24, 0xDF ; 223
1170: 80 93 b0 00 sts 0x00B0, r24
// If the pin that support PWM output, we need to turn it off
// before getting a digital reading.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
if (*portInputRegister(port) & bit) return HIGH;
1174: 89 2f mov r24, r25
1176: 90 e0 ldi r25, 0x00 ; 0
1178: 88 0f add r24, r24
117a: 99 1f adc r25, r25
117c: 84 58 subi r24, 0x84 ; 132
117e: 9f 4f sbci r25, 0xFF ; 255
1180: fc 01 movw r30, r24
1182: a5 91 lpm r26, Z+
1184: b4 91 lpm r27, Z+
1186: 8c 91 ld r24, X
1188: 20 e0 ldi r18, 0x00 ; 0
118a: 30 e0 ldi r19, 0x00 ; 0
118c: 84 23 and r24, r20
118e: 11 f0 breq .+4 ; 0x1194 <digitalRead+0xa2>
1190: 21 e0 ldi r18, 0x01 ; 1
1192: 30 e0 ldi r19, 0x00 ; 0
return LOW;
}
1194: c9 01 movw r24, r18
1196: 08 95 ret
Duane B
It's true. Although you don't need assembler to determine that It's all right there in the C code.
Hi,
Thats true, but its still interesting to look at the assembler, I assumed that some functions would be inlined but they are not, its also interesting to see how many cycles anything involving a volatile long takes - read four bytes from memory to register, do something to four bytes, write four bytes back to memory.
I am interested because the RC Channel signals I am dealing with are 500us from neutral to full throttle, I will often have a situation with several pending interrupts, the lowest priority interrupt can be forced to wait 8us or more which shows up as a 2% error in the desired output signal.
I have half a dozen strategies to reduce this and will be working on them over the coming few days.
Duane B