CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

write_program_memory doesn't work

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
scarey_4567



Joined: 06 Aug 2014
Posts: 5

View user's profile Send private message

write_program_memory doesn't work
PostPosted: Wed Aug 06, 2014 4:36 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Aug 06, 2014 5:37 am     Reply with quote

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: 19552

View user's profile Send private message

PostPosted: Wed Aug 06, 2014 5:45 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Aug 06, 2014 5:58 am     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Wed Aug 06, 2014 7:40 am     Reply with quote

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: 19552

View user's profile Send private message

PostPosted: Wed Aug 06, 2014 7:51 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Aug 06, 2014 7:58 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Aug 06, 2014 8:12 am     Reply with quote

Brilliant - thanks for your help. I think I'll buy the upgrade as that'll be quicker!
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Wed Aug 06, 2014 9:30 am     Reply with quote

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....
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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