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 support@ccsinfo.com

write_program_memory PIC10F322
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
viki2000



Joined: 08 May 2013
Posts: 233

View user's profile Send private message

PostPosted: Tue Feb 25, 2014 7:31 am     Reply with quote

@amarquez

Did you finally mange to write/read from flash memory as EEPROM?
I use the same PIC10F322 and I want to save in 4 or more locations, thinking also at User ID with 4 empty memory locations.
But flash memory would give me the possibility to store more.

Do you have the final C code that you tried?
Could you publish it?

The fact is, that I already have 80% flash memory used for the program.
If the subroutines for flash memory or User ID takes more than 15%-20% of flash, then is not good for me.

Could you please tell me how much flash memory requires the program to read/write to flash memory or User ID?
Ttelmah



Joined: 11 Mar 2010
Posts: 19260

View user's profile Send private message

PostPosted: Tue Feb 25, 2014 10:47 am     Reply with quote

Worth testing the latest compiler.
On a new PIC12, which has similar unlock requirements, the unlock/write code wasn't working a couple of releases ago, but does now.
Key thing is that with all these, you have to read the page, modify this in RAM, and then write to the page boundary (to trigger an erase).

Best Wishes
Ttelmah



Joined: 11 Mar 2010
Posts: 19260

View user's profile Send private message

PostPosted: Wed Feb 26, 2014 5:39 am     Reply with quote

There is a real 'problem' with the flash memory on these chips.

The manufacturer tells us it does have 'high endurance flash', as the low byte, of each word at the top of the program memory (0x1F8 to 1FF, or F8 to FF for the 320), but this corresponds to just eight high endurance bytes, and you have to erase 16 words to use it. So you potentially lose 1/16th the ROM on the smaller chip, and 1/32th ROM on the larger, to allow just 8 bytes to be stored!. Even if you ignore this, and just use the whole 16 low bytes of the page, with lower durability, it is such a large slice of the RAM needed to buffer this.
The CCS code seems still to not work. I suspect because of the extra complexity of their 'generic' routines, they are very tight on size to actually fit!. The read routine seems to be OK.
If you keep RAM down to a small size for just 8 bytes (say), and trigger the erase manually, when you update the eight bytes, then you have:
Code:

#include <10F322.h>
#FUSES NOWDT                   
#FUSES NOBROWNOUT         
#FUSES NOLVP                   
#use delay(internal=4000000)
#define ADDRESS_TO_USE_FOR_STORAGE 0x1F8 //This is the high endurance flash - 0xF8 for 10F320
#define BYTES_TO_USE 8 //Key is that the high endurance flash is 8 * bytes only low bytes in word only

#ROM int16 ADDRESS_TO_USE_FOR_STORAGE = {1,2,3,4,5,6,7} //Preload the HEF
//studying the assembler suggest the supplied memory write/erase functions still won't work.
//rewrite trimmed versions of these....
int8 buffer[BYTES_TO_USE]; //buffer for HEF

#byte PMADRH=getenv("SFR:PMADRH")
#byte PMADRL=getenv("SFR:PMADRL")
#bit CFGS=getenv("BIT:CFGS")
#bit WREN=getenv("BIT:WREN")
#bit LWLO=getenv("BIT:LWLO")
#bit FREE=getenv("BIT:FREE")
#byte PMDATL=getenv("SFR:PMDATL")
#byte PMDATH=getenv("SFR:PMDATH")
#byte PMCON2=getenv("SFR:PMCON2")
#bit WR=getenv("BIT:WR")
#bit RD=getenv("BIT:WR")
//#byte FSR0=getenv("SFR:INDF0")
#define delay_2() delay_cycles(1);delay_cycles(1) //two nops
#bit GIE=getenv("BIT:GIE")

#define UNLOCK()    PMCON2=0x55; PMCON2=0xAA; WR=TRUE; delay_2() //chip unlock sequence

#define select_address(add) CFGS=FALSE;PMADRL=make8(add,0);PMADRH=make8(add,1) //load address

void erase_row(int16 address) //erases the row containing 'address'.
{
   disable_interrupts(GLOBAL); //ensure interrupts are off
   select_address(address & 0x1F0); //select page
   FREE=TRUE;
   WREN=TRUE;
   UNLOCK(); //Perfrom the actual erase
   WREN=FALSE;
   enable_interrupts(GLOBAL);
}

void write_block(int8 *ram, int8 ctr, int16 address)
{
   //function to replace non working write
   //Warnings....
   //Writes 'ctr' bytes to the _low_ byte only of the memory block starting at 'address'
   //Must fit inside a row. No testing done to ensure this (keep space small...)
   disable_interrupts(GLOBAL); //ensure interrupts are off
   
   select_address(address);
   LWLO=TRUE;
   WREN=TRUE;
   FREE=FALSE;
   //Now need to load the latches
   do
   {
      PMDATH=0;
      PMDATL=*ram;
      ram++; //next byte
      if (--ctr==0) break;
      UNLOCK();
      PMADRL++; //Next word
   }
   while (TRUE);
   //Now all but last latch loaded
   LWLO=FALSE; //switch to physical write
   UNLOCK(); //and write the data
   WREN=FALSE;
   enable_interrupts(GLOBAL); 
}

void save_HEF(void) //copies the 8 HEF bytes to RAM buffer
{
   int16 address;
   //now read the max 8 HEF bytes
   for (address=0;address<BYTES_TO_USE;address++)
   {
      buffer[address]=read_program_eeprom(address+ADDRESS_TO_USE_FOR_STORAGE);
   }
}

void write_HEF(void)
{
   //Uses my replacement functions to write the 8 HEF bytes to ROM
   erase_row(ADDRESS_TO_USE_FOR_STORAGE); //erase entire row
   write_block(buffer,8,ADDRESS_TO_USE_FOR_STORAGE); //write the 8 HEF bytes
}

void main()
{
   while(TRUE)
   {
      save_HEF();
      //Now buffer contains the bytes from the HEF
      //Now modify, and try writing.
      buffer[2]=34;
      buffer[4]=56;
      buffer[7]=78;
      write_HEF();
      do {
      }
      while (TRUE); //stop here, don't want to write more than once...
   }
}

The code is 'pointless', but shows attempting to read the eight bytes from the HEF, change them, and write them back.

No guarantees, haven't got one of these chips at the moment to try.

You can reduce the number of bytes by reducing 'bytes to use'.
You can also increase this, but then the address would have to go down to 0x1F0, and you are no longer writing to the high endurance memory.
Obviously more bytes used, the larger the buffer. Max 16ytes. Remember also the code does not check the boundaries of the page, so with 0x1F0, 8 bytes max, or you will corrupt data....

Takes less than 30% ROM and RAM.

Worth also saying, that the problem with the 'user ID' memory, is it is the same page as the fuses. You have to save all these if you want to change the ID bytes, and if the power is lost after the erase, the chip will become un-bootable....

Best Wishes
viki2000



Joined: 08 May 2013
Posts: 233

View user's profile Send private message

PostPosted: Wed Feb 26, 2014 7:12 am     Reply with quote

Thank you very much for the above information. It is really helpful.
There are few more details.
My intention is to measure and store the temperature of the chip as min, max, avg. Then after long time to check these values. They are useless to me if I cannot check them later after few weeks or years outside the PIC.
Additional I want to protect the code with CP bit.
I was thinking to send these 3 values of temperature at 1 pin in a serial mode, regularly. Then I can protect the code and still know the variables stored in the non-volatile memory.
The main problem that may appear is that I do not have control over the PIC power in a real application, that means may be lost anytime. That looks dangerous if the power disappear random and with bad luck is just in a middle of write moment. I need to save some bytes in non-volatile memory each 1 hour.
And the PIC has no idea when its power will be lost. I am not so sure I understand how can I protect the PIC against such situation by avoiding to end in a non-bootable chip or with wrong code inside. Could you develop a bit more the idea.

Because 4 memory locations might be enough for me, I still think at User ID.
The MPASM help speaks about "__idlocs" which seems easier to be used when I write in User ID. And hopefully takes less memory, as I already used 70-80% of flash.
There are only 2 things unclear:
- what do I use to read from User ID in RAM? Only ASM code as the one posted by you or from datasheet?
- what happens with the PIC if it loses the power right when is writing in User ID memory locations? It will really become an unusable non-bootable PIC for the given application somewhere in the field, which means a non-working application?
In my application, the PIC10F322 has also some other functions besides measuring the temperature.
temtronic



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

View user's profile Send private message

PostPosted: Wed Feb 26, 2014 7:38 am     Reply with quote

re: PIC lose power during eeprom writing.
The normal hardware solution to this problem is to have enough 'energy' stored to allow the PIC to complete 'housekeeping'(save data) after it detects 'loss of power'.How large a 'reserve' will have to be determined by you as well as how it's stored. You might require say 50ms after power failure ,so maybe a 'supercap' will do.Perhaps a NiMh battery or coincell is better, depending on application.
Power failure can either be detected by hardware or software, and of course, software has to ensure a 'neat and orderly' power down sequence AND proper 'power up/restored' as well.
If the PIC powersupply is fed from line voltage, typically you use a zerocross detector and timer combination.No AC for xx ms = power failure, execute 'power down mode'.
As there are several ways to do this, it's your choice as you control the project.

hth
jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19260

View user's profile Send private message

PostPosted: Wed Feb 26, 2014 8:47 am     Reply with quote

Remember just how little power the chip can use. The problem is (of course) that you need some way of 'knowing' that power will stay good, or is going off. Realistically means a pin. Though there are possibly 'sneaky' ways of sensing depending on your circuit.

If you only want four bytes, just change the 'BYTES_TO_USE' value to 4 above. The ROM usage will be 16words more than using the ID locations, but the RAM usage will be the same.

Remember also that the ID memory, only has 'normal' write life. The point about the HEF bytes is they have over 10* the durability. They are designed for repeated writing.

With the HEF bytes, you can enable CP so the code cannot be read by an external programmer, and then enable write protection on the low half of the memory 0x000 to 0xFF. Still allows the HEF bytes to be written and read by the code.

Writing to the configuration memory, is slightly different, than the program memory, and exiting this will be a little more work.

If you want to read the User ID with MPLAB for instance, it only return 7bit values from the registers. Might be a problem?.

Best Wishes
viki2000



Joined: 08 May 2013
Posts: 233

View user's profile Send private message

PostPosted: Wed Feb 26, 2014 10:05 am     Reply with quote

"If you want to read the User ID with MPLAB for instance, it only return 7bit values from the registers. Might be a problem?. "

YES. That is a problem. I need minimum 8 bits or if is possible 14bits, because I understood that User ID are memory locations which holds 14 bits each one.
I prefer to send them serial to one pin. I already have the code for that. I only need to write and read from RAM to User ID with the smallest code as possible.

Regarding random power off:
- actually the application works with AC sinus and detects zero-cross moments. I already know the zero-cross moments in the existing code.
- I cannot add additional capacitors or batteries, but I have now a 10uF capacitor right at the power pins of the PIC. I just need to measure how long time the voltage is kept within acceptable limits for the PIC after power off moment. I guess an oscilloscope would do the job. Any other ideas?
Ttelmah



Joined: 11 Mar 2010
Posts: 19260

View user's profile Send private message

PostPosted: Wed Feb 26, 2014 11:53 am     Reply with quote

If you are detecting zero crossing then it is fairly easy. If there has not been a crossing detected in the last 1/80th second (say), don't start a write.
The memory locations themselves are 14bit, but if using programmers through MPLAB, you only see 7bit. They assume the ID will be _text_. You can use the whole size.

The code I posted can be modified to do ID location writing (CFGS bit needs to change), but the exit code at the end of the routine is more complex. Read the notes about this.
viki2000



Joined: 08 May 2013
Posts: 233

View user's profile Send private message

PostPosted: Thu Feb 27, 2014 1:39 am     Reply with quote

I use now MPLABX v2.00. Just have a look at the next picture.

http://i926.photobucket.com/albums/ad102/viki2000/Microchip/UserID_zps09613716.jpg

If I go Windows-PIC Memory Views-User ID Memory, then I see at the bottom location 2000 with 0x7F7F7F7F
On some forums, some people complaint that it would be a bug in MPLABX that shows only location 2000 and not the other 3 (2001, 2002, 2003).
But actually we see repeated "7F" 4 times which is maybe equivalent with 4 memory locations and the MPLABX displays only the start address.
Am I wrong?
If not and is true, then we have for one memory location 7F which is "1111111", so 7 times "1".
Because 0x7F7F7F7F is "1111111011111110111111101111111" and that cannot be stored in one memory location.
So, why do I see only 7 bits in MPLABX as you mentioned first time?
viki2000



Joined: 08 May 2013
Posts: 233

View user's profile Send private message

PostPosted: Thu Feb 27, 2014 2:21 am     Reply with quote

I see it now.

From here on page 6:
http://ww1.microchip.com/downloads/en/DeviceDoc/41572D.pdf

we read next:
http://i926.photobucket.com/albums/ad102/viki2000/Microchip/UserID_2_zpsa2c73230.jpg
viki2000



Joined: 08 May 2013
Posts: 233

View user's profile Send private message

PostPosted: Thu Feb 27, 2014 4:24 pm     Reply with quote

I have a question which derives from wearing the flash memory (limited number of writings).
In my code I use the same pin sometimes as analog input and sometimes as digital output.
Another situation is that I use 2 pins as analog input, but inside the PIC10F322 there is only one analog to digital converter which has attached a multiplexer at input to select different inputs, which means only one input can be converted analog to digital at a certain moment.
When I need to switch between all these settings in real time as from one pin to another for AD or the type of pin as input or output, digital or analog or pwm or whatever, then I set some bits in some registers.
The question is:
- Is it any limitation how many times I set those registers?
- Or is nothing like flash memory wearing limited at 100000 times?
For example, in my case I change the nature of one pin 100 times per second. During each 10ms the pin becomes analog input and after 5ms becomes digital output with rectangular signal of 10KHz, then after few more ms, another pin is set as analog input, then later everything is set as it was first time and the cycle starts again.
- Should I worry about these switching or are normal?
Ttelmah



Joined: 11 Mar 2010
Posts: 19260

View user's profile Send private message

PostPosted: Fri Feb 28, 2014 1:54 am     Reply with quote

No limitation. They are just RAM. There probably is a limitation (when you switch it'll make more electrons flow around particular bits of the circuit), you we are talking billions of years, rather than a few thousand cycles. Smile

Best Wishes
viki2000



Joined: 08 May 2013
Posts: 233

View user's profile Send private message

PostPosted: Sat Mar 29, 2014 3:24 pm     Reply with quote

PCM programmer wrote:
There are bugs in the flash memory read/write routines. Are you sure
you want to do this ? Because if you type in the routines from the 10F322
data sheet, you might use a considerable portion of the Flash memory
that is available. These are small PICs, with only 512 words of Flash.

I wrote a little program to test reading a word from Flash. If you are
just playing around, I don't think it's worth the effort to finish all the
routines. Or at least, it may not be worth my effort.

But the following program does work. It displays "1234" on the TeraTerm
window on my PC. I have pin A2 connected to a Max232 chip, which
then connects to the PC with a cable. This was tested with vs. 4.135.
There also appear to be some problems with printf displaying control
characters and strings. I just used putc() to do the CR and LF chars.
Code:

#include <10F322.H>
#fuses INTRC,NOWDT,BROWNOUT,PUT,MCLR
#use delay(clock=4M)
#use rs232(baud=9600, xmit=PIN_A2)

#define FLASH_ADDR  0x1F0  // Use last 16 words of flash for testing

// Initialize the test area in flash to all 0's when
// the PIC is programmed.
#rom FLASH_ADDR = {0x1234,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} 


#byte PMADRL = 0x20
#byte PMADRH = 0x21
#byte PMDATL = 0x22
#byte PMDATH = 0x23
#byte PMCON1 = 0x24
#byte PMCON2 = 0x25

#bit  RD     = PMCON1.0
#bit  WR     = PMCON1.1
#bit  CFGS   = PMCON1.7

int16 read_program_word(int16 addr) 
{
int16 retval;

PMADRL = addr;       
PMADRH = addr >> 8; 
CFGS = 0;           
RD   = 1;           
#asm nop #endasm
#asm nop #endasm
retval = make16(PMDATH, PMDATL);
return(retval);
}

//====================================
void main(void)
{
int16 result;

result = read_program_word(FLASH_ADDR);
printf("%lx ", result);

putc(0x0d);
putc(0x0a);

while(1);
}


I would like to use a similar code as above in similar manner with next changes:
- I will use a pin for bing-banging (I already have and use the code) to communicate with another PIC16F88 which has an LCD attached to it. Later maybe I will attach MAX232 for PC serial port communication.
- I need to read the User ID memory.
- I write in User ID during programming time using MPLABX and PicKit3.

The questions that I have:
- how do you modify the code above in a simple manner to read the location memory 2000h to 2003h, which are User ID and read the LSB, 7 bits of each memory, because that is what I can read later as double-check with the MPLABX, even if the code is protected.
- In fact I am interested how do you read from User ID in RAM memory variables.
Once I have the values in RAM in some variables, I know how to send them out to LCD or PC.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Mar 29, 2014 8:35 pm     Reply with quote

Read this section of the 10F320 data sheet. It has sample code to
do what you want:
Quote:
9.4 User ID, Device ID and Configuration Word Access

http://ww1.microchip.com/downloads/en/DeviceDoc/40001585B.pdf

You don't have to do the BANKSEL as shown in the sample code.
CCS will handle setting the correct register bank.
viki2000



Joined: 08 May 2013
Posts: 233

View user's profile Send private message

PostPosted: Sun Mar 30, 2014 2:10 pm     Reply with quote

I thought that is a simple function as in example from page 188-189 in HI-TECH C Compiler user manual:
http://ww1.microchip.com/downloads/en/DeviceDoc/HTC_PIC_manual.pdf

DS51865A-page 189
Example

Code:
#include <htc.h>
void
main (void)
{
unsigned int data;
unsigned short address=0x1000;
data = flash_read(address);
flash_erase(address);
}

Return Value
flash_read() returns the data found at the given address, as an unsigned int.

I had in mind that replacing "unsigned short address=0x1000;" with "unsigned short address=0x2000;" I can read the User ID first memory location.

What about READ_PROGRAM_MEMORY function from page 259:
https://www.ccsinfo.com/downloads/ccs_c_manual.pdf

In fact, maybe to use read_program_eeprom( ) from page 261 link above.
Here was also a discussion:
http://www.ccsinfo.com/forum/viewtopic.php?t=27206&view=next
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3  Next
Page 2 of 3

 
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