PDA

View Full Version : This simple code fragment crashes and restarts MCU!



CuriousOne
- 16th August 2024, 16:32
Hello.

I have a small code for GPS, which works correctly, however, I've noticed the following:
IF GPS is physically disconnected from the input, or I disable the "serin 2" line, main loop crashes after the first execution and MCU restarts from the beginning. This happens also on other physical boards, so it is not issue of this particular MCU. Other power supplies, other ways of output, like LCD screen instead of serout were tried, as well as hardware serial inputs and outputs - no changes. I also tried same code on 16F1939, 18F45K22 - same result.



;----[16F886 Hardware Configuration]--------------------------------------------
#CONFIG
cfg1 = _INTRC_OSC_NOCLKOUT ; INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN
cfg1&= _WDT_ON ; WDT enabled
cfg1&= _PWRTE_OFF ; PWRT disabled
cfg1&= _MCLRE_OFF ; RE3/MCLR pin function is digital input, MCLR internally tied to VDD
cfg1&= _CP_OFF ; Program memory code protection is disabled
cfg1&= _CPD_OFF ; Data memory code protection is disabled
cfg1&= _BOR_OFF ; BOR disabled
cfg1&= _IESO_ON ; Internal/External Switchover mode is enabled
cfg1&= _FCMEN_ON ; Fail-Safe Clock Monitor is enabled
cfg1&= _LVP_OFF ; RB3 pin has digital I/O, HV on MCLR must be used for programming
cfg1&= _DEBUG_OFF ; In-Circuit Debugger disabled, RB6/ICSPCLK and RB7/ICSPDAT are general purpose I/O pins
__CONFIG _CONFIG1, cfg1


cfg2 = _BOR40V ; Brown-out Reset set to 4.0V
cfg2&= _WRT_OFF ; Write protection off
__CONFIG _CONFIG2, cfg2


#ENDCONFIG


TRISA=%00000001 'SET A TO OUTPUT 1=input
TRISC=%00001000 'set C3 for gps
TRISB=%00011000 'set PortB to output
ANSELH=%00000000 ' ADC OFF B
ANSEL=%000000000 'configure PortA as digital except first 2
ADCON1=%10000000 'adc justify
OSCCON=%01110101 'SET FREQUENCY TO 8MHZ
WPUB=%00000000 'turn off Pullups
CM1CON0=0 'DISABLE COMPARATORS
CM2CON0=0 'SAME HERE
'CCP1CON=%01000000 ' configure pwm
'PSTRCON=%00010110 'disable C pwm


DEFINE OSC 8
DEFINE ADC_BITS 12
DEFINE ADC_CLOCK 5
DEFINE ADC_SAMPLEUS 5


gps_data VAR BYTE[80] ' Buffer to store GPS data
gps_char VAR BYTE ' Character received from GPS
time_data VAR BYTE[6] ' Array to store the extracted time
i VAR BYTE ' Loop variable
start_found VAR BIT ' Flag to indicate start of time data


' Define the serial pins
GPS_RX var PORTC.7 ' RX pin for GPS (Adjust according to your setup)
GPS_TX var PORTC.5 ' TX pin for GPS (Adjust according to your setup)


' Initialize variables
start_found = 0
i = 0
serout2 portc.5,84, ["Start ok", 10, 13]
toggle portc.3 'test led
pause 100


mainx:
' Wait for data from GPS
serin2 GPS_RX,85,[gps_char] 'If I remove this line or disconnect the GPS, MCU will crash!
' Store data in buffer
gps_data[i] = gps_char
i = i + 1


' Check if we have a complete line of data
IF gps_char = 10 THEN
' Look for the $GPRMC sentence
IF (gps_data[1] = "G") AND (gps_data[2] = "P") AND (gps_data[3] = "R") AND (gps_data[4] = "M") AND (gps_data[5] = "C") THEN
' Extract time from the sentence
start_found = 1
FOR i = 7 TO 12
time_data[i-7] = gps_data[i]
NEXT i
ENDIF


' Reset buffer
i = 0
ENDIF
' Display time data
IF start_found = 1 THEN
serout2 portc.5,84, ["Time: ", time_data[0], time_data[1], ":", time_data[2], time_data[3], ":", time_data[4], time_data[5], 13, 10]
start_found = 0
ENDIF


GOTO mainx
high portc.3 'check if code comes to here
stop


Any ideas?

CuriousOne
- 16th August 2024, 16:42
Also it will crash randomly even when GPS is connected. Here's how output looks:

Time: 15:41:00
Time: 15:41:01
Time: 15:41:02
Time: 15:41:03
Time: 15:41:04
Time: 15:41:05
Time: 15:41:06
Time: 15:41:07
Start ok <------- it crashed and restarted here
Time: 15:41:10
Time: 15:41:11
Time: 15:41:12
Time: 15:41:13
Time: 15:41:14

So I think this is issue with arrays?

HenrikOlsson
- 16th August 2024, 17:02
Could be, easy to verify

' Wait for data from GPS
serin2 GPS_RX,85,[gps_char] 'If I remove this line or disconnect the GPS, MCU will crash!
' Store data in buffer
gps_data[i] = gps_char
i = i + 1

If i >= 80 'or whatever size you set the array to
serout2 portc.5,84, ["Next char will overrun buffer"]
ENDIF

amgen
- 16th August 2024, 17:03
not sure but first use of i and i+1 might overrun.

Jerson
- 16th August 2024, 17:15
I am not currentl with PBP, so, please refer the manual where necessary.

It is most likely you are overrunning the specified receive buffer gps_data of 80 bytes as you are not doing any bounds checking to keep the data within that 80 bytes region. That is trashing the variables declared beyond the 80 bytes boundary.

Ideally, you should receive characters until a terminating character is received like a CR or a $00 character (whichever method is used by the module) or the buffer limit is reached (i = 80 as per your code)

edit:looks like I posted together with Henrik and amgen.

CuriousOne
- 16th August 2024, 17:37
Yes you're correct, i is overrun.
This is AI generated code, by the way :)

I added this:



if i>=80 then
serout2 portc.5,84, ["Oops!", 10, 13]
i=0
endif


And now output looks like this with GPS connected:
Oops!
Oops!
Oops!
Time: 16:36:37
Time: 16:36:38
Time: 16:36:39
Time: 16:36:40
Oops!
Time: 16:36:42
Oops!

And only "Oops!" with GPS disconnected, but there are no more resets...

Jerson
- 17th August 2024, 03:02
If you're gettings false data when GPS is disconnected, perhaps you have left the RX pin floating. Maybe you could see if adding a pull-up resistor eliminates that problem for you.