示例#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;
}
/** Handler for the XPROG ENTER_PROGMODE command to establish a connection with the attached device. */
static void XPROGProtocol_EnterXPROGMode(void)
{
    Endpoint_ClearOUT();
    Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM);
    Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);

    bool NVMBusEnabled = false;

    if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
    {
        /* Enable PDI programming mode with the attached target */
        XPROGTarget_EnableTargetPDI();

        /* Store the RESET key into the RESET PDI register to keep the XMEGA in reset */
        XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
        XPROGTarget_SendByte(PDI_RESET_KEY);

        /* Lower direction change guard time to 0 USART bits */
        XPROGTarget_SendByte(PDI_CMD_STCS | PDI_CTRL_REG);
        XPROGTarget_SendByte(0x07);

        /* Enable access to the XPROG NVM bus by sending the documented NVM access key to the device */
        XPROGTarget_SendByte(PDI_CMD_KEY);
        for (uint8_t i = sizeof(PDI_NVMENABLE_KEY); i > 0; i--)
            XPROGTarget_SendByte(PDI_NVMENABLE_KEY[i - 1]);

        /* Wait until the NVM bus becomes active */
        NVMBusEnabled = XMEGANVM_WaitWhileNVMBusBusy();
    }
    else if (XPROG_SelectedProtocol == XPRG_PROTOCOL_TPI)
    {
        /* Enable TPI programming mode with the attached target */
        XPROGTarget_EnableTargetTPI();

        /* Lower direction change guard time to 0 USART bits */
        XPROGTarget_SendByte(TPI_CMD_SSTCS | TPI_CTRL_REG);
        XPROGTarget_SendByte(0x07);

        /* Enable access to the XPROG NVM bus by sending the documented NVM access key to the device */
        XPROGTarget_SendByte(TPI_CMD_SKEY);
        for (uint8_t i = sizeof(TPI_NVMENABLE_KEY); i > 0; i--)
            XPROGTarget_SendByte(TPI_NVMENABLE_KEY[i - 1]);

        /* Wait until the NVM bus becomes active */
        NVMBusEnabled = TINYNVM_WaitWhileNVMBusBusy();
    }

    Endpoint_Write_Byte(CMD_XPROG);
    Endpoint_Write_Byte(XPRG_CMD_ENTER_PROGMODE);
    Endpoint_Write_Byte(NVMBusEnabled ? XPRG_ERR_OK : XPRG_ERR_FAILED);
    Endpoint_ClearIN();
}
示例#3
0
/** Removes access to the target's NVM controller and physically disables the target's physical PDI interface. */
void XMEGANVM_DisablePDI(void)
{
	XMEGANVM_WaitWhileNVMBusBusy();

	/* Clear the RESET key in the RESET PDI register to allow the XMEGA to run */
	XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
	XPROGTarget_SendByte(0x00);

	/* Do it twice to make sure it takes effect (silicon bug?) */
	XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
	XPROGTarget_SendByte(0x00);

	XPROGTarget_DisableTargetPDI();
}
示例#4
0
文件: XMEGANVM.c 项目: trtg/lufa
/** Removes access to the target's NVM controller and physically disables the target's physical PDI interface. */
void XMEGANVM_DisablePDI(void)
{
	XMEGANVM_WaitWhileNVMBusBusy();

	/* Clear the RESET key in the RESET PDI register to allow the XMEGA to run - must perform this until the
	 * change takes effect, as in some cases it takes multiple writes (silicon bug?).
	 */
	do
	{
		/* Clear reset register */
		XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
		XPROGTarget_SendByte(0x00);

		/* Read back the reset register, check to see if it took effect */
		XPROGTarget_SendByte(PDI_CMD_LDCS | PDI_RESET_REG);
	} while (XPROGTarget_ReceiveByte() != 0x00);

	XPROGTarget_DisableTargetPDI();
}
示例#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
文件: XMEGANVM.c 项目: trtg/lufa
/** Enables the physical PDI interface on the target and enables access to the internal NVM controller.
 *
 *  \return Boolean true if the PDI interface was enabled successfully, false otherwise
 */
bool XMEGANVM_EnablePDI(void)
{
	/* Enable PDI programming mode with the attached target */
	XPROGTarget_EnableTargetPDI();

	/* Store the RESET key into the RESET PDI register to keep the XMEGA in reset */
	XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
	XPROGTarget_SendByte(PDI_RESET_KEY);

	/* Lower direction change guard time to 32 USART bits */
	XPROGTarget_SendByte(PDI_CMD_STCS | PDI_CTRL_REG);
	XPROGTarget_SendByte(0x02);

	/* Enable access to the XPROG NVM bus by sending the documented NVM access key to the device */
	XPROGTarget_SendByte(PDI_CMD_KEY);
	for (uint8_t i = sizeof(PDI_NVMENABLE_KEY); i > 0; i--)
	  XPROGTarget_SendByte(PDI_NVMENABLE_KEY[i - 1]);

	/* Wait until the NVM bus becomes active */
	return XMEGANVM_WaitWhileNVMBusBusy();
}
/** Handler for the XPROG LEAVE_PROGMODE command to terminate the PDI programming connection with
 *  the attached device.
 */
static void XPROGProtocol_LeaveXPROGMode(void)
{
    Endpoint_ClearOUT();
    Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM);
    Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);

    if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
    {
        XMEGANVM_WaitWhileNVMBusBusy();

        /* Clear the RESET key in the RESET PDI register to allow the XMEGA to run */
        XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
        XPROGTarget_SendByte(0x00);

        /* Do it twice to make sure it takes affect (silicon bug?) */
        XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
        XPROGTarget_SendByte(0x00);

        XPROGTarget_DisableTargetPDI();
    }
    else
    {
        TINYNVM_WaitWhileNVMBusBusy();

        /* Clear the NVMEN bit in the TPI CONTROL register to disable TPI mode */
        XPROGTarget_SendByte(TPI_CMD_SSTCS | TPI_CTRL_REG);
        XPROGTarget_SendByte(0x00);

        XPROGTarget_DisableTargetTPI();
    }

    Endpoint_Write_Byte(CMD_XPROG);
    Endpoint_Write_Byte(XPRG_CMD_LEAVE_PROGMODE);
    Endpoint_Write_Byte(XPRG_ERR_OK);
    Endpoint_ClearIN();
}
示例#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;
}