PIC12F1501 - Help with writing & reading flash memory
For my project using PIC12F1501 microcontroller, I am using the NCO peripheral with which I need to pulse my underlying circuit at a certain frequency. However, the exact value of the NCO frequency depends on the underlying components and therefore need a calibration routine needs to be carried out to identify the NCO frequency.
So, I have built a calibration routine which is carried out once in lifetime of uC by using a GPIO input and it includes,
1. Sweep the NCO frequency
2. Find the suitable NCO frequency
3. Store the needed values (two 16bit values) in the FLASH memory
Once calibration is done, the normal routine takes place every time after power on which includes,
1. Read the (two 16bit values) from the FLASH memory
2. Set the NCO frequency according to the stored value
3. Do calculations
I used the MCC to fetch flash program read & write routines but the FLASH_WriteWord () needs a ramBuf which already consumes 32 bytes of data. Since the Data Memory is only 64 bytes, I am running out of space with other declarations. I tried to reuse the ramBuf, but wasnt successful.
I tried to edit FLASH_WriteWord() routines to try to accommodate the available Data Memory but still wasnt able to get it working and it is really painful to see that the FLASH_WriteWord is built to write 16 rows and takes so much space even for writing two words.
Can someone help with me a better memory optimized code?
Jeyakrishna Sridhar main.c
/* Definitions for RAM Memory Allocation */ memory.c
uint16_t ramBuf[WRITE_FLASH_BLOCKSIZE]; // Needed for writing block
/* Reusing ramBuf */
#define StartFreq ramBuf
#define PWMSweep ramBuf
#define VGain_Freq ramBuf
#define FreqStep ramBuf
#define Calib_DONE ramBuf
/* Constants initialization */
StartFreq = 65529; // start at 999 kHz
FreqStep = 655; // Freq step of 10 kHz
/* Supporting variables */
PWMSweep = StartFreq;
VGain_Freq = 0;
// Find the maximum ADC value in a given frequency sweep and write the value for NCO in Flash
NCO1INCH = PWMSweep >> 8; // Load values to NCO register
NCO1INCL = PWMSweep & 0xFF;
if ( ADC_GetConversion(3) <= VGain_Freq)
PWMValue = PWMSweep;
PWMValue = ADC_GetConversion(0);
VGain_Freq = ADC_GetConversion(3);
PWMSweep = PWMSweep - FreqStep;
FLASH_WriteWord(NCOFreq_addr, ramBuf, PWMValue); // Write Values to Flash
Calib_DONE = 0x01; // Set this so that the calibration is done only once.
PWMValue = FLASH_ReadWord(NCOFreq_addr);
PWMValue = FLASH_ReadWord(NCOFreq_addr+1);
NCO1INCH = PWMValue >> 8;
NCO1INCL = PWMValue & 0xFF;
Freq_read = 0x01; // Set this when the frequency is read once.
if ( EN_CALIB_GetValue() == 0) // Calibration mode
if ( (Calib_DONE & 0x01) != 1) // If calibration is not done, call calibrate function.
else // Normal operation mode
if ((Freq_read & 0x01) != 1) // If frequency is not read, call calibrate function.
/*In memory.c, I changed the routine FLASH_WriteWord to accept a word array of size 2 so that 2 words of consecutive address are written. I am not sure if i can share */
void FLASH_WriteWord(uint16_t flashAddr, uint16_t *ramBuf, uint16_t *word)
uint16_t blockStartAddr = (uint16_t)(flashAddr & ((END_FLASH-1) ^ (ERASE_FLASH_BLOCKSIZE-1)));
uint8_t offset = (uint8_t)(flashAddr & (ERASE_FLASH_BLOCKSIZE-1));
// Entire row will be erased, read and save the existing data
for (i=0; i<ERASE_FLASH_BLOCKSIZE; i++)
ramBuf[i] = FLASH_ReadWord((blockStartAddr+i));
// Write at offset
ramBuf[offset] = word;
ramBuf[offset+1] = word;
// Writes ramBuf to current block