Баг мягко выражаясь странный ...
Есть inline функция AT91F_PDC_IsTxEmpty из AT91SAM7S256.h от Atmel,
вызывается AT91F_US_SendFrame --> AT91F_PDC_SendFrame --> AT91F_PDC_IsTxEmpty (все inline)
А вот код сгенерированный Keil'ом в котором вместо подстановки тела функции AT91F_PDC_IsTxEmpty,
вызов "несуществующей" функции. Только не говорите что компилятор в данном случае
проигнорировал директиву inline и вызывает AT91F_PDC_IsTxEmpty как обычную функцию.
Во-первых, переход (BL) осуществляется но адресу 0x00000000 что видно в debuger'е, во-вторых, из
map-файла видно, что данной функции в сегменте кода НЕТ.
Максимальный уровень вложенности вызова функции AT91F_PDC_IsTxEmpty в программе = 5
main() --> menu() --> message() --> AT91F_US_SendFrame() --> ...
BAD
----------- ASSEMBLER CODE LISTING
152: AT91F_US_SendFrame( AT91C_BASE_US0, debug_message, len, 0, 0 );
00202DA4 E1A00001 MOV R0,R1; len
00202DA8 E1A01C00 MOV R1,R0,LSL #24; len
00202DAC E1A01C21 MOV R1,R1,LSR #24
00202DB0 ---- Variable 'szBuffer' assigned to Register 'R1' ----
00202DB0 E59F30A0 LDR R3,[PC,+160]; PoolRef @0x202E58
00202DB4 ---- Variable 'pUSART' assigned to Register 'R3' ----
00202DB4 E59F2098 LDR R2,[PC,+152]; PoolRef @0x202E54; debug_message
00202DB8 ---- Variable 'pBuffer' assigned to Register 'R2' ----
00202DB8 E3A00000 MOV R0,#0x0
00202DBC ---- Variable 'pNextBuffer' assigned to Register 'R0' ----
2712: __inline unsigned int AT91F_US_SendFrame(
00202DBC ; SCOPE-START
2719: return AT91F_PDC_SendFrame(
00202DBC E1A06003 MOV R6,R3; pUSART
00202DC0 E2866C01 ADD R6,R6,#0x0100; pUSART
00202DC4 ---- Variable 'pPDC' assigned to Register 'R6' ----
00202DC4 E1A05002 MOV R5,R2; pBuffer
00202DC8 ---- Variable 'pBuffer' assigned to Register 'R5' ----
00202DC8 E1A04001 MOV R4,R1; szBuffer
00202DCC ---- Variable 'szBuffer' assigned to Register 'R4' ----
00202DCC E1A07000 MOV R7,R0; pNextBuffer
00202DD0 ---- Variable 'pNextBuffer' assigned to Register 'R7' ----
385: __inline unsigned int AT91F_PDC_SendFrame(
00202DD0 ; SCOPE-START
392: if (AT91F_PDC_IsTxEmpty(pPDC)) {
00202DD0 E1A00006 MOV R0,R6; pPDC
00202DD4 EBF7F489 BL AT91F_PDC_IsTxEmpty?A ; Targ=0x0 !!! ERROR !!!
00202DD8 E3500000 CMP R0,#0x0000; AT91F_PDC_IsTxEmpty?A
00202DDC 0A000008 BEQ L_705 ; Targ=0x202E04
----------- KEIL DEBUGER + SIMULATOR
152: AT91F_US_SendFrame( AT91C_BASE_US0, debug_message, len, 0, 0 );
0x00202DA4 E1A00001 MOV R0,R1
0x00202DA8 E1A01C00 MOV R1,R0,LSL #24
0x00202DAC E1A01C21 MOV R1,R1,LSR #24
0x00202DB0 E59F30A0 LDR R3,[PC,#0x00A0]
0x00202DB4 E59F2098 LDR R2,[PC,#0x0098]
0x00202DB8 E3A00000 MOV R0,#0x00000000
0x00202DBC E1A06003 MOV R6,R3
0x00202DC0 E2866C01 ADD R6,R6,#0x00000100
0x00202DC4 E1A05002 MOV R5,R2
0x00202DC8 E1A04001 MOV R4,R1
0x00202DCC E1A07000 MOV R7,R0
0x00202DD0 E1A00006 MOV R0,R6
0x00202DD4 EBF7F489 BL 0x00000000 !!! ERROR !!!
0x00202DD8 E3500000 CMP R0,#0x00000000
0x00202DDC 0A000008 BEQ 0x00202E04
А вот если уменьшить максимальный уровень вложенности до 4х
main() --> message() --> AT91F_US_SendFrame() --> ...
код генерируется правильный:
GOOD
----------- ASSEMBLER CODE LISTING
152: AT91F_US_SendFrame( AT91C_BASE_US0, debug_message, len, 0, 0 );
00202D98 E1A00001 MOV R0,R1; len
00202D9C E1A02C00 MOV R2,R0,LSL #24; len
00202DA0 E1A02C22 MOV R2,R2,LSR #24
00202DA4 ---- Variable 'szBuffer' assigned to Register 'R2' ----
00202DA4 E59F3110 LDR R3,[PC,+272]; PoolRef @0x202EBC
00202DA8 ---- Variable 'pUSART' assigned to Register 'R3' ----
00202DA8 E59F0108 LDR R0,[PC,+264]; PoolRef @0x202EB8; debug_message
00202DAC ---- Variable 'pBuffer' assigned to Register 'R0' ----
00202DAC E3A08000 MOV R8,#0x0
00202DB0 ---- Variable 'pNextBuffer' assigned to Register 'R8' ----
2712: __inline unsigned int AT91F_US_SendFrame(
00202DB0 ; SCOPE-START
2719: return AT91F_PDC_SendFrame(
00202DB0 E1A01003 MOV R1,R3; pUSART
00202DB4 E2811C01 ADD R1,R1,#0x0100; pUSART
00202DB8 ---- Variable 'pPDC' assigned to Register 'R1' ----
00202DB8 E1A03000 MOV R3,R0; pBuffer
00202DBC ---- Variable 'pBuffer' assigned to Register 'R3' ----
00202DBC E1A00002 MOV R0,R2; szBuffer
00202DC0 ---- Variable 'szBuffer' assigned to Register 'R0' ----
00202DC0 E1A04008 MOV R4,R8; pNextBuffer
385: __inline unsigned int AT91F_PDC_SendFrame(
00202DC4 ; SCOPE-START
392: if (AT91F_PDC_IsTxEmpty(pPDC)) {
00202DC4 E1A05001 MOV R5,R1; pPDC
00202DC8 ---- Variable 'pPDC' assigned to Register 'R5' ----
304: __inline int AT91F_PDC_IsTxEmpty ( // \return return 1 if transfer is complete
00202DC8 ; SCOPE-START
307: return !(pPDC->PDC_TCR);
00202DC8 E1A02005 MOV R2,R5; pPDC
00202DCC E592200C LDR R2,[R2,#0xC]
00202DD0 E3520000 CMP R2,#0x0000
00202DD4 1A000001 BNE L_717 ; Targ=0x202DE0
00202DD8 E3A05001 MOV R5,#0x1
00202DDC EA000000 B L_718 ; Targ=0x202DE4
00202DE0 L_717:
00202DE0 E3A05000 MOV R5,#0x0
00202DE4 L_718:
00202DE4 ---- Variable 'AT91F_PDC_IsTxEmpty?A?Rtv' assigned to Register 'R5' ----
308: }
----------- DEBUGER
152: AT91F_US_SendFrame( AT91C_BASE_US0, debug_message, len, 0, 0 );
0x00202D98 E1A00001 MOV R0,R1
0x00202D9C E1A02C00 MOV R2,R0,LSL #24
0x00202DA0 E1A02C22 MOV R2,R2,LSR #24
0x00202DA4 E59F3110 LDR R3,[PC,#0x0110]
0x00202DA8 E59F0108 LDR R0,[PC,#0x0108]
0x00202DAC E3A08000 MOV R8,#0x00000000
0x00202DB0 E1A01003 MOV R1,R3
0x00202DB4 E2811C01 ADD R1,R1,#0x00000100
0x00202DB8 E1A03000 MOV R3,R0
0x00202DBC E1A00002 MOV R0,R2
0x00202DC0 E1A04008 MOV R4,R8
0x00202DC4 E1A05001 MOV R5,R1
0x00202DC8 E1A02005 MOV R2,R5
0x00202DCC E592200C LDR R2,[R2,#0x000C]
0x00202DD0 E3520000 CMP R2,#0x00000000
0x00202DD4 1A000001 BNE 0x00202DE0
0x00202DD8 E3A05001 MOV R5,#0x00000001
0x00202DDC EA000000 B 0x00202DE4
0x00202DE0 E3A05000 MOV R5,#0x00000000