PIC18 Reset Vector in disassembly listing? - Page 1
Forum section: electronics / general

author: IDEngineer
author_rank: Super Contributor
timestamp: January 16, 2025, 06:21:42 pm
content: 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!

author: ggchab
author_rank: Frequent Contributor
timestamp: January 16, 2025, 06:41:27 pm
content: 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.

author: fchk
author_rank: Frequent Contributor
timestamp: January 16, 2025, 06:53:27 pm
content: Quote from: IDEngineer on January 16, 2025, 06:21:42 pmThe 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:globalpowerup,startpsectpowerup,class=CODE,delta=1,reloc=2powerup:nop; Suggested Microchip errata workaroundgotostartend

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 16, 2025, 07:00:49 pm
content: Using MPLABX? You can see what's going on here:Window -> Target Memory View -> Program Memory

author: IDEngineer
author_rank: Super Contributor
timestamp: January 16, 2025, 07:47:16 pm
content: Quote from: fchk on January 16, 2025, 06:53:27 pmRight, 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.

author: IDEngineer
author_rank: Super Contributor
timestamp: January 16, 2025, 10:07:56 pm
content: The initialization code starts at address 0x022B2, and the symbol table shows:Code:start_initialization 22B2At the end of the initialization portion of the listing, this line jumps to main():Code:002314 EF85 F007goto_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....

author: westfw
author_rank: Super Contributor
timestamp: January 16, 2025, 11:13:32 pm
content: QuoteLooks 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.

author: IDEngineer
author_rank: Super Contributor
timestamp: January 16, 2025, 11:57:01 pm
content: 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!

author: JPortici
author_rank: Super Contributor
timestamp: January 17, 2025, 09:06:34 am
content: 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-1FFF2a)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 codeCode:;remap the interrupt vectorspsect HiVector,class=CODE,delta=1,absorg 0x08goto 0x2008psect LoVector,class=CODE,delta=1,absorg 0x18goto 0x2018endThe 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 applicationevery interrupt routine will have to use the base(0x2200) attribute. this the only absolute address you'll have to enter in the application firmwaredon't forget the default interrupt, also with base(0x2200) attributein 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 itadd to the firmware project, linker options this line: -mivt=0x2200Application startup code will take care of remapping the IVT.3) To launch the application, just do thisCode:#define ApplicationEntryPoint 0x2200void 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 doCode: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 problemThe application then gets written as if there was no bootloader. Just remember (2b) if the device has vectored interrupts.After the application is complete1) Go to the linker options and add2000to 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.

author: IDEngineer
author_rank: Super Contributor
timestamp: January 17, 2025, 02:33:33 pm
content: Quote from: JPortici on January 17, 2025, 09:06:34 amPIC18F26K80 without prioritized interrupts. Not so far and likely never for the obvious reasons.QuoteYep, already have all of this working.QuoteHaven'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.

author: JPortici
author_rank: Super Contributor
timestamp: January 17, 2025, 02:56:52 pm
content: Quote from: IDEngineer on January 17, 2025, 02:33:33 pmWhat? 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 vectorsto 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.

author: IDEngineer
author_rank: Super Contributor
timestamp: January 17, 2025, 04:54:18 pm
content: 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!

author: IDEngineer
author_rank: Super Contributor
timestamp: January 21, 2025, 12:49:51 am
content: 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 size0 = 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 2Kwords."...or used the wrong digits, and should have read:"One of these is a boot block of2or4Kbytes."Can anyone confirm the boot blocks are indeed 2 or 4 kilobytes? Pages from the spec sheet are attached for reference.Thanks!

author: IDEngineer
author_rank: Super Contributor
timestamp: January 23, 2025, 03:06:06 pm
content: Bump... nobody knows for sure?

author: JPortici
author_rank: Super Contributor
timestamp: January 23, 2025, 03:10:03 pm
content: Missed it!should be kiloWords1kWords = 1024 words = 2048 bytes (0x800)

author: IDEngineer
author_rank: Super Contributor
timestamp: January 23, 2025, 05:11:49 pm
content: So two, or four, kilobytes. That's what made sense but it's good to confirm. Thanks!