|
|
View previous topic :: View next topic |
Author |
Message |
esteban
Joined: 01 Sep 2007 Posts: 13
|
bank switching problem? |
Posted: Mon Sep 03, 2007 6:37 am |
|
|
Hi, all.
I'm having a strange problem that has me stuck for days now.
My original code (the one that first showed strange issues) is much more complex than this one. I've struggled to simplify it while keeping the same odd behaviour, so it's not nice, but is short for convenience (and as a form of thanks in advance to every one who is reading it). I just hope not have made some wrong assumption at any point in the problem, so i've cut down the original one and replaced it for some other (probably stupid) one in this 'reduced' version.
That's the reason of the so many 'unused' variables, by the way.
My board has two led's i'm using for debugging.
It's a PIC 16F877A running at 20MHz
CCSC version is 4.020
I'm using Shane Tolmie's bootloader:(http://www.microchipc.com/PIC16bootload/) on bottom of memory (0x1F00-0x1FFF)
The problem looks so improbable that i would not bother you if i'd still have some usable part of my brain . But i've busted it chasing this one down (or at least it's a fancy way to say i'm dumb).
The thing is that in the main, the while just turn the LED_1 on and off. So i can check with the scope if it is still 'alive'.
The RDA_ISR flips the other led.
After some (random, as far as i can see) number of chars received (actually just the getch(), nothing with them), both leds turn on, which means i'm out of the while.
I find out in the .sym file that the "Bucle" variable is at position 0xC8 (bit 1), while the "LargoDatos_COM" variable is at 0x48.
Suspecting of a bank switching problem, i intentionally put that variable to 0 inside the isr, to maximize the chances of failure (hoping to catch the problem).
Notably, if i set that to 0xFF, i never had the 2 leds on, even after sending chars (watching led_2 pulses on the scope) for quite a long while. Even though, i eventually have the thing apparently hang (no more pulses on LED_1). Even sometimes the isr is still responding (LED_1 off, but LED_2 turning on and off while i send chars).
On the "complete" version of this code, other things happened. I think it could be useless and annoying to give details about that now since it was another code. But if someone think it worth it, i can tell other symptoms i had, and how did i get to this trivial and reduced piece of code.
On previous tries, the same problem occured when i used the TMR0 interrupt (code similar to this one, just harder to track since it 'hang' or "twoleded' almost instantly), or the RB interrupt.
I've checked the LST, and can't find any point in code where a bank switching problem could be occuring, even being so obviuous the symptom. I can see that the global handler is saving STATUS and W, and restoring them later on its way out. I've added the #asm/#endasm blocks in the isr just ... well... just because i didn't know what else to try.
I've tried many, many things, since when the first strange thigs started to happen, the code was pretty bigger, (and i was 10 days younger and used to sleep back then), so i appologize in advance if i find myself replying "i've already done that". It's an awkward answer, i know, and i'm sorry, and hope not have the chance to use it.
I hope someone be so gentle as to take a look at this and point me back on track. Hope i'n not being too tedious, and, again, thanks in advance.
Code: |
#include "C:\Barreras\PIC\Pic_Barrera.h"
#BYTE PUERTO_C=0x07
#org 0x1F00, 0x1FFF void loader16F876(void) {} //protect bootloader code for the 8k 16F876/7
char Buffer[30];
int8 Estado;
#locate STATUS_TEMP =0x67
#locate Flag =0x68
int1 Up;
unsigned int8 LargoDatos_COM = 0;
#define Buffer_COM_SIZE 40
unsigned int8 Buffer_COM[Buffer_COM_SIZE];
unsigned int8 Buffer_COM_Next_In = 0;
unsigned int8 Buffer_COM_Next_Out = 0;
unsigned int8 Estado_COM = 0;
unsigned int8 ContadorCaracteres_COM = 0;
int1 COM_Procesando_Comando = 0;
int1 BUFFER_OVERRUN = 0;
int1 COM_Dato_Valido = 0;
int1 ContarTimeout_COM = 0;
#BIT TXIF = 0x0C.4
char Identificacion[10] = "Carrera ";
char INFO_Unidad[2];
#define Timeout_COM_Protocolo 76 //1 Seg + o -
unsigned int16 Timeout_COM_Protocolo_Contador = 0;
unsigned int16 Contador_Timeout_1 = 0;
#INT_RDA
void RDA_isr()
{
#asm ASIS
SWAPF 03,W
CLRF 03
MOVWF STATUS_TEMP
#endasm
getc();
if (Flag)
{
LED_2_OFF
Flag = 0;
}
else
{
LED_2_ON
Flag = 1;
}
LargoDatos_COM = 0x00;
#asm ASIS
CLRF 03
SWAPF STATUS_TEMP,W
MOVWF 03
#endasm
}
void main()
{
int1 Bucle;
int1 dumb1;
unsigned int8 dumb2;
unsigned int8 dumb3=0;
unsigned int16 dumb4=0;
unsigned char Mem[2];
set_tris_D(0x00);
output_D(0x00);
set_tris_B(0x00);
set_tris_A(0x01);
set_tris_C(0xC9);
set_tris_E(0x00);
setup_adc_ports(NO_ANALOGS);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
// This thing with the uart is because the bootloader sets it to 19200, so i'm resetting it.
setup_uart(0);
#use rs232(baud=38400,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, stream=SERIAL, ERRORS)
setup_uart(1);
LED_1_OFF
LED_2_OFF
Estado = 'C';
Bucle = 1; //<-- The condition for the while.
Timeout_COM_Protocolo_Contador = 0;
INFO_Unidad[1] = 'R';
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
set_timer0(0);
while (Bucle==1)
{
LED_1_ON;
LED_1_OFF;
}
LED_1_ON;
LED_2_ON;
}
This is the H file:
#opt 9 //<-- Tried with 0-9
#include <16F877A.h>
#device *=16
#device adc=10;
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES BROWNOUT //Reset when brownout detected
#FUSES LVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#define SERIAL 0xCE
#use delay(clock=20000000)
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, stream=SERIAL)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#BYTE PCLATH=0x0A
//#Byte
#define LED_1_ON Output_LOW(PIN_C1);
#define LED_1_OFF Output_HIGH(PIN_C1);
#define LED_2_ON Output_LOW(PIN_C2);
#define LED_2_OFF Output_HIGH(PIN_C2); |
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Sep 03, 2007 7:17 am |
|
|
The easiest thing to test is using another compiler version.
The v4.0xx compilers are getting stable but the official state is still 'beta', the official stable release is v3.249. The first bunch of releases was really terrible and only with v4.030 the quality became something what other companies would name beta quality. Considering we are now at version 4.053 you can imagine many bugs have fixed since the release you are using.
Are you really using a low voltage programmer? About 99% of the people using a PIC use a high voltage programmer. With the fuse LVP fuse active you can see erratic program behaviour when there is no pull-up (or pull down, I never know) on this pin. |
|
|
esteban
Joined: 01 Sep 2007 Posts: 13
|
|
Posted: Mon Sep 03, 2007 8:07 am |
|
|
Hi. Thanks for your reply!.
Well, the compiler topic sounds good. I'm kind of confused because i've assumed that if i see it on the LST, there should be good. But i'll not hesistate in trying if there's a chance to solve it (i'll surely have the time to figure out later, and will want to). I'll install the old version i was using (don't remember which one it was, but have hope).
About the LVP, i'm using this same plataform since about six months by now. It doesn't mean a lot, i know, but had not major problems but this one, and this one doesn't 'feel' very erratic. Of course, please note that i say 'feel'. I'm in no way rejecting the possibility. In fact, i'll try to get my hands back on the hardware and set up a high voltage programmer. On the other hand, i have pull down's everywhere. i.e. 10Kohm in every unconnected pin of the micro. And even some weaker ones (33Kohm) on certain connected pins (an oscillator, tachogenerator...). Plus power planes on the board, shieldings, decoupler capacitors, all that stuff.
What i'm trying to say (i'm not made to be concise, sorry, i try. And english is not my mother language), is that if this problem i'm having is what you'd call erratic. Could it be? I'm working with pics since about a year, but i need to learn a lot yet.
Hope i can try with the older version of the compiler by today. Any other suggestion will be more than welcome. And, again, thanks a lot. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Sep 03, 2007 8:33 am |
|
|
CCS could do a better job in explaining that their website contains two versions for download, a stable version and a new version with all latest versions but not extensively tested yet. This complaint has been brought to their attention several times but most likely for commercial reasons they don't want to add this text to their website (it takes them an awkward long time to produce a new stable version, the last stable release is almost 1.5 years old).
It's ok to use a low voltage programmer, or even when using a high voltage programmer you can enable this fuse setting. It is just that it is not very common to see being used. With the LVP fuse set you need a pull-down at pin_b3 to prevent accidental activation of the programming mode which would make the PIC to look like crashed. With this pull-down present there is no problem to be expected. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
|
Ttelmah Guest
|
|
Posted: Mon Sep 03, 2007 9:41 am |
|
|
What happens, if you let the compiler do it's job?...
Why are _you_ fiddling with the W register, and the status, in the interrupt handler?.
As it stands, this is wasted work. The code you write here, is _not_ the core interrupt handler, but a subroutine called _by_ this. If you want to write the handler yourself, then you need to rewrite the 'global' handler, and do a lot more work yourself (reset the interrupt, and store _every_ register used in the routine). This could well cause problems with the optimiser, since it wll assume that any bank selected inside the routine, is still selected on the return.
So, what happens if you remove this?.
Best Wishes |
|
|
esteban
Joined: 01 Sep 2007 Posts: 13
|
|
Posted: Mon Sep 03, 2007 9:43 am |
|
|
Yes, i was aware of the RMW performance. Anyway, the post you just sent me, point it out in a very clear fashion, so it was very interesting.
In fact, after reading, i'm gladly surprised that the scope is showing me a pretty square wave when i look in the led pins. 390 Ohm is doing just fine, as it seems
Anyway, i'd have no big trouble if the RMW would be the problem. Remember that i just put the leds to reach a model (a scaled model, if you like) of the program that is causing troubles to me, so i could post it here whitout being hated.
Actually, the leds are pinned in a socket that should be occupied with a triac optocoupler. I'm using that for this test only, simply because got handy.
The fact i humbly consider relevant about the timing issue is that in one of my tests, i've added large delays between every (each one) instruction inside the 'while' loop. I mean, 200 or even 400 msecs each. When i did that, the problem persisted, even though it was much less noticeable. I've assumed that it was because the number of effective instructions inside the 'while' was much bigger, (because of the cycling of the delays) so the evaluation of the 'bucle' variable occured much less often. And so, the interrupt that is disturbing the bank switching would be happening very much less likely in the (lets call it) critical zone. Kind of hiding the problem. But it took no more than ten minutes or so (of continually sending chars from the pc) for the two leds go on. I could repeat that several times with varying results. Never less than 30 seconds, never more than 10 mins.
Again, it seemed to me that it was the same 'unexplainable' (for me, of course, and for now) problem of bank switching, this time obscured for the delays.
At this point, i don't know if i'm obsessed with the bank switching, or if any of my assumptions has any sense at all!
Yeah! Pin_B3! Brought me that problem you mention (PIC looking dead from time to time). But that was quite some time ago, when i first started the board. I have it very pulled down since then.
Hey, thanks again for so much feedback. I start to feel less desperate. |
|
|
esteban
Joined: 01 Sep 2007 Posts: 13
|
|
Posted: Mon Sep 03, 2007 10:07 am |
|
|
Ttelmah wrote: | What happens, if you let the compiler do it's job?...
Why are _you_ fiddling with the W register, and the status, in the interrupt handler?.
As it stands, this is wasted work. The code you write here, is _not_ the core interrupt handler, but a subroutine called _by_ this. If you want to write the handler yourself, then you need to rewrite the 'global' handler, and do a lot more work yourself (reset the interrupt, and store _every_ register used in the routine). This could well cause problems with the optimiser, since it wll assume that any bank selected inside the routine, is still selected on the return.
So, what happens if you remove this?.
Best Wishes |
Hi. I'm new posting to this forum, and as i said, english is not my mother language. So it's probably my mistake that i haven't been clear enough. If so, i'm sorry.
In my original post, i tried to say that, in particular, this #asm/#endasm block inside the RDA_ISR, was nothing but another of many, many trials.
Quote: |
I've checked the LST, and can't find any point in code where a bank switching problem could be occuring, even being so obviuous the symptom. I can see that the global handler is saving STATUS and W, and restoring them later on its way out. I've added the #asm/#endasm blocks in the isr just ... well... just because i didn't know what else to try.
|
Of course i started letting 'the compiler do it's job'. I added that code you mention after suspecting it was not doing it, and even without a clear understanding of why it wasn't. Just trying to catch the error after many days of work around this.
So, in a new effort to try to be clear, the answer to your question is that if i don't write that code inside the RDA routine, the behaviour is the same.
I'm sorry for the inconvenience and thank you all for the time you are giving me. Hope we can find the problem. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Sep 03, 2007 12:06 pm |
|
|
Quote: | It's a PIC 16F877A running at 20MHz
CCSC version is 4.020
I'm using Shane Tolmie's bootloader.
#FUSES NOWDT
#FUSES HS
#FUSES PUT
#FUSES NOPROTECT
#FUSES NODEBUG
#FUSES BROWNOUT
#FUSES LVP
#FUSES NOCPD
#FUSES NOWRT |
The fuses are set when you program the bootloader HEX file into your PIC.
The fuses in your CCS code shown above, have no effect. They are
not programmed into the PIC at any time. It's only the fuses in the
Shane Tolmie Bootloader that have an effect.
Post the filename of the HEX file for the bootloader that you programmed
into your PIC. Also post the version of the bootloader, or provide
a link the bootloader Zip file that you used. |
|
|
esteban
Joined: 01 Sep 2007 Posts: 13
|
|
Posted: Mon Sep 03, 2007 12:20 pm |
|
|
The bootloader is v9-50
I'm setting the fuses with ICProg when i program the bootloader. I'm aware that the #fuses directives in the c source i've pasted is not in effect.
The hex file of the bootloader is
bootldra.HEX
The zip file i've downloaded from the link i've posted above is
PIC16F87xA_bootloader_v9-50.zip
The link to that zip is
http://www.microchipc.com/PIC16bootload/PIC16F87xA_bootloader_v9-50.zip
and the fuses (as set with ICProg and saved in the bootldra.hex) are:
PWRT (Power On Reset)
BODEN (Brown Out Reset)
LVP (Low Voltage Programming Enable)
HS (High Speed Crystal)
WRT OFF (NOWRT)
Do you think it could have something to do with the bootloader?
Thanks! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Sep 03, 2007 12:30 pm |
|
|
Quote: | LVP (Low Voltage Programming Enable) |
Why do you do this ? Are you using a Low Voltage programmer ?
If so, what is it name ?
I imported the bootldra.hex file into MPLAB and here are the fuses,
converted to CCS notation:
Code: | #fuses HS, NOWDT, PUT, NOBROWNOUT, NOLVP |
|
|
|
esteban
Joined: 01 Sep 2007 Posts: 13
|
|
Posted: Mon Sep 03, 2007 12:45 pm |
|
|
Yes, i'm using a LVP to program the bootloader.
(this one:
http://finitesite.com/d3jsys/
)
The switches you are seeing from the bootloader hex, are the ones with which the bootloader comes inside the zip.
ICProg (the utility i'm using to program the bootloader) allows you to change the fuses and save them back to the hex. That's what i did.
I also change the baudrate on the source of the bootloader (set it to 19200 after running a while at 9600, the default), and recompile it with MPLAB.
On my previuous post, i opened the bootldra.hex with ICProg and copied the fuses configuration. A bit later double checked with mi docs, just in case.
As ckielstra aimed at the LVP also, i had checked again the pulldown (10K) resistor on RB_3 a couple of hours ago. Tested between gnd and the PIC pin and seems ok. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Sep 03, 2007 1:59 pm |
|
|
Are you using a printed circuit board that you bought, such as a PicDem2-
Plus, or is this a board that you built by yourself ?
If you built it, did you put a 100 nF (0.1 uF) ceramic capacitor going to
ground, on each of the two Vdd pins on the PIC ? The 16F877A needs
those capacitors for reliable operation. They should be placed very
close to the Vdd pins, and the connections to ground should also be
very short. The main voltage regulator (7805 type) should have a
10 uF tantalum capacitor between the +5v output pin and ground.
Also, are you running the PIC at +5v ? Or some lower voltage ? |
|
|
esteban
Joined: 01 Sep 2007 Posts: 13
|
|
Posted: Mon Sep 03, 2007 2:01 pm |
|
|
I've just tried compiling with an older version (3.249). Nothing seems to change. Same behaviour.
And about one of my previous posts, forget it, im starting to desesperate again. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Sep 03, 2007 2:04 pm |
|
|
I compiled the program that you posted above with vs. 3.249 and
vs. 4.020. Other than a slight difference in the setup of the TXSTA
register, they look the same.
I suggest that you check for the presence of the 100 nF ceramic
capacitors on the PIC's Vdd pins.
Also, add the ERRORS directive to all #use rs232() statements that
use the hardware pins (which is all of them, in your program). |
|
|
|
|
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
|