CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Ways to view variable allocation to memory?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
hello188



Joined: 02 Jun 2010
Posts: 74

View user's profile Send private message

Ways to view variable allocation to memory?
PostPosted: Fri Oct 19, 2012 10:37 pm     Reply with quote

Hi, I am using PIC18F47J53 TX1 module. with following buffered TX routine.

Code:

#define T1_BUFFER_SIZE 64
uint8_t t1_buffer[T1_BUFFER_SIZE];
 uint8_t t1_next_in = 0;
 uint8_t t1_next_out = 0;


Code:
void bputc1(char c) {
   short restart;
   int ni;

   restart=t1_next_in==t1_next_out;
   t1_buffer[t1_next_in]=c;
   ni=(t1_next_in+1) % T1_BUFFER_SIZE;
   while(ni==t1_next_out);
   t1_next_in=ni;
   if(restart){
      RED_DEBUG_PORT = !RED_DEBUG_PORT;
      //Enable TX
        _DE1_PORT = 1;//ENABLE DRIVER
        //Disable RX
        disable_interrupts(INT_RDA);
        disable_interrupts(INT_TIMER4);
        disable_interrupts(INT_TIMER5);
        RCSTA1_CREN = 0;
       
        delay_us(10);//Adjust accordingly
      enable_interrupts(int_tbe);
   }   
}


Code:

void send_bytes1(uint8_t array[], uint8_t length){
    uint8_t i;
    for(i=0; i<length; i++) bputc1(array[i]);
}


Code:
#INT_TBE
void serial_isr() {
   bus_idle_timer = 0;
   if(t1_next_in!=t1_next_out){
      TXREG1 = t1_buffer[t1_next_out];
      t1_next_out=(t1_next_out+1) % T1_BUFFER_SIZE;
   }else{
      //Finished sending Command. Start the Slave Response timer

      //TX_complete = 1;
      disable_interrupts(INT_TBE);
      set_timer5(-48000);//1ms
      clear_interrupt(INT_TIMER5);
      enable_interrupts(INT_TIMER5);
      RX1_buffer_idx = 0;
      
      while(!TXSTA1_TRMT);//Wait until transmission has finished
      _DE1_PORT = 0;
      RCSTA1_CREN = 1;
      clear_interrupt(INT_RDA);
      enable_interrupts(INT_RDA);      
   }       
}


After certain point, or from the start of the program, the send_byte() routine wouldn't trigger INT_TBE, failing to send out bytes. The problem was that, t1_next_out became 97(over the 63 which is the maximum buffer index). No where else in the code touches this variable other than the part of the code above.

The cause of it, I think is from 2)

1) I am using hot insertion of the module(hardware with programmed PIC), onto 24V powered backplane. I suspect program memory or ram corruption while insertion? I programmed same program onto another identical hardware and the t1_next_out doesn't get corrupted. but for this particular board, it does get corrupted(I managed to design the code so that I can observe it using USB). I am not exactly sure if it is software problem or hardware problem from hot inserting. Can hot insertion corrupt program/data memory or program counter? I am using voltage superviser from microchip that has power up delay of reset line. So, I don't think the error might be from the powering up glitch.

2) If it is program problem, what I am suspecting is over-indexing of some array that I declared. If so, are there ways to know at which physical memory location the compiler located the variables??

I am very confused, because the same code works on some hardware and not on others.

Any advice from experts??


Thank you.

[/code]
Ttelmah



Joined: 11 Mar 2010
Posts: 19518

View user's profile Send private message

PostPosted: Sat Oct 20, 2012 12:42 am     Reply with quote

The sym file shows the locations of the variables.
The 'odds' are they are in the order declared, unless the chip is relatively tight on memory, which would suggest it was t1_buffer overflowing.

However I think there is a potential problem with the logic.
If you interrupt in the period between where you have added a character to the buffer, but have not yet updated the pointer, the INT_TBE, could decide that the buffer is empty (since the counter has not been updated), and go to the 'off' state, but since next_in==next_out in the external code, was evaluated before the character was added, bputc, wouldn't re-enable the interrupt, and the code would be hung. This fault is in CCS's example as well. It only happens in the very low probability that an interrupt occurs in that exact moment, but can cause problems. For most users there is an immediate recovery, when the next byte is sent, but you seem to actually be switching operating modes from TX to RX when the buffer is seen to be empty and potentially then getting completely hung....
There are several solutions, but possibly the simplest is to disable_interrupts(GLOBAL); on the line before evaluating next_in==next_out, and then re-enable this after t1_next_in=ni; is executed. This ensures the pointers are updated _before_ the interrupt occurs.
You'd have to enable the interrupt also if the buffer was full.

Best Wishes
hello188



Joined: 02 Jun 2010
Posts: 74

View user's profile Send private message

PostPosted: Sat Oct 20, 2012 2:45 am     Reply with quote

OK. I found the problem. I failed to initialize the a variable that is used as an index to some array resulting in memory corruption. I am wondering, If I do not initialize variable, does it load as some random value everytime the CPU starts up?? For example, at one time, it may read as 0x88, and the other times, it may read as some other value??



Thank you for your feedback. Now, I can make my code more error tight.
Basically, I have to disable only INT_TBE until the pointer was updated since that is the place where it checks the pointer.


Is disable_interrupts() and enable_interrupts() function atomic? In other words, does it take only single instruction cycle and the interrupt is disable on the following cycle??

If not, at least on the C source code, would the interrupt be disabled by the time the next code in line starts to execute??

Thanks.
Ttelmah



Joined: 11 Mar 2010
Posts: 19518

View user's profile Send private message

PostPosted: Sat Oct 20, 2012 4:11 am     Reply with quote

Interrupts are only actually serviced on the first clock of an instruction.
disable_ints and enable_ints, update the flag before the first clock of the next instruction, so interrupts are stopped/started immediately.
The RAM contents on power on, are defined in the data sheet as 'x' (unknown). However many cells will tend to initialise to a fairly constant value. So a sort of 'dartboard' value, rather than truly random.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group