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

Is there a solution for this code crash?

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



Joined: 11 Mar 2016
Posts: 62
Location: izmir / Turkey

View user's profile Send private message

Is there a solution for this code crash?
PostPosted: Wed Nov 21, 2018 2:24 pm     Reply with quote

Hello again,
I have this code, I'm writing some things on OLED screen via i2c in main loop but I also use int_ext2. There is some i2c readings in interrupt routine from another device and system crashes if i use external interrupt so much. My guess is that external interrupt kicks in before completing i2c writings and starts i2c readings and i2c bus collision is occurring. So I disabled interrupts while writing to oled and it solved the problem. What I wonder is if there is a better way to solve it without disabling interrupts?

18lf2550 v5.070

It is a long code so I paste only related parts.
Main loop Oled codes which runs every 1 seconds :
Code:
if((ScreenPower==1)&&(SMinutes<1))
         {
            disable_interrupts(GLOBAL);
            OLED_gotoxy(0,0);
            printf(OLED_putc,"%02u",Hours);
            OLED_gotoxy(2,0);
            OLED_text(text1,strlen(text1));
            OLED_gotoxy(3,0);
            printf(OLED_putc,"%02u",Minutes);
            OLED_gotoxy(5,0);
            OLED_text(text1,strlen(text1));
            OLED_gotoxy(6,0);
            printf(OLED_putc,"%02u",Seconds);
            OLED_gotoxy(0,1);
            OLED_text(text2,strlen(text2));
            OLED_gotoxy(13,1);
            printf(OLED_putc,"%05Lu",SensorCount);
            OLED_gotoxy(0,2);
            printf(OLED_putc,"%02u",Rtc_Time_Values[4]);
            OLED_gotoxy(2,2);
            OLED_text(text1,strlen(text1));
            OLED_gotoxy(3,2);
            printf(OLED_putc,"%02u",Rtc_Time_Values[3]);
            OLED_gotoxy(5,2);
            OLED_text(text1,strlen(text1));
            OLED_gotoxy(6,2);
            printf(OLED_putc,"%02u",Rtc_Time_Values[2]);
            OLED_gotoxy(8,2);
            OLED_text(text1,strlen(text1));
            OLED_gotoxy(9,2);
            printf(OLED_putc,"%02u",Rtc_Time_Values[1]);
            OLED_gotoxy(11,2);
            OLED_text(text1,strlen(text1));
            OLED_gotoxy(12,2);
            printf(OLED_putc,"%02u",Rtc_Time_Values[0]);
            OLED_gotoxy(0,3);
            printf(OLED_putc,"%02u",ConStatus);
            Oled_gotoxy(0,4);
            OLED_text(EspRcvBuff,strlen(EspRcvBuff));
            OLED_gotoxy(19,7);
            if(ErrorCode!=0)
            {
               printf(OLED_putc,"%02u",ErrorCode);
            }
            else
            {
               OLED_text(textNoError,strlen(textNoError));
            }
            enable_interrupts(GLOBAL);
         }


and this is ext_int2 codes :
Code:
#int_EXT2
void EXT2_isr()
{
   RtcReadTime();
   ext2DropTime=(Rtc_Time_Values[0]+(Rtc_Time_Values[1]*100)+(Rtc_Time_Values[2]*10000)+(Rtc_Time_Values[3]*1000000)+(Rtc_Time_Values[4]*100000000));
   if ((ext2DropTime-ext2LastDropTime)<7)
   {
      delay_cycles(1);
   }
   else
   {
      ext2DropInterval=ext2DropTime-ext2LastDropTime;
      ext2DropCount++;
      ext2TotalDropVolume+=ext2DropVolumeCalculator(ext2DropInterval);
      ext2LastDropTime=ext2DropTime;
   }
   SensorCount++;
}
where RtcReadTime(); does i2c readings.
_________________
There is nothing you can't do if you try
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Nov 21, 2018 4:36 pm     Reply with quote

Quote:
ext2DropTime=(Rtc_Time_Values[0]+(Rtc_Time_Values[1]*100)+(Rtc_Time_Values[2]*10000)+(Rtc_Time_Values[3]*1000000)+(Rtc_Time_Values[4]*100000000));
if ((ext2DropTime-ext2LastDropTime)<7)

What is the time interval in the above code ? I can't tell from the calculation.
Is it in seconds ?

Also, what causes the external interrupt ? And at what time interval ?
Jerson



Joined: 31 Jul 2009
Posts: 125
Location: Bombay, India

View user's profile Send private message Visit poster's website

PostPosted: Wed Nov 21, 2018 7:00 pm     Reply with quote

I would avoid calling any functions inside the ISR. RTCReadTime itself could be causing problems if the device doesn't like too frequent queries. What is the ISR execution Rate - every second or lesser?
elcrcp



Joined: 11 Mar 2016
Posts: 62
Location: izmir / Turkey

View user's profile Send private message

PostPosted: Thu Nov 22, 2018 6:03 am     Reply with quote

PCM programmer wrote:
Quote:
ext2DropTime=(Rtc_Time_Values[0]+(Rtc_Time_Values[1]*100)+(Rtc_Time_Values[2]*10000)+(Rtc_Time_Values[3]*1000000)+(Rtc_Time_Values[4]*100000000));
if ((ext2DropTime-ext2LastDropTime)<7)

What is the time interval in the above code ? I can't tell from the calculation.
Is it in seconds ?

Also, what causes the external interrupt ? And at what time interval ?


Rtc_Time_Values 0,1,2,3,4 presents tenth miliseconds,seconds,mins,hours and days. These lines are to omit any interrupt happens before 70 miliseconds after first one.

Clock speed is 8MHz internal and 400KHz I2C speed by the way.

External interrupts are triggered by a photointerrupter, intervals changes from miliseconds to hours but fastest interval would be 100-150 miliseconds
_________________
There is nothing you can't do if you try


Last edited by elcrcp on Thu Nov 22, 2018 6:17 am; edited 1 time in total
elcrcp



Joined: 11 Mar 2016
Posts: 62
Location: izmir / Turkey

View user's profile Send private message

PostPosted: Thu Nov 22, 2018 6:17 am     Reply with quote

Jerson wrote:
I would avoid calling any functions inside the ISR.

Well I have to, because ext_int occuring moment is the exact time I need to know. I normally use flags to avoid doing long calculations or calling functions in ISRs but it has to be done here =)
Jerson wrote:
What is the ISR execution Rate - every second or lesser?

it changes from miliseconds to hours but maximum rate would be 100-150 miliseconds or maybe 200
I use 8MHz clock speed and 400KHz I2C speed
_________________
There is nothing you can't do if you try
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Thu Nov 22, 2018 7:13 am     Reply with quote

Quote:

it has to be done here


No it doesn't....

Keep time in the PIC. Don't read the RTC in this interrupt. A simple timer 'tick',
can give you time, which even using the internal clock will not drift much. I do
this, and every hour' (by this), read the RTC once and re-sync. That way your
int_ext only needs to record the time, and doesn't have to be trying to read the
RTC. Your interrupt can just record the count on the timer, or the value from
this internal time.
This way two triggers can be really close together, and cause no problems.
Also, since you don't then use the I2C in the interrupt, you can leave interrupts
enabled while talking to the OLED, which will improve the accuracy of the time
recorded.

Also by multiplying up the RTC time inside the interrupt, you are using a
huge amount of time. int32 arithmetic several times. several hundred
thousand machine cycles.... :(

Your issue is occurring, because I2C operations require a complete 'set'
of actions. The compiler automatically protects the parts, but not the
'set'. So you talk to a device with a start, address, data, stop. The
components of this are each protected from being interrupted, but once
the bus is 'open' (the start has been sent), if an interrupt occurs the bus
is already in use when the code in the interrupt happens. You could
disable on a 'per transaction' basic.
Your transactions are actually very inefficiently done. Much better to
assemble a complete string contining the hours, mins, seconds, and send
this as one operation, instead of sending locations for each character/pair
of characters.
elcrcp



Joined: 11 Mar 2016
Posts: 62
Location: izmir / Turkey

View user's profile Send private message

PostPosted: Thu Nov 22, 2018 5:18 pm     Reply with quote

All right, I made some changes but I haven't tried it on device yet. My RTC has 10 milliseconds resolution and so I setup timer3 same to follow RTC and added some lines to main loop to align RTC and TMR3 every hour. Here is main loop :
Code:
while(TRUE)
   {
.
.
.
.
         if((ScreenPower==1)&&(SMinutes<1))
         {
            OLED_gotoxy(0,0);
            printf(OLED_putc,"%02u",Hours);
            OLED_gotoxy(2,0);
            OLED_text(text1,strlen(text1));
            OLED_gotoxy(3,0);
            printf(OLED_putc,"%02u",Minutes);
            OLED_gotoxy(5,0);
            OLED_text(text1,strlen(text1));
            OLED_gotoxy(6,0);
            printf(OLED_putc,"%02u",Seconds);
            OLED_gotoxy(0,1);
            OLED_text(text2,strlen(text2));
            OLED_gotoxy(13,1);
            printf(OLED_putc,"%05Lu",SensorCount);
            OLED_gotoxy(0,2);
            printf(OLED_putc,"%02u",TMR3_Time_Values[4]);
            OLED_gotoxy(2,2);
            OLED_text(text1,strlen(text1));
            OLED_gotoxy(3,2);
            printf(OLED_putc,"%02u",TMR3_Time_Values[3]);
            OLED_gotoxy(5,2);
            OLED_text(text1,strlen(text1));
            OLED_gotoxy(6,2);
            printf(OLED_putc,"%02u",TMR3_Time_Values[2]);
            OLED_gotoxy(8,2);
            OLED_text(text1,strlen(text1));
            OLED_gotoxy(9,2);
            printf(OLED_putc,"%02u",TMR3_Time_Values[1]);
            OLED_gotoxy(11,2);
            OLED_text(text1,strlen(text1));
            OLED_gotoxy(12,2);
            printf(OLED_putc,"%02u",TMR3_Time_Values[0]);
            OLED_gotoxy(0,3);
            printf(OLED_putc,"%02u",ConStatus);
            Oled_gotoxy(0,4);
            OLED_text(EspRcvBuff,strlen(EspRcvBuff));
            OLED_gotoxy(19,7);
            if(ErrorCode!=0)
            {
               printf(OLED_putc,"%02u",ErrorCode);
            }
            else
            {
               OLED_text(textNoError,strlen(textNoError));
            }
         }
.
.
.
.
         if(Hours!=HoursLast)
         {
            if(!RTC_Read_Done)
            {
               disable_interrupts(GLOBAL);
               RtcReadTime();
               TMR3_Time_Values[0]=Rtc_Time_Values[0];
               TMR3_Time_Values[1]=Rtc_Time_Values[1];
               TMR3_Time_Values[2]=Rtc_Time_Values[2];
               TMR3_Time_Values[3]=Rtc_Time_Values[3];
               TMR3_Time_Values[4]=Rtc_Time_Values[4];
               enable_interrupts(GLOBAL);
               RTC_Read_Done=1;
            }
            else
            {
               EspSendHourlyData();
            }
         }
.
.
.
.   

I used enable/disable interrupt at TMR and RTC aligning lines because I want that job done as fast as can without interrupted.

and I also changed ext2 ISR so it won't read RTC.
Plus, my time data form is dd:hh:mm:ss:uu and their max values are 31:23:59:59:99 so I used shifts instead of multiplication considering their max values and I thing it will relive a lot of cycles XD.
Code:
#int_EXT2
void EXT2_isr()
{
   ext2DropTime=(TMR3_Time_Values[0]+(TMR3_Time_Values[1]<<7)+(TMR3_Time_Values[2]<<13)+(TMR3_Time_Values[3]<<19)+(TMR3_Time_Values[4]<<24));
   if ((ext2DropTime-ext2LastDropTime)<7)
   {
      delay_cycles(1);
   }
   else
   {
      ext2DropInterval=ext2DropTime-ext2LastDropTime;
      ext2DropCount++;
      ext2TotalDropVolume+=ext2DropVolumeCalculator(ext2DropInterval);
      ext2LastDropTime=ext2DropTime;
   }
   SensorCount++;
}

_________________
There is nothing you can't do if you try
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Fri Nov 23, 2018 2:23 am     Reply with quote

Code:

ext2DropTime=(TMR3_Time_Values[0]+(TMR3_Time_Values[1]<<7)+(TMR3_Time_Values[2]<<13)+(TMR3_Time_Values[3]<<19)+(TMR3_Time_Values[4]<<24));


Probably won't work.
Reason is 'size'.

Assume TMR3_Time_values, is int8?.

Then you can't shift it left 7, 13, 19 or 24 bits, since the variable is not large enough to take the result.
The only reason it worked with the multiplication, was implicit casting. If you multiplied an int8, by 10000 (say), the compiler sees that this multiplicand is a 16bit value, and implicitly casts the value up to the larger type. For your shifts, this doesn't happen.
You'd need to explicitly cast up. So:
Code:

ext2DropTime=(TMR3_Time_Values[0]+((int16)TMR3_Time_Values[1]<<7)+((int32)TMR3_Time_Values[2]<<13)+((int32)TMR3_Time_Values[3]<<19)+((int32)TMR3_Time_Values[4]<<24));


However I'd honestly still say, why not just have a tick, stored in an int32?. The tests then become a doddle, so do the conversions here etc.. You can convert this 'tick' back and forth to the separate bytes form very easily when you read or write the RTC. In CPU terms working with a 'tick' value is a much nicer way to go.
elcrcp



Joined: 11 Mar 2016
Posts: 62
Location: izmir / Turkey

View user's profile Send private message

PostPosted: Fri Nov 23, 2018 5:25 am     Reply with quote

Ttemah wrote:
However I'd honestly still say, why not just have a tick
I think you mean "#USE TIMER" funciton? I checked it after you mentioned but there is no start/stop command for that function. However I believe I can control it by controlling releated timer on/off bit. I just don't get how that function increases tick counts without using an ISR? I mean, there is a timer counting in background and there is a variable to write that ticks to. When and where it writes in that variable if its not interrupting the program flow? Confused
_________________
There is nothing you can't do if you try
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Fri Nov 23, 2018 5:31 am     Reply with quote

No, I just meant use a tick.

Just have a counter. When you read the time from the RTC, turn this into a count from an arbitrary point in time you have chosen. Load the counter with this. Then just have an interrupt tick called every 10mSec, that increments this.

In your edge interrupt code, storing the time, just becomes a matter of saving the count in this. Nothing more.

If you want to display this, just use simple division to give the 'clock' time.

I quite commonly use 'mSec in the day' as a tick value (since then I don't have to calculate the day times, since these don't change all day).

#use timer, is a CCS 'complication', to try to make using a timer simpler.... However if you choose your timer with care, the chip can make it simpler for you. So (for example), in your case if you are not using timer2, this using /16 prescaler, PR2=124, and postscale /10, gives 100 interrupts/second.
elcrcp



Joined: 11 Mar 2016
Posts: 62
Location: izmir / Turkey

View user's profile Send private message

PostPosted: Fri Nov 23, 2018 5:20 pm     Reply with quote

Oh, I see now. So you say, instead of doing tests and increase seconds,minutes etc. in timer isr and then merging them together in every ext2 isr, just use a mseconds counter in timer isr and use that value in ext2 isr and only convert them to seconds, minutes, etc. when I show or send them. This is indeed much efficient.
I think my thinking is stuck at dd:hh:mm:ss:uu format because of RTC data format and couldn't understand what you are trying to say.

Thank you!
_________________
There is nothing you can't do if you try
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Sat Nov 24, 2018 2:01 am     Reply with quote

Exactly.
And (of course), the key is that the 'efficiency' is exactly where you need it (in
the ISR). Delays for the conversions only occur out in the display code. Smile

RTC chips are generically 'designed' for things like 'clocks', where output is in
'human readable' form. C has a standard library (time.c/time.h), which
converts a 'tick', backwards and forwards to a human readable form. You have
to define 'CLOCK_PER_SECOND' to tell it what the 'tick' rate actually is, and the
functions in this can then handle all the conversions.
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