I have another problem with parameter passing in v4.8, my money says is is the same problem as it has to do with the string parameter passing problem. This time it is from within the interrupt.
I know this is a huge program but I am hoping with the listing file and pascal source you can see what is not being generated in the listing correctly.
Look in the NMRA_DCC.mpas file and find this function:
Code: Select all
procedure Direct_LoadMessage(BufferPtr: PDCCBufferInfo; ServiceMode_State: Byte; OpCode: Byte; PreambleCount: Byte);
var
i: Integer;
begin
BufferPtr^.TX_TransmittingMessage.MessageBytes[0] := OpCode or (ServiceModeInfo.Buffer.Address shr 8);
BufferPtr^.TX_TransmittingMessage.MessageBytes[1] := ServiceModeInfo.Buffer.Address and Word($00FF);
if (ServiceMode_State = STATE_SERVICEMODE_DIRECT_INSTRUCTION_BIT_WRITE) or (ServiceMode_State = STATE_SERVICEMODE_DIRECT_INSTRUCTION_BIT_READ) then
BufferPtr^.TX_TransmittingMessage.MessageBytes[2] := %11100000 or ServiceModeInfo.Buffer.Value
else
BufferPtr^.TX_TransmittingMessage.MessageBytes[2] := ServiceModeInfo.Buffer.Value;
BufferPtr^.TX_TransmittingMessage.Flags := 3;
BufferPtr^.TX_XOR_Byte := 0;
for i := 0 to 2 do
BufferPtr^.TX_XOR_Byte := BufferPtr^.TX_XOR_Byte xor BufferPtr^.TX_TransmittingMessage.MessageBytes[i];
BufferPtr^.TX_PreambleBitCount := PreambleCount;
Inc(ServiceModeInfo.TotalSent);
end;
Scroll down a few line to see where it is called:
Code: Select all
procedure Direct_Instruction(ServiceMode_State: Byte; InstructionCode: Byte; BufferPtr: PDCCBufferInfo; PreambleCount: Byte);
begin
if ServiceModeInfo.iStateMachinePacket = 2 then // Start looking for an ACK from the decoder after the packet sent to the decoder
ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_SCAN_FOR_ACK_BIT := 1;
if ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_DETECTED_BIT = 1 then // Break off once a ACK is detected
begin
case ServiceMode_State of
STATE_SERVICEMODE_DIRECT_INSTRUCTION_WRITE,
STATE_SERVICEMODE_DIRECT_INSTRUCTION_BIT_WRITE : Direct_HandleAckDetected(BufferPtr, STATE_SERVICEMODE_DIRECT_WRITE_RECOVER_CYCLE, PreambleCount);
STATE_SERVICEMODE_DIRECT_INSTRUCTION_READ,
STATE_SERVICEMODE_DIRECT_INSTRUCTION_BIT_READ : Direct_HandleAckDetected(BufferPtr, STATE_SERVICEMODE_DIRECT_SEQUENCE_COMPLETE, PreambleCount);
end
end else
begin
Direct_LoadMessage(BufferPtr, ServiceMode_State, InstructionCode, PreambleCount); << CALLED HERE
So if I run this program on my custom CCA and set a breakpoint on
Code: Select all
Direct_LoadMessage(BufferPtr, ServiceMode_State, InstructionCode, PreambleCount);
Here are the passed parameter values:
BufferPtr = 0x0906; Correct
ServiceMode_State = 12; Correct
InstructionCode = 116; Correct
PreambleCount = 20; Correct;
I now step into Direct_LoadMessage
BufferPtr = 0x0906; Correct
ServiceMode_State = 12; Correct
InstructionCode = 12; INCORRECT!!!!!!!!!!!!!!!!!!!!
PreambleCount = 20; Correct;
Here is the generated code setting up the passed registers into the function:
Code: Select all
;NMRA_DCC.mpas,715 :: Direct_LoadMessage(BufferPtr, ServiceMode_State, InstructionCode, PreambleCount);
0x31EC 0x781F8A PUSH WREG10
0x31EE 0x781F8A PUSH WREG10
0x31F0 0x78050C MOV WREG12, WREG10
0x31F2 0x7805CF POP WREG11
0x31F4 0x78460B MOV.B WREG11, WREG12
0x31F6 0x07F919 RCALL NMRA_DCC_Direct_LoadMessage
0x31F8 0x78054F POP WREG10
And the code to at the entry point into the function
Code: Select all
NMRA_DCC_Direct_LoadMessage:
0x242A 0xFA0000 LNK #0
;NMRA_DCC.mpas,672 :: begin
;NMRA_DCC.mpas,673 :: BufferPtr^.TX_TransmittingMessage.MessageBytes[0] := OpCode or (ServiceModeInfo.Buffer.Address shr 8);
0x242C 0x450164 ADD WREG10, #4, WREG2
0x242E 0x8071B0 MOV _ServiceModeInfo+26, WREG0
0x2430 0xDE00C8 LSR WREG0, #8, WREG1
0x2432 0xFB800C ZE WREG12, WREG0
0x2434 0x700001 IOR WREG0, WREG1, WREG0
0x2436 0x784900 MOV.B WREG0, [WREG2]
;NMRA_DCC.mpas,674 :: BufferPtr^.TX_TransmittingMessage.MessageBytes[1] := ServiceModeInfo.Buffer.Address and Word($00FF);
0x2438 0x450064 ADD WREG10, #4, WREG0
Something seems wrong in the setup of the register:
Code: Select all
;NMRA_DCC.mpas,715 :: Direct_LoadMessage(BufferPtr, ServiceMode_State, InstructionCode, PreambleCount);
0x31EC 0x781F8A PUSH WREG10
0x31EE 0x781F8A PUSH WREG10
0x31F0 0x78050C MOV WREG12, WREG10
0x31F2 0x7805CF POP WREG11
Why is WREG10 pushed to the stack twice and popped into WREG11. Up to the pop WREG11 contains the correct value for OpCode (116). After the pop 116 is not in any registers.
The way I fixed this was to changed the type of one of the parameters, the first Byte is now a Boolean;
Code: Select all
procedure Direct_LoadMessage(BufferPtr: PDCCBufferInfo; IsBitMode: Boolean; OpCode: Byte; PreambleCount: Byte);
var
i: Integer;
begin
BufferPtr^.TX_TransmittingMessage.MessageBytes[0] := OpCode or (ServiceModeInfo.Buffer.Address shr 8);
BufferPtr^.TX_TransmittingMessage.MessageBytes[1] := ServiceModeInfo.Buffer.Address and Word($00FF);
if IsBitMode then
BufferPtr^.TX_TransmittingMessage.MessageBytes[2] := %11100000 or ServiceModeInfo.Buffer.Value
else
BufferPtr^.TX_TransmittingMessage.MessageBytes[2] := ServiceModeInfo.Buffer.Value;
BufferPtr^.TX_TransmittingMessage.Flags := 3;
BufferPtr^.TX_XOR_Byte := 0;
for i := 0 to 2 do
BufferPtr^.TX_XOR_Byte := BufferPtr^.TX_XOR_Byte xor BufferPtr^.TX_TransmittingMessage.MessageBytes[i];
BufferPtr^.TX_PreambleBitCount := PreambleCount;
Inc(ServiceModeInfo.TotalSent);
end;
And called it like this:
Code: Select all
procedure Direct_Instruction(ServiceMode_State: Byte; InstructionCode: Byte; BufferPtr: PDCCBufferInfo; PreambleCount: Byte);
var
IsBitMode: Boolean;
begin
if ServiceModeInfo.iStateMachinePacket = 2 then // Start looking for an ACK from the decoder after the packet sent to the decoder
ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_SCAN_FOR_ACK_BIT := 1;
if ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_DETECTED_BIT = 1 then // Break off once a ACK is detected
begin
case ServiceMode_State of
STATE_SERVICEMODE_DIRECT_INSTRUCTION_WRITE,
STATE_SERVICEMODE_DIRECT_INSTRUCTION_BIT_WRITE : Direct_HandleAckDetected(BufferPtr, STATE_SERVICEMODE_DIRECT_WRITE_RECOVER_CYCLE, PreambleCount);
STATE_SERVICEMODE_DIRECT_INSTRUCTION_READ,
STATE_SERVICEMODE_DIRECT_INSTRUCTION_BIT_READ : Direct_HandleAckDetected(BufferPtr, STATE_SERVICEMODE_DIRECT_SEQUENCE_COMPLETE, PreambleCount);
end
end else
begin
IsBitMode := (ServiceMode_State = STATE_SERVICEMODE_DIRECT_INSTRUCTION_BIT_WRITE) or (ServiceMode_State = STATE_SERVICEMODE_DIRECT_INSTRUCTION_BIT_READ);
Direct_LoadMessage(BufferPtr, IsBitMode, InstructionCode, PreambleCount);
Here are the passed parameter values of a test:
BufferPtr = 0x0906; Correct
IsBitMode = False; Correct
InstructionCode = 116; Correct
PreambleCount = 20; Correct;
I now step into Direct_LoadMessage
BufferPtr = 0x0906; Correct
IsBitMode = False; Correct
InstructionCode = 116; CORRECT THIS TIME!!!!!!!!!!!!!!!!!!!!
PreambleCount = 20; Correct;
Again I know this is a large program but it seems that this should be enough detail to track down the problem. This is a nasty problem that can really cause strange bugs in user code and waste a lot of time tracking down.
Thanks,
Jim