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 support@ccsinfo.com

How can I return to the main position from interrupt?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ZextroM



Joined: 10 Apr 2012
Posts: 10

View user's profile Send private message

How can I return to the main position from interrupt?
PostPosted: Fri Nov 23, 2012 9:42 am     Reply with quote

How can I return to the main position without using either reset instruction or goto statement ?

I'm looking forward to hearing this question's answer to make up a newly kind of a go-back algorithm to the main place in order to check and re-execute all conditions (some kind of task execution in rtos) to scan main cycle consecutively.

I'm waiting for your entire responses impatiently to see the results of your solutions.

Best regards, ZextroM
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Fri Nov 23, 2012 12:03 pm     Reply with quote

I'm not certain I understand what you want.

You mention interrupt in your title, but not in the main text.

Show us in some sort of pseudo code of what you really want.

Or, better still what you've tried.

Mike
dyeatman



Joined: 06 Sep 2003
Posts: 1924
Location: Norman, OK

View user's profile Send private message

PostPosted: Fri Nov 23, 2012 2:01 pm     Reply with quote

I think they want what we have seen requested earlier a number of times,
the program receives an interrupt then, after the interrupt, it starts from the
beginning rather than where it left off. Then they throw the no reset and no
goto caveat in. Sounds to me like a school project where they don't fully
understand how to structure a program. Most of his problem can be solved
using flag(s) and a background loop in main
_________________
Google and Forum Search are some of your best tools!!!!
ZextroM



Joined: 10 Apr 2012
Posts: 10

View user's profile Send private message

PostPosted: Fri Nov 23, 2012 2:25 pm     Reply with quote

In my main file, lots of function and its sub-functions. When the suitable interrupt routine occurs, the system checks conditions then brunch the endless loop to maintain in the endless loop. In order to expel my working from the endless loop, I use break command, but I do want to go back to the top of the main (not go back to where the int happened in the program counter) without reset instruction ... (like using the program counter's main address to go back its address) (here I don't know how to call the pc's counter type in ccs).

Something like below:
Code:


#int_ext1
{
    .....
    ....
    ....
    while(true)
    {
         ....
         ....
         ...
         break; (from this point to --->)
    }
}



main()
{
    ( >-----    to this point)

    while(true)
    {
        function1
        function2
        function3
        function4
    }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Nov 23, 2012 2:48 pm     Reply with quote

Why don't you like the reset_cpu() function ?
ZextroM



Joined: 10 Apr 2012
Posts: 10

View user's profile Send private message

PostPosted: Fri Nov 23, 2012 2:56 pm     Reply with quote

This shown interrupt routine keeps one output as a 'high'. If I reset the mcu it is gonna be low, and all general working (I/O) affects another real-time (soft-plc system) system's working. When I reset my mcu, all I/O's position shows so weird movement in the real-time. That's why I need to keep the control of system in my hand always. That's why I don't want to reset my mcu rather than go back to below of main to check entire software from overall.
Ttelmah



Joined: 11 Mar 2010
Posts: 19369

View user's profile Send private message

PostPosted: Fri Nov 23, 2012 3:41 pm     Reply with quote

At the end of the day, this is down to hardware design. Add a pull up resistor to the line that must be 'high', so when it floats, it goes high....
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Nov 23, 2012 3:57 pm     Reply with quote

Here are some previous threads on jumping out of an interrupt routine:
http://www.ccsinfo.com/forum/viewtopic.php?t=46639
http://www.ccsinfo.com/forum/viewtopic.php?t=24536
http://www.ccsinfo.com/forum/viewtopic.php?t=45697
http://www.ccsinfo.com/forum/viewtopic.php?t=30011
http://www.ccsinfo.com/forum/viewtopic.php?t=47217
How to break out of a routine and go to the top:
http://www.ccsinfo.com/forum/viewtopic.php?t=22971
http://www.ccsinfo.com/forum/viewtopic.php?t=19704
ZextroM



Joined: 10 Apr 2012
Posts: 10

View user's profile Send private message

PostPosted: Fri Nov 23, 2012 4:21 pm     Reply with quote

Thanks PCM Programmer for your links, but i wrote above, not with goto statement ... because, in the help manual is written as:

Statement: goto label;
The goto statement cause an unconditional branch to the label

I cannot take this risk for my 2500 rows codes ...


I want to get my mcu worked as plc system or rtos system as called as parallel working ... each time i should return the main and scan entire my codes and when interrupts invokes which should interrupt the program.

In my case, I basically need to check program counter and where the main process begin to return its address by using pointer ... but i don't know how to read or control the program counter in ccs c 4.134 ...

Another question, how mcus of plc scan the main routine even in 10 ms ? If we have a minor problem to be able to go back to main ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19369

View user's profile Send private message

PostPosted: Sat Nov 24, 2012 2:29 am     Reply with quote

You do understand, that if you jump 'out' of an interrupt routine, you will leave the stack unbalanced, unless you pop the stack. This will eventually cause the chip to do a reset.

Also though, you may well get a glitch to the signal you are worried about, if you do this, since the peripherals will all be re-initialised.

This is why using a flag is the 'right' way to do this, if your code is properly written.
10mSec is an absolute 'age'. Depends on the speed of your PIC, but one of the modern PIC18's, will execute over 100000 instructions in this time. Now, if your individual states are designed to be quick - no waiting for things - if you want data, and it is not available, you immediately exit. The same for things like doing timings they are all based on using timers, rather than delays, and if the timer has not triggered you again exit the state. Then the master state machine loop, tests for the flag from the interrupt, and if this is triggered force the state to where you want to start. 'example type code':
Code:

    enum {START, PULSEON, PULSEOFF, WAITSERIAL} states=START;
    //Initialisation etc.
    do {
       switch (states) {
       case START:
          //Initialise system here
          states++; //next operation
          break;
       case PULSEON:
          set_timer1(SOMETIME);
          clear_interrupt(INT_TIMER1);
          output_high(PULSE_PIN);
          state++;
          break;
      case PULSEOFF:
          if (interrupt_active(INT_TIMER1)) {
              //Timer has triggered to turn off the pulse
              output_low(PULSE_PIN);
              state++;
          }
          break; //note returns immediately if the timer has not triggered
          //retries in a few _uSec_
      case WAITSERIAL:
          if (bkbhit()) {
              //Here handle the serial that has been received by the interrupt
          }
          state=PULSEON;
          break;
      }
      if (flag_from interrupt) state=START;
   } while (TRUE);
}

Now the code here sits looping in the do...while. Where I want to do something for a 'time', (PULSEON/PULSEOFF), I don't sit in the state, but continuously exit the state till the hardware timer triggers. This way the code is spending all it's 'spare' time out in the loop, where the test for 'flag_from_interrupt' is tested.
Similarly serial is not handled in the individual states, but by using an interrupt triggered (EX_SISR) type receive, and at some point in the states the buffer is tested (bkbhit), and if data has been received, this is processed. The processing of this can be done using another state machine. The key point is that each sub state is very fast - taking no more than a handful of uSec, and getting back to the outer loop, which can then react to the flag from the interrupt, and take the code 'back' to START. I have a state machine like this handling PWM control of opto-encoded servos, and at the same time reading four ADC's, two buttons, and a serial connection (again use the hardware - trigger the ADC, and read it a few states _later_, rather than waiting for the conversion), and executes the outside loop at around 10000*/second. Not 10mSec, but 0.1mSec. It is all down to design.

Best Wishes
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sat Nov 24, 2012 2:48 am     Reply with quote

You have two things to consider:-

1) PC, the program counter.
2) The stack.

With the way you're looking at things one or the other is going to get screwed up.

The approach you're suggesting should not be necessary.

So, let's start again.

Tell us:-

a) How much time must each of your functions take.
b) How often each function must execute.
c) How often the interrupt occurs.

Mike

EDIT Ttelmah's done it for you, whilst I was at the keyboard
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sat Nov 24, 2012 3:21 am     Reply with quote

The suggested methods to implement the intended behaviour ("return to the main position") by regular
C language constructs are preferable also in my opinion. Nevertheless it's possible to realize a kind of
soft reset that skips the hardware initialization involved with reset_cpu() and possibly other actions,
e.g. initialize only a selected part of the variables.

A soft_reset needs to manipulate the stack, as already mentioned. It can be done by a few inline
assembly instructions, but requires a certain understanding of low-level PIC programming. Your posts,
e.g. what you said related to goto statement, gives the impression that you should better refer to regular C.
ZextroM



Joined: 10 Apr 2012
Posts: 10

View user's profile Send private message

PostPosted: Sun Nov 25, 2012 2:59 pm     Reply with quote

Thanks guys for your all replies ...

To Mike Walne:

One of my overall function takes 45 seconds that includes 15 sub-functions and 6 infinite loops (they are broken to assign value from another functions) as well. Also I let the ext (h to L) interrupt occur in this function brunch. However i also want to turn the main cases to begin + scan the entire programme from this one big 45 seconds function. If I choose to restart my cpu in this function, my output affects one real-time-working system to creates so weird condition. That's why I need to soft-reset (so-called) to scan my working after returning from the interrupt.

I also measure adc values within sequently 500us and evaluate their differences within 2ms in this big (45 secs function) function as well.

I've no chance to do as you all mentioned above to figure out one flag position, because I don't know where & when my interrupt occurs to terminate my big function. If I proceed normal interrupt routine, it turns where it stopped by popping out stack. It means my related registers are triggered again and my function again work though I'll ever never prefer !!!

Ttelmah, mentions if you do want to change any situation when the stacks read and re-back, it automatically generates the glitch in my cpu and again force to restart (as far as i understand).

At the end, it is not simple to solve this type of strength in the mcu's world.
Ttelmah



Joined: 11 Mar 2010
Posts: 19369

View user's profile Send private message

PostPosted: Sun Nov 25, 2012 3:37 pm     Reply with quote

Seriously, 'one big 45 second function', just sounds like bad design.
If (for example), the ADC part is done as a state machine, you trigger the ADC, and keep looping in the outer loop, till ADIF says the value is ready. Then read the value, select the next channel, and again loop in the outer function till Tacq has completed. Then trigger the ADC, etc. etc.
There is no reason in any program to stay inside a function like this.
It is just a matter of changing how you think.
You speak about your 2500 lines, as if this is large.
The current project I'm on runs to 60000 lines. It's handling USB, an SD card five ADC channels, an RS485 serial port, an I2C link, keyboard, LCD, a DAC, a dozen solenoids, two PWM outputs, signal routing etc., yet no part of it is ever left 'unserviced' for more than 10mSec. You can push a key at any point, send a USB command, and all are responded to, including things like an emergency stop command from the I2C, which is responded to by flags exactly as being described.

Best Wishes
dyeatman



Joined: 06 Sep 2003
Posts: 1924
Location: Norman, OK

View user's profile Send private message

PostPosted: Sun Nov 25, 2012 3:52 pm     Reply with quote

You talk about dangerous...messing with the processor stack directly is
about the most dangerous thing I can imagine!

I have done some of that in some real time embedded control C++ stuff on
a QNX PC104 stack but I avoid it like the plague when possible.

All that being said, as Ttelmah said one huge function is not good design.
It's better to call a series of functions to service a particular area, a "state
machine" if you will.

I currently maintain a PC104 program with 390,000+ lines of code. It uses a
state machine dispatcher for real time processing of a sort control
system handling three items per second. Using semaphores(flags) the
entire program completes all of the servicing loops (there are 9)
approximately 20 times per second running at 133MHZ with quite a bit of
time left over.
_________________
Google and Forum Search are some of your best tools!!!!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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