|
|
View previous topic :: View next topic |
Author |
Message |
gilavar
Joined: 03 Mar 2009 Posts: 24
|
Help with bootloader, PIC24FJ32 |
Posted: Thu Aug 20, 2009 12:41 pm |
|
|
It is my first project with “C” and CCS. Application is very complex system and after 4 month everything is working just fine. Before releasing this product I have to implement the bootloader, so updates can be performed globally on all the units. I am using PIC24FJ32GA004 and put modified bootloader functions in the memory area 0x5000 and up. Host is sending many different commands were unit is performing predefined functions and idea was to set one of the commands (“#BTL” for example) to jump to the bootloader area, erase everything below 0x5000 and then write line by line the HEX code. I tried to use only local functions located in bootload area, but for some reason controller getting stuck when erasing block 0x1800. I found that in different compilation it gets stuck erasing different memory area. Looking in disassembly windows I found that in erase loop code calling for address in 0~0x400 range. Here is the code I modified for bootloader, (I know it is long, sorry).
Code: |
int1 bl_err; //BootLoad error
int1 bl_to; //BootLoader UART time out
#org 0x5000,0x5038
char bl_getc() //Receive USART character with 0.5 Sec. time-out Size 0x36
{
long timeout;
bl_to=0;
timeout=0;
while(!kbhit()&&(++timeout<50000)) // 1/2 second
delay_us(10);
if(kbhit())
return(fgetc(PC));
else {
bl_to=1;
return(0);
}
}
#org 0x5040,0x508F
char bl_gets(*s, unsigned int8 max_char) //Receive string from UART with time-out. Size 0x003A
{
unsigned int8 icnt;
char d_byte;
if(max_char == 0)
max_char = 127; //Limit of FTDA Rx buffer
for(icnt = 0;icnt < max_char;++icnt)
{
d_byte = bl_getc();
if(bl_to != 0)
{
host_step = 0;
return;
}
if(d_byte == 0x0D)
return;
else
s[icnt] = d_byte;
}
}
#org 0x5090,0x50EF
unsigned int8 atoi_b16(char *s) //Size 0x0044
{ // Convert two hex characters to a int8
unsigned int8 result = 0;
unsigned int8 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 0x50F0,0x512F
signed int8 bl_strcmp(char *s1, char *s2) //Size 0x0032
{
for (; *s1 == *s2; s1++, s2++)
if (*s1 == '\0')
return(0);
return((*s1 < *s2) ? -1: 1);
}
#org default
#org 0x5130,0x5500
void process_bl() //Size 0x02D4
{
char bl_buffer[64];
unsigned int8 bl_data[32];
unsigned int16 l_addr,h_addr=0;
unsigned int8 bl_counter=0;
unsigned int32 bl_address=0;
unsigned int16 buffidx;
unsigned int8 bl_checksum, line_type, bli,bl_dataidx;
char bl_cmd[5] = "0000";
char bl_key[5] = "1234";
disable_interrupts(int_timer3);
disable_interrupts(int_timer5);
disable_interrupts(int_rda);
puts("OK");
bl_loop1:
bl_gets(bl_cmd,0); //Get bootloader key
if((bl_to != 0) || (bl_strcmp(bl_cmd,bl_key) != 0)) //Loop until key is in
{
goto bl_loop1;
puts("ERR");
}
//bl_address=getenv("FLASH_ERASE_SIZE");
//Erase flash 0x0000~0x4FFF
for(bl_address=0x1000;bl_address < 0x3800;bl_address += 0x400) //getenv("FLASH_ERASE_SIZE"))
{
//bl_address = 0x0000;
erase_program_memory(bl_address);
}
puts("OK");
bl_loop2:
buffidx = bl_gets(bl_buffer,64); //Get first line of the bootfile
if (bl_buffer[0] != ':')
{
puts("ERR");
goto bl_loop2; //First key of the line should be ":"
}
puts("OK"); ///////TEMP
bl_counter = atoi_b16 (&bl_buffer[1]); // Get the number of bytes from the buffer
l_addr = make16(atoi_b16(&bl_buffer[3]),atoi_b16(&bl_buffer[5])); // Get the lower 16 bits of address
line_type = atoi_b16(&bl_buffer[7]); //Get type of data
bl_address = make32(h_addr,l_addr) / 2;
if (line_type == 1)
goto bl_complete;
else if ((bl_address < 0x4FFF))
{
bl_checksum = 0; // Sum the bytes to find the check sum value
for (bli=1; bli<((bl_counter*2) + 8); bli+=2)
bl_checksum += atoi_b16 (&bl_buffer[bli]);
bl_checksum = 0xFF - bl_checksum + 1;
if (bl_checksum != atoi_b16 (&bl_buffer[(bl_counter * 2) +9]))
{
puts("ERR");
goto bl_loop2;
}
else
{
if (line_type == 0)
{
// Loops through all of the data bytes and stores it in bl_data
// The last 2 bytes are the check sum, hence buffidx-3
for (bli = 9,bl_dataidx=0; bli < ((bl_counter*2) + 8); bli += 2)
bl_data[bl_dataidx++]=atoi_b16(&bl_buffer[bli]);
write_program_memory(bl_address, bl_data, bl_counter);
puts("OK");
}
else if (line_type == 4)
h_addr = make16(atoi_b16(&bl_buffer[9]), atoi_b16(&bl_buffer[11]));
puts("OK");
}
}
goto bl_loop2;
bl_complete:
puts("OK");
reset_cpu();
}
|
Here is disassembly snapshot in erase loop showing call to 0x000346:
Code: |
102: {
103: //bl_address = 0x0000;
104: erase_program_memory(bl_address);
51E8 807F30 mov.w 0x0fe6,0x0000
51EA 807F41 mov.w 0x0fe8,0x0002
51EC 880191 mov.w 0x0002,0x0032
51EE BB0801 tblwtl.w 0x0002,[0x0000]
51F0 240421 mov.w #0x4042,0x0002
51F2 020346 call 0x000346
105: }
|
Please help, what am I doing wrong? |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Thu Aug 20, 2009 3:58 pm |
|
|
I don't understand your bootloader layout. If the loader is located starting from 0x5000, how can it call flash write code at 0x346 (the main application area). |
|
|
gilavar
Joined: 03 Mar 2009 Posts: 24
|
|
Posted: Thu Aug 20, 2009 4:55 pm |
|
|
FvM wrote: | I don't understand your bootloader layout. If the loader is located starting from 0x5000, how can it call flash write code at 0x346 (the main application area). |
Thank you for reply. I added "default" and "#ORG default" to keep compilers library within the functions and it appears I can erase all the memory blocks below 0x5000.
Now I have to find out how to write there. Is that normal procedure to write to the memory blocks below? |
|
|
|
|
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
|