示例#1
0
/** Erases a specific memory space of the target.
 *
 *  \param[in] EraseCommand  NVM erase command to send to the device
 *  \param[in] Address  Address inside the memory space to erase
 *
 *  \return Boolean true if the command sequence complete successfully
 */
bool XMEGANVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address)
{
	/* Wait until the NVM controller is no longer busy */
	if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
	  return false;
	  
	/* Send the memory erase command to the target */
	XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
	XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
	XPROGTarget_SendByte(EraseCommand);
	
	/* Chip erase is handled separately, since it's procedure is different to other erase types */
	if (EraseCommand == XMEGA_NVM_CMD_CHIPERASE)
	{
		/* Set CMDEX bit in NVM CTRLA register to start the chip erase */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
		XPROGTarget_SendByte(1 << 0);		
	}
	else
	{
		/* Other erase modes just need us to address a byte within the target memory space */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendAddress(Address);
		XPROGTarget_SendByte(0x00);
	}
	
	/* Wait until the NVM bus is ready again */
	if (!(XMEGANVM_WaitWhileNVMBusBusy()))
	  return false;
	  
	return true;
}
示例#2
0
/** Reads memory from the target's memory spaces.
 *
 *  \param[in]  ReadAddress  Start address to read from within the target's address space
 *  \param[out] ReadBuffer   Buffer to store read data into
 *  \param[in]  ReadSize     Number of bytes to read
 *
 *  \return Boolean true if the command sequence complete successfully
 */
bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize)
{
	/* Wait until the NVM controller is no longer busy */
	if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
	  return false;
	
	/* Send the READNVM command to the NVM controller for reading of an arbitrary location */
	XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
	XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
	XPROGTarget_SendByte(XMEGA_NVM_CMD_READNVM);

	/* Load the PDI pointer register with the start address we want to read from */
	XPROGTarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES);
	XMEGANVM_SendAddress(ReadAddress);

	/* Send the REPEAT command with the specified number of bytes to read */
	XPROGTarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE);
	XPROGTarget_SendByte(ReadSize - 1);
		
	/* Send a LD command with indirect access and postincrement to read out the bytes */
	XPROGTarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
	while (ReadSize-- && TimeoutMSRemaining)
	  *(ReadBuffer++) = XPROGTarget_ReceiveByte();
	
	return (TimeoutMSRemaining != 0);
}
示例#3
0
/** Waits while the target's NVM controller is busy performing an operation, exiting if the
 *  timeout period expires.
 *
 *  \return Boolean true if the NVM controller became ready within the timeout period, false otherwise
 */
bool XMEGANVM_WaitWhileNVMControllerBusy(void)
{
	/* Poll the NVM STATUS register while the NVM controller is busy */
	while (TimeoutMSRemaining)
	{
		/* Send a LDS command to read the NVM STATUS register to check the BUSY flag */
		XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_STATUS);
		
		uint8_t StatusRegister = XPROGTarget_ReceiveByte();

		/* We might have timed out waiting for the status register read response, check here */
		if (!(TimeoutMSRemaining))
		  return false;

		/* Check to see if the BUSY flag is still set */
		if (!(StatusRegister & (1 << 7)))
		{
			TimeoutMSRemaining = COMMAND_TIMEOUT_MS;
			return true;
		}
	}
	
	return false;
}
示例#4
0
/** Waits while the target's NVM controller is busy performing an operation, exiting if the
 *  timeout period expires.
 *
 *  \return Boolean \c true if the NVM controller became ready within the timeout period, \c false otherwise
 */
bool XMEGANVM_WaitWhileNVMControllerBusy(void)
{
	/* Preload the pointer register with the NVM STATUS register address to check the BUSY flag */
	XPROGTarget_SendByte(PDI_CMD_ST(PDI_POINTER_DIRECT, PDI_DATASIZE_4BYTES));
	XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_STATUS);

	/* Poll the NVM STATUS register while the NVM controller is busy */
	for (;;)
	{
		/* Fetch the current status value via the pointer register (without auto-increment afterwards) */
		XPROGTarget_SendByte(PDI_CMD_LD(PDI_POINTER_INDIRECT, PDI_DATASIZE_1BYTE));

		uint8_t StatusRegister = XPROGTarget_ReceiveByte();

		/* We might have timed out waiting for the status register read response, check here */
		if (TimeoutTicksRemaining == 0){
		  return false;
		}

		/* Check to see if the BUSY flag is still set */
		if (!(StatusRegister & (1 << 7))) {
		  return true;
		}
	}
}
示例#5
0
/** Retrieves the CRC value of the given memory space.
 *
 *  \param[in]  CRCCommand  NVM CRC command to issue to the target
 *  \param[out] CRCDest     CRC Destination when read from the target
 *
 *  \return Boolean \c true if the command sequence complete successfully
 */
bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand,
                           uint32_t* const CRCDest)
{
	*CRCDest = 0;

	/* Wait until the NVM controller is no longer busy */
	if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
	  return false;

	/* Set the NVM command to the correct CRC read command */
	XPROGTarget_SendByte(PDI_CMD_STS(PDI_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
	XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
	XPROGTarget_SendByte(CRCCommand);

	/* Set CMDEX bit in NVM CTRLA register to start the CRC generation */
	XPROGTarget_SendByte(PDI_CMD_STS(PDI_DATASIZE_4BYTES, PDI_DATASIZE_1BYTE));
	XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
	XPROGTarget_SendByte(XMEGA_NVM_BIT_CTRLA_CMDEX);

	/* Wait until the NVM bus is ready again */
	if (!(XMEGANVM_WaitWhileNVMBusBusy()))
	  return false;

	/* Wait until the NVM controller is no longer busy */
	if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
	  return false;

	/* Load the PDI pointer register with the DAT0 register start address */
	XPROGTarget_SendByte(PDI_CMD_ST(PDI_POINTER_DIRECT, PDI_DATASIZE_4BYTES));
	XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT0);

	/* Send the REPEAT command to grab the CRC bytes */
	XPROGTarget_SendByte(PDI_CMD_REPEAT(PDI_DATASIZE_1BYTE));
	XPROGTarget_SendByte(XMEGA_CRC_LENGTH_BYTES - 1);

	/* Read in the CRC bytes from the target */
	XPROGTarget_SendByte(PDI_CMD_LD(PDI_POINTER_INDIRECT_PI, PDI_DATASIZE_1BYTE));
	for (uint8_t i = 0; i < XMEGA_CRC_LENGTH_BYTES; i++)
	  ((uint8_t*)CRCDest)[i] = XPROGTarget_ReceiveByte();

	return (TimeoutTicksRemaining > 0);
}
示例#6
0
/** Writes byte addressed memory to the target's memory spaces.
 *
 *  \param[in]  WriteCommand  Command to send to the device to write each memory byte
 *  \param[in]  WriteAddress  Address to write to within the target's address space
 *  \param[in]  Byte          Byte to write to the target
 *
 *  \return Boolean true if the command sequence complete successfully
 */
bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t Byte)
{
	/* Wait until the NVM controller is no longer busy */
	if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
	  return false;

	/* Send the memory write command to the target */
	XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
	XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
	XPROGTarget_SendByte(WriteCommand);
	
	/* Send new memory byte to the memory to the target */
	XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
	XMEGANVM_SendAddress(WriteAddress);
	XPROGTarget_SendByte(Byte);
	
	return true;
}
示例#7
0
/** Writes page addressed memory to the target's memory spaces.
 *
 *  \param[in]  WriteBuffCommand  Command to send to the device to write a byte to the memory page buffer
 *  \param[in]  EraseBuffCommand  Command to send to the device to erase the memory page buffer
 *  \param[in]  WritePageCommand  Command to send to the device to write the page buffer to the destination memory
 *  \param[in]  PageMode          Bitfield indicating what operations need to be executed on the specified page
 *  \param[in]  WriteAddress      Start address to write the page data to within the target's address space
 *  \param[in]  WriteBuffer       Buffer to source data from
 *  \param[in]  WriteSize         Number of bytes to write
 *
 *  \return Boolean true if the command sequence complete successfully
 */
bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand, const uint8_t EraseBuffCommand,
                              const uint8_t WritePageCommand, const uint8_t PageMode, const uint32_t WriteAddress,
                              const uint8_t* WriteBuffer, uint16_t WriteSize)
{
	if (PageMode & XPRG_PAGEMODE_ERASE)
	{
		/* Wait until the NVM controller is no longer busy */
		if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
		  return false;

		/* Send the memory buffer erase command to the target */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
		XPROGTarget_SendByte(EraseBuffCommand);

		/* Set CMDEX bit in NVM CTRLA register to start the buffer erase */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
		XPROGTarget_SendByte(1 << 0);
	}

	if (WriteSize)
	{
		/* Wait until the NVM controller is no longer busy */
		if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
		  return false;

		/* Send the memory buffer write command to the target */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
		XPROGTarget_SendByte(WriteBuffCommand);

		/* Load the PDI pointer register with the start address we want to write to */
		XPROGTarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES);
		XMEGANVM_SendAddress(WriteAddress);

		/* Send the REPEAT command with the specified number of bytes to write */
		XPROGTarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE);
		XPROGTarget_SendByte(WriteSize - 1);
			
		/* Send a ST command with indirect access and postincrement to write the bytes */
		XPROGTarget_SendByte(PDI_CMD_ST | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
		while (WriteSize--)
		  XPROGTarget_SendByte(*(WriteBuffer++));
	}
	
	if (PageMode & XPRG_PAGEMODE_WRITE)
	{
		/* Wait until the NVM controller is no longer busy */
		if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
		  return false;

		/* Send the memory write command to the target */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
		XPROGTarget_SendByte(WritePageCommand);
		
		/* Send the address of the first page location to write the memory page */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendAddress(WriteAddress);
		XPROGTarget_SendByte(0x00);
	}

	return true;
}
示例#8
0
/** Erases a specific memory space of the target.
 *
 *  \param[in] EraseCommand  NVM erase command to send to the device
 *  \param[in] Address       Address inside the memory space to erase
 *
 *  \return Boolean true if the command sequence complete successfully
 */
bool XMEGANVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address)
{
	/* Wait until the NVM controller is no longer busy */
	if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
	  return false;

	/* EEPROM and Chip erasures are triggered differently to FLASH section erasures */
	if (EraseCommand == XMEGA_NVM_CMD_CHIPERASE)
	{
		/* Send the memory erase command to the target */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
		XPROGTarget_SendByte(EraseCommand);

		/* Set CMDEX bit in NVM CTRLA register to start the erase sequence */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
		XPROGTarget_SendByte(1 << 0);
	}
	else if (EraseCommand == XMEGA_NVM_CMD_ERASEEEPROM)
	{
		/* Send the EEPROM page buffer erase command to the target */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
		XPROGTarget_SendByte(XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF);

		/* Set CMDEX bit in NVM CTRLA register to start the buffer erase */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
		XPROGTarget_SendByte(1 << 0);

		/* Wait until the NVM controller is no longer busy */
		if (!(XMEGANVM_WaitWhileNVMControllerBusy()))
		  return false;

		/* Send the EEPROM memory buffer write command to the target */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
		XPROGTarget_SendByte(XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF);

		/* Load the PDI pointer register with the EEPROM page start address */
		XPROGTarget_SendByte(PDI_CMD_ST | (PDI_POINTER_DIRECT << 2) | PDI_DATSIZE_4BYTES);
		XMEGANVM_SendAddress(Address);

		/* Send the REPEAT command with the specified number of bytes to write */
		XPROGTarget_SendByte(PDI_CMD_REPEAT | PDI_DATSIZE_1BYTE);
		XPROGTarget_SendByte(XPROG_Param_EEPageSize - 1);

		/* Send a ST command with indirect access and post-increment to tag each byte in the EEPROM page buffer */
		XPROGTarget_SendByte(PDI_CMD_ST | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);
		for (uint8_t PageByte = 0; PageByte < XPROG_Param_EEPageSize; PageByte++)
		  XPROGTarget_SendByte(0x00);

		/* Send the memory erase command to the target */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
		XPROGTarget_SendByte(EraseCommand);

		/* Set CMDEX bit in NVM CTRLA register to start the EEPROM erase sequence */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CTRLA);
		XPROGTarget_SendByte(1 << 0);
	}
	else
	{
		/* Send the memory erase command to the target */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_CMD);
		XPROGTarget_SendByte(EraseCommand);

		/* Other erase modes just need us to address a byte within the target memory space */
		XPROGTarget_SendByte(PDI_CMD_STS | (PDI_DATSIZE_4BYTES << 2));
		XMEGANVM_SendAddress(Address);
		XPROGTarget_SendByte(0x00);
	}

	/* Wait until the NVM bus is ready again */
	if (!(XMEGANVM_WaitWhileNVMBusBusy()))
	  return false;

	return true;
}