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

Need help for bootloader code with pic18f6723
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
manisha



Joined: 03 Feb 2012
Posts: 29

View user's profile Send private message

Need help for bootloader code with pic18f6723
PostPosted: Sat Nov 30, 2013 1:31 am     Reply with quote

Hello everyone...

I need some clarification regarding the code ex_bootloader.c present in the examples folder of PICC. Please help me..
My code is as follows:

main bootloader code :

Code:
/*
#if defined(__PCM__)
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)  // Jumpers: 8 to 11, 7 to 12
*/
//#elif defined(__PCH__)
//#include <18F452.h>
#include <18F6723.h>
#fuses WDT,PUT,PROTECT,BROWNOUT,HS
#use delay(clock=20000000)
#use rs232(baud=9600, ERRORS,xmit=PIN_C6, rcv=PIN_C7)  // Jumpers: 8 to 11, 7 to 12
//#endif


#define _bootloader


#include <codebootload.h>   //bootloader.h
#include <codeloader.c>        //loader.c


/*#if defined(__PCM__)
 #org LOADER_END+1,LOADER_END+10
 
#elif defined(__PCH__)*/
 #org LOADER_END+2,LOADER_END+20
//#endif
void application(void) {
//printf("E");
  while(TRUE);
}

//#if defined(__PCH__)
#org 0x40,0x9F
/*#else
#org 0x20,0x3F
#endif*/

void main(void) {
   if(!input(PIN_G5))   //MCLR to check with reset
   {
       printf("E");
      load_program();
       printf("R");
   }
   
 
   application();
}

#ORG default

#int_global
void isr(void) {
   jump_to_isr(LOADER_END+5*(getenv("BITS_PER_INSTRUCTION")/8));
}


second is bootloader.h renamed as codebootload.h:

Code:
/*#if defined(__PCM__)
   #define LOADER_END   0x1FF
   #define LOADER_SIZE   0x1BF
#elif defined(__PCH__)
*/
   #define FLASH_SIZE getenv("FLASH_ERASE_SIZE")
   #warning FLASH_SIZE
   #if ((0x500 % FLASH_SIZE) == 0 )       //IF 0x500 is even flash boundary
      #define LOADER_END   0x4FF      //difference of 256
      #define LOADER_SIZE  0x3FF
   //  #define LOADER_END   0x100FF   //difference of 256
    // #define LOADER_SIZE  0xFFFF
   #else                                  //ELSE, goto next even boundary
      #define LOADER_END   ((0x500+FLASH_SIZE-(0x500%FLASH_SIZE))-1)
      #define LOADER_SIZE  (LOADER_END-0x100)
   #endif
//#endif

#ifndef _bootloader

/*#if defined(__PCM__)
   #build(reset=LOADER_END+1, interrupt=LOADER_END+5)
#elif defined(__PCH__)*/
   #build(reset=LOADER_END+1, interrupt=LOADER_END+9)
//#endif

#org 0, LOADER_END {}

#endif


Below is loader.c: renamed in code as codeloader.c

Code:

#ifndef LOADER_END

#define LOADER_END      getenv("PROGRAM_MEMORY")-1

/*#if defined(__PCM__)
   #define LOADER_SIZE   0x17F
#elif defined(__PCH__)*/
   //#define LOADER_SIZE   0x3FF
   #define LOADER_SIZE   0x3FF
//#endif
#endif


#define LOADER_ADDR LOADER_END-LOADER_SIZE
#define BUFFER_LEN_LOD 64

int  buffidx;
char buffer[BUFFER_LEN_LOD];

#define ACKLOD 0x06
#define XON    0x11
#define XOFF   0x13

#SEPARATE
unsigned int atoi_b16(char *s);

#ORG LOADER_ADDR+10, LOADER_END auto=0 default
void real_load_program (void)
{
 
   int1  do_ACKLOD, done=FALSE;
   int8  checksum, line_type;
   int16 l_addr,h_addr=0;
   int32 addr;
   #if getenv("FLASH_ERASE_SIZE")>2
      int32 next_addr;
   #endif
   int8  dataidx, i, count;
   int8  data[32];

   while (!done)  // Loop until the entire program is downloaded
   {
      buffidx = 0;  // Read into the buffer until 0x0D ('\r') is received or the buffer is full
      do {
         buffer[buffidx] = getc();
      } while ( (buffer[buffidx++] != 0x0D) && (buffidx <= BUFFER_LEN_LOD) );

      putchar (XOFF);  // Suspend sender

      do_ACKLOD = TRUE;

      // Only process data blocks that start with ':'
      if (buffer[0] == ':') {
         count = atoi_b16 (&buffer[1]);  // Get the number of bytes from the buffer

         // Get the lower 16 bits of address
         l_addr = make16(atoi_b16(&buffer[3]),atoi_b16(&buffer[5]));

         line_type = atoi_b16 (&buffer[7]);

         addr = make32(h_addr,l_addr);

         #if defined(__PCM__)  // PIC16 uses word addresses
            addr /= 2;
         #endif

         // If the line type is 1, then data is done being sent
         if (line_type == 1) {
            done = TRUE;
         #if defined(__PCM__)
         } else if ((addr < LOADER_ADDR || addr > LOADER_END) && addr < 0x2000){
         #elif defined(__PCH__)
         } else if ((addr < LOADER_ADDR || addr > LOADER_END) && addr < 0x300000){
         #endif
            checksum = 0;  // Sum the bytes to find the check sum value
            for (i=1; i<(buffidx-3); i+=2)
               checksum += atoi_b16 (&buffer[i]);
            checksum = 0xFF - checksum + 1;

            if (checksum != atoi_b16 (&buffer[buffidx-3]))
               do_ACKLOD = FALSE;
            else   {
               if (line_type == 0) {
                  // Loops through all of the data and stores it in data
                  // The last 2 bytes are the check sum, hence buffidx-3
                  for (i = 9,dataidx=0; i < buffidx-3; i += 2)
                     data[dataidx++]=atoi_b16(&buffer[i]);

                  #if getenv("FLASH_ERASE_SIZE") > getenv("FLASH_WRITE_SIZE")
                     #if defined(__PCM__)
                        if ((addr!=next_addr)&&(addr&(getenv("FLASH_ERASE_SIZE")-1)!=0))
                     #else
                        if ((addr!=next_addr)&&(addr&(getenv("FLASH_ERASE_SIZE")/2-1)!=0))
                     #endif
                           erase_program_eeprom(addr);
                     next_addr = addr + 1;
                  #endif
                  write_program_memory(addr, data, count);
               }
               else if (line_type == 4)
                  h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));
            }
         }
      }

      if (do_ACKLOD)
         putchar (ACKLOD);

      putchar(XON);
   }

   putchar (ACKLOD);
   putchar(XON);
   #ifndef _bootloader
   reset_cpu();
   #endif
}

unsigned int atoi_b16(char *s) {  // Convert two hex characters to a int8
   unsigned int result = 0;
   int i;

   for (i=0; i<2; i++,s++)  {
      if (*s >= 'A')
         result = 16*result + (*s) - 'A' + 10;
      else
         result = 16*result + (*s) - '0';
   }

   return(result);
}

#ORG default


#ORG LOADER_ADDR, LOADER_ADDR+9
void load_program(void)
{
   real_load_program();
}


First I have loaded the above code as bootloader,then when I have checked for the execution of the main & it is seen that printf("E"); presnt in the main code is executed on hyperterminal and it is struck in the load program() and the next printf i.e R is not executed. I think there is a concern with loader_size and loader_end... When E is displayed on serial port monitor when I have dumped the hex of below file it is received by the controller but no result..

The application file is:
Code:
#include <18F6723.h>
#fuses WDT,PUT,PROTECT,BROWNOUT,HS             
#use delay(clock=20000000,restart_wdt)
#USE RS232(baud=9600,xmit=pin_c6,rcv=pin_c7,ERRORS)
                                                                   
#byte    PORTA  = 0xF80                                                               
#byte    PORTB  = 0xF81                                           
#byte    PORTC  = 0xF82                                                                                             
#byte    PORTD  = 0xF83                                   
#byte    PORTE  = 0xF84                               
#byte    PORTF  = 0xF85                                                                                 
#byte    PORTG  = 0xF86

                                                               
#include<stdio.h>                                             
#include<math.h>                                                           
#include<stddef.h>                                                                 
#include<string.h>                                 
#include<stdlib.h>                         
#include<LCDLEDOP.c>
#define _bootloader

#include <codebootload.h>

#SEPARATE
VOID init_io()         
{                                                   
  set_tris_a(0X00);               
  set_tris_b(0x00);                         
  set_tris_c(0x80);   //1000 0010                       
  set_tris_d(0x00);   //                         
  set_tris_e(0x00);
  set_tris_f(0x00);     //1001 0000
  set_tris_g(0x14);       
}

void display()
{
   lcd_gotoxy(1,4);
   printf (lcd_putc, " From bootloader ");
   delay_ms (100);   
}   

void main(){
    init_io();                   // UC Intializing
    lcd_init();                  // LCD Intializing                                     
    delay_ms(500);                               
                       
    SETUP_WDT(WDT_ON);       
                   
   while(TRUE)                                           
   {   
  restart_wdt();   
  printf("hello");
  display();
   }
}


want the solution for above code i.e to dump code into controller via bootloader. Please help me in solving this problem..
Waiting for a quick reply...
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Nov 30, 2013 11:49 am     Reply with quote

one problem I see is in the if/else processor type statements

I'd delete the conditional if/else and 'hardcode' for the PIC you're using.
Also check to be sure the memory configuring is correct.

and.. always add 'errors' to the use rs232(...options...) when using the hardware UART.


hth
jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Sat Nov 30, 2013 1:29 pm     Reply with quote

The key thing is that if you change the size of the bootloader, you have to change the sizes to match.
You compile the bootloader, look at it's size, round it 'up' to the next page boundary, and put this into the sizes.
Printf statements are quite large, so it'll need to grow quite a bit.
However, you don't say what compiler version you are using?. There were a number of problems with the program memory write routine, a little while ago (very little...). If you are adding the printf's because the actual bootloader won't work, these may be your problem.

Best Wishes
manisha



Joined: 03 Feb 2012
Posts: 29

View user's profile Send private message

PostPosted: Sun Dec 01, 2013 11:30 pm     Reply with quote

Quote:
The key thing is that if you change the size of the bootloader, you have to change the sizes to match.
You compile the booloader, look at it's size, round it 'up' to the next page boundary, and put this into the sizes.
Printf statements are quite large, so it'll need to grow quite a bit.
However, you don't say what compiler version you are using?.


I am using version 4.120 and can you please tell me how to decide the LOADER_SIZE and LOADER_END values?

I have also added the ERRORS for uart...
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Dec 02, 2013 12:13 am     Reply with quote

Quote:
can you please tell me how to decide the LOADER_SIZE and LOADER_END values?

Read this post:
http://www.ccsinfo.com/forum/viewtopic.php?t=45044&start=6

Especially read the 2nd half of the post, which starts like this:
Quote:
---------------------
To fix the problem we need to increase the ROM segment size


If you have questions, ask them here in this thread, not in that one.
SeeCwriter



Joined: 18 Nov 2013
Posts: 160

View user's profile Send private message

PostPosted: Mon Dec 02, 2013 4:57 pm     Reply with quote

This thread is rather fortuitous, since I am just looking into a boot loader for the 18F87J60.

I read through the recommended post on how to modify ex_bootloader.c to compile for a different PIC. First, I don't get any compiler errors for either the default PIC (18F4522) or the 18F87J60. Does that mean I can use ex_bootloader.c as is, with some minor changes? I don't have to adjust segment sizes or #org locations?

I also have question about the memory map. When I compile for the default PIC (18F4522) I get the following:
Code:

ROM Allocation:
000008  isr
00001E  @const724.call
00003A  @const726.call
000054  @PSTRINGC_9600_31766_31767
000076  @PUTCHARI_BIU_1
00007E  atoi_b16
0000E4  @FLASHWR
000104  @WRITE_PROGRAM_MEMORY
000148  real_load_program
00031A  load_program
000320  MAIN
000320  @cinit1
000354  @cinit2
000500  application


And the following defines are produced:

Code:

#define LOADER_END    0x4ff
#define LOADER_SIZE   0x4ff
//          0x00         0x4ff        0x4ff
#define LOADER_ADDR   (LOADER_END - LOADER_SIZE)


The loader address doesn't seem right to me. Is that correct?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Dec 02, 2013 4:59 pm     Reply with quote

Explain to us how you got those numbers (0x4ff everywhere).

And post your compiler version.
SeeCwriter



Joined: 18 Nov 2013
Posts: 160

View user's profile Send private message

PostPosted: Mon Dec 02, 2013 5:25 pm     Reply with quote

I printed out the values of LOADER_END, LOADER_SIZE, and LOADER_ADDR.

Code:

#warning Loader end: LOADER_END
#warning Loader size: LOADER_SIZE
#warning Loader addr: LOADER_ADDR


I' using v5.015 of PCWHD.
SeeCwriter



Joined: 18 Nov 2013
Posts: 160

View user's profile Send private message

PostPosted: Mon Dec 02, 2013 6:03 pm     Reply with quote

As I look at the code, it appears that LOADER_ADDR is not used if BOOTLOADER_AT_START is defined. And it is defined right at the top of bootloader.h. So maybe it doesn't matter what the value of LOADER_ADDR is.

The more interesting question for me is, what does the isr in ex_bootloader.c do?

Code:

#int_global
void isr(void) {
   jump_to_isr(LOADER_END+5*(getenv("BITS_PER_INSTRUCTION")/8));
}


First, I don't see where any interrupts are enabled anywhere. And even if interrupts managed to get enabled, what is the isr jumping to? I don't see its purpose.
SeeCwriter



Joined: 18 Nov 2013
Posts: 160

View user's profile Send private message

PostPosted: Tue Dec 03, 2013 12:10 pm     Reply with quote

Still trying to understand how the bootloader works. I compiled the example program ex_bootloader.c for the 18F87J60.

In function real_load_program() in file loader.c, there is this block of code:
Code:

if (addr == (getenv("PROGRAM_MEMORY") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE"))))
{
    read_program_memory(getenv("PROGRAM_MEMORY"), buffer, getenv("FLASH_ERASE_SIZE") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")));
    write_program_memory(addr, data, count);
    write_program_memory(getenv("PROGRAM_MEMORY"), buffer, getenv("FLASH_ERASE_SIZE") - (getenv("PROGRAM_MEMORY") % getenv("FLASH_ERASE_SIZE")));
}


with "buffer" declared as:
Code:

char buffer[64];


The values of the various macros are:

PROGRAM_MEMORY: 131064
FLASH_ERASE_SIZE: 1024
FLASH_WRITE_SIZE: 64

as determined by using the warning directive to print out the values.
Code:

#warning Flash erase size: getenv("FLASH_ERASE_SIZE")
#warning Flash write size: getenv("FLASH_WRITE_SIZE")
#warning Program mem: getenv("PROGRAM_MEMORY")


Now look at the function read_program_memory() above.

The starting address is 131064. It starts reading at the end of memory? Does it then read down, or does the address wrap to 0, or does it read from non-existent memory?

Then after writing a line of data to program memory, it writes the array in 'buffer' back to program memory. How do we know that it didn't just overwrite what was written?
SeeCwriter



Joined: 18 Nov 2013
Posts: 160

View user's profile Send private message

PostPosted: Tue Dec 03, 2013 1:32 pm     Reply with quote

Ok, I think I see what is happening. The block of code I posted before is saving the last 8-bytes of program memory, writing data, then writing back the 8-bytes of saved program memory. I'm guessing there must be some special information saved in the last 8-bytes of program memory that must be protected/preserved at all costs.

Anyway, I guess I'm talking to myself here.
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Tue Dec 03, 2013 3:52 pm     Reply with quote

SeeCwriter wrote:
As I look at the code, it appears that LOADER_ADDR is not used if BOOTLOADER_AT_START is defined. And it is defined right at the top of bootloader.h. So maybe it doesn't matter what the value of LOADER_ADDR is.

The more interesting question for me is, what does the isr in ex_bootloader.c do?

Code:

#int_global
void isr(void) {
   jump_to_isr(LOADER_END+5*(getenv("BITS_PER_INSTRUCTION")/8));
}


First, I don't see where any interrupts are enabled anywhere. And even if interrupts managed to get enabled, what is the isr jumping to? I don't see its purpose.


This 're-vectors' the interrupts to work with the main code.
The bootloader does not use interrupts, but the main code may. Interrupts physically always call addresses right where the bootloader sits. When you compile with the main code set to start just after the LOADER_END, the interrupt code is put the required number of instructions after this point, and this code then makes the physical interrupt jump to _this_ address.

Best Wishes
SeeCwriter



Joined: 18 Nov 2013
Posts: 160

View user's profile Send private message

PostPosted: Wed Dec 04, 2013 5:00 pm     Reply with quote

Thank you for the explanation.

I compiled ex_bootloader.c for the 18F6722, which is the PIC on the development board I'm using. This is what the .sym file reports:
Code:

ROM Allocation:
000008  isr
00001E  @const724.call
00003A  @const726.call
000054  @PSTRINGC_9600_31766_31767
00007E  @PUTCHARI_BIU_1
000086  atoi_b16
0000EC  @FLASHWR
00010C  @WRITE_PROGRAM_MEMORY
000150  real_load_program
00031E  load_program
000324  MAIN
000324  @cinit1
000346  @cinit2
000500  application

The org statement for function application() is:
Code:

#org LOADER_END+2,LOADER_END+4


Where LOADER_END = 0x4ff

How does function application() end up 0x500, because my calculator says 0x4ff + 2 = 0x501?

Next I compiled ex_bootload.c. The .sym file reports the following:
Code:

ROM Allocation:
000508  @const705.call
000524  @delay_ms1
00054E  @PSTRINGC_9600_31766_31767
00057A  @DIV88
0005A2  @PRINTF_U_9600_31766_31767
000610  main
000610  @cinit1
000632  @cinit2


Doesn't main() need to be at 0x500 for this to work?
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Thu Dec 05, 2013 2:15 am     Reply with quote

The second number in the #ORG, is the end of the space allocated for the 'application'. Nothing to do with the ISR. The ISR, is placed in the _default_ memory space, which starts (for the bootloader) at address zero, and is always (by default) eight bytes (for a PIC18) 'up' in this space. So the #INT_GLOBAL is placed at address 0008. Jump to ISR, for a PIC 18, generates _two_ jumps. One located where the ISR sits, and one 0x10 bytes higher, going to a point 0x10 bytes higher. These are in case interrupt hardware priorities are used.

'Main' is _not_ the code entry point.

Compile a program without the bootloader. Look where 'main' sits.

On the PIC, you have a single 'jump' at the start of memory, which jumps 'to' main. Main is then the 'main' routine.
There has to be this jump, because your main code cannot sit at the start of memory, because it is followed just four instructions (8 bytes) latter by the interrupt entry point. So the memory layout on standard PIC18 code is:

0000 jump to main
0008 jump to high priority ISR
0018 jump to low priority ISR or ISR code
system routines
main etc..

or if interrupt priorities are not used

0000 jump to main
0008 ISR code
system routines
main etc..

With the build at 0x500, add 500 to each of these addresses. Note that 'main' does not sit at 500. It is the jump _to_ it that sits at 500.

Best Wishes
SeeCwriter



Joined: 18 Nov 2013
Posts: 160

View user's profile Send private message

PostPosted: Thu Dec 05, 2013 9:29 am     Reply with quote

I didn't explained myself very well. I will try again.

My understanding of how the bootloader works is, the bootloader code gets programmed into flash between addresses 0 and 0x4ff. And this code never changes. Address 0, the "jump to main" instruction, jumps to the bootloader's main function where it decides whether to enter the loader function or the application. The application is located at 0x500, the first memory address outside the bootloader region. The downloaded application goes into address 0x500 and up. So when the PIC boots up and decides to run the application it calls the function at address 0x500, which is where the downloaded application starts. If the application is put somewhere else, how is the bootloader going to know where it is so it can run it?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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