I think other users would appreciate if you share your work.
Thanks!
I think other users would appreciate if you share your work.
Thanks!
I think you mean YOUR work!
Without posting a VB "updater" (which is going to be very application specific for this case), there's really not much to post.
The idea here is to create a "firmware update file" from a master, so it can be distributed in the field or wherever.
Suffice to say that if your main program has a hidden "dump all my code out via serial" subroutine, then you don't have to muck about with interpreting intel hex files, you just get raw code (instructions) from memory location A to memory location B from your "master" that you've updated with your PIC programmer (the upper memory program is always included with this).
Once you have that "master" file captured by a PC, you can send it back out its serial port to be intercepted by the "main program" on any unit to be UPDATED, and stored on I2C. After checking the checksum, then you call the "reprogram" code sitting in upper memory to rewrite all the lower code, stopping shy of the "tucked" upper subroutine location. Encryption is just a matter of manipulation at the PC end after receiving the original dump, and reverse-manipulation at the PIC end as you pull the words back out of I2C (before doing the codewrite).
Last edited by picster; - 10th May 2016 at 20:44.
It didn't get to me that you can easily dump PIC code from programed PIC if you don't want to muck with hex.
That is great idea!
Yeah well, at least I contributed SOMETHING! LOL
This is a major game-changer for field updates. The approach should also work fine for PIC16F88's.
I'll try to create a somewhat "generic" windows firmware updater based on this approach, with VB6 in the next little while and post it for others to use. It will only be able to Xfer a file IN (PIC readcode dump-->PC), and send a file OUT (PC-->PIC firmware update). It will NOT have encryption built into it, since that's also critically dependent upon a PIC decryption subroutine.
Did you manage to successfully pass variables from your "main program" to your "bootloader" section? If so, did you declare them in BOTH, or was that the purpose of your BLOCKSIZE declaration as a system variable, so it would be accessible for the upper memory AND the resident program?
Thanks,
picster
I did, but via EEPROM and other way. So main app knows when it is first run, so it can configure I2C memory, etc...
But you can define variables at specific addresses.
From manual:
wsave VAR BYTE $70 'Creates "wsave" at RAM address 0x70 (hex)
Just create variable at address $70 both in main app and bootloader. And load it in main app before jumping to bootloader, and use it in bootloader. But you must be careful not to clear it, before use.
BLOCK_SIZE is ASM constant for each pic. And it tell how long is one block or page in FLASH.
So to get this information to PBP, I used this code:
If variable is not defined as systemCode:@ MovLW BLOCK_SIZE ;move literal to W @ MovWF BlockSize ;Move W to File(variable)
BANKA must be used, or in ASM you need to set correct bank.Code:BlockSize VAR BYTE BANKA @ MovLW BLOCK_SIZE @ MovWF _BlockSize
This can be done in few ways, but i don't like that. All my ASM routines use variables in BANKA, so I doesn't have to deal with selecting bank.
SYSTEM just removes underscore in ASM variable name. Default behavior of PBP is to put _ in front of name. Eg if you declare A var byte, in ASM variable is called _A. With modifiers SYSTEM PBP will create same name for ASM.
Just habit that I have to put all ASM variables to BANKA SYSTEM...
[EDIT]This also could be done with EXT modifier.[/EDIT]
FLASH is erased and write ONE PAGE at TIME. PBP will track address that you are writing, and when it align with page it will dump all data to FLASH.
Data are temporally stored to TBL. So if you just put one WRITECODE instruction, your byte or word wont be written to FLASH. It took me some while to get it. At least for PIC18F.
If you measure how much time it takes to do instruction WRITECODE, you will see eg 63 very fast(10-20 uS, depending on oscillator speed), and 64th will take about 5mS(doesn't depend on oscillator). This is if your page size is 64 byte. Don't hold me to exact figures, I can remember just ballpark value.
Last edited by pedja089; - 11th May 2016 at 15:14.
Ok, thanks - so variables can be transferred either via EEPROM (which is bidirectional [main program<-->updater] since it stays put after reset) or via variables assigned in BANKA (which is uni-directional, since it's cleared upon reboot after the lower code is rewritten).
You determined that BLOCK_SIZE was a constant by looking at the INCLUDE file for the pic, right?
I haven't tried it, but do you think it should be possible to use:
Blocksize VAR BYTE $70
Blocksize=BLOCK_SIZE
and then pass it that way, since BLOCK_SIZE is pre-defined in the device's include file?
You get something wrong, probably because my bad English
Constant BLOCK_SIZE is defined in microchip MPLAB, and doesn't have anything with PBP. So PBP compiler won't be aware of BLOCK_SIZE and will throw an error.
(And I can't remember where I found it, I think it was used in some PBP lib file)
[EDIT]BLOCK_SIZE is defined in includes that are located at PBP3\DEVICES. But this is ASM level include as far as I know. It is just added to .lst file after compiling. So compiler isn't aware of this file.[/EDIT]
But if you use it in ASM, compiler will just forward your ASM line to .LST file. And .LST file will be assembled into ASM and then in HEX file.
So to be clear(or try to be), BLOCK_SIZE is in assembler include, BlockSize is any variable in PBP preferably in BANKA.
There is two way, one I used is to move constant to variable in ASM, and other is similar to yours, but you must use EXT to tell PBP compiler that your constant is declared somewhere else, but assembler can reach it.
That should look like this
BLOCK_SIZE CON EXT
BlockSize VAR BYTE
BlockSize=BLOCK_SIZE
But then you don't need variable BlockSize, because you can use constant BLOCK_SIZE.
I didn't try this, I just know what I learned from Darrel's post about EXT.
To pass variable from main app to bootloader, variable doesn't have to be in any specific bank, it must be at specific address.
In main app:
VarAtAdr50 VAR BYTE 50 'This is variable declared at decimal address 50
....
VarAtAdr50=10
GOTO StartBootloader
In Bootloader:
VarAtAdr50 VAR BYTE 50
If VarAtAdr50=10 THEN ....
I hope that this clears things, if not can somebody else try to explain it better? Thanks, in advance.
Last edited by pedja089; - 11th May 2016 at 23:49.
Bookmarks