Changeset a4bc90af in rtems


Ignore:
Timestamp:
Feb 24, 2014, 11:45:00 AM (6 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
3378be95
Parents:
95d0c98
git-author:
Sebastian Huber <sebastian.huber@…> (02/24/14 11:45:00)
git-committer:
Sebastian Huber <sebastian.huber@…> (02/24/14 15:12:02)
Message:

sparc: Fix CPU counter support

The SPARC processors supported by RTEMS have no built-in CPU counter
support. We have to use some hardware counter module for this purpose.
The BSP must provide a 32-bit register which contains the current CPU
counter value and a function for the difference calculation. It can use
for example the GPTIMER instance used for the clock driver.

Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/sparc/erc32/Makefile.am

    r95d0c98 ra4bc90af  
    3636    startup/erc32mec.c startup/boardinit.S startup/bspidle.c \
    3737    startup/bspdelay.c ../../sparc/shared/startup/early_malloc.c
    38 libbsp_a_SOURCES += ../../shared/cpucounterread.c
    3938# ISR Handler
    4039libbsp_a_SOURCES += ../../sparc/shared/irq_asm.S
  • c/src/lib/libbsp/sparc/erc32/clock/ckinit.c

    r95d0c98 ra4bc90af  
    2525#include <bsp.h>
    2626#include <bspopts.h>
     27#include <rtems/counter.h>
    2728
    2829#if SIMSPARC_FAST_IDLE==1
     
    6465  bsp_clock_nanoseconds_since_last_tick
    6566
     67static CPU_Counter_ticks erc32_counter_difference(
     68  CPU_Counter_ticks second,
     69  CPU_Counter_ticks first
     70)
     71{
     72  CPU_Counter_ticks period = rtems_configuration_get_microseconds_per_tick();
     73
     74  return (first + period - second) % period;
     75}
     76
    6677#define Clock_driver_support_initialize_hardware() \
    6778  do { \
     
    8192            ERC32_MEC_TIMER_COUNTER_RELOAD_AT_ZERO \
    8293    ); \
     94    _SPARC_Counter_initialize( \
     95      &ERC32_MEC.Real_Time_Clock_Counter, \
     96      erc32_counter_difference \
     97    ); \
     98    rtems_counter_initialize_converter(1000000); \
    8399  } while (0)
    84100
  • c/src/lib/libbsp/sparc/leon2/Makefile.am

    r95d0c98 ra4bc90af  
    5353    ../../shared/bspinit.c startup/bspdelay.c \
    5454    ../../sparc/shared/startup/early_malloc.c
    55 libbsp_a_SOURCES += ../../shared/cpucounterread.c
    5655# ISR Handler
    5756libbsp_a_SOURCES += ../../sparc/shared/irq_asm.S
  • c/src/lib/libbsp/sparc/leon3/clock/ckinit.c

    r95d0c98 ra4bc90af  
    3030 *  The Real Time Clock Counter Timer uses this trap type.
    3131 */
    32 
    33 #if defined(RTEMS_MULTIPROCESSING)
    34   #define LEON3_CLOCK_INDEX \
    35     (rtems_configuration_get_user_multiprocessing_table() ? LEON3_Cpu_Index : 0)
    36 #else
    37   #define LEON3_CLOCK_INDEX 0
    38 #endif
    3932
    4033volatile struct gptimer_regs *LEON3_Timer_Regs = 0;
  • c/src/lib/libbsp/sparc/leon3/include/leon.h

    r95d0c98 ra4bc90af  
    274274#define LEON_REG_TIMER_COUNTER_CURRENT_MODE_MASK  0x00000003
    275275
     276#if defined(RTEMS_MULTIPROCESSING)
     277  #define LEON3_CLOCK_INDEX \
     278    (rtems_configuration_get_user_multiprocessing_table() ? LEON3_Cpu_Index : 0)
     279#else
     280  #define LEON3_CLOCK_INDEX 0
     281#endif
     282
    276283/* Load 32-bit word by forcing a cache-miss */
    277284static inline unsigned int leon_r32_no_cache(uintptr_t addr)
  • c/src/lib/libbsp/sparc/leon3/startup/cpucounter.c

    r95d0c98 ra4bc90af  
    1313 */
    1414
    15 #include <bsp.h>
    16 #include <bsp/fatal.h>
    1715#include <leon.h>
    1816
    1917#include <rtems/counter.h>
    2018
    21 static volatile struct gptimer_regs *leon3_cpu_counter_gpt;
     19static volatile struct gptimer_regs *adev_to_gpt(struct ambapp_dev *adev)
     20{
     21  return (volatile struct gptimer_regs *) DEV_TO_APB(adev)->start;
     22}
     23
     24static CPU_Counter_ticks free_counter_difference(
     25  CPU_Counter_ticks second,
     26  CPU_Counter_ticks first
     27)
     28{
     29  return first - second;
     30}
     31
     32static CPU_Counter_ticks clock_counter_difference(
     33  CPU_Counter_ticks second,
     34  CPU_Counter_ticks first
     35)
     36{
     37  CPU_Counter_ticks period = rtems_configuration_get_microseconds_per_tick();
     38
     39  return (first + period - second) % period;
     40}
     41
     42static void gpt_counter_initialize(
     43  volatile struct gptimer_regs *gpt,
     44  size_t timer_index,
     45  uint32_t frequency,
     46  SPARC_Counter_difference counter_difference
     47)
     48{
     49  _SPARC_Counter_initialize(
     50    (volatile const uint32_t *) &gpt->timer[timer_index].value,
     51    counter_difference
     52  );
     53
     54  rtems_counter_initialize_converter(frequency);
     55}
    2256
    2357void leon3_cpu_counter_initialize(void)
    2458{
    2559  struct ambapp_dev *adev;
    26   int idx = 1;
    27   volatile struct gptimer_regs *gpt;
    28   unsigned new_prescaler = 8;
    29   unsigned prescaler;
    30   uint32_t frequency;
    3160
    3261  adev = (void *) ambapp_for_each(
     
    3665    GAISLER_GPTIMER,
    3766    ambapp_find_by_idx,
    38     &idx
     67    NULL
    3968  );
    40   if (adev == NULL) {
    41     bsp_fatal(LEON3_FATAL_CPU_COUNTER_INIT);
     69  if (adev != NULL) {
     70    volatile struct gptimer_regs *gpt = adev_to_gpt(adev);
     71    unsigned prescaler = gpt->scaler_reload + 1;
     72
     73    /* Assume that GRMON initialized the first GPTIMER to 1MHz */
     74    uint32_t frequency = 1000000;
     75
     76    uint32_t max_frequency = frequency * prescaler;
     77    int idx = 1;
     78
     79    adev = (void *) ambapp_for_each(
     80      &ambapp_plb,
     81      OPTIONS_ALL | OPTIONS_APB_SLVS,
     82      VENDOR_GAISLER,
     83      GAISLER_GPTIMER,
     84      ambapp_find_by_idx,
     85      &idx
     86    );
     87    if (adev != NULL) {
     88      /* Use the second GPTIMER if available */
     89      unsigned min_prescaler = 8;
     90
     91      gpt = adev_to_gpt(adev);
     92
     93      gpt->scaler_reload = min_prescaler - 1;
     94      gpt->timer[0].reload = 0xffffffff;
     95      gpt->timer[0].ctrl = LEON3_GPTIMER_EN | LEON3_GPTIMER_RL
     96        | LEON3_GPTIMER_LD;
     97
     98      frequency = max_frequency / min_prescaler;
     99      gpt_counter_initialize(gpt, 0, frequency, free_counter_difference);
     100    } else {
     101      /* Fall back to the first GPTIMER */
     102      gpt_counter_initialize(
     103        gpt,
     104        LEON3_CLOCK_INDEX,
     105        frequency,
     106        clock_counter_difference
     107      );
     108    }
    42109  }
    43 
    44   gpt = (volatile struct gptimer_regs *) DEV_TO_APB(adev)->start;
    45 
    46   prescaler = gpt->scaler_reload + 1;
    47   gpt->scaler_reload = new_prescaler - 1;
    48   gpt->timer[0].reload = 0xffffffff;
    49   gpt->timer[0].ctrl = LEON3_GPTIMER_EN | LEON3_GPTIMER_RL
    50     | LEON3_GPTIMER_LD;
    51 
    52   leon3_cpu_counter_gpt = gpt;
    53 
    54   /* Assume that GRMON initialized the timer to 1MHz */
    55   frequency = UINT32_C(1000000) * (prescaler / new_prescaler);
    56   rtems_counter_initialize_converter(frequency);
    57110}
    58 
    59 CPU_Counter_ticks _CPU_Counter_read(void)
    60 {
    61   volatile struct gptimer_regs *gpt = leon3_cpu_counter_gpt;
    62 
    63   return 0U - gpt->timer[0].value;
    64 }
  • cpukit/score/cpu/sparc/Makefile.am

    r95d0c98 ra4bc90af  
    1212noinst_LIBRARIES = libscorecpu.a
    1313libscorecpu_a_SOURCES = cpu.c cpu_asm.S
     14libscorecpu_a_SOURCES += sparc-counter.c
    1415libscorecpu_a_SOURCES += sparcv8-atomic.c
    1516libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS)
  • cpukit/score/cpu/sparc/rtems/score/cpu.h

    r95d0c98 ra4bc90af  
    12741274typedef uint32_t CPU_Counter_ticks;
    12751275
    1276 CPU_Counter_ticks _CPU_Counter_read( void );
     1276typedef CPU_Counter_ticks (*SPARC_Counter_difference)(
     1277  CPU_Counter_ticks second,
     1278  CPU_Counter_ticks first
     1279);
     1280
     1281/*
     1282 * The SPARC processors supported by RTEMS have no built-in CPU counter
     1283 * support.  We have to use some hardware counter module for this purpose.  The
     1284 * BSP must provide a 32-bit register which contains the current CPU counter
     1285 * value and a function for the difference calculation.  It can use for example
     1286 * the GPTIMER instance used for the clock driver.
     1287 */
     1288typedef struct {
     1289  volatile const CPU_Counter_ticks *counter_register;
     1290  SPARC_Counter_difference counter_difference;
     1291} SPARC_Counter;
     1292
     1293extern SPARC_Counter _SPARC_Counter;
     1294
     1295/*
     1296 * Returns always a value of one regardless of the parameters.  This prevents
     1297 * an infinite loop in rtems_counter_delay_ticks().  Its only a reasonably safe
     1298 * default.
     1299 */
     1300CPU_Counter_ticks _SPARC_Counter_difference_default(
     1301  CPU_Counter_ticks second,
     1302  CPU_Counter_ticks first
     1303);
     1304
     1305static inline bool _SPARC_Counter_is_default( void )
     1306{
     1307  return _SPARC_Counter.counter_difference
     1308    == _SPARC_Counter_difference_default;
     1309}
     1310
     1311static inline void _SPARC_Counter_initialize(
     1312  volatile const CPU_Counter_ticks *counter_register,
     1313  SPARC_Counter_difference counter_difference
     1314)
     1315{
     1316  _SPARC_Counter.counter_register = counter_register;
     1317  _SPARC_Counter.counter_difference = counter_difference;
     1318}
     1319
     1320static inline CPU_Counter_ticks _CPU_Counter_read( void )
     1321{
     1322  return *_SPARC_Counter.counter_register;
     1323}
    12771324
    12781325static inline CPU_Counter_ticks _CPU_Counter_difference(
     
    12811328)
    12821329{
    1283   return second - first;
     1330  return (*_SPARC_Counter.counter_difference)( second, first );
    12841331}
    12851332
Note: See TracChangeset for help on using the changeset viewer.