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

PIC16f1938 Bootloader

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



Joined: 03 Mar 2009
Posts: 40

View user's profile Send private message

PIC16f1938 Bootloader
PostPosted: Tue Feb 08, 2011 11:16 pm     Reply with quote

Hey all,

I have yet another perplexing problem that I am in need of some assistance with. ( he he)

I am attempting to modify the ex_bootloader.c file for a 16f1938 chip. however, when I change the #include statement to the 1938.h file I get an error that I am out of rom. Now I have taken a look at the tree file and it is as follows:


ÀÄex_bootloader
ÃÄMAIN Ram=0
³ ÃÄ??0??
³ ÃÄload_program Ram=0
³ ³ ÀÄreal_load_program ?/460 Ram=54
³ ³ ÃÄ@PUTCHARI_BIU_1 0/6 Ram=0
³ ³ ÃÄatoi_b16 0/53 Ram=5
³ ³ ÃÄatoi_b16 0/53 Ram=5
³ ³ ÃÄatoi_b16 0/53 Ram=5
³ ³ ÃÄatoi_b16 0/53 Ram=5
³ ³ ÃÄatoi_b16 0/53 Ram=5
³ ³ ÃÄatoi_b16 0/53 Ram=5
³ ³ ÃÄatoi_b16 0/53 Ram=5
³ ³ ÃÄ@@FLASHWR 0/18 Ram=0
³ ³ ÃÄ@@WRITE_PROGRAM_MEMORY (Inline) Ram=7
³ ³ ³ ÃÄ@@FLASHWR 0/18 Ram=0
³ ³ ³ ÃÄ@@FLASHWR 0/18 Ram=0
³ ³ ³ ÃÄ@@FLASHWR 0/18 Ram=0
³ ³ ³ ÀÄ@@FLASHWR 0/18 Ram=0
³ ³ ÃÄatoi_b16 0/53 Ram=5
³ ³ ÃÄatoi_b16 0/53 Ram=5
³ ³ ÃÄ@PUTCHARI_BIU_1 0/6 Ram=0
³ ³ ÃÄ@PUTCHARI_BIU_1 0/6 Ram=0
³ ³ ÃÄ@PUTCHARI_BIU_1 0/6 Ram=0
³ ³ ÀÄ@PUTCHARI_BIU_1 0/6 Ram=0
³ ÀÄapplication Ram=0
ÀÄisr 0/5 Ram=0

I notice that the problem is when the atioi_b16() function is being called it is being called a whole bunch. Now with the memory this chip has there should be no problem with ROM being too small since this works with the pic16f877 chips and they have less rom memory than this chip.

I have read that you need to place #separate directives before the function prototype as well as the function definition. I have done this and there is no change.

If anyone knows of a good bootloader for the 16f1938 or if they can tell me what I am doing wrong with this one I would greatly appreciate it. I have been at this for weeks now and I cannot find a solution.

thanks again!
misperry



Joined: 03 Mar 2009
Posts: 40

View user's profile Send private message

PostPosted: Fri Feb 11, 2011 8:18 pm     Reply with quote

bump
misperry



Joined: 03 Mar 2009
Posts: 40

View user's profile Send private message

PostPosted: Mon Mar 14, 2011 9:33 pm     Reply with quote

Well I have been working on this and I believe that I have just made things worse I think. (he he)

I am trying to use the ex_bootloader.c ccs c bootloader with a 16f1938 chip. I was wondering if I am in the right direction or if I am just missing it completely.

here is my software so far

bootloader.h
Code:

#define LOADER_END      getenv("PROGRAM_MEMORY")-10
#define LOADER_SIZE   0x230
#define LOADER_ADDR LOADER_END-LOADER_SIZE


#build(reset=LOADER_ADDR-1, interrupt=LOADER_END+5)

loader.c
Code:

#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;
         }
         else if ((addr < LOADER_ADDR || addr > LOADER_END) && addr < 0x4000){
            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 ((addr!=next_addr)&&(addr&(getenv("FLASH_ERASE_SIZE")-1)!=0))
                        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();
}

ex_bootloader.c
Code:

#include <16F1938.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(INTERNAL=4M)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)  // Jumpers: 8 to 11, 7 to 12

#define _bootloader


#include <bootloader.h>
#include <loader.c>


#org 0x5E,0x60
void application(void) {
  while(TRUE);
}

#org LOADER_ADDR-0x3F,LOADER_ADDR-2
void main(void) {
   if(!input(PIN_B5))
   {
      printf("load_program");
      load_program();
   }

   application();
}

#ORG default

#int_global
void isr(void) {
   jump_to_isr(((LOADER_END-LOADER_SIZE)-1)*(getenv("BITS_PER_INSTRUCTION")/8));
}

I know it compiles but have no Idea why it doesn't work.

Also this is my first time reworking a bootloader for a different chip so any help would be greatly Appreciated.

Thanks so much everyone.
misperry



Joined: 03 Mar 2009
Posts: 40

View user's profile Send private message

PostPosted: Tue Mar 22, 2011 8:53 pm     Reply with quote

bump
BugVito



Joined: 12 Nov 2010
Posts: 3

View user's profile Send private message

PostPosted: Sun Aug 28, 2011 9:57 am     Reply with quote

were you able to find a solution to your problem? I have issues with the 16f1947 and was not able to make any bootloader work so far.
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

Brothers in arms....1947
PostPosted: Mon Aug 29, 2011 10:02 am     Reply with quote

BugVito - I thought I was only one using the 16F1947! Glad to see that Microchip sold another unit!

Misperry - tag along on this conversation - much of what we may send back and forth will probably be applicable.

I have had some mixed success on using the CCS example bootloader code. I have poured over the code quite a bit with another colleague. Though there are some areas that are vague, we do understand the general method to the madness.

Blindly changing the memory allocations will not work. Keep in mind that you have to control the memory, which not something most of us never need to worry about; however, when it comes to the bootloader, it is a different ballgame.

I recommend that you read through the following thread so that you can hopefully avoid the 2 days that I lost. May my sacrifice be to your benefit. Here were the issues that I had:

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

BUT, I'll try to summarize:

1. Even if you copy the bootloader.h to your local directory, the compiler maybe finding the bootloader.h in the C:\Program Files\PICC directory. Therefore, change the name of the file and make sure to change the name in the include statements for the ex_bootloader.c. In fact, I recommend that you change all of the file names (ex_bootloader.c, loader.c, and bootloader.h) and their corresponding include statements to the new names so that there is no possibility of the original code being used by the compiler.

2. With that being said, you can change your memory allocation. However, when you do so and if you are successful in your compilation, check your .lst file. I found that the compiler was putting the delay command at the address where the application was suppose to reside, thereby, stomping on itself as it was writing it. In particular, it was doing it to the delay_ms( ) command, which I need since I doing this in a RS485 half duplex mode. If that is the case, there may be more moving about of the memory.

3. Keep in mind that the allocations of the memory for 877 will more than likely NOT going to work for the 1947 or the 1937. So, you will need to stretch out the allocations.

PCM Programmer wrote a very good explanation of how the memory allocations are handled in the bootloader example. I highly recommend that you look at it. Knowing this is half the battle.

http://www.ccsinfo.com/forum/viewtopic.php?t=45044&highlight=ive+created+technique+solve+problem

Regards -

RckRllRfg
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

Now, I have a question....
PostPosted: Mon Aug 29, 2011 10:17 am     Reply with quote

Why is the hex file calling for an address that is 2x the address of what I was expecting? If I call for the application to start at 600, I see the address in the hex file as 0C00. I also notice that the bootloader accounts for this by dividing the addr (/2). Why is the compiler doing this to begin with?

Thanks -

RckRllRfg
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Aug 29, 2011 12:23 pm     Reply with quote

It's because PIC program memory consists of 12-bit, or 14-bit or 16-bit
words, depending on the series. Each word has an sequential address,
such as 0, 1, 2, 3. But Hex Files only use bytes.

So for example, one instruction word for an 18F452 might be 0x0E90
(which is MOVLW 0x90). But because the Hex file is only in byte format,
that word is broken up into two separate bytes. Each byte is at a different
address in the Hex file.

Basically, it's just the result of converting words into bytes. There are
2 bytes per word, so there are twice as many addressable objects in
the Hex file, hence all addresses are 2x, compared to the .LST file.
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

I see...said the blind man.
PostPosted: Mon Aug 29, 2011 1:36 pm     Reply with quote

PCM programmer.

Thank you for that explanation.

RckRllRfg
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

Here's what is bothering me....
PostPosted: Mon Aug 29, 2011 11:45 pm     Reply with quote

If this has been discussed in another area, please provide the link....

The explanation thus far is for the divide by 2 is fine; however, from a bootloader point of view, it concerns me.

Consider the following 2 lines of hex code. I have spaces so that it is a bit easier to differentiate the different aspects of the code, the underscore is used to keep the data together.

:10 0010 00 09_00_20_30_85_00_77_30_84_00_00_08_03_19_1E_28 6D
:10 0020 00 05_30_F8_00_F7_01_F7_0B_13_28_F8_0B_12_28_2E_30 D3

The 1st line declares that there are a total of 10h (16 decimal) bytes that will be sent (bits 1 and 2). It's start address is 10h (bits 3,4,5&6). For the newbies out there, the colon is bit 0 and is required by the standard.

The 2nd line basically declares the same thing. It is sending 16 bytes of data starting at 20h. More importantly, the address 20h is necessary since the 1st line sent 16 bytes. 20h-10h = F (16 decimal)

In the bootloader, there is a command to divide the address by 2 if a PIC falls within the PCM family. As far as I know, this is all of the PIC16s. But, here's the rub - if I divide the addresses by 2, I get 08h and 10h, which means that the distance of the addresses has been cut in half, from 16 down to 8. That's bad because this mean that I am effectively stomping on 8 bits of the prior line to write the new line. The number of bytes being sent did not change, only the address.

Am I understanding this correctly?

RckRllRfg
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Aug 30, 2011 12:15 pm     Reply with quote

Each pair of bytes is re-assembled into an instruction word. Each line in
the hex file contains enough bytes for 8 instruction words. That's why
you seeing that address delta.
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