File indexing completed on 2025-05-11 08:24:00
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include <stdlib.h>
0029 #include <bsp/fatal.h>
0030 #include <bsp/irq.h>
0031 #include <bsp/niosv.h>
0032
0033 #include <rtems/sysinit.h>
0034 #include <rtems/counter.h>
0035 #include <rtems/timecounter.h>
0036 #include <rtems/btimer.h>
0037 #include <rtems/score/riscv-utility.h>
0038
0039 #define BENCHMARK_TIMER_INTERVAL_FREQ 1000000
0040
0041
0042 void Clock_isr(void *arg);
0043
0044 static volatile uint64_t interval_period;
0045 static volatile uint64_t last_mtimecmp;
0046 static volatile uint64_t benchmark_timer_base;
0047
0048 static struct timecounter niosv_clock_tc;
0049
0050 static uint64_t niosv_mtime_get(void)
0051 {
0052 uint32_t lowbits;
0053 uint32_t highbits;
0054
0055
0056 do {
0057 highbits = CLOCK_REGS->mtime_hi;
0058 lowbits = CLOCK_REGS->mtime_lo;
0059 } while (CLOCK_REGS->mtime_hi != highbits);
0060
0061 return (((uint64_t)highbits) << 32) | lowbits;
0062 }
0063
0064 static void niosv_mtimecmp_set(uint64_t next_time)
0065 {
0066
0067
0068
0069
0070 CLOCK_REGS->mtimecmp_hi = 0xFFFFFFFF;
0071 CLOCK_REGS->mtimecmp_lo = (uint32_t)next_time;
0072 CLOCK_REGS->mtimecmp_hi = (uint32_t)(next_time >> 32);
0073 last_mtimecmp = next_time;
0074 }
0075
0076 static void niosv_clock_exit(void)
0077 {
0078 clear_csr(mie, MIP_MTIP);
0079 }
0080
0081 static uint32_t niosv_timer_read( void )
0082 {
0083
0084 TIMER_REGS->snap = 0;
0085
0086 return (0xFFFFFFFF - TIMER_REGS->snap);
0087 }
0088
0089 static uint32_t niosv_tc_get_timecount(struct timecounter *tc)
0090 {
0091 return niosv_timer_read();
0092 }
0093
0094 static void niosv_clock_initialize(void)
0095 {
0096 uint64_t current_time;
0097
0098
0099 atexit(niosv_clock_exit);
0100
0101 interval_period = (((uint64_t)CLOCK_FREQ) / 1000000) *
0102 (uint64_t)rtems_configuration_get_microseconds_per_tick();
0103 niosv_mtimecmp_set(MTIMECMP_MAX_VALUE);
0104
0105 set_csr(mie, MIP_MTIP);
0106
0107 current_time = niosv_mtime_get();
0108 niosv_mtimecmp_set(current_time + interval_period);
0109
0110
0111 niosv_clock_tc.tc_get_timecount = niosv_tc_get_timecount;
0112 niosv_clock_tc.tc_counter_mask = 0xffffffff;
0113 niosv_clock_tc.tc_frequency = BENCHMARK_TIMER_INTERVAL_FREQ;
0114 niosv_clock_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
0115 rtems_timecounter_install(&niosv_clock_tc);
0116 }
0117
0118 static void niosv_clock_at_tick(void)
0119 {
0120 niosv_mtimecmp_set(last_mtimecmp + interval_period);
0121 }
0122
0123 static void niosv_clock_handler_install(void)
0124 {
0125 rtems_status_code sc;
0126
0127 sc = rtems_interrupt_handler_install(
0128 NIOSV_INTERRUPT_VECTOR_TIMER,
0129 "Clock",
0130 RTEMS_INTERRUPT_UNIQUE,
0131 (rtems_interrupt_handler) Clock_isr,
0132 NULL
0133 );
0134 if (sc != RTEMS_SUCCESSFUL) {
0135 bsp_fatal(RISCV_FATAL_CLOCK_IRQ_INSTALL);
0136 }
0137 }
0138
0139 static void niosv_counter_initialize( void )
0140 {
0141
0142 TIMER_REGS->control = ALTERA_AVALON_TIMER_CONTROL_STOP_MSK;
0143
0144
0145 TIMER_REGS->period = 0xFFFFFFFF;
0146
0147
0148 TIMER_REGS->prescalar = (
0149 BENCHMARK_TIMER_FREQ / BENCHMARK_TIMER_INTERVAL_FREQ
0150 ) - 1;
0151
0152
0153
0154
0155 TIMER_REGS->control = ALTERA_AVALON_TIMER_CONTROL_CONT_MSK |
0156 ALTERA_AVALON_TIMER_CONTROL_START_MSK;
0157 }
0158
0159 void benchmark_timer_initialize(void)
0160 {
0161 benchmark_timer_base = niosv_timer_read();
0162 }
0163
0164 benchmark_timer_t benchmark_timer_read(void)
0165 {
0166 uint32_t timer_snap = niosv_timer_read();
0167
0168
0169 if(benchmark_timer_base < timer_snap) {
0170 return (timer_snap - benchmark_timer_base);
0171 }
0172 return ((0xFFFFFFFF - benchmark_timer_base) + timer_snap + 1);
0173 }
0174
0175 void benchmark_timer_disable_subtracting_average_overhead(
0176 bool find_average_overhead
0177 )
0178 {
0179 ( void ) find_average_overhead;
0180 }
0181
0182 uint32_t _CPU_Counter_frequency( void )
0183 {
0184 return BENCHMARK_TIMER_INTERVAL_FREQ;
0185 }
0186
0187 CPU_Counter_ticks _CPU_Counter_read( void )
0188 {
0189 return (CPU_Counter_ticks)niosv_timer_read();
0190 }
0191
0192 RTEMS_SYSINIT_ITEM(
0193 niosv_counter_initialize,
0194 RTEMS_SYSINIT_CPU_COUNTER,
0195 RTEMS_SYSINIT_ORDER_FIRST
0196 );
0197
0198 #define Clock_driver_support_at_tick(arg) niosv_clock_at_tick()
0199
0200 #define Clock_driver_support_initialize_hardware() niosv_clock_initialize()
0201
0202 #define Clock_driver_support_install_isr(isr) niosv_clock_handler_install()
0203
0204 #include "../../../shared/dev/clock/clockimpl.h"
0205