/*
Copyright 2007, Freie Universitaet Berlin. All rights reserved.

These sources were developed at the Freie Universität Berlin, Computer
Systems and Telematics group.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

- Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

This software is provided by FUB and the contributors on an "as is"
basis, without any representations or warranties of any kind, express
or implied including, but not limited to, representations or
warranties of non-infringement, merchantability or fitness for a
particular purpose. In no event shall FUB or contributors be liable
for any direct, indirect, incidental, special, exemplary, or
consequential damages (including, but not limited to, procurement of
substitute goods or services; loss of use, data, or profits; or
business interruption) however caused and on any theory of liability,
whether in contract, strict liability, or tort (including negligence
or otherwise) arising in any way out of the use of this software, even
if advised of the possibility of such damage.

This implementation was developed by the CST group at the FUB.

For documentation and questions please use the web site
http://scatterweb.mi.fu-berlin.de and the mailinglist
scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
Berlin, 2007
*/

/**
 * \defgroup	reprog	(Re-) Programming
 *
 * <h2>MSP430 flash memory introduction</h2>
 *
 * <p>The internal flash memory is divided in several 512 byte segments.<br>
 * Exceptions: The MSP430F169s and MSP430F1612s n-th segment (the first one above the RAM) is
 * only 256 byte large.</p>
 *
 * <p>The memory is byte and word addressable. Memory can be erased only in whole segments. Cleared memory is set to
 * 0xFF for every byte. Writing memory basically means setting bits from 1 to 0. Therefore its even possible to
 * write single bits.</p>
 *
 * <p>Writing or erasing memory can be done from code within the flash or RAM. Please note the following information
 * regarding the process:
 * <ul>
 * 	<li>The cpu is halted if erasing or writing from flash memory.</li>
 * 	<li>If the process is initialized from RAM the cpu continues code execution - don't access
 * 		flash until BUSY flag in FCTL3 is reset!!! (or else unpredictable flash results are possible
 * 		due to a system reset)</li>
 * </ul>
 * Before manipulation the flash memory you should also switch the interrupts (see IE1) and watchdog (see WDTCTL and \ref stopWatchdog) off
 * and save the timer register (see TAR) if necessary for time critical applications.
 * </p>
 *
 * <p>You have to take care not to overwrite the area used by the compiler (and linker) to store
 * program code. Usually the end of the used memory is depicted by <tt>\ref __noinit_end_rom</tt>. Every segment
 * above this address until the end of the flash rom at 0xFFFF (minus 1 segment because of the interrupt vector
 * table) may be used.</p>
 *
 * <p> Memory segmentation of the MSP430F1612:
 * <table style="width: 100%" class="style2">
	<tr>
		<th style="width: 73px">Area</th>
		<th style="width: 119px">Address</th>
		<th style="width: 92px">Label</th>
		<th>Description</th>
	</tr>
	<tr>
		<td rowspan="17" style="width: 73px">Flash ROM</td>
		<td style="width: 119px" >0xFFFF</td>
		<td style="width: 92px">&nbsp;</td>
		<td rowspan="2">Segment 0<br />
		incl. IVT at [0xFFFF - 0xFFE0]</td>
	</tr>
	<tr>
		<td style="width: 119px" >0xFE00</td>
		<td style="width: 92px">&nbsp;</td>
	</tr>
	<tr>
		<td style="width: 119px" >0xFDFF</td>
		<td style="width: 92px">&nbsp;</td>
		<td rowspan="2" >Segment 1<br />
		(free space)</td>
	</tr>
	<tr>
		<td style="width: 119px" >0xFC00</td>
		<td style="width: 92px">&nbsp;</td>
	</tr>
	<tr>
		<td style="width: 119px" >&nbsp;</td>
		<td style="width: 92px">&nbsp;</td>
		<td >Multiple Segments<br />
		(free space)</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x????<br />
		(Segment border)</td>
		<td style="width: 92px">&nbsp;</td>
		<td  rowspan="6">Multiple Segments<br />
		(used)</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x????</td>
		<td style="width: 92px">\ref __noinit_end_rom</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x????</td>
		<td style="width: 92px">__noinit_start_rom</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x????</td>
		<td style="width: 92px">__data_end_rom</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x????</td>
		<td style="width: 92px">__data_start_rom</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x????</td>
		<td style="width: 92px">\ref __app_end</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x29FF</td>
		<td style="width: 92px">&nbsp;</td>
		<td rowspan="2" >Segment n-2<br />
		(used)</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x2800</td>
		<td style="width: 92px">&nbsp;</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x27FF</td>
		<td style="width: 92px">&nbsp;</td>
		<td rowspan="2" >Segment n-1<br />
		(used)</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x2600</td>
		<td style="width: 92px">&nbsp;</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x25FF</td>
		<td style="width: 92px">&nbsp;</td>
		<td rowspan="2" >Segment n<br />
		(used)</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x2500</td>
		<td style="width: 92px">\ref __app_header<br />
		\ref __app_start</td>
	</tr>
	<tr>
		<td rowspan="2" style="width: 73px">RAM</td>
		<td style="width: 119px" >0x24FF</td>
		<td style="width: 92px"><strong>__</strong>stack</td>
		<td  rowspan="2">&nbsp;</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x1100</td>
		<td style="width: 92px">&nbsp;</td>
	</tr>
	<tr>
		<td rowspan="4" style="width: 73px">Infomem</td>
		<td style="width: 119px" >0x10FF</td>
		<td style="width: 92px">&nbsp;</td>
		<td  rowspan="2">Segment A</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x1080</td>
		<td style="width: 92px">&nbsp;</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x107F</td>
		<td style="width: 92px">&nbsp;</td>
		<td  rowspan="2">Segment B</td>
	</tr>
	<tr>
		<td style="width: 119px" >0x1000</td>
		<td style="width: 92px">__infomem</td>
	</tr>
</table>

 * <p>If you would like to learn more about memory management, have a look at the default linker script in
 * <tt>System/lddefault.x</tt> and after compiling an application at the memory map file <tt>APPLICATION/out/APPLICATION.map</tt>.</p>
 *
 * <p>To modify the information memory please have a look at the \ref infomem description.
 *
 * <p>For further information please refer to Texas Instruments documentation (slau049f.pdf and msp430f1612.pdf).</p>
 *
 */

/**
 * @file	ScatterWeb.Programming.h
 * @brief	Necessary function to reprogram the MSP430 microcontroller
 * @ingroup	reprog
 * @author	Bastian Blywis, et al
 * @version	$Revision: 277 $
 * @since	1.0
 */

#ifndef _PROGRAMMINGH_
#define _PROGRAMMINGH_

#include <signal.h>
#include <ScatterWeb.TypeDefs.h>

/**
 * @name Compile time configuration
 */
//@{
#ifndef __COMPILE_TIME
	#define __COMPILE_TIME
	#error "Define __COMPILE_TIME through compiler to current UTC time."
#endif
#ifndef __PLATFORM
	#define __PLATFORM		"MSB430  "	///< default platform definition
	#define __PLATFORM_REV	1			///< default platform revision
#endif
//@}

/**
 * @brief Application header
 *
 * Macro defining the application header
 */
#define APPHEADER(name, type, hwName, hwRev, appName, appVerH, appVerL, fpReset)	\
	const appHeader_t name = {														\
		type ,																		\
		hwName , hwRev ,															\
		appName ,{ appVerH , appVerL },												\
		(uint16_t) fpReset,															\
		__COMPILE_TIME ,															\
		( type + hwRev + appVerH + appVerL + __COMPILE_TIME ) % 0xFF				\
	}

/**
 * @brief Application header
 *
 * Application header type
 */
typedef struct {
	uint8_t		type;
	uint8_t		platformName[9];	///< name of supported hardware platform (8 chars + CHAR_NULL)
	uint8_t		platformRev;		///< revision of supported hardware platform
	uint8_t		appName[9];			///< name of application (8 chars + CHAR_NULL)
	uint8_t		appVer[2];			///< major and minor version of application
	uint16_t	resetAdr;			///< address of application reset function
	uint32_t	compileTime;		///< compile time in seconds since 1970-01-01 00:00:00 UTC
	uint8_t		checksum;			///<
} appHeader_t; // 30 bytes

/**
 * @brief Convert value to pointer
 * @param x address
 *
 * Convert/cast a given value to pointer.
 */
#define ADRTOPTR(x)      (*((uint16_t*)x))

/**
 * @brief Pointer defined by the linker script at the application start.
 */
extern uint16_t __app_start;

/**
 * @brief Pointer defined by the linker script at the application end.
 */
extern uint16_t __app_end;

/**
 * @brief Pointer defined by the linker script at the firmware start.
 */
extern uint16_t __bld_start;

/**
 * @brief Pointer defined by the linker script at the firmware end.
 * @since		1.1
 * @see			appHeader_t, LOADER_INSTALLED
 */
extern uint16_t __bld_end;

/**
 * @brief		Pointer to bootloader header (if installed)
 * @since		1.1
 * @see			appHeader_t, LOADER_INSTALLED
 */
extern uint16_t __bld_header;

/**
 * @brief		Pointer to operating system header
 * @since		1.1
 * @see			appHeader_t, LOADER_INSTALLED
 */
extern uint16_t __eos_header;

/**
 * @brief		Pointer to application header
 * @since		1.1
 * @see			appHeader_t, LOADER_INSTALLED
 */
extern uint16_t __app_header;

/**
 * @brief		Pointer to the last used address in memory
 * @since		1.2
 */
extern uint16_t __noinit_end_rom;

/**
 * @name Public interface
 * @{
 */

/**
 * @brief Software header.
 * Theses variables are defined by the linker script, they are needed in the
 * software header
 */
extern const appHeader_t	appHeader;

/**
 * @brief Number of libraries
 *
 * Contains the number of libraries linked into the firmware image.
 */
extern const uint8_t		library_count;

/**
 * @brief Names of used libraries
 *
 * Lists the names of all libraries linked into the firmware image.
 */
extern const char*			library_names[];

/**
 * @brief Application macro
 *
 * Used in each ScatterWeb.Process.c
 */
#define APP(type, appName, appVerH, appVerL)												\
	extern void __attribute__((__noreturn__))	_reset_vector__(void);						\
	const uint8_t library_count = LIBRARY_COUNT;											\
	const char* library_names[] = { LIBRARY_STRINGLIST };									\
	const fp_t	library_init[] = { LIBRARY_INIT };											\
	__attribute__((section(".app_header")))													\
	APPHEADER( appHeader, type, __PLATFORM, __PLATFORM_REV, appName, appVerH, appVerL,		\
	&_reset_vector__ )

/**
 * @brief ???
 *
 * @todo document Prog_TestMetadata
 */
bool Prog_TestMetadata( appHeader_t* md );

/**
 * @brief ???
 *
 * @todo document Prog_EnableBootloader
 */
bool Prog_EnableBootloader(bool state);

/**
 * @brief Clear flash memory segment
 * @param Data_ptr clear the segment containing this address
 *
 * Clear a flash memory segment
 */
void Prog_Flash_clr(uint16_t* Data_ptr);

/**
 * @brief Write word to flash memory segment
 * @param Data_ptr write to this address
 * @param word data to write
 *
 * Write a word to a given flash memory address.
 */
void Prog_Flash_ww(uint16_t* Data_ptr, uint16_t word);

/**
 * @brief Application header flags
 */
enum APPH_Flags {
	APPH_VERSION	= 0x00, ///< version
	APPH_FLASHABLE	= 0x20,	///< set if device flashable
	APPH_LOADER		= 0x40,	///< set if loader present
	APPH_OS			= 0x80	///< OS
};

#define APPH_FLAG_MASK				0xF8
#define APPH_VERSION_MASK			0x07

#define	APPH_STATIC_APP 			APPH_VERSION
#define	APPH_FLASHABLE_APP			(APPH_VERSION | APPH_FLASHABLE)

///@}
#endif
