PDA

View Full Version : Odd behavior if too many instructions



dksoba
- 15th February 2010, 12:03
I'm using a 16f877a on a Lab X-2 board, at 20mhz. I'm using microcode studio plus w/PBP and MicroCode Loader bootloader.

My program has an assembly interrupt routine, which to my knowledge is correct. I have a simple:

main:

LED = 1
pause 50
LED = 0

goto Main

Other_Routines:
...
End

Although right now my program DOES NOT use "Other Routines"... they somehow affect my program. If I move my encoder, which triggers the assembly interrupt, and I have not commented out "Other Routines", there is considerable lag in the time the LED blinks on off. If I delete a large portion of my unused routine (other routine) then the LED blinks on/off normally dispite the huge number of interrupts, which don't take a long time to process.

I am totally lost. Without the "other routines" my code only takes ~800 words. With it, it's over 1100. I'm wondering if I'm going into a different page, but then I"m not sure because my code is still less than 2k words... if I did go into a new page... what are the consequences of that?

Matt

Acetronics2
- 15th February 2010, 12:51
Hi, Matt

Without your "Faulty" code ... no luck to tell you something usable ...

could be as simple as an Interrupt flag you've forgotten to reset ...

COULD be ...

Alain

dksoba
- 15th February 2010, 22:02
Here is my code:

http://pastebin.com/f456e5db

Sorry it's a bit of a mess. If I comment the "IF" on Line 343, with the corresponding ENDIF, the code runs much more consistently. Also, "Encoder_Counting" at 395 disabled interrupts to do some processing, but only for a few lines while it copies a buffer. If I disable interrupts for the entire routine, one of my problems goes away. The problem was that "Current_Position" got changed randomly. I guessed that my interrupt was screwing with it, so I disabled interrupts for that entire routine. Theoretically, my interrupt shouldn't interfere with that at all. None of the variables there are used by the interrupt. When I copy from the variables which are used during the interrupt, I disable global interrupts. ::Confused::

About assembly interrupts, when I use them I only restore the W register. Do I need to do anything with wsave1, wsave2, or wsave3? I know I have to declare them, but I"m not sure where they get used.

Thanks,
MAtt

Darrel Taylor
- 15th February 2010, 23:09
I'm using microcode studio plus w/PBP and MicroCode Loader bootloader.
Try adding ...

DEFINE LOADER_USED 1 ' Bootloader Used

dksoba
- 16th February 2010, 03:27
Try adding ...

DEFINE LOADER_USED 1 ' Bootloader Used

That is defined in generic_include.inc. I moved it to my main pbp file and removed that include, and it still does the same thing.

Does this have something to do with stacksize? If you overflow the stack... what happens?

Matt

Darrel Taylor
- 16th February 2010, 03:38
Does this have something to do with stacksize? If you overflow the stack... what happens?
It has nothing to do with the stack.
It just makes sure nothing is in the first 4 words.
Those locations are needed for the Bootloader.

And when you overflow the stack on 16F's ... Nothing happens.
It's when you return, that you may end up in the wrong place.

What else is in your Includes?
Can you post them too?
<br>

dksoba
- 16th February 2010, 03:50
My main code (updated):

http://pastebin.com/m7513a97d

Includes:

generic_include.inc:
http://pastebin.com/m1be5ca8f

LCD_Init_PortD.inc:
http://pastebin.com/m17a1888d

ADC10:
http://pastebin.com/m3b596568


In my updated code, something bizarre happens. My setup has an optical encoder w/channels A/B. When I start my program, it drops into "Main" after initializing variables and such. Main displays the current position of the encoder. As my code stands, it's fast and normal. The LCD updates w/the correct position at the speed it's supposed to. If I make ONE simple modification, if I comment out DEBUG_STACK declaration on line 30, all of a sudden for no apparent reason, the update rate of the LCD will be 0.5-1s. No idea what's going on. This isn't the only thing to trigger that. If I then comment out the PID_Loop routine, it'll be fast again... I'm so confused and frustrated and I'm not sure wtf is happening. Oh yea, Even if the LCD updates slowly, it still displays the correct position, which tells me that the interrupt service routine is working.

Thanks,
Matt

Darrel Taylor
- 16th February 2010, 10:16
Ok, this is probably what's happening.

You've got just enough variables that 1 or 2 are getting pushed into BANK1.
In particular _portb_masked.

_portb_masked is used in the interrupt handler, but the Bank isn't being changed. So it ends up overwriting memory in BANK0.
Where it's located makes it overwrite PBP's system registers at R1.

If you comment out the DEBUG_STACK variable like you mentioned, the _portb_masked variable moves and then overwrites PBP's R0 system var.

As the placement of the variable moves, so does the apparent problem that it causes, which corresponds with your symptoms.
If you were to remove two more variables, _portb_masked would no longer be in BANK1, and it would probably run correctly.

Unless you are handling the Banking, any variables you use at the ASM level should be declared in BANK0.

encoder_history VAR BYTE BANK0:encoder_history = 0 'Store the current and last state of channelA/B of the encoder
portb_masked VAR BYTE BANK0:portb_masked = 0 'Masked port B to have only the encoder channels
interrupt_debug VAR BYTE BANK0: interrupt_debug = 0


HTH,

dksoba
- 16th February 2010, 11:10
Thanks! That seems to have done the trick. I'm using MicroCode Studio Plus, is there anyway to see what variables are stored in what banks?

Also, more importantly, I'm not currently saving/restoring the FSR register when I go into my interrupt service routine. I'm not sure if any of the PBP commands use indirect addressing, do they?

If they do, I can do the following:



'create fsrsave
fsrsave VAR byte bank0 system 'What does the "system" do anyways?

...

ASM
...
movf FSR,W
movwf fsrsave

...do the routine

...at the end, restore stuff, and then before retfie
movf fsrsave,W
movwf FSR
retfie



Right? I'm learning so damn much from this project. It's not even an electrical engineering project, it's a mechanical engineering project, but I like to take it to the next level to learn more :).

Thanks,
Matt

Darrel Taylor
- 16th February 2010, 11:52
You can look in the .LST file to see the addresses where each variable is assigned.

You can also File > Import the .cof file into MPLAB then View > File Registers > Symbolic Tab.
It's a lot easier to read than the .lst file.
Of course, you need the datasheet to figure out where the banks are.

And there are many PBP commands that use the FSR.
But none of the statements in your ISR do, so right now there's no need to save/restore it.

Cheers,

dksoba
- 16th February 2010, 18:38
If I go over 1 page of code (2k words, right?) is there anything I need to worry about w/my current code? I know the pbp code will take care of itself, but my ASM ISR might not. I do use PCLATH for the table jump, so that should be fine. And my GOTO's should be fine so long as the entire ISR is in page0, right?

Thanks,
Matt

Darrel Taylor
- 16th February 2010, 21:43
I do use PCLATH for the table jump, so that should be fine. And my GOTO's should be fine so long as the entire ISR is in page0, right?
You do have PCLATH pointing to the Jump Table. But it doesn't take into account the Jump it makes FROM the table.

If _No_Change, _Decrement, _Increment or _Error end up on the other side of a boundary, it will jump to the wrong place.

As long as the entire ISR is in the same page (doesn't have to be page 0), then it won't have a problem.
The trick is knowing when there is a problem, which you can do easily by adding these lines to the end of the ISR ...


retfie ; Return from interrupt
if ((high($) & 18h) != (high(ISR) & 18h))
error ISR crosses page boundary
endif
ENDASM


If the ISR ends up crossing a boundary, that will flag an error to let you know something needs to be moved.

HTH,

dksoba
- 19th February 2010, 18:30
Thanks for all the help. Because of it I was able to finish the robot project I was working on using optical encoders (instead of potentiometers... PID + nonlinear, 270 degree pots ==slow || messy).

The robot contest was for my senior design class at UCSD (Mechanical Engineering). We had to build a robot to move small pieces of PVC pipe from one rotary table to another rotary table, as fast as possible. The recieving table was at least 1 inch higher than the starting table. Also, the receiving table started out with some positions filled, so you had to at least detect if there was space to move cargo there.

My turntables were stacked. IR sensors were used to detect the presence of pipes on both the top and bottom tables. As soon as a PVC pipe was detected (bottom) or an empty slot detected (top), the PIC would rotate the turntable to that position to align with an air nozzle. The air nozzle shot air between 45-60 PSI at the PVC pipe (there was a round cover for the bottom to prevent the air from just going through the pipe).

My PID was very slow (I was running my motor at around 40% duty cycle MAX) because I was having problems getting my derivative term working well at high speed (worked fine at low speed). I've identified the problem, but it's too late. Our robot was the fastest in the class anyways :). We transferred 3 PVC pipes in 1.19-1.86 seconds. I think the second fastest time was on the order of 6 seconds.

Here is a highspeed video of our robot (I think this was our 1.86 second time).

http://www.youtube.com/watch?v=-WweWBp4xNg

Thanks so much,
Matt

Darrel Taylor
- 19th February 2010, 21:58
Congratulations on the Win!

Looks like it was fun.
Maybe I should go back to school. (Just for the challenges) :)
<br>