View previous topic :: View next topic |
Author |
Message |
guy
Joined: 21 Oct 2005 Posts: 297
|
Bootloader clears configuration bits despite WPCFG |
Posted: Wed Sep 03, 2014 1:17 am |
|
|
A weird thing is happening with the bootloader I am using (a modified CCS PCD example), PIC24FJ64GA308, compiler 5.026 .
I program the bootloader to the chip, read the program memory and it's reading correctly. So far so good. Then I upload a HEX file with the same #FUSES as the bootloader, the program *is* loaded correctly but the configuration bits all get cleared (or at least messed up) : the oscillator works at a different speed (I see the program running but at low speed) and the chip becomes code protect.
Things I tried and didn't work:
- upload a hex file with #FUSES none
- program the bootloader with WPCFG on (write-protect configuration bits - even that didn't help!)
I never sweated so much on a project... I guess it was a mistake to move to PIC24 and PCD with such a big project... :-) |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Sep 03, 2014 1:46 am |
|
|
Step back.
What happens if you use the example?.
It sounds as if the core code of the bootloader, is not handling perhaps the extended addressing properly, so talking to the wrong page in memory.
On the protection, are you possibly (maybe by accident) compiling in debug mode?. This turns off a lot of the protection fuses, so would stop the protection from being implemented. The old MPLAB override possibly.... |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
|
Posted: Wed Sep 03, 2014 2:09 am |
|
|
Bootloader code - could be. I'll check into it and report.
WPCFG - I'm compiling with RELEASE, using Pic-kit3 as programmer (not debugger), and checking on the Configuration Bits window that WPCFG is indeed enabled.
Now struggling with another issue. The same code/hardware works with UART1 but not with UART4.
This works (ISR gets called) :
Code: | #PIN_SELECT U1RX =PIN_B9 // from 232
#PIN_SELECT U1TX =PIN_B8 // to 232
#use RS232(STREAM=TBLT, BAUD=38400, UART1, ERRORS)
...
#INT_RDA
void rdaIsr() {
tmp=fgetc(TBLT);
}
...
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
|
but the following:
Code: | #PIN_SELECT U4RX =PIN_B9 // from 232
#PIN_SELECT U4TX =PIN_B8 // to 232
#use RS232(STREAM=TBLT, BAUD=38400, UART4, ERRORS)
...
#INT_RDA4
void rda4Isr() {
tmp=fgetc(TBLT);
}
...
enable_interrupts(INT_RDA4);
enable_interrupts(GLOBAL);
|
creates one false interrupt as soon as I enable it, and then never again. clearInterrupt(INT_RDA4); before enabling it solves the false interrupt but the interrupt routine won't get called when a char arrives. I will start digging into the PPS and UART4 registers... |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
UART4 |
Posted: Wed Sep 03, 2014 2:28 am |
|
|
Solved the UART4 problem - it's a compiler bug (compiler version 5.026)
Setting the PPS manually solved it:
#WORD RPINR27 = 0x6B6 // PPS register for UART4 CTS and RX
RPINR27 = 0b0011111100001001; // point U4RXR<5:0> to RP9/RB9
I'll send an e-mail to support@ccs with the .LST file :-) |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Sep 03, 2014 2:39 am |
|
|
Have you tried with another UART?.
I remember on another chip, CCS had the UART 'numbers' swapped.
Have a look at the compiled listing for the fgetc, and check what register it actually talks to.
The behaviour you describe on the configuration, is what you would expect if a page erase operation is performed to the page containing the configuration words:
"Note: Performing a page erase operation on the
last page of program memory clears the
Flash Configuration Words, enabling code
protection as a result. Therefore, users
should avoid performing page erase
operations on the last page of program
memory.".
I'd write a test into your bootloader, so if it receives an address that is in this range, it just throws the data away. Effectively 'code protecting' this area.
So if (for instance) you are using the compilers 'write_program_memory' function, you could 'encapsulate' it as:
Code: |
void my_write_program_memory(int32 address, char * data, int16 count)
{
if (address>=0xF80000)
return;
write_program_memory(address, data, count);
}
|
and then call this instead of write_program_memory.
If it then starts working, it comes down to setting a flag before each call to the code, which you record on the 'trapped' route, so you can trace exactly where it is getting the wrong value from.
Best Wishes |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
|
Posted: Wed Sep 03, 2014 2:45 am |
|
|
re bootloader - great hint! THANKS! Also explains the silly WPCFG behaviour.
re UART - it's only on UART4. The relevant PPS register seems uninitialized. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Sep 03, 2014 3:02 am |
|
|
Well done.
You 'beat me to it', I was just generating a short test, to see if it was setting the registers.
In the device editor, UART4, is listed, and shown as using the programmable pin functions. The output bit look as though it sets. I think it is only the input bit that is missed.....
The bits for this are defined in the data for the chip using the low bits in RPINR27 (bit 0 to 5), but they are not set by the select function. It doesn't do U4CTS or RTS either |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
|
Posted: Wed Sep 03, 2014 3:18 am |
|
|
I added protection to the bootloader and the whole config area:
Code: | void my_write_program_memory(int32 address, char * data, int16 count)
{
if ((address<0x0C00)||(address>=0x800000)) {
return;
}
write_program_memory(address, data, count);
}
|
The same thing still happens (code protect, config is corrupted). I tried as standalone (Release) and in debug mode. In debug, I put a breakpoint inside the IF but it doesn't reach it.
Still investigating... Maybe it's the erase_program_memory... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Sep 03, 2014 3:41 am |
|
|
Are you using erase separately?.
I was assuming you were using the built in erase in the write function.
If you are erasing separately, then definately trap this the same way. It'll also help narrow down where it comes from. |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
|
Posted: Wed Sep 03, 2014 3:49 am |
|
|
(re erase - there are erases in the PCD bootloader code, BUT...)
Good news and bad news:
Good news - the bootloader is ok (I think).
Bad news - the following statement seems to mess things up, and I'm not sure why:
Code: |
#define FLASH_DATA_AREA 0xA800
#define FLASH_DATA_SIZE 64 // in instructions
#RESERVE FLASH_DATA_AREA, FLASH_DATA_AREA+511 // page reserved for config data
byte flashBuf[FLASH_DATA_SIZE*4];
write_program_memory(FLASH_DATA_AREA, flashBuf, FLASH_DATA_SIZE*4); |
The way I designed the software is that there is a configuration area in prog memory which holds a flag. When a firmware upgrade is requested the flag is set to 'bootloader' (in prog memory) and the chip resets. The startup code/bootloader tests the flag, performs the firmware upgrade, then sets the flag to 'runtime' and resets itself again.
I think there is a problem with the address I am using with write_program_memory.
Help??? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Sep 03, 2014 4:21 am |
|
|
Look at the memory map.
Flash config words are held at 0xAB78 on your chip.
The erase page size is 2KB.... So a write to 0xA800, erases everything from 0xA800 to 0xAFFF. Oops.... |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
|
Posted: Wed Sep 03, 2014 4:37 am |
|
|
As a newbie in PIC24 I need an explanation...
Quote: | RTSP (Run-Time Self-Programming) is accomplished using TBLRD (Table Read) and TBLWT (Table Write) instructions. With RTSP, the user may write program memory data in blocks of 64 instructions (192 bytes) at a time and erase program memory in blocks of 512 instructions (1536 bytes) at a time. |
I thought the addresses were in 'units' of 1 instruction...? So the erase block is 512 instr. or 0xA800 to 0xA9FF...?
Besides, during the discussion you mentioned that the config was at (address>=0xF80000). I do see in the data sheet
Quote: | Configuration Word
Addresses, PIC24FJ64GA3XX 00ABF8h:00ABFEh | so why 0xF80000 ?
[/quote] |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Sep 03, 2014 5:01 am |
|
|
There are two separate addresses for the config.
Where it 'appears' as far as the programmer is concerned, and where it is 'held' when running. The former is 0xF80000, while the latter if 0xABF8.
Then the erase size, is 512 _32bit words_ (of which only 24bits exist). So 2KB of space containing 1536 useable bytes.
Addresses are in bytes. |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
|
Posted: Wed Sep 03, 2014 5:05 am |
|
|
Now I have something to chew on (while I get things to work).
Thank you so much Ttelmah. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Wed Sep 03, 2014 7:38 am |
|
|
Ttelmah wrote: |
Then the erase size, is 512 _32bit words_ (of which only 24bits exist). So 2KB of space containing 1536 useable bytes.
Addresses are in bytes. |
Just a clarification question. On the PIC24 chips I have worked on, ROM addresses are in units of 16 bit words, so for every instruction you use 2 addresses (upper word and lower word). I haven't perused the data sheet of that chip specifically, but if it says 512 instructions, under normal PIC24 chips, I would expect 1024 addresses or 0x400 sized pages. Is this one different from normal PIC24's? For comparison, I work with PIC24FJ64GA004/104 and PIC24F32KA302/304 most often. |
|
|
|