Exemple #1
0
Fichier : vc.c Projet : AoLaD/rtems
static inline int bcm2835_mailbox_send_read_buffer( void *buf )
{
  RTEMS_COMPILER_MEMORY_BARRIER();
  raspberrypi_mailbox_write( BCM2835_MBOX_CHANNEL_PROP_AVC,
    (unsigned int) buf + BCM2835_VC_MEMORY_MAPPING );
  raspberrypi_mailbox_read( BCM2835_MBOX_CHANNEL_PROP_AVC );
  RTEMS_COMPILER_MEMORY_BARRIER();
  return 0;
}
Exemple #2
0
  void _SMP_Handler_initialize(void)
  {
    int         cpu;
    size_t      size;
    uintptr_t   ptr;

    /*
     *  Initialize per CPU structures.
     */
    size = (_SMP_Processor_count) * sizeof(Per_CPU_Control);
    memset( _Per_CPU_Information, '\0', size );

    /*
     *  Initialize per cpu pointer table
     */
    size = Configuration.interrupt_stack_size;
    _Per_CPU_Information_p[0] = &_Per_CPU_Information[0];
    for (cpu=1 ; cpu < rtems_configuration_smp_maximum_processors; cpu++ ) {

      Per_CPU_Control *p = &_Per_CPU_Information[cpu];

      _Per_CPU_Information_p[cpu] = p;

      p->interrupt_stack_low = _Workspace_Allocate_or_fatal_error( size );

      ptr = (uintptr_t) _Addresses_Add_offset( p->interrupt_stack_low, size );
      ptr &= ~(CPU_STACK_ALIGNMENT - 1);
      p->interrupt_stack_high = (void *)ptr;
      p->state = RTEMS_BSP_SMP_CPU_INITIAL_STATE;
      RTEMS_COMPILER_MEMORY_BARRIER();
    }
  }
void _Thread_Disable_dispatch( void )
{
  /*
   *  This check is very brutal to system performance but is very helpful
   *  at finding blown stack problems.  If you have a stack problem and
   *  need help finding it, then uncomment this code.  Every system
   *  call will check the stack and since mutexes are used frequently
   *  in most systems, you might get lucky.
   */
  #if defined(RTEMS_HEAVY_STACK_DEBUG)
    if (_System_state_Is_up(_System_state_Get()) && (_ISR_Nest_level == 0)) {
      if ( rtems_stack_checker_is_blown() ) {
	printk( "Stack blown!!\n" );
	rtems_fatal_error_occurred( 99 );
      }
    }
  #endif

  _Thread_Dispatch_increment_disable_level();
  RTEMS_COMPILER_MEMORY_BARRIER();

  /*
   * This check is even more brutal than the other one.  This enables
   * malloc heap integrity checking upon entry to every system call.
   */
  #if defined(RTEMS_HEAVY_MALLOC_DEBUG)
    if ( _Thread_Dispatch_get_disable_level() == 1 ) {
      _Heap_Walk( RTEMS_Malloc_Heap,99, false );
    }
  #endif
}
Exemple #4
0
void _SMP_lock_spinlock_nested_Release(
  SMP_lock_spinlock_nested_Control *lock,
  ISR_Level                        level
)
{
  #if defined (RTEMS_DEBUG) || defined(SMPLOCK_DEBUG)
    if ( lock->count == 0 ) {
      printk(
        "\ncpu %d lock %d Releasing spinlock when count is already "
        "zero (%p from %p,%p)?!?!\n",
        bsp_smp_processor_id(),  
        lock->cpu_id,
        lock,
        __builtin_return_address(0),
        __builtin_return_address(1)
      );
      debug_dump_log();
      return;
    }
  #endif

  /* assume we actually have it */
  if (lock->count == 1) {
    lock->cpu_id = -1;
    debug_logit( 'U', lock );
    lock->count  = 0;
    RTEMS_COMPILER_MEMORY_BARRIER();
    lock->lock = 0;
  } else {
    debug_logit( 'u', lock );
    lock->count--;
  }

  _ISR_Enable_on_this_core( level ); 
}
Exemple #5
0
ISR_Level _SMP_lock_spinlock_simple_Obtain(
  SMP_lock_spinlock_simple_Control *lock
)
{
   ISR_Level  level = 0;
   uint32_t   value = 1;
   uint32_t   previous;

   /* Note: Disable provides an implicit memory barrier. */
  _ISR_Disable_on_this_core( level );
   do {
     RTEMS_COMPILER_MEMORY_BARRIER();
     SMP_CPU_SWAP( lock, value, previous );
     RTEMS_COMPILER_MEMORY_BARRIER();
   } while (previous == 1);

  return level;
}
Exemple #6
0
ISR_Level _SMP_lock_spinlock_nested_Obtain(
  SMP_lock_spinlock_nested_Control *lock
)
{
  ISR_Level  level = 0;
  uint32_t   value = 1;
  uint32_t   previous;
  int        cpu_id;

  /* Note: Disable provides an implicit memory barrier. */
  _ISR_Disable_on_this_core( level ); 

  cpu_id = bsp_smp_processor_id();

  /*
   *  Attempt to obtain the lock.  If we do not get it immediately, then
   *  do a single "monitor" iteration.  This should allow the loop to back
   *  off the bus a bit and allow the other core to finish sooner.
   */
  while (1) {
    RTEMS_COMPILER_MEMORY_BARRIER();
    SMP_CPU_SWAP( &lock->lock, value, previous );
    RTEMS_COMPILER_MEMORY_BARRIER();
    if ( previous == 0 ) {
      /* was not locked */
      break;
    }

    /* Deal with nested calls from one cpu */
    if (cpu_id == lock->cpu_id) {
      lock->count++;
      debug_logit( 'l', lock );
      return level;
    }
  }

  lock->cpu_id = cpu_id;
  lock->count = 1;
  debug_logit( 'L', lock );

  return level;
}
Exemple #7
0
/* init_ecap
 * Initialize an eCAP module. This module will trigger on
 *  every rising edge, and will store four captures.
 *
 */
void init_ecap(
        rtems_interrupt_handler handler,
        struct eCAP_data* arg)
{

    uint32_t cm_per_clk_reg_offset;
    uint8_t  ecap_intr_num;
    char     ecap_intr_name[6];
    uint8_t  ecap_pin_mux_mode;
    uint32_t ecap_pin_reg_offset;
    struct eCAP_regs*  ecap_regs;
    struct PWMSS_regs* pwmss_regs;
    uint8_t  pwmss_tbclken_shift;
    rtems_event_set ecap_event_id;

    uint32_t util_val; /* used for clarity in register operations */

    switch (arg->ecap_module)
    {
        case (0):
            cm_per_clk_reg_offset = CM_PER_EPWMSS0_CLKCTRL_OFFSET;
            ecap_intr_num = ECAP0_INT;
            strncpy(ecap_intr_name, "eCAP0", 6);
            ecap_pin_mux_mode   = CONTROL_CONF_MUXMODE(0);
            ecap_pin_reg_offset = CONTROL_CONF_ECAP0_IN_PWM0_OUT_OFFSET;
            ecap_regs  = (struct eCAP_regs*)ECAP0_REGS_BASE;
            pwmss_regs = (struct PWMSS_regs*)PWMSS0_MMIO_BASE;
            pwmss_tbclken_shift = PWMSS0_TBCLKEN;
            ecap_event_id = ECAP_0_EVENT;
            break;
        default:
            return;
    }

    /* Set up some generic data used by the ecap task and interrupt handler */
    arg->num_intr  = 0;
    arg->ecap_regs = ecap_regs;
    arg->ecap_event_id = ecap_event_id;

    /* Disable interrupts while we start up the eCAP module */
    rtems_interrupt_level irqlvl;
    rtems_interrupt_disable(irqlvl);

    mmio_write(SOC_CONTROL_REGS + CONTROL_CONF_PWMSS_CTRL,
            (TBCLKEN_ENABLE << pwmss_tbclken_shift));

    /* Enable the eCAP module in CM_PER_EPWMSS0_CLKCTRL (8.1.12.1.36) */
    util_val = mmio_read(CM_PER_MMIO_BASE + cm_per_clk_reg_offset);
    util_val |= (MODULEMODE_ENABLE << MODULEMODE);
    mmio_write(CM_PER_MMIO_BASE + cm_per_clk_reg_offset, util_val);
    /* the following read _must_ happen or the ECCTL1 doesn't get set */
    /* no, I don't know why. */
    util_val = mmio_read(CM_PER_MMIO_BASE + cm_per_clk_reg_offset);
    RTEMS_COMPILER_MEMORY_BARRIER();

    /* Configure the eCAP module to 
     *   trigger on rising pulses with no timer prescale
     *   interrupt when the timer wraps
     *   run in capture mode
     *   wrap the timer
     *   disable input and output synchronization
     */
    ecap_regs->ECEINT = 0x0;
    RTEMS_COMPILER_MEMORY_BARRIER();
    ecap_regs->ECCTL1 = (EC_RISING << CAP1POL)     | (EC_RISING << CAP2POL)
                      | (EC_RISING << CAP3POL)     | (EC_RISING << CAP4POL)
                      | (EC_ABS_MODE << CTRRST1)   | (EC_ABS_MODE << CTRRST2)
                      | (EC_ABS_MODE << CTRRST3)   | (EC_ABS_MODE << CTRRST4)
                      | (EC_ENABLE << CAPLDEN)     | (EC_DIV1 << PRESCALE);
    RTEMS_COMPILER_MEMORY_BARRIER();
    ecap_regs->ECCTL2 = (EC_CONTINUOUS << CONT_ONESHT)
                      | (EC_EVENT4 << STOP_WRAP)
                      | (EC_DISABLE << SYNCI_EN)
                      | (EC_SYNCO_DIS << SYNCO_SEL)
                      | (EC_CAP_MODE << CAP_APWM);

    /* Per the docs, clear all the interrupt flags and timer registers, and
     * then enable the interrupts (15.3.4.1.9) */
    ecap_regs->ECCLR  = BIT(CTR_EQ_CMP) | BIT(CTR_EQ_PRD) | BIT(CTROVF) 
                      | BIT(CEVT4) | BIT(CEVT3) | BIT(CEVT2) | BIT(CEVT1)
                      | BIT(INT);
    ecap_regs->ECEINT = BIT(CTROVF) | BIT(CEVT4) | BIT(CEVT3) | BIT(CEVT2) | BIT(CEVT1);
    RTEMS_COMPILER_MEMORY_BARRIER();

    /* Enable the eCAP 0 timer (it will start when the clock is enabled */
    ecap_regs->ECCTL2 |= (EC_RUN << TSCTRSTOP);
    RTEMS_COMPILER_MEMORY_BARRIER();

    /* Set the "smart" idle mode in register SYSCONFIG (15.1.3.2) */
    util_val = (IDLEMODE_SMART << SYSCONFIG_IDLEMODE);
    pwmss_regs->SYSCONFIG = util_val;
    RTEMS_COMPILER_MEMORY_BARRIER();

    /* Enable the clock in pwmss_ctrl (9.3.1.32) */
    util_val = pwmss_regs->CLKCONFIG;
    util_val |= (CLKCONFIG_CLK_EN << eCAPCLK_EN);
    pwmss_regs->CLKCONFIG = util_val;
    RTEMS_COMPILER_MEMORY_BARRIER();

    util_val = pwmss_regs->CLKSTATUS;
    if ( !(util_val & (1<<eCAP_CLK_EN_ACK)) ) 
    { 
        perror("Failed to start eCAP counter!\n"); 
    }

    rtems_status_code have_isr = rtems_interrupt_handler_install(
            ecap_intr_num,
            ecap_intr_name,
            RTEMS_INTERRUPT_UNIQUE,
            handler,
            (void*)arg);

    if (have_isr != RTEMS_SUCCESSFUL) { printf("Failed to install eCAP0 ISR!\n"); }

    /* Re-enable interrupts, preserving cpsr */
    rtems_interrupt_enable(irqlvl);

    /* Mux the ecap pin by setting the RXACTIVE bit and mode  
     * in pin register (9.3.1.51) to enable external eCAP
     * triggering
     */
    mux_pin(ecap_pin_reg_offset, ecap_pin_mux_mode);

}
Exemple #8
0
Fichier : vc.c Projet : AoLaD/rtems
static inline bool bcm2835_mailbox_buffer_suceeded(
  const bcm2835_mbox_buf_hdr *hdr )
{
  RTEMS_COMPILER_MEMORY_BARRIER();
  return ( hdr->buf_code == BCM2835_MBOX_BUF_CODE_REQUEST_SUCCEED );
}