# Reading a char array provides different results in and out of ISR

I'm having problems reading a char array inside of an ISR. I'm using PIC18F4680 and C18 compiler version 3.41.

The array has several elements which are populated from data read from an RTC and they should be later on used to generate data in another matrix which will be later on used to drive a 5x7 display.

My problem is that when I read the elements of the array, I get one set of values in the ISR and another outside of the ISR.

Here's the output of what I'm getting:

 1  1
0  0
0  0

1  1
0  0
0  0

1  1
0  0
0  0

*******************
1  7
0  0
0  0

*******************
1  1
0  0
0  0

1  1
0  0
0  0

1  1
0  0
0  0


The top line is seconds, second line is minutes and third line is hours since the system was started. The three lines with stars above and below them were send from the ISR. As we can see, the value of seconds was 11 before ISR, 17 in ISR and 11 after the ISR. I've also noticed that this never happens during first 10 seconds after start of a minute or during last 10 seconds of a minute. At other times the changes seem to happen at random.

Here's the relevant code:

k=0;//this is a sort of critical section
data[0]=from_seconds (data[0]);
data[1]=from_minutes (data[1]);
data[2]=from_hours (data[2]).time;
k=1;//if it's zero, ISR won't read the data

for (i=0;i<3;i++)
//I made sure here that the counter variable isn't used anywhere else
{
WriteUSART ( (data[i]/10)+48 );//Converting decimal into ASCII
putrsUSART (" ");
WriteUSART ( (data[i]%10)+48 );
putrsUSART ("\r\n");
}
putrsUSART ("\r\n");
putrsUSART ("\r\n");
putrsUSART ("\r\n");
putrsUSART ("\r\n");


Here's the ISR:

 if (INTCON3bits.INT1IF)
{
if(k)//I know that I'll miss the interrupt if the k is zero, but I'll fix that later
{
fill_matrix (data[2],data[1], data[0]);

putrsUSART ("\r\n");
putrsUSART ("\r\n");
putrsUSART ("*******************");
putrsUSART ("\r\n");

for (j=0;j<3;j++)
{
WriteUSART ( (data[j]/10)+48 );
putrsUSART (" ");
WriteUSART ( (data[j]%10)+48 );
putrsUSART ("\r\n");
}
putrsUSART ("\r\n");
putrsUSART ("\r\n");
putrsUSART ("\r\n");
putrsUSART ("*******************");
putrsUSART ("\r\n");
}
INTCON3bits.INT1IF=0;
}


Any ideas what could be happening here?

UPDATE:

About tcrosley's comment: The part separated by exclamation marks is read by the reading ISR and the part separated by stars is made by the writing ISR.

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
0  0  0  0  0
0  0  0  0  0
0  0  0  0  0
0  0  0  0  0
0  0  0  0  0
0  0  0  0  0
0  0  0  0  0

!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
0  0  0  0  0
0  0  0  0  0
0  0  0  0  0
0  0  0  0  0
0  0  0  0  0
0  0  0  0  0
0  0  0  0  0

!!!!!!!!!!!!!!!!!!!!!!!!

*******************
1  [  _  [  1
t  @  4  0  [
„  0  4  1  Z
t  1  _  1  Z
t  0  5  0  Z
t  0  5  0  Z
0  t  _  Z  0

*******************

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1  [  _  [  1
t  @  4  0  [
„  0  4  1  Z
t  1  _  1  Z
t  0  5  0  Z
t  0  5  0  Z
0  t  _  Z  0

!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1  [  _  [  1
t  @  4  0  [
„  0  4  1  Z
t  1  _  1  Z
t  0  5  0  Z
t  0  5  0  Z
0  t  _  Z  0

!!!!!!!!!!!!!!!!!!!!!!!!

*******************
Q  ›    ›  Q
t  @  ґ  0  ›
„  0  ґ  Q  љ
t  1    Q  љ
t  0  Х  0  љ
t  0  Х  0  љ
0  t    љ  0

*******************

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Q  ›    ›  Q
t  @  ґ  0  ›
„  0  ґ  Q  љ
t  1    Q  љ
t  0  Х  0  љ
t  0  Х  0  љ
0  t    љ  0

!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Q  ›    ›  Q
t  @  ґ  0  ›
„  0  ґ  Q  љ
t  1    Q  љ
t  0  Х  0  љ
t  0  Х  0  љ
0  t    љ  0

!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Q  ›    ›  Q
t  @  ґ  0  ›
„  0  ґ  Q  љ
t  1    Q  љ
t  0  Х  0  љ
t  0  Х  0  љ
0  t    љ  0

!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Q  ›    ›  Q
t  @  ґ  0  ›
„  0  ґ  Q  љ
t  1    Q  љ
t  0  Х  0  љ
t  0  Х  0  љ
0  t    љ  0

!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Q  ›    ›  Q
t  @  ґ  0  ›
„  0  ґ  Q  љ
t  1    Q  љ
t  0  Х  0  љ
t  0  Х  0  љ
0  t    љ  0

!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Q  ›    ›  Q
t  @  ґ  0  ›
„  0  ґ  Q  љ
t  1    Q  љ
t  0  Х  0  љ
t  0  Х  0  љ
0  t    љ  0

!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Q  ›    ›  Q
t  @  ґ  0  ›
„  0  ґ  Q  љ
t  1    Q  љ
t  0  Х  0  љ
t  0  Х  0  љ
0  t    љ  0

!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Q  ›    ›  Q
t  @  ґ  0  ›
„  0  ґ  Q  љ
t  1    Q  љ
t  0  Х  0  љ
t  0  Х  0  љ
0  t    љ  0

!!!!!!!!!!!!!!!!!!!!!!!!

*******************
P  ћ    ћ  P
„  1  ±  0  ћ
…  0  ±  P  ћ
„  0    P  ћ
„  0  С  0  ћ
„  0  С  0  ћ
0  „    ћ  0

*******************

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
P  ћ    ћ  P
„  1  ±  0  ћ
…  0  ±  P  ћ
„  0    P  ћ
„  0  С  0  ћ
„  0  С  0  ћ
0  „    ћ  0

!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
P  ћ    ћ  P
„  1  ±  0  ћ
…  0  ±  P  ћ
„  0    P  ћ
„  0  С  0  ћ
„  0  С  0  ћ
0  „    ћ  0

!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
P  ћ    ћ  P
„  1  ±  0  ћ
…  0  ±  P  ћ
„  0    P  ћ
„  0  С  0  ћ
„  0  С  0  ћ
0  „    ћ  0

!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
P  ћ    ћ  P
„  1  ±  0  ћ
…  0  ±  P  ћ
„  0    P  ћ
„  0  С  0  ћ
„  0  С  0  ћ
0  „    ћ  0

!!!!!!!!!!!!!!!!!!!!!!!!

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
P  ћ    ћ  P
„  1  ±  0  ћ
…  0  ±  P  ћ
„  0    P  ћ
„  0  С  0  ћ
„  0  С  0  ћ
0  „    ћ  0

!!!!!!!!!!!!!!!!!!!!!!!!


As far as I see, the reading ISR always gets the correct data from the matrix, even after several tens of seconds.

-
In your ISR, what does the line "fill_matrix (data[2],data[1], data[0]);" do? –  tcrosley May 11 '12 at 12:01
@tcrosley It reads the three chars given to it as arguments and then fills the data into a matrix which will later on be used to draw show images on displays. –  AndrejaKo May 11 '12 at 12:14
@tcrosley I have a char [7][5] matrix and each char in it contains bits which will be sent to shift registers controlling the 5x7 displays. Another interrupt reads the data from the matrix and sends it to the shift registers and turns on individual dots. –  AndrejaKo May 11 '12 at 12:16
What happens if you dump out the contents of the matrix, either in this ISR or the other ISR that reads the matrix? –  tcrosley May 11 '12 at 12:28
is k volatile? –  Thorn May 11 '12 at 12:40

k=0;//this is a sort of critical section
data[0]=from_seconds (data[0]);
data[1]=from_minutes (data[1]);
data[2]=from_hours (data[2]).time;
k=1;//if it's zero, ISR won't read the data


Where does data[0] get its initial value from? OP comments imply it is first loaded with RTC data, then gets converted here into a different format. But where is the RTC data loaded?

In order to re-use the array, both loading RTC data and converting should happen within the "critical section". Otherwise, it would be possible for the ISR to fire between being loaded with RTC data and being converted. In general, I frown on re-using data arrays like that, especially with ISRs because an ISR will go out of its way to fire at the worst possible time.

Instead, it should work more on a handshaking philosophy. First, load an otherwise-unused array with the RTC data. Then, do the conversion inside the critical section. This ensures that at any and every possible time that the ISR could fire, the values in the data array will always be correct.

As a bonus, I would recommend against this type of critical section approach. Instead, if you need this sort of functionality, set INTCON3bits.INT1IE = 0 so that only this interrupt is masked. The interrupt flag will still be set, and when you set INTCON3bits.INT1IE = 1 later on, the interrupt will fire as expected.

-
Looks like this was the problem after all. Thanks a lot! –  AndrejaKo May 11 '12 at 21:30