Completely at a loss...
-
- Posts: 417
- Joined: 10 Jan 2009 22:03
Completely at a loss...
Hi,
I have a large code base that implements a protocol for a model train communication bus I am prototyping. This code base is written so I can run it in Lazarus to debug then I have files that I link in for specific IO hardware/modules (CAN, Ethernet, EEPROM, SRAM, Disk File, etc).
This code base runs in Lazarus in a thread (or two) looping round robin, just like in the micro. It also runs on many variants of dsPIC using the mikroPascal compiler. I was expecting a simple transition to PIC32 since all I had to to was figure out the specific IO modules for the PIC32 with the core code that has lots of history behind it.
Well I can't even get my core code to enter the first phase of my main state machine with mikroPascal for PIC32. It does all sorts of bizarre things such as entering if/then blocks before I set the bit flag to start the core state machine running. It starts to run the state machine then gets "stuck" somewhere and won't continue down the case statement or it will simply stop executing the main loop and timer interrupts (I am assuming it is hitting an exception or something). Everytime I hit the reset button it fails in a different way but I have not had it run more than 10 cycle of my main state machine before it dies.
The code does not use the micro controller type syntax so it uses more general Pascal for setting bits and such. I know it is not efficient but having it run in Lazarus speeds development time and prototyping drastically.
I have a ticket in for a strange timing problem that changes behavior if I add a few nops in key places. Is this part of the issue? I don't know. Has anyone else made this transition and found old code that worked fine in other micro controllers won't work with the PIC32? Does anyone have any thoughts? I am totally stumped to even know how to proceed to figure out what is going on...
Jim
I have a large code base that implements a protocol for a model train communication bus I am prototyping. This code base is written so I can run it in Lazarus to debug then I have files that I link in for specific IO hardware/modules (CAN, Ethernet, EEPROM, SRAM, Disk File, etc).
This code base runs in Lazarus in a thread (or two) looping round robin, just like in the micro. It also runs on many variants of dsPIC using the mikroPascal compiler. I was expecting a simple transition to PIC32 since all I had to to was figure out the specific IO modules for the PIC32 with the core code that has lots of history behind it.
Well I can't even get my core code to enter the first phase of my main state machine with mikroPascal for PIC32. It does all sorts of bizarre things such as entering if/then blocks before I set the bit flag to start the core state machine running. It starts to run the state machine then gets "stuck" somewhere and won't continue down the case statement or it will simply stop executing the main loop and timer interrupts (I am assuming it is hitting an exception or something). Everytime I hit the reset button it fails in a different way but I have not had it run more than 10 cycle of my main state machine before it dies.
The code does not use the micro controller type syntax so it uses more general Pascal for setting bits and such. I know it is not efficient but having it run in Lazarus speeds development time and prototyping drastically.
I have a ticket in for a strange timing problem that changes behavior if I add a few nops in key places. Is this part of the issue? I don't know. Has anyone else made this transition and found old code that worked fine in other micro controllers won't work with the PIC32? Does anyone have any thoughts? I am totally stumped to even know how to proceed to figure out what is going on...
Jim
Re: Completely at a loss...
Hi Jim,This code base runs in Lazarus in a thread (or two) looping round robin, just like in the micro.
I also use this approach, but with Delphi. The first thing I am thinking is to make sure you use 32-bit pointers, and if you work with pointer arithmetics, there are some differences between a PIC32 and a PC. One of the first problems I encountered was that Boolean type is 32-bits long in PIC32 and 8-bits in Delphi. So, I had to change it to LongBool to match type sizes. Also, function calls by pointers are a bit different, since the memory scheme is different.
Regarding the strange behaviors you describe here, I have no idea but being some memory overlap problem. In my project, I use memory overlap of different structures (records) to "emulate" some class style inheritance and mikroPascal for PIC32 does the job nicely.
Although I never tried it, there is some post on this forum, about an year old, about writing an exception handler for PIC32. It might help. http://www.mikroe.com/forum/viewtopic.p ... ap#p212402
HTH
Re: Completely at a loss...
Jim,
i cannot confirm such behaviour, i migrated several projects to PIC32 and was surprised to see how wel this works. One possible reason can be the speed, i imagine you have digital inputs on your system and debouncing of these can be important as the pic is a lot faster than the train!
Allthough i understand the idea, i develop always on the pic, debug mainly through a uart reserved for this purpose as in the end MP and Lazarus have their differences.
i cannot confirm such behaviour, i migrated several projects to PIC32 and was surprised to see how wel this works. One possible reason can be the speed, i imagine you have digital inputs on your system and debouncing of these can be important as the pic is a lot faster than the train!
Allthough i understand the idea, i develop always on the pic, debug mainly through a uart reserved for this purpose as in the end MP and Lazarus have their differences.
Au royaume des aveugles, les borgnes sont rois.
-
- Posts: 417
- Joined: 10 Jan 2009 22:03
Re: Completely at a loss...
jpc:
The code had not reached a place where it is looking at IO pins yet, except for where it write to the CAN module. In the example I sent mE I have that commented out so it does a "virtual write to somewhere" and immediately succeeds and returns. This takes any question about my interrupt driven CAN code out of the picture.
Where it is failing is such a simple part of the code base, no IO read/write, a handful of CAN writes but like I said I have bypassed this and just tell the code base it is sent and all went well. It just runs a state machine and a timer to effectively log into the layout control bus over the CAN by sending a correctly timed sequence of messages.
Vcc:
The 32 bit pointer were my first thought too. The things I am doing where the problems are is:
1) I have pointers to data structures but I am letting the compiler figure out the address for me
2) I do have constants in FLASH that I access by address. I have read the help and I think the way it is done in the dsPIC is still valid in the PIC32.
Here is how simple the code is:
Main Loop:
Here is what is called to Process:
I have put a UART write statement after :
if OPStack.State and OPS_PROCESSING <> 0 then
and it has hit the UART write and printed out that OPState.State = $0000 Why did it enter that statement?
It is weird because sometimes it enters that block immediately other times, after a reset it can sit there for minutes then suddenly jump into that block.
In the main loop sending the UART "4" is what sets the OPS_PROCESSING bit in OPStack.State to start the state machine.
The pointer stuff looks like this:
So you can see I don't assume the number of bits any pointers are, I allow the compiler to define that.
All this code is open to anyone. Would either of you have time to take a look at it? I am testing it on a Fusion 7 with the PIC32MX795F512L, like I said if I pull that out and plug in the dsPIC33EP512MU810 (running at 120Hhz) and compile with the dsPIC compiler it will run trains all day long without a hitch.
I can prune the code base and give you a link to a zip with just what you need to compile it. Like I said it is not hard to see the issues. I can also create a dsPIC specific version so you can see what is suppose to happen. When I say this I have debug UART statements that show the progression through the state machine. You don't need anything connected to CAN to make it work, just the Fusion 7 and the PIC32 board with cables to connect to UART A on the board.
Jim
The code had not reached a place where it is looking at IO pins yet, except for where it write to the CAN module. In the example I sent mE I have that commented out so it does a "virtual write to somewhere" and immediately succeeds and returns. This takes any question about my interrupt driven CAN code out of the picture.
Where it is failing is such a simple part of the code base, no IO read/write, a handful of CAN writes but like I said I have bypassed this and just tell the code base it is sent and all went well. It just runs a state machine and a timer to effectively log into the layout control bus over the CAN by sending a correctly timed sequence of messages.
Vcc:
The 32 bit pointer were my first thought too. The things I am doing where the problems are is:
1) I have pointers to data structures but I am letting the compiler figure out the address for me
2) I do have constants in FLASH that I access by address. I have read the help and I think the way it is done in the dsPIC is still valid in the PIC32.
Here is how simple the code is:
Main Loop:
Code: Select all
while True do
begin
OPStackCore_Process;
// this does nothing as I am not sending any UART data when the issues occur, this is for debugging
if UART1_Data_Ready then
begin
case UART1_Read of
'1' : OPStackBuffers_PrintBuffers;
'2' : DumpEEProm(EEPROM_BANK_0, False, 0, 255, UART_1);
'3' : _25AAxxxx_Erase(EEPROM_BANK_0);
'4' : OPStackCore_Enable(True);
end;
end;
end;
Code: Select all
// *****************************************************************************
// procedure OPStackCore_Process
// Parameters:
// Returns:
// Description:
// *****************************************************************************
function OPStackCore_Process: PNMRAnetnode;
begin
if OPStack.State and OPS_PROCESSING <> 0 then
begin
Result := OPStackNode_NextNode;
if Result <> nil then
begin
NodeRunStateMachine(Result);
AppCallback_UserStateMachine_Process(Result);
end;
ProcessHardwareMessages;
end;
end;
if OPStack.State and OPS_PROCESSING <> 0 then
and it has hit the UART write and printed out that OPState.State = $0000 Why did it enter that statement?
It is weird because sometimes it enters that block immediately other times, after a reset it can sit there for minutes then suddenly jump into that block.
In the main loop sending the UART "4" is what sets the OPS_PROCESSING bit in OPStack.State to start the state machine.
The pointer stuff looks like this:
Code: Select all
type
TNMRAnetNode = record
iIndex: Byte; // Index in the main array
State: Byte; // See the NS_xxxx flags; State of the Node
Events: TNodeEvents;
Info: TNodeInfo; // Information about a Node
Login: TNMRAnetNodeLoginInfo; // Login Information
Flags: Word; // Message Flags for messages passed to the Node through a simple set bit (no complex reply data needed like destination Alias), see the MF_xxxx flags
iStateMachine: Byte; // Statemachine index for the main bus login
IncomingMessages: POPStackMessage; // Linked List of Messages incoming to process for the node
OutgoingMessages: POPStackMessage; // Linked List of Messages outgoing from the node, mainly for Datagrams and Streams
{$IFDEF FPC}
UserData: Pointer;
{$ELSE}
UserData: ^Byte; // Pointer to User Data
{$ENDIF}
iUserStateMachine: Byte; // For user (application level) statemachine
UserWatchdog_1s: Word; // For user
{$IFDEF SUPPORT_TRACTION}TrainData: TTrainData;{$ENDIF} // Realtime information about the Train Node
end;
PNMRAnetNode = ^TNMRAnetNode;
All this code is open to anyone. Would either of you have time to take a look at it? I am testing it on a Fusion 7 with the PIC32MX795F512L, like I said if I pull that out and plug in the dsPIC33EP512MU810 (running at 120Hhz) and compile with the dsPIC compiler it will run trains all day long without a hitch.
I can prune the code base and give you a link to a zip with just what you need to compile it. Like I said it is not hard to see the issues. I can also create a dsPIC specific version so you can see what is suppose to happen. When I say this I have debug UART statements that show the progression through the state machine. You don't need anything connected to CAN to make it work, just the Fusion 7 and the PIC32 board with cables to connect to UART A on the board.
Jim
-
- Posts: 417
- Joined: 10 Jan 2009 22:03
Re: Completely at a loss...
As I proof read this one thing I have not thought of is I am using a function but I am not using the reply in this code... I need to assign a result, or change it to a procedure to see if that solves the first issue with the if/then statement....
Jim
Jim
Re: Completely at a loss...
Code: Select all
{$IFDEF FPC}
UserData: Pointer;
{$ELSE}
UserData: ^Byte; // Pointer to User Data
{$ENDIF}
Re: Completely at a loss...
I have three questions:
1. How is OPStack.State initialized ?
2. Can OPStack.State be modified by some "unexpected/unseen/unnoticed" external event in another thread (e.g interrupt) after evaluating ?
3. Is is reproducible on simulator ?
There may be some initialization difference between PC and PIC32 of global vars. I don't know which variables are initialized by PC compilers by default, but as far as i know, mikroPascal for PIC32 doesn't initialize variables by default.
The following code works as expected on PIC32MX795F512L (@80MHz):
If I comment , the LED never gets lit.
1. How is OPStack.State initialized ?
2. Can OPStack.State be modified by some "unexpected/unseen/unnoticed" external event in another thread (e.g interrupt) after evaluating
Code: Select all
if OPStack.State and OPS_PROCESSING <> 0 then
3. Is is reproducible on simulator ?
There may be some initialization difference between PC and PIC32 of global vars. I don't know which variables are initialized by PC compilers by default, but as far as i know, mikroPascal for PIC32 doesn't initialize variables by default.
The following code works as expected on PIC32MX795F512L (@80MHz):
Code: Select all
var
LED1: sbit at LATG.12;
type
//unknown types
TNodeEvents = DWord;
TNodeInfo = DWord;
TNMRAnetNodeLoginInfo = DWord;
POPStackMessage = DWord;
TNMRAnetNode = record
iIndex: Byte; // Index in the main array
State: Byte; // See the NS_xxxx flags; State of the Node
Events: TNodeEvents;
Info: TNodeInfo; // Information about a Node
Login: TNMRAnetNodeLoginInfo; // Login Information
Flags: Word; // Message Flags for messages passed to the Node through a simple set bit (no complex reply data needed like destination Alias), see the MF_xxxx flags
iStateMachine: Byte; // Statemachine index for the main bus login
IncomingMessages: POPStackMessage; // Linked List of Messages incoming to process for the node
OutgoingMessages: POPStackMessage; // Linked List of Messages outgoing from the node, mainly for Datagrams and Streams
{$IFDEF FPC}
UserData: Pointer;
{$ELSE}
UserData: ^Byte; // Pointer to User Data
{$ENDIF}
iUserStateMachine: Byte; // For user (application level) statemachine
UserWatchdog_1s: Word; // For user
{$IFDEF SUPPORT_TRACTION}TrainData: TTrainData;{$ENDIF} // Realtime information about the Train Node
end;
PNMRAnetNode = ^TNMRAnetNode;
type
TOPStack = record
State: Word; // The State of the OPStack Library, see the OPS_xxx flags
_1sCounter: Byte; // Counts 10 100ms timer ticks to update items at a 1s rate
end;
var
OPStack: TOPStack;
const
OPS_PROCESSING = $0001; // Start and stops the main StateMachine for running. Default is Off on startup Allows holding off OLCB processing until the node is read (Ethernet link is up, etc)
function OPStackCore_Process: PNMRAnetnode;
begin
Result := nil;
if OPStack.State and OPS_PROCESSING <> 0 then
begin
//
LED1 := 1;
end;
end;
var
Counter: DWord;
begin
Delay_ms(100);
TRISG.12 := 0;
LED1 := 0;
Counter := 0;
OPStack.State := 0; //init state to 0
repeat
Inc(Counter);
if Counter = 10000000 then
OPStack.State := 1;
OPStackCore_Process;
until False;
end.
Code: Select all
if Counter = 10000000 then
OPStack.State := 1;
-
- Posts: 417
- Joined: 10 Jan 2009 22:03
Re: Completely at a loss...
Yes I have noticed the PIC32 compiler is a bit different than the dsPIC. A thread a while ago from mE said to write portable code use ^Byte as it is compatible with any pointer type. Like you said in the PIC32 if define like this then any dereferencing you do will _only_ effect 8 bits of the data pointed to. The dsPIC compiler seems to work differently. It is a bit tricky (ending in ugly typcasting) to write code that work across mP compiler and Lazarus (both 32 and 64 bit).VCC wrote:This the stuff I was talking about. Perhaps I'm wrong, but I would change ^Byte to ^DWord.Code: Select all
{$IFDEF FPC} UserData: Pointer; {$ELSE} UserData: ^Byte; // Pointer to User Data {$ENDIF}
I have not reached a point in my code where these issues would make a difference... yet.
1) Good point, before I left for work this morning I noticed running in the ICD build that some of the variables in theI have three questions:
1. How is OPStack.State initialized ?
2. Can OPStack.State be modified by some "unexpected/unseen/unnoticed" external event in another thread (e.g interrupt) after evaluating
Code: Select all
if OPStack.State and OPS_PROCESSING <> 0 then
?
3. Is is reproducible on simulator ?
Code: Select all
TNMRAnetNode = record
were not initialized like I thought they should be. I will check tonight.
2) No, I do check
also in a timer interrupt to see if the library should be incremented with its 100ms timer, but I never change the state variable anywhere else.if OPStack.State and OPS_PROCESSING <> 0 then
3) Again I noticed this morning that it would not "do the wrong" thing running in the IDC simulator..... It is starting to point to not initializing variables that I think I am.
Jim
-
- Posts: 417
- Joined: 10 Jan 2009 22:03
Re: Completely at a loss...
Nope, all is initialized.....
and the _only_ place that I write to this variable is when I enabled the state machine:
other than that I test it in 4 places in the code with the same test:
Jim
Code: Select all
begin
{ Main program }
TRISF12_bit := 0;
LATF12_bit := 0;
TRISF13_bit := 0;
LATF13_bit := 0;
OPStackCore_Initialize; <<<<<<<
Code: Select all
procedure OPStackCore_Initialize;
begin
OPStack.State := 0;
OPStack._1sCounter := 0;
OPStackDefines_Initialize;
.......
end;
Code: Select all
procedure OPStackCore_Enable(DoEnable: Boolean);
begin
if DoEnable then
OPStack.State := OPStack.State or OPS_PROCESSING
else
OPStack.State := OPStack.State and not OPS_PROCESSING;
end;
Code: Select all
OPStack.State and OPS_PROCESSING <> 0
-
- Posts: 417
- Joined: 10 Jan 2009 22:03
Re: Completely at a loss...
I you want the real code here is this project:
http://sourceforge.net/p/openlcb/svn/HE ... ck_Bug.zip
The project is
\OPStack_Bug\Projects\PIC32MX_Basic
Jim
http://sourceforge.net/p/openlcb/svn/HE ... ck_Bug.zip
The project is
\OPStack_Bug\Projects\PIC32MX_Basic
Jim
Re: Completely at a loss...
I can't look at the code any sooner than weekend, so I hope it's not a problem.
Re: Completely at a loss...
Jim,
in order to build this number of units are missing :
in order to build this number of units are missing :
Code: Select all
unit MCU_Setup_PIC32MXxxx;
uses
[b]M25P80_Driver,
PIC32MX_CAN_RawBuffers,
template_hardware,
PIC32MX_CAN;[/b]
Au royaume des aveugles, les borgnes sont rois.
-
- Posts: 417
- Joined: 10 Jan 2009 22:03
Re: Completely at a loss...
Ah, yes this is a frustration I have with the mE compilers and paths. I wish the IDE would use relative paths and not absolute paths....
Open the "Edit Search Paths" menu and "Delete Invalid Paths". Then add
\OPStack_Bug\Projects\PIC32MX_Basic\Templates
\OPStack_Bug\HardwareLayerImplementations\PIC32MX_CAN
\OPStack_Bug\ConfigurationLayerImplementations\_M25P80_SPI
These are the interface files to external modules specific to the device I am compiling for.
All the files are there to compile, you just need to get the paths to all the folders in the zip added.
Jim
Open the "Edit Search Paths" menu and "Delete Invalid Paths". Then add
\OPStack_Bug\Projects\PIC32MX_Basic\Templates
\OPStack_Bug\HardwareLayerImplementations\PIC32MX_CAN
\OPStack_Bug\ConfigurationLayerImplementations\_M25P80_SPI
These are the interface files to external modules specific to the device I am compiling for.
All the files are there to compile, you just need to get the paths to all the folders in the zip added.
Jim
-
- Posts: 417
- Joined: 10 Jan 2009 22:03
Re: Completely at a loss...
Here is what you should see:
So here is something I have not discussed here yet. If I run this with a scope on pin LATF13_bit from above this pin toggles every 20 MILLISECONDS.......
If I add a few nops here:
The pin toggles every 500NANOSECONDS which makes more sense.
That is what I have in as a ticket.
So for the issues discussed here uncomment everything and connect a cable to UART A:
Now if you hyper link into NodeRunStateMachine you can see that if this state machine runs it will print out states on the UART as it goes (if you uncomment TRACE_MAIN_STATEMACHINE at the top of the file).
The first states should just run
When it should put a message out on the CAN bus it does everything up until the actual time it talks to the CAN module, there I just do this:
So it succeeds and prints out a message that you "Fake Transmitted on the CAN bus"
Once you get to the "STATE_NODE_WAITSTATE" state in the state machine it is waiting for 500ms to pass so that is in the main file Timer Interrupt
You will need to uncomment the call that actually increments the tick count in the Node record.
Now to start the state machine send a "2" on the UART
After doing all this what you should see is
1) "STARTED" is printed on the UART before you send a "2" in order to start the state machine.
2) The main state that is the "run" state is "STATE_NODE_PERMITTED". I don't have a UART print there because that state is call for the lifetime of the node on the network so that just overloads the UART. I have only gotten it to make it to the STATE_NODE_PERMITTED state a couple of times. It typically just stops running (the two pins I have toggling in the main loop and 100ms timer stop toggling).
Thanks for looking at this. I know the compiler can't be that messed up since you guy are not having issues. It has to be something boneheaded I am doing.....
Jim
Code: Select all
begin
{ Main program }
TRISF12_bit := 0;
LATF12_bit := 0;
TRISF13_bit := 0;
LATF13_bit := 0;
OPStackCore_Initialize;
MCU_Setup_Initialize;
MCU_EnableSerialFlash;
MCU_EnableUARTA;
MCU_Enable100msTimer;
MCU_EnableCAN;
EnableInterrupts;
UART2_Write_Text('Configured' + LF);
while True do
begin
OPStackCore_Process; // BUG: Go to this function and uncomment the nop; nop line to fix the problem.....
LATF13_bit := not LATF13_bit;
if UART2_Data_Ready = 1 then
begin
case UART2_Read of
'1' : ON__T5CON_bit := not ON__T5CON_bit;
'2' : begin
OPStackCore_Initialize;
OPStackCore_Enable(True);
end;
'3' : begin
OPStackCore_Enable(False);
end;
end;
end;
end;
Code: Select all
function OPStackCore_Process: PNMRAnetnode;
begin
Result := nil;
if OPStack.State and OPS_PROCESSING <> 0 then
// if OPStack.State and OPS_PROCESSING = OPS_PROCESSING then
begin
// Result := OPStackNode_NextNode;
if Result <> nil then
begin
// NodeRunStateMachine(Result);
// AppCallback_UserStateMachine_Process(Result); // Do I want to let this run with nil? Why should there be a nil? There shouldn't
end;
// ProcessHardwareMessages;
end;
end;
Code: Select all
function OPStackCore_Process: PNMRAnetnode;
begin
nop; nop; // <<<<<<<<<HERE
Result := nil;
if OPStack.State and OPS_PROCESSING <> 0 then
// if OPStack.State and OPS_PROCESSING = OPS_PROCESSING then
begin
// Result := OPStackNode_NextNode;
if Result <> nil then
begin
// NodeRunStateMachine(Result);
// AppCallback_UserStateMachine_Process(Result); // Do I want to let this run with nil? Why should there be a nil? There shouldn't
end;
// ProcessHardwareMessages;
end;
end;
That is what I have in as a ticket.
So for the issues discussed here uncomment everything and connect a cable to UART A:
Code: Select all
function OPStackCore_Process: PNMRAnetnode;
begin
Result := nil;
if OPStack.State and OPS_PROCESSING <> 0 then
begin
Result := OPStackNode_NextNode;
if Result <> nil then
begin
NodeRunStateMachine(Result);
AppCallback_UserStateMachine_Process(Result);
end;
ProcessHardwareMessages;
end;
end;
Code: Select all
procedure NodeRunStateMachine(Node: PNMRAnetNode);
var
OPStackMessage: POPStackMessage;
CAN_MTI: DWord;
i: Integer;
begin
OPStackMessage := nil;
case Node^.iStateMachine of
STATE_NODE_START :
begin {$IFDEF TRACE_MAIN_STATEMACHINE}UART2_Write_Text('STATE_NODE_START'+LF);{$ENDIF}
UART2_Write_Text('STARTED' + LF);
Node^.Login.iCID := 0;
Node^.iStateMachine := STATE_NODE_TRANSMIT_CID;
end;
STATE_NODE_GENERATE_NODE_ALIAS :
begin {$IFDEF TRACE_MAIN_STATEMACHINE}UART2_Write_Text('STATE_NODE_GENERATE_NODE_ALIAS'+LF);{$ENDIF}
Node^.Info.AliasID := NMRAnetUtilities_CreateAliasID(Node^.Login.Seed, False);
Node^.Login.iCID := 0;
Node^.iStateMachine := STATE_NODE_TRANSMIT_CID;
end;
STATE_RANDOM_NUMBER_GENERATOR :
begin {$IFDEF TRACE_MAIN_STATEMACHINE}UART2_Write_Text('STATE_RANDOM_NUMBER_GENERATOR'+LF);{$ENDIF}
NMRAnetUtilities_PsudoRandomNumberGeneratorOnSeed(Node^.Login.Seed);
Node^.iStateMachine := STATE_NODE_GENERATE_NODE_ALIAS;
end;
STATE_NODE_TRANSMIT_CID :
begin {$IFDEF TRACE_MAIN_STATEMACHINE}UART2_Write_Text('STATE_NODE_TRANSMIT_CID'+LF);{$ENDIF}
Hardware_DisableInterrupts;
if IsOutgoingBufferAvailable then
When it should put a message out on the CAN bus it does everything up until the actual time it talks to the CAN module, there I just do this:
Code: Select all
procedure PIC32MX_StartTransmission(Buffer: PNMRAnetCanBuffer; IsExtended: Boolean);
var
Next: PCANRawBuffer;
begin
if Buffer <> nil then // If there is something to send then send it
begin
UART2_Write_Text('Tx''ing' + LF);
{
PIC32MX_CAN_Transmitting := True;
Next := Map_Physical_To_KSEG0( PIC32MX_CAN_Next_Buffer_Address(LocalCAN_Channel, FIFO_TX_LO_PRIORITY)); // Get where the next buffer to transmit is
PIC32MX_DMA_Style_Buffer(Buffer^, IsExtended, CAN_DIRECTION_WRITE, Next); // Convert it into a version that matches the registers
PIC32MX_CAN_Inc_Buffer_Index(LocalCAN_Channel, FIFO_TX_LO_PRIORITY); // Message is loaded move to the next one
PIC32MX_CAN_Tx_Interrupt_Empty_Enable(LocalCAN_Channel, FIFO_TX_LO_PRIORITY, True); // Fire the interrupt when the buffer is empty
PIC32MX_CAN_RequestTransmit(LocalCAN_Channel, FIFO_TX_LO_PRIORITY); // Set the Flag to start the transmission
UART2_Write_Text('Tx''ed');
}
end
end;
Once you get to the "STATE_NODE_WAITSTATE" state in the state machine it is waiting for 500ms to pass so that is in the main file Timer Interrupt
You will need to uncomment the call that actually increments the tick count in the Node record.
Code: Select all
procedure OPStack_100ms_Timer(); iv IVT_TIMER_5; iLevel 2; ics ICS_AUTO;
begin
T5IF_bit := 0;
OPStackCore_Timer; <<<< UNCOMMENT THIS
LATF12_bit := not LATF12_bit;
end;
Code: Select all
if UART2_Data_Ready = 1 then
begin
case UART2_Read of
'1' : ON__T5CON_bit := not ON__T5CON_bit;
'2' : begin
OPStackCore_Initialize; <<<<<< STARTS THE STATEMACHINE
OPStackCore_Enable(True);
end;
'3' : begin
OPStackCore_Enable(False);
end;
end;
1) "STARTED" is printed on the UART before you send a "2" in order to start the state machine.
Code: Select all
case Node^.iStateMachine of
STATE_NODE_START :
begin {$IFDEF TRACE_MAIN_STATEMACHINE}UART2_Write_Text('STATE_NODE_START'+LF);{$ENDIF}
UART2_Write_Text('STARTED' + LF);
Thanks for looking at this. I know the compiler can't be that messed up since you guy are not having issues. It has to be something boneheaded I am doing.....
Jim
Re: Completely at a loss...
First tests, on 795F512L, 80MHz, with small changes:
UART1 configured as UART1_Init(256000), instead of UART2_Init(230400), because of different hardware.
Sending #32#33 (enable, then disable FSM) to PIC32 through USART Terminal.
Receiving:
Configured
2Core_En: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
3Core_En: 0000
With in OPStackCore_Process function, the main loop LED toggles at 597KHz.
Without nop nop, it is a bit faster, as expected, it toggles at 615KHz.
I had to mention, I disabled the MCU_EnableSerialFlash call, because it gets stuck there. So far, there was no entering into the if OPStack.State and OPS_PROCESSING <> 0 then section with State being 0. However, it happened few times, that the PIC was reset, either by some EMI or by some exception. I don't know which one triggered the reset. So the new log looks like:
Configured
2Core_En: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
3Core_En: 0000
Configured
It never triggered a state machine "enable" event. Enabling/disabling Timer5 made no difference since there is still commented code in OPStackCore_Process function.
UART1 configured as UART1_Init(256000), instead of UART2_Init(230400), because of different hardware.
Code: Select all
var
AText: string[10];
ReadResult: Word; volatile;
begin
//.............
UART1_Write_Text('Configured' + LF);
while True do
begin
//UART1_Write_Text('loop' + LF);
//Delay_ms(100); //slow down a bit
OPStackCore_Process; // BUG: Go to this function and uncomment the nop; nop line to fix the problem.....
LATG13_bit := not LATG13_bit; //I use LATG
LATB.2 := not LATB.2; //I use this pin to measure frequency
if UART1_Data_Ready = 1 then
begin
ReadResult := UART1_Read; //use ReadResult to log its value
UART1_Write(ReadResult);
case ReadResult of
#0 : UART1_Write_Text('Wrong ReadResult'); //signal wrong commands
'1' : ON__T5CON_bit := not ON__T5CON_bit;
'2' : begin
OPStackCore_Initialize;
OPStackCore_Enable(True);
end;
'3' : begin
OPStackCore_Enable(False);
end;
end;
end;
end;
Code: Select all
var
ASendText: string[10];
function OPStackCore_Process: PNMRAnetnode;
begin
//nop; nop; // <<<<<<<<<HERE
Result := nil;
if OPStack.State and OPS_PROCESSING <> 0 then
// if OPStack.State and OPS_PROCESSING = OPS_PROCESSING then
begin
WordToHex(OPStack.State, ASendText);
UART1_Write_Text('Core_Proc: ' + ASendText + LF);
// Result := OPStackNode_NextNode;
if Result <> nil then
begin
// NodeRunStateMachine(Result);
// AppCallback_UserStateMachine_Process(Result); // Do I want to let this run with nil? Why should there be a nil? There shouldn't
end;
// ProcessHardwareMessages;
end;
end;
procedure OPStackCore_Enable(DoEnable: Boolean);
begin
if DoEnable then
OPStack.State := OPStack.State or OPS_PROCESSING
else
OPStack.State := OPStack.State and not OPS_PROCESSING;
WordToHex(OPStack.State, ASendText);
UART1_Write_Text('Core_En: ' + ASendText + LF);
end;
Receiving:
Configured
2Core_En: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
3Core_En: 0000
With
Code: Select all
nop; nop; // <<<<<<<<<HERE
Without nop nop, it is a bit faster, as expected, it toggles at 615KHz.
I had to mention, I disabled the MCU_EnableSerialFlash call, because it gets stuck there. So far, there was no entering into the if OPStack.State and OPS_PROCESSING <> 0 then section with State being 0. However, it happened few times, that the PIC was reset, either by some EMI or by some exception. I don't know which one triggered the reset. So the new log looks like:
Configured
2Core_En: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
Core_Proc: 0001
3Core_En: 0000
Configured
It never triggered a state machine "enable" event. Enabling/disabling Timer5 made no difference since there is still commented code in OPStackCore_Process function.