Forked from
card10 / firmware
1519 commits behind the upstream repository.
hardware.c 2.56 KiB
/*
* Hardware routines for l0dables.
*
* You shouldn't have to do much here. SystemInit/SystemCoreClockUpdate are
* called automatically before main(), and provide you with a sensible execution
* environment.
*
* However, if you wish, you can define your own SystemInit and take over the
* initialization before main() gets called.
*/
#include <stddef.h>
#include "epicardium.h"
#include "max32665.h"
#include "mxc_sys.h"
#include "gcr_regs.h"
#include "icc_regs.h"
#include "pwrseq_regs.h"
uint32_t SystemCoreClock = HIRC_FREQ >> 1;
void SystemCoreClockUpdate(void)
{
uint32_t base_freq, div, clk_src;
// Determine the clock source and frequency
clk_src = (MXC_GCR->clkcn & MXC_F_GCR_CLKCN_CLKSEL);
switch (clk_src)
{
case MXC_S_GCR_CLKCN_CLKSEL_HIRC:
base_freq = HIRC_FREQ;
break;
case MXC_S_GCR_CLKCN_CLKSEL_XTAL32M:
base_freq = XTAL32M_FREQ;
break;
case MXC_S_GCR_CLKCN_CLKSEL_LIRC8:
base_freq = LIRC8_FREQ;
break;
case MXC_S_GCR_CLKCN_CLKSEL_HIRC96:
base_freq = HIRC96_FREQ;
break;
case MXC_S_GCR_CLKCN_CLKSEL_HIRC8:
base_freq = HIRC8_FREQ;
break;
case MXC_S_GCR_CLKCN_CLKSEL_XTAL32K:
base_freq = XTAL32K_FREQ;
break;
default:
// Values 001 and 111 are reserved, and should never be encountered.
base_freq = HIRC_FREQ;
break;
}
// Clock divider is retrieved to compute system clock
div = (MXC_GCR->clkcn & MXC_F_GCR_CLKCN_PSC) >> MXC_F_GCR_CLKCN_PSC_POS;
SystemCoreClock = base_freq >> div;
}
__weak void SystemInit() {
// Enable FPU.
SCB->CPACR |= SCB_CPACR_CP10_Msk | SCB_CPACR_CP11_Msk;
__DSB();
__ISB();
// Enable ICache1 Clock
MXC_GCR->perckcn1 &= ~(1 << 22);
// Invalidate cache and wait until ready
MXC_ICC1->invalidate = 1;
while (!(MXC_ICC1->cache_ctrl & MXC_F_ICC_CACHE_CTRL_CACHE_RDY));
// Enable Cache
MXC_ICC1->cache_ctrl |= MXC_F_ICC_CACHE_CTRL_CACHE_EN;
SystemCoreClockUpdate();
}
// newlib syscall to allow printf to work.
long _write(int fd, const char *buf, size_t cnt)
{
/*
* Only print one line at a time. Insert `\r` between lines so
* they are properly displayed on the serial console.
*/
size_t i, last = 0;
for (i = 0; i < cnt; i++) {
if (buf[i] == '\n') {
epic_uart_write_str(&buf[last], i - last);
epic_uart_write_str("\r", 1);
last = i;
}
}
if (last != i) {
epic_uart_write_str(&buf[last], cnt - last);
}
return cnt;
}
// newlib syscall to allow for a heap
extern uint32_t __heap_start;
uint32_t _sbrk(int incr)
{
static char *brk = NULL;
if (brk == NULL) {
brk = (char *)&__heap_start;
}
char *prev_brk = brk;
brk += incr;
return (uint32_t)prev_brk;
}