• AVR Freaks

AnsweredHot!Reading program memory with PLIB_NVM_FlashRead in PIC32MZ

Author
jens_munk
New Member
  • Total Posts : 8
  • Reward points : 0
  • Joined: 2017/05/20 01:55:18
  • Location: 0
  • Status: offline
2019/04/04 01:12:44 (permalink)
0

Reading program memory with PLIB_NVM_FlashRead in PIC32MZ

As part of a bootloader I want to store the version number of the loaded program, and since the PIC32MZ's do not have an EEPROM, I am attempting to place this in the 4 topmost bytes of program memory. Writing appears OK by using the "APP_NVMWordWrite" from the booloader example. But I cannot read it back. Using the Harmony function:
 
data = PLIB_NVM_FlashRead(NVM_ID_0, addr);

 
cause an exception and crash the program. Stepping into the library shows that it is the access itself that causes the exception. And yes, the address is correct: 0xD1FFFFFB for the PIC32MZ2048EFM, I am using.
 
PLIB_TEMPLATE uint32_t NVM_FlashRead_Default( NVM_MODULE_ID index , uint32_t address )
{
    return ( *((uint32_t *)(address)) ); //<==== CRASHES HERE!
}



What am I doing wrong?
#1
Paul PortSol
Super Member
  • Total Posts : 471
  • Reward points : 0
  • Joined: 2015/07/03 11:52:03
  • Location: Newfoundland, Canada
  • Status: offline
Re: Reading program memory with PLIB_NVM_FlashRead in PIC32MZ 2019/04/04 04:04:14 (permalink)
4 (1)
a) Just read directly, no need for special read function as PIC32 is linear memory space.
 
b) I have these blocks for factory write only, and for field re-writable structures:
**Header: 
typedef struct {//DCI Page=4096bytes=1024*32bit, Row=512bytes=128*32bit
uint32_t _uID32; //ModuleID (ID16 in Low Bits)
Tchar4u32 _tFW_ID; //Firmware Type/ID (Defined which Firmware to Load so Compatible with PCB)
uint32_t _uOptions32;// Model Options (Selects operating modes within a single Firmware Load)
uint32_t _uFlags; //Bitwise Flags TBD
uint32_t _puReserved[64-4];//Spare (64*32bit = 256bytes) (minus number of above uint32_t)
char _pcText64a[64], _pcText64b[64], _pcText64c[64], _pcText64d[64];//Spare = 256bytes
} SFactFLASH;
#if (D_Declare_DataFLASH_IsExtern)
D_Declare_DataFLASH const SFactFLASH *pcsFactFlash;//Simple Pointer works
#else
const SFactFLASH *pcsFactFlash = ((SFactFLASH*)D_FactFLASH_Add);//Simple Pointer works if don't want initialized
#endif
 
typedef struct {
uint32_t _uDoBL; //D_FlagLoad==BootloaderMode, Other==NormalRunMode
uint32_t _uFlags; //Bitwise Flags TBD
uint32_t _puReserved[64-2];//Spare (64*32bit = 256bytes) (minus number of above uint32_t)
char _pcText64a[64], _pcText64b[64], _pcText64c[64], _pcText64d[64];//Spare = 256bytes
} SDataFLASH;
#if (D_Declare_DataFLASH_IsExtern)
D_Declare_DataFLASH const SDataFLASH *pcsDataFlash;//Simple Pointer works
#else
const SDataFLASH *pcsDataFlash = ((SDataFLASH*)D_DataFLASH_Add);//Simple Pointer works if don't want initialized
#endif
 
**Code file for declaring the areas with contents:
const SFactFLASH sFactFlashInit __attribute__ ((keep)) __attribute__((address(D_FactFLASH_Add))) = 
{//Init Required for Proper Compiling/Run
._uID32 = 0x00006118,//RemID
._tFW_ID = {"DCIa"},//0x00006000,//DCIa
._uOptions32 = 0x0000d032,//None
._uFlags = 0x0000dF32,//None
//Rest unused left as 0xFFFFFFFF or 0x00000000
};
// ==========
const SDataFLASH sDataFlashInit __attribute__ ((keep)) __attribute__((address(D_DataFLASH_Add))) =
{//Init Required for Proper Compiling/Run
._uDoBL = D_FlagRunApp,//Allow to run any existing App (Maybe a Loadable)
._uFlags = 0x0000FF32, //None
//Rest unused left as 0xFFFFFFFF or 0x00000000
};
 
c) Consider putting at beginning of Codespace (0x9d000000). This would keep your code consistent if you used PIC's with different FLASH sizes. You would need to shift things in the linker file.
 
d) It is also best to reserve at least 1page in case you later decide to support flash erase/write for these blocks, as 1page is minimum erase size.
 
e) If you will be supporting a bootloader then consider setting it up now so you don't have to alter the addresses again. Some bootloaders will overflow into program FLASH space depending on selected protocol and chosen PIC's available boot memory size.
 
Paul
 
#2
jens_munk
New Member
  • Total Posts : 8
  • Reward points : 0
  • Joined: 2017/05/20 01:55:18
  • Location: 0
  • Status: offline
Re: Reading program memory with PLIB_NVM_FlashRead in PIC32MZ 2019/04/04 04:48:03 (permalink)
0
Thanks for your reply, but isn't this exactly what it does? I.e. read the memory directly with:
return ( *((uint32_t *)(address)) ); //<==== CRASHES HERE!
in its most simple form.
 
 
 
#3
Paul PortSol
Super Member
  • Total Posts : 471
  • Reward points : 0
  • Joined: 2015/07/03 11:52:03
  • Location: Newfoundland, Canada
  • Status: offline
Re: Reading program memory with PLIB_NVM_FlashRead in PIC32MZ 2019/04/04 04:57:38 (permalink)
4 (1)
What exact address are you providing?
Careful of Virtual address versus Physical address (See memory map in PIC datasheet) when specifying numbers.
 
For mine the address is in the range 0x9d000000~0x9d07FFFF (not 0x1dxxxxxx).
 
Paul
 
#4
jens_munk
New Member
  • Total Posts : 8
  • Reward points : 0
  • Joined: 2017/05/20 01:55:18
  • Location: 0
  • Status: offline
Re: Reading program memory with PLIB_NVM_FlashRead in PIC32MZ 2019/04/04 05:46:59 (permalink)
0
Good point but it still crashes. Here is the very simplified function I am trying to get alive:
uint32_t APP_NVMWordRead(void* address)
{
    uint32_t data;
    uint32_t addr;

    addr = 0x9D1FFFFB;
    data = ( *((uint32_t *)(addr)) ); //<=== CRASHES HERE
    
    return data;
}

 
Shouldn't this work?
#5
Mysil
Super Member
  • Total Posts : 3326
  • Reward points : 0
  • Joined: 2012/07/01 04:19:50
  • Location: Norway
  • Status: offline
Re: Reading program memory with PLIB_NVM_FlashRead in PIC32MZ 2019/04/04 07:01:01 (permalink) ☼ Best Answerby jens_munk 2019/04/05 03:45:26
5 (1)
Hi,
addr = 0x9D1FFFFB   Does Not align on a 4 byte  boundary: 0x0, 0x4, 0x8 and 0xC,
so there will be a Unaligned memory access exception.
 
You may correct the address to a correct alignment for 32 bit word access,
or you may write a exception handler to move one byte at a time into CPU register,
and then resume operation with the next instruction.
 
NVM write operation may have truncated the address, by ignoring the 2 least significant address bits,
and may have written the word on address 0x...08
 
Also, note that if ECC memory error correction is used on PIC32MZ, then flash writing should be aligned on 16 byte boundaries, writing 4 words together.
 
    Mysil
post edited by Mysil - 2019/04/04 07:04:29
#6
aschen0866
Super Member
  • Total Posts : 4481
  • Reward points : 0
  • Joined: 2006/01/08 22:18:32
  • Location: San Diego
  • Status: offline
Re: Reading program memory with PLIB_NVM_FlashRead in PIC32MZ 2019/04/04 07:33:16 (permalink)
0
jens_munk
Good point but it still crashes. Here is the very simplified function I am trying to get alive:
uint32_t APP_NVMWordRead(void* address)
{
    uint32_t data;
    uint32_t addr;

    addr = 0x9D1FFFFB;
    data = ( *((uint32_t *)(addr)) ); //<=== CRASHES HERE
    
    return data;
}

 
Shouldn't this work?


This will cause address exception as already pointed out. If you need a general function that reads any location as a 32-bit word, you can try something like this:

uint32_t APP_NVMWordRead(void* address)
{
struct unaligned
{
uint32_t data;
} __attribute__((packed)) * rp;

rp = address;

return rp->data;
}

 
#7
Paul PortSol
Super Member
  • Total Posts : 471
  • Reward points : 0
  • Joined: 2015/07/03 11:52:03
  • Location: Newfoundland, Canada
  • Status: offline
Re: Reading program memory with PLIB_NVM_FlashRead in PIC32MZ 2019/04/04 08:28:10 (permalink)
0
If you are letting the linker choose the memory settings (the default) then it may be defaulting to the smallest PIC32MZ that can hold your program, and thus the address may be outside allowed for that smaller IC.
You can check this under Project > Properties > ICD3 (or whatever programmer you have).
 
This goes back to what I suggested in the beginning:
- define your address as something real so the linker and programmer know its there and allocate appropriate space, or
- reserve the space at the beginning of FLASH so it is consistently there no matter what memory size PIC is compiler for.
 
I had tried that "put at the end", and ran into the unexpected programmer selecting a smaller PIC back when I did my NVM tests a few months ago. There is no advantage of "at the end" since if you wish to erase/write the flash you are still going to be reserving a full page (4096=0x1000bytes) as that is min erase on PIC32MZ. 
 
It can be messy go at the linker, but I had to do that anyway for my custom bootloader.
 
Paul
#8
jens_munk
New Member
  • Total Posts : 8
  • Reward points : 0
  • Joined: 2017/05/20 01:55:18
  • Location: 0
  • Status: offline
Re: Reading program memory with PLIB_NVM_FlashRead in PIC32MZ 2019/04/05 03:47:33 (permalink)
0
Thanks!
 
That resolved it. I knew it was something obvious - just couldn't spot it.
 
Jens.
 
 
Mysil
Hi,
addr = 0x9D1FFFFB   Does Not align on a 4 byte  boundary: 0x0, 0x4, 0x8 and 0xC,
so there will be a Unaligned memory access exception.
 
You may correct the address to a correct alignment for 32 bit word access,
or you may write a exception handler to move one byte at a time into CPU register,
and then resume operation with the next instruction.
 
NVM write operation may have truncated the address, by ignoring the 2 least significant address bits,
and may have written the word on address 0x...08
 
Also, note that if ECC memory error correction is used on PIC32MZ, then flash writing should be aligned on 16 byte boundaries, writing 4 words together.
 
    Mysil




#9
Jump to:
© 2019 APG vNext Commercial Version 4.5