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

Make16 difficulties in the loader.c file

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



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

Make16 difficulties in the loader.c file
PostPosted: Thu Aug 25, 2011 1:22 am     Reply with quote

Hi everyone -

I at a show stopping point for my project. I am using the bootloader code provided by CCS. I have made the adjustments to the ORGs as so eloquently described by PCM programmer. But, when I try to run the code, I am getting a but of a stomp job. It took me a while to determine this; however, I have pinpointed it to the make16 command.

In my last run, the address in the hex code was 1000. l_addr was declaring it to be 0000. That run didn't go very far since the loader program starts at address 40...

I wrote a very simple code to test the make16 and to understand it better. I think I duplicated the issue. Here's are the results from my fprintfs:

Code:

atoi1: 0x0001 
atoi2: 0x0023 
laddr2 with atoi1 and 2: 0x0023
laddr3 using basic C: 0x0023
LONG laddr4 using basic C: 0x0023 


Loader.c has been around for a while, so I know that it works.

Here's my theory - I am using a PIC16. This would be an 8 bit memory. I'm trying to biuld an 16 bit word. When I look at the .lst file, I simply see the make16 putting each byte one after the other. For example:

Code:

.................     l_addr2 = make16(atoi1,atoi2);
09C2:  MOVF   2B,W
09C3:  MOVWF  28
09C4:  MOVF   2C,W
09C5:  MOVWF  27


So, am I dealing with a paging issue? ie, is the location of the of memory outside of my address range?

I will post the "simple" code and the bootloader.h which will be needed to compile and run. I have modified it to give me ample memory for the real_load_program to include PRINTF statements.

Using Version V4.123
Using a PIC16F1947 (but don't let that scare ya since a fool like me has made it dance and sing...I just need to give it a boot!)

RckRllRfg
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

The code ....
PostPosted: Thu Aug 25, 2011 1:30 am     Reply with quote

Code:

#include <16F1947.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=16000000)
#use rs232( UART2, baud=9600, parity=N, xmit=PIN_G1, rcv=PIN_G2, bits=8, stream=sourceside)


#include <bootloader.h>

   int i=0;
   char buffer[4];
   int16 l_addr1, l_addr2, l_addr3;
   int8  atoi1,atoi2;
   long l_addr4;

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);
}

void main(void) {

   
   //Activate the Transciever (OUT-ON)
    output_high(PIN_E5);
    // Establish protocol mode on Pin RE6:  RS-485 is high
    output_high(PIN_E6);
   //// Enable TX mode (DXEN)
    output_high(PIN_E7);
    //// Disable RX mode (RXEN)
   output_low(PIN_E4);

 setup_oscillator(OSC_16MHZ);
   
 buffer[0] = '0';
 buffer[1] = '1';
 buffer[2] = '2';
 buffer[3] = '3';

atoi1 = atoi_b16(&buffer[0]);
atoi2 = atoi_b16(&buffer[2]);

fprintf(sourceside,"atoi1: 0x%4x  \r\n", atoi1);
fprintf(sourceside,"atoi2: 0x%4x  \r\n", atoi2);

l_addr1 = make16(atoi_b16(&buffer[0]),atoi_b16(&buffer[2]));

fprintf(sourceside,"laddr1: 0x%4x  \r\n", l_addr1);

l_addr2 = make16(atoi1,atoi2);
fprintf(sourceside,"laddr2 with atoi1 and 2: 0x%4x \r\n", l_addr2);
   
l_addr3 = atoi2 | (atoi1 <<8);
fprintf(sourceside,"laddr3 using basic C: 0x%4x \r\n", l_addr3);

l_addr4 = atoi2 | (atoi1 <<8);
fprintf(sourceside,"LONG laddr4 using basic C: 0x%4x \r\n", l_addr4);
   
}


NOTES:

You can remove my Transceiver stuff. I am using a half duplex RS485 and I need to control the direction.

I am using the internal 16M oscillator, so change the delay if using a different speed and remove the ocsillator declaration.

I am using UART2. Make sure the rs232 command is set accordingly for UART 1
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

bootloader.h
PostPosted: Thu Aug 25, 2011 1:34 am     Reply with quote

Code:

// for now, give me a ton of memory
 // LOADER_END at 0x1FF + 0x600 = 7FF
   #define LOADER_END   (0x1FF + 0x600 )
   #define LOADER_SIZE  (0x1BF + 0x600 )


#ifndef _bootloader

// With LOADER_END at 0x1FF + 0x600 = 7FF
// reset

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


#org 0, LOADER_END {}

#endif


Notes:

I remove the PCH stuff to thin out the code

I added as much memory for the loader that I could get away with. I'll thin it out later; however, the 1947 has a ton of memory, so I'm not worried about keeping the code tight at this point.
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Thu Aug 25, 2011 5:35 am     Reply with quote

Two wrongs don't make a right... nor do they imply a well used and well proven CCS function is wrong.

There's nothing wrong with make16(). However there are two problems with your code.

The format specified 'x' formats an int, i.e. 8 bits only. Even if you give it an int32, or even an int32 it will only format and print the lowest two hex digits. To get int16s to format in hex you need 'Lx'. You might be thinking that 'x' formats an int, and so it does, but in CCS int is just 8 bits.

The other problem is all about casting. I've been writing recently on another thread about this. l_addr3 = atoi2 | (atoi1 <<8); wont do what I think you are expecting. atoi1 and atoi2 are int8s, and the literal '8' will fit into an int8 therefore the expression atoi2 | (atoi1 <<8) will be evaluated in int8 arithmetic. That means you will loose all of atoi1 as it will get shifted out of an int8. What you need is l_addr3 = atoi2 | ((int16)atoi1 <<8); which forces the whole expression to be computed in int16 form. It doesn't matter anyway as your format specifier, 'x', will ignore the top byte of any int16.

RF Developer
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

Recommendations worked...but, where's lies the problem?
PostPosted: Thu Aug 25, 2011 7:19 am     Reply with quote

RF Developer -

Thank you for your insights and recommendations. Upon implimenting them in the sample code, I was able to see the 16 bit values.

With that being said... I'm going to have to start digging around again. I know that I have a stomp job going on . At this point, the "disintegration" of the loader program is repeatable.

I need to think about this and look further into it. But, any recommendations would be appreciated.

RckRllRfg
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