View previous topic :: View next topic |
Author |
Message |
TSEYFARTH
Joined: 01 Jul 2006 Posts: 1054
|
Posted: Sat Nov 22, 2014 12:16 am Post subject: Best practice - waiting for an interrupt - do nothing loop? |
|
|
Hello all,
I need to wait for an interrupt to occur. What is the best way to do this? I was thinking of a Counting loop just to do nothing but to provide a time out. This interrupt is used for several subs/functions but not at the same time. Any suggestions for managing this with best practices?
Thanks,
Tim
(BASCOM-AVR version : 2.0.7.7 ) |
|
Back to top |
|
|
Arera
Joined: 23 Sep 2007 Posts: 386 Location: Wuppertal, Germany
|
Posted: Sun Nov 23, 2014 2:17 pm Post subject: |
|
|
Hello Tim,
after a couple of hours here is the firt reply to you question. It might have take so long, because it seems there is a deeper fault in the structure of your prog.
I think the core of the problem is the general structure of the prog, and I think many people find that to be unclear. To me, it has been the hardestt part of programming in the beginning years.
It's hard to figure out where to begin, but here's my attempt:
Let's split up your taks in two problems:
1st: waiting for the interrupt
2nd: do something after a timeout
In this post, let's have a look a 1st, and step over to 2nd as soon as 1st is clear.
Generally, no prog should ever wait for anything for more than a few milliseconds.
If that idea sound wired to you, think about this procedure:
A prog should have a main routine, which is executed regulary (do...loop).
Inside this main-loop thre are all the steps and procedures you need, even those that you need only once a year at chistmas.
Outside the main-loop there are interrupt-routines, and things that need to be done only once at all, like configuring external HW.
Now a problems occurs:
How to prevent the chistmas part from beeing executed EVERY run of the main-loop?
The answer might be a flag. A flag might be a bit-var.
The chistmas loop only executes if the flag is SET. The routine must not forget to RESET the flag!
fake-example:
do 'main loop
if christmas_flag = 1 then
reset chistmas flag
toggle led1 'it toggles if the ISR_chistmas occurs (triggered by who knows, it's a fake prog...)
end if
toggle led2 'it toggles very fast....
loop 'end main loop
ISR_christmas:
set chistmas_flag
return
end
As you can see, you don't have to wait until chistmas to toggle led2!
Important: you do not "wait" (halt your prog) until the interrupt occurs, instead you "switch active" the christmas-part of the always-running main-loop to be executed once an interrupt occurs.
So far for now, please let me know if that ideas are helpfull...
Marc |
|
Back to top |
|
|
EDC
Joined: 26 Mar 2014 Posts: 971
|
Posted: Sun Nov 23, 2014 4:19 pm Post subject: |
|
|
State of program You can change in any place of your code and other decisions may be depend on te Program state
Code: | Dim Program_state As Byte
Dim Timeout As Word
Do
If Switch = 0 Then
Program_state = 1
Timeout = 1000
End If
If Program_state = 1 Then
' we waiting for something
End If
If Program_state <> 0 Then
If Timeout = 0 Then Program_state = 0 'choose state You want
End If
Loop
Timer_isr:
If Timeout > 0 Then Decr Timeout 'work only if needed
|
I have one more example of program do nothing whole day and waiting for trigerring
This is programm for stairs or driveway highlighting . To facilitate the movements through the code I used aliases and this works. If anyone interessted i have whole working code with PWM and sequentialy one by one raising bulbs/LED`s.
Code: |
Const Waiting = 0
Const Switch_on_from_down = 1
Const Lighted_from_up = 2
Const Switch_off_from_down = 3
Const Switch_on_from_up = 4
Const Lighted_from_down = 5
Const Switch_off_from_up = 6
'---------------------------------------------------
Do
Select Case Satus
Case Waiting
If Sw1 = 0 Then Status = Switch_on_from_down 'sensors
If Sw2 = 0 Then Status = Switch_on_from_up
Case Lighted_from_down
If Timeout = 0 Then Status = Switch_off_from_down
Case Lighted_from_up
If Timeout = 0 Then Status = Switch_off_from_up
End Select
Gosub Control
Loop
End
'----------------------------------------------------
Control:
Select Case Status
'slowly one by one
Case Switch_on_from_down
'Switch_on_from_down and then..
Status = Lighted_from_down
Timeout = Timeout_time
Case Switch_off_from_down
'Switch_off_from_down and then..
Status = Waiting
Case Switch_on_from_up
'Switch_on_from_up and then..
Status = Lighted_from_up
Timeout = Timeout_time
Case Switch_off_from_up
'Switch_off_from_up and then..
Status = Waiting
End Select
Return |
So Status can be changed in any place. |
|
Back to top |
|
|
TSEYFARTH
Joined: 01 Jul 2006 Posts: 1054
|
Posted: Sun Nov 23, 2014 8:37 pm Post subject: |
|
|
Thanks for the replies.
The problem is, that I have to wait for a radio uC to get to a state before sending a command. This is true for most all of the commands that are sent to the uC. So a command is sent, then you have to wait for the radio to respond back that it is ready to accept the next part of the command. True using flags is appropriate in many case. However in this case, I want to prevent another process from occurring without preventing the interrupt from occurring. This would be easy using waitus... but that also stops all other processes including interrupts, I believe. This is why my thought of a do-nothing or do little loop might make sense.
Code: |
Do
waitus 1
incr cntr
If IntFlag = 1 Then Exit Do
Loop Until Cntr = 1000
|
This, BTW, was an effort to improve code that did similar:
Code: |
Function Api_WaitforCTS() as byte 'returns 1 if CTS is ready.
local w_TO as word
w_TO=0
Api_WaitforCTS=1
while rfm24_CTS_pin = 0 '
waitus 1
incr w_TO
If w_TO = 5000 Then '3000 then 'Time out in 3+mS. Power up is longest command so far. It takes 2.5mS.
Api_WaitforCTS=0
Print "No CTS "
exit function
End If
wend
end function
|
Code such as this calls the above function. There are many other commands code sets that also call the function - waiting for a pin to change, which can also be tied to an Isr - either a Int1 or PCINT10.
Code: |
sub Read_Cmd_Buf(byref b_dat() as byte, byval b_Length as byte)
'Max value of b_Length is 16, no check is done.
local b_Cmd as byte
local b_temp as byte
b_temp=Api_WaitforCTS()
'READ_CMD_BUF
b_Cmd=&h44
reset rfm24_Nsel
spiout b_Cmd,1
b_temp=Api_WaitforCTS()
spiin b_dat(1),b_Length
set rfm24_Nsel
end sub
|
The sub above can be called from many other code sections throughout the program, and as previously stated the Function Api_WaitforCTS is called from any other subs each performing different operations.
So using a flag, or series of flags, at least to me at the moment, would be very complicated.
Finally, it was an effort to speed up the operation overall. In the end, I left it as it is shown above without the use of an Isr.
Thanks again for your responses. I apologize too, it may have been better to include in the original post, what has been included here.
Tim |
|
Back to top |
|
|
EDC
Joined: 26 Mar 2014 Posts: 971
|
|
Back to top |
|
|
i.dobson
Joined: 05 Jan 2006 Posts: 1570 Location: Basel, Switzerland
|
Posted: Mon Nov 24, 2014 6:09 am Post subject: |
|
|
Hi EDC,
Your solution would work, but it doesn't look ready nice. This looks much nicer:
or
Code: |
do
loop until busy=1
|
Regards
Ian Dobson _________________ Walking on water and writing software to specification is easy if they're frozen. |
|
Back to top |
|
|
TSEYFARTH
Joined: 01 Jul 2006 Posts: 1054
|
Posted: Mon Nov 24, 2014 6:20 am Post subject: |
|
|
Ian,
When being executed, I think it is also faster for the uC to use a single line of code rather than If/Then/End If. I did some tests some years back and that ws the case. Mark may have improved that making my comment be false, but I am not sure.
Tim |
|
Back to top |
|
|
Paulvk
Joined: 28 Jul 2006 Posts: 1257 Location: SYDNEY
|
Posted: Mon Nov 24, 2014 9:06 am Post subject: |
|
|
Hello Tim
I found myself that using the case statement was faster and created less code in some of the matrix clock program where I kept running out of flash.
But this does not hold true all the time sometimes it was the same.
Mark said at the time that with the case it loads the value then keeps comparing it each time
but with If Then Else it has to load it each time it tests.
Regards Paul |
|
Back to top |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Mon Nov 24, 2014 11:15 am Post subject: |
|
|
TSEYFARTH wrote: | using waitus... but that also stops all other processes including interrupts, I believe. |
You believe wrong in regard of interrupts.
In contrary, a heavy interrupt load will lengthen any wait. |
|
Back to top |
|
|
EDC
Joined: 26 Mar 2014 Posts: 971
|
Posted: Mon Nov 24, 2014 12:48 pm Post subject: |
|
|
What about open Library for LCD4busy or LCD4busy_anypin and grab ASM procedure from that (for RW pin) Then make Your own Macro I test this later |
|
Back to top |
|
|
|