Source file: /~heha/hsn/bl/bl.zip/bl.cpp

#include "bl.h"

/* Simple function pointer type to call user program */
typedef void (*func_ptr)();

static void delay(uint32_t timeout) {
 do __NOP(); while (--timeout);
}

static void USB_Renum() {
  BB_BIT(GPIOA->CRH,16) = 1;	// PA12: Open Drain Output
  BB_BIT(GPIOA->ODR,12) = 0;	// PA12 nach Low ziehen
  delay(0x10000);
  BB_BIT(GPIOA->ODR,12) = 1;	// PA12 nach High freilassen
  BB_BIT(GPIOA->CRH,16) = 0;	// PA12: Eingang
}

#define SRAM_SIZE (20*1024)		// 20 KiByte SRAM size

static bool check_user_code() {
 uint32_t sp = *reinterpret_cast<uint32_t*>(USER_PROGRAM)-SRAM_BASE;
/* Check if the stack pointer in the vector table points somewhere in SRAM */
 return sp <= SRAM_SIZE;
}

static uint16_t get_and_clear_magic_word() {
	/* Enable the power and backup interface clocks by setting the
	 * PWREN and BKPEN bits in the RCC_APB1ENR register */
 uint32_t save = RCC->APB1ENR;
 RCC->APB1ENR = save | RCC_APB1ENR_BKPEN|RCC_APB1ENR_PWREN;
 uint16_t value = BKP->DR4;
 if (value) {	/* Enable write access to the backup registers and the RTC. */
  BB_BIT(PWR->CR,8) = 1;
  BKP->DR4 = 0;
  BB_BIT(PWR->CR,8) = 0;
 }
 RCC->APB1ENR = save;
 return value;
}

void set_sysclock() {		// hier: 48 MHz (24 MHz geht nicht)
 BB_BIT(RCC->CR,16) = 1;	// Enable High-Speed External Oscillator
 while (!BB_BIT(RCC->CR,17));	// Wait until HSE is ready
 BB_BIT(FLASH->ACR,0) = 1;	// Enable Prefetch Buffer & set Flash access to 1 wait state
	/* SYSCLK = PCLK2 = HCLK */
	/* PCLK1 = HCLK / 2 */
	/* PLLCLK = HSE * 6 = 48 MHz */
 RCC->CFGR =	1<<22 | RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE2_DIV1 | RCC_CFGR_PPRE1_DIV2 |
		RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6 | 0x80;
 BB_BIT(RCC->CR,24) = 1;	// Enable PLL
 while (!BB_BIT(RCC->CR,25)) ;	// Wait until PLL is ready
 BB_BIT(RCC->CFGR,1) = 1;	// Select PLL as system clock source
 while (!BB_BIT(RCC->CFGR,3)) ;	// Wait until PLL is used as system clock source
}

void revert_sysclock() {
 BB_BIT(RCC->CFGR,1) = 0;
 BB_BIT(RCC->CR,24) = 0;
 RCC->CFGR = 0;
 BB_BIT(FLASH->ACR,0) = 0;
 BB_BIT(RCC->CR,16) = 0;
}

// Keep in mind that .bss is not zeroed out!
// Blöd (210917): Nach dem Flashen mit stm32flash.exe ist der Bootloader
// nicht bereit für hid-flash.exe. Nach Reset geht's aber. Nicht schlimm.
static void Reset_Handler() __attribute__((naked,noreturn));
static void Reset_Handler() {
 uint32_t csr = RCC->CSR;	// früh Reset-Ursache erfassen
 RCC->CSR = 1<<24;		// und Bits löschen
 if (get_and_clear_magic_word() == 0x424C
 || csr & 1<<26 && !(csr & 1<<27)// Reset vom Taster: Bootloader aktivieren!
 || !check_user_code()) {
  uint32_t cyclecounter = 0;
  RCC->APB2ENR = 0x3C;
//  set_sysclock();
  LED_INIT;
  UploadState = 0;
  USB_Renum();
  usb::init();
  while (!(UploadState&4)) {
   usb::poll();		// polling instead of interrupt
   if (!UploadState&1) LED = ++cyclecounter>>13&1;
  }
  usb::shutdown();	/* Reset the USB */
//  revert_sysclock();
  RCC->APB2ENR = 0;
 }
 SCB->VTOR = USER_PROGRAM;	// Setup the vector table to the user-defined one in Flash memory
 asm volatile(
"	msr	msp,%0	\n"	// setup stack pointer to the user-defined one
::"r"(*(uint32_t*)(USER_PROGRAM)));
 asm volatile(
"	mov	r0,%0	\n"	// pass reset reason in r0
"	bx	%1	\n"	// jump to user code, LSB dictates ARM(0) or THUMB(1) mode
::"r"(csr),"r"(*(uint32_t*)(USER_PROGRAM+4)));
}	// BUGBUG: Luckily, %1 is not r0, but I don't know how to restrict this.

/* Minimal Flash-based vector table */
func_ptr vectors[] __attribute__((section(".vectors"))) = {
 reinterpret_cast<func_ptr>(SRAM_BASE+SRAM_SIZE),	// Initial stack pointer (MSP)
 Reset_Handler,		// Initial program counter (PC): Reset handler
};
Detected encoding: UTF-80