|
|
View previous topic :: View next topic |
Author |
Message |
RckRllRfg
Joined: 20 Jul 2011 Posts: 60
|
Memory stomping in the bootloader |
Posted: Thu Sep 01, 2011 12:07 pm |
|
|
Hi Everyone -
I have been fighting the good fight in regards to the bootloader on 16F1947. In general, I am able to get it to work for very small applications.
Using the 4.124 CCS Compiler, MPLAB 8.73 as the host for the compiler.
I seem to be stomping on memory in the bootloader as I increase the size of the application program that the bootloader is loading.
I have mapped out my allocations as follows:
0000-0002 - loader - Initial Jump (goto 030) with MOVLP set to 00
0004-0008 - loader - #int_global
0009-001E - loader - Location for delay_ms command
0030-0069 - loader - Bootloader Main
0080-0081 - loader - Load_Program (which calls the real load program)
0094-0099 - loader - #use rs232 declaration for UART
009A-00CE -loader - AtoI function
00E1-026A -loader - Real load program part I
02B6-0315 - loader - Real load program part II
0400-0401 - loader - Application loop (never ending call to itself)
0400-0402 - Application - initial jump w/MOVLP set to 08 & goto set to 000
05A0-05D2 -Application - AtoI function (used in the application)
055E-06D6 - Application -main
In attempting to find the general location of the stomping, I created a series of "beacons" in the code to see at what point the stomping may be occuring. They are nothing more than putc commands for me to see as the data is being processed. I have systematically placed then in the code, which I will explain momentarily.
I am using RealTerm with a delay of 5ms/char and 300ms/line. The 300ms is to allow the write back to the terminal window after the line of hex code is received. Since I am running half duplex, I added some delay to the putchar commands when switching from RX to TX and back. I can speed things up later when I have this memory thing beat and can remove the beacons.
A basic output of the beacons looks like:
1aIIII1bIIIIIIIIIIIIIIIIIIII2aIIIIIIIIIIIIIIIII2b
1a - Located immediately after the while loop that obtains the line data
I - Indicates that the AtoI function is being implimented
1b - Located after all of the commands to extract memory addr data
2a - Located after the accumulation of checksum values prior to checksum compare
2b - Just after a write to memory is performed
What I wanted to see is if or when any of the beacons failed to "light" when the bootloader was writing to memory.
In this process, I found 2 notes of potential interest:
The last lines of the hex code are as follows:
:020000040001F9
:04000E00E219FF0FE5
:00000001FF
HOWEVER, the second to last line NEVER gets written, even when the loader works. Note the beacons:
:020000040001F9
1aIIII1bIIIIII2aIII3a
:04000E00E219FF0FE5
1aIIII1b
The program sees it and establishes a memory address for it; however, it is never written.
I believe that the following line in the bootloader is preventing it from doing so:
//"else if ((addr < LOADER_ADDR || addr > LOADER_END) && addr < 0x2000){"
:00000001FF
1aIIII1b2c
!!!
The other beacons:
2c - EOF record detected
3a - Line Type 4 declared (and I'm not sure if this has any bearing on PCM)
!!! - Occurs at the very end of the load function prior to the jump back to the main.
After establishing the beacons, I started to grow the application. It did not take that long t break it.
For application program lengths between 400 to 6A7, everything seems fine. Once I added another print statement and brought the range to 6D6, the failures started to occur.
Below is the signature of the beacons for the failure. It stopped dead and does not proceed at this point. I believe this to be the 3rd to last line of the hex file since the prior line matches the signature for a 00 record type of 1aIIII1bIIIIIIIIIIIIIIIIIIII2aIIIIIIIIIIIIIIIII2b:
1aIIII1bIIIIIIII2aIIIII
By the way, this does NOT match the healthy signature:
1aIIII1bIIIIII2aIII3a
One other note. I did try it on Tera Term and got the exact same result.
Anyways, I hope that these are a few clues for you. Any leads would be greatly appreciate. More than happy to post what you need.
I will post the codes momentarily..... |
|
|
RckRllRfg
Joined: 20 Jul 2011 Posts: 60
|
code with beacons |
Posted: Thu Sep 01, 2011 12:17 pm |
|
|
I only made changes as needed to loader.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
#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
#define CR 0x0D
#SEPARATE
unsigned int atoi_b16(char *s);
//#ORG LOADER_ADDR+10, LOADER_END auto=0 default
#ORG LOADER_ADDR+20, LOADER_END auto=0 default
#use rs232(UART2, baud=9600, xmit=PIN_G1, rcv=PIN_G2)
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];
//lights to indicate bootload operation
output_low(PIN_D1);
output_low(PIN_D3);
output_low(PIN_D5);
output_low(PIN_D7);
// must enable transceiver for UART2/source side
output_high(PIN_E5); // OUT-ON enabled
output_high(PIN_E6); // RS-485
while (!done) // Loop until the entire program is downloaded
{
output_low(PIN_E7); // TX Off
output_high(PIN_E4); // RX On
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) );
output_low(PIN_E4); // RX Off
output_high(PIN_E7); // TX On
putchar (XOFF); // Suspend sender
delay_ms(5);
putchar ('1');
delay_ms(5);
putchar ('a');
delay_ms(5);
output_high(PIN_E7); // TX Off
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
output_high(PIN_E7); // TX On
putchar ('1');
delay_ms(5);
putchar ('b');
delay_ms(5);
output_low(PIN_E7); // TX Off
// If the line type is 1, then data is done being sent
if (line_type == 1) {
done = TRUE;
output_high(PIN_E7); // TX On
putchar ('2');
delay_ms(5);
putchar ('c');
delay_ms(5);
output_low(PIN_E7); // TX Off
#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;
output_high(PIN_E7); // TX On
putchar ('2');
delay_ms(5);
putchar ('a');
delay_ms(5);
output_low(PIN_E7); // TX Off
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);
output_high(PIN_E7); // TX On
putchar ('2');
delay_ms(5);
putchar ('b');
delay_ms(5);
output_low(PIN_E7); // TX Off
}
else if (line_type == 4)
{
h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));
output_high(PIN_E7); // TX On
putchar ('3');
delay_ms(5);
putchar ('a');
delay_ms(5);
output_low(PIN_E7); // TX Off
}
}
}
}
|
The changes made:
Putc characters for beacons.
ms_delay added for transceivers
PIN_E7 and PIN_E4 for TX and Rx enablement
PIN_Dx for LEDs
#device name change
My bootloader.h code was given another name to prevent the compiler from using the one in the PICC directory:
Code: |
#define LOADER_END (0x3FF) //extend out the end addr
#define LOADER_SIZE (0x37F) //but keep the size slightly smaller
#ifndef _bootloader
#build(reset=LOADER_END+1, interrupt=LOADER_END+5)
#org 0, LOADER_END {}
#endif
|
My loader main is as follows:
Code: |
#include <ROS16F1947.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=16000000)
#use rs232(UART2, baud=9600, xmit=PIN_G1, rcv=PIN_G2, stream=sourceside)
#define _bootloader
#include <ROSbootloader.h>
#include <ROSloader.c>
#org LOADER_END+1,LOADER_END+20
void application(void) {
while(TRUE);
}
//#org 0x20,0x3F
#org 0x30, 0x7A
void main(void) {
setup_oscillator(OSC_16MHZ);
if(!input(PIN_C5))
{
load_program();
}
delay_ms(1000); // Ensure that there is no cross communication
// since RealTerm is still data dumping
application();
}
#ORG default
#int_global
void isr(void) {
jump_to_isr(LOADER_END+5*(getenv("BITS_PER_INSTRUCTION")/8));
}
|
|
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Thu Sep 01, 2011 1:21 pm |
|
|
The posted code is incomplete and can't be compiled.
I guess, the problem is, that you are leaving voids in the boot loader area, that is filled by the main application. These locations are however excluded from the bootload process. |
|
|
RckRllRfg
Joined: 20 Jul 2011 Posts: 60
|
That's an interestng idea |
Posted: Thu Sep 01, 2011 2:13 pm |
|
|
FvM -
thank you for taking the time to look at the code. It may not be compiling due to the include statements. I have a file names with these prefixes in order to prevent the compiler from looking at the original code in the PICC directory. If the code is incomplete in any other way, please let me know and I will repost.
But, I did forget to add my targeted application code:
Code: |
#include <ROS16F1947.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 <ROSbootloader.h>
int i=0;
char buffer[12];
int16 l_addr1, l_addr2, l_addr3, l_addr4;
int8 atoi1,atoi2, atoi3, atoi4, atoi5, atoi6;
long l_addr5;
int8 offset;
int32 addr;
//Added a make16 command to see if it works
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);
fprintf(sourceside, "\r\nApplication program version 1.00 \r\n");
buffer[0] = '0';
buffer[1] = '1';
buffer[2] = '2';
buffer[3] = '3';
buffer[4] = '4';
buffer[5] = '5';
buffer[6] = '6';
buffer[7] = '7';
buffer[8] = '8';
buffer[9] = '9';
buffer[10] = 'A';
buffer[11] = 'B';
// while(TRUE)
// {
// fprintf(sourceside,"%u ",++i);
atoi1 = atoi_b16(&buffer[0]);
atoi2 = atoi_b16(&buffer[2]);
atoi3 = atoi_b16(&buffer[4]);
atoi4 = atoi_b16(&buffer[6]);
atoi5 = atoi_b16(&buffer[8]);
atoi6 = atoi_b16(&buffer[10]);
// fprintf(sourceside,"atoi1: 0x%4x \r\n", atoi1);
// fprintf(sourceside,"atoi2: 0x%4x \r\n", atoi2);
// fprintf(sourceside,"atoi3: 0x%4x \r\n", atoi3);
// fprintf(sourceside,"atoi4: 0x%4x \r\n", atoi4);
// fprintf(sourceside,"atoi5: 0x%4x \r\n", atoi5);
// fprintf(sourceside,"atoi6: 0x%4x \r\n", atoi6);
offset = 2;
l_addr1 = make16(atoi_b16(&buffer[0]),atoi_b16(&buffer[2+offset]));
l_addr2 = make16(atoi_b16(&buffer[4]),atoi_b16(&buffer[6+offset]));
l_addr3 = make16(atoi_b16(&buffer[8]),atoi_b16(&buffer[10]));
l_addr4 = make16(atoi_b16(&buffer[0]),atoi_b16(&buffer[2+1]));
l_addr5 = make16(atoi_b16(&buffer[4]),atoi_b16(&buffer[6+1]));
fprintf(sourceside,"laddr1 with offset=2: 0x%4lx \r\n", l_addr1);
fprintf(sourceside,"laddr2 with offset=2: 0x%4lx \r\n", l_addr2);
fprintf(sourceside,"laddr3: 0x%4lx \r\n", l_addr3);
fprintf(sourceside,"laddr4 with offset=1: 0x%4lx \r\n", l_addr4);
fprintf(sourceside,"laddr5 with offset=1: 0x%4lx \r\n", l_addr5);
/*
addr = make32(l_addr1,l_addr2);
fprintf(sourceside,"make32 with addr 1 & 2: 0x%8lx \r\n", addr);
addr /= 2; //PIC16 uses word addresses
fprintf(sourceside,"make32 with addr 1 & 2 /2: 0x%8lx \r\n", addr);
*/
}
|
I have some additional thoughts and questionson this, but let me construct an intelligent response. Back soon.... |
|
|
RckRllRfg
Joined: 20 Jul 2011 Posts: 60
|
I don't think it is the application that pulls the trigger |
Posted: Thu Sep 01, 2011 2:25 pm |
|
|
I do not believe that it is the application that causes the stompage since the bootloader.h has a very specific command that prevents this from happening:
Code: |
#org 0, LOADER_END {}
|
As for the bootloader, there is some protection in the code to prevent the load command from being stomped upon:
Code: |
else if ((addr < LOADER_ADDR || addr > LOADER_END) && addr < 0x2000)
|
HOWEVER, it only protects the loader function, not the main() or the AtoI function, that happens before the code.
There is one piece of code that seem to take the brunt of the stomage is the end of the real_load_program, from the declaration of line_type == 4 to the end of the function. |
|
|
RckRllRfg
Joined: 20 Jul 2011 Posts: 60
|
The loader.c with ALL the code. |
Posted: Thu Sep 01, 2011 2:27 pm |
|
|
Sorry about that FvM!
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
#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
#define CR 0x0D
#SEPARATE
unsigned int atoi_b16(char *s);
//#ORG LOADER_ADDR+10, LOADER_END auto=0 default
#ORG LOADER_ADDR+20, LOADER_END auto=0 default
#use rs232(UART2, baud=9600, xmit=PIN_G1, rcv=PIN_G2)
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];
//lights to indicate bootload operation
output_low(PIN_D1);
output_low(PIN_D3);
output_low(PIN_D5);
output_low(PIN_D7);
// must enable transceiver for UART2/source side
output_high(PIN_E5); // OUT-ON enabled
output_high(PIN_E6); // RS-485
while (!done) // Loop until the entire program is downloaded
{
output_low(PIN_E7); // TX Off
output_high(PIN_E4); // RX On
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) );
output_low(PIN_E4); // RX Off
output_high(PIN_E7); // TX On
putchar (XOFF); // Suspend sender
delay_ms(5);
putchar ('1');
delay_ms(5);
putchar ('a');
delay_ms(5);
output_high(PIN_E7); // TX Off
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
output_high(PIN_E7); // TX On
putchar ('1');
delay_ms(5);
putchar ('b');
delay_ms(5);
output_low(PIN_E7); // TX Off
// If the line type is 1, then data is done being sent
if (line_type == 1) {
done = TRUE;
output_high(PIN_E7); // TX On
putchar ('2');
delay_ms(5);
putchar ('c');
delay_ms(5);
output_low(PIN_E7); // TX Off
#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;
output_high(PIN_E7); // TX On
putchar ('2');
delay_ms(5);
putchar ('a');
delay_ms(5);
output_low(PIN_E7); // TX Off
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);
output_high(PIN_E7); // TX On
putchar ('2');
delay_ms(5);
putchar ('b');
delay_ms(5);
output_low(PIN_E7); // TX Off
}
else if (line_type == 4)
{
h_addr = make16(atoi_b16(&buffer[9]), atoi_b16(&buffer[11]));
output_high(PIN_E7); // TX On
putchar ('3');
delay_ms(5);
putchar ('a');
delay_ms(5);
output_low(PIN_E7); // TX Off
}
}
}
}
output_high(PIN_E7); // TX ON
if (do_ACKLOD)
{
putchar (ACKLOD);
}
putchar(XON);
delay_ms(5);
putchar(CR);
delay_ms(5);
//output_low(PIN_E7); // TX OFF
}
output_high(PIN_E7); // TX ON
putchar (ACKLOD);
delay_ms(5);
putchar(XON);
delay_ms(5);
putchar('!');
delay_ms(5);
putchar('!');
delay_ms(5);
putchar('!');
delay_ms(5);
output_low(PIN_E7); // TX OFF
#ifndef _bootloader
reset_cpu();
#endif
}
unsigned int atoi_b16(char *s) { // Convert two hex characters to a int8
unsigned int result = 0;
int i;
output_high(PIN_E7); // TX On
//putchar ('A');
//delay_ms(5);
putchar ('I');
delay_ms(5);
output_low(PIN_E7); // TX Off
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
#ORG LOADER_ADDR, LOADER_ADDR+19
void load_program(void)
{
real_load_program();
}
|
|
|
|
RckRllRfg
Joined: 20 Jul 2011 Posts: 60
|
Bad unit? |
Posted: Thu Sep 01, 2011 2:31 pm |
|
|
Though I have requested a 2nd unit and awaiting its arrival, is there a chance that I am dealing with a bad part? I know that the ICD will perform a checksum and I can verify the checksum (which I always do). Are they bulletproof? |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Thu Sep 01, 2011 4:10 pm |
|
|
Quote: | HOWEVER, it only protects the loader function, not the main() or the AtoI function, that happens before the code. |
Yes, I don't know why. I didn't yet work with the PIC16 bootloader code. In my PIC18 bootloader, the complete bootloader area and the fuses are protected. Apparently, CCS is writing confuse stuff in the low memory range. Simply block this in the bootloader and see what happens. I didn't check however, if the code starting at 0x400 is correct or if something is mssing. |
|
|
RckRllRfg
Joined: 20 Jul 2011 Posts: 60
|
Another twist to this story |
Posted: Mon Sep 05, 2011 12:05 pm |
|
|
FvM -
I have been running different size pieces of code. What I am finding interesting is that the failure seems to occur at the end of the code, in particular, if the code is calling for 14 data words (0Eh) rather than the usual 16(10h) I am wondering if the size of the line is having something to do with it.
For example: The good code that works:
Code: |
:100C30002300910004309200031004302000C20011
:040C4000A724212E96
:020000040001F9
:04000E00E219FF0FE5
:00000001FF
|
Example of the 2 code that do not work:
Code: |
:100D9000C2005730C3003725623023009100043071
:0E0DA0009200031004302000C200E424D62E7E
:020000040001F9
:04000E00E219FF0FE5
:00000001FF
|
Code: |
:1026F00003197C2B22007E2B2200B603852B2000A1
:0E270000F501FB01FC012200852B20000800E2
:020000040001F9
:04000E00E219FF0FE5
:00000001FF
|
|
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Mon Sep 05, 2011 2:40 pm |
|
|
You should change
Code: | else if ((addr < LOADER_ADDR || addr > LOADER_END) && addr < 0x2000) |
to
Code: | else if (addr > LOADER_END && addr < 0x4000) |
as a first step. |
|
|
RckRllRfg
Joined: 20 Jul 2011 Posts: 60
|
An interesting find |
Posted: Tue Sep 06, 2011 12:49 am |
|
|
FvM -
I will definitely give your recommendation a try. In the meantime, I have been experimenting by adding NOPs into the code. Each time I added a NOP into the application code to see if the bootloader responded correctly. No changes to the bootloader were made. Note that the lower data counts for a given line were fine. The higher data counts for a line caused the bootloader to hang.
I am curious to know if this correlates to the code change you recommended. I was under the impression that the 2000 was simply an upper address limit. If there is more to it, please explain.
Code: |
#include <ROS16F1947.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 <ROSbootloader.h>
int i=0;
char buffer[12];
int16 l_addr1, l_addr2, l_addr3, l_addr4;
int8 atoi1,atoi2, atoi3, atoi4, atoi5, atoi6;
long l_addr5;
int8 offset;
int32 addr;
//Added a make16 command to see if it works
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);
fprintf(sourceside, "\r\nApplication program version 1.00 \r\n");
buffer[0] = '0';
buffer[1] = '1';
buffer[2] = '2';
buffer[3] = '3';
buffer[4] = '4';
buffer[5] = '5';
buffer[6] = '6';
buffer[7] = '7';
buffer[8] = '8';
buffer[9] = '9';
buffer[10] = 'A';
buffer[11] = 'B';
// while(TRUE)
// {
// fprintf(sourceside,"%u ",++i);
atoi1 = atoi_b16(&buffer[0]);
atoi2 = atoi_b16(&buffer[2]);
atoi3 = atoi_b16(&buffer[4]);
atoi4 = atoi_b16(&buffer[6]);
atoi5 = atoi_b16(&buffer[8]);
atoi6 = atoi_b16(&buffer[10]);
// fprintf(sourceside,"atoi1: 0x%4x \r\n", atoi1);
// fprintf(sourceside,"atoi2: 0x%4x \r\n", atoi2);
// fprintf(sourceside,"atoi3: 0x%4x \r\n", atoi3);
// fprintf(sourceside,"atoi4: 0x%4x \r\n", atoi4);
// fprintf(sourceside,"atoi5: 0x%4x \r\n", atoi5);
// fprintf(sourceside,"atoi6: 0x%4x \r\n", atoi6);
offset = 2;
l_addr1 = make16(atoi_b16(&buffer[0]),atoi_b16(&buffer[2+offset]));
l_addr2 = make16(atoi_b16(&buffer[4]),atoi_b16(&buffer[6+offset]));
l_addr3 = make16(atoi_b16(&buffer[8]),atoi_b16(&buffer[10]));
l_addr4 = make16(atoi_b16(&buffer[0]),atoi_b16(&buffer[2+1]));
l_addr5 = make16(atoi_b16(&buffer[4]),atoi_b16(&buffer[6+1]));
fprintf(sourceside,"laddr1 with offset=2: 0x%4lx \r\n", l_addr1);
fprintf(sourceside,"laddr2 with offset=2: 0x%4lx \r\n", l_addr2);
fprintf(sourceside,"laddr3: 0x%4lx \r\n", l_addr3);
fprintf(sourceside,"laddr4 with offset=1: 0x%4lx \r\n", l_addr4);
fprintf(sourceside,"laddr5 with offset=1: 0x%4lx \r\n", l_addr5);
#asm ASIS
// Up to this point, the end hex is 0E, which did not work
nop; //00 - Worked :100DA0009200031004302000C200E4240000D72E7B
nop; //02 - Worked :020DB000D82E3B
nop; //04 - Worked :040DB0000000D92E38
nop; //06 - Worked :060DB00000000000DA2E35
nop; //08 - No Go :080DB000000000000000DB2E32
nop; //0A - No Go :0A0DB0000000000000000000DC2E2F
nop; //0C - No Go :0C0DB00000000000000000000000DD2E2C
nop; //0E - No Go :0E0DB000000000000000000000000000DE2E29
nop; //10 - Worked :100DB0000000000000000000000000000000DF2E26
nop; //12 - Worked :020DC000E02E23
nop; //14 - Worked :040DC0000000E12E20
nop; //16 - Worked :060DC00000000000E22E1D
nop; //18 - No Go :080DC000000000000000E32E1A
nop; //1a - No Go :0A0DC0000000000000000000E42E17
nop; //1c - No Go :0C0DC00000000000000000000000E52E14
nop; //1e - No Go :0E0DC000000000000000000000000000E62E11
nop; //20 - Worked :100DC0000000000000000000000000000000E72E0E
*/
#endasm
// }
}
|
|
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Sep 06, 2011 1:53 am |
|
|
The highest code address code 16F1947 is 0x3fff instead of 0x1fff. The respective change to the bootloader matters only for larger applications. The problem, as far as I saw, was that the compiler tried to write a few bytes in the 0..0x1f memory range, corrupting the bootloader image, although no regular code seems to be placed there. I didn't yet understand what it's intended for, so idea is to block it and check if something's missing for the application.
P.S.: The last lines of the hex files are intended to write the fuses. They are apparently misunderstood by the bootloader. But fuse reprogramming should be blocked by the bootloader anyway.
P.P.S.: I reviewed the bootloader code and think, the last lines should be decoded correctly and not allowed to be written to the device. |
|
|
|
|
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
|