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 CCS Technical Support

Serial bootloader & RS232 & reset_cpu()

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
verba



Joined: 17 Aug 2004
Posts: 12

View user's profile Send private message

Serial bootloader & RS232 & reset_cpu()
PostPosted: Fri Aug 20, 2004 2:08 pm     Reply with quote

I have problem. I designed a board to reset auto each day and self reprogramming, but I saw that it doesn�t reprogram with the bootloader when it resets itself (reset_cpu()) and I define the #use RS232
If I push MCLR all it�s ok, the downloader reprogram the micro perfect.
If I don�t use #use RS232 in my program and I send the order to reset by I2C, the micro resets and the downloader reprogram it perfect too. But I want that when I send it a data by I2C the slave detect the change of data and reset_cpu(), in that moment the donwloader program that is waiting at that time should donwload the new program but the downloader seems that detect something and then says "Timeout"
How can I use the RS232 of the micro to send data to the pc among program execution and when it executes "reset_cpu()" and the downloader is waiting, reprograme it ?
What am I doing wrong?
I�m using 16f876-4Mhz and the bootloader of www.microchipc.com precompiled to 16f877/6-19200-4Mhz
My fuses of the bootloader are all off except WRT that is on I tested too with the brown out and power on timer, but same results
My CCS version is 3.206
Thanks[/url]
Haplo



Joined: 06 Sep 2003
Posts: 659
Location: Sydney, Australia

View user's profile Send private message

PostPosted: Fri Aug 20, 2004 6:26 pm     Reply with quote

From what I remember, reset_cpu() does not reset your variables, so if you have any flags set or anything similar after the previous download they might be preventing the code from entering the download routine again.

Also, try letting the watchdog time-out instead of reset_cpu(), it might help.
falleaf1
Guest







PostPosted: Sat Aug 21, 2004 1:27 pm     Reply with quote

try with Tiny bootloader. I found it the best bootloader until now. 100 words only, for most self programmable chips!! (tested).
verba



Joined: 17 Aug 2004
Posts: 12

View user's profile Send private message

Doesn�t work
PostPosted: Mon Aug 23, 2004 3:29 am     Reply with quote

Yes, I know that reset_cpu() only goes to reset vector, but I tried reset the registers of USART and that didn�t work.
I tried also the tiny bootloader, but it�s the same problem, when the micro does the reset_cpu() instruction, the pc software start download but it seems that the chip is changing of state, because the downloader stop with "Out of time"
What registers exactly I need change before a reset_cpu() to the bootloader works?
Thanks
jds-pic



Joined: 17 Sep 2003
Posts: 205

View user's profile Send private message

Re: Doesn't work
PostPosted: Mon Aug 23, 2004 8:37 am     Reply with quote

verba wrote:
What registers exactly I need change before a reset_cpu() to the bootloader works?


verba,

I had this exact problem on a project that I did last year. It was extremely difficult to resolve since it's almost impossible to debug manually or with an ICE. Eventually I traced it down. Unfortunately my old posts were lost when the CCS forum was upgraded, so I'll repeat it here.

All bootloaders, in an effort to save space, make a lot of assumptions about the initial state of the hardware. Simply put, the bootloader expects that all of the special purpose registers are in their power-up condition. This includes the USART, timers, interrupts, WDT, etc etc -- everything. For example, if you leave any timer register in non-power up mode, it is likely that it will interfere with the bootloader operation.

Now then, how to solve this problem... first, get out your databook and find the locations and default values for the special purpose registers. Before running reset_cpu() you MUST set all of the registers back to valid power-up values. This is of course a bit painstaking but as you have found out it is the only way the environment for the bootloader will be set up correctly.

The other problem that may be occurring is if you are running your bootloader serial code at one speed, and your application serial code at another speed. Don't do this if you can. The basic issue occurs when transitioning back into the bootloader; if a char arrives from the host before the bootloader has (re)configured the USART, the USART error flag can get set due to under/overflow (i.e., mismatched baud rates). Once this error bit is set, there is no provision in the bootloader to clear it. Now the bootloader will be stuck, unable to RX as the USART is locked. Once again, it is necessary to reset the entire USART register space before transitioning back into the bootloader. Even this is a little hazardous as a "SYNC" char from the host can arrive at any time, so take care to minimize the window.

My code for the 18F252 bootloader reentry looks as follows:

In included header file, e.g. foobar.h
Code:

// used to reset to power-up defaults for bootloader reentry.
// 18Fxxx special purpose register locations // power up values:

#byte PCL =    0xFF9
#byte FSR0H =  0xFEA // 0x00
#byte FSR0L =  0xFE9 // 0x00

#byte INTCON = 0xFF2 // 0x00
#byte INTCON2= 0xFF1 // 0xF5
#byte INTCON3= 0xFF0 // 0xC0
#byte FSR0H =  0xFEA // 0x00

#byte STATUS = 0xFD8 // 0x00

#byte TMR0H =  0xFD7 // 0x00
#byte TMR0L =  0xFD6 // 0x00
#byte T0CON =  0xFD5 // 0xFF

#byte TMR1H =  0xFCF // 0x00
#byte TMR1L =  0xFCE // 0x00
#byte T1CON =  0xFCD // 0x00

#byte TMR2 =   0xFCC // 0x00
#byte PR2 =    0xFCB // 0xff
#byte T2CON =  0xFCA // 0x00

#byte SSPADD = 0xFC8 // 0x00
#byte SSPSTAT= 0xFC7 // 0x00

#byte SSPCON1= 0xFC6 // 0x00
#byte SSPCON2= 0xFC5 // 0x00

#byte TMR3H =  0xFB3 // 0x00
#byte TMR3L =  0xFB2 // 0x00
#byte T3CON =  0xFB1 // 0x00

#byte SPBRG =  0xFAF // 0x00
#byte RCREG =  0xFAE // 0x00
#byte TXREG =  0xFAD // 0x00
#byte TXSTA =  0xFAC // 0x02
#byte RCSTA =  0xFAB // 0x00

#byte PIR2 =   0xFA1 // 0x00
#byte PIR1 =   0xF9E // 0x00
#byte PIE1 =   0xF9D // 0x00

#byte TRISC =  0xF94 // 0xff
#byte TRISB =  0xF93 // 0xff
#byte TRISA =  0xF92 // 0x3f

#byte PORTC =  0xF82 // 0x00
#byte PORTB =  0xF81 // 0x00
#byte PORTA =  0xF80 // 0x00



in application code file, foobar.c
Code:

void jump_to_bootloader() {
   disable_interrupts(GLOBAL);
   internal_eeprom(INCREMENT16, EEPROM_FLASH_ATT, DONT_CARE);
   display_message(MSG_FWUPDATE,MOD_NONE,TIMEOUT_NONE);
   delay_ms(250);    // >200ms for downloader sync
   FSR0H =  0x00;    //  clean up special purpose registers
   PIR1 =   0x00;
   PIR2 =   0x00;
   TMR2 =   0x00;
   T2CON =  0x00;
   PIE1 =   0x00;
   PR2 =    0xff;
   STATUS = 0x00;
   TMR0H =  0x00;
   TMR0L =  0x00;
   T0CON =  0xFF;
   INTCON = 0x00;
   INTCON2= 0xff;
   INTCON3= 0xc0;
   T1CON =  0x00;
   TMR1L =  0x00;
   TMR1H =  0x00;
   SPBRG =  0x00;
   TXSTA =  0x02;
   RCSTA =  0x00;
   TXREG =  0x00;
   RCREG =  0x00;
   reset_cpu();      // then jump to reset vector
   }


You will notice that the very last thing I do is clean up the USART registers. This ensures that there is very little window of opportunity for the USART error bit(s) to hang me up prior to the bootloader re-running.

n.b.
An alternate approach is to revise the bootloader to clean things up. ideally you'd want to do this for maximum reliability. For example, the PIC could have been reset by an ESD hit. If so, all of the registers could be scrambled eggs. In this case the bootloader will fail to bootload, since as you now are aware, it's expects a sane power-up environment. The tradeoff is that including all of the "cleaning code" in the bootloader makes it more complicated and larger -- two things you don't want in a bootloader.

Hope that helps.

jds-pic
verba



Joined: 17 Aug 2004
Posts: 12

View user's profile Send private message

Thanks jds
PostPosted: Tue Aug 24, 2004 2:31 am     Reply with quote

Thank you for your answer jds.
I saw your antique post in the old forum (google is incredible ;-) and I tried code your solution to my micro 16f876, but the problem is that I�m newbie in pics and I don�t know where find the adresses for some of the registers that you define in your code.
I think that they are the addresses that the datasheet of 16f876 put in "special function register summary" (page 17 of the pdf). I�m right?
I will try it today and today I will tell you if this works too with 16f876.
Thank you very much
PD.- I will put now in another post a very strange problem with the accuracy of the ADC. The values move a lot. If you have experience in this, could you read it, please? Thanks Very Happy
verba



Joined: 17 Aug 2004
Posts: 12

View user's profile Send private message

PERFECT!!!!
PostPosted: Tue Aug 24, 2004 5:58 am     Reply with quote

Perfect, you are rigth, I only translate the addresses of the registers to the pic16f876 and voila Smile

Here is my code if is helpful to anybody that use 16f876

THANK YOU VERY MUCH!!!!

Code:
//Definitions of registers//Initial values

#byte PCL=0x02
#byte FSR=0x04//0x00
#byte INTCON=0x0B//0x00
#byte STATUS=0x03//0x00
#byte TMR0=0x01//0x00
#byte TMR1H=0x0F//0x00
#byte TMR1L=0x0E//0x00
#byte T1CON=0x10//0x00
#byte TMR2=0x11//0x00
#byte PR2=0x92//0xff
#byte T2CON=0x12//0x00
#byte SSPADD=0x93//0x00
#byte SSPSTAT=0x94//0x00
#byte SSPCON=0x14//0x00
#byte SSPCON2=0x91//0x00
#byte SPBRG=0x99//0x00
#byte RCREG=0x1A//0x00
#byte TXREG=0x19//0x00
#byte TXSTA=0x98//0x02
#byte RCSTA=0x18//0x00
#byte PIR2=0x0D//0x00
#byte PIR1=0x0C//0x00
#byte PIE1=0x8C//0x00
#byte TRISC=0x87//0xff
#byte TRISB=0x86//0xff
#byte TRISA=0x85//0x3f
#byte PORTC=0x07//0x00
#byte PORTB=0x06//0x00
#byte PORTA=0x05//0x00


void resetcpu(){
   disable_interrupts(GLOBAL);
   delay_ms(50);    // >200ms for downloader sync
   FSR  =  0x00;    //  clean up special purpose registers
   PIR1 =   0x00;
   PIR2 =   0x00;
   TMR2 =   0x00;
   T2CON =  0x00;
   PIE1 =   0x00;
   PR2 =    0xff;
   STATUS = 0x00;
   TMR0 =  0x00;
   INTCON = 0x00;
   T1CON =  0x00;
   TMR1L =  0x00;
   TMR1H =  0x00;
   SPBRG =  0x00;
   TXSTA =  0x02;
   RCSTA =  0x00;
   TXREG =  0x00;
   RCREG =  0x00;
   reset_cpu();      // then jump to reset vector   
}


As you said, it works only with the 4 last registers (RS232) but I use i2c too and I think that is more secure
THANKS
I only have the problem of the ADC Could help me?
Thanks again Wink
Guest








Re: Thanks jds
PostPosted: Tue Aug 24, 2004 6:02 am     Reply with quote

verba wrote:
I think that they are the addresses that the datasheet of 16f876 put in "special function register summary" (page 17 of the pdf). I�m right?


yes,

i used the same approach on an 16f873 project; your 16f876 code should be similar...

Code:

// used to reset to power-up defaults for bootloader reentry
// special purpose register power up values:
#byte TMR0 =   0x01 // 0x00
#byte PCL =    0x02
#byte STATUS = 0x03 // 0x18
#byte FSR =    0x04 // 0x00
#byte PORTA =  0x05 // 0x00
#byte PORTB =  0x06 // 0x00
#byte PORTC =  0x07 // 0x00
#byte PCLATH = 0x0a // 0x18
#byte INTCON = 0x0b // 0x00
#byte PIR1 =   0x0c // 0x00
#byte PIR2 =   0x0d // 0x00
#byte TMR1L =  0x0e // 0x00
#byte TMR1H =  0x0f // 0x00
#byte T1CON =  0x10 // 0x00
#byte TMR2 =   0x11 // 0x00
#byte T2CON =  0x12 // 0x00
#byte SSPCON = 0x14 // 0x00
#byte RCSTA =  0x18 // 0x00
#byte TXREG =  0x19 // 0x00
#byte RCREG =  0x1a // 0x00
#byte OPTION_REG = 0x81 // 0xff
#byte TRISA =  0x85 // 0x3f
#byte TRISB =  0x86 // 0xff
#byte TRISC =  0x87 // 0xff
#byte PIE1 =   0x8c // 0x00
#byte PCON =   0x8E // ??
#byte PR2 =    0x92 // 0xff
#byte SSPADD = 0x93 // 0x00
#byte SSPSTAT= 0x94 // 0x00
#byte TXSTA =  0x98 // 0x02
#byte SPBRG =  0x99 // 0x00
#byte ADCON =  0x9f // 0x00


Code:

void jump_to_bootloader() {
   FSR =    0x00;          //  clean up special purpose registers
   PCLATH = 0x18;
   INTCON = 0x00;
   PIR1 =   0x00;
   PIR2 =   0x00;
   T1CON =  0x00;
   TMR2 =   0x00;
   T2CON =  0x00;
   OPTION_REG = 0xff;
   PIE1 =   0x00;
   PR2 =    0xff;
   STATUS = 0x18;
   SPBRG =  0x00;
   TMR0 =   0x00;
   TMR1L =  0x00;
   TMR1H =  0x00;
   TXSTA =  0x02;
   RCSTA =  0x00;
   TXREG =  0x00;
   RCREG =  0x00;
   #define BOOTLOADER_ENTRY 0x1F34
   goto_address(BOOTLOADER_ENTRY);  // jump to bootloader start.
   }


note that in the called function i jump to the bootloader entry address, this will work the same as reset_cpu() since the first four instructions at 0x0000 simply jump to the bootloader anyway. for clarity i would use reset_cpu().

jds-pic
Guest








PostPosted: Tue Aug 24, 2004 6:05 am     Reply with quote

oh, i see that you have got it working while i was typing the last reply!!!

that's great, glad to have helped out. send me a beer or a prototype of your project.

Laughing


jds-pic
verba



Joined: 17 Aug 2004
Posts: 12

View user's profile Send private message

PostPosted: Tue Aug 24, 2004 10:34 am     Reply with quote

Don�t worry, if you want a beer I�ll invite you in my project presentation (Madrid, september), anyway you�ll have it.
If you can, could you take a look to my problems in the post "Extrange changes in ADC", I don�t know what it is going wrong.
Thank you very much
Verba
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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