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.

[PIC] Why more codes do not work with PIC microcontroller when RAM and ROM have free spaces

Status
Not open for further replies.

Indramal

Newbie level 4
Joined
Sep 24, 2018
Messages
7
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
85
I code for reading EEPROM and edit those EEPROM data and work with those data. Normally I am coding something and upload to PIC and check that code.

When I am code more than some point it is not working. I connected LCD with PIC it also shows all pixels ON. when I remove codes in somewhere then again working. When codes are high PIC not working. When codes are less then PIC working.

But when I compiled it shows PIC have free ROM and RAM spaces.

11.PNG

I am using 4Mhz crystal oscillator and PIC18F4550 microcontroller. I am using MikroC for coding.

Why did this happen in Hardware?

My code:

Code:
 // LCD module connections
sbit LCD_RS at RD0_bit;
sbit LCD_EN at RD1_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;

sbit LCD_RS_Direction at TRISD0_bit;
sbit LCD_EN_Direction at TRISD1_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// End LCD module connections
unsigned short shedno=0,i=0,shedc=0,streg,lsreg,rang,x;
unsigned count=0,reg1, reg2, reg3, reg4, reg5, reg6,sttime=1000;
char shednon[4]="",countn[6]="",stregn[4]="",lsregn[4]="",regval[6]="",ntrel1[6]="",ntrel2[6]="",ntrel3[6]="",ntrel4[6]="",ntrel5[6]="",ntrel6[6]="";


 void findshed(int sno){
    shedno = EEPROM_Read(0x00);
    shedno = 256 - shedno;
    shedno = shedno + sno;
    ByteToStr(shedno, shednon);
    
    streg = 6*shedno+4;
    lsreg = streg + 5;
    ByteToStr(streg, stregn);
    ByteToStr(lsreg, lsregn);
 }

  void shedrelay(){
          rang =0;
          for(x=streg; x<=lsreg; x++){
            regval[rang] = EEPROM_Read(x);
            Delay_ms(100);
            if(rang < 6){
            rang++;
            }
          }
          reg1 =  regval[0]+sttime;
          reg2 =  regval[1]+sttime;
          reg3 =  regval[2]+sttime;
          reg4 =  regval[3]+sttime;
          reg5 =  regval[4]+sttime;
          reg6 =  regval[5]+sttime;
          Wordtostr(reg1,ntrel1);
          Wordtostr(reg2,ntrel2);
          Wordtostr(reg3,ntrel3);
          Wordtostr(reg4,ntrel4);
          Wordtostr(reg5,ntrel5);
          Wordtostr(reg6,ntrel6);
 }
  void shedselectdis(){
          Lcd_Cmd(_LCD_CLEAR);
          Lcd_Out(1,1,"Next Shedule: S");
          Lcd_Out(1,16,shednon);
          Lcd_Out(2,1,"R1:");
          Lcd_Out(2,4,ntrel1);
          Lcd_Out(2,11,"R2:");
          Lcd_Out(2,14,ntrel2);
          Lcd_Out(3,1,"R3:");
          Lcd_Out(3,4,ntrel3);
          Lcd_Out(3,11,"R4:");
          Lcd_Out(3,14,ntrel4);
          Lcd_Out(4,1,"R5:");
          Lcd_Out(4,4,ntrel5);
          Lcd_Out(4,11,"R6:");
          Lcd_Out(4,14,ntrel6);
 }

 void editshed(){
              Lcd_Cmd(_LCD_CLEAR);
              Lcd_Cmd(_LCD_CURSOR_OFF);
              Lcd_Out(1,1,"Edit Shedule: S");
              Lcd_Out(1,16,shednon);
              Lcd_Out(2,1,"R1:");
              Lcd_Out(2,4,ntrel1);
              Lcd_Out(2,11,"R2:");
              Lcd_Out(2,14,ntrel2);
              Lcd_Out(3,1,"R3:");
              Lcd_Out(3,4,ntrel3);
              Lcd_Out(3,11,"R4:");
              Lcd_Out(3,14,ntrel4);
              Lcd_Out(4,1,"R5:");
              Lcd_Out(4,4,ntrel5);
              Lcd_Out(4,11,"R6:");
              Lcd_Out(4,14,ntrel6);
 }

 void relayssw(int x1, int x2, int x3, int x4, int x5, int x6){
          PORTA = 0b00000001;
          VDelay_ms(x1);
          PORTA = 0b00000000;
          Delay_ms(50);

          PORTA = 0b00000010;
          VDelay_ms(x2);
          PORTA = 0b00000000;
          Delay_ms(50);

          PORTA = 0b00000100;
          VDelay_ms(x3);
          PORTA = 0b00000000;
          Delay_ms(50);

          PORTA = 0b00001000;
          VDelay_ms(x4);
          PORTA = 0b00000000;
          Delay_ms(50);

          PORTA = 0b00010000;
          VDelay_ms(x5);
          PORTA = 0b00000000;
          Delay_ms(50);

          PORTA = 0b00100000;
          VDelay_ms(x6);
          PORTA = 0b00000000;
          Delay_ms(50);
 }
  void disval(){
    Lcd_Cmd(_LCD_CLEAR);
    findshed(0);
    Lcd_Out(1,1,"Shedule: S");
    Lcd_Out(1,11,shednon);
    Lcd_Out(2,1,"Count:");
    WordToStr(count, countn);
    Lcd_Out(2,1,"Count:");
    Lcd_Out(2,8,countn);
    Lcd_Out(3,1,"Steps:");
    Lcd_Out(4,1,"Temp:");
 }

void main() {
  TRISA = 0b00000000;
  TRISB = 0b11111111;

  PORTA = 0b00000000;
  
  ADCON0=0;
  ADCON1=0X0F;
  CMCON=0X07;
  CCP1CON=0;
  CCP2CON=0;
  SSPCON1=0;
  Lcd_Init();
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Cmd(_LCD_CURSOR_OFF);
  Lcd_Out(1,6,"Welcome !");
  Delay_ms(2000);
  Lcd_Cmd(_LCD_CLEAR);
  disval();
  EEPROM_Write(0x00,255);
for(i=1;i<131;i++){
   EEPROM_Write(i,i);
Delay_ms(50);
  }
  while(1){
      if(PORTB.B7 = 1){  //proximity count
        Delay_ms(300);
        count++;
        disval();
      }
      //
      if(PORTB.B5 = 1){  //proximity count reset
        Delay_ms(300);
        Lcd_Cmd(_LCD_CLEAR);
        Lcd_Out(1,1,"Reset Count?");
        WordToStr(count, countn);
        Lcd_Out(2,1,countn);
        Lcd_Out(3,1,"Press Enter to Reset");
        Lcd_Out(4,1,"Press Up to Back");
        while(1){
          if(PORTB.B4 = 1){ //enter
              Delay_ms(300);
              count=0;
              disval();
              break;
          }else if(PORTB.B2 = 1){  //up
              Delay_ms(300);
              disval();
              break;
          }
        }
      }
      //
      if(PORTB.B1 = 1){  //settings
         shedc = 0;
         Lcd_Cmd(_LCD_CLEAR);
         Lcd_Out(1,1,"Select Shedule: S");
         findshed(0);
         Lcd_Out(1,18,shednon);
         Lcd_Out(2,1,"Select Set. to Back");
         Lcd_Out(3,1,"Select Enter to Edit");
         Lcd_Out(4,1,"Select Up or Down");
         Lcd_Cmd(_LCD_FIRST_ROW);
         for(i=1;i<17;i++){
            Lcd_Cmd(_LCD_MOVE_CURSOR_RIGHT);
         }
         Lcd_Cmd(_LCD_BLINK_CURSOR_ON);
         while(1){
            if(PORTB.B1 = 1){  //exit
              Delay_ms(300);
              disval();
              Lcd_Cmd(_LCD_CURSOR_OFF);
              break;
            }else if(PORTB.B2 = 1){ //up button
              Delay_ms(300);
              if(shedno < 20){
                 shedc++;
               }

              findshed(shedc);
              Lcd_Out(1,18,shednon);
              Lcd_Cmd(_LCD_FIRST_ROW);
              for(i=1;i<17;i++){
                  Lcd_Cmd(_LCD_MOVE_CURSOR_RIGHT);
              }
              Lcd_Cmd(_LCD_BLINK_CURSOR_ON);
            }else if(PORTB.B3 = 1){ //down button
              Delay_ms(300);
              if(shedno > 1){
                 shedc--;
               }

              findshed(shedc);
              Lcd_Out(1,18,shednon);
              Lcd_Cmd(_LCD_FIRST_ROW);
              for(i=1;i<17;i++){
                  Lcd_Cmd(_LCD_MOVE_CURSOR_RIGHT);
              }
              Lcd_Cmd(_LCD_BLINK_CURSOR_ON);
            }else if(PORTB.B4 = 1){ //enter button
              Delay_ms(300);
              findshed(shedc);
              shedrelay();
              editshed();
              Lcd_Cmd(_LCD_SECOND_ROW);
              Lcd_Cmd(_LCD_BLINK_CURSOR_ON);
              while(1){
                 if(PORTB.B4 = 1){
                    Delay_ms(300);
                    Lcd_Cmd(_LCD_SECOND_ROW);
                    for(i=1;i<11;i++){
                       Lcd_Cmd(_LCD_MOVE_CURSOR_RIGHT);
                    }
                    Lcd_Cmd(_LCD_BLINK_CURSOR_ON);
                    while(1){
                        if(PORTB.B4 = 1){
                            Delay_ms(300);
                            Lcd_Cmd(_LCD_THIRD_ROW);
                            Lcd_Cmd(_LCD_BLINK_CURSOR_ON);
                            while(1){
                               if(PORTB.B4 = 1){
                                  Delay_ms(300);
                                  Lcd_Cmd(_LCD_THIRD_ROW);
                                  for(i=1;i<11;i++){
                                      Lcd_Cmd(_LCD_MOVE_CURSOR_RIGHT);
                                  }
                                  Lcd_Cmd(_LCD_BLINK_CURSOR_ON);
                                  while(1){
                                  
                                  }
                               }else if(PORTB.B2 = 1){//up
                                  
                               }else if(PORTB.B3 = 1){//down
                                  
                               }
                            }
                        }else if(PORTB.B2 = 1){//up
                        
                        }else if(PORTB.B3 = 1){//down
                         
                        }
                    }
                 }else if(PORTB.B2 = 1){//up
                 
                 
                 }else if(PORTB.B3 = 1){//down


                 }

              }
            }
         }
      }
      //
      if((PORTB.B2 = 1)||(PORTB.B3 = 1)){ //up or down
          shedc = 0;
          Delay_ms(300);
          Lcd_Cmd(_LCD_CLEAR);
          findshed(0);
          Lcd_Out(1,1,"Runing: S");
          Lcd_Out(1,10,shednon);
          Lcd_Out(2,1,"Next:");
          Lcd_Out(3,1,"Press Up or Down Key");
          Lcd_Out(4,1,"Press Reset to Back");
          while(1){
              if(PORTB.B3 = 1){ //down
                  Delay_ms(300);
                  if(shedno > 1){
                     shedc--;
                  }
                  findshed(shedc);
                  shedrelay();
                  shedselectdis();
              }else if(PORTB.B2 = 1){ //up
                  Delay_ms(300);
                  if(shedno < 20){
                     shedc++;
                  }
                  findshed(shedc);
                  shedrelay();
                  shedselectdis();
              }else if(PORTB.B4 = 1){ //enter
                  Delay_ms(300);
                  findshed(shedc);
                  EEPROM_Write(0x00,256-shedno);
                  disval();
                  break;
              }else if(PORTB.B6 = 1){ //test
                   Delay_ms(300);
                   PORTC = 0b00000000;
                   Delay_ms(100);
                   relayssw(reg1, reg2, reg3, reg4, reg5,reg6);
              }else if(PORTB.B5 = 1){ //reset
                  Delay_ms(300);
                  disval();
                  break;
              }
          }
      }
      //
      
  }

}
 

Free space isn't the only thing that could be stopping it. Without any idea of what your code is supposed to do, it is difficult to advise on the problem. Maybe a timing problem is responsible, for example I see you are writing data to EEPROM in a loop, do you wait until each write operation is finished before sending the next byte? Maybe this is dealt with in the library.

Brian.
 

But why when I remove code somewhere which means decrease code then it is working. Is it Nested Calls Limitations ? I see datasheet have Overflow disable
CONFIG4L: CONFIGURATION REGISTER 4 LOW
rigister.

My code purpose is follows

There are 20 shedules and each shedules have 6 times for 6 Relays ON. First EEPROM 0x00 is store the shedule no. then 10 to 129 EEPROM use to store the times of each shedules.

20 shedules x 6 times + 9 (9 for start from 10)

This code have for select shedules and edit shedules. //settings comment If condition is for edit shedules and //up or down If condition is for select the shedule.

There are 7 buttons Inputs which are Settings (B1) , Up(B2), Down(B3), Enter (B4), Reset(B5), Test(B6), Proximity(B7).

Proximity is for only counting up.

Test button for test each shedule times by giveing output PORTA. I externalise as funtion relayssw(int x1, int x2, int x3, int x4, int x5, int x6). X are relay times.
 

It is not demo version it can compile more than 2k. If you have licence version please send me HEX file.
 

This is happening with both Hardware and simulation.

When i simulate Proteus it gives following error.

[PIC18 STACK] PC=0x098E. Stack overflow is forcing device reset. [U1]
 

Why did this happen in Hardware?

It is possible to happen it software (but I am not sure at this time). The loader occupies a small part of the memory and at the end it just disappears. That space appears like a hole at the bottom.

It is usually very small (perhaps about a 100 or so bytes) but free space in both ROM and RAM are generally interesting. Your program will naturally go into the RAM area but I do not understand what is being saved in the RAM.

It is common if your PIC is installed with a boot loader but there are other boot loaders that ...

- - - Updated - - -

But the amount of free space available is not small; there must be other reasons. Perhaps limited options or functionality? Did you test with another compiler?
 

Yes, it is nested calls problem and they are causing stack overflow. In mikroC Project>Edit Project... dialog box you can disable "Stack Overflow will cause reset" option but your code will not work fine. Make small functions for each block and just call the functions in the main loop() when required.
 

Disabling stack overflow reset only stops the automatic reset, it doesn't stop the stack overflowing and causing problems.

Either you have too many nested subroutines and it doesn't have stack space to hold all the return addresses or you are somehow jumping out of a subroutine without 'popping' it's return address off the stack. If you are really out of stack space and can't find a way to reduce the number of calls, consider using a 'soft stack' routine that simulates the real stack but uses normal RAM instead. It increases the available stack depth but at the expense of slower and bigger code.


Brian.
 

Disabling stack overflow reset only stops the automatic reset, it doesn't stop the stack overflowing and causing problems.

Either you have too many nested subroutines and it doesn't have stack space to hold all the return addresses or you are somehow jumping out of a subroutine without 'popping' it's return address off the stack. If you are really out of stack space and can't find a way to reduce the number of calls, consider using a 'soft stack' routine that simulates the real stack but uses normal RAM instead. It increases the available stack depth but at the expense of slower and bigger code.


Brian.

How to use soft stack for funtions? Can we use soft stack IF Elase statements? Please give me a example. Accouding to my code there are no more than 31 calls.

mikroC PRO for PIC limits the number of non-recursive nested calls to:

  • 8 calls for PIC12 family,
  • 8 calls for PIC16 family,
  • 16 calls for PIC16 Enhancea d family.
  • 31 calls for PIC18 family.
 

I can't give you exact code for your processor but the technique is to use the existing stack as a gateway to a software routine that maintains a stack in normal user RAM. So when you make a call, the software intercepts it and the stack handler routine saves it to a list in RAM. When you return from the routine, it retrieves the data from the list and jumps to the return address. It is quite complicated to do because 'C' also uses the stack to pass parameters between routines.

The penalty is every subroutine imposes a time penalty because of the extra address handling but it does give you 'stack' depth limited only by available free RAM. The extra code only makes it feasible in larger PICs, anything with less than about 2K of RAM or program memory is counter productive.

Usually, with care you can re-code an existing program to use the existing stack.

Brian.
 

Hi,

Usually, with care you can re-code an existing program to use the existing stack.
This is my recommendation also.

You need to know how your microcontroller/code behaves.

A software design usually starts with a flow chart. And an analysis about timing, RAM usuage, code usage and so on.
This does not necessarily need a lot of time and a lot of paperwork. The more experienced you are the more you can do in mind.
The more complex your project is the more important is the analysis ... before ... your start the project.

In my case: I usually consider 80% of this before I start to design the hardware and software.
There are raw flow charts on paper. Hand-drawn. Just to find out the basics and the bottlenecks.
I´m mainly doing real time measurement and control applications.
Here timing is important. One needs to detect processing power bottlenecks, like square-root-calculations. How to solve the timing problems. With dividing into smaller individual parts, in main loop or interrupt, interruptable or not, as subroutine or inline... and so on.
All this considerations I do before starting the project.

If you don´t do this beforehand ... it will come back to you later... and may cause a lot of trouble and headache...and often with a lot of drawbacks... like reduced performance...

Klaus
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top