// main.c
// part of "030-demo" project
// 23 January 2017
// Dale Wheat
// https://www.dalewheat.com
// dale@dalewheat.com

#include "main.h"

void main(void) {

	uint32_t x = 0; // *** debug *** test variable

	RCC->AHBENR |= (RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOAEN); // enable GPIO port A, B clock

	// initialize on-chip input & output ports

	// PORT A

	//	PA0
	//	PA1
	//	PA2
	//	PA3
	//	PA4 - LED active low
	//	PA5
	//	PA6
	//	PA7

	//	PA9
	//	PA10

	//	PA13
	//	PA14

	GPIOA->MODER |= GPIO_MODER_MODER4_0; // PA4 = output

	// PORT B

	//	PB1

	// PORT F

	//	PF0 - OSC_IN
	//	PF1 - OSC_OUT

	// main program loop

	while(1) {

		x++; // *** debug *** increment test variable
	}
}

// reset() - reset handling routine

void reset(void) {

    extern char _etext, _data, _edata, _bss, _ebss;
    char *src = &_etext;
    char *dst = &_data;

    // determine source of reset

	// set up clock

	// note:  after reset, default clock source is HSI (~8 MHz)

    // prepare for program execution

    while (dst < &_edata) *dst++ = *src++; // initialize .data segment
    for (dst = &_bss; dst < &_ebss; dst++) *dst = 0; // clear .bss segment

    //SysTick->LOAD = 8000; // 1 ms period
    SysTick->LOAD = 4000000; // 500 ms period
    SysTick->VAL = 1000; // low starting count
    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; // start SysTick counter

    main(); // jump to main() function

    while(1); // do something clever here when main() returns, because it's not supposed to
}

// NMI (non-maskable interrupt) handler

void nmi(void) {

    while(1); // just hang out here for a while
}

// hard fault handler

void hard_fault(void) {

    while(1); // just hang out here for a while
}

void SysTick_vector(void) {

	// SysTick handler

	LED_PORT->ODR ^= LED_PIN; // *** debug *** toggle LED
}

// Cortex-M0 vector table

extern char _estack; // defined in linker script

volatile struct {

	uint32_t *initial_stack_pointer; // usually end-of-RAM pointer
	void (*vector_list[15])(); // list of vectors

} vectors  __attribute__ ((section("vector"))) = {

    (uint32_t *) &_estack,			// initial stack pointer

	{
		reset,			// reset vector
		nmi,			// NMI handler
		hard_fault,		// hard fault handler
		0,				// 4 reserved
		0,				// 5 reserved
		0,				// 6 reserved
		0,				// 7 reserved
		0,				// 8 reserved
		0,				// 9 reserved
		0,				// 10 reserved
		0,				// SVCall
		0,				// 12 reserved
		0,				// 13 reserved
		0,				// PendSV
		SysTick_vector,	// Systick
    }
};

// [end-of-file]
