|
|
View previous topic :: View next topic |
Author |
Message |
warren.woolseyiii
Joined: 19 Jul 2013 Posts: 10
|
PIC24FV Application RESET & GOTO Vector woes |
Posted: Fri May 08, 2015 12:39 pm |
|
|
I am using the PCWHD compiler for an application targeting the PIC24FV32KA304. My compiler and IDE version are Version 4.134.
I am writing a chip specific boot loader, to support firmware upgrades for the application code in the field. My boot loader utilizes the default interrupt vector table, the default GOTO vector, and the default RESET vector. The important memory setting code for the boot loader is pasted below:
Code: | /***
** bootloader memory ranges from:
** 0x1000 to 0x1FE0
** 0x1000 / 2 = 0x0800
** 0x1FE0 / 2 = 0x0FF0
***/
#include <24FV32KA304.h>
#device ICD=3
#device ADC=10
#org 0x0800, 0x0FF0 default
#fuses HS, NOWDT, PR, SOSC_DIGITAL
#use delay (clock=32000000)
#use rs232 (baud=115200, UART1, BITS=8, STOP=1) |
Any application that utilizes this boot loader must be set up to use the Alternate Interrupt Vector Table (AIVT), and must have it's RESET vector relocated to address 0x0200. The boot loader code will automatically jump to address 0x0200 upon successful loading of the application hex file. I have pasted the relevant code below from the boot loader:
Code: | #define RESET_VECTOR 0x0200
loadSuccess = BootLoader();
disable_interrupts(INT_RDA);
disable_interrupts(INT_UART1E);
if (loadSuccess > 0)
{
msgBuff[0] = BOOTLOAD_SUCCESS;
SendMsg(msgBuff, 1);
delay_ms(100);
goto_address(RESET_VECTOR);
}
else
{
reset_cpu();
}
|
When I create a target application, I am able to use the AIVT, ignore the boot loader memory space, and relocate the application RESET vector to address 0x0200. In a test project such as a hello world example containing interrupt service routines, a modified stack, and nested interrupts (which my real target application uses), I am able to correctly set up and allocate memory so that the application will work with the boot loader. I have posted relevant code from the test application hello world project below:
Code: | #case
#include <24FV32KA304.h>
#device ICD=3
#device ADC=10
#device NESTED_INTERRUPTS
#org 0x0800, 0x1FE0 {} // space for the bootloader -- may have to divide these numbers by 2
#build (STACK=512)
#build (ALT_INTERRUPT)
#build (RESET=0x0200)
#fuses NONE //HS, NOWDT, PR, SOSC_DIGITAL
#use delay (clock=32000000)
#use rs232 (baud=115200, UART1, BITS=8, STOP=1)
#include "mySource.c"
unsigned int8 myVar1 = 0;
unsigned int8 myVar2 = 15;
unsigned int8 myFunction(unsigned int8 arg)
{
arg++;
return arg;
}
void main()
{
setup_timer1(TMR_INTERNAL | TMR_DIV_BY_256);
setup_timer3(TMR_INTERNAL | TMR_DIV_BY_64);
enable_interrupts(INT_EXT0);
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER3);
enable_interrupts(INT_RDA);
delay_ms(1000);
putc(0xFF);
putc(0x5A);
putc(0x02);
putc(0x55);
putc(0x06);
printf("Hello");
putc(0xFF);
putc(0xFF);
while(1) {
delay_ms(1000);
putc(0xFF);
putc(0x5A);
putc(0x02);
putc(0x55);
putc(0x01);
putc(0x72);
putc(0xFF);
putc(0xFF);
mySecondFunc();
myThirdFunc(&myVar1);
}
}
#INT_RDA
void myISR(void)
{
myVar2 = getc();
//putc(myVar2);
enable_interrupts(INT_TBE);
clear_interrupt(INT_RDA);
}
#INT_EXT0
void myOtherISR(void)
{
myVar1 += 69;
putc(0xFF);
putc(0x5A);
putc(0x02);
putc(0x55);
putc(0x01);
putc(myVar1);
putc(0xFF);
putc(0xFF);
clear_interrupt(INT_EXT0);
}
#INT_TBE
void myTbeIsr(void)
{
putc(myVar2);
clear_interrupt(INT_TBE);
disable_interrupts(INT_TBE);
}
#INT_TIMER1 Level=1
void myTimer1Isr(void)
{
putc(0xFF);
putc(0x5A);
putc(0x02);
putc(0x55);
putc(0x01);
putc(0x31);
putc(0xFF);
putc(0xFF);
clear_interrupt(INT_TIMER1);
}
// 10 Hz Timer
#INT_TIMER3 Level=1
void myTimer3Isr(void)
{
putc(0xFF);
putc(0x5A);
putc(0x02);
putc(0x55);
putc(0x01);
putc(0x33);
putc(0xFF);
putc(0xFF);
clear_interrupt(INT_TIMER3);
} |
The hex file that is generated by compiling this project will relocate the reset vector to the proper space in memory, and will not overwrite the boot loader's GOTO vector located at address 0x0000. I have posted the relevant records from the file main.hex below:
Code: | :04022800840200004C <--- line 0 of the hex file
:04023400240300009F
:04024800920300001D
:0802540058020000FA0200004C
:1004000056050400000000003220EF000321200008 |
My issue is that when I use the same memory allocation setup for my target application (which is significantly larger than the hello world demo) the compiler generates an application GOTO vector located at address 0x0000, even though I have used the #build (RESET= 0x0200) directive. Upon loading my application file through the boot loader, the boot loader will crash because it overwrites its own GOTO vector. I have successfully come up with a work around to remedy this problem by telling the application to leave the memory address 0x0200 - 0x020E unpopulated and have the bootloader manually insert the application GOTO vector at that address. Below is the relevant code from both the application project and the bootloader:
Code: | bootloader.c code (with work around)
else if (hexAddr == 0x0000)
{
hexAddr = 0x0200;
// get the hex data
for (dataNdx = 0, hexNdx = HEX_DATA_START; dataNdx < hexLen; hexNdx += 2)
{
data[dataNdx++] = getHexbyte(&hexBuffer[hexNdx]);
}
write_program_memory(hexAddr, data, hexLen);
delay_us(10);
} |
Code: | application.c code (with work around)
#case
#include <24FV32KA304.h>
#device ICD=3
#device ADC=10
#device NESTED_INTERRUPTS
#org 0x0800, 0x1FE0 {} // space for the bootloader
#org 0x0200, 0x020E {} // space reserved for the new GOTO / RESET vector. This will be manually inserted by the bootloader
#build (ALT_INTERRUPT)
#build (STACK=512)
#fuses NONE /* fuses are set in bootloader - HS, NOWDT, PR, SOSC_DIGITAL */
#use delay (clock=32000000)
#use rs232 (baud=115200, UART1, BITS=8, STOP=1)
#include "HardwareAbstraction.c"
#include "PID.c"
#include "Buffer.c"
#include "RS485Comms.c"
#include "StateMachine.c"
#include "Eeprom_HAL.c"
#include "VersionInfo.h" |
Code: | application.hex code (with workaround)
:0800000070450400000000003F <---- application GOTO vector which will attempt to overwrite bootloader space
:040228005230000050
:0402340020020000A4
:04024800440200006C
:080254003A310000D031000036
:100420000421EF00449022001408880004012000F9 |
Code: | application.c code (without workaround)
#case
#include <24FV32KA304.h>
#device ICD=3
#device ADC=10
#device NESTED_INTERRUPTS
#org 0x0800, 0x1FE0 {} // space for the bootloader
#build (ALT_INTERRUPT)
#build (STACK=512)
#build (RESET=0x0200)
#fuses NONE /* fuses are set in bootloader - HS, NOWDT, PR, SOSC_DIGITAL */
#use delay (clock=32000000)
#use rs232 (baud=115200, UART1, BITS=8, STOP=1)
#include "HardwareAbstraction.c"
#include "PID.c"
#include "Buffer.c"
#include "RS485Comms.c"
#include "StateMachine.c"
#include "Eeprom_HAL.c"
#include "VersionInfo.h" |
Code: | application.hex code (without workaround)
:08000000E068EF0000000600BB <--- application GOTO vector which will attempt to overwrite bootloader space
:040228004230000060
:0402340014020000B0
:040248003802000078
:080254002A310000C031000056
:1004000060450400000000000421EF004490220039 |
I am uncertain why the compiler will insert the application GOTO vector for my application project at address 0x0000 when I am using the #build directive to change the RESET vector. I am especially puzzled why this works when I create a hello world example, like the one I posted above, and why this does not work when I use the same memory setup parameters in my application.
Any insight as to why this is occurring would be greatly appreciated.
Thank you for your time! |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1354
|
|
Posted: Fri May 08, 2015 1:09 pm |
|
|
Whenever you use the #build to move the reset vector (or the IVT), you need to accompany it with a #org start,end{} to block off that memory. You didn't have a
#org 0x0000,0x0003{}
so the compiler assumes it is free to use space.
the example you provided wouldn't compile for me directly so I deleted out the the #include and the function calls that caused errors. I also reorganized things into a more compiler friendly order:
Code: |
#case
#include <24FV32KA304.h>
#fuses NONE //HS, NOWDT, PR, SOSC_DIGITAL
#device ICD=3
#device ADC=10
#device NESTED_INTERRUPTS
#build (RESET=0x0200,ALT_INTERRUPT,STACK=512)
#org 0x0000,0x0003{}
#org 0x0800, 0x1FE0 {} // space for the bootloader -- may have to divide these numbers by 2
#use delay (clock=32000000)
#use rs232 (baud=115200, UART1, BITS=8, STOP=1)
unsigned int8 myVar1 = 0;
unsigned int8 myVar2 = 15;
unsigned int8 myFunction(unsigned int8 arg)
{
arg++;
return arg;
}
void main()
{
setup_timer1(TMR_INTERNAL | TMR_DIV_BY_256);
setup_timer3(TMR_INTERNAL | TMR_DIV_BY_64);
enable_interrupts(INT_EXT0);
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER3);
enable_interrupts(INT_RDA);
delay_ms(1000);
putc(0xFF);
putc(0x5A);
putc(0x02);
putc(0x55);
putc(0x06);
printf("Hello");
putc(0xFF);
putc(0xFF);
while(1) {
delay_ms(1000);
putc(0xFF);
putc(0x5A);
putc(0x02);
putc(0x55);
putc(0x01);
putc(0x72);
putc(0xFF);
putc(0xFF);
}
}
#INT_RDA
void myISR(void)
{
myVar2 = getc();
//putc(myVar2);
enable_interrupts(INT_TBE);
clear_interrupt(INT_RDA);
}
#INT_EXT0
void myOtherISR(void)
{
myVar1 += 69;
putc(0xFF);
putc(0x5A);
putc(0x02);
putc(0x55);
putc(0x01);
putc(myVar1);
putc(0xFF);
putc(0xFF);
clear_interrupt(INT_EXT0);
}
#INT_TBE
void myTbeIsr(void)
{
putc(myVar2);
clear_interrupt(INT_TBE);
disable_interrupts(INT_TBE);
}
#INT_TIMER1 Level=1
void myTimer1Isr(void)
{
putc(0xFF);
putc(0x5A);
putc(0x02);
putc(0x55);
putc(0x01);
putc(0x31);
putc(0xFF);
putc(0xFF);
clear_interrupt(INT_TIMER1);
}
// 10 Hz Timer
#INT_TIMER3 Level=1
void myTimer3Isr(void)
{
putc(0xFF);
putc(0x5A);
putc(0x02);
putc(0x55);
putc(0x01);
putc(0x33);
putc(0xFF);
putc(0xFF);
clear_interrupt(INT_TIMER3);
}
|
Generates the following hex
Code: |
:04022800460200008A
:04023400EE020000D6
:04024800600300004F
:0802540016020000C0020000C8
:10040000E2030400000000003220EF00032120007E
:10041000008041001040BA000160EF0000000600BB
:10042000486500006C6C00006F0000004200F8009E
:100430003600F8003200F800801F7800200020000D
:100440000C000900B01F78002202AE00FEFF37004A
:10045000301180005BE8B7009580A8000300090018
:100460002682BF008560A9008560A900A001200048
:100470000C0009004F1078004F0078003200F9009E
:100480003600F9004200F900004006004200F80082
:100490003600F8003200F800801F780020002000AD
:1004A0000C000900B01F780054042000D3428000E3
:1004B00004C041005AE8B70000C0EB002302AE00C0
:1004C000FEFF370024E2B7002562EF00A0C5B300AD
:1004D0002302AE00FEFF370024E2B7002562EF00E2
:1004E00020C0B3002302AE00FEFF370024E2B700B5
:1004F0002562EF0050C5B3002302AE00FEFF3700B7
:1005000024E2B7002562EF0010C0B3002302AE0062
:10051000FEFF370024E2B7002562EF005AC8BF0093
:100520002302AE00FEFF370024E2B7002562EF0091
:1005300000C0EB002302AE00FEFF370024E2B7004C
:100540002562EF0000C0EB002302AE00FEFF370083
:1005500024E2B7002562EF008400A9008400A9000E
:10056000A00120000C0009004F1078004F00780017
:100570003200F9003600F9004200F90000400600A0
:100580008580A9004200F8003600F8003200F8002B
:10059000801F7800200020000C000900B01F7800A8
:1005A0005BC8BF002302AE00FEFF370024E2B700A5
:1005B0002562EF008580A9009580A900A001200098
:1005C0000C0009004F1078004F0078003200F9004D
:1005D0003600F9004200F900004006004200F80031
:1005E0003600F8003200F800801F7800200020005C
:1005F0000C000900B01F780000C0EB002302AE0021
:10060000FEFF370024E2B7002562EF00A0C5B3006B
:100610002302AE00FEFF370024E2B7002562EF00A0
:1006200020C0B3002302AE00FEFF370024E2B70073
:100630002562EF0050C5B3002302AE00FEFF370075
:1006400024E2B7002562EF0010C0B3002302AE0021
:10065000FEFF370024E2B7002562EF0010C3B300AD
:100660002302AE00FEFF370024E2B7002562EF0050
:1006700000C0EB002302AE00FEFF370024E2B7000B
:100680002562EF0000C0EB002302AE00FEFF370042
:1006900024E2B7002562EF008460A9008460A9000D
:1006A000A00120000C0009004F1078004F007800D6
:1006B0003200F9003600F9004200F900004006005F
:1006C0004200F8003600F8003200F800801F780081
:1006D000200020000C000900B01F780000C0EB00D3
:1006E0002302AE00FEFF370024E2B7002562EF00D0
:1006F000A0C5B3002302AE00FEFF370024E2B7001E
:100700002562EF0020C0B3002302AE00FEFF3700D9
:1007100024E2B7002562EF0050C5B3002302AE000B
:10072000FEFF370024E2B7002562EF0010C0B300DF
:100730002302AE00FEFF370024E2B7002562EF007F
:1007400030C3B3002302AE00FEFF370024E2B7003F
:100750002562EF0000C0EB002302AE00FEFF370071
:1007600024E2B7002562EF0000C0EB002302AE00D8
:10077000FEFF370024E2B7002562EF008500A900E4
:100780008500A900A00120000C0009004F1078008E
:100790004F0078003200F9003600F9004200F900FD
:1007A000004006000000E0004220AF0004003700D7
:1007B0007B3E0900000000000000E900FCFF3A0059
:1007C000000006000FE02000F0FF200020A0B7008E
:1007D000000000004044210020058800104424004F
:1007E0004005880083E0A80081E0A90004002800FB
:1007F0000411880004402000141188002062A80021
:1008000024022000441188005A68EF00F0C0B300B1
:100810005BE8B700E024EF00E224EF00E424EF00FF
:100820000421EF0002A1EF0004032800240888003F
:100830001221EF000EA1EF000402280094088800A6
:100840009400A8009460A8009500A8009560A800F6
:10085000803E2000D20302000000000000C0EB0038
:100860002302AE00FEFF370024E2B7002562EF004E
:10087000A0C5B3002302AE00FEFF370024E2B7009C
:100880002562EF0020C0B3002302AE00FEFF370058
:1008900024E2B7002562EF0050C5B3002302AE008A
:1008A000FEFF370024E2B7002562EF0060C0B3000E
:1008B0002302AE00FEFF370024E2B7002562EF00FE
:1008C00001002000010078000160EF000402020036
:1008D000000000008100E8002302AE00FEFF3700A8
:1008E00024A2B700400020000008E600F5FF370012
:1008F00000C0EB002302AE00FEFF370024E2B70089
:100900002562EF0000C0EB002302AE00FEFF3700BF
:1009100024E2B7002562EF00803E2000D2030200EF
:100920000000000000C0EB002302AE00FEFF370015
:1009300024E2B7002562EF00A0C5B3002302AE0099
:10094000FEFF370024E2B7002562EF0020C0B300AD
:100950002302AE00FEFF370024E2B7002562EF005D
:1009600050C5B3002302AE00FEFF370024E2B700FB
:100970002562EF0010C0B3002302AE00FEFF370077
:1009800024E2B7002562EF0020C7B3002302AE00C7
:10099000FEFF370024E2B7002562EF0000C0EB0045
:1009A0002302AE00FEFF370024E2B7002562EF000D
:1009B00000C0EB002302AE00FEFF370024E2B700C8
:0C09C0002562EF00D4FF3700FFFF370076
:00000001FF
;PIC24FV32KA304
;CRC=6A27 CREATED="08-May-15 15:03"
|
So all above 0x0100 as desired.
This is with the 5.044 version of PCWHD |
|
|
warren.woolseyiii
Joined: 19 Jul 2013 Posts: 10
|
|
Posted: Fri May 08, 2015 2:25 pm |
|
|
jeremiah, that seemed to work! Thank you for the insight |
|
|
|
|
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
|