В общем-то вызываемая функция возвращает разные заначения, сейчас покажу. Так что думаю, не то это.
Исходник:
CODE
//Функция проверки кадра
//Возвращает 0 если все ОК
//#pragma inline=forced
unsigned char modbus_frame_check(void)
{
//Ошибки физического уровня (в usart0_received)
if((usart_flags&(1<<mberr))!=0){return 1;}
//Длина кадра (не менее 4 символов)
unsigned char num=usart_count;
if(num<4){return 2;}
//Контрольная сумма
num-=2;
//if(crc16(&usart_stack[0],num)!=(usart_stack[num]+(usart_stack[num+1]<<8))){return 3;}
//
return num;
}
/************************************************************/
//Обработчик ведомого Modbus (зациклен)
void modbus_slave_routine(void)
{
start:
//Сбрасываем таймер и всё-всё-всё и ждем приема
ClearBits(usart_flags,(1<<t15)|(1<<t35)|(1<<mberr)|(1<<rxok));
TCNT1H=0;
TCNT1L=0;
TCCR1B=(1<<WGM12)|(0<<CS12)|(0<<CS11)|(0<<CS10);
usart_count=0;
usart_SP=&usart_stack[0];
//Ждем первый символ
while((usart_flags&(1<<rxok))==0){;}
//Ждем окончания приема кадра
while((usart_flags&(1<<t15))==0){;}
//Проверяем посылку
if(modbus_frame_check()!=0){goto start;}
//Обрабатываем посылку и готовим ответ
_delay_ms(20);
}
И то, что в дизассемблере с включенной Function inlining:
CODE
@00000096: modbus_slave_routine
276: ClearBits(usart_flags,(1<<t15)|(1<<t35)|(1<<mberr)|(1<<rxok));
+00000096: B100 IN R16,0x00 In from I/O location
+00000097: 700F ANDI R16,0x0F Logical AND with immediate
+00000098: B900 OUT 0x00,R16 Out to I/O location
277: TCNT1H=0;
+00000099: E000 LDI R16,0x00 Load immediate
+0000009A: BD0D OUT 0x2D,R16 Out to I/O location
278: TCNT1L=0;
+0000009B: BD0C OUT 0x2C,R16 Out to I/O location
279: TCCR1B=(1<<WGM12)|(0<<CS12)|(0<<CS11)|(0<<CS10);
+0000009C: E008 LDI R16,0x08 Load immediate
+0000009D: BD0E OUT 0x2E,R16 Out to I/O location
283: while((usart_flags&(1<<rxok))==0){;}
+0000009E: 9B02 SBIS 0x00,2 Skip if bit in I/O register set
+0000009F: CFFE RJMP PC-0x0001 Relative jump
285: while((usart_flags&(1<<t15))==0){;}
+000000A0: 9B00 SBIS 0x00,0 Skip if bit in I/O register set
+000000A1: CFFE RJMP PC-0x0001 Relative jump
287: if(modbus_frame_check()!=0){goto start;}
+000000A2: B100 IN R16,0x00 In from I/O location
+000000A3: CFF2 RJMP PC-0x000D Relative jump
Как видно, modbus_frame_check() вообще не вызывается. И что характерно, даже нет попытки ее компилировать (если я правильно выражаюсь) - ее просто нет.
А теперь отключаем оптимизацию Function inlining - функция появилась и работает:
CODE
@000000AF: modbus_frame_check
259: if((usart_flags&(1<<mberr))!=0){return 1;}
+000000AF: 9B03 SBIS 0x00,3 Skip if bit in I/O register set
+000000B0: C002 RJMP PC+0x0003 Relative jump
259: if((usart_flags&(1<<mberr))!=0){return 1;}
+000000B1: E001 LDI R16,0x01 Load immediate
+000000B2: 9508 RET Subroutine return
261: unsigned char num=usart_count;
+000000B3: 91000000 LDS R16,0x0000 Load direct from data space
262: if(num<4){return 2;}
+000000B5: 3004 CPI R16,0x04 Compare with immediate
+000000B6: F410 BRCC PC+0x03 Branch if carry cleared
262: if(num<4){return 2;}
+000000B7: E002 LDI R16,0x02 Load immediate
+000000B8: 9508 RET Subroutine return
267: return num;
+000000B9: 5002 SUBI R16,0x02 Subtract immediate
+000000BA: 9508 RET Subroutine return
@000000BB: modbus_slave_routine
272: void modbus_slave_routine(void)
273: {
+000000BB: E000 LDI R16,0x00 Load immediate
+000000BC: E012 LDI R17,0x02 Load immediate
+000000BD: 9300015A STS 0x015A,R16 Store direct to data space
+000000BF: 9310015B STS 0x015B,R17 Store direct to data space
276: ClearBits(usart_flags,(1<<t15)|(1<<t35)|(1<<mberr)|(1<<rxok));
+000000C1: B100 IN R16,0x00 In from I/O location
+000000C2: 700F ANDI R16,0x0F Logical AND with immediate
+000000C3: B900 OUT 0x00,R16 Out to I/O location
277: TCNT1H=0;
+000000C4: E000 LDI R16,0x00 Load immediate
+000000C5: BD0D OUT 0x2D,R16 Out to I/O location
278: TCNT1L=0;
+000000C6: BD0C OUT 0x2C,R16 Out to I/O location
279: TCCR1B=(1<<WGM12)|(0<<CS12)|(0<<CS11)|(0<<CS10);
+000000C7: E008 LDI R16,0x08 Load immediate
+000000C8: BD0E OUT 0x2E,R16 Out to I/O location
280: usart_count=0;
+000000C9: E000 LDI R16,0x00 Load immediate
+000000CA: 9300015E STS 0x015E,R16 Store direct to data space
283: while((usart_flags&(1<<rxok))==0){;}
+000000CC: 9B02 SBIS 0x00,2 Skip if bit in I/O register set
+000000CD: CFFE RJMP PC-0x0001 Relative jump
285: while((usart_flags&(1<<t15))==0){;}
+000000CE: 9B00 SBIS 0x00,0 Skip if bit in I/O register set
+000000CF: CFFE RJMP PC-0x0001 Relative jump
287: if(modbus_frame_check()!=0){goto start;}
+000000D0: DFDE RCALL PC-0x0021 Relative call subroutine
+000000D1: 2300 TST R16 Test for Zero or Minus
+000000D2: F771 BRNE PC-0x11 Branch if not equal
289: _delay_ms(20);
+000000D3: E30F LDI R16,0x3F Load immediate
+000000D4: E91C LDI R17,0x9C Load immediate
+000000D5: 5001 SUBI R16,0x01 Subtract immediate
+000000D6: 4010 SBCI R17,0x00 Subtract immediate with carry
+000000D7: F7E9 BRNE PC-0x02 Branch if not equal
+000000D8: C000 RJMP PC+0x0001 Relative jump
+000000D9: 0000 NOP No operation
291: }
+000000DA: 9508 RET Subroutine return
Что характерно, если из вызывающей функции удалить обнуление таймера и счетчиков, все тоже работает, только вызываемая функция заинлайнена:
CODE
@00000096: modbus_slave_routine
272: void modbus_slave_routine(void)
273: {
+00000096: 9110015E LDS R17,0x015E Load direct from data space
283: while((usart_flags&(1<<rxok))==0){;}
+00000098: 9B02 SBIS 0x00,2 Skip if bit in I/O register set
+00000099: CFFE RJMP PC-0x0001 Relative jump
285: while((usart_flags&(1<<t15))==0){;}
+0000009A: 9B00 SBIS 0x00,0 Skip if bit in I/O register set
+0000009B: CFFE RJMP PC-0x0001 Relative jump
287: if(modbus_frame_check()!=0){goto start;}
+0000009C: 9903 SBIC 0x00,3 Skip if bit in I/O register cleared
+0000009D: CFFA RJMP PC-0x0005 Relative jump
+0000009E: 2F01 MOV R16,R17 Copy register
+0000009F: 3014 CPI R17,0x04 Compare with immediate
+000000A0: F3B8 BRCS PC-0x08 Branch if carry set
+000000A1: 5002 SUBI R16,0x02 Subtract immediate
+000000A2: F7A9 BRNE PC-0x0A Branch if not equal
289: _delay_ms(20);
+000000A3: E30F LDI R16,0x3F Load immediate
+000000A4: E91C LDI R17,0x9C Load immediate
+000000A5: 5001 SUBI R16,0x01 Subtract immediate
+000000A6: 4010 SBCI R17,0x00 Subtract immediate with carry
+000000A7: F7E9 BRNE PC-0x02 Branch if not equal
+000000A8: C000 RJMP PC+0x0001 Relative jump
+000000A9: 0000 NOP No operation
291: }
+000000AA: 9508 RET Subroutine return
Вот это для меня уже вообще непостижимо.