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; }
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 }
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 ); }
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; }
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; }
/* 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); }
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 ); }