Answered in the other forum.
<br>
DT said:
e: ASM vs PBP interrupts
Do you have other I2C statements in the Main program?
If you attempt to execute I2C statements in the interrupt handler, it's possible that another I2C command is already being executed from the main loop.
In which case, everything gets confused.
By commenting the line that you did. When it returns to the main loop, the currently executing I2C statement suddenly thinks it's done with what it was doing, but in actuality, it was the I2C in the interrupt handler that finished, not the one that got interrupted.
Hi Mr Taylor:
Thanks for your response. No, I'm not using i2c out of interrupts routine, but I'm planning to. So I think (the same way yo do) is not a good idea to comment any line in your code. Because of that, here I post you a new "strange workaround" I have found making some tests:
The workaround is to add a byte variable to ReEnterPBP-18.bas like that:
HP_Vars VAR WORD[34] ; group vars together for less banking
R0_SaveH VAR HP_Vars[0]
......
......
TBLPTRH_SaveH VAR TBLPTR_H.highbyte
TBLPTRL_SaveH VAR TBLPTR_H.lowbyte
Product_H VAR HP_Vars[33]
nothing VAR byte
With this new variable called "nothing" I can re-enable the commented line at RestorePBP_H routine:
FLAGS = FLAGS_SaveH
And the code keep working properly. Why???????????????
I don't know the reason, but the last time an issue was fixed with a dummy variable definition, was because of banking errors.
Any suggestion???????
The mystery continues.....
dcorraliza
dcorraliza,
The things you are saying make no sense.
I'm sure you are just seeing the symptoms of the problem, and when they change, you feel that what you changed fixed it. But, more than likely the problem just moved somewhere else.
Only seeing 5 or 6 lines of your 64k code gives me no way of knowing what's going wrong.
Attempting to convert an already existing (very large) program to use Instant Interrupts, almost never works.
When the program was written to begin with. No attention was paid to what can happen with interrupts. The program has already been debugged and known to be working.
Then when you suddenly try to add interrupts, and nothing works anymore. Since you already know the program worked before, it must be Darrel's program that's causing the problem. And any other possibilities are ignored because again. It already works. (on it's own)
DT_INTS is a starting point. If you start writing your program with it. You'll end up with a really cool program in the end.
If you want to apply it to an existing program that wasn't written for interrupts. It's not likely to work.
Sorry,
Darrel Taylor
Hi Mr Taylor:
I agree with you about the difficult task of introducing interrupts on a big program, but I think the problem isn't there.
Following your recommendations I have extract the core lines of my program, just to test the interrupts, so my lite-version is that:
DEFINE LOADER_USED 1
iNCLUDE "cfgvtol-MIXER_18f2685_40mhz.bas"
INCLUDE "DT_INTS-18.bas"
INCLUDE "ReEnterPBP-18.bas"
DEC_MICRO:
DEFINE I2C_HOLD 1
ADCON1 = %00001111
PORTA = 0
TRISA = %111101
PORTB = 0
TRISB = %00000001
PORTC = 0
TRISC = %10000100
PORTE = 0
I2C_RDR_SCL VAR PORTC.3 ' I2C Reader clock
I2C_RDR_SDA VAR PORTC.4 ' I2C Reader data
RDR_I2C_DIR_SLAVE con $24
RDR_I2C_BUFFER_SIZE con 32
RDR_I2C_BUFFER var byte[RDR_I2C_BUFFER_SIZE]
RDR_FLAG VAR BIT
RDR_AUX VAR Byte
RDR_VALUE VAR WORD
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler INT0_INT, _INT_READER, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
@ INT_ENABLE INT0_INT ; enable external (INT) interrupts
RDR_FLAG=0
LOOP:
if rdr_flag then
for RDR_AUX=0 to RDR_I2C_BUFFER_SIZE-1 step 2
RDR_VALUE.lowbyte = RDR_I2C_BUFFER[RDR_AUX]
RDR_VALUE.highbyte = RDR_I2C_BUFFER[RDR_AUX+1]
hserout[dec RDR_VALUE, tab]
next RDR_AUX
hserout [cr, lf]
rdr_flag=0
endif
GOTO LOOP
INT_READER:
I2CREAD i2c_rdr_SDA, i2c_rdr_SCL, rdr_I2C_DIR_SLAVE , [str RDR_I2C_BUFFER\RDR_I2C_BUFFER_SIZE], INT_READER_ERR
RDR_FLAG = 1
INT_READER_ERR:
@ INT_RETURN
This program only waits for an interrupt in the RB0 port and then performs an I2CREAD. If the I2CREAD has success a flag is activated.
In the main loop, we just look for the flag to change, and then the data received is sent through the serial port.
As you said, defining a new variable on your code, makes no changes (my mistake), but restoring FLAG var still is the clue. If FLAG var is restored, the i2cread is only executed properly the first time, and if I delete that line (I know that isn't right, but is used to investigate) I2CREAD is executed every 20ms (the right frame)
Following that trail, I have introduced some dummy vars to obtain FLAGS var status in different moments of the interrupt:
FLAGS=00100000 When being saved for the first time.
FLAGS=01100000 After I2CREAD has being executed.
FLAGS_SaveH=00000100 Line before restoring FLAG, is a little strange because FLAGS was 00100000 when was saved (When was FLAGS_SaveH modified?????)
FLAGS=00000100 After restoring
If that value is restored, I2CREAD don't work any more.
As I have said, if we don't restore the FLAGS var I2CREAD keeps working, leaving FLAGS=01100000
I hope you can help me with this reduced program that shows something strange happening.
Maybe is a nonsense, but value of FLAGS_SaveH when saved (00100000) and when restored (00000100) is the same value with inverted alignment, ?????
Thanks in advance,
dcorraliza
Hi all:
Finally the problem has an explanation, and I feel I have found it. Has been a lot of hours trying to understand this strange behaviour, but at least I caught it.
The question was easier that it seems, it was an "initial" condition, the one that makes all go bad. The first time an interrupt was handled disable the I2CREAD routine. The clue was in the values tracked by me of:
FLAGS=00100000 When being saved for the first time.
FLAGS=01100000 After I2CREAD has being executed.
FLAGS_SaveH=00000100 Line before restoring FLAG, is a little strange because FLAGS was 00100000 when was saved (When was FLAGS_SaveH modified?????)
FLAGS=00000100 After restoring
In this previous paragraph I take notice that the value that was saved on FLAGS_SaveH wasn't the same when we tray to restore it, and I said: When was FLAGS_SaveH modified?????
This is a wrong question, the question is: Was FLAGS saved on FLAGS_SaveH? And the answer is NO. This flag var was not saved, because on top of "SavePBP_H:" routine we only save vars if VarsSaved_H = 0. And this is the reason, VarsSaved_H wasn't initialized at the beginning of the program so depending on the compilation it could have a "0" (Like when I added de "nothing" var) and make all work properly, or a "1" that makes the first interrupt handling not to save previous values, and then restoring rubbish ones.
My workaround is to add a initialization line under variable definition:
DEFINE ReEnterHPused 1
VarsSaved_H VAR BIT
VarsSaved_H=0 <-------ADDED
But maybe Mr Taylor, can help me to know if this initialization should be done on INT_ENABLE routine, to ensure its value every time we enable interrupts. What do you think Mr Taylor?
That's all for now, I hope all of you have enjoyed the mystery resolution, as I do...
Greetings,
dcorraliza
Still looking at my program for your problem I see.
VarsSaved_H is a flag that gets set when ever the Instant Interrupt system saves PBP's System variables in a High Priority interrupt.
With complex programs using both ASM and PBP type handlers, it allows the system to only save and restore the system variables when it needs to.
You are only using a single PBP type interrupt. That bit will always be set on entry to the interrupt handler, And is cleared after the handler has finished. Initializing it to 0 will not do anything.
The only way it could possibly have an affect on your program, is if you have enabled Interrupts that do not have an associated handler.
So anyhow, what are you reading with the I2C statement. (what chip)
<br>
DT
Bookmarks