mirror of
https://github.com/t-crest/rtems.git
synced 2025-11-16 12:34:47 +00:00
Implemented exceptions and timer management functions to remove dependencies from newlib
This commit is contained in:
@@ -22,10 +22,6 @@
|
||||
#include <rtems.h>
|
||||
#include <bsp.h>
|
||||
|
||||
#include <machine/patmos.h>
|
||||
#include <machine/exceptions.h>
|
||||
#include <machine/rtc.h>
|
||||
|
||||
void Clock_exit( void );
|
||||
rtems_isr Clock_isr( rtems_vector_number vector )__attribute__((naked));
|
||||
|
||||
@@ -52,10 +48,9 @@ uint32_t Clock_isrs; /* ISRs until next tick */
|
||||
|
||||
rtems_device_major_number rtems_clock_major = ~0;
|
||||
rtems_device_minor_number rtems_clock_minor;
|
||||
/* cycles from RTEMS start to Install_clock routine */
|
||||
uint64_t cycles_offset;
|
||||
/* CPU frequency in MHZ */
|
||||
uint32_t freq;
|
||||
|
||||
/* usecs from RTEMS start to Install_clock routine */
|
||||
uint64_t usecs_bias;
|
||||
/* timestamp of the last tick in usec */
|
||||
uint64_t usec_offset;
|
||||
|
||||
@@ -67,6 +62,36 @@ rtems_isr_entry Old_ticker;
|
||||
|
||||
void Clock_exit( void );
|
||||
|
||||
/*
|
||||
* Get the current RTC microsecond value
|
||||
*/
|
||||
uint64_t get_cpu_usecs(void) {
|
||||
unsigned ulo, uhi;
|
||||
|
||||
_iodev_ptr_t hi_usec = (_iodev_ptr_t)(__PATMOS_RTC_TIME_UP_ADDR);
|
||||
_iodev_ptr_t lo_usec = (_iodev_ptr_t)(__PATMOS_RTC_TIME_LOW_ADDR);
|
||||
|
||||
// Order is important here
|
||||
ulo = *lo_usec;
|
||||
uhi = *hi_usec;
|
||||
|
||||
return (((unsigned long long) uhi) << 32) | ulo;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the timeout for the clock timer. The RTC will trigger an interrupt once
|
||||
* the cycle counter reaches the given value.
|
||||
*/
|
||||
static inline void arm_usec_timer(uint64_t timestamp) {
|
||||
|
||||
_iodev_ptr_t hi_usec = (_iodev_ptr_t)(__PATMOS_RTC_TIME_UP_ADDR);
|
||||
_iodev_ptr_t lo_usec = (_iodev_ptr_t)(__PATMOS_RTC_TIME_LOW_ADDR);
|
||||
|
||||
// Order is important here
|
||||
*lo_usec = (unsigned)timestamp;
|
||||
*hi_usec = (unsigned)(timestamp>>32);
|
||||
}
|
||||
|
||||
void set_usec_timer (uint64_t time_warp)
|
||||
{
|
||||
|
||||
@@ -78,21 +103,9 @@ void set_usec_timer (uint64_t time_warp)
|
||||
arm_usec_timer(usec_offset);
|
||||
}
|
||||
|
||||
uint32_t get_cpu_freq_mhz(void)
|
||||
{
|
||||
return get_cpu_freq()/1000000;
|
||||
}
|
||||
|
||||
uint32_t bsp_clock_nanoseconds_since_last_tick(void)
|
||||
{
|
||||
/*uint64_t volatile cycles_since_first_tick = (uint64_t)Clock_driver_ticks*rtems_configuration_get_microseconds_per_tick()*freq;
|
||||
uint64_t volatile cycles_since_program_start = get_cpu_cycles();
|
||||
uint64_t volatile cycles_since_last_tick = cycles_since_program_start - cycles_since_first_tick - cycles_offset;
|
||||
uint64_t volatile microseconds_since_last_tick = cycles_since_last_tick*1000;
|
||||
uint64_t nsecs = microseconds_since_last_tick / ((uint64_t)freq);*/
|
||||
|
||||
uint64_t nsecs = ((get_cpu_cycles() - ((uint64_t)Clock_driver_ticks*rtems_configuration_get_microseconds_per_tick()*freq) - cycles_offset)
|
||||
* 1000) / ((uint64_t)freq);
|
||||
uint64_t nsecs = (get_cpu_usecs() - usecs_bias - Clock_driver_ticks*rtems_configuration_get_microseconds_per_tick())*1000;
|
||||
|
||||
return (uint32_t) nsecs;
|
||||
}
|
||||
@@ -324,13 +337,14 @@ void Install_clock(
|
||||
Clock_driver_ticks = 0;
|
||||
Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
|
||||
|
||||
exc_register(EXC_INTR_USEC, (uint32_t)clock_isr);
|
||||
// set the isr routine
|
||||
set_exc_handler(EXC_INTR_USEC, (uint32_t)clock_isr);
|
||||
// clear pending flags
|
||||
intr_clear_all_pending();
|
||||
// unmask interrupt
|
||||
intr_unmask(EXC_INTR_USEC);
|
||||
// enable interrupts
|
||||
intr_enable();
|
||||
patmos_enable_interrupts();
|
||||
|
||||
#if defined(Clock_driver_nanoseconds_since_last_tick)
|
||||
rtems_clock_set_nanoseconds_extension(
|
||||
@@ -338,19 +352,15 @@ void Install_clock(
|
||||
);
|
||||
#endif
|
||||
|
||||
freq = get_cpu_freq_mhz();
|
||||
|
||||
/*
|
||||
* reset the cpu_cycles count to determine clock_nanoseconds_since_last_tick
|
||||
* reset the cpu_usecs count to determine clock_nanoseconds_since_last_tick
|
||||
*/
|
||||
cycles_offset = get_cpu_cycles();
|
||||
usecs_bias = get_cpu_usecs();
|
||||
|
||||
usec_offset = get_cpu_usecs();
|
||||
|
||||
set_usec_timer(rtems_configuration_get_microseconds_per_tick());
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Schedule the clock cleanup routine to execute if the application exits.
|
||||
*/
|
||||
|
||||
@@ -118,6 +118,8 @@ extern char _uart_base; /* linker symbol giving the address of the UART */
|
||||
|
||||
extern char _timer_base; /* linker symbol giving the address of the RTC */
|
||||
|
||||
extern uint64_t get_cpu_usecs (void);
|
||||
|
||||
extern void set_usec_timer (uint64_t time_warp);
|
||||
|
||||
/* Address to access the cycle counter low register of the RTC */
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
#include <bsp.h>
|
||||
|
||||
#include <machine/rtc.h>
|
||||
|
||||
bool benchmark_timer_find_average_overhead;
|
||||
|
||||
#define AVG_OVERHEAD 0 /* It typically takes 0 microseconds */
|
||||
@@ -33,7 +31,7 @@ void benchmark_timer_initialize(void)
|
||||
/*
|
||||
* Timer runs long and accurate enough not to require an interrupt.
|
||||
*/
|
||||
timer_offset = get_cpu_cycles();
|
||||
timer_offset = get_cpu_usecs();
|
||||
}
|
||||
|
||||
int benchmark_timer_read(void)
|
||||
@@ -44,7 +42,7 @@ int benchmark_timer_read(void)
|
||||
* Read the timer and see how many clicks it has been since we started.
|
||||
*/
|
||||
|
||||
total = (get_cpu_cycles() - timer_offset)/get_cpu_freq_mhz();
|
||||
total = get_cpu_usecs() - timer_offset;
|
||||
|
||||
if ( benchmark_timer_find_average_overhead == true )
|
||||
return total; /* in one microsecond units */
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <rtems.h>
|
||||
#include <bsp.h>
|
||||
|
||||
#include "exceptions.h"
|
||||
|
||||
/*
|
||||
* Enable interrupts
|
||||
*/
|
||||
@@ -33,3 +35,27 @@ void patmos_enable_interrupts(void){
|
||||
void patmos_disable_interrupts(void){
|
||||
EXC_STATUS &= ~1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a function as exception handler.
|
||||
* n - The exception to register the function for
|
||||
* fun - The exception handler
|
||||
*/
|
||||
void set_exc_handler(unsigned n, exc_handler_t fun){
|
||||
EXC_VEC(n) = (unsigned)fun;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the pending flag of all interrupts
|
||||
*/
|
||||
void intr_clear_all_pending(void){
|
||||
EXC_PEND = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unmask a particular interrupts
|
||||
* n - The interrupt to be unmasked
|
||||
*/
|
||||
void intr_unmask(unsigned n){
|
||||
EXC_MASK |= (1 << n);
|
||||
}
|
||||
|
||||
@@ -14,10 +14,34 @@
|
||||
#ifndef __PATMOS_EXCEPTIONS_h
|
||||
#define __PATMOS_EXCEPTIONS_h
|
||||
|
||||
/*
|
||||
* The exception handler type
|
||||
*/
|
||||
typedef void (*exc_handler_t)(void);
|
||||
|
||||
/*
|
||||
* The exception vector array
|
||||
*/
|
||||
#define EXC_VEC(I) (((_IODEV exc_handler_t volatile * const)(&_excunit_base+0x80))[I])
|
||||
|
||||
/*
|
||||
* Various named exception vector entry numbers
|
||||
*/
|
||||
#define EXC_ILLEGAL_OP 0
|
||||
#define EXC_ILLEGAL_ADDRESS 1
|
||||
#define EXC_INTR_CLOCK 16
|
||||
#define EXC_INTR_USEC 17
|
||||
|
||||
void patmos_enable_interrupts(void);
|
||||
|
||||
void patmos_disable_interrupts(void);
|
||||
|
||||
void set_exc_handler(unsigned n, exc_handler_t fun);
|
||||
|
||||
void intr_clear_all_pending(void);
|
||||
|
||||
void intr_unmask(unsigned n);
|
||||
|
||||
#endif
|
||||
|
||||
/* end of include file */
|
||||
|
||||
Reference in New Issue
Block a user