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

PIC24FV Application RESET & GOTO Vector woes

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



Joined: 19 Jul 2013
Posts: 10

View user's profile Send private message

PIC24FV Application RESET & GOTO Vector woes
PostPosted: Fri May 08, 2015 12:39 pm     Reply with quote

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: 1344

View user's profile Send private message

PostPosted: Fri May 08, 2015 1:09 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Fri May 08, 2015 2:25 pm     Reply with quote

jeremiah, that seemed to work! Thank you for the insight Smile
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