diff BootLoader/Src/base_bootlader.c @ 30:ea1003f63e44

ADD GPL License ...
author jDG
date Tue, 23 Jan 2018 17:29:40 +0100
parents 97eafbcb81a9
children 7801c5d8a562
line wrap: on
line diff
--- a/BootLoader/Src/base_bootlader.c	Tue Jan 23 13:36:25 2018 +0100
+++ b/BootLoader/Src/base_bootlader.c	Tue Jan 23 17:29:40 2018 +0100
@@ -1,1516 +1,1516 @@
-/**
-  ******************************************************************************
-	* @copyright heinrichs weikamp
-  * @file   		base_bootlader.c
-  * @author 		heinrichs/weikamp, Christian Weikamp
-  * @date   		26-February-2014
-  * @version		V1.0.4
-  * @since			09-Jan-2016
-  * @brief			The beginning of it all. main() is part of this.
-	*							 + Do the inits for hardware
-	*							 + check for button press or update process reset trigger
-	*							 + Do the inits for sub-systems like menu, dive screen etc.
-	*							 + Start IRQs
-	*							 + Start MainTasks not in IRQs
-	* @bug
-	* @warning
-  @verbatim
-	
-  ==============================================================================
-              ##### bootloader specific #####
-  ==============================================================================
-
-	151130	chsw	sleep on button3 
-								(MX_tell_reset_logik_alles_ok() + DataEX_call() in endlos loop)
-	
-	==============================================================================
-              ##### bootloader specific #####
-  ==============================================================================
-
-	Bootloader info is set right here in this file.
-	The location is 0x0800A000 instead of 0x08050000 (firmware)
-	
-	on system reset (Menu Start Bootloader in firmware) the update process
-	is started automatically if no button is pressed
-
-	if the right button is pressed the bootloader menu is started
-	
-	after update process (with update or empty) cleaning of EEPROM is started
-	afterwards the watchdog reset starts without activating the update process
-
-	bluetooth chip is started in tComm on start of the mini bootloader firmware
-	
-	SMALLCPU_CSB_PIN must be re-set to 0 to communicate with small CPU / CPU2 / RTE 
-	
-	for RealTerm to send file / firmware, Delays has to be increased to 0
-	
-	RTE update / SPI1 with DMA gave IBUSERR, now it is working fine :-) 150828
-	==============================================================================
-	from standard firmware, parts might be invalid here:
-	==============================================================================
-              ##### IRQs #####
-  ==============================================================================
-  [..] The IRQs are very important and most functions should only run there.
-
-				PreemptPriority are as follows
-				(#) 2 (low)		sprintf _only_ here. Don't use in maintask or anywhere else.
-											Called by Buttons und Timer3
-											Timer3 is 1/10 second
-				(#) 1 (mid)		anything that should work while in IRQ2 like HalDelay(), VSYNC
-											and DMA2D Transfer Complete for housekeepingFrame();
-				(#)	0 (high)	_very very short_ interrupts like The HAL hardware part for
-											spi, uart, i2c.
-
-				SubPriority within 	PreemptPriority give the order to execute.
-				Introduced 30.Oct.14 as it used by several HAL examples.
-				Three levelAmbients are available (2 low,1 mid,0 high)
-
-				The STM32F4 has 4bits for IRQ levelAmbients, divided 2/2 in this code
-				with the NVIC_PRIORITYGROUP_2 setting.
-
-  ==============================================================================
-              ##### MainTask #####
-  ==============================================================================
-  [..] For everthing slow without importance to be 'in time'.
-			 Like VPM and Buehlmann.
-			 No sprintf and probably no GFX_SetFramesTopBottom() stuff neither.
-			 If sprintf is called while sprintf is executed it blows up everything.
-
-  ==============================================================================
-              ##### Frames / the external SDRAM #####
-  ==============================================================================
-  [..] The SDRAM is handled by getFrame() and releaseFrame().
-			 Each frame with 800*480*2 Bytes.
-			 Be carefull to release every frame
-			 otherwise there will be a memory leakage over time.
-			 housekeepingFrame() in the MainTask takes care of cleaning the frames.
-			 All frames are filled with 0x00. This will be transparent with color of
-			 CLUT_Font020 (is CLUT 0) if the alpha is set for a 16bit pair.
-			 housekeepingFrame() delays the cleaning of frames still used as screen
-			 buffer to prevent flickering.
-
-  ==============================================================================
-              ##### Display #####
-  ==============================================================================
-  [..] There is a Top layer, Bottom layer and background color.
-			 All are perfectly alpha-blended by hardware.
-
-				(#) top layer			has 800x480 option function calls only
-													as it is not used for cursors here
-				(#)	bottom layer	has free size and start option to be used
-													for cursors (or sprites in the future ;-)
-				(#) background		only black in the moment.
-													ToDo: Could be anything else for warnings etc.
-													if needed
-
-	[..] Frame updates, switching and cursors is done with
-
-				(#) GFX_SetFramesTopBottom() and the subset
-						GFX_SetFrameTop() + GFX_SetFrameBottom()
-						Those do not change anything on the display but give commands to..
-				(#) GFX_change_LTDC()	The only place that changes the pointer.
-															This prevents erratic behaviour if several changes
-															are made within one refresh rate of the screen.
-															Is called in IRQ by PD4 and HAL_GPIO_EXTI_IRQHandler
-															from VSYNC signal.
-
-	[..] Content
-
-				(#) Colors	by LookupTable only. This could be modified by
-										system settings in the future. (gfx_color.h/.c)
-
-				(#) Text		by text_multilinguage.h/.c with one char
-										necessary only starting from '\x80'
-										with automatic language switch by
-										selected_language in SSettings
-										see openEdit_Language() in tMenuEditSystem.c
-										Therefore there are differnent functions
-										for example:
-										write_label_fix() for single char multilanguage
-										write_label_var() for strings that could include
-										multilanguage as well
-										see GFX_write_string() to get an overview of the controls
-										as well as the command list in gfx_engine.h
-										There is no clear before writing, text overlay is always on.
-										Many options to have LargeFont.SmallFont for numbers etc.
-
-  ==============================================================================
-              ##### Update, DualBoot and build-in FLASH memory usage #####
-  ==============================================================================
-  [..] Boot0 pin, Boot1/PB2 pin and BFB2 software bit control the behaviour.
-				PB2 should be tied to GND.
-				Boot0 == VDD -> bootloader on start, otherwise boot from Bank1 or Bank2
-				depending on BFB2.
-				Bank2 contains the Fonts and should contain a proper test code in future
-				Bank1 is the main code (Bank1 is 1 MB too, usage as of Oct. 14 is 200 KB)
-	[..] Bootloader should be either UART or USB (on FS pins _only_)
-				USB HS to FS like on the Eval board does not work.
-	[..] Bootloader for the smaller CPU2 is implemented via the SPI used for DMA copy.
-
-  ==============================================================================
-              ##### Connection to CPU2 (STM32F411 as of Oct.14 #####
-  ==============================================================================
-  [..] Connected via SPI and DMA for every purpose.
-				two entire arrays are transfered for data security reasons
-				with respect to master (STM32F429) might interrupt internal
-				data copy in CPU2 (like hi byte, low byte, etc.).
-	[..] The entire life data is calculated in CPU2. Like tissues, CNS,...
-				Therefore the main unit is _not_ necessarily a Real Time system.
-				Simulation on the main unit can be executed without disrupting life data.
-	[..] SPI is triggered and timed by calling DataEX_call() in data_exchange_main.c
-				DataEX_copy_to_LifeData() does the transfer from buffer to variables used.
-
-  ==============================================================================
-              ##### Menu, MenuEdit, Info #####
-  ==============================================================================
-  [..] tMenu.c, tMenuEdit.c and tInfo.c is the system used.
-				logbook is part of Info not Menu.
-				The Info Menu is accessed by button 'Back'
-				The regular Menu is accessed by button 'Enter'
-	[..] Menu content is kept in frame memory for fast access.
-				There is no need to build pages if the 'Enter' button is pressed.
-				This is in contrast to MenuEdit pages.
-	[..] Button control for new pages (and pages in general) have to implemented
-				in tMenu.c, tMenuEdit.c or tInfo.c
-
-	[..] ToDo (Oct. 14) Timeout for menus via Timer3 / IRQ 2
-
-  ==============================================================================
-              ##### specials #####
-  ==============================================================================
-  [..] There was code for vector graphics from great demos
-				(peridiummmm and jupiter) that can be fitted again
-
-	 @endverbatim
-  ******************************************************************************
-  * @attention
-  *
-  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
-  *
-  ******************************************************************************
-  */
-
-/* Includes ------------------------------------------------------------------*/
-#include "base_bootloader.h"
-
-// From Bootloader/Inc:
-#include "tInfoBootloader.h"
-
-// ?
-#include "externLogbookFlash.h"
-#include "firmwareEraseProgram.h"
-#include "firmwareJumpToApplication.h"
-
-// From Common/Inc:
-#include "FirmwareData.h"
-
-// From Common/Drivers:
-#include "stm32f4xx_hal.h"
-#include "stm32f4xx_hal_rcc.h"
-#include "stm32f4xx_hal_flash_ex.h"
-#include "stm32f4xx_hal_wwdg.h"
-
-// From Discovery/Inc (shall be shared...)
-#include "data_exchange_main.h"
-#include "display.h"
-#include "gfx_engine.h"
-#include "ostc.h"
-#include "tComm.h"
-#include "tStructure.h"
-
-// From AC6 support:
-#include <stdio.h>
-#include <string.h> // for memcopy
-
-/** @addtogroup OSTC 4
-  * @{
-  */
-
-/* Private typedef -----------------------------------------------------------*/
-/* Private define ------------------------------------------------------------*/
-#define BUFFER_SIZE         ((uint32_t)0x00177000)
-#define WRITE_READ_ADDR     ((uint32_t)0x0000)
-#define REFRESH_COUNT       ((uint32_t)0x0569)   /* SDRAM refresh counter (90Mhz SD clock) */
-
-/* Private macro -------------------------------------------------------------*/
-/* Private variables ---------------------------------------------------------*/
-uint8_t returnFromCommCleanUpRequest = 0;
-
-const SFirmwareData bootloader_FirmwareData __attribute__(( section(".bootloader_firmware_data") )) =
-{
-    .versionFirst   = 1,
-    .versionSecond  = 0,
-    .versionThird   = 1,
-    .versionBeta    = 1,
-
-	/* 4 bytes with trailing 0 */
-	.signature = "cw",
-	
-	.release_year   = 16,
-	.release_month  = 4,
-	.release_day    = 8,
-	.release_sub    = 0,
-	
-	/* max 48 with trailing 0 */
-	.release_info ="tComm with all",
-	
-	/* for safety reasons and coming functions*/
-	.magic[0] = FIRMWARE_MAGIC_FIRST,
-	.magic[1] = FIRMWARE_MAGIC_SECOND,
-	.magic[2] = FIRMWARE_MAGIC_FIRMWARE, /* the magic byte */
-	.magic[3] = FIRMWARE_MAGIC_END
-};
-
-
-const SHardwareData HardwareData __attribute__((at(HARDWAREDATA_ADDRESS))) = {
-
-	// first 52 bytes
-	.primarySerial = 0xFFFF,
-	.primaryLicence	= 0xFF,
-	.revision8bit = 0xFF,
-	.production_year = 0xFF,
-	.production_month = 0xFF,
-	.production_day = 0xFF,
-	.production_bluetooth_name_set = 0xFF,
-
-	.production_info = {
-		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
-
-	// other 12 bytes (64 in total)
-	.secondarySerial = 0xFFFF,
-	.secondaryLicence = 0xFF,
-	.secondaryReason8bit = 0xFF,
-	.secondary_year = 0xFF,
-	.secondary_month = 0xFF,
-	.secondary_day = 0xFF,
-	.secondary_bluetooth_name_set = 0xFF,
-	.secondary_info = {0xFF,0xFF,0xFF,0xFF}
-};
-
-
-RTC_HandleTypeDef	RtcHandle;
-TIM_HandleTypeDef   TimHandle; /* used in stm32f4xx_it.c too */
-TIM_HandleTypeDef   TimBacklightHandle; /* used in stm32f4xx_it.c too */
-
-uint32_t time_before;
-uint32_t time_between;
-uint32_t time_after;
-
-/* SDRAM handler declaration */
-SDRAM_HandleTypeDef hsdram;
-FMC_SDRAM_TimingTypeDef SDRAM_Timing;
-FMC_SDRAM_CommandTypeDef command;
-
-FLASH_OBProgramInitTypeDef    OBInit;
-FLASH_AdvOBProgramInitTypeDef AdvOBInit;
-
-
-/* Private variables with external access ------------------------------------*/
-
-uint32_t globalStateID = 0;
-uint8_t globalModeID = SURFMODE;
-uint32_t time_without_button_pressed_deciseconds = 0;
-uint8_t bootToBootloader = 0;
-
-/* Private function prototypes -----------------------------------------------*/
-
-//static void LCD_ToggleFramebuffer(GFX_DrawCfgTypeDef *hconfig);
-//static void LCD_Config(GFX_DrawCfgTypeDef *hconfig);
-static void SystemClock_Config(void);
-static void Error_Handler(void);
-
-static void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command);
-static void SDRAM_Config(void);
-//static void DualBoot(void);
-static void EXTILine_Buttons_Config(void);
-//static void RTC_init(void);
-static void TIM_init(void);
-static void TIM_BACKLIGHT_init(void);
-//static void TIM_BACKLIGHT_adjust(void);
-static void gotoSleep(void);
-uint8_t checkResetForFirmwareUpdate(void);
-void DeleteResetToFirmwareUpdateRegister(void);
-void reset_to_firmware_using_Watchdog(void);
-void reset_to_update_using_system_reset(void);
-
-//static void DualBootToBootloader(void);
-
-/* ITM Trace-------- ---------------------------------------------------------*/
-/*
-#define ITM_Port8(n)    (*((volatile unsigned char *)(0xE0000000+4*n)))
-#define ITM_Port16(n)   (*((volatile unsigned short*)(0xE0000000+4*n)))
-#define ITM_Port32(n)   (*((volatile unsigned long *)(0xE0000000+4*n)))
-
-#define DEMCR           (*((volatile unsigned long *)(0xE000EDFC)))
-#define TRCENA          0x01000000
-
-struct __FILE { int handle; };
-FILE __stdout;
-FILE __stdin;
-
-int fputc(int ch, FILE *f) {
-  if (DEMCR & TRCENA) {
-    while (ITM_Port32(0) == 0);
-    ITM_Port8(0) = ch;
-  }
-  return(ch);
-}
-*/
-
-/* Private functions ---------------------------------------------------------*/
-
-/**
-  * @brief   Main program
-  * @param  None
-  * @retval None
-  */
-
-void GPIO_test_I2C_lines(void)
-{
-  GPIO_InitTypeDef   GPIO_InitStructure;
-  __GPIOA_CLK_ENABLE();
-  __GPIOG_CLK_ENABLE();
-  GPIO_InitStructure.Pin = GPIO_PIN_7;
-  GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
-  GPIO_InitStructure.Pull = GPIO_PULLUP;
-  GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
-  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); 
-  GPIO_InitStructure.Pin = GPIO_PIN_3;
-  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); 
-
-	while(1)
-	{
-	HAL_GPIO_WritePin(GPIOG,GPIO_PIN_7,GPIO_PIN_SET);	
-	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET);	
-	HAL_Delay(10);
-	HAL_GPIO_WritePin(GPIOG,GPIO_PIN_7,GPIO_PIN_RESET);	
-	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET);	
-	HAL_Delay(10);
-	}
-}
-
-
-int main(void)
-{
-	
-/*
-	HAL_Init();
-  SystemClock_Config();
-GPIO_test_I2C_lines();
-*/
-	uint32_t pLayerInvisible;
-	uint32_t firmware_load_result;
-	uint8_t magicbyte = 0;
-	uint8_t callForUpdate;
-	uint8_t status = 0;
-	char textVersion[32];
-	uint8_t ptr;
-	uint32_t pOffset;
-	
-	set_globalState(StBoot0);
-
-  HAL_Init();
-  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
-
-	/* feedback for the user
-	 * aber sehr unsch�n beim Warmstart
-	 * da das letzte Bild noch lange nachleuchtet */
-//	MX_GPIO_Backlight_max_static_only_Init();
-
-
-	/* button press is only 40 to 50 us low */
-	MX_GPIO_One_Button_only_Init();
-
-	uint32_t i = 500000;
-
-	callForUpdate = __HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST);
-
-	if(callForUpdate)
-	{
-		i = 0;
-	}
-	else
-	if(			(firmware_MainCodeIsProgammed() == 0)
-			||	(hardwareDataGetPointer()->primarySerial == 0xFFFF)
-			||	(hardwareDataGetPointer()->production_bluetooth_name_set == 0xFF))
-	{
-		i = 1;
-	}
-	else
-	{
-		while(MX_GPIO_Read_The_One_Button() && i)
-		{
-			i--;
-			__NOP();
-		}
-		if(i)
-		{
-			i = 200000;
-			while(!MX_GPIO_Read_The_One_Button() && i)
-			{
-				i--;
-				__NOP();
-			}
-			if(i)
-			{
-				i = 200000;
-				while(MX_GPIO_Read_The_One_Button() && i)
-				{
-					i--;
-					__NOP();
-				}
-				if(i)
-				{
-					i = 200000;
-					while(!MX_GPIO_Read_The_One_Button() && i)
-					{
-						i--;
-						__NOP();
-					}
-					if(i)
-					{
-						i = 200000;
-						while(MX_GPIO_Read_The_One_Button() && i)
-						{
-							i--;
-							__NOP();
-						}
-					}
-				}
-			}
-		}
-	}
-	
-	if((i == 0) && (callForUpdate == 0))
-		firmware_JumpTo_Application();
-
-  SystemClock_Config();
-
-  MX_GPIO_Init();
-	MX_Bluetooth_PowerOn();
-	MX_SPI_Init();
-	SDRAM_Config();
-	HAL_Delay(100);
-
-	GFX_init1_no_DMA(&pLayerInvisible, 2);
-
-	TIM_BACKLIGHT_init();
-
-// -----------------------------
-
-	display_power_on__1_of_2__pre_RGB();
-	GFX_LTDC_Init();
-	GFX_LTDC_LayerDefaultInit(TOP_LAYER, pLayerInvisible);
-	GFX_LTDC_LayerDefaultInit(BACKGRD_LAYER, pLayerInvisible);
-	GFX_SetFramesTopBottom(pLayerInvisible,pLayerInvisible,480);
-	HAL_Delay(20);
-	display_power_on__2_of_2__post_RGB();
-
-// -----------------------------
-	GFX_change_LTDC();
-	GFX_hwBackgroundOn();
-	GFX_change_LTDC();
-// -----------------------------
-	tInfoBootloader_init();
-// -----------------------------
-	if(i == 0)
-	{
-		tInfo_newpage("load firmware data");
-		uint8_t* pBuffer = (uint8_t*)((uint32_t)0xD0000000); /* blocked via  GFX_init1_no_DMA */
-		firmware_load_result = ext_flash_read_firmware(pBuffer,768000, &magicbyte);
-
-		if((firmware_load_result > 0) && (firmware_load_result < 768000) && (magicbyte == 0xEE))
-		{
-			ptr = ext_flash_read_firmware_version(textVersion);
-			textVersion[ptr++] = 'f';
-			textVersion[ptr++] = 'o';
-			textVersion[ptr++] = 'u';
-			textVersion[ptr++] = 'n';
-			textVersion[ptr++] = 'd';
-			textVersion[ptr] = 0;
-
-			tInfo_newpage(textVersion);
-			tInfo_write("erase flash");
-			status = firmware_eraseFlashMemory();
-			if(status != HAL_OK)
-			{
-				tInfo_newpage("error. try again.");
-				status = firmware_eraseFlashMemory();
-				if(status != HAL_OK)
-				{
-					tInfo_newpage("error. skip update.");
-					HAL_Delay(1000);
-				}
-			}
-			if(status == HAL_OK)
-			{
-				tInfo_write("programm flash");
-				status = firmware_programFlashMemory(pBuffer,firmware_load_result);
-				if(status != HAL_OK)
-				{
-					tInfo_newpage("error. try again.");
-					status = firmware_programFlashMemory(pBuffer,firmware_load_result);
-					if(status != HAL_OK)
-					{
-						tInfo_newpage("error. skip update.");
-						HAL_Delay(1000);
-					}
-				}
-			}
-		}
-	}
-
-	/* here comes the variable upper firmware loader */
-	if((i == 0) && (status == HAL_OK))
-	{
-		tInfo_newpage("load firmware2 data");
-		uint8_t* pBuffer = (uint8_t*)((uint32_t)0xD0000000); /* blocked via  GFX_init1_no_DMA */
-		firmware_load_result = ext_flash_read_firmware2(&pOffset, pBuffer,768000*2,0,0);
-
-		if((firmware_load_result > 0) && (firmware_load_result + pOffset <= 1024000))
-		{
-			ptr = 0;
-			ptr += gfx_number_to_string(7,0,&textVersion[ptr],firmware_load_result);
-			textVersion[ptr++] = ' ';
-			textVersion[ptr++] = 'b';
-			textVersion[ptr++] = 'y';
-			textVersion[ptr++] = 't';
-			textVersion[ptr++] = 'e';
-			textVersion[ptr++] = 's';
-			textVersion[ptr++] = ' ';
-			textVersion[ptr++] = 'w';
-			textVersion[ptr++] = 'i';
-			textVersion[ptr++] = 't';
-			textVersion[ptr++] = 'h';
-			textVersion[ptr++] = ' ';
-			ptr += gfx_number_to_string(7,0,&textVersion[ptr],pOffset);
-			textVersion[ptr++] = ' ';
-			textVersion[ptr++] = 'o';
-			textVersion[ptr++] = 'f';
-			textVersion[ptr++] = 'f';
-			textVersion[ptr++] = 's';
-			textVersion[ptr++] = 'e';
-			textVersion[ptr++] = 't';
-			textVersion[ptr] = 0;
-			tInfo_newpage(textVersion);
-
-			ptr = 0;
-			textVersion[ptr++] = 'f';
-			textVersion[ptr++] = 'o';
-			textVersion[ptr++] = 'u';
-			textVersion[ptr++] = 'n';
-			textVersion[ptr++] = 'd';
-			textVersion[ptr] = 0;
-
-			tInfo_write(textVersion);
-			tInfo_write("erase flash");
-			status = firmware2_variable_upperpart_eraseFlashMemory(firmware_load_result,pOffset);
-			if(status != HAL_OK)
-			{
-				tInfo_newpage("error. try again.");
-				status = firmware2_variable_upperpart_eraseFlashMemory(firmware_load_result,pOffset);
-				if(status != HAL_OK)
-				{
-					tInfo_newpage("error. skip update.");
-					HAL_Delay(1000);
-				}
-			}
-			if(status == HAL_OK)
-			{
-				tInfo_write("programm flash");
-				status = firmware2_variable_upperpart_programFlashMemory(firmware_load_result,pOffset,pBuffer,firmware_load_result,0);
-				if(status != HAL_OK)
-				{
-					tInfo_newpage("error. try again.");
-					status = firmware2_variable_upperpart_programFlashMemory(firmware_load_result,pOffset,pBuffer,firmware_load_result,0);
-					if(status != HAL_OK)
-					{
-						tInfo_newpage("error. skip update.");
-						HAL_Delay(1000);
-					}
-				}
-			}
-		}
-	}
-
-	if((i == 0) && (status == HAL_OK))
-	{
-		tInfo_newpage("Done.");
-		tInfo_write("Cleaning.");
-		ext_flash_erase_firmware_if_not_empty();
-		ext_flash_erase_firmware2_if_not_empty();
-		tInfo_write("Reset device.");
-		reset_to_firmware_using_Watchdog();
-	}
-
-	ptr = 0;
-	textVersion[ptr++] = '\021';
-	textVersion[ptr++] = 's';
-	textVersion[ptr++] = 'e';
-	textVersion[ptr++] = 'r';
-	textVersion[ptr++] = 'i';
-	textVersion[ptr++] = 'a';
-	textVersion[ptr++] = 'l';
-	textVersion[ptr++] = ' ';
-	if(HardwareData.primarySerial == 0xFFFF)
-	{
-		textVersion[ptr++] = 'n';
-		textVersion[ptr++] = 'o';
-		textVersion[ptr++] = 't';
-		textVersion[ptr++] = ' ';
-		textVersion[ptr++] = 's';
-		textVersion[ptr++] = 'e';
-		textVersion[ptr++] = 't';
-	}
-	else if(HardwareData.secondarySerial == 0xFFFF)
-	{
-		textVersion[ptr++] = '#';
-		ptr += gfx_number_to_string(5,1,&textVersion[ptr],HardwareData.primarySerial);
-	}
-	else
-	{
-		textVersion[ptr++] = '#';
-		ptr += gfx_number_to_string(5,1,&textVersion[ptr],HardwareData.secondarySerial);
-		textVersion[ptr++] = ' ';
-		textVersion[ptr++] = '(';
-		ptr += gfx_number_to_string(5,1,&textVersion[ptr],HardwareData.primarySerial);
-		textVersion[ptr++] = ')';
-	}
-	textVersion[ptr++] = '\020';
-	textVersion[ptr] = 0;
-
-	tInfo_button_text("Exit","","Sleep");
-	tInfo_newpage("Bootloader 160602");
-	tInfo_write("start bluetooth");
-	tInfo_write("");
-	tInfo_write(textVersion);
-	tInfo_write("");
-	
-	TIM_init();
-	MX_UART_Init();
-	MX_Bluetooth_PowerOn();
-	tComm_Set_Bluetooth_Name(0);
-	
-	tComm_init();
-	set_globalState_Base();
-
-	GFX_start_VSYNC_IRQ();
-
-	EXTILine_Buttons_Config();
-/*	
-  uint8_t* pBuffer1 = (uint8_t*)getFrame(20);
-	firmware_load_result = ext_flash_read_firmware(pBuffer1,768000);
-	
-	if((firmware_load_result > 0) && (firmware_load_result < 768000))
-	{
-		firmware_eraseFlashMemory();
-		firmware_programFlashMemory(pBuffer1,firmware_load_result);
-		// not for testing
-		//ext_flash_erase_firmware_if_not_empty();
-    reset_to_firmware_using_Watchdog();  
-	}
-*/
-	while(1)
-	{
-//		if(bootToBootloader)
-//			DualBootToBootloader();
-
-		if(bootToBootloader)
-			reset_to_update_using_system_reset();
-				
-		tComm_control(); // will stop while loop if tComm Mode started until exit from UART
-	};
-}
-
-
-void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
-{
-
-	SStateList status;
-
-	get_globalStateList(&status);
-
-	switch(status.base)
-	{
-		default:
-//			TIM_BACKLIGHT_adjust();
-			break;
-	}
-
-	if(returnFromCommCleanUpRequest)
-	{
-		tComm_exit();
-		returnFromCommCleanUpRequest = 0;
-		GFX_hwBackgroundOn();
-		tInfo_button_text("Exit","","Sleep");
-		tInfo_newpage("bluetooth disonnected");
-		tInfo_write("");
-		tInfo_write("");
-		tInfo_write("");
-		tInfo_write("");
-	}
-	
-	get_globalStateList(&status);
-
-	switch(status.base)
-	{
-		case BaseComm:
-			if(get_globalState() == StUART_STANDARD)
-			 tComm_refresh();
-			break;
-		default:
-			break;
-	}
-}
-
-void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
-{
-	uint8_t action;
-	SStateList status;
-	static uint8_t counterToPreventSleep = 0;
-  if(GPIO_Pin == VSYNC_IRQ_PIN) // rechts, unten
-	{
-		GFX_change_LTDC();
-		housekeepingFrame();
-		if(counterToPreventSleep < 250)
-			counterToPreventSleep++;
-		else
-		if(counterToPreventSleep != 255)
-		{
-			counterToPreventSleep = 255;
-		}
-		
-		return;
-	}
-
-	time_without_button_pressed_deciseconds	= 0;
-
-	if(GFX_logoStatus() != 0)
-		return;
-
-  if(GPIO_Pin == BUTTON_BACK_PIN) // links
-		action = ACTION_BUTTON_BACK;
-	else
-  if(GPIO_Pin == BUTTON_ENTER_PIN) // mitte
-		action = ACTION_BUTTON_ENTER;
-	else
-  if(GPIO_Pin == BUTTON_NEXT_PIN) // rechts
-		action = ACTION_BUTTON_NEXT;
-#ifdef BUTTON_CUSTOM_PIN
-	else
-  if(GPIO_Pin == BUTTON_CUSTOM_PIN) // extra
-		action = ACTION_BUTTON_CUSTOM;
-#endif
-	else
-		action = 0;
-	get_globalStateList(&status);
-
-	switch(status.base)
-	{
-		case BaseComm:
-			if(action == ACTION_BUTTON_BACK)
-			{
-				reset_to_firmware_using_Watchdog();
-			}
-		 break;
-			
-		default:
-			if((action == ACTION_BUTTON_NEXT) && (counterToPreventSleep == 255) && (get_globalState() == StS))
-			{
-				while(1)
-				{
-					MX_tell_reset_logik_alles_ok();
-					DataEX_call();
-					HAL_Delay(100);
-				}
-			}
-			else
-			if(action == ACTION_BUTTON_BACK)
-			{
-				reset_to_firmware_using_Watchdog();
-			}
-			else
-			if(action == ACTION_BUTTON_CUSTOM)
-			{
-				if(get_globalState() == StS)
-					gotoSleep();
-			}
-			else
-			if(action == ACTION_BUTTON_ENTER)
-			{
-				reset_to_update_using_system_reset();
-			}
-			break;
-	}
-}
-
-
-void gotoSleep(void)
-{
-	ext_flash_erase_firmware_if_not_empty();
-	set_globalState(StStop);
-}
-
-// -----------------------------
-
-
-void MainBootLoaderInit(void)
-{
-	void (*SysMemBootJump)(void);
-	SysMemBootJump=(void (*)(void)) (*((uint32_t *) 0x1fff0004));
-
-	// DMA, SPI, UART, TIM, ExtIRQ, graphics DMA, LTDC
-
-	HAL_RCC_DeInit();
-	SysTick->CTRL = 0;
-	SysTick->LOAD = 0;
-	SysTick->VAL = 0;
-
-	__set_PRIMASK(1);
-
-	__set_MSP(0x20002318);
-	SysMemBootJump();
-}
-
-uint32_t get_globalState(void)
-{
-	return globalStateID;
-}
-
-void get_globalStateList(SStateList *output)
-{
-	output->base  = (uint8_t)((globalStateID >> 28) & 0x0F);
-	output->page  = (uint8_t)((globalStateID >> 24) & 0x0F);
-	output->line  = (uint8_t)((globalStateID >> 16) & 0xFF);
-	output->field = (uint8_t)((globalStateID >> 8) & 0xFF);
-	output->mode  = (uint8_t)((globalStateID     ) & 0xFF);
-}
-
-void get_idSpecificStateList(uint32_t id, SStateList *output)
-{
-	output->base  = (uint8_t)((id >> 28) & 0x0F);
-	output->page  = (uint8_t)((id >> 24) & 0x0F);
-	output->line  = (uint8_t)((id >> 16) & 0xFF);
-	output->field = (uint8_t)((id >> 8) & 0xFF);
-	output->mode  = (uint8_t)((id     ) & 0xFF);
-}
-
-void	set_globalState_Base(void)
-{
-	set_globalState(StS);
-}
-
-void set_globalState_Menu_Page(uint8_t page)
-{
-	globalStateID = ((BaseMenu << 28) + (page << 24));
-}
-
-void set_globalState_Log_Page(uint8_t pageIsLine)
-{
-	globalStateID = StILOGLIST + (pageIsLine << 16);
-}
-
-
-void set_globalState_Menu_Line(uint8_t line)
-{
-	globalStateID = ((globalStateID & MaskLineFieldDigit) + (line << 16));
-}
-
-
-void set_globalState(uint32_t newID)
-{
-	globalStateID = newID;
-}
-
-
-
-void delayMicros(uint32_t micros)
-{
-	micros = micros * (168/4) - 10;
-	while(micros--);
-}
-
-
-void get_RTC_DateTime(RTC_DateTypeDef * sdatestructureget, RTC_TimeTypeDef * stimestructureget)
-{
-  /* Get the RTC current Time */
-	if(sdatestructureget)
-		HAL_RTC_GetTime(&RtcHandle, stimestructureget, FORMAT_BIN);
-  /* Get the RTC current Date */
-	if(stimestructureget)
-		HAL_RTC_GetDate(&RtcHandle, sdatestructureget, FORMAT_BIN);
-}
-
-
-void set_RTC_DateTime(RTC_DateTypeDef * sdatestructure, RTC_TimeTypeDef * stimestructure)
-{
-	if(sdatestructure)
-		if(HAL_RTC_SetDate(&RtcHandle,sdatestructure,FORMAT_BCD) != HAL_OK)
-		{
-			/* Initialization Error */
-			Error_Handler();
-		}
-
-	if(stimestructure)
-		if(HAL_RTC_SetTime(&RtcHandle,stimestructure,FORMAT_BCD) != HAL_OK)
-		{
-			/* Initialization Error */
-			Error_Handler();
-		}
-}
-
-static void TIM_init(void)
-{
-	uint16_t uwPrescalerValue = 0;
-
-  uwPrescalerValue = (uint32_t) ((SystemCoreClock /2) / 10000) - 1;
-
-  /* Set TIMx instance */
-  TimHandle.Instance = TIMx;
-
-  /* Initialize TIM3 peripheral as follows:
-       + Period = 10000 - 1
-       + Prescaler = ((SystemCoreClock/2)/10000) - 1
-       + ClockDivision = 0
-       + Counter direction = Up
-  */
-  TimHandle.Init.Period = 1000 - 1;
-  TimHandle.Init.Prescaler = uwPrescalerValue;
-  TimHandle.Init.ClockDivision = 0;
-  TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
-  if(HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
-  {
-    /* Initialization Error */
-    Error_Handler();
-  }
-
-  /*##-2- Start the TIM Base generation in interrupt mode ####################*/
-  /* Start Channel1 */
-  if(HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK)
-  {
-    /* Starting Error */
-    Error_Handler();
-  }
-}
-
-#ifndef TIM_BACKLIGHT
-/*
-static void TIM_BACKLIGHT_adjust(void)
-{
-}
-*/
-static void TIM_BACKLIGHT_init(void)
-{
-}
-#else
-/*
-static void TIM_BACKLIGHT_adjust(void)
-{
-
-	TIM_OC_InitTypeDef sConfig;
-	sConfig.OCMode     = TIM_OCMODE_PWM1;
-  sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
-  sConfig.OCFastMode = TIM_OCFAST_DISABLE;
-	sConfig.Pulse = 600;
-
-	HAL_TIM_PWM_ConfigChannel(&TimBacklightHandle, &sConfig, TIM_BACKLIGHT_CHANNEL);
-	HAL_TIM_PWM_Start(&TimBacklightHandle, TIM_BACKLIGHT_CHANNEL);
-}
-*/
-static void TIM_BACKLIGHT_init(void)
-{
-	uint32_t uwPrescalerValue = 0;
-	TIM_OC_InitTypeDef sConfig;
-
-  uwPrescalerValue = (uint32_t) ((SystemCoreClock /2) / 18000000) - 1;
-
-  TimBacklightHandle.Instance = TIM_BACKLIGHT;
-
-  // Initialize TIM3 peripheral as follows:	30 kHz
-	
-  TimBacklightHandle.Init.Period = 600 - 1;
-  TimBacklightHandle.Init.Prescaler = uwPrescalerValue;
-  TimBacklightHandle.Init.ClockDivision = 0;
-  TimBacklightHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
-	HAL_TIM_PWM_Init(&TimBacklightHandle);
-
-	sConfig.OCMode     = TIM_OCMODE_PWM1;
-  sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
-  sConfig.OCFastMode = TIM_OCFAST_DISABLE;
-	sConfig.Pulse = 50 * 6;
-
-	HAL_TIM_PWM_ConfigChannel(&TimBacklightHandle, &sConfig, TIM_BACKLIGHT_CHANNEL);
-	HAL_TIM_PWM_Start(&TimBacklightHandle, TIM_BACKLIGHT_CHANNEL);
-}
-#endif
-
-  /* Configure RTC prescaler and RTC data registers */
-  /* RTC configured as follow:
-      - Hour Format    = Format 24
-      - Asynch Prediv  = Value according to source clock
-      - Synch Prediv   = Value according to source clock
-      - OutPut         = Output Disable
-      - OutPutPolarity = High Polarity
-      - OutPutType     = Open Drain */
-	/*#define RTC_ASYNCH_PREDIV  0x7F    LSE as RTC clock */
-	/*LSE: #define RTC_SYNCH_PREDIV   0x00FF  LSE as RTC clock */
-	/*LSI: #define RTC_SYNCH_PREDIV   0x0130  LSI as RTC clock */
-/*
-static void RTC_init(void)
-{
-  RtcHandle.Instance = RTC;
-
-
-  RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24;
-  RtcHandle.Init.AsynchPrediv = 0x7F;
-  RtcHandle.Init.SynchPrediv = 0x0130;
-  RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
-  RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
-  RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
-
-  if(HAL_RTC_Init(&RtcHandle) != HAL_OK)
-  {
-    Error_Handler();
-  }
-}
-*/
-
-static void EXTILine_Buttons_Config(void)
-{
-  GPIO_InitTypeDef   GPIO_InitStructure;
-
-	BUTTON_ENTER_GPIO_ENABLE();
-	BUTTON_NEXT_GPIO_ENABLE();
-	BUTTON_BACK_GPIO_ENABLE();
-
-  /* Configure pin as weak PULLUP input  */
-	/* buttons */
-  GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
-  GPIO_InitStructure.Pull = GPIO_NOPULL;
-	GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
-
-  GPIO_InitStructure.Pin = BUTTON_ENTER_PIN;
-  HAL_GPIO_Init(BUTTON_ENTER_GPIO_PORT, &GPIO_InitStructure);
-
-  GPIO_InitStructure.Pin = BUTTON_NEXT_PIN;
-  HAL_GPIO_Init(BUTTON_NEXT_GPIO_PORT, &GPIO_InitStructure);
-
-	GPIO_InitStructure.Pin = BUTTON_BACK_PIN;
-  HAL_GPIO_Init(BUTTON_BACK_GPIO_PORT, &GPIO_InitStructure);
-
-  /* Enable and set EXTI Line0 Interrupt to the lowest priority */
-  HAL_NVIC_SetPriority(BUTTON_ENTER_EXTI_IRQn, 2, 0);
-  HAL_NVIC_SetPriority(BUTTON_NEXT_EXTI_IRQn,  2, 0);
-  HAL_NVIC_SetPriority(BUTTON_BACK_EXTI_IRQn,  2, 0);
-  HAL_NVIC_EnableIRQ(BUTTON_ENTER_EXTI_IRQn);
-  HAL_NVIC_EnableIRQ(BUTTON_NEXT_EXTI_IRQn);
-  HAL_NVIC_EnableIRQ(BUTTON_BACK_EXTI_IRQn);
-
-#ifdef BUTTON_CUSTOM_PIN
-	BUTTON_CUSTOM_GPIO_ENABLE();
-  GPIO_InitStructure.Pin = BUTTON_CUSTOM_PIN;
-  HAL_GPIO_Init(BUTTON_CUSTOM_GPIO_PORT, &GPIO_InitStructure);
-  HAL_NVIC_SetPriority(BUTTON_CUSTOM_EXTI_IRQn,  2, 0);
-  HAL_NVIC_EnableIRQ(BUTTON_CUSTOM_EXTI_IRQn);
-#endif
-}
-
-
-/**
-  * @brief  System Clock Configuration
-  *         The system Clock is configured as follow :
-  *            System Clock source            = PLL (HSE)
-  *            SYSCLK(Hz)                     = 180000000
-  *            HCLK(Hz)                       = 180000000
-  *            AHB Prescaler                  = 1
-  *            APB1 Prescaler                 = 4
-  *            APB2 Prescaler                 = 2
-  *            HSE Frequency(Hz)              = 8000000
-  *            PLL_M                          = 8
-  *            PLL_N                          = 360
-  *            PLL_P                          = 2
-  *            PLL_Q                          = 7
-  *            VDD(V)                         = 3.3
-  *            Main regulator output voltage  = Scale1 mode
-  *            Flash Latency(WS)              = 5
-  *         The LTDC Clock is configured as follow :
-  *            PLLSAIN                        = 192
-  *            PLLSAIR                        = 4
-  *            PLLSAIDivR                     = 8
-  * @param  None
-  * @retval None
-  */
-static void SystemClock_Config(void)
-{
-  RCC_ClkInitTypeDef RCC_ClkInitStruct;
-  RCC_OscInitTypeDef RCC_OscInitStruct;
-  RCC_PeriphCLKInitTypeDef  PeriphClkInitStruct;
-
-  /* Enable Power Control clock */
-  __PWR_CLK_ENABLE();
-
-  /* The voltage scaling allows optimizing the power consumption when the device is
-     clocked below the maximum system frequency, to update the voltage scaling value
-     regarding system frequency refer to product datasheet.  */
-  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
-
-  /*##-1- System Clock Configuration #########################################*/
-  /* Enable HSE Oscillator and activate PLL with HSE as source */
-  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
-  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
-  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
-  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
-  RCC_OscInitStruct.PLL.PLLM = 8;
-  RCC_OscInitStruct.PLL.PLLN = 336;//360;
-  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
-  RCC_OscInitStruct.PLL.PLLQ = 7;
-  HAL_RCC_OscConfig(&RCC_OscInitStruct);
-
-//  HAL_PWREx_ActivateOverDrive();
-HAL_PWREx_DeactivateOverDrive();
-  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
-     clocks dividers */
-  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
-  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
-  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
-  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
-  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
-  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_8);//FLASH_LATENCY_5);
-
-  /*##-2- LTDC Clock Configuration ###########################################*/
-  /* LCD clock configuration */
-  /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
-  /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */
-  /* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/4 = 48 Mhz */
-  /* LTDC clock frequency = PLLLCDCLK / RCC_PLLSAIDIVR_8 = 48/8 = 6 Mhz */
-	
-	/* neu: 8MHz/8*300/5/8 = 7,5 MHz = 19,5 Hz bei 800 x 480 */ 
-  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
-  PeriphClkInitStruct.PLLSAI.PLLSAIN = 300;//192;
-  PeriphClkInitStruct.PLLSAI.PLLSAIR = 5;//4;
-  PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_8;//RCC_PLLSAIDIVR_4;// RCC_PLLSAIDIVR_2; // RCC_PLLSAIDIVR_8
-  HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
-}
-
-
-/**
-  * @brief  This function is executed in case of error occurrence.
-  * @param  None
-  * @retval None
-  */
-static void Error_Handler(void)
-{
-    /* Turn LED3 on */
-//    BSP_LED_On(LED3);
-    while(1)
-    {
-    }
-}
-
-/**
-  * @brief  Perform the SDRAM exernal memory inialization sequence
-  * @param  hsdram: SDRAM handle
-  * @param  Command: Pointer to SDRAM command structure
-  * @retval None
-  */
-static void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command)
-{
-  __IO uint32_t tmpmrd =0;
-  /* Step 3:  Configure a clock configuration enable command */
-  Command->CommandMode 			 = FMC_SDRAM_CMD_CLK_ENABLE;
-  Command->CommandTarget 		 = FMC_SDRAM_CMD_TARGET_BANK2;
-  Command->AutoRefreshNumber 	 = 1;
-  Command->ModeRegisterDefinition = 0;
-
-  /* Send the command */
-  HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
-
-  /* Step 4: Insert 100 ms delay */
-  HAL_Delay(100);
-
-  /* Step 5: Configure a PALL (precharge all) command */
-  Command->CommandMode 			 = FMC_SDRAM_CMD_PALL;
-  Command->CommandTarget 	     = FMC_SDRAM_CMD_TARGET_BANK2;
-  Command->AutoRefreshNumber 	 = 1;
-  Command->ModeRegisterDefinition = 0;
-
-  /* Send the command */
-  HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
-
-  /* Step 6 : Configure a Auto-Refresh command */
-  Command->CommandMode 			 = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
-  Command->CommandTarget 		 = FMC_SDRAM_CMD_TARGET_BANK2;
-  Command->AutoRefreshNumber 	 = 4;
-  Command->ModeRegisterDefinition = 0;
-
-  /* Send the command */
-  HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
-
-  /* Step 7: Program the external memory mode register */
-  tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2          |
-                     SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |
-                     SDRAM_MODEREG_CAS_LATENCY_3           |
-                     SDRAM_MODEREG_OPERATING_MODE_STANDARD |
-                     SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
-
-  Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
-  Command->CommandTarget 		 = FMC_SDRAM_CMD_TARGET_BANK2;
-  Command->AutoRefreshNumber 	 = 1;
-  Command->ModeRegisterDefinition = tmpmrd;
-
-  /* Send the command */
-  HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
-
-  /* Step 8: Set the refresh rate counter */
-  /* (15.62 us x Freq) - 20 */
-  /* neu: (8 us x Freq) - 20 */
-  /* Set the device refresh counter */
-  HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT);
-}
-
-/*
-static void DualBoot(void)
-{
-    // Set BFB2 bit to enable boot from Flash Bank2
-    // Allow Access to Flash control registers and user Falsh
-    HAL_FLASH_Unlock();
-
-    // Allow Access to option bytes sector
-    HAL_FLASH_OB_Unlock();
-
-    // Get the Dual boot configuration status
-    AdvOBInit.OptionType = OBEX_BOOTCONFIG;
-    HAL_FLASHEx_AdvOBGetConfig(&AdvOBInit);
-
-    // Enable/Disable dual boot feature
-    if (((AdvOBInit.BootConfig) & (FLASH_OPTCR_BFB2)) == FLASH_OPTCR_BFB2)
-    {
-      AdvOBInit.BootConfig = OB_DUAL_BOOT_DISABLE;
-      HAL_FLASHEx_AdvOBProgram (&AdvOBInit);
-    }
-    else
-    {
-      AdvOBInit.BootConfig = OB_DUAL_BOOT_ENABLE;
-      HAL_FLASHEx_AdvOBProgram (&AdvOBInit);
-    }
-
-    // Start the Option Bytes programming process
-    if (HAL_FLASH_OB_Launch() != HAL_OK)
-    {
-      // User can add here some code to deal with this error
-      while (1)
-      {
-      }
-    }
-    // Prevent Access to option bytes sector
-    HAL_FLASH_OB_Lock();
-
-    // Disable the Flash option control register access (recommended to protect
-    // the option Bytes against possible unwanted operations)
-    HAL_FLASH_Lock();
-
-    // Initiates a system reset request to reset the MCU
-    reset_to_firmware_using_Watchdog();
-}
-*/
-/**
-  ******************************************************************************
-  ******************************************************************************
-  ******************************************************************************
-  */
-
-
-/**
-  * @brief DMA2D configuration.
-  * @note  This function Configure tha DMA2D peripheral :
-  *        1) Configure the transfer mode : memory to memory W/ pixel format conversion
-  *        2) Configure the output color mode as ARGB4444
-  *        3) Configure the output memory address at SRAM memory
-  *        4) Configure the data size : 320x120 (pixels)
-  *        5) Configure the input color mode as ARGB8888
-  *        6) Configure the input memory address at FLASH memory
-  * @retval
-  *  None
-  */
-
-static void SDRAM_Config(void)
-{
-  /*##-1- Configure the SDRAM device #########################################*/
-  /* SDRAM device configuration */
-  hsdram.Instance = FMC_SDRAM_DEVICE;
-
-  /* Timing configuration for 90 Mhz of SD clock frequency (180Mhz/2) */
-  /* TMRD: 2 Clock cycles */
-  SDRAM_Timing.LoadToActiveDelay    = 2;
-  /* TXSR: min=70ns (6x11.90ns) */
-  SDRAM_Timing.ExitSelfRefreshDelay = 7;
-  /* TRAS: min=42ns (4x11.90ns) max=120k (ns) */
-  SDRAM_Timing.SelfRefreshTime      = 4;
-  /* TRC:  min=63 (6x11.90ns) */
-  SDRAM_Timing.RowCycleDelay        = 7;
-  /* TWR:  2 Clock cycles */
-  SDRAM_Timing.WriteRecoveryTime    = 2;
-  /* TRP:  15ns => 2x11.90ns */
-  SDRAM_Timing.RPDelay              = 2;
-  /* TRCD: 15ns => 2x11.90ns */
-  SDRAM_Timing.RCDDelay             = 2;
-
-  hsdram.Init.SDBank             = FMC_SDRAM_BANK2;
-  hsdram.Init.ColumnBitsNumber   = FMC_SDRAM_COLUMN_BITS_NUM_9;
-  hsdram.Init.RowBitsNumber      = FMC_SDRAM_ROW_BITS_NUM_13;
-  hsdram.Init.MemoryDataWidth    = SDRAM_MEMORY_WIDTH;
-  hsdram.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
-  hsdram.Init.CASLatency         = FMC_SDRAM_CAS_LATENCY_3;
-  hsdram.Init.WriteProtection    = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
-  hsdram.Init.SDClockPeriod      = SDCLOCK_PERIOD;
-  hsdram.Init.ReadBurst          = FMC_SDRAM_RBURST_DISABLE;
-  hsdram.Init.ReadPipeDelay      = FMC_SDRAM_RPIPE_DELAY_1;
-
-  /* Initialize the SDRAM controller */
-  if(HAL_SDRAM_Init(&hsdram, &SDRAM_Timing) != HAL_OK)
-  {
-    /* Initialization Error */
-    Error_Handler();
-  }
-
-  /* Program the SDRAM external device */
-  SDRAM_Initialization_Sequence(&hsdram, &command);
-}
-
-
-uint8_t checkResetForFirmwareUpdate(void)
-{
-	uint32_t backupRegisterContent;
-	
-	RTC_HandleTypeDef RtcHandle;
-	RtcHandle.Instance = RTC;
-	backupRegisterContent = HAL_RTCEx_BKUPRead(&RtcHandle,RTC_BKP_DR0);
-	
-	if(backupRegisterContent == 0x12345678)
-		return 1;
-	else
-		return 0;
-}
-
-void DeleteResetToFirmwareUpdateRegister(void)
-{
-	RTC_HandleTypeDef RtcHandle;
-	RtcHandle.Instance = RTC;
-  __HAL_RTC_WRITEPROTECTION_DISABLE(&RtcHandle);
-	HAL_RTCEx_BKUPWrite(&RtcHandle,RTC_BKP_DR0,0x00);
-  __HAL_RTC_WRITEPROTECTION_ENABLE(&RtcHandle);
-}
-
-#ifdef  USE_FULL_ASSERT
-
-/**
-  * @brief  Reports the name of the source file and the source line number
-  *         where the assert_param error has occurred.
-  * @param  file: pointer to the source file name
-  * @param  line: assert_param error line source number
-  * @retval None
-  */
-void assert_failed(uint8_t* file, uint32_t line)
-{
-  /* User can add his own implementation to report the file name and line number,
-     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
-
-  /* Infinite loop */
-  while (1)
-  {
-  }
-}
-#endif
-
-/*
-static void DualBootToBootloader(void)
-{
-    // Set BFB2 bit to enable boot from Flash Bank2
-    // Allow Access to Flash control registers and user Falsh
-    HAL_FLASH_Unlock();
-  
-    // Allow Access to option bytes sector
-    HAL_FLASH_OB_Unlock();
-    
-    // Get the Dual boot configuration status
-    AdvOBInit.OptionType = OPTIONBYTE_BOOTCONFIG;
-    HAL_FLASHEx_AdvOBGetConfig(&AdvOBInit);
-
-    // Enable/Disable dual boot feature
-		if (((AdvOBInit.BootConfig) & (FLASH_OPTCR_BFB2)) == FLASH_OPTCR_BFB2)
-    {
-      AdvOBInit.BootConfig = OB_DUAL_BOOT_DISABLE;
-      HAL_FLASHEx_AdvOBProgram (&AdvOBInit);
-			if (HAL_FLASH_OB_Launch() != HAL_OK)
-			{
-				while (1)
-				{
-				}
-			}
-    }
-    else
-    {
-
-      AdvOBInit.BootConfig = OB_DUAL_BOOT_ENABLE;
-      HAL_FLASHEx_AdvOBProgram (&AdvOBInit);
-			if (HAL_FLASH_OB_Launch() != HAL_OK)
-			{
-				while (1)
-				{
-				}
-			}
-		}
-    
-    // Prevent Access to option bytes sector
-    HAL_FLASH_OB_Lock();
-    
-    / Disable the Flash option control register access (recommended to protect 
-    // the option Bytes against possible unwanted operations)
-    HAL_FLASH_Lock();    
-    
-    // Initiates a system reset request to reset the MCU
-    reset_to_firmware_using_Watchdog();  
-}
-*/
-
-void reset_to_update_using_system_reset(void)
-{
-	__HAL_RCC_CLEAR_RESET_FLAGS();
-	HAL_NVIC_SystemReset();
-}
-
-void reset_to_firmware_using_Watchdog(void)
-{
-	__HAL_RCC_CLEAR_RESET_FLAGS();
-  __HAL_RCC_WWDG_CLK_ENABLE();
-
-	WWDG_HandleTypeDef   WwdgHandle;
-	WwdgHandle.Instance = WWDG;
-
-  WwdgHandle.Init.Prescaler = WWDG_PRESCALER_8;
-  WwdgHandle.Init.Window    = 80;
-  WwdgHandle.Init.Counter   = 127;
-  
-  HAL_WWDG_Init(&WwdgHandle);
-	HAL_WWDG_Start(&WwdgHandle);
-	while(1);
-}
-
-
-void set_returnFromComm(void)
-{
-	returnFromCommCleanUpRequest = 1;
-}
-
-/**
-  * @}
-  */
-
-/**
-  * @}
-  */
-
-/************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/
+///////////////////////////////////////////////////////////////////////////////
+/// -*- coding: UTF-8 -*-
+///
+/// \file   BootLoader/Src/base_bootlader.c
+/// \brief  he beginning of it all. main() is part of this.
+/// \author heinrichs/weikamp, Christian Weikamp
+/// \date   26-February-2014
+///
+/// $Id$
+///////////////////////////////////////////////////////////////////////////////
+/// \par Copyright (c) 2014-2018 Heinrichs Weikamp gmbh
+///
+///     This program is free software: you can redistribute it and/or modify
+///     it under the terms of the GNU General Public License as published by
+///     the Free Software Foundation, either version 3 of the License, or
+///     (at your option) any later version.
+///
+///     This program is distributed in the hope that it will be useful,
+///     but WITHOUT ANY WARRANTY; without even the implied warranty of
+///     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+///     GNU General Public License for more details.
+///
+///     You should have received a copy of the GNU General Public License
+///     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//////////////////////////////////////////////////////////////////////////////
+/**
+	* @detail	 The beginning of it all. main() is part of this.
+	*							 + Do the inits for hardware
+	*							 + check for button press or update process reset trigger
+	*							 + Do the inits for sub-systems like menu, dive screen etc.
+	*							 + Start IRQs
+	*							 + Start MainTasks not in IRQs
+	* @bug
+	* @warning
+	@verbatim
+
+	==============================================================================
+							##### bootloader specific #####
+	==============================================================================
+
+	151130	chsw	sleep on button3
+								(MX_tell_reset_logik_alles_ok() + DataEX_call() in endlos loop)
+
+	==============================================================================
+							##### bootloader specific #####
+	==============================================================================
+
+	Bootloader info is set right here in this file.
+	The location is 0x0800A000 instead of 0x08050000 (firmware)
+
+	on system reset (Menu Start Bootloader in firmware) the update process
+	is started automatically if no button is pressed
+
+	if the right button is pressed the bootloader menu is started
+
+	after update process (with update or empty) cleaning of EEPROM is started
+	afterwards the watchdog reset starts without activating the update process
+
+	bluetooth chip is started in tComm on start of the mini bootloader firmware
+
+	SMALLCPU_CSB_PIN must be re-set to 0 to communicate with small CPU / CPU2 / RTE
+
+	for RealTerm to send file / firmware, Delays has to be increased to 0
+
+	RTE update / SPI1 with DMA gave IBUSERR, now it is working fine :-) 150828
+	==============================================================================
+	from standard firmware, parts might be invalid here:
+	==============================================================================
+							##### IRQs #####
+	==============================================================================
+	[..] The IRQs are very important and most functions should only run there.
+
+				PreemptPriority are as follows
+				(#) 2 (low)		sprintf _only_ here. Don't use in maintask or anywhere else.
+											Called by Buttons und Timer3
+											Timer3 is 1/10 second
+				(#) 1 (mid)		anything that should work while in IRQ2 like HalDelay(), VSYNC
+											and DMA2D Transfer Complete for housekeepingFrame();
+				(#)	0 (high)	_very very short_ interrupts like The HAL hardware part for
+											spi, uart, i2c.
+
+				SubPriority within 	PreemptPriority give the order to execute.
+				Introduced 30.Oct.14 as it used by several HAL examples.
+				Three levelAmbients are available (2 low,1 mid,0 high)
+
+				The STM32F4 has 4bits for IRQ levelAmbients, divided 2/2 in this code
+				with the NVIC_PRIORITYGROUP_2 setting.
+
+	==============================================================================
+							##### MainTask #####
+	==============================================================================
+	[..] For everthing slow without importance to be 'in time'.
+			 Like VPM and Buehlmann.
+			 No sprintf and probably no GFX_SetFramesTopBottom() stuff neither.
+			 If sprintf is called while sprintf is executed it blows up everything.
+
+	==============================================================================
+							##### Frames / the external SDRAM #####
+	==============================================================================
+	[..] The SDRAM is handled by getFrame() and releaseFrame().
+			 Each frame with 800*480*2 Bytes.
+			 Be carefull to release every frame
+			 otherwise there will be a memory leakage over time.
+			 housekeepingFrame() in the MainTask takes care of cleaning the frames.
+			 All frames are filled with 0x00. This will be transparent with color of
+			 CLUT_Font020 (is CLUT 0) if the alpha is set for a 16bit pair.
+			 housekeepingFrame() delays the cleaning of frames still used as screen
+			 buffer to prevent flickering.
+
+	==============================================================================
+							##### Display #####
+	==============================================================================
+	[..] There is a Top layer, Bottom layer and background color.
+			 All are perfectly alpha-blended by hardware.
+
+				(#) top layer			has 800x480 option function calls only
+													as it is not used for cursors here
+				(#)	bottom layer	has free size and start option to be used
+													for cursors (or sprites in the future ;-)
+				(#) background		only black in the moment.
+													ToDo: Could be anything else for warnings etc.
+													if needed
+
+	[..] Frame updates, switching and cursors is done with
+
+				(#) GFX_SetFramesTopBottom() and the subset
+						GFX_SetFrameTop() + GFX_SetFrameBottom()
+						Those do not change anything on the display but give commands to..
+				(#) GFX_change_LTDC()	The only place that changes the pointer.
+															This prevents erratic behaviour if several changes
+															are made within one refresh rate of the screen.
+															Is called in IRQ by PD4 and HAL_GPIO_EXTI_IRQHandler
+															from VSYNC signal.
+
+	[..] Content
+
+				(#) Colors	by LookupTable only. This could be modified by
+										system settings in the future. (gfx_color.h/.c)
+
+				(#) Text		by text_multilinguage.h/.c with one char
+										necessary only starting from '\x80'
+										with automatic language switch by
+										selected_language in SSettings
+										see openEdit_Language() in tMenuEditSystem.c
+										Therefore there are differnent functions
+										for example:
+										write_label_fix() for single char multilanguage
+										write_label_var() for strings that could include
+										multilanguage as well
+										see GFX_write_string() to get an overview of the controls
+										as well as the command list in gfx_engine.h
+										There is no clear before writing, text overlay is always on.
+										Many options to have LargeFont.SmallFont for numbers etc.
+
+	==============================================================================
+							##### Update, DualBoot and build-in FLASH memory usage #####
+	==============================================================================
+	[..] Boot0 pin, Boot1/PB2 pin and BFB2 software bit control the behaviour.
+				PB2 should be tied to GND.
+				Boot0 == VDD -> bootloader on start, otherwise boot from Bank1 or Bank2
+				depending on BFB2.
+				Bank2 contains the Fonts and should contain a proper test code in future
+				Bank1 is the main code (Bank1 is 1 MB too, usage as of Oct. 14 is 200 KB)
+	[..] Bootloader should be either UART or USB (on FS pins _only_)
+				USB HS to FS like on the Eval board does not work.
+	[..] Bootloader for the smaller CPU2 is implemented via the SPI used for DMA copy.
+
+	==============================================================================
+							##### Connection to CPU2 (STM32F411 as of Oct.14 #####
+	==============================================================================
+	[..] Connected via SPI and DMA for every purpose.
+				two entire arrays are transfered for data security reasons
+				with respect to master (STM32F429) might interrupt internal
+				data copy in CPU2 (like hi byte, low byte, etc.).
+	[..] The entire life data is calculated in CPU2. Like tissues, CNS,...
+				Therefore the main unit is _not_ necessarily a Real Time system.
+				Simulation on the main unit can be executed without disrupting life data.
+	[..] SPI is triggered and timed by calling DataEX_call() in data_exchange_main.c
+				DataEX_copy_to_LifeData() does the transfer from buffer to variables used.
+
+	==============================================================================
+							##### Menu, MenuEdit, Info #####
+	==============================================================================
+	[..] tMenu.c, tMenuEdit.c and tInfo.c is the system used.
+				logbook is part of Info not Menu.
+				The Info Menu is accessed by button 'Back'
+				The regular Menu is accessed by button 'Enter'
+	[..] Menu content is kept in frame memory for fast access.
+				There is no need to build pages if the 'Enter' button is pressed.
+				This is in contrast to MenuEdit pages.
+	[..] Button control for new pages (and pages in general) have to implemented
+				in tMenu.c, tMenuEdit.c or tInfo.c
+
+	[..] ToDo (Oct. 14) Timeout for menus via Timer3 / IRQ 2
+
+	==============================================================================
+							##### specials #####
+	==============================================================================
+	[..] There was code for vector graphics from great demos
+				(peridiummmm and jupiter) that can be fitted again
+
+	 @endverbatim
+	******************************************************************************
+	*/
+
+/* Includes ------------------------------------------------------------------*/
+#include "base_bootloader.h"
+
+// From Bootloader/Inc:
+#include "tInfoBootloader.h"
+
+// ?
+#include "externLogbookFlash.h"
+#include "firmwareEraseProgram.h"
+#include "firmwareJumpToApplication.h"
+
+// From Common/Inc:
+#include "FirmwareData.h"
+
+// From Common/Drivers:
+#include "stm32f4xx_hal.h"
+#include "stm32f4xx_hal_rcc.h"
+#include "stm32f4xx_hal_flash_ex.h"
+#include "stm32f4xx_hal_wwdg.h"
+
+// From Discovery/Inc (shall be shared...)
+#include "data_exchange_main.h"
+#include "display.h"
+#include "gfx_engine.h"
+#include "ostc.h"
+#include "tComm.h"
+#include "tStructure.h"
+
+// From AC6 support:
+#include <stdio.h>
+#include <string.h> // for memcopy
+
+/* Private define ------------------------------------------------------------*/
+#define BUFFER_SIZE         ((uint32_t)0x00177000)
+#define WRITE_READ_ADDR     ((uint32_t)0x0000)
+#define REFRESH_COUNT       ((uint32_t)0x0569)   /* SDRAM refresh counter (90Mhz SD clock) */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+uint8_t returnFromCommCleanUpRequest = 0;
+
+const SFirmwareData bootloader_FirmwareData __attribute__(( section(".bootloader_firmware_data") )) =
+{
+		.versionFirst   = 1,
+		.versionSecond  = 0,
+		.versionThird   = 1,
+		.versionBeta    = 1,
+
+	/* 4 bytes with trailing 0 */
+	.signature = "cw",
+
+	.release_year   = 16,
+	.release_month  = 4,
+	.release_day    = 8,
+	.release_sub    = 0,
+
+	/* max 48 with trailing 0 */
+	.release_info ="tComm with all",
+
+	/* for safety reasons and coming functions*/
+	.magic[0] = FIRMWARE_MAGIC_FIRST,
+	.magic[1] = FIRMWARE_MAGIC_SECOND,
+	.magic[2] = FIRMWARE_MAGIC_FIRMWARE, /* the magic byte */
+	.magic[3] = FIRMWARE_MAGIC_END
+};
+
+
+const SHardwareData HardwareData __attribute__((at(HARDWAREDATA_ADDRESS))) = {
+
+	// first 52 bytes
+	.primarySerial = 0xFFFF,
+	.primaryLicence	= 0xFF,
+	.revision8bit = 0xFF,
+	.production_year = 0xFF,
+	.production_month = 0xFF,
+	.production_day = 0xFF,
+	.production_bluetooth_name_set = 0xFF,
+
+	.production_info = {
+		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
+
+	// other 12 bytes (64 in total)
+	.secondarySerial = 0xFFFF,
+	.secondaryLicence = 0xFF,
+	.secondaryReason8bit = 0xFF,
+	.secondary_year = 0xFF,
+	.secondary_month = 0xFF,
+	.secondary_day = 0xFF,
+	.secondary_bluetooth_name_set = 0xFF,
+	.secondary_info = {0xFF,0xFF,0xFF,0xFF}
+};
+
+
+RTC_HandleTypeDef	RtcHandle;
+TIM_HandleTypeDef   TimHandle; /* used in stm32f4xx_it.c too */
+TIM_HandleTypeDef   TimBacklightHandle; /* used in stm32f4xx_it.c too */
+
+uint32_t time_before;
+uint32_t time_between;
+uint32_t time_after;
+
+/* SDRAM handler declaration */
+SDRAM_HandleTypeDef hsdram;
+FMC_SDRAM_TimingTypeDef SDRAM_Timing;
+FMC_SDRAM_CommandTypeDef command;
+
+FLASH_OBProgramInitTypeDef    OBInit;
+FLASH_AdvOBProgramInitTypeDef AdvOBInit;
+
+
+/* Private variables with external access ------------------------------------*/
+
+uint32_t globalStateID = 0;
+uint8_t globalModeID = SURFMODE;
+uint32_t time_without_button_pressed_deciseconds = 0;
+uint8_t bootToBootloader = 0;
+
+/* Private function prototypes -----------------------------------------------*/
+
+//static void LCD_ToggleFramebuffer(GFX_DrawCfgTypeDef *hconfig);
+//static void LCD_Config(GFX_DrawCfgTypeDef *hconfig);
+static void SystemClock_Config(void);
+static void Error_Handler(void);
+
+static void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command);
+static void SDRAM_Config(void);
+//static void DualBoot(void);
+static void EXTILine_Buttons_Config(void);
+//static void RTC_init(void);
+static void TIM_init(void);
+static void TIM_BACKLIGHT_init(void);
+//static void TIM_BACKLIGHT_adjust(void);
+static void gotoSleep(void);
+uint8_t checkResetForFirmwareUpdate(void);
+void DeleteResetToFirmwareUpdateRegister(void);
+void reset_to_firmware_using_Watchdog(void);
+void reset_to_update_using_system_reset(void);
+
+//static void DualBootToBootloader(void);
+
+/* ITM Trace-------- ---------------------------------------------------------*/
+/*
+#define ITM_Port8(n)    (*((volatile unsigned char *)(0xE0000000+4*n)))
+#define ITM_Port16(n)   (*((volatile unsigned short*)(0xE0000000+4*n)))
+#define ITM_Port32(n)   (*((volatile unsigned long *)(0xE0000000+4*n)))
+
+#define DEMCR           (*((volatile unsigned long *)(0xE000EDFC)))
+#define TRCENA          0x01000000
+
+struct __FILE { int handle; };
+FILE __stdout;
+FILE __stdin;
+
+int fputc(int ch, FILE *f) {
+	if (DEMCR & TRCENA) {
+		while (ITM_Port32(0) == 0);
+		ITM_Port8(0) = ch;
+	}
+	return(ch);
+}
+*/
+
+/* Private functions ---------------------------------------------------------*/
+
+/**
+	* @brief   Main program
+	* @param  None
+	* @retval None
+	*/
+
+void GPIO_test_I2C_lines(void)
+{
+	GPIO_InitTypeDef   GPIO_InitStructure;
+	__GPIOA_CLK_ENABLE();
+	__GPIOG_CLK_ENABLE();
+	GPIO_InitStructure.Pin = GPIO_PIN_7;
+	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
+	GPIO_InitStructure.Pull = GPIO_PULLUP;
+	GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+	HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
+	GPIO_InitStructure.Pin = GPIO_PIN_3;
+	HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+	while(1)
+	{
+	HAL_GPIO_WritePin(GPIOG,GPIO_PIN_7,GPIO_PIN_SET);
+	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET);
+	HAL_Delay(10);
+	HAL_GPIO_WritePin(GPIOG,GPIO_PIN_7,GPIO_PIN_RESET);
+	HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET);
+	HAL_Delay(10);
+	}
+}
+
+
+int main(void)
+{
+
+/*
+	HAL_Init();
+	SystemClock_Config();
+GPIO_test_I2C_lines();
+*/
+	uint32_t pLayerInvisible;
+	uint32_t firmware_load_result;
+	uint8_t magicbyte = 0;
+	uint8_t callForUpdate;
+	uint8_t status = 0;
+	char textVersion[32];
+	uint8_t ptr;
+	uint32_t pOffset;
+
+	set_globalState(StBoot0);
+
+	HAL_Init();
+	HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
+
+	/* feedback for the user
+	 * aber sehr unsch�n beim Warmstart
+	 * da das letzte Bild noch lange nachleuchtet */
+//	MX_GPIO_Backlight_max_static_only_Init();
+
+
+	/* button press is only 40 to 50 us low */
+	MX_GPIO_One_Button_only_Init();
+
+	uint32_t i = 500000;
+
+	callForUpdate = __HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST);
+
+	if(callForUpdate)
+	{
+		i = 0;
+	}
+	else
+	if(			(firmware_MainCodeIsProgammed() == 0)
+			||	(hardwareDataGetPointer()->primarySerial == 0xFFFF)
+			||	(hardwareDataGetPointer()->production_bluetooth_name_set == 0xFF))
+	{
+		i = 1;
+	}
+	else
+	{
+		while(MX_GPIO_Read_The_One_Button() && i)
+		{
+			i--;
+			__NOP();
+		}
+		if(i)
+		{
+			i = 200000;
+			while(!MX_GPIO_Read_The_One_Button() && i)
+			{
+				i--;
+				__NOP();
+			}
+			if(i)
+			{
+				i = 200000;
+				while(MX_GPIO_Read_The_One_Button() && i)
+				{
+					i--;
+					__NOP();
+				}
+				if(i)
+				{
+					i = 200000;
+					while(!MX_GPIO_Read_The_One_Button() && i)
+					{
+						i--;
+						__NOP();
+					}
+					if(i)
+					{
+						i = 200000;
+						while(MX_GPIO_Read_The_One_Button() && i)
+						{
+							i--;
+							__NOP();
+						}
+					}
+				}
+			}
+		}
+	}
+
+	if((i == 0) && (callForUpdate == 0))
+		firmware_JumpTo_Application();
+
+	SystemClock_Config();
+
+	MX_GPIO_Init();
+	MX_Bluetooth_PowerOn();
+	MX_SPI_Init();
+	SDRAM_Config();
+	HAL_Delay(100);
+
+	GFX_init1_no_DMA(&pLayerInvisible, 2);
+
+	TIM_BACKLIGHT_init();
+
+// -----------------------------
+
+	display_power_on__1_of_2__pre_RGB();
+	GFX_LTDC_Init();
+	GFX_LTDC_LayerDefaultInit(TOP_LAYER, pLayerInvisible);
+	GFX_LTDC_LayerDefaultInit(BACKGRD_LAYER, pLayerInvisible);
+	GFX_SetFramesTopBottom(pLayerInvisible,pLayerInvisible,480);
+	HAL_Delay(20);
+	display_power_on__2_of_2__post_RGB();
+
+// -----------------------------
+	GFX_change_LTDC();
+	GFX_hwBackgroundOn();
+	GFX_change_LTDC();
+// -----------------------------
+	tInfoBootloader_init();
+// -----------------------------
+	if(i == 0)
+	{
+		tInfo_newpage("load firmware data");
+		uint8_t* pBuffer = (uint8_t*)((uint32_t)0xD0000000); /* blocked via  GFX_init1_no_DMA */
+		firmware_load_result = ext_flash_read_firmware(pBuffer,768000, &magicbyte);
+
+		if((firmware_load_result > 0) && (firmware_load_result < 768000) && (magicbyte == 0xEE))
+		{
+			ptr = ext_flash_read_firmware_version(textVersion);
+			textVersion[ptr++] = 'f';
+			textVersion[ptr++] = 'o';
+			textVersion[ptr++] = 'u';
+			textVersion[ptr++] = 'n';
+			textVersion[ptr++] = 'd';
+			textVersion[ptr] = 0;
+
+			tInfo_newpage(textVersion);
+			tInfo_write("erase flash");
+			status = firmware_eraseFlashMemory();
+			if(status != HAL_OK)
+			{
+				tInfo_newpage("error. try again.");
+				status = firmware_eraseFlashMemory();
+				if(status != HAL_OK)
+				{
+					tInfo_newpage("error. skip update.");
+					HAL_Delay(1000);
+				}
+			}
+			if(status == HAL_OK)
+			{
+				tInfo_write("programm flash");
+				status = firmware_programFlashMemory(pBuffer,firmware_load_result);
+				if(status != HAL_OK)
+				{
+					tInfo_newpage("error. try again.");
+					status = firmware_programFlashMemory(pBuffer,firmware_load_result);
+					if(status != HAL_OK)
+					{
+						tInfo_newpage("error. skip update.");
+						HAL_Delay(1000);
+					}
+				}
+			}
+		}
+	}
+
+	/* here comes the variable upper firmware loader */
+	if((i == 0) && (status == HAL_OK))
+	{
+		tInfo_newpage("load firmware2 data");
+		uint8_t* pBuffer = (uint8_t*)((uint32_t)0xD0000000); /* blocked via  GFX_init1_no_DMA */
+		firmware_load_result = ext_flash_read_firmware2(&pOffset, pBuffer,768000*2,0,0);
+
+		if((firmware_load_result > 0) && (firmware_load_result + pOffset <= 1024000))
+		{
+			ptr = 0;
+			ptr += gfx_number_to_string(7,0,&textVersion[ptr],firmware_load_result);
+			textVersion[ptr++] = ' ';
+			textVersion[ptr++] = 'b';
+			textVersion[ptr++] = 'y';
+			textVersion[ptr++] = 't';
+			textVersion[ptr++] = 'e';
+			textVersion[ptr++] = 's';
+			textVersion[ptr++] = ' ';
+			textVersion[ptr++] = 'w';
+			textVersion[ptr++] = 'i';
+			textVersion[ptr++] = 't';
+			textVersion[ptr++] = 'h';
+			textVersion[ptr++] = ' ';
+			ptr += gfx_number_to_string(7,0,&textVersion[ptr],pOffset);
+			textVersion[ptr++] = ' ';
+			textVersion[ptr++] = 'o';
+			textVersion[ptr++] = 'f';
+			textVersion[ptr++] = 'f';
+			textVersion[ptr++] = 's';
+			textVersion[ptr++] = 'e';
+			textVersion[ptr++] = 't';
+			textVersion[ptr] = 0;
+			tInfo_newpage(textVersion);
+
+			ptr = 0;
+			textVersion[ptr++] = 'f';
+			textVersion[ptr++] = 'o';
+			textVersion[ptr++] = 'u';
+			textVersion[ptr++] = 'n';
+			textVersion[ptr++] = 'd';
+			textVersion[ptr] = 0;
+
+			tInfo_write(textVersion);
+			tInfo_write("erase flash");
+			status = firmware2_variable_upperpart_eraseFlashMemory(firmware_load_result,pOffset);
+			if(status != HAL_OK)
+			{
+				tInfo_newpage("error. try again.");
+				status = firmware2_variable_upperpart_eraseFlashMemory(firmware_load_result,pOffset);
+				if(status != HAL_OK)
+				{
+					tInfo_newpage("error. skip update.");
+					HAL_Delay(1000);
+				}
+			}
+			if(status == HAL_OK)
+			{
+				tInfo_write("programm flash");
+				status = firmware2_variable_upperpart_programFlashMemory(firmware_load_result,pOffset,pBuffer,firmware_load_result,0);
+				if(status != HAL_OK)
+				{
+					tInfo_newpage("error. try again.");
+					status = firmware2_variable_upperpart_programFlashMemory(firmware_load_result,pOffset,pBuffer,firmware_load_result,0);
+					if(status != HAL_OK)
+					{
+						tInfo_newpage("error. skip update.");
+						HAL_Delay(1000);
+					}
+				}
+			}
+		}
+	}
+
+	if((i == 0) && (status == HAL_OK))
+	{
+		tInfo_newpage("Done.");
+		tInfo_write("Cleaning.");
+		ext_flash_erase_firmware_if_not_empty();
+		ext_flash_erase_firmware2_if_not_empty();
+		tInfo_write("Reset device.");
+		reset_to_firmware_using_Watchdog();
+	}
+
+	ptr = 0;
+	textVersion[ptr++] = '\021';
+	textVersion[ptr++] = 's';
+	textVersion[ptr++] = 'e';
+	textVersion[ptr++] = 'r';
+	textVersion[ptr++] = 'i';
+	textVersion[ptr++] = 'a';
+	textVersion[ptr++] = 'l';
+	textVersion[ptr++] = ' ';
+	if(HardwareData.primarySerial == 0xFFFF)
+	{
+		textVersion[ptr++] = 'n';
+		textVersion[ptr++] = 'o';
+		textVersion[ptr++] = 't';
+		textVersion[ptr++] = ' ';
+		textVersion[ptr++] = 's';
+		textVersion[ptr++] = 'e';
+		textVersion[ptr++] = 't';
+	}
+	else if(HardwareData.secondarySerial == 0xFFFF)
+	{
+		textVersion[ptr++] = '#';
+		ptr += gfx_number_to_string(5,1,&textVersion[ptr],HardwareData.primarySerial);
+	}
+	else
+	{
+		textVersion[ptr++] = '#';
+		ptr += gfx_number_to_string(5,1,&textVersion[ptr],HardwareData.secondarySerial);
+		textVersion[ptr++] = ' ';
+		textVersion[ptr++] = '(';
+		ptr += gfx_number_to_string(5,1,&textVersion[ptr],HardwareData.primarySerial);
+		textVersion[ptr++] = ')';
+	}
+	textVersion[ptr++] = '\020';
+	textVersion[ptr] = 0;
+
+	tInfo_button_text("Exit","","Sleep");
+	tInfo_newpage("Bootloader 160602");
+	tInfo_write("start bluetooth");
+	tInfo_write("");
+	tInfo_write(textVersion);
+	tInfo_write("");
+
+	TIM_init();
+	MX_UART_Init();
+	MX_Bluetooth_PowerOn();
+	tComm_Set_Bluetooth_Name(0);
+
+	tComm_init();
+	set_globalState_Base();
+
+	GFX_start_VSYNC_IRQ();
+
+	EXTILine_Buttons_Config();
+/*
+	uint8_t* pBuffer1 = (uint8_t*)getFrame(20);
+	firmware_load_result = ext_flash_read_firmware(pBuffer1,768000);
+
+	if((firmware_load_result > 0) && (firmware_load_result < 768000))
+	{
+		firmware_eraseFlashMemory();
+		firmware_programFlashMemory(pBuffer1,firmware_load_result);
+		// not for testing
+		//ext_flash_erase_firmware_if_not_empty();
+		reset_to_firmware_using_Watchdog();
+	}
+*/
+	while(1)
+	{
+//		if(bootToBootloader)
+//			DualBootToBootloader();
+
+		if(bootToBootloader)
+			reset_to_update_using_system_reset();
+
+		tComm_control(); // will stop while loop if tComm Mode started until exit from UART
+	};
+}
+
+
+void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
+{
+
+	SStateList status;
+
+	get_globalStateList(&status);
+
+	switch(status.base)
+	{
+		default:
+//			TIM_BACKLIGHT_adjust();
+			break;
+	}
+
+	if(returnFromCommCleanUpRequest)
+	{
+		tComm_exit();
+		returnFromCommCleanUpRequest = 0;
+		GFX_hwBackgroundOn();
+		tInfo_button_text("Exit","","Sleep");
+		tInfo_newpage("bluetooth disonnected");
+		tInfo_write("");
+		tInfo_write("");
+		tInfo_write("");
+		tInfo_write("");
+	}
+
+	get_globalStateList(&status);
+
+	switch(status.base)
+	{
+		case BaseComm:
+			if(get_globalState() == StUART_STANDARD)
+			 tComm_refresh();
+			break;
+		default:
+			break;
+	}
+}
+
+void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
+{
+	uint8_t action;
+	SStateList status;
+	static uint8_t counterToPreventSleep = 0;
+	if(GPIO_Pin == VSYNC_IRQ_PIN) // rechts, unten
+	{
+		GFX_change_LTDC();
+		housekeepingFrame();
+		if(counterToPreventSleep < 250)
+			counterToPreventSleep++;
+		else
+		if(counterToPreventSleep != 255)
+		{
+			counterToPreventSleep = 255;
+		}
+
+		return;
+	}
+
+	time_without_button_pressed_deciseconds	= 0;
+
+	if(GFX_logoStatus() != 0)
+		return;
+
+	if(GPIO_Pin == BUTTON_BACK_PIN) // links
+		action = ACTION_BUTTON_BACK;
+	else
+	if(GPIO_Pin == BUTTON_ENTER_PIN) // mitte
+		action = ACTION_BUTTON_ENTER;
+	else
+	if(GPIO_Pin == BUTTON_NEXT_PIN) // rechts
+		action = ACTION_BUTTON_NEXT;
+#ifdef BUTTON_CUSTOM_PIN
+	else
+	if(GPIO_Pin == BUTTON_CUSTOM_PIN) // extra
+		action = ACTION_BUTTON_CUSTOM;
+#endif
+	else
+		action = 0;
+	get_globalStateList(&status);
+
+	switch(status.base)
+	{
+		case BaseComm:
+			if(action == ACTION_BUTTON_BACK)
+			{
+				reset_to_firmware_using_Watchdog();
+			}
+		 break;
+
+		default:
+			if((action == ACTION_BUTTON_NEXT) && (counterToPreventSleep == 255) && (get_globalState() == StS))
+			{
+				while(1)
+				{
+					MX_tell_reset_logik_alles_ok();
+					DataEX_call();
+					HAL_Delay(100);
+				}
+			}
+			else
+			if(action == ACTION_BUTTON_BACK)
+			{
+				reset_to_firmware_using_Watchdog();
+			}
+			else
+			if(action == ACTION_BUTTON_CUSTOM)
+			{
+				if(get_globalState() == StS)
+					gotoSleep();
+			}
+			else
+			if(action == ACTION_BUTTON_ENTER)
+			{
+				reset_to_update_using_system_reset();
+			}
+			break;
+	}
+}
+
+
+void gotoSleep(void)
+{
+	ext_flash_erase_firmware_if_not_empty();
+	set_globalState(StStop);
+}
+
+// -----------------------------
+
+
+void MainBootLoaderInit(void)
+{
+	void (*SysMemBootJump)(void);
+	SysMemBootJump=(void (*)(void)) (*((uint32_t *) 0x1fff0004));
+
+	// DMA, SPI, UART, TIM, ExtIRQ, graphics DMA, LTDC
+
+	HAL_RCC_DeInit();
+	SysTick->CTRL = 0;
+	SysTick->LOAD = 0;
+	SysTick->VAL = 0;
+
+	__set_PRIMASK(1);
+
+	__set_MSP(0x20002318);
+	SysMemBootJump();
+}
+
+uint32_t get_globalState(void)
+{
+	return globalStateID;
+}
+
+void get_globalStateList(SStateList *output)
+{
+	output->base  = (uint8_t)((globalStateID >> 28) & 0x0F);
+	output->page  = (uint8_t)((globalStateID >> 24) & 0x0F);
+	output->line  = (uint8_t)((globalStateID >> 16) & 0xFF);
+	output->field = (uint8_t)((globalStateID >> 8) & 0xFF);
+	output->mode  = (uint8_t)((globalStateID     ) & 0xFF);
+}
+
+void get_idSpecificStateList(uint32_t id, SStateList *output)
+{
+	output->base  = (uint8_t)((id >> 28) & 0x0F);
+	output->page  = (uint8_t)((id >> 24) & 0x0F);
+	output->line  = (uint8_t)((id >> 16) & 0xFF);
+	output->field = (uint8_t)((id >> 8) & 0xFF);
+	output->mode  = (uint8_t)((id     ) & 0xFF);
+}
+
+void	set_globalState_Base(void)
+{
+	set_globalState(StS);
+}
+
+void set_globalState_Menu_Page(uint8_t page)
+{
+	globalStateID = ((BaseMenu << 28) + (page << 24));
+}
+
+void set_globalState_Log_Page(uint8_t pageIsLine)
+{
+	globalStateID = StILOGLIST + (pageIsLine << 16);
+}
+
+
+void set_globalState_Menu_Line(uint8_t line)
+{
+	globalStateID = ((globalStateID & MaskLineFieldDigit) + (line << 16));
+}
+
+
+void set_globalState(uint32_t newID)
+{
+	globalStateID = newID;
+}
+
+
+
+void delayMicros(uint32_t micros)
+{
+	micros = micros * (168/4) - 10;
+	while(micros--);
+}
+
+
+void get_RTC_DateTime(RTC_DateTypeDef * sdatestructureget, RTC_TimeTypeDef * stimestructureget)
+{
+	/* Get the RTC current Time */
+	if(sdatestructureget)
+		HAL_RTC_GetTime(&RtcHandle, stimestructureget, FORMAT_BIN);
+	/* Get the RTC current Date */
+	if(stimestructureget)
+		HAL_RTC_GetDate(&RtcHandle, sdatestructureget, FORMAT_BIN);
+}
+
+
+void set_RTC_DateTime(RTC_DateTypeDef * sdatestructure, RTC_TimeTypeDef * stimestructure)
+{
+	if(sdatestructure)
+		if(HAL_RTC_SetDate(&RtcHandle,sdatestructure,FORMAT_BCD) != HAL_OK)
+		{
+			/* Initialization Error */
+			Error_Handler();
+		}
+
+	if(stimestructure)
+		if(HAL_RTC_SetTime(&RtcHandle,stimestructure,FORMAT_BCD) != HAL_OK)
+		{
+			/* Initialization Error */
+			Error_Handler();
+		}
+}
+
+static void TIM_init(void)
+{
+	uint16_t uwPrescalerValue = 0;
+
+	uwPrescalerValue = (uint32_t) ((SystemCoreClock /2) / 10000) - 1;
+
+	/* Set TIMx instance */
+	TimHandle.Instance = TIMx;
+
+	/* Initialize TIM3 peripheral as follows:
+			 + Period = 10000 - 1
+			 + Prescaler = ((SystemCoreClock/2)/10000) - 1
+			 + ClockDivision = 0
+			 + Counter direction = Up
+	*/
+	TimHandle.Init.Period = 1000 - 1;
+	TimHandle.Init.Prescaler = uwPrescalerValue;
+	TimHandle.Init.ClockDivision = 0;
+	TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
+	if(HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
+	{
+		/* Initialization Error */
+		Error_Handler();
+	}
+
+	/*##-2- Start the TIM Base generation in interrupt mode ####################*/
+	/* Start Channel1 */
+	if(HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK)
+	{
+		/* Starting Error */
+		Error_Handler();
+	}
+}
+
+#ifndef TIM_BACKLIGHT
+/*
+static void TIM_BACKLIGHT_adjust(void)
+{
+}
+*/
+static void TIM_BACKLIGHT_init(void)
+{
+}
+#else
+/*
+static void TIM_BACKLIGHT_adjust(void)
+{
+
+	TIM_OC_InitTypeDef sConfig;
+	sConfig.OCMode     = TIM_OCMODE_PWM1;
+	sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
+	sConfig.OCFastMode = TIM_OCFAST_DISABLE;
+	sConfig.Pulse = 600;
+
+	HAL_TIM_PWM_ConfigChannel(&TimBacklightHandle, &sConfig, TIM_BACKLIGHT_CHANNEL);
+	HAL_TIM_PWM_Start(&TimBacklightHandle, TIM_BACKLIGHT_CHANNEL);
+}
+*/
+static void TIM_BACKLIGHT_init(void)
+{
+	uint32_t uwPrescalerValue = 0;
+	TIM_OC_InitTypeDef sConfig;
+
+	uwPrescalerValue = (uint32_t) ((SystemCoreClock /2) / 18000000) - 1;
+
+	TimBacklightHandle.Instance = TIM_BACKLIGHT;
+
+	// Initialize TIM3 peripheral as follows:	30 kHz
+
+	TimBacklightHandle.Init.Period = 600 - 1;
+	TimBacklightHandle.Init.Prescaler = uwPrescalerValue;
+	TimBacklightHandle.Init.ClockDivision = 0;
+	TimBacklightHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
+	HAL_TIM_PWM_Init(&TimBacklightHandle);
+
+	sConfig.OCMode     = TIM_OCMODE_PWM1;
+	sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
+	sConfig.OCFastMode = TIM_OCFAST_DISABLE;
+	sConfig.Pulse = 50 * 6;
+
+	HAL_TIM_PWM_ConfigChannel(&TimBacklightHandle, &sConfig, TIM_BACKLIGHT_CHANNEL);
+	HAL_TIM_PWM_Start(&TimBacklightHandle, TIM_BACKLIGHT_CHANNEL);
+}
+#endif
+
+	/* Configure RTC prescaler and RTC data registers */
+	/* RTC configured as follow:
+			- Hour Format    = Format 24
+			- Asynch Prediv  = Value according to source clock
+			- Synch Prediv   = Value according to source clock
+			- OutPut         = Output Disable
+			- OutPutPolarity = High Polarity
+			- OutPutType     = Open Drain */
+	/*#define RTC_ASYNCH_PREDIV  0x7F    LSE as RTC clock */
+	/*LSE: #define RTC_SYNCH_PREDIV   0x00FF  LSE as RTC clock */
+	/*LSI: #define RTC_SYNCH_PREDIV   0x0130  LSI as RTC clock */
+/*
+static void RTC_init(void)
+{
+	RtcHandle.Instance = RTC;
+
+
+	RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24;
+	RtcHandle.Init.AsynchPrediv = 0x7F;
+	RtcHandle.Init.SynchPrediv = 0x0130;
+	RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
+	RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
+	RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
+
+	if(HAL_RTC_Init(&RtcHandle) != HAL_OK)
+	{
+		Error_Handler();
+	}
+}
+*/
+
+static void EXTILine_Buttons_Config(void)
+{
+	GPIO_InitTypeDef   GPIO_InitStructure;
+
+	BUTTON_ENTER_GPIO_ENABLE();
+	BUTTON_NEXT_GPIO_ENABLE();
+	BUTTON_BACK_GPIO_ENABLE();
+
+	/* Configure pin as weak PULLUP input  */
+	/* buttons */
+	GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
+	GPIO_InitStructure.Pull = GPIO_NOPULL;
+	GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+
+	GPIO_InitStructure.Pin = BUTTON_ENTER_PIN;
+	HAL_GPIO_Init(BUTTON_ENTER_GPIO_PORT, &GPIO_InitStructure);
+
+	GPIO_InitStructure.Pin = BUTTON_NEXT_PIN;
+	HAL_GPIO_Init(BUTTON_NEXT_GPIO_PORT, &GPIO_InitStructure);
+
+	GPIO_InitStructure.Pin = BUTTON_BACK_PIN;
+	HAL_GPIO_Init(BUTTON_BACK_GPIO_PORT, &GPIO_InitStructure);
+
+	/* Enable and set EXTI Line0 Interrupt to the lowest priority */
+	HAL_NVIC_SetPriority(BUTTON_ENTER_EXTI_IRQn, 2, 0);
+	HAL_NVIC_SetPriority(BUTTON_NEXT_EXTI_IRQn,  2, 0);
+	HAL_NVIC_SetPriority(BUTTON_BACK_EXTI_IRQn,  2, 0);
+	HAL_NVIC_EnableIRQ(BUTTON_ENTER_EXTI_IRQn);
+	HAL_NVIC_EnableIRQ(BUTTON_NEXT_EXTI_IRQn);
+	HAL_NVIC_EnableIRQ(BUTTON_BACK_EXTI_IRQn);
+
+#ifdef BUTTON_CUSTOM_PIN
+	BUTTON_CUSTOM_GPIO_ENABLE();
+	GPIO_InitStructure.Pin = BUTTON_CUSTOM_PIN;
+	HAL_GPIO_Init(BUTTON_CUSTOM_GPIO_PORT, &GPIO_InitStructure);
+	HAL_NVIC_SetPriority(BUTTON_CUSTOM_EXTI_IRQn,  2, 0);
+	HAL_NVIC_EnableIRQ(BUTTON_CUSTOM_EXTI_IRQn);
+#endif
+}
+
+
+/**
+	* @brief  System Clock Configuration
+	*         The system Clock is configured as follow :
+	*            System Clock source            = PLL (HSE)
+	*            SYSCLK(Hz)                     = 180000000
+	*            HCLK(Hz)                       = 180000000
+	*            AHB Prescaler                  = 1
+	*            APB1 Prescaler                 = 4
+	*            APB2 Prescaler                 = 2
+	*            HSE Frequency(Hz)              = 8000000
+	*            PLL_M                          = 8
+	*            PLL_N                          = 360
+	*            PLL_P                          = 2
+	*            PLL_Q                          = 7
+	*            VDD(V)                         = 3.3
+	*            Main regulator output voltage  = Scale1 mode
+	*            Flash Latency(WS)              = 5
+	*         The LTDC Clock is configured as follow :
+	*            PLLSAIN                        = 192
+	*            PLLSAIR                        = 4
+	*            PLLSAIDivR                     = 8
+	* @param  None
+	* @retval None
+	*/
+static void SystemClock_Config(void)
+{
+	RCC_ClkInitTypeDef RCC_ClkInitStruct;
+	RCC_OscInitTypeDef RCC_OscInitStruct;
+	RCC_PeriphCLKInitTypeDef  PeriphClkInitStruct;
+
+	/* Enable Power Control clock */
+	__PWR_CLK_ENABLE();
+
+	/* The voltage scaling allows optimizing the power consumption when the device is
+		 clocked below the maximum system frequency, to update the voltage scaling value
+		 regarding system frequency refer to product datasheet.  */
+	__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
+
+	/*##-1- System Clock Configuration #########################################*/
+	/* Enable HSE Oscillator and activate PLL with HSE as source */
+	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
+	RCC_OscInitStruct.HSEState = RCC_HSE_ON;
+	RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+	RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
+	RCC_OscInitStruct.PLL.PLLM = 8;
+	RCC_OscInitStruct.PLL.PLLN = 336;//360;
+	RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
+	RCC_OscInitStruct.PLL.PLLQ = 7;
+	HAL_RCC_OscConfig(&RCC_OscInitStruct);
+
+//  HAL_PWREx_ActivateOverDrive();
+HAL_PWREx_DeactivateOverDrive();
+	/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
+		 clocks dividers */
+	RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
+	RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+	RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+	RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
+	RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
+	HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_8);//FLASH_LATENCY_5);
+
+	/*##-2- LTDC Clock Configuration ###########################################*/
+	/* LCD clock configuration */
+	/* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
+	/* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */
+	/* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/4 = 48 Mhz */
+	/* LTDC clock frequency = PLLLCDCLK / RCC_PLLSAIDIVR_8 = 48/8 = 6 Mhz */
+
+	/* neu: 8MHz/8*300/5/8 = 7,5 MHz = 19,5 Hz bei 800 x 480 */
+	PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
+	PeriphClkInitStruct.PLLSAI.PLLSAIN = 300;//192;
+	PeriphClkInitStruct.PLLSAI.PLLSAIR = 5;//4;
+	PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_8;//RCC_PLLSAIDIVR_4;// RCC_PLLSAIDIVR_2; // RCC_PLLSAIDIVR_8
+	HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
+}
+
+
+/**
+	* @brief  This function is executed in case of error occurrence.
+	* @param  None
+	* @retval None
+	*/
+static void Error_Handler(void)
+{
+		/* Turn LED3 on */
+//    BSP_LED_On(LED3);
+		while(1)
+		{
+		}
+}
+
+/**
+	* @brief  Perform the SDRAM exernal memory inialization sequence
+	* @param  hsdram: SDRAM handle
+	* @param  Command: Pointer to SDRAM command structure
+	* @retval None
+	*/
+static void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command)
+{
+	__IO uint32_t tmpmrd =0;
+	/* Step 3:  Configure a clock configuration enable command */
+	Command->CommandMode 			 = FMC_SDRAM_CMD_CLK_ENABLE;
+	Command->CommandTarget 		 = FMC_SDRAM_CMD_TARGET_BANK2;
+	Command->AutoRefreshNumber 	 = 1;
+	Command->ModeRegisterDefinition = 0;
+
+	/* Send the command */
+	HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
+
+	/* Step 4: Insert 100 ms delay */
+	HAL_Delay(100);
+
+	/* Step 5: Configure a PALL (precharge all) command */
+	Command->CommandMode 			 = FMC_SDRAM_CMD_PALL;
+	Command->CommandTarget 	     = FMC_SDRAM_CMD_TARGET_BANK2;
+	Command->AutoRefreshNumber 	 = 1;
+	Command->ModeRegisterDefinition = 0;
+
+	/* Send the command */
+	HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
+
+	/* Step 6 : Configure a Auto-Refresh command */
+	Command->CommandMode 			 = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
+	Command->CommandTarget 		 = FMC_SDRAM_CMD_TARGET_BANK2;
+	Command->AutoRefreshNumber 	 = 4;
+	Command->ModeRegisterDefinition = 0;
+
+	/* Send the command */
+	HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
+
+	/* Step 7: Program the external memory mode register */
+	tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2          |
+										 SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |
+										 SDRAM_MODEREG_CAS_LATENCY_3           |
+										 SDRAM_MODEREG_OPERATING_MODE_STANDARD |
+										 SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
+
+	Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
+	Command->CommandTarget 		 = FMC_SDRAM_CMD_TARGET_BANK2;
+	Command->AutoRefreshNumber 	 = 1;
+	Command->ModeRegisterDefinition = tmpmrd;
+
+	/* Send the command */
+	HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
+
+	/* Step 8: Set the refresh rate counter */
+	/* (15.62 us x Freq) - 20 */
+	/* neu: (8 us x Freq) - 20 */
+	/* Set the device refresh counter */
+	HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT);
+}
+
+/*
+static void DualBoot(void)
+{
+		// Set BFB2 bit to enable boot from Flash Bank2
+		// Allow Access to Flash control registers and user Falsh
+		HAL_FLASH_Unlock();
+
+		// Allow Access to option bytes sector
+		HAL_FLASH_OB_Unlock();
+
+		// Get the Dual boot configuration status
+		AdvOBInit.OptionType = OBEX_BOOTCONFIG;
+		HAL_FLASHEx_AdvOBGetConfig(&AdvOBInit);
+
+		// Enable/Disable dual boot feature
+		if (((AdvOBInit.BootConfig) & (FLASH_OPTCR_BFB2)) == FLASH_OPTCR_BFB2)
+		{
+			AdvOBInit.BootConfig = OB_DUAL_BOOT_DISABLE;
+			HAL_FLASHEx_AdvOBProgram (&AdvOBInit);
+		}
+		else
+		{
+			AdvOBInit.BootConfig = OB_DUAL_BOOT_ENABLE;
+			HAL_FLASHEx_AdvOBProgram (&AdvOBInit);
+		}
+
+		// Start the Option Bytes programming process
+		if (HAL_FLASH_OB_Launch() != HAL_OK)
+		{
+			// User can add here some code to deal with this error
+			while (1)
+			{
+			}
+		}
+		// Prevent Access to option bytes sector
+		HAL_FLASH_OB_Lock();
+
+		// Disable the Flash option control register access (recommended to protect
+		// the option Bytes against possible unwanted operations)
+		HAL_FLASH_Lock();
+
+		// Initiates a system reset request to reset the MCU
+		reset_to_firmware_using_Watchdog();
+}
+*/
+/**
+	******************************************************************************
+	******************************************************************************
+	******************************************************************************
+	*/
+
+
+/**
+	* @brief DMA2D configuration.
+	* @note  This function Configure tha DMA2D peripheral :
+	*        1) Configure the transfer mode : memory to memory W/ pixel format conversion
+	*        2) Configure the output color mode as ARGB4444
+	*        3) Configure the output memory address at SRAM memory
+	*        4) Configure the data size : 320x120 (pixels)
+	*        5) Configure the input color mode as ARGB8888
+	*        6) Configure the input memory address at FLASH memory
+	* @retval
+	*  None
+	*/
+
+static void SDRAM_Config(void)
+{
+	/*##-1- Configure the SDRAM device #########################################*/
+	/* SDRAM device configuration */
+	hsdram.Instance = FMC_SDRAM_DEVICE;
+
+	/* Timing configuration for 90 Mhz of SD clock frequency (180Mhz/2) */
+	/* TMRD: 2 Clock cycles */
+	SDRAM_Timing.LoadToActiveDelay    = 2;
+	/* TXSR: min=70ns (6x11.90ns) */
+	SDRAM_Timing.ExitSelfRefreshDelay = 7;
+	/* TRAS: min=42ns (4x11.90ns) max=120k (ns) */
+	SDRAM_Timing.SelfRefreshTime      = 4;
+	/* TRC:  min=63 (6x11.90ns) */
+	SDRAM_Timing.RowCycleDelay        = 7;
+	/* TWR:  2 Clock cycles */
+	SDRAM_Timing.WriteRecoveryTime    = 2;
+	/* TRP:  15ns => 2x11.90ns */
+	SDRAM_Timing.RPDelay              = 2;
+	/* TRCD: 15ns => 2x11.90ns */
+	SDRAM_Timing.RCDDelay             = 2;
+
+	hsdram.Init.SDBank             = FMC_SDRAM_BANK2;
+	hsdram.Init.ColumnBitsNumber   = FMC_SDRAM_COLUMN_BITS_NUM_9;
+	hsdram.Init.RowBitsNumber      = FMC_SDRAM_ROW_BITS_NUM_13;
+	hsdram.Init.MemoryDataWidth    = SDRAM_MEMORY_WIDTH;
+	hsdram.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
+	hsdram.Init.CASLatency         = FMC_SDRAM_CAS_LATENCY_3;
+	hsdram.Init.WriteProtection    = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
+	hsdram.Init.SDClockPeriod      = SDCLOCK_PERIOD;
+	hsdram.Init.ReadBurst          = FMC_SDRAM_RBURST_DISABLE;
+	hsdram.Init.ReadPipeDelay      = FMC_SDRAM_RPIPE_DELAY_1;
+
+	/* Initialize the SDRAM controller */
+	if(HAL_SDRAM_Init(&hsdram, &SDRAM_Timing) != HAL_OK)
+	{
+		/* Initialization Error */
+		Error_Handler();
+	}
+
+	/* Program the SDRAM external device */
+	SDRAM_Initialization_Sequence(&hsdram, &command);
+}
+
+
+uint8_t checkResetForFirmwareUpdate(void)
+{
+	uint32_t backupRegisterContent;
+
+	RTC_HandleTypeDef RtcHandle;
+	RtcHandle.Instance = RTC;
+	backupRegisterContent = HAL_RTCEx_BKUPRead(&RtcHandle,RTC_BKP_DR0);
+
+	if(backupRegisterContent == 0x12345678)
+		return 1;
+	else
+		return 0;
+}
+
+void DeleteResetToFirmwareUpdateRegister(void)
+{
+	RTC_HandleTypeDef RtcHandle;
+	RtcHandle.Instance = RTC;
+	__HAL_RTC_WRITEPROTECTION_DISABLE(&RtcHandle);
+	HAL_RTCEx_BKUPWrite(&RtcHandle,RTC_BKP_DR0,0x00);
+	__HAL_RTC_WRITEPROTECTION_ENABLE(&RtcHandle);
+}
+
+#ifdef  USE_FULL_ASSERT
+
+/**
+	* @brief  Reports the name of the source file and the source line number
+	*         where the assert_param error has occurred.
+	* @param  file: pointer to the source file name
+	* @param  line: assert_param error line source number
+	* @retval None
+	*/
+void assert_failed(uint8_t* file, uint32_t line)
+{
+	/* User can add his own implementation to report the file name and line number,
+		 ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
+
+	/* Infinite loop */
+	while (1)
+	{
+	}
+}
+#endif
+
+/*
+static void DualBootToBootloader(void)
+{
+		// Set BFB2 bit to enable boot from Flash Bank2
+		// Allow Access to Flash control registers and user Falsh
+		HAL_FLASH_Unlock();
+
+		// Allow Access to option bytes sector
+		HAL_FLASH_OB_Unlock();
+
+		// Get the Dual boot configuration status
+		AdvOBInit.OptionType = OPTIONBYTE_BOOTCONFIG;
+		HAL_FLASHEx_AdvOBGetConfig(&AdvOBInit);
+
+		// Enable/Disable dual boot feature
+		if (((AdvOBInit.BootConfig) & (FLASH_OPTCR_BFB2)) == FLASH_OPTCR_BFB2)
+		{
+			AdvOBInit.BootConfig = OB_DUAL_BOOT_DISABLE;
+			HAL_FLASHEx_AdvOBProgram (&AdvOBInit);
+			if (HAL_FLASH_OB_Launch() != HAL_OK)
+			{
+				while (1)
+				{
+				}
+			}
+		}
+		else
+		{
+
+			AdvOBInit.BootConfig = OB_DUAL_BOOT_ENABLE;
+			HAL_FLASHEx_AdvOBProgram (&AdvOBInit);
+			if (HAL_FLASH_OB_Launch() != HAL_OK)
+			{
+				while (1)
+				{
+				}
+			}
+		}
+
+		// Prevent Access to option bytes sector
+		HAL_FLASH_OB_Lock();
+
+		/ Disable the Flash option control register access (recommended to protect
+		// the option Bytes against possible unwanted operations)
+		HAL_FLASH_Lock();
+
+		// Initiates a system reset request to reset the MCU
+		reset_to_firmware_using_Watchdog();
+}
+*/
+
+void reset_to_update_using_system_reset(void)
+{
+	__HAL_RCC_CLEAR_RESET_FLAGS();
+	HAL_NVIC_SystemReset();
+}
+
+void reset_to_firmware_using_Watchdog(void)
+{
+	__HAL_RCC_CLEAR_RESET_FLAGS();
+	__HAL_RCC_WWDG_CLK_ENABLE();
+
+	WWDG_HandleTypeDef   WwdgHandle;
+	WwdgHandle.Instance = WWDG;
+
+	WwdgHandle.Init.Prescaler = WWDG_PRESCALER_8;
+	WwdgHandle.Init.Window    = 80;
+	WwdgHandle.Init.Counter   = 127;
+
+	HAL_WWDG_Init(&WwdgHandle);
+	HAL_WWDG_Start(&WwdgHandle);
+	while(1);
+}
+
+
+void set_returnFromComm(void)
+{
+	returnFromCommCleanUpRequest = 1;
+}
+
+/************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/