|
|
View previous topic :: View next topic |
Author |
Message |
jgschmidt
Joined: 03 Dec 2008 Posts: 184 Location: Gresham, OR USA
|
reading/writing to program memory problems |
Posted: Mon May 14, 2012 12:45 am |
|
|
Compiler: PCWH/PCD 4.130
Processor: 24HJ128GP202
I'm writing and reading from program memory. When I read back the data every 4th byte is 0x00. Am I doing something wrong or is this a bug in the compiler?
I've attached the minimum amount of code to demonstrate this:
Code: | #CASE
#include <24HJ128GP202.h>
#fuses NOWRTB //Boot block not write protected
#fuses NOBSS //No boot segment
#fuses NORBS //No Boot RAM defined
#fuses NOWDT //No Watch Dog Timer
#fuses PUT128 //Power On Reset Timer value 128ms
#fuses NOALTI2C //I2C mapped to SDA1/SCL1 pins
#fuses ICSP1 //ICD uses PGC1/PGD1 pins
#fuses NOJTAG //JTAG disabled
#fuses NODEBUG //No Debug mode for ICD
#fuses NOWRTSS //Secure segment not write protected
#fuses NOSSS //No secure segment
#fuses NORSS //No secure segment RAM
#fuses NOPROTECT //Code not protected from reading
#fuses PR_PLL //Primary Oscillator with PLL
#fuses IESO //Internal External Switch Over mode enabled
#fuses XT // Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#fuses NOOSCIO //OSC2 is clock output
#fuses NOIOL1WAY //Allows multiple reconfigurations of peripheral pins
#fuses CKSNOFSM //Clock Switching is enabled, fail Safe clock monitor is disabled
#use delay( clock=80M, xtal=10M )
// Setup Port IOs as all digital
#define AD1PCFGL_Def 0xffff;
//-----------------------------------------------------------------------------
//------ Hardware pin assignments ---------------------------------------------
//-----------------------------------------------------------------------------
#pin_select U1TX = PIN_B0 // Console
#pin_select U1RX = PIN_B1
#use rs232( baud=38400, UART1, ERRORS, stream=CONSOLE )
//-----------------------------------------------------------------------------
// pseudo-EEPROM stuff for write/read_program_eeprom()
// Used to save config info
//-----------------------------------------------------------------------------
#define EE_BUFFER_SIZE 64 // bytes
#define PROGRAM_MEMORY_SIZE getenv("PROGRAM_MEMORY")
#define EE_BUFFER_END (PROGRAM_MEMORY_SIZE - 1)
#define EE_BUFFER_START (PROGRAM_MEMORY_SIZE - EE_BUFFER_SIZE)
int32 eepromAddress; // pointer to address location to write
struct {
int8 exitDelay; // number of seconds to wait
int8 numSnaps; // default number of pictures to take
BYTE oldDir[14]; // oldest directory name
} camConfig;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void main ()
{
delay_ms( 100 );
fprintf(CONSOLE,"%s %s %s \r\n",__FILENAME__, __DATE__,__TIME__);
fprintf(CONSOLE, "MEMORY Locations: %ld %ld %ld \r\n",PROGRAM_MEMORY_SIZE, EE_BUFFER_START, EE_BUFFER_END);
// initialize structure
camConfig.exitDelay = 30;
camConfig.numSnaps = 10;
sprintf(camConfig.oldDir,"12345678.abc");
// write structure to program memory
eepromAddress = (int32)EE_BUFFER_START;
write_program_memory( eepromAddress, &camConfig, sizeof(camConfig) );
// fill structure with other data to be sure we are overwriting when we read program memory
camConfig.exitDelay = 8;
camConfig.numSnaps = 9;
sprintf(camConfig.oldDir,"abcdefgh.123");
fprintf(CONSOLE," %d %d >%s<\r\n",camConfig.exitDelay, camConfig.numSnaps, camConfig.oldDir);
// read program memory
eepromAddress = (int32)EE_BUFFER_START;
read_program_memory( eepromAddress, &camConfig, sizeof(camConfig) );
fprintf(CONSOLE," %d %d >%s<\r\n",camConfig.exitDelay, camConfig.numSnaps, camConfig.oldDir);
fprintf(CONSOLE,"Starting with 3rd byte in struct: %x %x %x %x %x %x %x %x %x %x %x %x %x\r\n", camConfig.oldDir[0], camConfig.oldDir[1], camConfig.oldDir[2],
camConfig.oldDir[3], camConfig.oldDir[4], camConfig.oldDir[5], camConfig.oldDir[6], camConfig.oldDir[7], camConfig.oldDir[8],
camConfig.oldDir[9], camConfig.oldDir[10], camConfig.oldDir[11], camConfig.oldDir[12]);
delay_ms( 100 );
} |
Which produces the following output:
pgm_mem.c 14-May-12 01:40:44
MEMORY Locations: 88064 88000 88063
8 9 >abcdefgh.123<
30 10 >1<
Starting with 3rd byte in struct: 31 0 33 34 35 0 37 38 2e 0 62 63 0
Thanks. _________________ Jürgen
www.jgscraft.com |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Mon May 14, 2012 1:44 am |
|
|
You say:
"When I read back the data every 4th byte is 0x00. Am I doing something wrong or is this a bug in the compiler?".
Neither.....
You need to understand that the program memory is _24bits wide_.
It is organised as (quote from data sheet):
"it is more appropriate to think of each address of the program memory as a lower and upper word, with the upper byte of the upper word being unimplemented."
Note the 'unimplemented'.
So you have a 32bit memory value, with the top 8 bits being 'unimplemented'.
So if you want to store values into the program memory, you need to handle breaking the values into 3byte pieces, and re-assembling these.
Best Wishes |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1348
|
|
Posted: Mon May 14, 2012 6:13 am |
|
|
Something else you want to pay attention to is how and where you write to Program Memory. In order to write to program memory, you need to do a page erase first, even if you don't plan on writing the whole page. Most pic24's if not all, have a page size of 0x400 words (0x800 bytes). you can get the value with:
#define PM_PAGE_SIZE (getenv("PAGE_ERASE_SIZE)/2) //words
Also note that write_program_memory() will do the erase for you if you write to the page address itself, which is a multiple of the PM_PAGE_SIZE
Additionally, since you are working with the last area of memory, you don't want to erase the last page of memory because that is where the program FUSES reside. You can manage this a couple ways. You can either manually specify the page or calculate it, and then do a page erase on it.
Code: |
#define PM_PAGE_SIZE (getenv("PAGE_ERASE_SIZE)/2) //words
#define PM_FUSE_ADDR getenv("PROGRAM_MEMORY")
#define PM_FUSE_PAGE_ADDR ((PM_FUSE_ADDR/PM_PAGE_SIZE)*PM_PAGE_SIZE)
//pick the PM page before the one using the fuses.
#define PM_EE_BUFFER_START (PM_FUSE_PAGE_ADDR-PM_PAGE_SIZE)
#define PM_EE_BUFFER_END (PM_FUSE_PAGE_ADDR-1)
#define PM_EE_BUFFER_SIZE PM_PAGE_SIZE
//make sure your code can't go into this space:
#org PM_EE_BUFFER_START,PM_EE_BUFFER_END {}
|
|
|
|
jgschmidt
Joined: 03 Dec 2008 Posts: 184 Location: Gresham, OR USA
|
|
Posted: Mon May 14, 2012 8:11 am |
|
|
I get it. Thanks for the great explanations. _________________ Jürgen
www.jgscraft.com |
|
|
|
|
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
|