Author Topic: PIC18 Reset Vector in disassembly listing?  (Read 1751 times)

0 Members and 1 Guest are viewing this topic.

Offline IDEngineerTopic starter

  • Super Contributor
  • ***
  • Posts: 1956
  • Country: us
PIC18 Reset Vector in disassembly listing?
« on: January 16, 2025, 06:21:42 pm »
I'm creating a bootloader, which obviously requires moving the "application" code (as Microchip likes to call it) above the protected bootloader block in low memory.

As part of this research I'm looking for the actual startup address for the code. It's not the base address of main() because there's initialization code which must execute prior to that. Therefore the reset vector at program address 0x0000 must contain an unconditional branch, e.g. GOTO, to this init code which then itself calls main().

I note that the ISR function itself (not a GOTO) is linked to absolute address 0x0008, so the CPU is expecting exectable code and not just addresses at these locations.

Where is the Reset GOTO instruction in the disassembly listing? I've looked everywhere but can't find it. Somehow, somewhere, the code has to program that into the flash but I can't find it.

Thanks!
« Last Edit: January 16, 2025, 07:48:13 pm by IDEngineer »
 

Offline ggchab

  • Frequent Contributor
  • **
  • Posts: 283
  • Country: be
Re: PIC18 Reset Vector in disassembly listing?
« Reply #1 on: January 16, 2025, 06:41:27 pm »
I wrote a bootloader for a PIC18. Instead of moving the application, I installed the bootloader at the end of the memory.
A program starts at address 0x0000 and that generally contains a "GOTO". When a bootloader is installed, the GOTO jumps to the bootloader.
When the bootloader loads a program into memory, it has to read the "GOTO" address of the program, and save it somewhere.

 

Online fchk

  • Frequent Contributor
  • **
  • Posts: 301
  • Country: de
Re: PIC18 Reset Vector in disassembly listing?
« Reply #2 on: January 16, 2025, 06:53:27 pm »

Where is the reset vector/BRA instruction in the disassembly listing? I've looked everywhere but can't find it.


The reset vector is part of the C runtime that is always linked to your application code.
Look at ./xc8/v2.50/pic/sources/c99/pic18/powerup.S (for XC8 Version 2.50 in C99 mode)

Code: [Select]
global powerup,start
psect powerup,class=CODE,delta=1,reloc=2
powerup:
nop ; Suggested Microchip errata workaround
goto start
end
« Last Edit: January 16, 2025, 06:55:11 pm by fchk »
 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 6470
  • Country: es
Re: PIC18 Reset Vector in disassembly listing?
« Reply #3 on: January 16, 2025, 07:00:49 pm »
Using MPLABX? You can see what's going on here:
Window -> Target Memory View -> Program Memory
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline IDEngineerTopic starter

  • Super Contributor
  • ***
  • Posts: 1956
  • Country: us
Re: PIC18 Reset Vector in disassembly listing?
« Reply #4 on: January 16, 2025, 07:47:16 pm »
The reset vector is part of the C runtime that is always linked to your application code.
Code: [Select]
global powerup,start
psect powerup,class=CODE,delta=1,reloc=2
powerup:
nop ; Suggested Microchip errata workaround
goto start
end
Right, but I cannot find a reference to the label "start" in the listing. The bootloader will replace the vectors at the bottom of program memory so it must know how to reach the "original" code. Granted I can just hardcode an Assembly GOTO to the linker offset for the application (in the PIC18 typically 0x400 for 1K or 0x800 for 2K of reserved bootloader space) but I'd honestly like to see how the linker is tying it all together. It's nice that powerup.s can just refer to the label "start" but eventually all those labels have to be resolved.
 

Offline IDEngineerTopic starter

  • Super Contributor
  • ***
  • Posts: 1956
  • Country: us
Re: PIC18 Reset Vector in disassembly listing?
« Reply #5 on: January 16, 2025, 10:07:56 pm »
The initialization code starts at address 0x022B2, and the symbol table shows:

Code: [Select]
start_initialization 22B2
At the end of the initialization portion of the listing, this line jumps to main():

Code: [Select]
002314  EF85  F007          goto _main ;jump to C main() function
...and machine code 0xEF85 0xF007 translates to GOTO 0x00785.

All well and good, except:

* The listing shows nothing, anywhere, that puts a GOTO 0x022B2 at the Reset address of 0x0000 so it's not clear how the init code ever gets invoked;
* There is no listing line with address 0x00785, so it's not clear what the PC is pointing to when the init code jumps there; and
* The listing says main() starts at address 0x00F0A, not 0x00785, so the init code is definitely not jumping to main().

The ISR starts right at address 0x0008, so there's no redirection required. (The low priority vector at 0x0018 gets overwritten with code but that doesn't matter since this application doesn't use the PIC18's interrupt priority.)

Very baffling....
« Last Edit: January 16, 2025, 10:27:03 pm by IDEngineer »
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4383
  • Country: us
Re: PIC18 Reset Vector in disassembly listing?
« Reply #6 on: January 16, 2025, 11:13:32 pm »

Quote
The listing says main() starts at address 0x00F0A, not 0x00785

Looks like the standard “byte addressing vs word addressing” issue.
On a Harvard-architecture pic18 (or an AVR), branch destinations are “word” addresses or offsets.
Many tools like to deal in bytes.
« Last Edit: January 16, 2025, 11:16:00 pm by westfw »
 
The following users thanked this post: IDEngineer

Offline IDEngineerTopic starter

  • Super Contributor
  • ***
  • Posts: 1956
  • Country: us
Re: PIC18 Reset Vector in disassembly listing?
« Reply #7 on: January 16, 2025, 11:57:01 pm »
That's an excellent observation. 0x785 is indeed 0xF0A when shifted left one bit.

Digging deeper, I see that the GOTO instruction replaces bits 20:1 (not the 0th bit!) of the PC. And according to 6.1.2, "the LSb of PCL is fixed to a value of '0'".

Thank you, this little detail entirely escaped my attention!  :-+
 

Online JPortici

  • Super Contributor
  • ***
  • Posts: 3611
  • Country: it
Re: PIC18 Reset Vector in disassembly listing?
« Reply #8 on: January 17, 2025, 09:06:34 am »
Which PIC18?
Do you use interrupts on the bootloader?

All my bootloaders are designed like this:
Bootloader resides at the start of memory, as it is intended*
Let's assume the application code starts at 0x2000.

1)Create the bootloader project. Restrict the ROM range in the linker options by adding 0-1FFF
2a)If the device has the legacy interrupt controller (only capable of high/low priority) the bootloader will not use interrupts, but polling. Which is 99% of the time fine, anyway.
I add an asm file to the project containing this code
Code: [Select]
;remap the interrupt vectors
psect HiVector,class=CODE,delta=1,abs
org 0x08
    goto 0x2008

psect LoVector,class=CODE,delta=1,abs
org 0x18
    goto 0x2018

end
The effect is to redirect the interrupt vectors to the application program memory by placing exactly two goto instructions where needed.
Because the bootloader doesn't use interrupts, this doesn't mess anything.
The code above plays well with pic-as, the assembler in current XC8 (2.00-3.00)

2b) If the device has the newer VIC module, just use the interrupt as default in the bootloader.
In the application, however, you will have to explicitely redirect the IVT, for example at 0x2200 so, in the application
  • every interrupt routine will have to use the base(0x2200) attribute. this the only absolute address you'll have to enter in the application firmware
  • don't forget the default interrupt, also with base(0x2200) attribute
  • in the bootloader/application project (whichever will set the configuration bits), don't forget to set IVT1WAY = OFF, because the startup code sets IVT base and locks it
  • add to the firmware project, linker options this line: -mivt=0x2200
Application startup code will take care of remapping the IVT.

3) To launch the application, just do this
Code: [Select]
#define ApplicationEntryPoint 0x2200

void vBlStartApplication(void) {
  asm("ljmp " ___mkstr(ApplicationEntryPoint));
  Nop();
  Nop();
}
ljmp is a pseudoinstruction that will also load PCLH if needed before the goto.

You can also do
Code: [Select]
void (*startApplication)(void) = (void*)ApplicationEntryPoint;
startApplication();
Nop()
Nop();
but that produces a call instead of a goto, and you lose a call stack level. Though some (all?) PIC18 can manipulate the call stack and reset it in the startup code so it should not be a problem

The application then gets written as if there was no bootloader. Just remember (2b) if the device has vectored interrupts.
After the application is complete
1) Go to the linker options and add 2000 to code offset. All addresses that are not absolute will be shifted by 2000, making the application run in the "application space" outside the bootloader.
2) In the project options, go to loadables and add the bootloader project.

Now, when you compile, the compiler will compiler the bootloader project, the application project, put the respective hexes at the usual place and then combine the two using hexmate. The hex file containing "unified" in its name is the combination of the two.

When you debug, if a breakpoint hits, or if you are single stepping in memory that belongs to the bootloader you will be looking at the debugger source code. Neat!

* The debugger executive code likes to be put at the end of memory. It also plays havok with the SAF when you enable code execution exception from there.
« Last Edit: January 17, 2025, 09:13:39 am by JPortici »
 

Offline IDEngineerTopic starter

  • Super Contributor
  • ***
  • Posts: 1956
  • Country: us
Re: PIC18 Reset Vector in disassembly listing?
« Reply #9 on: January 17, 2025, 02:33:33 pm »
Which PIC18? Do you use interrupts on the bootloader?
PIC18F26K80 without prioritized interrupts. Not so far and likely never for the obvious reasons.

Quote
1)Create the bootloader project. Restrict the ROM range in the linker options by adding 0-1FFF
2a)If the device has the legacy interrupt controller (only capable of high/low priority) the bootloader will not use interrupts, but polling. Which is 99% of the time fine, anyway.
I add an asm file to the project... The effect is to redirect the interrupt vectors to the application program memory by placing exactly two goto instructions where needed.
Yep, already have all of this working.

Quote
when you compile, the compiler will compiler the bootloader project, the application project, put the respective hexes at the usual place and then combine the two using hexmate. The hex file containing "unified" in its name is the combination of the two.
Haven't played with this yet. Right now I have a single project that has the "application" code-offsetted up to 0x400 using the linker option. That project has a single .as file which contains the two goto's at the absolute addresses, and if I write the bootloader in Assembly I can just put that code in the existing .as file.

However, it will be substantially easier to write the bootloader in C, and if I go that route I suspect I'll have to do the "two merged projects" route because AFAIK the linker doesn't have the granularity to offset the application but not the bootloader. I might be able to force that using compiler options (say, keep the application in one PSECT and the bootloader in another, and manually address each) but that also might be too clever by half and end up a giant maintenance mess.
 

Online JPortici

  • Super Contributor
  • ***
  • Posts: 3611
  • Country: it
Re: PIC18 Reset Vector in disassembly listing?
« Reply #10 on: January 17, 2025, 02:56:52 pm »
However, it will be substantially easier to write the bootloader in C, and if I go that route I suspect I'll have to do the "two merged projects" route because AFAIK the linker doesn't have the granularity to offset the application but not the bootloader. I might be able to force that using compiler options (say, keep the application in one PSECT and the bootloader in another, and manually address each) but that also might be too clever by half and end up a giant maintenance mess.

What? no, reread my post.
You don't need to write the bootloader in assembly, unless you *need* it to be as small as possible. what you describe sound like wanting to make yourself miserable for no reason. The tools provide a simple workflow, don't go against it.

You write the bootloader as a C project. Restrict the rom range. add the asm file that redirects the interrupt vectors to the bootloader project. When the bootloader project is working, great. Forget about it.
Application project: write as if it's a standalone project, add the bootloader project as a loadable, add the codeoffset option in the application linker options.

That's it.
No assembly, other than the interrupt vector redirect, 6 lines of assembly, big whoop.

If you want to make sure the bootloader doesn't change, copy the bootloader hex file to the application project, and add the hex file as a loadable instead of the project. You will lose the ability to debug the bootloader area (debugger will report "no source code found at address xxx" if you pause while it's in the bootloader area) but that's it.

I see no maintenance mess


*Unfortunately you can't do this with GCC based compilers, because of how gcc works. It's only valid for XC8 for PIC.
« Last Edit: January 17, 2025, 02:59:03 pm by JPortici »
 

Offline IDEngineerTopic starter

  • Super Contributor
  • ***
  • Posts: 1956
  • Country: us
Re: PIC18 Reset Vector in disassembly listing?
« Reply #11 on: January 17, 2025, 04:54:18 pm »
I was emphasizing the value of having both the application and the bootloader in a single shared project.

Yes, I'm not interested in writing the bootloader in Assembly. I was just openly wondering if that would make it easier to have a single shared project.

I haven't played with having a "second application" as a loadable, but that sounds promising. Thanks for the tip!
 

Offline IDEngineerTopic starter

  • Super Contributor
  • ***
  • Posts: 1956
  • Country: us
Re: PIC18 Reset Vector in disassembly listing?
« Reply #12 on: January 21, 2025, 12:49:51 am »
Confirming what I believe is a typo in the K80 spec sheet.

The text in Section 28.6 speaks of boot blocks of 1Kbytes (which would be 0-3FFh) or 2Kbytes (0-7FFh):

"One of these is a boot block of 1 or 2 Kbytes."

However, Figure 28-6 shows a Boot Block of 2Kwords which occupies 0-FFFh (4Kbytes) and a smaller Boot Block that occupies 0-07FFh (2Kbytes). Meanwhile, register CONFIG4L:BBSIZ0 says:

1 = 2kW boot block size
0 = 1kW boot block size


...which agrees with Figure 28-6 but disagrees with the text of Section 28-6.

I believe the text of Section 28-6 used the wrong suffix, and should have read:

"One of these is a boot block of 1 or 2 Kwords."

...or used the wrong digits, and should have read:

"One of these is a boot block of 2 or 4 Kbytes."

Can anyone confirm the boot blocks are indeed 2 or 4 kilobytes? Pages from the spec sheet are attached for reference.

Thanks!


 

Offline IDEngineerTopic starter

  • Super Contributor
  • ***
  • Posts: 1956
  • Country: us
Re: PIC18 Reset Vector in disassembly listing?
« Reply #13 on: January 23, 2025, 03:06:06 pm »
Bump... nobody knows for sure?
 

Online JPortici

  • Super Contributor
  • ***
  • Posts: 3611
  • Country: it
Re: PIC18 Reset Vector in disassembly listing?
« Reply #14 on: January 23, 2025, 03:10:03 pm »
Missed it!
should be kiloWords

1kWords = 1024 words = 2048 bytes (0x800)
 

Offline IDEngineerTopic starter

  • Super Contributor
  • ***
  • Posts: 1956
  • Country: us
Re: PIC18 Reset Vector in disassembly listing?
« Reply #15 on: January 23, 2025, 05:11:49 pm »
So two, or four, kilobytes. That's what made sense but it's good to confirm. Thanks!
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf