bool MainMemoryAccessBase::doRead(uint32_t address, uint32_t* buffer, size_t count)
{
	MemoryArea* cpu = mm->getMemoryArea("CPU");
	if (!cpu)
		return false;

	uint32_t pc = 0;
	cpu->read(0, &pc, 1);

	bool omitFirst = (address & 0x1);
	if (omitFirst) {
		--address;
		++count;
	}
	bool omitLast = (count & 1);
	if (omitLast) {
		++count;
	}

	const hal_id readMacro = devHandle->supportsQuickMemRead() ?
								ID_ReadMemQuick : ID_ReadMemWords;

	HalExecElement* el = new HalExecElement(this->devHandle->checkHalId(readMacro));
	el->appendInputData32(this->getStart() + address);
	el->appendInputData32(static_cast<uint32_t>(count/2));
	el->appendInputData32(pc);

	el->setOutputSize(count);

	ReadElement r(buffer, count, omitFirst, omitLast, 0);
	this->readMap[this->elements.size()] = r;
	this->elements.push_back(el);
	return true;
}
bool FetControl::kill (uint8_t id)
{
    bool success = false;

    if (id > 0)
    {
        boost::mutex::scoped_lock lock(this->rhMutex);

        ResponseHandlerTable::iterator it = responseHandlers.find(id);
        if (it != responseHandlers.end())
            responseHandlers.erase(it);
    }

    HalExecCommand kill;
    HalExecElement* el = new HalExecElement(ID_Zero, CmdKill);
    el->appendInputData8(id);
    kill.elements.push_back(el);

    success = this->send(kill);
    // Free the ID from the reserved list
    {
        boost::mutex::scoped_lock lock(this->CriMutex);
        std::map<uint8_t, bool>::iterator it = reservedIds.find(id & 0x3f);

        if(it != reservedIds.end())
        {
            reservedIds.erase(it);
        }
    }

    return success;
}
bool MemoryAreaBase::sendWithChainInfo(HalExecElement * elem, HalExecCommand * cmd)
{
	HalExecElement* el = new HalExecElement(ID_SetDeviceChainInfo);
	el->appendInputData16(static_cast<uint16_t>(this->devHandle->getDevChainInfo()->getBusId()));
	cmd->elements.push_back(el);
	/* this transfers one object to cmd.elements */
	cmd->elements.push_back(elem);
	if (!this->devHandle->send(*cmd)) 
	{
		return false;
	}
	return true;
}
bool MemoryAreaBase::sendWithChainInfo(boost::ptr_vector<HalExecElement> * elem, HalExecCommand * cmd)
{	
	HalExecElement* el = new HalExecElement(ID_SetDeviceChainInfo);
	el->appendInputData16(static_cast<uint16_t>(this->devHandle->getDevChainInfo()->getBusId()));
	cmd->elements.push_back(el);
	/* this transfers all object from given elements to cmd.elements */
	cmd->elements.transfer(cmd->elements.end(), *elem);
	if (!this->devHandle->send(*cmd)) 
	{
		this->elements.transfer(elem->end(), cmd->elements);
		return false;
	}
	return true;
}
bool FetControl::resumeLoopCmd (uint8_t id)
{
    bool success = true;
    if(id > 0)
    {
        HalExecElement* el = new HalExecElement(ID_Zero, CmdResumeLoop);
        el->appendInputData8(id);

        HalExecCommand command;
        command.elements.push_back(el);

        success = send(command);
    }
    return success;
}
bool RandomMemoryAccess::writeBytes (uint32_t address, uint32_t* buffer, size_t count)
{
	HalExecElement* el = new HalExecElement(ID_WriteMemBytes);
	el->appendInputData32(this->getStart() + address);
	el->appendInputData32(static_cast<uint32_t>(count));
	for (size_t i = 0; i < count; ++i) 
	{
		if (buffer[i] > 0xFF) 
		{
			delete el;
			return false;
		}
		el->appendInputData8(static_cast<uint8_t>(buffer[i]));
	}
	el->setInputMinSize(9);
	this->elements.push_back(el);
	return true;
}
/** each buffer element contains one _byte_ */
bool RandomMemoryAccess::writeWords (uint32_t address, uint32_t* buffer, size_t count)
{
	if (address & 0x1)
		return false;

	HalExecElement* el = new HalExecElement(this->devHandle->checkHalId(ID_WriteMemWords));
	el->appendInputData32(this->getStart() + address);
	el->appendInputData32(static_cast<uint32_t>(count/2));
	for (size_t i = 0; i+1 < count; i += 2) 
	{
		if (buffer[i] > 0xFF || buffer[i+1] > 0xFF) 
		{
			delete el;
			return false;
		}
		el->appendInputData16(static_cast<uint16_t>(buffer[i] | (buffer[i+1] << 8)));
	}
	el->setInputMinSize(10);
	this->elements.push_back(el);
	return true;
}
	bool BootcodeRomAccess::doRead (uint32_t address, uint32_t* buffer, size_t count)
	{
		bool omitFirst = (address & 0x1);
		if (omitFirst) 
		{
			--address;
			++count;
		}
		bool omitLast = (count & 1);
		if (omitLast) 
		{
			++count;
		}	

		HalExecElement* el = new HalExecElement(this->devHandle->checkHalId(ID_ReadMemQuick));
		el->appendInputData32(this->getStart() + address);
		el->appendInputData32(static_cast<uint32_t>(count/2));
		el->setOutputSize(count);

		ReadElement r(buffer, count, omitFirst, omitLast, 0);
		this->readMap[this->elements.size()] = r;
		this->elements.push_back(el);
		return true;
	}
bool DeviceHandleManagerV3::setChainConfiguration()
{
	HalExecCommand cmd;
	HalExecElement* el = new HalExecElement(ID_SetChainConfiguration);

	DeviceChainInfoList::iterator it = this->list.begin();
    for (; it != this->list.end(); ++it) {

		if (!it->isMSP430())
		{
			el->appendInputData8((static_cast<uint8_t>(it->getLenIR())) & 0x7F);
		}
		else
		{
			if (it->isInUse())
				el->appendInputData8(0x81);
			else
				el->appendInputData8(0x80);
		}
	}
    el->appendInputData8(0x00);     // End of description
	cmd.elements.push_back(el);
	return parent->send(cmd);
}
bool RandomMemoryAccess::doWrite (uint32_t address, uint32_t* buffer, size_t count)
{
	if (count > this->getSize())
		return false;

	uint32_t start_val = 0;
	const uint32_t end_adr = address + count;
	size_t paddedCount = count;

	if(address & 1)
	{
		++paddedCount;
		if( !doRead(address - 1, &start_val, 1) || !sync() )
			return false;
	}

	uint32_t end_val = 0;
	if(end_adr & 1)
	{
		++paddedCount;
		if( !doRead(end_adr, &end_val, 1) || !sync() )
			return false;
	}

	HalExecElement* el = new HalExecElement(this->devHandle->checkHalId(ID_WriteMemWords));

	address += getStart();

	el->appendInputData32(static_cast<uint32_t>(address & 0xfffffffe));
	el->appendInputData32(static_cast<uint32_t>(paddedCount / 2));

	if(address & 1)
	{
		el->appendInputData8(static_cast<uint8_t>(start_val));
	}
	for (size_t i = 0; i < count; ++i)
	{
		el->appendInputData8(static_cast<uint8_t>(buffer[i]));
	}
	if (end_adr & 1) 
	{
		el->appendInputData16(static_cast<uint8_t>(end_val));
	}

	el->setInputMinSize(8);		// at least address and size (4+4)
	this->elements.push_back(el);

	return true;
}
bool FramMemoryAccessBaseFR57<MPU>::erase(uint32_t start, uint32_t end, uint32_t block_size, int type)
{
	using boost::shared_ptr;
	using boost::bind;

	// check if valid erase type is used
	if ((type != ERASE_SEGMENT) && (type != ERASE_MAIN))
	{
		return false;
	}
	if (block_size < 1)
	{
		return false;
	}
	// if the  MPU is enabled, disable it to enable memory erase
	if(!mpu.readMpuSettings() || !mpu.disableMpu())
	{
		return false;
	}

	// get Device RAM parameters for funclet upload
	MemoryArea* ram = mm->getMemoryArea("system", 0);
	if (!ram)
	{
		return false;
	}

	if ( !uploadFunclet(FuncletCode::ERASE) )
	{
		return false;
	}
	shared_ptr<void> restoreRamOnExit(static_cast<void*>(0), 
									  bind(&FramMemoryAccessBaseFR57<MPU>::restoreRam, this));

	//Note the erase on an FRAM device is just a dummy write with 0xFFFF to the device FRAm 
	int32_t erase_address = start;

	const FuncletCode& funclet = devHandle->getFunclet(FuncletCode::ERASE);
	
	const uint32_t eraseType = 0;
	const uint32_t eraseLength = end - start + 1;
	const uint16_t flags = 0x0;
	const uint16_t programStartAddress = ram->getStart() + funclet.programStartOffset();

	HalExecCommand cmd;
	cmd.setTimeout(10000);	// overwrite 3 sec default with 10 sec
	HalExecElement* el = new HalExecElement(ID_SetDeviceChainInfo);
	el->appendInputData16(static_cast<uint16_t>(this->devHandle->getDevChainInfo()->getBusId()));
	cmd.elements.push_back(el);

	el = new HalExecElement(this->devHandle->checkHalId(ID_ExecuteFunclet));
	el->appendInputData16(static_cast<uint16_t>(ram->getStart() & 0xFFFF));
	el->appendInputData16(static_cast<uint16_t>(ram->getSize() & 0xFFFF));
	el->appendInputData16(programStartAddress);
	el->appendInputData32(static_cast<uint32_t>(erase_address));
	el->appendInputData32(eraseLength);
	el->appendInputData16(eraseType);
	el->appendInputData16(flags);
	el->appendInputData16(devHandle->getClockCalibration()->getCal0());
	el->appendInputData16(devHandle->getClockCalibration()->getCal1());

	//Dummy data to trigger execution of erase funclet
	el->appendInputData32(0xDEADBEEF);

	// set value for return length
	el->setOutputSize(2);
	cmd.elements.push_back(el);

	if (!this->devHandle->send(cmd))
	{
		return false;
	}
	return true;
}
bool FramMemoryAccessBaseFR57<MPU>::doWrite (uint32_t address, uint32_t* buffer, size_t count)
{
		if (count > this->getSize())
	{
		return false;
	}

	address += this->getStart();

	MemoryArea* ram = mm->getMemoryArea("system");
	if (ram == NULL)
	{
		return false;
	}	
			
	//32bit alignment
	const uint32_t alignedAddress = address & 0xfffffffc;
	const int frontPadding = address - alignedAddress;
	const int stubble = (address + count) % 4;
	const int backPadding = (4 - stubble) % 4;

	HalExecElement* el = new HalExecElement(this->devHandle->checkHalId(ID_WriteFramQuickXv2));
	el->appendInputData32(alignedAddress);
	el->appendInputData32( (static_cast<uint32_t>(count) + frontPadding + backPadding)/2 );

	vector<uint32_t> frontBuffer(frontPadding);
	vector<uint32_t> backBuffer(backPadding);

	if(frontPadding != 0)
	{
		mm->read(alignedAddress, &frontBuffer[0], frontPadding);
		mm->sync();
	}

	if(backPadding != 0)
	{
		mm->read(address+count, &backBuffer[0], backPadding);
		mm->sync();
	}

	for (int i = 0; i < frontPadding; ++i) 
	{
		el->appendInputData8(frontBuffer[i]);
	}

	for (size_t i = 0; i < count; ++i)
	{
		if (buffer[i] > 0xFF) 
		{
			delete el;
			return false;
		}
		el->appendInputData8(static_cast<uint8_t>(buffer[i]));
	}
			
	for (int i = 0; i < backPadding; ++i)
	{
		el->appendInputData8(backBuffer[i]);
	}

	this->elements.push_back(el);

	return true;		
}
bool FetControl::resetCommunication()
{
    std::vector<uint8_t> data;
    data.push_back(0x03);
    data.push_back(0x92);
    data.push_back(0x00);
    data.push_back(0x00);
    this->sendData(data);		// reset connection

    boost::this_thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(100));

    HalExecElement* el = new HalExecElement(ID_Zero);
    el->appendInputData8(STREAM_CORE_ZERO_VERSION);
    el->setOutputSize(12);

    HalExecCommand cmd;
    cmd.elements.push_back(el);

    const bool success = send(cmd);
    if(success)
    {
        fetSwVersion.push_back(el->getOutputAt8(0));
        fetSwVersion.push_back(el->getOutputAt8(1));
        fetSwVersion.push_back(el->getOutputAt8(2));
        fetSwVersion.push_back(el->getOutputAt8(3));
        fetHwVersion.push_back(el->getOutputAt8(4));
        fetHwVersion.push_back(el->getOutputAt8(5));
        fetHwVersion.push_back(el->getOutputAt8(6));
        fetHwVersion.push_back(el->getOutputAt8(7));


        unsigned char major=fetSwVersion.at(1);
        uint8_t minor = (major & 0x3f);
        uint8_t patch = fetSwVersion.at(0);
        uint16_t flavor = (fetSwVersion.at(3) << 8) + fetSwVersion.at(2);
        VersionInfo HalVersion((((major & 0xC0) >> 6) + 1), minor, patch, flavor);

        // this is the minimum hal version number for new eZ-FET or MSP-FET
        if (HalVersion.get() >= 30300000 ||
                (fetSwVersion[0] == 0xAA && fetSwVersion[1] == 0xAA && fetSwVersion[2] == 0xAA && fetSwVersion[3] == 0xAA) || /*eZ-FET*/
                (fetSwVersion[0] == 0xCC && fetSwVersion[1] == 0xCC && fetSwVersion[2] == 0xCC && fetSwVersion[3] == 0xCC) || /*MSP-FET UIF*/
                (fetSwVersion[0] == 0xAA && fetSwVersion[1] == 0xAB && fetSwVersion[2] == 0xAA && fetSwVersion[3] == 0xAB))   /*eZ-FET no DCDC*/
        {
            fetToolId	   = (el->getOutputAt16(8));
            fetCoreVersion = (el->getOutputAt16(10));
            fetHilVersion  = (el->getOutputAt16(12));
            fetDcdcLayerVersion  = (el->getOutputAt16(14));
            fetDcdcSubMcuVersion  = (el->getOutputAt16(16));
            fetComChannelVersion = (el->getOutputAt16(18));

            fetHilCrc = (el->getOutputAt16(20));
            fetHalCrc = (el->getOutputAt16(22));
            fetDcdcCrc = (el->getOutputAt16(24));
            fetCoreCrc = (el->getOutputAt16(26));
            fetComChannelCrc = (el->getOutputAt16(28));

            if((fetSwVersion[0]  != 0xAA && fetSwVersion[1] != 0xAA && fetSwVersion[2] != 0xAA && fetSwVersion[3] != 0xAA) &&  /*eZ-FET*/
                    (fetSwVersion[0] != 0xCC && fetSwVersion[1] != 0xCC && fetSwVersion[2] != 0xCC && fetSwVersion[3] != 0xCC) &&  /*MSP-FET UIF*/
                    (fetSwVersion[0] != 0xAA && fetSwVersion[1] != 0xAB && fetSwVersion[2] != 0xAA && fetSwVersion[3] !=  0xAB))   /*eZ-FET no DCDC*/
            {
                // reset global vars
                HalExecCommand ResetCmd;
                HalExecElement* el = new HalExecElement(ID_ResetStaticGlobalVars);
                ResetCmd.elements.push_back(el);
                this->send(ResetCmd);
            }
        }
        else if(HalVersion.get() <= 30300000 && HalVersion.get() >= 30000000) // this handles an older verion of MSP-FET430UIF
        {
            fetToolId = 0xCCCC;
            fetCoreVersion = (el->getOutputAt16(8));
            fetSafeCoreVersion = (el->getOutputAt16(10));
        }
        else
        {
            fetToolId = 0x1111;
        }
    }
    return success;
}
bool DebugManagerV3::run (uint16_t controlMask, DebugEventTarget * cb, bool releaseJtag)
{
	MemoryManager* mm = this->parent->getMemoryManager();
	MemoryArea* cpu = mm->getMemoryArea("CPU"); 
	if (!cpu)
    {
		return false;
    }

	lpm5WakeupDetected = false;

	if(cb!=0)
	{
		cbx=cb;	
	}

	uint32_t pc, sr;
	cpu->read(0, &pc, 1);
	cpu->read(2, &sr, 1);

	if(mm->flushAll()==false)
	{
		return false;
	}
	
	cycleCounter_.reset();
	ConfigManager *cm = parent->getFetHandle()->getConfigManager();

	const uint16_t mdb = parent->getEmulationManager()->getSoftwareBreakpoints()->getSwbpManager()->getInstructionAt(pc);
	if (mdb != 0)
	{
		mdbPatchValue = mdb;
	}

	HalExecElement* el = new HalExecElement(this->parent->checkHalId(ID_RestoreContext_ReleaseJtag));
	this->parent->getWatchdogControl()->addParamsTo(el);
	el->appendInputData32(pc);
	el->appendInputData16(sr);
	el->appendInputData16(controlMask!=0? 0x0007: 0x0006);	// eem control bits 
	el->appendInputData16(mdbPatchValue);		// mdb
	el->appendInputData16(releaseJtag ? 1 : 0);
	el->appendInputData16(cm->ulpDebugEnabled() ? 1 : 0);

	mdbPatchValue = 0;

	HalExecCommand cmd;
	cmd.elements.push_back(el);

	if (!this->parent->send(cmd))
	{
		return false;
	}
	
	// handle lpmx5 polling
	if (releaseJtag)
	{
		pausePolling();
	}
	else
	{
		this->resumePolling();
	}	

	if (controlMask!=0 && !releaseJtag)
	{
		if (!activatePolling(controlMask))
		{
			return false;
		}
	}

	resetCycleCounterBeforeNextStep = true;

	return true;
}