News:

;) This forum is the property of Proton software developers

Main Menu

PIC keeps resetting

Started by kcsl, Jul 28, 2024, 01:19 PM

Previous topic - Next topic

kcsl

I've been experimenting with CAN BUS and everything was going pretty good until I tried to get the PIC to raise an interrupt when a frame is received.

I've removed everything from the code and left just the bare bones and it's still doing it.

The below program will happily just sit there until a frame is received who's ID matches the filter and then it will just restart.
I know it's restarting because both LEDs flash as soon as the transmitting device sends the frame.
Disabling the CANRXB0 interrupt fixes the problem, so I'm fairly sure it's something to do with that.


Does anybody have any ideas please ?

Device 18F25K83     

    Device 18F25K83     
    Declare Optimiser_Level = 0


    ' Set to Internal OSC   
    Config_Start           
        FEXTOSC = OFF ;Oscillator not enabled
        RSTOSC = HFINTOSC_64MHZ ;HFINTOSC with HFFRQ = 64 MHz and CDIV = 1:1   
        CLKOUTEN = OFF ;CLKOUT function is disabled
        PR1WAY = OFF ;PRLOCK bit can be set and cleared repeatedly
        CSWEN = On ;Writing to NOSC and NDIV is allowed
        FCMEN = OFF ;Fail-Safe Clock Monitor disabled
        MCLRE = EXTMCLR ;If LVP = 0, MCLR pin is MCLR; If LVP = 1, RE3 pin function is MCLR
        PWRTS = PWRT_OFF ;PWRT is disabled
        MVECEN = On ;Multi-vector enabled, Vector table used for interrupts
        IVT1WAY = On ;IVTLOCK bit can be cleared and set only once
        LPBOREN = OFF ;ULPBOR disabled
        BOREN = NOSLP ;Brown-out Reset enabled while running, disabled in Sleep; SBOREN is ignored
        BORV = VBOR_2P45 ;Brown-out Reset Voltage (VBOR) set to 2.45V
        ZCD = OFF ;ZCD disabled. ZCD can be enabled by setting the ZCDSEN bit of ZCDCON
        PPS1WAY = OFF ;PPSLOCK bit can be set and cleared repeatedly (subject to the unlock sequence)
        STVREN = On ;Stack full/underflow will cause Reset
        Debug = OFF ;Background debugger disabled
        XINST = OFF ;Extended Instruction Set and Indexed Addressing Mode disabled
        WDTCPS = WDTCPS_31 ;Divider ratio 1:65536; software control of WDTPS
        WDTE = OFF ;WDT Disabled; SWDTEN is ignored
        WDTCWS = WDTCWS_7 ;window always open (100%); software control; keyed access not required
        WDTCCS = SC ;Software Control
        BBSIZE = BBSIZE_512 ;Boot Block size is 512 words
        BBEN = OFF ;Boot block disabled
        SAFEN = OFF ;SAF disabled
        WRTAPP = OFF ;Application Block not write protected
        WRTB = OFF ;Configuration registers (300000-30000Bh) not write-protected
        WRTC = OFF ;Boot Block (000000-0007FFh) not write-protected
        WRTD = OFF ;Data EEPROM not write-protected
        WRTSAF = OFF ;SAF not Write Protected
        LVP = On ;Low voltage programming enabled. MCLR/VPP pin function is MCLR. MCLRE configuration bit is ignored
        Cp = OFF ;PFM and Data EEPROM code protection disabled
    Config_End
    OSCCON1 = %01100000 ' Internal OSC
    OSCFRQ = %0000110   ' 32MHz

    Declare Xtal 32             
    All_Digital = TRUE ' Disable all the A/D converters

    Symbol LED_ORANGE       = LATA.2
    Symbol LED_BLUE         = LATA.4

    ' Configure the CAN module TX & RX pins to point to physcial I/O pins
    ' Unlock PPS Sequence
    PPSLOCK = 0x55
    PPSLOCK = 0xAA   
    PPSLOCKbits_PPSLOCKED = 0 ' Unlock

    CANRXPPS = 0x0B           ' RB3 = CAN RX (0x0B is the code for RB3)
    RB4PPS = 0x33             ' RB4 = CAN TX (Check out table 17-2)

    ' Lock PPS Sequence
    PPSLOCK = 0x55
    PPSLOCK = 0xAA   
    PPSLOCKbits_PPSLOCKED = 1 ' Lock

    TRISB = %11101111
    ANSELB = %00000000


' -----------------------------------------------------------------------------------------------------------
' Configure the CAN module - need to enter CAN module configuration mode
' -----------------------------------------------------------------------------------------------------------
    CANCON = $80 ' Enter config mode

    While CANSTAT <> $80 ' Wait to enter config. mode (Page 604)
    Wend

    ' 250 BAUD
    BRGCON1 = $43 ' (Page 640)
    BRGCON2 = $EE ' (Page 641)
    BRGCON3 = $01 ' (Page 642)

    ' CAN Control registers
    CIOCON = $20 ' CANCAP enabled, End of message interrupt disabled   

    ' Set up filter And mask To allow only messages with ID 0x080
    RXF0SIDH = 0x02 ' Set filter 0 To 0x17
    RXF0SIDL = 0xE0
    RXM0SIDH = 0xFF ' Set mask 0 To only check the standard ID bits
    RXM0SIDL = 0xE0

    ' Enable filter 0
    RXFCON0 = 0x01 ' Enable filter 0           

    ' EXIT CONFIG.MODE (back to normal mode)
    CANCON = $00

    ' Lamp Test
    High LED_ORANGE
    High LED_BLUE
    DelayMS 1000
    Low LED_ORANGE
    Low LED_BLUE 

   
    On_Hardware_Interrupt GoTo ISR_handler   

    ' Enable CAN receive interrupt
    PIE5bits_RXB0IE = 1 ' Enable CAN RXB0 interrupt     
    PIR5bits_RXB0IF = 0 ' Clear RXB0 interrupt flag   
    INTCON0bits_IPEN_INTCON0 = 0 ' Disable priority levels
    INTCON0bits_GIE = 1 ' Enable all unmasked ints.

' -----------------------------------------------------------------------------------------------------------
' All initialisation complete
' START OF PROGRAM LOOP
' -----------------------------------------------------------------------------------------------------------

MainLoop:   
    Toggle LED_ORANGE
    DelayMS 250     
    GoTo MainLoop

' -----------------------------------------------------------------------------------------------------------
' Interrupt Service Routine (ISR)
' -----------------------------------------------------------------------------------------------------------
ISR_handler:
    Context Save   
       
    Context Restore
' *** THIS IS THE END OF THE ISR ***
' -----------------------------------------------------------------------------------------------------------
There's no room for optimism in software or hardware engineering.

tumbleweed

The first thing is to set config MVECEN = OFF.
You should also add code to clear the interrupt flag in the isr otherwise it'll never really exit.

The intosc isn't accurate enough for CAN use.

RGV250

Hi,
You might be able to pick what you need out of this, I really need to revisit it for the newer devices.
Don't forget there are 2 buffers so if one is not cleared the second will get the next message.
'****************************************************************       
'* Interrupt Service Routine                                    *
'****************************************************************
'* Determine if it is a timed interrupt or CAN module interrupt *
'* Also the ISR determines whether a Valid message or CAN error *
'* interrupt has occured and then proceeds accordingly          *
'****************************************************************
'High_Int_Sub_Start
INTERRUPT_ROUTINE:
        Context Save           
        If PIR1.0 = 0 Then GoTo CAN_MODULE_INTERRUPT
        Clear T1CON.0           'Stop timer


       
'Flag to increment counters in "User code .INC file"
        UpdateBit = 1
        Inc CAN_TX_COUNT
 
        If CAN_TX_COUNT >= CAN_TX_TIME Then GoTo TX_ON_TIME
 
'If it was just a timer interrupt and TIMED_INT not selected then return from interrupt.         
'Set / clear relevant bits before returning from interupt
        PIR1.0 = 0          'Clear Timer 1 overflow interrupt bit
        TIMER1 = TIMER_1_OFFSET  'Re-load timer
        Set T1CON.0         'Re-start timer
        GoTo Exit_INT     

'This routine is called at intervals set by value in TX_TIME
'It always uses message 0
'Values in TIMED_TX_DATA array are created elsewhere       
TX_ON_TIME:   
        Toggle TX_LED   'Flash LED - let me know it is transmitting
                                                                           
        CANSetMsgID(0,STD)     'Timed data is always message zero
       
' The message will be transmitted with the Node address as set in "CANsetNodeID" in the USER CODE.INC file
' and the message ID as set above.
' Timed data will always be MsgID 0 & 8 data bytes.
        CANSendMessage(TIMED_TX_DATA,8,CAN_TX_PRIORITY_0 & CAN_TX_NO_RTR_FRAME,CAN_TX_OK) 

        CAN_TX_COUNT = 0

        PIR1.0 = 0              'Clear Timer 1 overflow interrupt bit
        TIMER1 = TIMER_1_OFFSET 'Re-load timer             
        Set T1CON.0             'Re-start timer
        GoTo Exit_INT
   
CAN_MODULE_INTERRUPT:
        If PIR3.0 = 1 Then GoTo CAN_RECEIVE
        If PIR3.1 = 1 Then GoTo CAN_RECEIVE
        If PIR3.5 = 1 Then GoTo CAN_ERROR
       
'****************************************************************       
'* CAN_RECEIVE                                                  *
'* The interrupt directs the program to here so there must be a *
'* message in one of the receive buffers.                       *
'* After the CANReceiveMessage routine returns the message the  *
'* sending Node ID and message ID is determined. DATA is then   *
'* stored in the relevant array.                                *
'* !!!! Only standard identifiers used - 5 bits for Node ID and *
'* 6 bits for the Message ID (32 Node ID's and 64 Messages).    *
'****************************************************************
CAN_RECEIVE:
        Toggle RX_LED      'Flash LED - let me know it is receiving

        CANReceiveMessage(RX_NODE_ID,RX_DATA,RX_MSG_LEN,RX_FLAGS)

'Determine Node ID
'Only STD message ID done in this example
'RX_NODE_ID#0/#1 = RXBxSIDH/L
        RX_NODE_NR.HighByte = RX_NODE_ID#0
        RX_NODE_NR.LowByte = RX_NODE_ID#1
        RX_NODE_NR = RX_NODE_NR >> 5
        RX_NODE_NR = RX_NODE_NR & %0000000000011111 'Mask higher 11 bits
'Test for duplicate Node ID on the BUS
'''''''''''''''''''        If RX_NODE_NR = TX_NODE_NR Then GoTo CAN_DUPLICATE_ERROR         

'Determine Message ID
'Only STD message ID done in this example
'RX_NODE_ID#0 = RXBxSIDH       
        RX_MSG_ID = RX_NODE_ID#0
        RX_MSG_ID = RX_MSG_ID >> 2
       
'Store data in relevant array               
        MAX_DATA = RX_MSG_LEN & %00001111   'strip RTR bit
       
        FSReg0 = VarPtr(RX_DATA)

'ADD/DELETE AS NECESSARY       
' Determine which was the transmitting node and store data accordingly
' See comments in "Variables For Data storage" regarding
' Array names IE "MESSAGE_0_DATA" could be "SPEED" etc.
' Message ID's do not have to be sequential

        If RX_NODE_NR = 1 Then GoTo MESSAGE_FROM_NODE_1 
        If RX_NODE_NR = 2 Then GoTo MESSAGE_FROM_NODE_2       
        If RX_NODE_NR = 3 Then GoTo MESSAGE_FROM_NODE_3                   
        If RX_NODE_NR = 4 Then GoTo MESSAGE_FROM_NODE_4
        If RX_NODE_NR = 5 Then GoTo MESSAGE_FROM_NODE_5
'The program should never get to here, if it does there is an issue so goto RX_MESSAGE_ERROR and log it 
        GoTo RX_MESSAGE_ERROR
     
MESSAGE_FROM_NODE_1:               
        FSReg1 = 0
        If RX_MSG_ID = 0 Then FSReg1 = VarPtr(MESSAGE_0_DATA) : GoTo STORE_RX_MESSAGES       
        If RX_MSG_ID = 1 Then FSReg1 = VarPtr(MESSAGE_1_DATA) : GoTo STORE_RX_MESSAGES     
        If RX_MSG_ID = 2 Then FSReg1 = VarPtr(MESSAGE_2_DATA) : GoTo STORE_RX_MESSAGES                 
        If RX_MSG_ID = 3 Then FSReg1 = VarPtr(MESSAGE_3_DATA) : GoTo STORE_RX_MESSAGES
        If RX_MSG_ID = 4 Then FSReg1 = VarPtr(MESSAGE_4_DATA) : GoTo STORE_RX_MESSAGES
'The program should never get to here, if it does there is an issue so goto RX_MESSAGE_ERROR and log it         
        GoTo RX_MESSAGE_ERROR
       
MESSAGE_FROM_NODE_2:               
        FSReg1 = 0
        If RX_MSG_ID = 0 Then FSReg1 = VarPtr(MESSAGE_5_DATA) : GoTo STORE_RX_MESSAGES       
        If RX_MSG_ID = 1 Then FSReg1 = VarPtr(MESSAGE_6_DATA) : GoTo STORE_RX_MESSAGES       
        If RX_MSG_ID = 2 Then FSReg1 = VarPtr(MESSAGE_7_DATA) : GoTo STORE_RX_MESSAGES                 
        If RX_MSG_ID = 3 Then FSReg1 = VarPtr(MESSAGE_8_DATA) : GoTo STORE_RX_MESSAGES
        If RX_MSG_ID = 4 Then FSReg1 = VarPtr(MESSAGE_9_DATA) : GoTo STORE_RX_MESSAGES
'The program should never get to here, if it does there is an issue so goto RX_MESSAGE_ERROR and log it 
        GoTo RX_MESSAGE_ERROR
       
MESSAGE_FROM_NODE_3:               
        FSReg1 = 0
        If RX_MSG_ID = 0 Then FSReg1 = VarPtr(MESSAGE_10_DATA) : GoTo STORE_RX_MESSAGES       
        If RX_MSG_ID = 1 Then FSReg1 = VarPtr(MESSAGE_11_DATA) : GoTo STORE_RX_MESSAGES     
        If RX_MSG_ID = 2 Then FSReg1 = VarPtr(MESSAGE_12_DATA) : GoTo STORE_RX_MESSAGES                 
        If RX_MSG_ID = 3 Then FSReg1 = VarPtr(MESSAGE_13_DATA) : GoTo STORE_RX_MESSAGES
        If RX_MSG_ID = 4 Then FSReg1 = VarPtr(MESSAGE_14_DATA) : GoTo STORE_RX_MESSAGES
'The program should never get to here, if it does there is an issue so goto RX_MESSAGE_ERROR and log it 
        GoTo RX_MESSAGE_ERROR
       
MESSAGE_FROM_NODE_4:               
        FSReg1 = 0
        If RX_MSG_ID = 0 Then FSReg1 = VarPtr(MESSAGE_15_DATA) : GoTo STORE_RX_MESSAGES       
        If RX_MSG_ID = 1 Then FSReg1 = VarPtr(MESSAGE_16_DATA) : GoTo STORE_RX_MESSAGES     
        If RX_MSG_ID = 2 Then FSReg1 = VarPtr(MESSAGE_17_DATA) : GoTo STORE_RX_MESSAGES                 
        If RX_MSG_ID = 3 Then FSReg1 = VarPtr(MESSAGE_18_DATA) : GoTo STORE_RX_MESSAGES
        If RX_MSG_ID = 4 Then FSReg1 = VarPtr(MESSAGE_19_DATA) : GoTo STORE_RX_MESSAGES
'The program should never get to here, if it does there is an issue so goto RX_MESSAGE_ERROR and log it 
        GoTo RX_MESSAGE_ERROR

MESSAGE_FROM_NODE_5:               
        FSReg1 = 0
        If RX_MSG_ID = 0 Then FSReg1 = VarPtr(MESSAGE_20_DATA) : GoTo STORE_RX_MESSAGES       
        If RX_MSG_ID = 1 Then FSReg1 = VarPtr(MESSAGE_21_DATA) : GoTo STORE_RX_MESSAGES     
        If RX_MSG_ID = 2 Then FSReg1 = VarPtr(MESSAGE_22_DATA) : GoTo STORE_RX_MESSAGES                 
        If RX_MSG_ID = 3 Then FSReg1 = VarPtr(MESSAGE_23_DATA) : GoTo STORE_RX_MESSAGES
        If RX_MSG_ID = 4 Then FSReg1 = VarPtr(MESSAGE_24_DATA) : GoTo STORE_RX_MESSAGES
'The program should never get to here, if it does there is an issue so goto RX_MESSAGE_ERROR and log it 
        GoTo RX_MESSAGE_ERROR
       
STORE_RX_MESSAGES:                   
        For TEMP_LOOP_COUNTER = 0 To MAX_DATA -1               
        POSTINC1 = POSTINC0     'Copy data from Receive buffer
        Next TEMP_LOOP_COUNTER                       

'If a message is still in one of the receive buffers then do it again
        If RXB0CON.7 = 1 Then GoTo CAN_RECEIVE
        If RXB1CON.7 = 1 Then GoTo CAN_RECEIVE
               
        PIR3 = 0               'Clear CAN interrupt bits
                               '? IS THIS CORRECT ? in RX routine
        GoTo Exit_INT
       
'****************************************************************
'* CAN Error routine   !!!!! to complete                        *
'* If the CAN module detects a CAN error or RX buffer 1 has     *
'* overflowed then process condition and exit.                  *
'* The If/Then statements are in order of priority in case      *
'* there are more than one. The worst case is first priority.   *
'*                                                              *
'* Counters are incremented for diagnosis and are sent out      *
'* later on in the program.                                     *
'****************************************************************
CAN_ERROR:
        If COMSTAT.1 = 1 Then GoTo RX_WARNING
        If COMSTAT.2 = 1 Then GoTo TX_WARNING       
        If COMSTAT.3 = 1 Then GoTo RX_IS_BUS_PASSIVE
        If COMSTAT.4 = 1 Then GoTo TX_IS_BUS_PASSIVE
        If COMSTAT.5 = 1 Then GoTo TX_IS_BUS_OFF               
        If COMSTAT.6 = 1 Then GoTo CAN_RX_OVERFLOW_ERROR
 
RX_WARNING:
        COMSTAT.1 = 0   'Probably leave as it should correct itself ??
        GoTo EXIT_CAN_ERRORS
        'Note to me !! reset bits and clear anything else needed

TX_WARNING:
        COMSTAT.2 = 0   'Probably leave as it should correct itself ??
        GoTo EXIT_CAN_ERRORS
        'Note to me !! reset bits and clear anything else needed
   
RX_IS_BUS_PASSIVE:
        COMSTAT.3 = 0
        GoTo EXIT_CAN_ERRORS
        'Note to me !! reset bits and clear anything else needed

TX_IS_BUS_PASSIVE:
        COMSTAT.4 = 0
        GoTo EXIT_CAN_ERRORS
        'Note to me !! reset bits and clear anything else needed

TX_IS_BUS_OFF:
        COMSTAT.5 = 0
        GoTo EXIT_CAN_ERRORS 
        'Note to me !! reset bits and clear anything else needed
       
CAN_RX_OVERFLOW_ERROR:
        COMSTAT.6 = 0
        GoTo EXIT_CAN_ERRORS
        'Note to me !! reset bits and clear anything else needed

'****************************************************************
'* CAN RX Error routine - Invalid message detected              *
'* If the program get to here it is because either the received *
'* node/message has not been decoded or that there is no pointer*
'* to an array for it to go to.                                 *
'* I have not decided how to handle this condition yet, this is *
'* just to trap the error so I know it has occured.             *
'* In practice, this could happen as the receiving node may not *
'* be interested in the transmitted data so no pointer for it.  *
'****************************************************************
 
RX_MESSAGE_ERROR:     
        Inc RX_CAN_ERRORS
       
        GoTo EXIT_ERRORS    'New 30-08-2019       
   
' Don't normally have functions like this in the interrupt routine 
' but it should not be called and at present it is for debugging.       
  '''      HSerOut ["RX CAN Errors detected MsgID ", Dec RX_MSG_ID," FSReg0/FSReg1 ", Dec FSReg0, " / ", Dec FSReg1, " ",10,13] 
   
EXIT_CAN_ERRORS:
        Inc CAN_ERRORS
' Dont normally have functions like this in the interrupt routine 
' but it should not be called and at present it is for debugging.       
 ''''       HSerOut ["CAN Errors detected ", Dec CAN_ERRORS," COMSTAT ", Bin COMSTAT, " ",10,13] 

EXIT_ERRORS:           'New 30-08-2019
        COMSTAT = 0
        PIR3.5 = 0             'Clear CAN error interrupt bit
       
Exit_INT:
        Context Restore        'Exit ISR and re-enable interrupts   
   
'****************************************************************
'* End of Interrupt routines                                    *
'****************************************************************   

Bob

kcsl

You sir are a genius. It was that MVECEN setting. New one on me... more reading required :(

I knew about the other things, I was just trying everything I could think of, and removing code to get to the absolute minimum.


Regards,
Joe

There's no room for optimism in software or hardware engineering.