simple_flash_example.cΒΆ
A simple example of run time self programming - reads/writes a single 16-bit value to flash.
#include "pic24_all.h"
#include <stdio.h>
#if (defined(__PIC24F__) || defined(__PIC24E__) || defined(__dsPIC33E__))
# warning "For all PIC24F and some PIC24E/dsPIC33E family members, the DATA_FLASH_PAGE is set to the second to last flash page instead of the last page,"
# warning "as the last flash page in the 24F family contains the configuration bits."
#endif
#if defined(__PIC24HJ64GP502__) || defined(__PIC24FJ64GA002__)
# define LAST_IMPLEMENTED_PMEM 0x00ABFF
#elif defined(__PIC24HJ32GP202__) || defined(__PIC24FJ32GA002__) || defined(__dsPIC33FJ32GP202__)
# define LAST_IMPLEMENTED_PMEM 0x0057FF
#elif defined(__dsPIC33FJ128GP802__)
# define LAST_IMPLEMENTED_PMEM 0x0157FF
#elif defined(__PIC24EP64GP202__) // test PIC24E device
# define LAST_IMPLEMENTED_PMEM 0x00AFFF
#elif defined(__dsPIC33EP64GP502__) || defined(__dsPIC33EP64GP503__) || defined(__dsPIC33EP64GP504__) || defined(__dsPIC33EP64GP506__)
# define LAST_IMPLEMENTED_PMEM 0x00AFFF
#elif defined(__dsPIC33EP128GP502__) || defined(__dsPIC33EP128GP504__) || defined(__dsPIC33EP128GP506__)
# define LAST_IMPLEMENTED_PMEM 0x0157FF
#elif defined(__dsPIC33EP256GP502__) || defined(__dsPIC33EP256GP504__) || defined(__dsPIC33EP256GP506__)
# define LAST_IMPLEMENTED_PMEM 0x02AFFF
#elif defined(__dsPIC33EP512GP502__) || defined(__dsPIC33EP512GP504__) || defined(__dsPIC33EP512GP506__)
# define LAST_IMPLEMENTED_PMEM 0x0557FF
#else
# error "Define LAST_IMPLEMENTED_PMEM for your processor!"
#endif
//calculate starting address of a flash page to store data
//some PIC24H/dsPIC33 store configuration bits on last page, so skip that
#if (defined(__PIC24F__) || defined(__PIC24E__)|| defined(__dsPIC33E__))
# define DATA_FLASH_PAGE (((LAST_IMPLEMENTED_PMEM/FLASH_PAGESIZE)*FLASH_PAGESIZE)-FLASH_PAGESIZE) //2nd to last page of flash
#endif
#if (defined(__PIC24H__) || defined(__dsPIC33F__))
# define DATA_FLASH_PAGE ((LAST_IMPLEMENTED_PMEM/FLASH_PAGESIZE)*FLASH_PAGESIZE) //last page of flash
#endif
typedef struct _REC {
uint16_t u16_val; //single 16-bit value
} REC;
#define NUM_ROWS (((sizeof(REC))/FLASH_ROWBYTES) + 1)
#define FLASH_DATA_SIZE (NUM_ROWS*FLASH_ROWBYTES)
typedef union _UFDATA {
REC dat;
char fill[FLASH_DATA_SIZE]; //worst case allocates extra row, but ensures RAM data block is multiple of row size
} UFDATA;
UFDATA fdata;
void doCommit(UFDATA* p_ufdata) {
union32 u_memaddr;
u_memaddr.u32 = DATA_FLASH_PAGE;
doWritePageFlash(u_memaddr, (uint8_t *) p_ufdata, FLASH_DATA_SIZE);
}
void doRead(UFDATA* p_ufdata) {
union32 u_memaddr;
u_memaddr.u32 = DATA_FLASH_PAGE;
doReadPageFlash(u_memaddr, (uint8_t *) p_ufdata, FLASH_DATA_SIZE);
}
uint8_t printMenu() {
printf("1 Read 16-bit value from flash.\n");
printf("2 Write 16-bit value to flash. \n");
printf(" Enter number (1-2): ");
return inCharEcho();
}
void doMenu() {
uint8_t u8_c;
char data[32];
uint16_t u16_val;
u8_c = printMenu();
printf("\n");
switch(u8_c) {
case '1':
doRead(&fdata);
printf("The 16-bit value read from memory is: %u (%x hex)\n",fdata.dat.u16_val,fdata.dat.u16_val);
break;
case '2':
printf("Enter 16-bit value+\\n (0 to 65535, decimal): ");
inStringEcho(data,31);
sscanf(data,"%d", (int *) &u16_val);
fdata.dat.u16_val = u16_val;
doCommit(&fdata); //write the data
break;
}
}
int main (void) {
configBasic(HELLO_MSG);
while(1) {
doMenu(1);
} //end while
}//end main