//----------------------------------------------------
/**
	\file		ctk/inc/nvmem.h
	\ingroup	hardware
	\ingroup	all

	\brief	Obecny typ nevolatilni pameti
			<<< ALL >>>

	\author	ConTeK s.r.o., Ing. Vladimir Kastner
	\version	01.01
	\date	12.01.2007
*/
//----------------------------------------------------

#ifndef _NVMEM_H_
#define _NVMEM_H_		//!< Definice pritomnosti knihovny

#include <ctktypes.h>


//----------------------------------------------------
/**
	\brief	Konstanty definujici status transakce
*/
//----------------------------------------------------
//@{
#define MMS_SUCCESS				0	//!< Transakce byla úspěšně dokončena
#define MMS_PENDING				1	//!< Transakce probíhá
#define MMS_BUS_ERROR			2	//!< Chyba transakce
#define MMS_INVALID_PAGE_SIZE	3	//!< Zadana neplatna velikost stranky
#define MMS_INVALID_PAGE_NUMBER	4	//!< Neplatny index stranky
#define MMS_INVALID_ADDR		5	//!< Neplatna adresa
#define MMS_INTERNAL_ERROR		6	//!< Vnitrni blize nespecifikovana chyba
#define MMS_OOM					7	//!< Nedostatek pameti pro transakci
#define MMS_ADDR_EMPTY			8	//!< Ctena adresa neobsahuje data
#define MMS_PAGE_ERROR			9	//!< Hledana stranka neni platna
#define MMS_INVALID_CMD			10	//!< Nepovoleny pozadavek
#define MMS_VERIFY_FAULT		11	//!< Neuspesna verifikace
#define MMS_WRITE_DATA_OVERSIZE	12	//!< Zapisovany blok dat je prilis velky
//@}

//----------------------------------------------------
/**
	\brief	Typy pameti
*/
//----------------------------------------------------

//----------------------------------------------------
//! \brief	Typ pameti
typedef enum
{
	// fyzicke typy pameti
	MEM_TYPE_UNDEFINED			= 0,	//!< Nedefinovana
	MEM_TYPE_RAM				= 1,	//!< RAM
	MEM_TYPE_ROM				= 2,	//!< ROM
	MEM_TYPE_IO					= 3,	//!< IO
	MEM_TYPE_NVRAM				= 4,	//!< NVRAM
	MEM_TYPE_FRAM				= 5,	//!< FRAM
	MEM_TYPE_FLASH				= 6,	//!< Flash
	MEM_TYPE_EEPROM				= 7,	//!< EEPROM
	MEM_TYPE_SDRAM				= 8,	//!< SDRAM
	MEM_TYPE_SRAM				= 9,	//!< SRAM
	MEM_TYPE_DATAFLASH			= 10,	//!< Data Flash

	// logicke typy pameti
	MEM_TYPE_FILE				= 100,	//!< Soubor
	MEM_TYPE_FLASHFS			= 101,	//!< Pamet ovladana knihovnou flashfs
	MEM_TYPE_BACKLOG			= 102,	//!< Pamet jistena backlogem

	MEM_TYPE_MAX						//!< Maximum memtype

} MEM_TYPE;


//----------------------------------------------------
//!		Typ adresy nevolatilni pameti

typedef uint32_t		nvptr_t;

struct _NVMEMDESC;

typedef void (* nvmMemTick_t) (struct _NVMEMDESC * const _memD);
typedef void (* nvmMemRead_t) (struct _NVMEMDESC * const _memD, void * const _ramPtr, nvptr_t _memPtr, nvptr_t _size);
typedef void (* nvmMemVerify_t) (struct _NVMEMDESC * const _memD, const void * const _ramPtr, nvptr_t _memPtr, nvptr_t _size);
typedef void (* nvmMemWrite_t) (struct _NVMEMDESC * const _memD, const nvptr_t _memPtr, const void * const _ramPtr, const nvptr_t _size);
typedef void (* nvmMemRestart_t) (const struct _NVMEMDESC * const _memD);

//----------------------------------------------------
//!	Struktura kontextu automatu

typedef struct _NVMEMDESC
{
	volatile bool_t		flRunning;		//!< je inicializovano, po ininializaci na TRUE, pred ukoncenim FALSE
	volatile uint8_t	Status;			//!< Status viz. MMS_xxx
	volatile uint8_t	State;			//!< Stav automatu

	nvmemlock_t		Lock;			//!< Zamek pameti

	nvmMemTick_t	MemTick;	//!< Tick automatu nevolatilni pameti
	nvmMemRead_t	MemRead;	//!< Cteni z nevolatilni pameti
	nvmMemVerify_t	MemVerify;	//!< Porovnani obsahu pameti s bufferem
	nvmMemWrite_t	MemWrite;	//!< Zapis do nevolatilni pameti
	nvmMemRestart_t MemRestart;	//!< Provede reinicializaci pameti

	union {
		const void * RO;		//!< Read only
		void * 	RW;				//!< Read / write
	} RamPtr;					//!< Ukazatel do RAM
	nvptr_t		MemPtr;			//!< Ukazatel do nevolatilni pameti
	nvptr_t		DataSize;		//!< Delka prenasenych dat

	nvptr_t		NvMemSize;		//!< Velikost nevolatilni pameti
	nvptr_t		PageSize;		//!< Velikost stranky, nema-li pamet stranky, pak 0
	MEM_TYPE	NvMemType;		//!< Typ pameti
	nvptr_t		MaxReadSize;	//!< Maximalni velikost bloku dat, ktery je pamet schopna precist naraz
	nvptr_t		MaxWriteSize;	//!< Maximalni velikost bloku dat, ktery je pamet schopna zapsat naraz
} NVMEMDESC;


//----------------------------------------------------
/**
	\brief	Funkce testuje dokončení předchozí operace

	\return	Funkce vrací nenulovou hodnotu v případě,
			že poslední operace byla dokončena
*/
//----------------------------------------------------

static inline bool_t NvMemReady(const NVMEMDESC * const _ctx)
{
	return (((volatile const NVMEMDESC *)_ctx)->Status != MMS_PENDING);
}


//----------------------------------------------------
/**
	\brief	Uzamkne pamet

	\param	_ctx		Kontext

	\note	Vyvola assert, pokud byla pamet jiz uzamcena
*/
//----------------------------------------------------

void NvMemLock(NVMEMDESC * const _ctx);


//----------------------------------------------------
/**
	\brief	Pokusi se uzamknout pamet

	\param	_ctx		Kontext

	\return		TRUE, pokud se uzamceni podarilo; FALSE, pokud byla pamet jiz predtim uzamcena
*/
//----------------------------------------------------

bool_t NvMemTryLock(NVMEMDESC * const _ctx);


//----------------------------------------------------
/**
	\brief	Odemkne pamet

	\param	_ctx		Kontext

	\note	Vyvola assert, pokud pamet nebyla uzamcena
*/
//----------------------------------------------------

void NvMemUnlock(NVMEMDESC * const _ctx);


//----------------------------------------------------
/**
	\brief	Funkce pro inicializaci pristupu k nevolatilni pameti

	\param	memD	struktura kontextu automatu

	\return	TRUE	inicializace probehla v poradku
			FALSE	chyba
*/
//----------------------------------------------------

bool_t NvMemInitialize(
		NVMEMDESC * const _memD,
		const MEM_TYPE _memType,
		const nvptr_t _nvMemSize,
		const nvptr_t _nvPageSize,
		const nvptr_t _maxReadSize,
		const nvptr_t _maxWriteSize);


//----------------------------------------------------
/**
	\brief	Funkce pro ukonceni pristupu k nevolatilni pameti

	\param	memD	struktura kontextu automatu
*/
//----------------------------------------------------

void NvMemFinalize(const NVMEMDESC * const _memD);

#endif // _NVMEM_H_
