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 <rtems.h>
|
||||||
#include <bsp.h>
|
#include <bsp.h>
|
||||||
|
|
||||||
#include <machine/patmos.h>
|
|
||||||
#include <machine/exceptions.h>
|
|
||||||
#include <machine/rtc.h>
|
|
||||||
|
|
||||||
void Clock_exit( void );
|
void Clock_exit( void );
|
||||||
rtems_isr Clock_isr( rtems_vector_number vector )__attribute__((naked));
|
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_major_number rtems_clock_major = ~0;
|
||||||
rtems_device_minor_number rtems_clock_minor;
|
rtems_device_minor_number rtems_clock_minor;
|
||||||
/* cycles from RTEMS start to Install_clock routine */
|
|
||||||
uint64_t cycles_offset;
|
/* usecs from RTEMS start to Install_clock routine */
|
||||||
/* CPU frequency in MHZ */
|
uint64_t usecs_bias;
|
||||||
uint32_t freq;
|
|
||||||
/* timestamp of the last tick in usec */
|
/* timestamp of the last tick in usec */
|
||||||
uint64_t usec_offset;
|
uint64_t usec_offset;
|
||||||
|
|
||||||
@@ -67,6 +62,36 @@ rtems_isr_entry Old_ticker;
|
|||||||
|
|
||||||
void Clock_exit( void );
|
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)
|
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);
|
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)
|
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 nsecs = (get_cpu_usecs() - usecs_bias - Clock_driver_ticks*rtems_configuration_get_microseconds_per_tick())*1000;
|
||||||
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);
|
|
||||||
|
|
||||||
return (uint32_t) nsecs;
|
return (uint32_t) nsecs;
|
||||||
}
|
}
|
||||||
@@ -324,13 +337,14 @@ void Install_clock(
|
|||||||
Clock_driver_ticks = 0;
|
Clock_driver_ticks = 0;
|
||||||
Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
|
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
|
// clear pending flags
|
||||||
intr_clear_all_pending();
|
intr_clear_all_pending();
|
||||||
// unmask interrupt
|
// unmask interrupt
|
||||||
intr_unmask(EXC_INTR_USEC);
|
intr_unmask(EXC_INTR_USEC);
|
||||||
// enable interrupts
|
// enable interrupts
|
||||||
intr_enable();
|
patmos_enable_interrupts();
|
||||||
|
|
||||||
#if defined(Clock_driver_nanoseconds_since_last_tick)
|
#if defined(Clock_driver_nanoseconds_since_last_tick)
|
||||||
rtems_clock_set_nanoseconds_extension(
|
rtems_clock_set_nanoseconds_extension(
|
||||||
@@ -338,19 +352,15 @@ void Install_clock(
|
|||||||
);
|
);
|
||||||
#endif
|
#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();
|
usec_offset = get_cpu_usecs();
|
||||||
|
|
||||||
set_usec_timer(rtems_configuration_get_microseconds_per_tick());
|
set_usec_timer(rtems_configuration_get_microseconds_per_tick());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Schedule the clock cleanup routine to execute if the application exits.
|
* 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 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);
|
extern void set_usec_timer (uint64_t time_warp);
|
||||||
|
|
||||||
/* Address to access the cycle counter low register of the RTC */
|
/* Address to access the cycle counter low register of the RTC */
|
||||||
|
|||||||
@@ -18,8 +18,6 @@
|
|||||||
|
|
||||||
#include <bsp.h>
|
#include <bsp.h>
|
||||||
|
|
||||||
#include <machine/rtc.h>
|
|
||||||
|
|
||||||
bool benchmark_timer_find_average_overhead;
|
bool benchmark_timer_find_average_overhead;
|
||||||
|
|
||||||
#define AVG_OVERHEAD 0 /* It typically takes 0 microseconds */
|
#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 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)
|
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.
|
* 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 )
|
if ( benchmark_timer_find_average_overhead == true )
|
||||||
return total; /* in one microsecond units */
|
return total; /* in one microsecond units */
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
#include <rtems.h>
|
#include <rtems.h>
|
||||||
#include <bsp.h>
|
#include <bsp.h>
|
||||||
|
|
||||||
|
#include "exceptions.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enable interrupts
|
* Enable interrupts
|
||||||
*/
|
*/
|
||||||
@@ -33,3 +35,27 @@ void patmos_enable_interrupts(void){
|
|||||||
void patmos_disable_interrupts(void){
|
void patmos_disable_interrupts(void){
|
||||||
EXC_STATUS &= ~1;
|
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
|
#ifndef __PATMOS_EXCEPTIONS_h
|
||||||
#define __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_enable_interrupts(void);
|
||||||
|
|
||||||
void patmos_disable_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
|
#endif
|
||||||
|
|
||||||
/* end of include file */
|
/* end of include file */
|
||||||
|
|||||||
Reference in New Issue
Block a user