Exemplo n.º 1
0
void write_flash_row()
{
	size_t offset;
	uint8_t i;
	uint32_t prog_addr = write_address;

	NVMCON = 0x4001;
	TBLPAG = prog_addr >> 16;
	offset = prog_addr & 0xffff;

	/* Write the data provided */
	for (i = 0; i < write_length; i++) {
		__builtin_tblwtl(offset, prog_buf[i]);
		__builtin_tblwth(offset, prog_buf[++i]);
		offset += 2;
	}

	/* Pad the rest of the row out with 0xff */
	for (; i < BUFFER_LENGTH; i += 2) {
		__builtin_tblwtl(offset, 0xffff);
		__builtin_tblwth(offset, 0xffff);
		offset += 2;
	}

	asm("DISI #5");
	__builtin_write_NVM();

	while (NVMCONbits.WR == 1)
		;
}
Exemplo n.º 2
0
void flashProgramInstructionRow ( u32 * wordAddress, const u32 * instructions )
{
    s16 i;
    u32 temp = *wordAddress;
    u32 offset;
    DWORD_VAL value;
    temp = FLASH_ROW( temp ); /* normalize to beginning of row */
    offset = temp & FLASH_TABLE_PAGE_SIZE_MASK; /* offset into table page */
    TBLPAG = temp >> FLASH_TABLE_PAGE_SIZE_SHIFT; /* select table page */

    /* a complete row is written -> update wordAddress */
    *wordAddress = temp + FLASH_ROW_SIZE_IN_WORDS; 

    /* perform write of complete row */
    for ( i = 0; i < FLASH_ROW_SIZE_IN_BYTES; i += 4, instructions++, offset += 2 )
    {
	  value.Val = *instructions;

	__builtin_tblwtl( offset, value.word.LW );
	__builtin_tblwth( offset, value.word.HW );
    }

    NVMCON = FLASH_ACCESS_ROW_PROGRAM;
    asm("DISI #5");
    __builtin_write_NVM();
    while(NVMCONbits.WR == 1);
}
Exemplo n.º 3
0
void WriteFlashSubBlock(void)		//Use word writes to write code chunks less than a full 64 byte block size.
{
	unsigned int i = 0;
	DWORD_VAL Address;

	NVMCON = 0x4003;		//Perform WORD write next time WR gets set = 1.

	while(BufferedDataIndex > 0)		//While data is still in the buffer.
	{
		Address.Val = ProgrammedPointer - BufferedDataIndex;
		TBLPAG = Address.word.HW;

		__builtin_tblwtl(Address.word.LW, ProgrammingBuffer[i]);		//Write the low word to the latch
		__builtin_tblwth(Address.word.LW, ProgrammingBuffer[i + 1]);	//Write the high word to the latch (8 bits of data + 8 bits of "phantom data")
		i = i + 2;

		asm("DISI #16");					//Disable interrupts for next few instructions for unlock sequence
		__builtin_write_NVM();
        while(NVMCONbits.WR == 1){}

		BufferedDataIndex = BufferedDataIndex - 2;		//Used up 2 (16-bit) words from the buffer.
	
        }

	NVMCONbits.WREN = 0;		//Good practice to clear WREN bit anytime we are not expecting to do erase/write operations, further reducing probability of accidental activation.
        

}
Exemplo n.º 4
0
/*********************************************************************
 * Function:        unsigned int NVMErasePage(void* address)
 *
 * Description:     Block Erases Program Memory
 * PreCondition:    None
 *
 * Inputs:          address:  Destination page address to Erase.
 *
 * Output:          '0' if operation completed successfully.
 *
 * Example:         NVMemErasePage(UINT32 0xBD000000)
 ********************************************************************/
UINT NVMemBlockErase(void)
{
	NVMCON = 0x400D;                // Bulk erase on next WR
	INTCON2bits.GIE = 0;            // Disable interrupts for next few instructions for unlock sequence
	__builtin_write_NVM();
	while (NVMCONbits.WR == 1) {}
	INTCON2bits.GIE = 1;            // Re-enable the interrupts (if required).

	return NVMCONbits.WRERR;        // Return WRERR state.
}
Exemplo n.º 5
0
void flashErasePage ( u32 wordAddress )
{
    u32 offset = wordAddress & FLASH_TABLE_PAGE_SIZE_MASK; /* offset into table page */
    TBLPAG = wordAddress >> FLASH_TABLE_PAGE_SIZE_SHIFT; /* select table page */

    __builtin_tblwtl( offset, 0x0000 /* value is don't care */ );

    NVMCON = FLASH_ACCESS_PAGE_ERASE;
    asm volatile ( "disi #5" );
    __builtin_write_NVM(); /* unlock sequence + start erase cycle */
    while(NVMCONbits.WR == 1);
}
Exemplo n.º 6
0
void write_freq(WORD newData)
{
  WORD offset;

  NVMCON = 0x4058;

  TBLPAG = __builtin_tblpage(&dat);
  offset = __builtin_tbloffset(&dat);
  __builtin_tblwtl(offset,0);

  asm volatile("disi #5");
  __builtin_write_NVM();
  while(NVMCONbits.WR == 1);

  NVMCON = 0x4004;

  TBLPAG = __builtin_tblpage(&dat);
  offset = __builtin_tbloffset(&dat);
  __builtin_tblwtl(offset,newData);

  asm volatile("disi #5");
  __builtin_write_NVM();
  while(NVMCONbits.WR == 1);
}
Exemplo n.º 7
0
BOOL FlashErasePage(DWORD address) {
  assert((address & 0x3FF) == 0);
  DWORD_VAL a = { address };

  NVMCON = 0x4042;  // Erase page

  TBLPAG = a.byte.UB;
  __builtin_tblwtl(a.word.LW, 0xFFFF);

  asm("DISI #5");
  __builtin_write_NVM();
  while(NVMCONbits.WR);
  NVMCONbits.WREN = 0;
  return NVMCONbits.WRERR == 0;
}	
Exemplo n.º 8
0
void EraseFlash(void)
{
	DWORD_VAL MemAddressToErase = {0x00000000};
	MemAddressToErase.Val = (((DWORD)ErasePageTracker) << 10);

	NVMCON = 0x4042;				//Erase page on next WR

	TBLPAG = MemAddressToErase.byte.UB;
	__builtin_tblwtl(MemAddressToErase.word.LW, 0xFFFF);

	asm("DISI #16");					//Disable interrupts for next few instructions for unlock sequence
	__builtin_write_NVM();
    while(NVMCONbits.WR == 1){}

//	EECON1bits.WREN = 0;  //Good practice now to clear the WREN bit, as further protection against any future accidental activation of self write/erase operations.
}
Exemplo n.º 9
0
BOOL FlashWriteDWORD(DWORD address, DWORD value)	{
  assert((address & 0x1) == 0);
  DWORD_VAL a = { address };
  DWORD_VAL v = { value };

  NVMCON = 0x4003;  // Word write

  TBLPAG = a.word.HW;
  __builtin_tblwtl(a.word.LW, v.word.LW);		//Write the low word to the latch
  __builtin_tblwth(a.word.LW, v.word.HW); 	//Write the high word to the latch (8 bits of data + 8 bits of "phantom data")

  asm("DISI #5");
  __builtin_write_NVM();
  while (NVMCONbits.WR);
  NVMCONbits.WREN = 0;
  return NVMCONbits.WRERR == 0;
}
Exemplo n.º 10
0
/*********************************************************************
 * Function:        unsigned int NVMErasePage(void* address)
 *
 * Description:     A page erase will erase a single page of program flash,
 *                  which equates to 1k instructions (3KBytes). The page to
 *                  be erased is selected using NVMADDR. The lower bytes of
 *                  the address given by NVMADDR are ignored in page selection.
 *
 * PreCondition:    None
 *
 * Inputs:          address:  Destination page address to Erase.
 *
 * Output:          '0' if operation completed successfully.
 *
 * Example:         NVMemErasePage(UINT32 0xBD000000)
 ********************************************************************/
UINT NVMemErasePage(UINT32 address)
{
	DWORD_VAL eraseAddress;
	eraseAddress.Val = address;

	TBLPAG = eraseAddress.byte.UB;
	NVMADRU = eraseAddress.word.HW;
	NVMADR = eraseAddress.word.LW;
	__builtin_tblwtl(eraseAddress.word.LW, 0xFFFF);
	NVMCON = 0x4003;                // Erase page on next WR

	INTCON2bits.GIE = 0;            // Disable interrupts for next few instructions for unlock sequence
	__builtin_write_NVM();
	while(NVMCONbits.WR == 1) {}
	INTCON2bits.GIE = 1;            // Re-enable the interrupts (if required).

	return NVMCONbits.WRERR;        // Return WRERR state.
}
Exemplo n.º 11
0
void flashProgram1Instruction ( u32 * wordAddress, u32 instruction )
{
    DWORD_VAL value;
    u32 temp = *wordAddress;
    u32 offset = temp & FLASH_TABLE_PAGE_SIZE_MASK; /* offset into table page */
    TBLPAG = temp >> FLASH_TABLE_PAGE_SIZE_SHIFT; /* select table page */

    /* a pic 24 word is 16-bits, we write 3-Bytes + phantom = 2 16-bit words */
    *wordAddress += 2;

    value.Val = instruction;

    __builtin_tblwtl( offset, value.word.LW );
    __builtin_tblwth( offset, value.word.HW );

    NVMCON = FLASH_ACCESS_WORD_PROGRAM;
    asm("DISI #5");
    __builtin_write_NVM();
    while(NVMCONbits.WR == 1);
}
Exemplo n.º 12
0
/*********************************************************************
 * Function:        unsigned int NVMWriteWord(UINT32 address, UINT32 data)
 *
 * Description:     The word at the location pointed to by NVMADDR is programmed.
 *
 * PreCondition:    None
 *
 * Inputs:          address:   Destination address to write.
 *                  data:      Word to write.
 *
 * Output:          '0' if operation completed successfully.
 *
 * Example:         NVMWriteWord(0xBD000000, 0x12345678)
 ********************************************************************/
UINT NVMemWriteWord(UINT32 address, UINT32 data)
{
	DWORD_VAL writeAddress;
	DWORD_VAL writeData;

	writeAddress.Val = address;
	writeData.Val = data;

	NVMCON = 0x4001;                            // Perform WORD write next time WR gets set = 1.
	NVMADRU = writeAddress.word.HW;
	NVMADR = writeAddress.word.LW;

	// Set the table address of "Latch". The data is programmed into the FLASH from a temporary latch. 
	TBLPAG = 0xFA;
	// The smallest block of data that can be programmed in
	// a single operation is 2 instruction words (6 Bytes + 2 Phantom Bytes).
	// Mask the high or low instruction words depending on the address and write either high or low instruction word.
	if (address % 4)
	{
		__builtin_tblwtl(0, 0xFFFF);            // Mask the low word of 1-st instruction into the latch.
		__builtin_tblwth(1, 0x00FF);            // Mask the high word of 1-st instruction into the latch. (8 bits of data + 8 bits of "phantom data" (phantom byte is always 0))

		__builtin_tblwtl(2, writeData.word.LW);	// Write the low word of 2-nd instruction into the latch
		__builtin_tblwth(3, writeData.word.HW);	// Write the high word of 2-nd instruction into the latch 		
	}
	else
	{
		__builtin_tblwtl(0, writeData.word.LW); // Write the low word of 1-st instruction into the latch
		__builtin_tblwth(1, writeData.word.HW); // Write the high word of 1-st instruction into the latch 
		__builtin_tblwtl(2, 0xFFFF);            // Mask the low word of 2-nd instruction into the latch.
		__builtin_tblwth(3, 0x00FF);            // Mask the high word of 2-nd instruction into the latch. (8 bits of data + 8 bits of "phantom data" (phantom byte is always 0))
	}

	INTCON2bits.GIE = 0;                        // Disable interrupts for next few instructions for unlock sequence
	__builtin_write_NVM();
	while(NVMCONbits.WR == 1){}
	INTCON2bits.GIE = 1;                        // Re-enable the interrupts (if required).

	return NVMCONbits.WRERR;                    // Return WRERR state.
}
Exemplo n.º 13
0
void clear_flash()
{
	uint32_t prog_addr = USER_REGION_BASE;
	size_t offset;

	/* Clear each flash block. TBLPAG/offset is set to the
	 * base address (lowest address) of each block. */
	while (prog_addr < USER_REGION_TOP) {
		TBLPAG = prog_addr >> 16;
		offset = prog_addr & 0xffff;

		__builtin_tblwtl(offset, 0x00);
		NVMCON = 0x4042;
		asm("DISI #5");
		__builtin_write_NVM();

		while (NVMCONbits.WR == 1)
			;

		prog_addr += FLASH_BLOCK_SIZE;
	}
}
Exemplo n.º 14
0
BOOL FlashWriteBlock(DWORD address, BYTE block[192]) {
  assert((address & 0x7F) == 0);
  unsigned int i = 0;
  DWORD_VAL a = { address };
  DWORD_VAL v;

  NVMCON = 0x4001;  // Block write

  TBLPAG = a.word.HW;
  while (i < 192) {
    v.byte.LB = block[i++];
    v.byte.HB = block[i++];
    v.byte.UB = block[i++];
    __builtin_tblwtl(a.word.LW, v.word.LW);  // Write the low word to the latch
    __builtin_tblwth(a.word.LW, v.word.HW);  // Write the high word to the latch (8 bits of data + 8 bits of "phantom data")
    a.word.LW += 2;
  }

  asm("DISI #5");
  __builtin_write_NVM();
  while (NVMCONbits.WR);
  NVMCONbits.WREN = 0;
  return NVMCONbits.WRERR == 0;
}
Exemplo n.º 15
0
BYTE MDD_IntFlash_SectorWrite(DWORD sector_addr, BYTE* buffer, BYTE allowWriteToZero)
{
#if !defined(INTERNAL_FLASH_WRITE_PROTECT)
    WORD i;
    BYTE j;
    WORD offset;
    DWORD flashAddress;
    WORD TBLPAGSave;


    //First, error check the resulting address, to make sure the MSD host isn't trying 
    //to erase/program illegal LBAs that are not part of the designated MSD volume space.
    if(sector_addr >= MDD_INTERNAL_FLASH_TOTAL_DISK_SIZE)
    {
        return FALSE;
    }  

    TBLPAGSave = TBLPAG;
    
#if defined (__dsPIC33E__) || defined (__PIC24E__)
    

    // First, save the contents of the entire erase page.  
    // To do this, we need to get a pointer to the start of the erase page.
    // AND mask 0xFFFFF800 is to clear the lower bits, 
    // so we go back to the start of the erase page.
    
    flashAddress = ((DWORD)FILES_ADDRESS + (DWORD)(sector_addr*MEDIA_SECTOR_SIZE)) 
                & (DWORD)0xFFFFF800;  
    
    //Now save all of the contents of the erase page.
    TBLPAG = (BYTE)(flashAddress >> 16);
    for(i = 0; i < ERASE_BLOCK_SIZE;i++)
    {
        file_buffer[i] = __builtin_tblrdl((WORD)flashAddress + (2 * i));
    }    

    // Now we want to overwrite the file_buffer[] contents 
    // for the sector that we are trying to write to.
    // The lower 2 bits of the helps to determine this.
   
    offset = 0x200 * (BYTE)(sector_addr & 0x3);   

    //Overwrite the file_buffer[] RAM contents for the sector that we are trying to write to.
    for(i = 0; i < MEDIA_SECTOR_SIZE; i++)
    {
        *((unsigned char *)file_buffer + offset + i) = *buffer++;
    }
#else

     //First, save the contents of the entire erase page.  To do this, we need to get a pointer to the start of the erase page.
    flashAddress = ((DWORD)FILES_ADDRESS + (DWORD)(sector_addr*MEDIA_SECTOR_SIZE)) & (DWORD)0xFFFFFC00;  //AND mask 0xFFFFFC00 is to clear the lower bits, so we go back to the start of the erase page.
    //Now save all of the contents of the erase page.
    for(i = 0; i < ERASE_BLOCK_SIZE;)
    {
        TBLPAG = (BYTE)(flashAddress >> 16);
        *(WORD*)&file_buffer[i] = __builtin_tblrdl((WORD)flashAddress);
        flashAddress += 2u;    //Skipping upper word.  Don't care about the implemented byte/don't use it when programming or reading from the sector.
        i += 2u;
    }    

    //Now we want to overwrite the file_buffer[] contents for the sector that we are trying to write to.
    //Need to figure out if the buffer[] data goes in the upper sector or the lower sector of the file_buffer[]
    if(sector_addr & 0x00000001)
    {
        //Odd sector address, must be the high file_buffer[] sector
        offset = MEDIA_SECTOR_SIZE;
    }
    else
    {
        offset = 0;
    }        

    //Overwrite the file_buffer[] RAM contents for the sector that we are trying to write to.
    for(i = 0; i < MEDIA_SECTOR_SIZE; i++)
    {
        file_buffer[offset + i] = *buffer++;
    }
    #endif
    

#if defined(__dsPIC33E__) || defined (__PIC24E__)

    INT gieBkUp;

    //Now erase the entire erase page of flash memory.  
    //First we need to calculate the actual flash memory 
    //address of the erase page. 
    
    gieBkUp = INTCON2bits.GIE;
    INTCON2bits.GIE = 0; // Disable interrupts
    NVMADRU = (WORD)(flashAddress >> 16);
    NVMADR = (WORD)(flashAddress & 0xFFFF);
    NVMCON = 0x4003;    // This value will erase a page.
    __builtin_write_NVM();
    INTCON2bits.GIE = gieBkUp; // Enable interrupts

    //Now reprogram the erase page with previously obtained contents of the file_buffer[]
    //We only write to the even flash word addresses, the odd word addresses are left blank.  
    //Therefore, we only store 2 bytes of application data for every 2 flash memory word addresses.
    //This "wastes" 1/3 of the flash memory, but it provides extra protection from accidentally executing
    //the data.  It also allows quick/convenient PSV access when reading back the flash contents.

    TBLPAG = 0xFA;
    j = 0;
    for(i = 0; i < ERASE_BLOCK_SIZE;i++)
    {

       //
        __builtin_tblwtl((j * 2), file_buffer[i]);
        __builtin_tblwth((j * 2), 0);
           
        j ++;

        //Check if we have reached a program block size boundary.  If so, program the last 128 
        //useful bytes (192 bytes total, but 64 of those are filled with '0' filler bytes).
        if(j >= 128u)
        {
            j = j - 128u;
            NVMADRU = (WORD)(flashAddress >> 16);
            NVMADR = (WORD)(flashAddress & 0xFFFF);
            NVMCON = 0x4002;
            gieBkUp = INTCON2bits.GIE;
            INTCON2bits.GIE = 0; // Disable interrupts
            __builtin_write_NVM();
            INTCON2bits.GIE = gieBkUp; // Enable interrupts
            flashAddress += 256;
        }    
    }