4
\$\begingroup\$

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.

asked May 11, 2012 at 11:21
\$\endgroup\$
15
  • \$\begingroup\$ In your ISR, what does the line "fill_matrix (data[2],data[1], data[0]);" do? \$\endgroup\$ Commented May 11, 2012 at 12:01
  • \$\begingroup\$ @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. \$\endgroup\$ Commented May 11, 2012 at 12:14
  • \$\begingroup\$ @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. \$\endgroup\$ Commented May 11, 2012 at 12:16
  • \$\begingroup\$ What happens if you dump out the contents of the matrix, either in this ISR or the other ISR that reads the matrix? \$\endgroup\$ Commented May 11, 2012 at 12:28
  • 3
    \$\begingroup\$ is k volatile? \$\endgroup\$ Commented May 11, 2012 at 12:40

1 Answer 1

4
+300
\$\begingroup\$
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.

answered May 11, 2012 at 21:29
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Looks like this was the problem after all. Thanks a lot! \$\endgroup\$ Commented May 11, 2012 at 21:30

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.