bool MemoryAreaBase::sync ()
{
	if (!preSync())
		return false;

	if (this->elements.empty())
		return true;

	HalExecCommand cmd;
	cmd.setTimeout(60000);

	if (!sendWithChainInfo(&this->elements,&cmd))
		return false;

	return postSync(cmd);
}
bool MemoryAreaBase::verify(uint32_t address, uint32_t* buffer, size_t count)
{
	MemoryCacheCtrl* cc = this->getCacheCtrl(); 
	if (cc && !cc->flush(address,count))
		return false;

	if (address & 0x1) 
	{
		uint32_t tmp = 0;	
		if (!this->read(address++, &tmp, 1) || !this->sync())
			return false;

		if (buffer? tmp != *(buffer++): tmp != 0xFF)
			return false;

		--count;
	}

	if (count > 1) 
	{
		HalExecCommand cmd;
		cmd.setTimeout( max((size_t)20000, count/15) ); //Set timeout according to data size
		
		HalExecElement*el = new HalExecElement(this->devHandle->checkHalId(ID_Psa));
		el->appendInputData32(static_cast<uint32_t>((address+this->getStart()) & 0xFFFFFFFF));
		el->appendInputData32(static_cast<uint32_t>((count / 2) & 0xFFFFFFFF));
		el->appendInputData8(this->psaType);
		el->setOutputSize(2);
		cmd.elements.push_back(el);
		if (!this->devHandle->send(cmd))
			return false;
		
		if (MemoryAreaBase::psa(address+this->getStart(), buffer, (size_t)((uint32_t)count&0xfffffffe)) != el->getOutputAt16(0))
			return false;				
	}

	if (count & 1) 
	{
		uint32_t tmp = 0;
		if (!this->read(address + count - 1, &tmp, 1) || !this->sync())
			return false;

		if (buffer? tmp != buffer[count - 1]: tmp != 0xFF)
			return false;
	}
	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 FetControl::send (HalExecCommand& command, function_map_type* fctMap)
{
    boost::recursive_mutex::scoped_lock lock(sendMutex);
    this->channel->setFunctionMap(fctMap);
    return command.send(*this, *this->channel);
}