|
|
View previous topic :: View next topic |
Author |
Message |
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
Bootloader questions with dsPIC30F6014A |
Posted: Mon Feb 10, 2014 6:36 pm |
|
|
Hi everyone,
I just got bootloader code successfully running on my dsPIC30F6014A chip with CCS compiler version 5.016. As I searched in this forum, I use Tera Term to send hex file. But I have a problem:
After I downloaded my program into the chip, I re-powered up my system, the bootloader gone and the program runs my main program directly.
I am not surprised to it, because even I use #ORG statement to specify the ROM address in my main program is from 0x0602 (0x0100 to 0x05FF used for bootloader code), there is still some code compiled in the address 0x0000 to 0x00FE, and I know that is reset vector address and interrupt vector, and I think the reset address is changed to my main program entry address not the bootloader program entry address.
So my question is:
1. what should I do to let my program always start from bootloader entry address without changed by downloading the main program hex file?
2. If the first question gets solved, How do I know my main program entry address in the ROM? I tried to use #ORG 0x0602 before the main function in my main program code, but the compiling not pass, because I think the compiler can not put my whole program in to section from 0x0602 to 0xFFFE. So my question is how do I define my main function entry address in main program code so that I can use this address to let bootloader know where is to entry if bootloader not triggered by external input?
Thanks for you guys help!
Kind Regards
Mark
EDIT: I use CCS bootloader example code as my bootloader program in this project with some address changes |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Mon Feb 10, 2014 9:00 pm |
|
|
Unless you reassign the reset and interrupt vector table using the #build command in your application, it will still put things there. I know you mentioned #ORG, but did you block out the full range?
I usually start my apps with
Code: |
#FUSES NONE
#BUILD (reset=APP_RESET_LOC,interrupt=APP_IVT_START)
//this line ensures application code won't be in this range, which is bootloader
#ORG 0x0000,(APP_RESET_LOC-1){}
|
Specifying the #defines using getenv() params (or you can hard code addresses). This usually ensures that my app will put 0 code in that section.
If you do remap the reset vector and IVT, make sure your bootloader has the correct jumps for those.
EDIT: Just tried it in 5.010 and it seems to work ok according to the LST and Hex files. |
|
|
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
|
Posted: Mon Feb 10, 2014 11:02 pm |
|
|
jeremiah wrote: | Unless you reassign the reset and interrupt vector table using the #build command in your application, it will still put things there. I know you mentioned #ORG, but did you block out the full range?
I usually start my apps with
Code: |
#FUSES NONE
#BUILD (reset=APP_RESET_LOC,interrupt=APP_IVT_START)
//this line ensures application code won't be in this range, which is bootloader
#ORG 0x0000,(APP_RESET_LOC-1){}
|
Specifying the #defines using getenv() params (or you can hard code addresses). This usually ensures that my app will put 0 code in that section.
If you do remap the reset vector and IVT, make sure your bootloader has the correct jumps for those.
EDIT: Just tried it in 5.010 and it seems to work ok according to the LST and Hex files. |
Thanks for your quick reply, jeremiah. I will try you way soon. Actually I work out another way to fix the my first question, in the bootloader code, I only allow it to write the address from 0x0004 to Bootloader_start_addr, and the address above bootloader_end_addr, which means I can not allow it to write Reset vector and reset target address, and it workds, every time it start from bootloader, however I am not sure if there is potential risk when i run my application (I think it is OK, because the bootloader code doesn't have interrtupt vector, so it should be safe and I tried after I downloaded my app, I re-powered up and enter the bootloader routine then download again, the bootload still works). Then it comes to my second question, how can I define my main function entry address in my application? any suggestion?
Thanks for your help. I do appreciate.
Mark
EDIT: I only have an idea to my second question is:
I define a static var in my bootloader code and fix it to store in an address in ROM or EEPROM, and when the bootloader gets the hex that needs to write reset vector, rather than ignore this(as i said above to make micro always starts with bootloader), I can grab this vector value and write it to that ROM address which store that variable, so no matter the entry address is in my apps, it can always fit. I will try my idea soon and back to tell you the result. But maybe my idea is redundant and stupid. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Tue Feb 11, 2014 9:27 am |
|
|
You can just #define the location of the application reset vector in the bootloader and use goto APPLICATION_RESET_VECTOR_LOCATION
The main thing is the bootloader needs the application reset vector defined and jumped to and the application needs the #build(reset=APPLICATION_RESET_VECTOR_LOCATION) so that they agree. The rest can be handled by the compiler. |
|
|
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
|
Posted: Tue Feb 11, 2014 3:38 pm |
|
|
jeremiah wrote: | You can just #define the location of the application reset vector in the bootloader and use goto APPLICATION_RESET_VECTOR_LOCATION
The main thing is the bootloader needs the application reset vector defined and jumped to and the application needs the #build(reset=APPLICATION_RESET_VECTOR_LOCATION) so that they agree. The rest can be handled by the compiler. |
Thank you very much, jeremiah. The image makes me understand your idea completely, I will try it now.
By the way, my idea for finding the "my application main entry address" works! But I will use your way if I can get it work because I don't need to record that in the EEPROM.
Thank you for your kind help again.
Mark |
|
|
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
|
Posted: Tue Feb 11, 2014 3:50 pm |
|
|
Hi jeremiah, I just tried your way, but it doesn't work, the code I put in my application is:
Code: |
#if defined(__PCD__)
#include <30F6014A.h>
#fuses HS/*,PR*/,NOWDT
#bulid (RESET = 0x0900)
#build (stack=0x1E00:0x1FFF)
#device ADC=12
#use delay(clock=20000000) // Actual crystal is 20M
#use RS232(UART1, BAUD=9600, BITS = 8, STOP = 1, PARITY = N, ERRORS)
#org 0x0100, 0x08FF {}
#endif |
The compiler gave the error that:
*** Error 7 "main.c" Line 7(2,7): Invalid Pre-Processor directive
*** Error 43 "main.c" Line 7(8,9): Expecting a declaration
*** Error 48 "main.c" Line 7(9,14): Expecting a (
*** Error 43 "main.c" Line 7(17,23): Expecting a declaration
*** Error 43 "main.c" Line 7(23,24): Expecting a declaration
5 Errors, 0 Warnings.
Build Failed.
I am using CCS compiler version 5.016 to compile dsPIC30F6014A, it looks not support that feature, or I did some mistake?
Thanks for your time.
Mark |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Tue Feb 11, 2014 4:12 pm |
|
|
You have to spell build correctly! |
|
|
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
|
Posted: Tue Feb 11, 2014 4:31 pm |
|
|
jeremiah wrote: | You have to spell build correctly! |
Sorry, mate, I just notice that and want to delete my last post and tell you this..
I will try you way now. Sorry for my stupid mistake. |
|
|
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
|
Posted: Tue Feb 11, 2014 4:41 pm |
|
|
I passed the compile and I am trying to download and see the result.
However, I doubt it will ok because after compiling my application I check the hex file, the first line is still about some content in address 0x0000 which will change the reset vector that should point to bootloader entry address. However, in my bootloader code, if the chip gets 0x0000 address to write, it will skip, so won't effect
Mark |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Tue Feb 11, 2014 4:44 pm |
|
|
That's because your #org starts at 0x0100 instead of 0x0000. Normally CCS won't put any real code there because the reset is there. Since the reset is moved it might unless you make sure #org prevents it.
Since you are leaving in the IVT but moving the reset, you'll need to #org around the IVT:
#build (reset = 0x0800)
#org 0x0000,0x0001 {}
#org 0x0100,0x07ff {}
Notice I also changed the values. You don't want to start mid Page as you have to erase an entire page at a time to write to it. You don't want to erase part of your bootloader. Always start on page boundaries.
EDIT: On that note, I'm not as familiar with that particular chip, but you might run into problems letting the application write to 0x0002-0x00ff for the interrupts. Once the bootloader is burned in, you can only write to that location once without reprogramming the bootloader again (remember have to erase on page boundaries but you don't want to erase the first page since your bootloader reset vector is there). Something to consider. On my bootloaders, I generally move both the reset vector and the IVT out of there so my app can use interrupts without having to reprogram the bootloader again.
EDIT: I also just noticed that you put FUSES in the application. This is generally a bad thing to do. If you change the fuses from what the bootloader uses, you can sometimes mess up the bootloader. If your bootloader ignores these it is ok, but I like to make sure to use
#FUSES NONE
In my application code. |
|
|
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
|
Posted: Tue Feb 11, 2014 5:01 pm |
|
|
jeremiah wrote: | That's because your #org starts at 0x0100 instead of 0x0000. Normally CCS won't put any real code there because the reset is there. Since the reset is moved it might unless you make sure #org prevents it.
Since you are leaving in the IVT but moving the reset, you'll need to #org around the IVT:
#build (reset = 0x0800)
#org 0x0000,0x0001 {}
#org 0x0100,0x07ff {}
Notice I also changed the values. You don't want to start mid Page as you have to erase an entire page at a time to write to it. You don't want to erase part of your bootloader. Always start on page boundaries.
EDIT: On that note, I'm not as familiar with that particular chip, but you might run into problems letting the application write to 0x0002-0x00ff for the interrupts. Once the bootloader is burned in, you can only write to that location once without reprogramming the bootloader again (remember have to erase on page boundaries). Something to consider.
EDIT: I also just noticed that you put FUSES in the application. This is generally a bad thing to do. If you change the fuses from what the bootloader uses, you can sometimes mess up the bootloader. If your bootloader ignores these it is ok, but I like to make sure to use
#FUSES NONE
In my application code. |
Yes, You're right. I changed my ORG:
#ORG 0x0000,0x08FF {}
And put
#build (RESET = 0x0900, INTERRUPT = 0x0904)
The hex file of my application looks fine now,
And in my bootloader, I use goto_address(0x0900);
After I tested, it doesn't work, I can trigger my bootloader but no matter after dowloading or not trigger, the chip can not enter in my application. Anything wrong I did? |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Tue Feb 11, 2014 6:16 pm |
|
|
How are you verifying that it didn't go to the application? What's your means of debugging available?
I'm still concerned about your 0x0900 address. Normally you would want to start on a page boundary (I'd have to look it up in the data sheet, but I think multiples of 0x0400 maybe? If so, you would either want 0x0800 or 0x0c00). |
|
|
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
|
Posted: Tue Feb 11, 2014 7:01 pm |
|
|
jeremiah wrote: | How are you verifying that it didn't go to the application? What's your means of debugging available?
I'm still concerned about your 0x0900 address. Normally you would want to start on a page boundary (I'd have to look it up in the data sheet, but I think multiples of 0x0400 maybe? If so, you would either want 0x0800 or 0x0c00). |
My application will start with a welcome picture on the LCD screen, that is why I know it doesn't start my application after downloading. I dont' have special debugging method, just use "printf" to output the value I monitor, MPLAB debug mode not working on my project, don't know why and don't have time to know why.
I also checked the flash erase size by output getenv("FLASH_ERASE_SIZE"), and it shows 128. I understand your concern and try to let me avoid erasing bootloader code area, but if the flash erase size is 128 which means 0x100, then my application starts from 0x900 should be fine, am I right?
Thanks a lot
Mark |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Tue Feb 11, 2014 7:35 pm |
|
|
Yes, if that is the erase size, you are good. I'm more familiar with other PCD chips, so I wasn't sure. On mine, flash erase size comes out to 2048, which is 1024 words or 0x0400. I typically use PIC24's though.
The reason I was asking about the debugging method was I was curious where it was failing.
I think the safest thing to do is that if your other method you mentioned earlier works, stick with that. I know my method works too (at least on my projects so far), but don't know where in between the issue cropped up. I don't want to hold you up trying to change everything and end up having you chase down a lot of problems. |
|
|
naughty_mark
Joined: 29 Aug 2012 Posts: 97
|
|
Posted: Tue Feb 11, 2014 7:51 pm |
|
|
jeremiah wrote: | Yes, if that is the erase size, you are good. I'm more familiar with other PCD chips, so I wasn't sure. On mine, flash erase size comes out to 2048, which is 1024 words or 0x0400. I typically use PIC24's though.
The reason I was asking about the debugging method was I was curious where it was failing.
I think the safest thing to do is that if your other method you mentioned earlier works, stick with that. I know my method works too (at least on my projects so far), but don't know where in between the issue cropped up. I don't want to hold you up trying to change everything and end up having you chase down a lot of problems. |
Thanks for your kind help, jeremiah. I do appreciate.
Yes, anyway I have a backup solution which is not effective but working
Another thing I would like to ask you is, when you try your bootloader on your project, what is your max baudrate you can transfer the hex file?
The reason I asked it is I am using Tera Term to send hex file as I mentioned, and I found the max speed I can achieve is 1.5KB/s which is even less than 19200 baudrate, so I can only use 9600 baudrate to transfer the HEX file. I know the reason and I debug with printf function, some of the data the micro recieved are corrupted, and there is no re-send strategy. I wrote a windows and command line program by VC++ in my other project which has re-send and time-out strategy and can work under 115200 without any problem. However, with this project, I would like to keep as simple as possible because to perform that strategy, my bootloader side also need some complex programming (not very tough, but I think it is not worth to do).
So do you have any recommandation of serial port software which has re-send strategy?
Thanks a lot
Mark |
|
|
|
|
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
|