/********************************************************************************
 * Dold Regler GmbH
 * Description:    Flash Update über USB
 *                 Der Bootloader wird im unteren Flash-Bereich installiert
 * Autor:          Markus Müller
 * Datum:          24.06.2008  V1.0.8624
 * Datum:          07.06.2011  V1.3.1607 JSB Anpassungen ELK02
 * Details:        Start der CPU erfolgt in FW_Main(). Wenn ein gültiges Programm
 *                 erkannt wurde dann wird nach main() weiter gesprungen. Wird
 *                 die Main Schleife beendet, so ist automatisch wieder der
 *                 Bootloader aktiv. Erst mit dem USB Reset Kommando wird dann
 *                 wieder in den main() Task gesprungen.
 *******************************************************************************/

#include "stm32f10x.h"
//#include "Include.h"
#include "FW_Update.h"

//*******************************************************************************
// Parametrierung Bootloader
// Version Bootloader steht auch weiter unten in den Texten!
#define FW_VERSION1V 0x83
#define FW_VERSION2V 0x1607

//*******************************************************************************
// Definition Flash-Bereich für Programm
#define __boot			__attribute__ ((section(".boot")))
// Definition Flash-Bereich für Flash-Daten (nach Programm)
#define __boottbl		__attribute__ ((section(".boottbl")))
// Definition RAM-Bereich
#define __bootdata		__attribute__ ((section(".bootdata")))
//*******************************************************************************
// Alle Texte müssen hier als Konstante deklariert werden !
// Wichtig !! Die serielle Ausgabe darf kein "U" senden !
const char str1[] __boottbl = {"\r\nFW-Loader V1.3.1607\r\n"};
const char str2[] __boottbl = {" ReadOutProtect ON\r\n"};
//*******************************************************************************

//*******************************************************************************
// Variablen

//*******************************************************************************
// FW-Update Funktion

//*******************************************************************************

//*******************************************************************************
// Typdeklarationen
u8	__bootdata FW_ForceHW;
u16	__bootdata FW_Timer;			// ms-Zähler

//*******************************************************************************
// Funktionen
void FW_Init(void);
void FW_UpdateLoop(void);
void FW_Seriell_Text(unsigned char iNr, const char * Value);

//*******************************************************************************
// Initialisierung FW-Update
void __boot FW_Main(void)
{
	SCB->VTOR = NVIC_VectTab_FLASH; // NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

	// Start-Test Boot-Loader /: Muss der HW abgepasst werden!// ToDo
	// CAN-TX ist auf LOW?
	FW_ForceHW = 0;

	RCC->APB2ENR = RCC_APB2Periph_GPIOD;
	GPIOD->BRR = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_12; // IPD, Out 0
  GPIOD->BSRR = GPIO_Pin_1|GPIO_Pin_3|GPIO_Pin_10; // Pin1 IPU, Out 1
  GPIOD->CRL = 0x33bb1884;  // aus App und Boot-Jumper Pin1 (PD1 CanTX)
  GPIOD->CRH = 0x1111b111;  // aus App
// HW_Out_WegFreigabe(void){GPIO_WriteBit(GPIOD, GPIO_Pin_10, uHW_Out.bits.o_REZ);}
	FW_Timer = 0x100;
	while(FW_Timer--);	// Warten bis der Pin Hi ist

  u16 FW_Pin_Loop = 0, FW_Pin_High = 0, FW_Pin_Low = 0;
  for (FW_Pin_Loop = 0; FW_Pin_Loop <5000; FW_Pin_Loop ++)
  {
    if ((GPIOD->IDR & GPIO_Pin_1) == 0) // FW-Boot Jumper steckt
      FW_Pin_Low ++;
    else
      FW_Pin_High ++;
  }
  if (FW_Pin_Low > 4000) // FW-Boot Jumper steckt
    FW_ForceHW = 1;

	while (1)
	{
		// Überprüfen ob in der Applikation die Main-Adresse vorhanden ist
		if (!FW_ForceHW)
		{
		  ;
		}
    FW_Init();
		if (FW_ForceHW)	// Ausgabe nur bei Hand-Funktion
		{
			FW_Seriell_Text(2, str1);	// Version Bootloader
			if (OB->RDP != 0x5AA5)	// Read-Out Protection gesetzt
				FW_Seriell_Text(2, str2);	// "ReadOutProtect ON"
	    FW_ForceHW = 0;
    } else { // Nur initialisierung. Wichtig: Das muss so programmiert werden, da der Compiler die Routinen nicht ordentlich ausführt!
		}
		FW_UpdateLoop();
	}
}

// Initialisierung FW-Update Pheriperie
void __boot FW_Init(void)
{
	SCB->VTOR = NVIC_VectTab_FLASH; // NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
	// Deaktivieren aller HW-Komponenten, SW-Reset
	RCC->APB2RSTR = 0xFFFFFFFF;
	RCC->APB1RSTR = 0xFFFFFFFF;
	RCC->APB2RSTR = 0;
	RCC->APB1RSTR = 0;
	// Alle Interrupts deaktivieren
	NVIC->ICER[0] = 0xFFFFFFFF;
	NVIC->ICER[1] = 0xFFFFFFFF;
	NVIC->ICER[2] = 0xFFFFFFFF;
	NVIC->ICER[3] = 0xFFFFFFFF;
	NVIC->ICER[4] = 0xFFFFFFFF;
	NVIC->ICER[5] = 0xFFFFFFFF;
	NVIC->ICER[6] = 0xFFFFFFFF;
	NVIC->ICER[7] = 0xFFFFFFFF;
// Flash-Zugriff vor Takterhoehung festlegen
	FLASH->ACR &= 0x31; // Flash Latency 1 (bis 48 MHz)
	FLASH->ACR |= 0x10;	// Flash Prefetch Buffer EIN
	// Aktivieren HSI, 8MHz
	RCC->CR |= 1;	// HSI Einschalten
	while ((RCC->CR & 2)!= 2);	// Warte bis HSIRDY  (besser so)
	RCC->CFGR &= 0xFFFFF8FC;	// Clk's Div by 1, HSI aktivieren
	// PLL aktivieren
	RCC->CR &= 0xFEFFFFFF;	// PLL AUS schalten
	RCC->CFGR = RCC_PLLSource_HSI_Div2 | RCC_PLLMul_12 | RCC_CFGR_PPRE1_DIV2;	// für 48MHz CPU
	RCC->CR |= 0x01000000;	// PLL EIN schalten
	while (!(RCC->CR & 0x02000000));	// PLL RDY?
	RCC->CFGR |= 0x00000002;	// PLL als Systemclock aktivieren
	// Buffer leeren / Variablen initialisieren
	FW_Timer = 0;
}

// FW-Update Loop
void __boot FW_UpdateLoop(void)
{
  u8 i;
  for (i = 0; i < 3; i++)
  {
    FW_Seriell_Text(i, "U");
  }
	while (1)
	{
		;
	}
}

void __boot FW_Seriell_Text(unsigned char iNr, const char * Value)
{

}

void __boot FWUSB_LP_CAN_RX0_IRQHandler(void)
{
}

void __boot FW_SysTickHandler(void)
{
}
