What appears to be happening is I have a few functions that encapsulate some formatting of strings for display on a GLCD. These functions are constantly interrupted in nested interrupts that contain a lot of function calls themselves. I am fairly sure the issues are do to the strings I am manipulating getting corrupted during and interrupt. I have seen the GLCD show a few random characters before the Address Trap was fired. Let me show some of the code that I have removed to solve the problem.
Some string constants:
Code: Select all
const
COMMANDSTATION_NAME = 'dspDCC';
COMPANY_NAME = 'by Mustangpeak';
STR_STATE_DATABASE = 'Database Information';
STR_STATE_QUEUE = 'DCC Queue Info';
STR_STATE_DCC = 'DCC Information';
STR_STATE_COMMANDSTATION = 'CommandStation State';
STR_STATE_ADC = 'Currents and Voltages';
// STR_STATE_DATABASE parameters
STR_SLOTS = 'Slots Used ';
STR_SLOTS_LEFT = 'Slots Open ';
STR_TRACK_QUEUE_PEAK = 'Trk Queue Pk ';
STR_TRACK_PRIORITY_QUEUE_PEAK = 'Trk PriQueue Pk';
STR_ACC_QUEUE_PEAK = 'Acc Queue Pk ';
// STR_STATE_ADC parameters
STR_3_3 = '3.3V ';
STR_5_0 = '5.0V ';
STR_12_0 = '12.0V ';
STR_BOOSTER1_CURRENT = 'DCC Output 1 ';
STR_BOOSTER2_CURRENT = 'DCC Output 2 ';
STR_PROG_BOOSTER_CURRENT = 'Prog Output ';
STR_ACC_BOOSTER_CURRENT = 'Accory Output ';
// STR_STATE_DCC parameters
STR_TRACK_PACKET_COUNT = 'Trk Pkts ';
STR_TRACK_PRIORITY_PACKET_COUNT = 'Pri Trk Pkts ';
STR_ACC_PACKET_COUNT = 'Acc Pkts ';
STR_PROG_PACKET_COUNT = 'Prog Pkts ';
STR_DCC_TIME = 'Max DCC Delta ';
STR_MAINLOOP_TIME = 'Max Loop T ';
// STR_STATE_COMMANDSTATION 1 parameters
STR_EMERGENCY_SHUTDOWN = 'Emgcy ShutDown ';
STR_EMERGENCY_STOP = 'Emgcy Stop ';
STR_BAUDRATE = 'BaudRate ';
STR_BOOSTER1 = 'Boost 1 Out ';
STR_BOOSTER2 = 'Boost 2 Out ';
STR_PROGRAMMING = 'Prog Track Out ';
STR_ACCESSORY = 'Accessory Out ';
// STR_STATE_COMMANDSTATION 2 parameters
STR_ACC_TO_TRACK_MAPPING = 'Acc to Track ';
STR_PROG_TO_TRACK_MAPPING = 'Prog to Track ';
STR_PROG_IN_SERVICEMODE = 'Service Mode ';
STR_ACK_IDLE_STATE = 'Svce Mode Idle ';
STR_SERVICEMODE_RESULTREQUEST_COUNT ='SM Rslt ';
STR_SERVICEMODE_QUEUE_COUNT = 'SM Queue ';
STR_US = 'us';
STR_MS = 'ms';
STR_115200 = '115200';
STR_38400 = '38400';
STR_57600 = '57600';
STR_19200 = '19200' ;
STR_ON = 'ON';
STR_OFF = 'OFF' ;
Code: Select all
function ADC_Channel_To_String(Channel: Byte; var S: string[15]): string[39];
var
_FloatStr: string[23];
_Units: string[1];
begin
Result := '';
SetADCSPIClock;
FloatToStr(real( SPI_Read_ADC_Channel(Channel)) * ADC_SCALING[Channel], _FloatStr);
TruncFloat(@_FloatStr, 2, 23);
SetPortExtenderSPIClock;
strcat2(Result, S, _FloatStr);
_Units := ADC_UNITS[Channel];
strcat2(Result, Result, _Units);
end;
function ComparisonToString(Comparison: Boolean; var S: string[15]): string[39];
begin
Result := '';
if Comparison then
strcat2(Result, S, STR_ON)
else
strcat2(Result, S, STR_OFF)
end;
Code: Select all
var
Str: string[39]; // Be careful that is long enough
Str2: string[5];
FloatStr: string[23];
procedure GUI_StateMachine;
var
Mask: Byte;
begin
if GUI_Info._840msTicks >= GUI_Info.Max_GUI_UpdateCount then
begin
SetPortExtenderSPIClock;
case GUI_Info.StateMachineIndex of
GUI_STATE_0 : // Database Information
begin
.....
end;
GUI_STATE_1 : // DCC Information
begin
......
end;
GUI_STATE_2 : // Commandstation Information
begin
case GUI_Info.SubStateMachineIndex of
GUI_SUBSTATE_0 :
begin
SPI_Glcd_Fill(0);
GUI_Info.Max_GUI_UpdateCount := 1;
SPI_Glcd_Write_Text(STR_STATE_COMMANDSTATION, 2, 0, 1);
Str := ComparisonToString(CommandStation.Flags.COMMANDSTATION_FLAGS_EMERGENCY_SHUTDOWN_BIT = 1, STR_EMERGENCY_SHUTDOWN);
SPI_Glcd_Write_Text(Str, 2, 1, 1);
Inc(GUI_Info.SubStateMachineIndex);
end;
GUI_SUBSTATE_1 :
begin
Inc(GUI_Info.SubStateMachineIndex);
Str := ComparisonToString(CommandStation.Flags.COMMANDSTATION_FLAGS_EMERGENCY_STOP_BIT = 1, STR_EMERGENCY_STOP);
SPI_Glcd_Write_Text(Str, 2, 2, 1);
Str := STR_BAUDRATE;
if CommandStation.Flags and COMMANDSTATION_FLAGS_BAUD_RATE_115200 = COMMANDSTATION_FLAGS_BAUD_RATE_115200 then Str := Str + STR_115200 else
if CommandStation.Flags and COMMANDSTATION_FLAGS_BAUD_RATE_38400 = COMMANDSTATION_FLAGS_BAUD_RATE_38400 then Str := Str + STR_38400 else
if CommandStation.Flags and COMMANDSTATION_FLAGS_BAUD_RATE_57600 = COMMANDSTATION_FLAGS_BAUD_RATE_57600 then Str := Str + STR_57600 else Str := Str + STR_19200;
SPI_Glcd_Write_Text(Str, 2, 3, 1);
end;
GUI_SUBSTATE_2 :
begin
Mask := CommandStation_DCC_Booster_Enabled_To_Mask;
Str := ComparisonToString(Mask and MASK_BOOSTER_ID_BOOSTER_1 <> 0, STR_BOOSTER1);
SPI_Glcd_Write_Text(Str, 2, 4, 1);
Str := ComparisonToString(Mask and MASK_BOOSTER_ID_BOOSTER_2 <> 0, STR_BOOSTER2);
SPI_Glcd_Write_Text(Str, 2, 5, 1);
Str := ComparisonToString(Mask and MASK_BOOSTER_ID_PROGRAMMING <> 0, STR_PROGRAMMING);
SPI_Glcd_Write_Text(Str, 2, 6, 1);
Str := ComparisonToString(Mask and MASK_BOOSTER_ID_ACCESSORY <> 0, STR_ACCESSORY);
SPI_Glcd_Write_Text(Str, 2, 7, 1);
Inc(GUI_Info.StateMachineIndex);
GUI_Info.SubStateMachineIndex := GUI_SUBSTATE_0;
GUI_Info.Max_GUI_UpdateCount := 5
end;
end;
end;
GUI_STATE_3 : // Commandstation Information
begin
case GUI_Info.SubStateMachineIndex of
GUI_SUBSTATE_0 :
begin
SPI_Glcd_Fill(0);
GUI_Info.Max_GUI_UpdateCount := 1;
SPI_Glcd_Write_Text(STR_STATE_COMMANDSTATION, 2, 0, 1);
Str := ComparisonToString(CommandStation.FlagsEx.COMMANDSTATION_FLAGSEX_MAP_ACC_TO_TRACK_BIT = 1, STR_ACC_TO_TRACK_MAPPING);
SPI_Glcd_Write_Text(Str, 2, 1, 1);
Inc(GUI_Info.SubStateMachineIndex);
end;
GUI_SUBSTATE_1 :
begin
Str := ComparisonToString(CommandStation.FlagsEx.COMMANDSTATION_FLAGSEX_MAP_PROG_TO_TRACK_BIT = 1, STR_PROG_TO_TRACK_MAPPING);
SPI_Glcd_Write_Text(Str, 2, 2, 1);
Str := ComparisonToString(ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_IN_SERVICEMODE_BIT = 1, STR_PROG_IN_SERVICEMODE);
SPI_Glcd_Write_Text(Str, 2, 3, 1);
Str := ComparisonToString(ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_IDLE_BIT = 1, STR_ACK_IDLE_STATE);
SPI_Glcd_Write_Text(Str, 2, 4, 1);
Inc(GUI_Info.SubStateMachineIndex);
end;
GUI_SUBSTATE_2 :
begin
.....
end;
end;
end;
GUI_STATE_4 : // Voltage and Current
begin
case GUI_Info.SubStateMachineIndex of
GUI_SUBSTATE_0 :
begin
SPI_Glcd_Fill(0);
GUI_Info.Max_GUI_UpdateCount := 1;
SPI_Glcd_Write_Text(STR_STATE_ADC, 2, 0, 1);
Str := ADC_Channel_To_String(4, STR_3_3);
SPI_Glcd_Write_Text(Str, 2, 1, 1);
Inc(GUI_Info.SubStateMachineIndex);
end;
GUI_SUBSTATE_1 :
begin
Str := ADC_Channel_To_String(5, STR_5_0);
SPI_Glcd_Write_Text(Str, 2, 2, 1);
Str := ADC_Channel_To_String(6, STR_12_0);
SPI_Glcd_Write_Text(Str, 2, 3, 1);
Inc(GUI_Info.SubStateMachineIndex);
end;
GUI_SUBSTATE_2 :
begin
Str := ADC_Channel_To_String(0, STR_BOOSTER1_CURRENT);
SPI_Glcd_Write_Text(Str, 2, 4, 1);
Str := ADC_Channel_To_String(1, STR_BOOSTER2_CURRENT);
SPI_Glcd_Write_Text(Str, 2, 5, 1);
Inc(GUI_Info.SubStateMachineIndex);
end;
GUI_SUBSTATE_3 :
begin
Str := ADC_Channel_To_String(2, STR_PROG_BOOSTER_CURRENT);
SPI_Glcd_Write_Text(Str, 2, 6, 1);
Str := ADC_Channel_To_String(3, STR_ACC_BOOSTER_CURRENT);
SPI_Glcd_Write_Text(Str, 2, 7, 1);
GUI_Info.StateMachineIndex := GUI_STATE_0;
GUI_Info.SubStateMachineIndex := GUI_SUBSTATE_0;
GUI_Info.Max_GUI_UpdateCount := 5
end;
end;
end;
end;
GUI_Info._840msTicks := 0;
end;
end;
Is there anything obvious that is wrong in this code? It compiles but it clearly is not "thread-safe" from interrupts.
Thanks,
Jim