97 lines
2.8 KiB
C
97 lines
2.8 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright (c) 2017-2019 by Löwenware Ltd
|
|
* Please, refer LICENSE file for legal information
|
|
*
|
|
******************************************************************************/
|
|
|
|
/**
|
|
* @file timer.c
|
|
* @author Ilja Kartašov <ik@lowenware.com>
|
|
* @brief
|
|
*
|
|
* @see https://lowenware.com/
|
|
*/
|
|
|
|
#include <aarch64/aarch64.h>
|
|
#include <drivers/soc/bcm2837/bcm2837.h>
|
|
#include <leos/log.h>
|
|
#include "timer.h"
|
|
|
|
const unsigned int m_interval = 200000;
|
|
unsigned int m_current = 0;
|
|
|
|
#ifndef CONFIG_ARM_TIMER
|
|
#define CONFIG_ARM_TIMER 1
|
|
#endif
|
|
|
|
#define TIMER_ENABLE ((1 << 31) | (1 << 29) | (1 << 28))
|
|
#define TIMER_RELOAD 1
|
|
|
|
/*
|
|
* https://www.raspberrypi.org/forums/viewtopic.php?t=213393
|
|
* The sequence on a real PI3 is
|
|
* 1.) Route the local timer to a core register 0x40000024 (bits 0..2)
|
|
* QA7_rev3.4.pdf page 18 ... say write 0 which is core 0
|
|
*
|
|
* 2.) Setup timer status control register 0x40000034 (all 32 bits)
|
|
* QA7_rev3.4.pdf page 17 ... reload value 5000000 = like half sec, enable clock, enable interrupt
|
|
* You can play with clock prescalers etc later.
|
|
* 3.) Hit timer interrupt clear and reload register 0x40000038 (bits 30 & 31)
|
|
* QA7_rev3.4.pdf page 18 ... write 1 to both bits which clears irq signal and loads value from above
|
|
*
|
|
* 4.) Setup timer interrupt control register 0x40000040 (all bits ... zero all but the one bit set)
|
|
* QA7_rev3.4.pdf page 13 ... now this depends what mode Core0 leaves your bootstub in.
|
|
* If you did no EL changes in stub the core0 will still be in Hyp mode if like me you dropped it to SVC mode it is Non Secure
|
|
*
|
|
* If Core0 enters in Hyp mode ... set nCNTHPIRQ_IRQ bit 1
|
|
* If Core0 enters in Svc mode ... set nCNTPNSIRQ_IRQ bit 2
|
|
*
|
|
* 5.) Now you need to enable global interupts
|
|
* asm(" cpsie i")
|
|
* */
|
|
|
|
void
|
|
Timer_init(void)
|
|
{
|
|
#if CONFIG_ARM_TIMER == 1
|
|
/* Route local timer to a core0 */
|
|
AARCH64_LOCAL_INT_ROUTING &= ~0x03;
|
|
/* Set up timer status control register */
|
|
AARCH64_LOCAL_TIMER_STATCTL = TIMER_ENABLE | TIMER_RELOAD;
|
|
/* clear interrupt flag and reload timer */
|
|
AARCH64_LOCAL_TIMER_RECLR |= (1 << 31) | (1 << 30);
|
|
/* Set timer interrupt control register */
|
|
AARCH64_CORE0_TIMER_IRQCTL = (1 << 1); /* nCNTPNSIR1 - Non Secure*/
|
|
|
|
#else
|
|
m_current = aarch64_get32r(TIMER_CLO);
|
|
m_current += m_interval;
|
|
aarch64_set32r(TIMER_C1, m_current);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
Timer_incFromISR(void)
|
|
{
|
|
m_current++; /*= m_interval;*/
|
|
#if CONFIG_ARM_TIMER == 1
|
|
/* clear interrupt flag and reload timer */
|
|
AARCH64_LOCAL_TIMER_RECLR |= (1 << 31) | (1 << 30);
|
|
#else
|
|
aarch64_set32r(TIMER_C1, m_current);
|
|
aarch64_set32r(TIMER_CS, TIMER_CS_M1);
|
|
#endif
|
|
/*
|
|
Log_putS("Timer: ");
|
|
Log_putI(m_current, 10);
|
|
Log_putS("\r\n");
|
|
*/
|
|
}
|
|
|
|
uint32_t
|
|
Timer_getTicks(void)
|
|
{
|
|
return m_current;
|
|
}
|