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 support@ccsinfo.com

CCS bootloader at the _TOP_ of the memory

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



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

CCS bootloader at the _TOP_ of the memory
PostPosted: Tue Jan 23, 2007 8:42 am     Reply with quote

Hi,

I've been implementing the CCS bootloader without succes so far. I've implemented the CCs bootloader that is at the beginning of the memory, but I'm experiencing problems with my main program and just can't find what's the problem there. Almost read every bootloader topic overhere! You can read that here:

http://www.ccsinfo.com/forum/viewtopic.php?t=29503

Now I want to put the bootloader on top of the memory. I'm using a PICLF877A with pcwh v3.226. This is my BOOTLOADER_HIGH code:

Code:
#include <16F877A.h>
#fuses XT, PUT, NOWDT, NOPROTECT, NOLVP, NOCPD, NOWRT, NOBROWNOUT, NODEBUG

#include "bootloader_high.h"

#org LOADER_ADDR, LOADER_END default

#use delay (clock = 4000000)
#use rs232 (baud = 9600, parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8, ERRORS)

#include "my_loader.c"

void   main (void);
void application (void);

void main (void)
{
   long timeout = 0;
   int8 i, triggers_found = 0;

   delay_us (50);                // Transmit Buffer clearen
   putc ('L');
   for ( i = 2; i > 0 ; i-- )
   {
      while ( !kbhit() && (++timeout < 0xFFFF) ) // 0xFFFF i.s.o. 50000 saves 5 bytes
         delay_us (100);

      if ( kbhit() )
      {
         if ( getc() == 170 )
            triggers_found++;
         else
            break;       // invalid char received, stop waiting.
      }
      else
         break;
   }
   if ( triggers_found == 2 )
     real_load_program ();
   application ();
}//main

#org 0x0200,0x0300
void application(void)                      // Dummy functie, eigenlijk staat hier de échte main
{
   while (TRUE);
}


bootloader_high.h
Code:
#define LOADER_END      getenv("PROGRAM_MEMORY")-1
#define LOADER_SIZE   0x1BF // 0x17F
#define LOADER_ADDR LOADER_END-LOADER_SIZE


Code:
0000:  MOVLW  18
0001:  MOVWF  0A
0002:  GOTO   7A1
0003:  NOP


These are the 4 first instructions. What do they do? There is nothing on adress 7A1; still the bootloader starts off. Where does the bootloader begin?


Last edited by Christophe on Wed Jan 24, 2007 4:32 am; edited 3 times in total
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Wed Jan 24, 2007 2:01 am     Reply with quote

anybody?

I want to create this:



However the beginning of 'goto start' where is that? Normally that is adress 0000h ?
Ttelmah
Guest







PostPosted: Wed Jan 24, 2007 3:30 am     Reply with quote

This is what the #build instruction does.
It defines where the compiler wil put it's 'start' jump. Similarly, the 'interrupt' entry, defines where the interrupt code jump will be placed.
Just build your main code, with something like:

#build (reset=0x40, interrupt=0x44)

Then your bootloder can just jump to 0x40, to goto the 'main' code.
Unless your bootloader is itself using interrupts, why not consider allowing enough space before the 'main', for the 'main' interrupt handler to be put in the normal location?. You can then just use something like:

#build (reset=0x200)
Which will leave the space for the standard interrupt handler. The bootloader will just need to have it's 'main' org'ed up to the high location in memory (the standard compile will then automatically place the required jump to this), and jump back to the 'reset' location when required.

Best Wishes
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Wed Jan 24, 2007 3:48 am     Reply with quote

in my main:

Code:

#include <C:\Documents and Settings\christophe.seyen\My Documents\Hardware\PIC\BOOTLOADER_HIGH\Bootloader_high.h>
#org LOADER_ADDR, LOADER_END {}
#build (reset=0x200)


this gives:

Code:
0200:  MOVLW  10
0201:  MOVWF  0A
0202:  GOTO   1ED
0203:  NOP


However my main is at 11ED. What is going wrong here?

Quote:
.................... //*********************************** Main ***********************************//
.................... void MAIN ()
.................... {
*
11ED: CLRF 04


The program should run normally, doesn't it?

edit: What does this do? When is this executed?

Code:


// somewhere above
UserBootVectorAddr=label_address(UserBootVector);

UserBootVector:
      #asm
      MOVLW   0x00
      MOVWF   0x0A
      GOTO   0x00
      NOP
      NOP
      #endasm

}


(infos: http://www.sparkfun.com/tutorial/Bloader/bloader-5-vectors.htm )
Ttelmah
Guest







PostPosted: Wed Jan 24, 2007 5:46 am     Reply with quote

The code at 0x200, _is_ a jump to 11ED. This is just how the processor works. The 'jump' instruction, can only contain 11 bits of the target address. Your 'target', needs 13bits. What is done, is that an offset (the '10), is pre-stored into another register, which gets added to the upper bits of the target address, when the next 'jump' occurs.
The compiler sticks the physical 'main' higher up in memory, since it'll always put things like the timer code, RS232 code, etc, in front of it.
The user boot vector jump, is a similar thing, loading the extra bytes.

Best Wishes
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Wed Jan 24, 2007 6:22 am     Reply with quote

Some questions on my program.

1. How can I make sure that when download mode is not activated, the _downloaded_ program starts off? Why does the bootloader program starts off at first?

2. Does loader.c can be used on high memory bootloaders?

Can you help me understand what this code does. I see this statement a lot in upper memory bootloaders.

Code:
unsigned int16 UserBootVectorAddr; // holds the address of our new boot vector

   if (input(RUN_BUTTON) ) {   // download mode activated

      UserBootVectorAddr=label_address(UserBootVector);
     // download code


UserBootVector:
      #asm
      MOVLW   0x00
      MOVWF   0x0A
      GOTO   0x00
      NOP
      NOP
      #endasm

}// main


This is the full listing: It is the gogo bootloader I want to understand. I want to use the CCS loader.c to write my own high memory bootloader. The gogo bootloader does not work with hyperterminal. loader.c does.

Code:
/////////////////////////////////////////////////////////////////////////////
//
//       =================================================
//
//       This code is released under the GPL license. Read the attached license
//       for full information but here's the basic points:
//        - Use it freely
//        - Let others use your new/modified code freely too
//        - So, please release the source
//
//       =================================================
//
//       PIC Boot Loader for the 16F877A MCU
//       V. 1.0 Nov 22, 2006
//       By Arnan (Roger) Sipitakiat
//       http://www.gogoboard.org
//
//       This code is designed for the GoGo board
//       but it should work with any 877A PIC device.
//
//       The loader will start when pin B7 is set high during
//       power-up.
//
//       The loader occupies memory addresses between 0x1e50-0x1fff (0.4k)
//       User code must not use this memory segment.
//       in CCS, you can use the following command to reserve the memory space
//          #ORG 0x1e50, 0x1fff {}
//
//       Note that the configuration bits can't be changed. Whatever is used
//       here is what the user's program is stuck with.
//
/////////////////////////////////////////////////////////////////////////////


#include <16F877A>
#device ADC=10 *=16

#case

#fuses HS,NOWDT,NOPROTECT, BROWNOUT, NOLVP, PUT

#use DELAY(clock=4000000)

#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7)

// define possible reply bytes
#define READY_FOR_NEXT  0x11
#define FINISH_FLAG     0x55
#define BOOTLOADER_OVERWRITE  0x80

#define LOADER_BEGIN      0x1E40
#define LOADER_END        0x1FFF

#define SerBufferSize 45  // serial input buffer size

#define RUN_BUTTON   PIN_B7
#define RUN_LED      PIN_B6
#define USER_LED     PIN_D0

// #org tells the compiler where to put the procedures in memory
#ORG LOADER_BEGIN, LOADER_END auto=0 default

// a slim version of atoi().
// converts ascii text to integer
// i.e. '1' = 1, 'A' = 10
unsigned int a2i(unsigned char asciiByte) {

      if (asciiByte >= 'A' && asciiByte <F> just skip.
            }

            // else if data overlaps the bootloader code -> halt
            else if ((writeAddr >= LOADER_BEGIN) && (writeAddr <LOADER_END> data is in program area
            else {
               for (i=0; i<recLen ;i++) {
                  // (*) Modifing the Boot Vector

                  // The first four commands in memory are called the boot
                  // vector. It resets the board and points to the address of
                  // the main function.

                  // Each HEX file has their own version of these commands. But
                  // since we always want the boot loader to run before the
                  // user code, we must not overwrite the loader's boot vertor.
                  // Instead, we move the user's boot vector to another location
                  // within the boot loader's program area
                  // (see label "UserBootVector" below).

                  // This 'if' command detects user's boot vector and redirects it
                  // The boot vector is at address 0x0000 - 0x0003
                  if ((writeAddr < 0x004) && (i<4) )
                     write_program_eeprom(UserBootVectorAddr + i, Buffer[i]);
                  else
                     write_program_eeprom(writeAddr + i, Buffer[i]);
               }

            }
            // Tells the PC to send the next line
            putc(READY_FOR_NEXT);


         }


      }

      // Tells the PC that we are finished
      putc(FINISH_FLAG);
      for (j=0;j<255;j++) {
         for (i=0;i<255;i++) {}; // this loop gives the chip time to finish
                                 // sending the serial byte before resetting it self.
                                 // I did not use delay_ms() because I have had
                                 // some strange problems with it.
      }

   }

// This is a reboot command written in Assembly.
// these four commands will be overwritten with the boot vector we obtain
// from the HEX file.
// See (*) above for more info.
UserBootVector:
      #asm
      MOVLW   0x00
      MOVWF   0x0A
      GOTO   0x00
      NOP
      NOP
      #endasm
}

#ORG default
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Wed Jan 24, 2007 8:50 am     Reply with quote

I'm able to download the code and the code starts off. However when I reset, the bootloader restarts. How can I enter my program again after a reset?
Ttelmah
Guest







PostPosted: Wed Jan 24, 2007 9:25 am     Reply with quote

Aargh....
The _bootloader_, _must_ always load. This is how it works...
You need to write _it_ to test for some factor at boot (an external pin, or a character on the serial etc.), and then if this is not in the state to trigger 'bootloading', jump to the main code. This is what pin B5, does on the CCS example.

Best Wishes
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Wed Jan 24, 2007 9:39 am     Reply with quote

After 2 weeks of studying bootloaders, I allready knew that.. Probably my question was posed not clear.

I managed to get the bootloader to work... Tks 4 all the support.

The trick was understanding this line:

Code:
UserBootVectorAddr=label_address(UserBootVector);


it gets the adress where a piece of code resides.
That piece of code is resetting the PIC.
When downloading a program, the RESET VECTOR of the hex file is overwritten on those locations. So that means that instead of that code overthere being executed, the _to be downloaded_ program's resetvector is executed and jumps to its main!
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