|
|
View previous topic :: View next topic |
Author |
Message |
RckRllRfg
Joined: 20 Jul 2011 Posts: 60
|
Jump to another address |
Posted: Sat Sep 10, 2011 11:39 am |
|
|
I have one more hurdle for the bootloader.
I am trying to implement a jump to the loader program from my application. Using the goto_address is not working. I tend to believe that it is due to the higher address in which the application resides. In addition I am concerned about clearing out the stack.
BTW, the .lst shows the following:
.................... goto_address(LOADER_END-LOADER_SIZE);
0B8F: CLRF 0A
0B90: MOVLW 80
0B91: MOVWF 02
0B92: MOVLB 00
This is more of side question, but an explanation would be appreciated. Should the MOVLB command be at the beginning of the 4 assembly commands listed above.?
CLRF 0A clears the value of the PCLATH
MOVLW 80 move the literal 80 (the address of interest) into W
MOVWF 02 puts 80 into the PCL. It is my understanding that upon this writing of the register, the jump to the address should take effect.
The MOVLB is to change to bank 00.
Using: CCS 4.124, MPLAB 8.76 and PIC16F1947
Thanks for your consideration -
RckRllRfg |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Sun Sep 11, 2011 2:39 am |
|
|
The compiler 'knows' what bank is currently selected, and will use this if it is what is needed. The PCL, and PCLATH register, are present in _all_ banks (0..7), so the compiler does not need to change banks before addressing these. The instruction to change banks, is for the following code, which should never be reached. The chip has already jumped.
The bank change doesn't come from the goto_address instruction. If you compile this in a little test program with nothing around it, there is no bank change instruction. The bank change, is a standard instruction put at the _end_ of a subroutine, to switch back to bank0, before the routine returns. If the routine contains any instruction that changes the bank, then at the end of the routine there will be this MOVLB 00 instruction. In this case it does nothing since the code has gone elsewhere.....
That you are in a subroutine, suggests your jump stack may contain something. If so you should consider setting STKPTR to 0x1F before jumping.
The jump certainly should work as it is. Is your loader really this small?. Just 0x80 bytes?.
Best Wishes |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun Sep 11, 2011 2:47 am |
|
|
Starting the bootloader by a jump or goto requires to think about restoring default conditions for the chip. Performing cpu_reset(), possibly setting a flag to distinguish from regular reset is the better variant in my opinion. |
|
|
RckRllRfg
Joined: 20 Jul 2011 Posts: 60
|
A few more details for your consideration |
Posted: Sun Sep 11, 2011 8:08 am |
|
|
FvM and Ttelmath -
First, thank you for the explanation and the recommendations. I will pursue them.
I should also provide a bit more explanation as to what I am trying to accomplish.
I would like to have 2 methods to jump to the bootloader. The first would be to use a specific configuration of DIP switches that the bootloader reads upon POR. The second is a jump to the bootloader after the application has identified a series of ASCII values sent from a terminal program such as RealTerm.
But, here's the rub - if the application is calling the bootloader, the DIP switches will not be in the bootloader configuration (and in the environment in which this equipment will be in, it will be extremely difficult to access the switches).
So, I was thinking that a way to handle this would be to jump to the real_load_program start address rather than the main of the bootloader.
I suppose that I could write some register prior to the jump and have the bootloader check it to see if this flag has been set, as FvM has suggested, but this still requires a jump. Since the loader and application are separate programs, I have to deal with this discontinuity.
I like the idea of the cpu_reset since should clear the stacks and other key registers. If use the cpu_reset(), would I lose the flag that I set?
RckRllRfg |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Sun Sep 11, 2011 9:57 am |
|
|
You need to understand the different types of 'reset'.
Only a power_on reset, clears the memory locations. On a watchdog, they will retain their previous values, as they will on a reset_cpu instruction. On a brownout, the values are indeterminate.
Even with a power_on reset, quite a few values are indeterminate. There is no actual _guarantee_ that a memory address will contain 0, or 1. There are determined values for quite a few of the registers, and these are in the memory map in the data sheet.
This is why it is possible to leave values uninitialised on boot, and only initialise them on a normal restart, and have code 'carry on' with existing values in the case of a watchdog restart.
Using this is where the 'restart_cause_ instruction comes in vitally useful. You can code at the start of your bootloader:
Code: |
if(restart_cause()==RESET_INSTRUCTION) {
//Here handle your restart from the main code bootloader operation
}
else {
//Here check your normal bootloader hardware bits
}
|
Obviously you would need further options if you have to handle a WDT restart for instance, but the basic idea is there.
Best Wishes |
|
|
RckRllRfg
Joined: 20 Jul 2011 Posts: 60
|
It worked!! |
Posted: Sun Sep 11, 2011 9:10 pm |
|
|
Ttelmah and FvM -
After making few adjustments to the memory allocations (cause my main got too big for its britches), adding in the reset_cpu in the application, and adding the reset_cause in the application, IT WORKED!!!
Thank you for your recommendations. I would go drink, but I have to write up the documentation....
My best to all of you,
RckRllRfg |
|
|
|
|
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
|