Book

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.

http://www.amazon.com/Some-Assembly-Required-Programming-Microcontroller/dp/1439820643/ref=sr_1_sc_1?s=books&ie=UTF8&qid=1335087290&sr=1-1-spell

Duane B

rcarduino.blogspot.com

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

rcarduino.blogspot.com

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

rcarduino.blogspot.co

It's true. Although you don't need assembler to determine that :grin: 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

rcarduino.blogspot.com