mem.c - Read/write the PIC’s program memory.

 
#include "pic24_util.h"

typedef short          Word16;
typedef unsigned short UWord16;
typedef long           Word32;
typedef unsigned long  UWord32;
 

Write these in C so that can we use the __PIC24H__, __PIC24F__ defines.

void WriteMem(UWord16 val) {
  UNUSED(val);

  asm("mov W0, NVMCON");
  __builtin_write_NVM();
 

Wait for write end.

  asm("1: btsc NVMCON, #15");
  asm("bra 1b");
}


#if (defined(__PIC24E__) || defined(__dsPIC33E__))
void WriteMem2(UWord16 addrhi, UWord16 addrlo, UWord16 val) {
  UNUSED(addrhi);
  UNUSED(addrlo);
  UNUSED(val);
 

Init Pointer to page to be erased.

  asm("mov W0, NVMADRU");

Init Pointer to offset to be erased.

  asm("mov W1, NVMADR");
  asm("mov W2, NVMCON");
  //__builtin_write_NVM();
  asm("disi #06");
  asm("mov #0x55, W0");
  asm("mov W0, NVMKEY");
  asm("mov #0xAA, W0");
  asm("mov W0, NVMKEY");
  asm("bset NVMCON, #15");
  asm("nop");
  asm("nop");
 

Wait for write end.

  asm("1: btsc NVMCON, #15");
  asm(" bra 1b");
}
#endif


//_LoadAddr:  ;W0=NVMADRU,W1=NVMADR - no return values
void LoadAddr(UWord16 nvmadru, UWord16 nvmadr) {
  UNUSED(nvmadru);
  UNUSED(nvmadr);

  asm("mov W0, TBLPAG");
  asm("mov W1, W1");
}

//_WriteLatch: ;W0=TBLPAG,W1=Wn,W2=WordHi,W3=WordLo - no return values
void WriteLatch(UWord16 addrhi,UWord16 addrlo, UWord16 wordhi, UWord16 wordlo) {
  UNUSED(addrhi);
  UNUSED(addrlo);
  UNUSED(wordhi);
  UNUSED(wordlo);

  asm("mov W0, TBLPAG");
  asm("tblwtl W3, [W1]");
  asm("tblwth W2, [W1]");
}


#if (defined(__PIC24E__) || defined(__dsPIC33E__))
//_LoadTwoWords: ;W0=TBLPAG,W1=Wn,W2=WordHi,W3=WordLo W4=Word2Hi,W5=Word2Lo
//W0,W1 not really used
void LoadTwoWords(UWord16 addrhi, UWord16 addrlo, UWord16 wordhi, UWord16 wordlo, UWord16 word2hi, UWord16 word2lo) {
  UNUSED(addrhi);
  UNUSED(addrlo);
  UNUSED(wordhi);
  UNUSED(wordlo);
  UNUSED(word2hi);
  UNUSED(word2lo);

  asm("mov #0xFA,W0");
  asm("mov W0, TBLPAG");
  asm("mov #0, W1");
  asm("tblwtl W3, [W1]");
  asm("tblwth W2, [W1++]");
  asm("tblwtl W5, [W1]");
  asm("tblwth W4, [W1++]");
}
#endif


//_ReadLatch: ;W0=TBLPAG,W1=Wn - data in W1:W0
UWord32 ReadLatch(UWord16 addrhi, UWord16 addrlo) {
  UNUSED(addrhi);
  UNUSED(addrlo);

  asm("mov W0, TBLPAG");
  asm("tblrdl [W1], W0");
  asm("tblrdh [W1], W1");

This gives a compiler warning because not explicitly returning a value from the function, but since this is assembly, do not know how to prevent warning. The function is correct, since W1:W0 being used to return the tblrdl,tblrdh. Could write less efficient code and use a temporary UWord32.

Attempts to suppress following warning:

bootloaderpic24_dspic33_bootloader.Xmem.c:110:1: warning: control reaches end of non-void function [-Wreturn-type]

#pragma GCC diagnostic warning “-Wreturn-type” works. However, if I later re-enable it at any point in this file with a #pragma GCC diagnostic warning “-Wreturn-type”, then the warning still appears. So, leave the warning for now, rather than possibly hide future warnings. See https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html for more information.

}


void ResetDevice(void) {
#if (defined(__PIC24E__) || defined(__dsPIC33E__))
  asm("goto 0x1300");
#else
  asm("goto 0x0E00");
#endif
}


void ResetDeviceasPOR(void) {
  _POR = 1;
  ResetDevice();
}


#if (defined(__PIC24E__) || defined(__dsPIC33E__))
void Erase(UWord16 addrhi, UWord16 addrlo, UWord16 val) {
  UNUSED(addrhi);
  UNUSED(addrlo);
  UNUSED(val);

  asm("mov W2,NVMCON");
 

Init Pointer to page to be erased.

  asm("mov W0, NVMADRU");

Init Pointer to offset to be erased.

  asm("mov W1, NVMADR");

  //__builtin_write_NVM();

  asm("disi #06");
  asm("mov #0x55, W0");
  asm("mov W0, NVMKEY");
  asm("mov #0xAA, W0");
  asm("mov W0, NVMKEY");
  asm("bset NVMCON, #15");
  asm("nop");
  asm("nop");
 

Wait for write end.

  asm("1: btsc NVMCON, #15");
  asm(" bra 1b");
}


#else
//_Erase:
void Erase(UWord16 addrhi, UWord16 addrlo, UWord16 val) {
  UNUSED(addrhi);
  UNUSED(addrlo);
  UNUSED(val);

  asm("push TBLPAG");
  asm("mov W2, NVMCON");
 

Init Pointer to page to be erased.

  asm("mov W0, TBLPAG");

Dummy write to select the row.

  asm("tblwtl W1,[W1]");

  __builtin_write_NVM();
 
Wait for write end.
  asm("1: btsc NVMCON, #15");
  asm(" bra 1b");

  asm("pop TBLPAG");
}
#endif