diff --git a/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c b/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c index e01d2e5..2dc914a 100644 --- a/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c +++ b/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c @@ -3,13 +3,15 @@ * * @ingroup bsp_clock * - * @brief or1k clock support. + * @brief generic_or1k clock support. */ /* * generic_or1k Clock driver * * COPYRIGHT (c) 2014-2015 Hesham ALMatary <heshamelmat...@gmail.com> + * Copyright (c) 2014-2016 ÅAC Microtec AB <www.aacmicrotec.com> + * Jakob Viketoft <jakob.viket...@aacmicrotec.com> * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at @@ -25,35 +27,30 @@ #include <rtems/timecounter.h> /* The number of clock cycles before generating a tick timer interrupt. */ -#define TTMR_NUM_OF_CLOCK_TICKS_INTERRUPT 0x09ED9 -#define OR1K_CLOCK_CYCLE_TIME_NANOSECONDS 10 +#define OR1K_CLOCK_CYCLE_TIME_NANOSECONDS (1000000000 / OR1K_BSP_CLOCK_FREQ) -static struct timecounter or1ksim_tc; - -/* CPU counter */ +static struct timecounter generic_or1k_tc; static CPU_Counter_ticks cpu_counter_ticks; +static uint32_t timer_counts_per_clock_tick; -/* This prototype is added here to Avoid warnings */ +/* These prototypes are added here to avoid warnings */ void Clock_isr(void *arg); +static uint32_t generic_or1k_get_timecount(struct timecounter *tc); static void generic_or1k_clock_at_tick(void) { - uint32_t TTMR; + uint32_t ttmr; - /* For TTMR register, - * The least significant 28 bits are the number of clock cycles - * before generating a tick timer interrupt. While the most - * significant 4 bits are used for mode configuration, tick timer - * interrupt enable and pending interrupts status. - */ - TTMR = (CPU_OR1K_SPR_TTMR_MODE_RESTART | CPU_OR1K_SPR_TTMR_IE | - (TTMR_NUM_OF_CLOCK_TICKS_INTERRUPT & CPU_OR1K_SPR_TTMR_TP_MASK) - ) & ~(CPU_OR1K_SPR_TTMR_IP); + /* Get TTMR value */ + ttmr = _OR1K_mfspr(CPU_OR1K_SPR_TTMR); - _OR1K_mtspr(CPU_OR1K_SPR_TTMR, TTMR); - _OR1K_mtspr(CPU_OR1K_SPR_TTCR, 0); + /* Clear interrupt */ + ttmr &= ~(CPU_OR1K_SPR_TTMR_IP); - cpu_counter_ticks += TTMR_NUM_OF_CLOCK_TICKS_INTERRUPT; + /* Write it back */ + _OR1K_mtspr(CPU_OR1K_SPR_TTMR, ttmr); + + cpu_counter_ticks += timer_counts_per_clock_tick; } static void generic_or1k_clock_handler_install( @@ -61,35 +58,19 @@ static void generic_or1k_clock_handler_install( proc_ptr old_isr ) { - rtems_status_code sc = RTEMS_SUCCESSFUL; old_isr = NULL; _CPU_ISR_install_vector(OR1K_EXCEPTION_TICK_TIMER, new_isr, old_isr); - - if (sc != RTEMS_SUCCESSFUL) { - rtems_fatal_error_occurred(0xdeadbeef); - } -} - -static uint32_t or1ksim_get_timecount(struct timecounter *tc) -{ - uint32_t ticks_since_last_timer_interrupt; - - ticks_since_last_timer_interrupt = _OR1K_mfspr(CPU_OR1K_SPR_TTCR); - - return cpu_counter_ticks + ticks_since_last_timer_interrupt; -} - -CPU_Counter_ticks _CPU_Counter_read(void) -{ - return or1ksim_get_timecount(NULL); } static void generic_or1k_clock_initialize(void) { - uint64_t frequency = (1000000000 / OR1K_CLOCK_CYCLE_TIME_NANOSECONDS); - uint32_t TTMR; + uint32_t ttmr; + + /* Calculate timer value for given time per clock tick */ + timer_counts_per_clock_tick = (1000 * rtems_configuration_get_microseconds_per_tick()) / + OR1K_CLOCK_CYCLE_TIME_NANOSECONDS; /* For TTMR register, * The least significant 28 bits are the number of clock cycles @@ -101,36 +82,52 @@ static void generic_or1k_clock_initialize(void) /* FIXME: Long interval should pass since initializing the tick timer * registers fires exceptions dispite interrupts has not been enabled yet. */ - TTMR = (CPU_OR1K_SPR_TTMR_MODE_RESTART | CPU_OR1K_SPR_TTMR_IE | - (0xFFED9 & CPU_OR1K_SPR_TTMR_TP_MASK) - ) & ~(CPU_OR1K_SPR_TTMR_IP); + ttmr = (CPU_OR1K_SPR_TTMR_MODE_RESTART | CPU_OR1K_SPR_TTMR_IE | + (timer_counts_per_clock_tick & CPU_OR1K_SPR_TTMR_TP_MASK)) & + ~(CPU_OR1K_SPR_TTMR_IP); - _OR1K_mtspr(CPU_OR1K_SPR_TTMR, TTMR); + _OR1K_mtspr(CPU_OR1K_SPR_TTMR, ttmr); _OR1K_mtspr(CPU_OR1K_SPR_TTCR, 0); + /* Initialize CPU Counter */ + cpu_counter_ticks = 0; + /* Initialize timecounter */ - or1ksim_tc.tc_get_timecount = or1ksim_get_timecount; - or1ksim_tc.tc_counter_mask = 0xffffffff; - or1ksim_tc.tc_frequency = frequency; - or1ksim_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; - rtems_timecounter_install(&or1ksim_tc); + generic_or1k_tc.tc_get_timecount = generic_or1k_get_timecount; + generic_or1k_tc.tc_counter_mask = 0xffffffff; + generic_or1k_tc.tc_frequency = OR1K_BSP_CLOCK_FREQ; + generic_or1k_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(&generic_or1k_tc); } static void generic_or1k_clock_cleanup(void) { - uint32_t sr; + uint32_t sr; sr = _OR1K_mfspr(CPU_OR1K_SPR_SR); /* Disable tick timer exceptions */ - _OR1K_mtspr(CPU_OR1K_SPR_SR, (sr & ~CPU_OR1K_SPR_SR_IEE) - & ~CPU_OR1K_SPR_SR_TEE); + _OR1K_mtspr(CPU_OR1K_SPR_SR, sr & ~CPU_OR1K_SPR_SR_TEE); /* Invalidate tick timer config registers */ _OR1K_mtspr(CPU_OR1K_SPR_TTCR, 0); _OR1K_mtspr(CPU_OR1K_SPR_TTMR, 0); } +static uint32_t generic_or1k_get_timecount(struct timecounter *tc) +{ + uint32_t counts_since_last_timer_interrupt; + + counts_since_last_timer_interrupt = _OR1K_mfspr(CPU_OR1K_SPR_TTCR); + + return cpu_counter_ticks + counts_since_last_timer_interrupt; +} + +CPU_Counter_ticks _CPU_Counter_read(void) +{ + return generic_or1k_get_timecount(NULL); +} + CPU_Counter_ticks _CPU_Counter_difference( CPU_Counter_ticks second, CPU_Counter_ticks first @@ -146,7 +143,7 @@ CPU_Counter_ticks _CPU_Counter_difference( #define Clock_driver_support_install_isr(isr, old_isr) \ do { \ old_isr = NULL; \ - generic_or1k_clock_handler_install(isr, old_isr); \ + generic_or1k_clock_handler_install(isr, old_isr); \ } while (0) #define Clock_driver_support_shutdown_hardware() generic_or1k_clock_cleanup()
Jakob Viketoft Senior Engineer in RTL and embedded software ÅAC Microtec AB Dag Hammarskjölds väg 48 SE-751 83 Uppsala, Sweden T: +46 702 80 95 97 http://www.aacmicrotec.com _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel