Completely at a loss...

General discussion on mikroPascal PRO for PIC32.
Author
Message
JimKueneman
Posts: 417
Joined: 10 Jan 2009 22:03

Completely at a loss...

#1 Post by JimKueneman » 29 Jul 2014 05:09

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

VCC
Posts: 461
Joined: 08 Jun 2009 18:31
Location: Romania

Re: Completely at a loss...

#2 Post by VCC » 29 Jul 2014 05:27

This code base runs in Lazarus in a thread (or two) looping round robin, just like in the micro.
Hi Jim,
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

jpc
Posts: 1986
Joined: 22 Apr 2005 17:40
Location: France 87

Re: Completely at a loss...

#3 Post by jpc » 29 Jul 2014 08:57

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.
Au royaume des aveugles, les borgnes sont rois.

JimKueneman
Posts: 417
Joined: 10 Jan 2009 22:03

Re: Completely at a loss...

#4 Post by JimKueneman » 29 Jul 2014 14:14

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:

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;
Here is what is called to Process:

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;
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:

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;
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

JimKueneman
Posts: 417
Joined: 10 Jan 2009 22:03

Re: Completely at a loss...

#5 Post by JimKueneman » 29 Jul 2014 14:22

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

VCC
Posts: 461
Joined: 08 Jun 2009 18:31
Location: Romania

Re: Completely at a loss...

#6 Post by VCC » 29 Jul 2014 17:30

Code: Select all

{$IFDEF FPC}
    UserData: Pointer;
    {$ELSE}
    UserData: ^Byte;                                                            // Pointer to User Data
    {$ENDIF}
This the stuff I was talking about. Perhaps I'm wrong, but I would change ^Byte to ^DWord.

VCC
Posts: 461
Joined: 08 Jun 2009 18:31
Location: Romania

Re: Completely at a loss...

#7 Post by VCC » 29 Jul 2014 19:14

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

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.
If I comment

Code: Select all

if Counter = 10000000 then
      OPStack.State := 1; 
, the LED never gets lit.

JimKueneman
Posts: 417
Joined: 10 Jan 2009 22:03

Re: Completely at a loss...

#8 Post by JimKueneman » 29 Jul 2014 21:41

VCC wrote:

Code: Select all

{$IFDEF FPC}
    UserData: Pointer;
    {$ELSE}
    UserData: ^Byte;                                                            // Pointer to User Data
    {$ENDIF}
This the stuff I was talking about. Perhaps I'm wrong, but I would change ^Byte to ^DWord.
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).

I have not reached a point in my code where these issues would make a difference... yet.
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
Code: Select all
if OPStack.State and OPS_PROCESSING <> 0 then
?
3. Is is reproducible on simulator ?
1) Good point, before I left for work this morning I noticed running in the ICD build that some of the variables in the

Code: Select all

TNMRAnetNode = record

were not initialized like I thought they should be. I will check tonight.

2) No, I do check
if OPStack.State and OPS_PROCESSING <> 0 then
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.

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

JimKueneman
Posts: 417
Joined: 10 Jan 2009 22:03

Re: Completely at a loss...

#9 Post by JimKueneman » 30 Jul 2014 05:14

Nope, all is initialized.....

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;

and the _only_ place that I write to this variable is when I enabled the state machine:

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;
other than that I test it in 4 places in the code with the same test:

Code: Select all

OPStack.State and OPS_PROCESSING <> 0
Jim

JimKueneman
Posts: 417
Joined: 10 Jan 2009 22:03

Re: Completely at a loss...

#10 Post by JimKueneman » 30 Jul 2014 05:28

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

VCC
Posts: 461
Joined: 08 Jun 2009 18:31
Location: Romania

Re: Completely at a loss...

#11 Post by VCC » 30 Jul 2014 06:47

I can't look at the code any sooner than weekend, so I hope it's not a problem. :?

jpc
Posts: 1986
Joined: 22 Apr 2005 17:40
Location: France 87

Re: Completely at a loss...

#12 Post by jpc » 30 Jul 2014 09:03

Jim,

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.

JimKueneman
Posts: 417
Joined: 10 Jan 2009 22:03

Re: Completely at a loss...

#13 Post by JimKueneman » 30 Jul 2014 13:54

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

JimKueneman
Posts: 417
Joined: 10 Jan 2009 22:03

Re: Completely at a loss...

#14 Post by JimKueneman » 30 Jul 2014 14:15

Here is what you should see:

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;
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.......

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;
If I add a few nops here:

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;
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:

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;
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).

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
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:

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;
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.

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;
Now to start the state machine send a "2" on the UART

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;
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.

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);
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

VCC
Posts: 461
Joined: 08 Jun 2009 18:31
Location: Romania

Re: Completely at a loss...

#15 Post by VCC » 31 Jul 2014 21:01

First tests, on 795F512L, 80MHz, with small changes:
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;
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

Code: Select all

nop; nop;  // <<<<<<<<<HERE
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.

Post Reply

Return to “mikroPascal PRO for PIC32 General”