Creating and Linking a Custom Bootloader or Library

This forum handles questions and discussions concerning Microchip’s 8-bit compilers, assemblers, linkers and related tools.

Re: Creating and Linking a Custom Bootloader or Library

Postby AaronD » Fri Aug 15, 2014 3:41 pm

Yes, my chip does save PCLATH and a few others automatically, so I'm good there. In fact, if I let the compiler put code at the interrupt vector, the first thing it does is MOVLP $.

For any newbies that might come across this, this is why you read the datasheet. It's not particularly exciting, but if you understand what you're running on, you can tell if you'll have this or any other problem at the hardware level. It doesn't say anything about your development tools though, only the chip itself and what it sees directly. It's a good indication of what the chip is capable of or not, which you can then use to direct your efforts in solving the problem. Maybe the chip just won't do it that way and the compiler knows it, or maybe the compiler is just being stupid. (yes, this happens sometimes 8-) )
AaronD
 
Posts: 11
Joined: Thu Jul 31, 2014 8:44 pm
PIC experience: Experienced Hobbyist

Re: Creating and Linking a Custom Bootloader or Library

Postby AaronD » Sat Aug 23, 2014 12:22 am

I think I'm far enough along for a useful progress report, but there are still a few problems to solve before I'm done. I've been talking to an apps engineer at Microchip also, so some of this comes from him:



Instead of #pragma psect, the help file prefers __section() for each function, constant, and variable that will be linked explicitly. I knew this from the start, but I couldn't make it work for a while. The help file uses a simpler example to suggest that I do it like this:
Code: Select all
const unsigned char __section("USBConst") string1[] = "foo";
const unsigned char __section("USBConst") string2[] = "bar";
const unsigned char *const __section("USBConst") string_table[] = {string1, string2};

Except it didn't like string_table. If I took out the __section() on that line only, it would work. If I rearrange it like this, it's happy:
Code: Select all
__section("USBConst") const unsigned char string1[] = "foo";
__section("USBConst") const unsigned char string2[] = "bar";
__section("USBConst") const unsigned char *const string_table[] = {string1, string2};

Except that doesn't work with anonymous structures. The first way does though, so I can mix and match to make all of them work.



I also found that you can use a negative address for the linker options to specify an ending address. Actually, this is one past the end, or the first address that you don't want to use. You can then, in theory, place psects consecutively before it so that all of them are packed together next to that maximum address. But it seems to have some trouble doing that:
Code: Select all
Linker:
-L-pUSBCode=-1FFEh,USBCode_split_1,USBCode_split_2,USBConst -L-pApplicationISR=0220h

Code: Select all
Output:
:0: warning: (596) segment "USBCode" (3DC2-3FFB) overlaps segment "USBCode_split_1" (3727-3EDE)
:0: warning: (596) segment "USBCode_split_1" (3727-3EDE) overlaps segment "USBCode_split_2" (3129-3B02)
:0: warning: (596) segment "USBCode_split_2" (3129-3B02) overlaps segment "USBConst" (35A3-3712)

The USBCode_split_# psects were created automatically because I probably assigned more stuff to USBCode than would fit. I didn't know this at first, so I only told the linker about USBCode, and so I still had stuff in the wrong place because I didn't tell it about these extra automatic psects. (in fact, I still have stuff in the wrong place because they clobber each other, but at least it's trying now ;) )



If you want to have an assembly file in a C project, it MUST have the extension .as. The help file is wrong in saying that it must be .s, and the MPLAB X IDE offers a choice of .s, .as (Edit: .as is actually not offered), or .asm with no explanation of the difference. :roll: Once I figured that out, it would find the .inc header file that I included from the .as assembly file, but it found syntax errors all over it. (this is an unmodified, stock header file that came with the toolchain :shock: ) After trying a few things there, I gave up, scrapped the includes, and defined my own registers and macros in the .as file itself. That worked. Don't forget to leave some handles for the linker to pick up.



So the remaining problems are:
  • How to keep a consecutive series of psects that are placed with a negative address from running over each other?
  • How to use wildcards in linker options, if they're supported at all, so that one label can collect the original and all of the splits without wasting space like I think a class would?
  • How to guarantee that the lower end of the series is padded down to the start of a 32-word row of flash?
I want to end up with at least one of my constants at the start of the lowest row so that I can distinguish a new image of upper memory from an ISR that would normally be there. I figure that the retlw instruction that comes free with every constant should do the job nicely.

According to the overall architecture of the project, interrupts are disabled before clobbering the ISR and not reenabled until the new ISR is present and verified.
AaronD
 
Posts: 11
Joined: Thu Jul 31, 2014 8:44 pm
PIC experience: Experienced Hobbyist

Re: Creating and Linking a Custom Bootloader or Library

Postby AaronD » Thu Aug 28, 2014 4:45 pm

I think I see part of why the reverse-assignment doesn't work:
  • It might stack them correctly as an intermediate step, but then it moves them up (wrong direction) to fit some boundaries that it likes. Or maybe the math is just wrong or executed too early in the process. Either way, it looks like they have a bug to fix.
  • Another weird result is that the hex file ends up with odd addresses for that part of the code. According to the file format, these are byte addresses, while this PIC uses word addresses. So a factor of 2 difference is expected, but a half-word offset is not. Other than that, the machine code is correct until the first overlap.

It also appears that if I assign a bunch of stuff to the same psect, it'll create the psect as a monolithic block and THEN try to place it. So even if it's made up of a bunch of smallish functions, it won't fill a hole that the entire psect doesn't fit into.

So now I'm experimenting with classes and more granular assignments to see if I can massage the hex file the way I want. Ultimately, I really don't care about psects or classes or any other hoops that I need to jump through; I only care about functions and constants packed as tightly as I can get, despite there being a page boundary in there somewhere. If I get less than a function's worth of unused space next to the page boundary, that's fine, but no more than that. And for future development that may not be intimately familiar with the details, I don't want to assign each function individually. I want to tell the toolchain that "these functions" all go together next to this one upper address and that "these constants" all go together next to the functions. Anything beyond that is okay for the linker to figure out.


Any insight would be appreciated.
AaronD
 
Posts: 11
Joined: Thu Jul 31, 2014 8:44 pm
PIC experience: Experienced Hobbyist

Previous

Return to MPLAB XC8

Who is online

Users browsing this forum: No registered users and 10 guests

cron