|
|
View previous topic :: View next topic |
Author |
Message |
scarey_4567
Joined: 06 Aug 2014 Posts: 5
|
write_program_memory doesn't work |
Posted: Wed Aug 06, 2014 4:36 am |
|
|
I'm using a PIC16F1826 and am struggling to get the write_program_memory function to work correctly. As far as I understand from the uChip datahseet, I need to write in 32 word blocks (although the CCS datasheet suggests I can write as many/few as I like).
Anyway, here's my code which I've isolated:
Code: | #include <16F1826.h>
#fuses HS,NOWDT,NOWRT,NOPROTECT,NOCPD, NOBROWNOUT, LVP, PUT, MCLR //,NOPROTECT,NOLVP,INTRC_IO,MCLR,NOBROWNOUT,PUT
// setup delay timer source
#use delay(internal=4M)
void main()
{
unsigned char data[64] = {0};
unsigned char i = 0;
for (i = 0; i < 64; i++)
{
data[i] = 0xAA;
}
write_program_memory(0x0400, data, 64);
}
|
When I read the memory via the PICKit3, it shows me this:
Code: |
x400 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF
x408 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF
x410 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF 3FFF
x418 2AAA 2AAA 2AAA 2AAA 2AAA 2AAA 2AAA 2AAA
|
Apart from only writing to the last 8 words, the data it's written is wrong, where's the 2A coming from?
This is all for a bootloader I'm trying to write so I've looked over the examples ex_bootloader.c and I can't see what I'm doing wrong.
Thanks |
|
|
scarey_4567
Joined: 06 Aug 2014 Posts: 5
|
|
Posted: Wed Aug 06, 2014 5:37 am |
|
|
I realised it's a 14-bit instruction device which explains why the x2AAA
I still don't get why it's not writing the block I want it to. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Wed Aug 06, 2014 5:45 am |
|
|
Start with how much you have to write.
You can write as little as you want. The key is though, that a 'write', can only change the bits in the byte you write, from 'erased' to 'non erased'. So if you have a block that has been erased, you can write the first byte on it's own, and then go back later and write the third byte etc..
An _erase_, can only erase an entire block.
So to change a single bit in a block from 'non erased' to the erased state, you have to erase the entire block. If you want to keep the other bytes, you have to read the entire block, change the bit you want, erase the entire block, and write it all back.
Now you leave out a critical bit of data. Compiler version number?.
There were problems in various compiler versions, with not handling the internal memory, on various chips. So, you must always tell us the version, when asking this type of question.
As comments, you have both the internal oscillator selected (internal=4M), and the external crystal (HS). Also are you really using LVP?. 99.99% of programmers are not LVP, and having this selected can cause operational problems. The PicKit, is not an LVP programmer.
2A, is what AA becomes.....
The program memory, is just 14bits wide.
Code: |
xx11111111111111 - bits available
1010101010101010 - 0xAA 0xAA
0010101010101010 - result 0x2A 0xAA
|
You cannot store a 16bit value into the 14bit memory.....
Now you need to work slightly differently. The memory erases 32 words at a time, but only writes 8 words at a time. From the data sheet section 11.3. "flash memory must be written in eight-word blocks".
So you need to do four writes to fill the entire block. The CCS function is meant to automatically handle this, but do it yourself. |
|
|
scarey_4567
Joined: 06 Aug 2014 Posts: 5
|
|
Posted: Wed Aug 06, 2014 5:58 am |
|
|
Hi Ttelmah
Thanks for the help.
Compiler version is 4.131. I had read that some compilers have issues but I couldn't find any release notes/change lists on which ones might be defective.
I've removed the HS fuse instruction and changed LVP to NOLVP
The main functions now looks like this (writes 16 bytes, 4 times - I know it only ever uses the first 16 bytes of the data array)
Code: |
void main()
{
disable_interrupts(GLOBAL);
unsigned char data[64] = {0};
unsigned int i = 0;
for (i = 0; i < 64; i++)
{
data[i] = 0x2A;
}
write_program_memory(0x0400, data, 16);
write_program_memory(0x0408, data, 16);
write_program_memory(0x0410, data, 16);
write_program_memory(0x0418, data, 16);
} |
My understanding is that the first _write_ will erase the full 32 words but this code gives me the same result. Presumably that means the erase part of the _write_ function isn't doing it's job properly? |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Aug 06, 2014 7:40 am |
|
|
PLEASE save yourself more anxiety:
CAREFULLY read what Mr. T already explained.
you CAN'T just write any old data !!
first you need to do an
erase_program_eeprom( )
erasing makes ALL the bits=1
then the WRITE flips the ZERO state of your NEW data bits
on the block to be re written
ONLY after ERASE- THEN you can write.
if you are not erasing FIRST you will never make it happen...... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Wed Aug 06, 2014 7:51 am |
|
|
Unfortunately, I had a 'nasty suspicion', when it wasn't automatically wrapping the write, that yours was going to be a faulty version. :(
Took this:
Code: |
#include <16F1826.h>
#fuses NOWDT,NOWRT,NOPROTECT,NOCPD, NOBROWNOUT, NOLVP, PUT, MCLR
// setup delay timer source
#use delay(internal=4M)
void main()
{
unsigned char data[64] = {0};
unsigned char i = 0;
for (i = 0; i < 64; i+=2)
{
data[i] = 0xAA;
data[i+1] = 0x2A;
}
write_program_memory(0x0400, data, 64);
while (TRUE) ;
}
|
Tried it on 5.026, and nicely see 2AAA 2AAA etc. from 0x400.
Then ran it up on 4.141, and it gives the same problem you have.
Remember this coming up here some time ago. Do you have the IDE?.
It is an error in the device table for the older compiler version.
If you have the IDE, select 'Tools', 'Device Editor', and select your chip. Then in the centre window, open the 'memory' tab (click on the +). About 3/4 way down the entries for this, is one called 'Flash access'. This is set to 'PIC16 64/64', which means the compiler thinks it can write the whole 64 bytes in one go.
Click on this, and there is a 'pull down' menu. Right near the bottom, you want the entry 'PIC16 16/64'. Select this, then push the button 'save' at the top of the screen, and exit the device editor.
You should then find it'll correctly handle writing 64 bytes (automatically performing the four writes).
Have just done this change on 4.141, and it then merrily works.
If you don't have the device editor, ask CCS if they could send you a devices file with this fixed. I haven't 'kept' 4.131, or I could generate it for you. Just explain clearly that it is the flash access entry incorrectly set for this device. |
|
|
scarey_4567
Joined: 06 Aug 2014 Posts: 5
|
|
Posted: Wed Aug 06, 2014 7:58 am |
|
|
The CCS Help file says:
Quote: | write_program_memory() - Writes any number of bytes, bytes outside the range of the write block are not changed. No erase is needed. |
In my device, getenv(“FLASH_ERASE_SIZE”) = getenv(“FLASH_WRITE_SIZE”) so the 'erase_program_eeprom()' function isn't available - it's incorporated in the write. For the sake of argument, I tried using the function and I get an error that it's not recognised.
I understand the need to erase the block before I write anything but as far as I can see, the function write_program_memory() is supposed to be a do-it-all function.
[/b] |
|
|
scarey_4567
Joined: 06 Aug 2014 Posts: 5
|
|
Posted: Wed Aug 06, 2014 8:12 am |
|
|
Brilliant - thanks for your help. I think I'll buy the upgrade as that'll be quicker! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Wed Aug 06, 2014 9:30 am |
|
|
The problem isn't with the erase.
The problem is that the compiler 'thinks' there are 32 write latches (same as the erase size), but the chip only has 8.
So it sets all 32 latches, but only 8 words actually get written.... |
|
|
|
|
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
|