Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Stack over flow forcing device reset in pic18f

Status
Not open for further replies.

Ranbeer Singh

Full Member level 5
Joined
Jul 30, 2015
Messages
259
Helped
22
Reputation
44
Reaction score
22
Trophy points
1,298
Location
Faridabad India
Activity points
3,266
Any body can explain me in deep what is Stack over?
How to find it in program?
what means of instruction instruction at 0x000050

when i run my program with MPLAB SIM This massage comes out CORE-E0001: Stack over flow error occurred from instruction at 0x000050
 

PIC18 has a dedicated hardware stack which only holds return addresses pushed during call and rcall instructions or interrupts.

Stackoverflow can happen by having too many nested function calls or various kinds of coding errors. You should be able to understand the cause by analyzing the compiler listing or tracing code execution in simulator.

If it's a small project, you could post *.cof and related source files.
 
Thank you for your valued reply

It's 1299 lines program.

The massage comes when I built it. I mean before simulate the program. It's sow instruction number only. How can I found it.
 

The massage comes when I built it.
Hardly. The shown error will be only dropped when executing the code. Maybe you have configured the simulator for automatic load and start?

The code at instruction address 0x0050 can inspected in the compiler assembly listing or MPLAB SIM disassembly window.
 

I tried to run. When It goes on address 00050. INTCON=0xF0; program code highlight

__________________________________________________
REGISTER 9-1: INTCON REGISTER

Note: Interrupt flag bits are set when an interrupt
condition occurs, regardless of the state of
its corresponding enable bit or the global
enable bit. User software should ensure
the appropriate interrupt flag bits are clear
prior to enabling an interrupt. This feature
allows for software polling.

bit 7 GIE/GIEH: Global Interrupt Enable bit
IPEN (RCON<7>) = 0:
1 = Enables all unmasked interrupts
0 = Disables all interrupts
When IPEN (RCON<7>) = 1:
1 = Enables all high priority interrupts
0 = Disables all interrupts
bit 6 PEIE/GIEL: Peripheral Interrupt Enable bit
When IPEN (RCON<7>) = 0:
1 = Enables all unmasked peripheral interrupts
0 = Disables all peripheral interrupts
When IPEN (RCON<7>) = 1:
1 = Enables all low priority peripheral interrupts
0 = Disables all low priority peripheral interrupts
bit 5 TMR0IE: TMR0 Overflow Interrupt Enable bit
1 = Enables the TMR0 overflow interrupt
0 = Disables the TMR0 overflow interrupt
bit 4 INT0IE: INT0 External Interrupt Enable bit
1 = Enables the INT0 external interrupt
0 = Disables the INT0 external interrupt
bit 3 RBIE: RB Port Change Interrupt Enable bit
1 = Enables the RB port change interrupt
0 = Disables the RB port change interrupt
bit 2 TMR0IF: TMR0 Overflow Interrupt Flag bit
1 = TMR0 register has overflowed (must be cleared in software)
0 = TMR0 register did not overflow
bit 1 INT0IF: INT0 External Interrupt Flag bit
1 = The INT0 external interrupt occurred (must be cleared in software)
0 = The INT0 external interrupt did not occur
bit 0 RBIF: RB Port Change Interrupt Flag bit
1 = At least one of the RB7:RB4 pins changed state (must be cleared in software)
0 = None of the RB7:RB4 pins have changed state

Note: A mismatch condition will continue to set this bit. Reading

________________________________________________________________

Please explain me. Where am I wrong?
 
Last edited by a moderator:

Apparently you are enabling interrupts at this point. This shouldn't be a problem unless it's done erroneously inside an interrupt handler. Or the interrupt handler itself is faulty, not terminated correctly with a RETFIE instruction. Or you already exhausted all available stack levels when enabling interrupts (unlikely).

Who about appending the C file?
 

It is my program base & main structure. I have setted all required configuration bits in MPLAB. In this application I am using modbus, LCD, EEPROM, SPI, SD card, GSM module & 256 inputs for data logging & SMS/Email Alarms.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include <p18f6720.h>
#define EnterButton PORTDbits.RD4
#define UpButton PORTDbits.RD5
#define DownButton PORTDbits.RD6
 
float ADC_Board1( char type, char pin, char InputNo );
void EEPROM_putc( unsigned char address , unsigned char data );
char EEPROM_getc( unsigned char address );
char *EEPROM_getStr( unsigned char address );
void DataFromEEPROM( void );
void UART_to_rom( void );
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
char Read_Chr_1USART( void );
void Write_Chr_USART( char data );
void Read_Str_1USART( char *buffer, unsigned char len );
void Write_Str_USART( const rom char *data );
char Data_Rdy_1USART( void );
char Busy_1USART( void );
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
//*********************************************************
char Read_Chr_RS485( void );
void Write_Chr_RS485( char data );
void Read_Str_RS485( char *buffer, unsigned char len );
void Write_Str_RS485( char *data );
char Data_Rdy_RS485( void );
char Busy_RS485( void );
//*********************************************************
 
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
void Char_LCD( char data );
void String_LCD( const rom char *buffer );
void Send_Commond_LCD( char cmd  );
void Clear_LCD( void );
void Line_Col_LCD(char lineNo, char ColNo);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 
void write_Str_SPI( const rom char *wrptr );
void Send_SMS( char ErrNo, float vl );
void mail_snd ( char ErrNo, float vl );
void timer_1sec( void );
void Time_1ms( int a );
void Getdatafrm_Board( char board );
void collect_hstry( void );
char *Float_To_Str( float in );
const rom char *Chr_To_Str( char in );
float Str_To_float( char *in );
char getDigitalVL_1Board( char pin );
float Read_IO_Board( char BdNo, char pin, char Intyp, char Aityp, char max5, char min5 );
void Count_Delay( char time, char InNo );
void Count_His_Delay( char t );
char Check_Comm(void);
void Desktop(void);
void MenuEnter(void);
void SubMenu(char no);
void WaitMode(void);
void RTC_SimData_Refresh(void);
 
char *DeviceId,*UnitName,*MailId1,*MailId2,*ServerAddr,*RTC,*Alarm,*SimCarrier,Network;
char *InputName[],*HostNo[];
char InputBDPoint[],InputType[],InputAlarm[],DiType[],DiAlarmDelay[],AiType[],AddressNo[];
char AiLowDelay[],AiHighDelay[],AiSensorFail[],AiSensorFailDelay[],Max5V[],Min5V[];
char InputBoard,TotalPoint,SMSYesNo,EmailYesNo,HstTime,TotalHstPoint,HstYesNo,TotalHost,BusNode,RelayActive,EmailPort,Pos,SendingMail;
int RomAddress;
float NewVal[],AiHighLimit[],AiLowLimit[];
char BNO,adrs,DT;
 
void main ()
{
    TRISA=0xFF;
    TRISB=0xC7;
    TRISC=0x3F;
    TRISD=0xFF;
    TRISE=0x00;
    TRISF=0xFF;
    TRISG=0xFE;
 
    T0CON=0x06;
    ADCON0=0x01;
    ADCON1=0x00;
    ADCON2=0xAE;
    INTCON=0xF0;
    INTCON2=0xF8;
    INTCON3=0x48;
    PIE1bits.RC1IE=1;
    PIE3bits.RC2IE=1;
    PIE2=0x10;
    IPR1=0x30;
    IPR2=0x00;
    IPR3=0x20;
    RCONbits.IPEN=1;
    
    SSPSTAT=0xC1;
    SSPCON1=0x18;   
 
    TXSTA1=0x26;
    RCSTA1=0x90;
    SPBRG1=64;
    TXSTA2=0x26;
    RCSTA2=0x90;
    SPBRG2=64;
 
    Send_Commond_LCD(0x38);     //LCD 8 Bit Data
    Send_Commond_LCD(0x06);     //Entry Mode
    Clear_LCD();                //Clear LCD
    Send_Commond_LCD(0x0C);     //LCD diplay on cursor not blinking
    Send_Commond_LCD(0x80);     //LCD cursor Pos. begain
    Write_Str_USART("AT+IPR=19200");
    String_LCD("Initialzing");
    Time_1ms(1000);
    Char_LCD('.');
    Time_1ms(1000);
    Char_LCD('.');
    Time_1ms(1000);
    Char_LCD('.');
    Time_1ms(1000);
    Char_LCD('.');
    Clear_LCD();
    String_LCD("Finding service provider"); 
    Time_1ms(2000);
    Check_Comm();
    Clear_LCD();
    Write_Str_USART("AT+CSPN?");
    Read_Str_1USART(SimCarrier,10);
    String_LCD(SimCarrier);
    Time_1ms(2000);
    String_LCD("Configuring Data momory & Communication  ");
    Time_1ms(4000);
    DataFromEEPROM();
    BusNode=Check_Comm();
    DataFromEEPROM();
    String_LCD("Node on bus - ");
    Char_LCD(InputBoard+48);        // ASCII value of InputBoard for display only
    Time_1ms(2000);
    Count_His_Delay(HstTime);
    Desktop();
    BNO=1;
    
while(1)
    {
        if(Data_Rdy_1USART()==1)
        {
            adrs=Read_Chr_1USART();
            if(adrs=='@')
            {
                Write_Chr_USART('#');
                UART_to_rom();
            }
            else{}
        }
        else{}
        if(INTCON3bits.INT1IF==1) collect_hstry();
        INTCON3bits.INT1IF=0;
        if(INTCONbits.INT0IF==1)
        {
            adrs=Read_Chr_RS485();
            if(adrs==6)
            {
                PORTGbits.RG3=0;
                Write_Chr_RS485(6);
                adrs=Read_Chr_RS485();
                if(SMSYesNo==1) Send_SMS(adrs,NewVal[adrs]);
                if(EmailYesNo==1) mail_snd(adrs,NewVal[adrs]);
            }
            else
            {
                PORTGbits.RG3=1;
                Check_Comm();
            }
        }
        else{}
        INTCONbits.INT0IF=0;
        Getdatafrm_Board( BNO );
        BNO++;
        if(BNO>32) BNO=1;
    }
}

 
Last edited by a moderator:

How did you arrive at the register settings you make during initialization. E.g. INTCON = 0xF0 without defining actual interrupt functions?

If you possibly stripped the interrupt code from your post - no chance to get a useful answer.
 

It's difficult to diagnose without the code for all the functions as well. I'm a little concerned that you are manipulating the interrupt bits in the main() section but seem to have no ISR. Maybe you are just using the interrupt bits as semaphores and do not need an ISR. Why do you have "else{}" in several places?

Brian.
 

How did you arrive at the register settings you make during initialization. E.g. INTCON = 0xF0 without defining actual interrupt functions?

I am defining it's priority levels and enables/disables only in main function
It's right or wrong?
 

Not necessarily wrong. Confusion emerged because you didn't show any ISR code.
 

Either you have ISR code in the other sources included with your project, then you should show it. Or you have no ISR code at all, then you must not enable interrupts.
 

I am using interrupts in USART, ADC functions only.

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  USART_1 codes Start
char Read_Chr_1USART()
{
  char data;        // Holds received data
  while(Data_Rdy_1USART()==0);// Wait for data to be received
  data = RCREG1;    // Read data
  return (data);    // Return the received data
}
 
void Write_Chr_1USART( char data )
{
  while(Busy_1USART()==1);
  TXREG1 = data;      // Write the data byte to the USART2
}
 
void Read_Str_1USART(char *buffer, unsigned char len)
{
  char i;    // Length counter
  unsigned char data;
  for(i=0;i<len;i++)  // Only retrieve len characters
  {
    data = Read_Chr_1USART();    // Get a character from the USART and save in the string
    *buffer = data;
    buffer++;              // Increment the string pointer
  }
}
 
char Data_Rdy_1USART()
{
  if(PIR1bits.RC1IF==1)return 1;             // If RCIF is set Data is available, return TRUE
  else if(PIR1bits.RC1IF==0) return 0;   // Data not available, return FALSE
}
 
char Busy_1USART()
{
  if(TXSTA1bits.TRMT==0) return 1;         // Is the transmit shift register empty No, return FALSE
  else if(TXSTA1bits.TRMT==1) return 0;     // Return TRUE
}
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  USART_1 codes End
 
 
 
 
 
float ADC_Board1( char type, char pin, char inputNo )
{
    int H;
    float vl;
    if(ADCON0bits.GO==1)
    {
        ADCON0=pin;              //Selection codes for Analog input pin
        if(ADRESH==0x00) H=0;
        else if(ADRESH==0x01) H=256;
        else if(ADRESH==0x10) H=512;
        else if(ADRESH==0x11) H=768;
        vl=H+ADRESL;
        if(type==1) vl=((((vl/204.8)/0.0025))-1000)*0.2564;             // Type=1 mean PT1000
        else if(type==2) vl=(((Max5V[inputNo]+Min5V[inputNo])/5)*vl);   // Type=2 mean 0-5V
    }
    else{}
    return vl;
}



- - - Updated - - -

Why do you have "else{}" in several places?

Hi betwixt

Thanks for your reply


I use "else{}" for nothing do with if statements.
 
Last edited by a moderator:

Those are not interrupt routines, you are just polling the USART interupt flag. If you are intending to use interrupts you need to write ISR routines. There is a special way to declare the interrupt functions. In them you should check the interrupt source then clear the interrupt flags. I'm sorry but I do not have the XC compilers with me at the moment to check the exact syntax but if you look up 'interrupt' in the help file it should give examples of you to do it.

I strongly recommend you DO use interrupts, they make the code easier and far more responsive when running.

Brian.
 
You can use the interrupt flags without using the interrupts but it isn't as reliable as using an ISR. I will try to explain.

With an ISR:
1. a character arrives at the USART
2. USART triggers an interrupt
3. Hardware forces the code to jump to the ISR
4. In the ISR you confirm it was the USART making the request (check the flags)
5. Either call your 'read the character' routine then return here -or- read the character here inside the ISR
6. Clear the interrupt flag so its ready for more characters to arrive
7. Leave the ISR, you will be back in your program where you were before the interrupt occurred.

Without an ISR:
1. a character arriving at the USART sets the interrupt flag
2. in your code loop you check the interrupt flag
3. if the flag is set, read the character
4. clear the interrupt flag so its ready for more characters to arrive.

The big advantage of using an ISR is you are guaranteed an immediate response when the USART has a character in it. If you rely on checking the interrupt flag in your code loop the timing becomes critical as there could be a time delay before you have chance to test it. With a peripheral like the USART where several characters may arrive in quick succession, there is a high risk that a second (or later) character arrives before you have read the first one. That results in lost characters as the later ones will overwrite the earlier ones without warning.

ISRs make the code simpler. All you have to do is move the instructions to read the USART into an interrupt function. They are then called automatically when needed.

Brian.
 

I tried to run after removing interrupt resister configuration. I have tried to run with Proteus ISIS simulator also.
It's working properly.


Thank you Ms. FvM & betwixt.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top