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

Flash write problem

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



Joined: 05 Aug 2014
Posts: 24

View user's profile Send private message

Flash write problem
PostPosted: Thu Dec 13, 2018 1:42 pm     Reply with quote

HI Guys
Maybe someone can point me in the right direction here.
I'm upgrading a Pic 12F675 to 12F1571.
But having problems with the flash write.
I'm using the write_program_memory(i, value, 2); and its not working.
I can see in the list file that it is not compiling for the unlock sequence.
i.e. write 55 the write AA etc..
Does the CCS compiler handle this or do I need to write the code myself?
Am I using the wrong command?
using compiler V5.074
_________________
Neville
temtronic



Joined: 01 Jul 2010
Posts: 9241
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Dec 13, 2018 1:58 pm     Reply with quote

you should post your program ( use code 'buttons...) so we can see what you're trying to do.
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Fri Dec 14, 2018 1:16 am     Reply with quote

Remember that unless you get rid of the #nolist at the start of the processor
include file, the CCS 'internal' code for core functions will not be shown in
the listing.
Also you must always say 'what compiler version' for a question like this.

I just put together a minimum test on the current compiler (5.081):
Code:

#include "12F1571.h" //using local copy with nolist removed
#device ADC=10
#fuses NOMCLR
#fuses NOLVP
#use delay(internal=4000000)

void main()
{
   char test[16] = "Test message";
   
   write_program_memory(0x200,test,16);   
   //Horrid will write every time chip boots.
   
   while(TRUE)
   {
   }
}


and in the listing, at the start of the write code (once it has loaded the
data latches), it calls address 3:
Code:

0003:  MOVF   INTCON,W
0004:  MOVWF  @78 //save interrupt status
0005:  BCF    INTCON.GIE  //disable interrupts
0006:  MOVLB  03 //bank 3
0007:  MOVLW  55  //first unlock byte
0008:  MOVWF  PMCON2
0009:  MOVLW  AA //second unlock byte
000A:  MOVWF  PMCON2
000B:  BSF    PMCON1.WR //now trigger write
000C:  NOP
000D:  NOP
000E:  BTFSC  PMCON1.WR //loop till write completes
000F:  GOTO   00E
0010:  BCF    PMCON1.WREN //turn off write enable
0011:  MOVF   @78,W
0012:  IORWF  INTCON,F //re-enable interrupts
0013:  MOVLB  00
0014:  RETURN


So the compiler is generating the unlock correctly.

Remember you cannot just write to a byte, like EPROM. The flash memory
is in pages (32 bytes). If you want to write a byte that is not at the start
of a page, you have to read the whole page, modify the single byte, and
write the whole page back. A write to a byte in the middle of a page, will
happen, but can only change bits from '1' to '0'. So if byte 5 in a page was
(say) 0xAA, and you wrote 0x11, the result would be 0x00!...
The page will be erased if you write to the first byte in a page, so if you
are (for example) storing some configuration data, then lay this out as
a single entity, and always write it to the start of the page. Remember
that the 'odd' bytes only have 6 bits available to use though...

As a further comment, unless 'value' is an array, your calling syntax is
wrong. You need to pass the address of the memory you want to transfer
so if 'value' is an int16, you need:

write_program_memory(i, &value, 2);

to pass the address of 'value'. This may well be why you think it is not
working....
Nevillestone



Joined: 05 Aug 2014
Posts: 24

View user's profile Send private message

Flash write problem
PostPosted: Sat Dec 15, 2018 1:36 am     Reply with quote

HI temtronic
Thank for your suggestion.
Tried them still no luck.

I'm trying to write 1 byte into flash for configuration purposes will do the erase once I have the code working.

My compiler version is 5.074

Here is my test code similar to yours but changed the string to a int16:
Code:

void main()
{
    Value=0x66;
   
  write_program_memory(0x0380, &Value, 2);     
   //Horrid will write every time chip boots.
   
    while (TRUE) {

        //Example program using Tick Timer
        CurrentTick = get_ticks();
}
}


The list
Code:

.................... { 
....................     Value=0x66;
00DC:  MOVLB  00
00DD:  CLRF   2B
00DE:  MOVLW  66
00DF:  MOVWF  2A
....................     
....................   write_program_memory(0x0380, &Value, 2);     
00E0:  MOVLW  03
00E1:  MOVLB  03
00E2:  MOVWF  12
00E3:  MOVLW  80
00E4:  MOVWF  11
00E5:  MOVLW  20
00E6:  MOVWF  05
00E7:  MOVLW  0A
00E8:  MOVWF  04
00E9:  MOVLW  02
00EA:  MOVLB  00
00EB:  MOVWF  2F
00EC:  GOTO   015
....................    //Horrid will write every time chip boots.
 

AS you can see still no unlock code
# nolist disabled
_________________
Neville
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Sat Dec 15, 2018 4:39 am     Reply with quote

Yes there is...

The 'goto 015', jumps to the physical 'write' code.

What you are posting, is the code that loads the value to save, the address
and the count, ready to call the write function.
The write itself is down at address 015.

If you compile in 'symbolic' mode, this is made much clearer:
(Using 5.074)
Code:

....................    write_program_memory(0x380,&Value,2);   
007C:  MOVLW  03
007D:  MOVLB  03
007E:  MOVWF  PMADRH
007F:  MOVLW  80
0080:  MOVWF  PMADRL
0081:  MOVLW  value+-1
0082:  MOVWF  FSR0H
0083:  MOVLW  value+-32
0084:  MOVWF  FSR0L
0085:  MOVLW  02
0086:  MOVLB  00
0087:  MOVWF  @WRITE_PROGRAM_MEMORY.P2
0088:  GOTO   @WRITE_PROGRAM_MEMORY

It's loading the address where the write is to go, then the FSR registers
with where it is to come 'from', loading the W register with the count, and
then jumps to the actual write routine.

The write routine itself is about 4* the size of this code, and has the unlock
sequence.
Nevillestone



Joined: 05 Aug 2014
Posts: 24

View user's profile Send private message

Flash write problem
PostPosted: Mon Dec 17, 2018 1:59 am     Reply with quote

Thanks for the detailed reply.
However your code does not fill address 0x380-038F with the message if you simulate the code. (or address 0x200 tried both in the MPLABX simulator and on a chip).
I'm compiling from within MPLABX V4.05'
CCS Compiler V5.074.
I'm looking in the program watch window.

The code I'm compiling:
Code:

#include<C:\Users\Neville\Documents\Stoneage\mplabpj\Flash\flash1571.>

void main()
{
   char test[16] = "Test message";
   
   write_program_memory(0x200,test,16);   
   //Horrid will write every time chip boots.
   
   while(TRUE)
   {
   }
}

Is there any sample code that works ? I can't find any.
_________________
Neville
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Mon Dec 17, 2018 6:40 am     Reply with quote

OK. Though the unlock is working, the actual write is not.
This gives a basic erase/block write of a 16byte area, and should get you going:
Code:

#include "12F1571.h"
#device ADC=10
#fuses NOMCLR
#fuses NOLVP
#fuses NOWDT
#use delay(internal=4000000)

#byte PMADRL=getenv("SFR:PMADRL")
#byte PMADRH=getenv("SFR:PMADRH")
#byte PMCON1=getenv("SFR:PMCON1")
#byte PMCON2=getenv("SFR:PMCON2")
#byte PMDATL=getenv("SFR:PMDATL")
#byte PMDATH=getenv("SFR:PMDATH")
#bit CFGS=PMCON1.6
#bit FREE=PMCON1.4
#bit LWLO=PMCON1.5
#bit WREN=PMCON1.2
#bit WR=PMCON1.1

void unlock_wr(void)
{
   //unlock and trigger write
   PMCON2=0x55;
   PMCON2=0xAA;
   WR=1;
   delay_cycles(1);
   delay_cycles(1); //NOP
   WR=0;
}

//This writes a block of 16bytes to the flash memory
void write_program_mem(int16 address, int8 * data)
{
   int8 ctr=16;
   //Basic memory erase/write 16 byte block
   disable_interrupts(GLOBAL);
   //first erase row
   PMADRL=make8(address,0) & 0xF0; //page boundary address
   PMADRH=make8(address,1);
   CFGS=0;
   FREE=1;
   WREN=1;
   unlock_wr(); //This will force an erase
   WREN=0;
   //now write 16 bytes (must be even number))
   CFGS=0;
   PMADRL=make8(address,0);
   PMADRH=make8(address,1);
   FREE=0;
   WREN=1;
   do
   {
      ctr-=2; //2 bytes at a time       
      LWLO=(ctr != 0); //loads LWLO with 1 except on last loop
      PMDATL=*data; //load data
      data++;
      PMDATH=*data; //second byte
      data++;
      unlock_wr(); //This write just sets the latches, except on last loop
      PMADRL++; //next address
   } while (ctr); //and loop
   WREN=0; //turn off write
   enable_interrupts(GLOBAL);
}

void main()
{
   char test[16] = "Test message";
   //remember alternate bytes of this will lose their top 2 bits

   //Horrid will write every time chip boots.
   write_program_mem(0x200,test);
   while(TRUE)
   {
   }
}
Nevillestone



Joined: 05 Aug 2014
Posts: 24

View user's profile Send private message

Flash write problem
PostPosted: Mon Dec 17, 2018 12:49 pm     Reply with quote

Thanks
it workes...
However it seems we are going backwards when we have to start coding in assembler after we have paid for a C compiler.
_________________
Neville
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Mon Dec 17, 2018 1:02 pm     Reply with quote

Not a single line of assembler there. Just C.

In fact the issue is a one line slip in the CCS code. I've reported it to them
and hopefully a fix will appear shortly. Basically they are setting the 'FREE'
bit during the code that is meant to perform the write. This results in the
cells being erased instead of 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