示例#1
0
static void
delay_us(cyg_int32 usecs)
{
    CYGARC_HAL_SAVE_GP();
#ifdef CYGPKG_KERNEL
    {
        cyg_int32 start, elapsed;
        cyg_int32 usec_ticks, slice;

        // How many ticks total we should wait for.
        usec_ticks = usecs*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
        usec_ticks /= CYGNUM_HAL_RTC_NUMERATOR/CYGNUM_HAL_RTC_DENOMINATOR/1000;

        do {
            // Spin in slices of 1/2 the RTC period. Allows interrupts
            // time to run without messing up the algorithm. If we spun
            // for 1 period (or more) of the RTC, there'd be also problems
            // figuring out when the timer wrapped.  We may lose a tick or
            // two for each cycle but it shouldn't matter much.
            slice = usec_ticks % (CYGNUM_KERNEL_COUNTERS_RTC_PERIOD / 2);
    
            HAL_CLOCK_READ(&start);
            do {
                HAL_CLOCK_READ(&elapsed);
                elapsed = (elapsed - start); // counts up!
                if (elapsed < 0)
                    elapsed += CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
            } while (elapsed < slice);
            
            // Adjust by elapsed, not slice, since an interrupt may have
            // been stalling us for some time.
            usec_ticks -= elapsed;
        } while (usec_ticks > 0);
    }
#else // CYGPKG_KERNEL
#ifdef HAL_DELAY_US
    // Use a HAL feature if defined
    HAL_DELAY_US(usecs);
#else
    // If no accurate delay mechanism, just spin for a while. Having
    // an inaccurate delay is much better than no delay at all. The
    // count of 10 should mean the loop takes something resembling
    // 1us on most CPUs running between 30-100MHz [depends on how many
    // instructions this compiles to, how many dispatch units can be
    // used for the simple loop, actual CPU frequency, etc]
    while (usecs-- > 0) {
        int i;
        for (i = 0; i < 10; i++);
    }
#endif // HAL_DELAY_US
#endif // CYGPKG_KERNEL
    CYGARC_HAL_RESTORE_GP();
}
示例#2
0
__externC void hal_delay_us( cyg_int32 us )
{
    cyg_uint32 t0, t1;

    HAL_CLOCK_READ( &t0 );
    while ( us > 0 )
    {
        HAL_CLOCK_READ( &t1 );
        if( t1 < t0 )
            us -= (t1 + CYGNUM_HAL_RTC_PERIOD - t0);
        else
        	us -= t1 - t0;
        t0 = t1;
    }
}
示例#3
0
static long long
ns_time(void)
{
    cyg_uint32 off;
    long long ns, clocks;

    ns_per_system_clock = 1000000/rtc_resolution[1];
    HAL_CLOCK_READ(&off);
    ns = (ns_per_system_clock * (long long)off) / CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
    ns += 5;  // for rounding to .01us
    clocks = (cyg_current_time() * 10000000) + ns;
    return clocks;
}
示例#4
0
static void
delay_us(cyg_int32 usecs)
{
    CYGARC_HAL_SAVE_GP();
#if defined(CYGPKG_KERNEL) && defined(HAL_CLOCK_READ)
    {
        cyg_uint32 start, elapsed_hal;
        cyg_int32 elapsed, elapsed_usec;
        cyg_int32 slice;
        cyg_int32 usec_per_period = CYGNUM_HAL_RTC_NUMERATOR/CYGNUM_HAL_RTC_DENOMINATOR/1000;
        cyg_int32 ticks_per_usec = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/usec_per_period;
        
        do {
            // Spin in slices of 1/2 the RTC period. Allows interrupts
            // time to run without messing up the algorithm. If we
            // spun for 1 period (or more) of the RTC, there would also
            // be problems figuring out when the timer wrapped.  We
            // may lose a tick or two for each cycle but it shouldn't
            // matter much.

            // The tests against CYGNUM_KERNEL_COUNTERS_RTC_PERIOD
            // check for a value that would cause a 32 bit signed
            // multiply to overflow. But this also implies that just
            // multiplying by ticks_per_usec will yield a good
            // approximation.  Otherwise we need to do the full
            // multiply+divide to get sufficient accuracy. Note that
            // this test is actually constant, so the compiler will
            // eliminate it and only compile the branch that is
            // selected.
            
            if( usecs > usec_per_period/2 )
                slice = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2;
            else if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2 >= 0x7FFFFFFF/usec_per_period )
                slice = usecs * ticks_per_usec;
            else
            {
                slice = usecs*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
                slice /= usec_per_period;
            }
    
            HAL_CLOCK_READ(&start);
            do {
                HAL_CLOCK_READ(&elapsed_hal);
                elapsed = (elapsed_hal - start); // counts up!
                if (elapsed < 0)
                    elapsed += CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
            } while (elapsed < slice);
            
            // Adjust by elapsed, not slice, since an interrupt may
            // have been stalling us for some time.

            if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD >= 0x7FFFFFFF/usec_per_period )
                elapsed_usec = elapsed / ticks_per_usec;
            else
            {
                elapsed_usec = elapsed * usec_per_period;
                elapsed_usec = elapsed_usec / CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
            }

            // It is possible for elapsed_usec to end up zero in some
            // circumstances and we could end up looping indefinitely.
            // Avoid that by ensuring that we always decrement usec by
            // at least 1 each time.
            
            usecs -= elapsed_usec ? elapsed_usec : 1;
            
        } while (usecs > 0);
    }
#else // CYGPKG_KERNEL
#ifdef HAL_DELAY_US
    // Use a HAL feature if defined
    HAL_DELAY_US(usecs);
#else
    // If no accurate delay mechanism, just spin for a while. Having
    // an inaccurate delay is much better than no delay at all. The
    // count of 10 should mean the loop takes something resembling
    // 1us on most CPUs running between 30-100MHz [depends on how many
    // instructions this compiles to, how many dispatch units can be
    // used for the simple loop, actual CPU frequency, etc]
    while (usecs-- > 0) {
        int i;
        for (i = 0; i < 10; i++);
    }
#endif // HAL_DELAY_US
#endif // CYGPKG_KERNEL
    CYGARC_HAL_RESTORE_GP();
}
示例#5
0
文件: serial.c 项目: LucidOne/Rovio
static void
serial_rcv_char(serial_channel *chan, unsigned char c)
{
    cbuf_t *cbuf = &chan->in_cbuf;

#ifdef CYGPKG_NET_BLUEZ_STACK
	if(chan->receive)//clyu
	{
		extern unsigned char bluetooth_buf[];
		int len = 0;
		struct tty_ldisc *ldisc = chan->tty_ldisc;
		if(ldisc && ldisc->receive_buf && cbuf->nb)
		{
			diag_printf("bluetooth\n");
			if(cbuf->put < cbuf->get)
			{
				memcpy(bluetooth_buf, cbuf->data + cbuf->get, cbuf->len - cbuf->get);
				len = cbuf->len - cbuf->get;
				//ldisc->receive_buf(serial_driver, cbuf->data + cbuf->get, (char*)cbuf, cbuf->len - cbuf->get);
				cbuf->nb -= len;
				cbuf->get = 0;
			}
			memcpy(bluetooth_buf + len, cbuf->data + cbuf->get, cbuf->put);
			len += cbuf->put;
			cbuf->get = cbuf->put;
			cbuf->nb -= len;
			//ldisc->receive_buf(serial_driver, cbuf->data + cbuf->get, (char*)cbuf, cbuf->nb); 
			ldisc->receive_buf(serial_driver, bluetooth_buf, (char*)cbuf, len); 
			
		}
		chan->receive = 0;
		return;
	}
#endif

#if CYGINT_IO_SERIAL_BLOCK_TRANSFER
    CYG_ASSERT(false == cbuf->block_mode_xfer_running,
               "Attempting char rcv while block transfer is running");
#endif
#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_SOFTWARE
    // for software flow control, if the driver returns one of the characters
    // we act on it and then drop it (the app must not see it)
    if ( chan->config.flags & CYGNUM_SERIAL_FLOW_XONXOFF_TX ) {
        if ( c == CYGDAT_IO_SERIAL_FLOW_CONTROL_XOFF_CHAR ) {
            throttle_tx( chan );
            return; // it wasn't a "real" character
        } else if ( c == CYGDAT_IO_SERIAL_FLOW_CONTROL_XON_CHAR ) {
            restart_tx( chan );
            return; // it wasn't a "real" character
        }
    }
#endif    
#ifdef CYGPKG_IO_SERIAL_FLOW_CONTROL
    // If we've hit the high water mark, tell the other side to stop
    if ( cbuf->nb >= cbuf->high_water ) {
        throttle_rx( chan, false );
    }
#endif
#ifdef CYGPKG_IO_SERIAL_SELECT_SUPPORT
    // Wake up any pending selectors if we are about to
    // put some data into a previously empty buffer.
    if( cbuf->nb == 0 )
        cyg_selwakeup( &cbuf->selinfo );
#endif

    // If the flow control is not enabled/sufficient and the buffer is
    // already full, just throw new characters away.

    if ( cbuf->nb < cbuf->len ) {
        cbuf->data[cbuf->put++] = c;
        if (cbuf->put == cbuf->len) cbuf->put = 0;
        cbuf->nb++;
    } // note trailing else
#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS
    else {
        // Overrun. Report the error.
        cyg_serial_line_status_t stat;
        stat.which = CYGNUM_SERIAL_STATUS_OVERRUNERR;
        serial_indicate_status(chan, &stat);
    }
#endif

    if (cbuf->waiting) {
#ifdef XX_CYGDBG_DIAG_BUF
            extern int enable_diag_uart;
            int _enable = enable_diag_uart;
            int _time, _stime;
            externC cyg_tick_count_t cyg_current_time(void);
            enable_diag_uart = 0;
            HAL_CLOCK_READ(&_time);
            _stime = (int)cyg_current_time();
            diag_printf("Signal reader - time: %x.%x\n", _stime, _time);
            enable_diag_uart = _enable;
#endif // CYGDBG_DIAG_BUF
        cbuf->waiting = false;
        cyg_drv_cond_signal(&cbuf->wait);
    }
    
}
示例#6
0
文件: serial.c 项目: LucidOne/Rovio
static Cyg_ErrNo 
serial_read(cyg_io_handle_t handle, void *_buf, cyg_uint32 *len)
{
    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
    serial_channel *chan = (serial_channel *)t->priv;
    serial_funs *funs = chan->funs;
    cyg_uint8 *buf = (cyg_uint8 *)_buf;
    cyg_int32 size = 0;
    cbuf_t *cbuf = &chan->in_cbuf;
    Cyg_ErrNo res = ENOERR;
#ifdef XX_CYGDBG_DIAG_BUF
            extern int enable_diag_uart;
            int _enable = enable_diag_uart;
            int _time, _stime;
            externC cyg_tick_count_t cyg_current_time(void);
#endif // CYGDBG_DIAG_BUF

    cyg_drv_mutex_lock(&cbuf->lock);
    cbuf->abort = false;

    if (cbuf->len == 0) {
        // Non interrupt driven (i.e. polled) operation
        while (size++ < *len) {
            cyg_uint8 c = (funs->getc)(chan);
#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_SOFTWARE
            // for software flow control, if the driver returns one of the
            // characters we act on it and then drop it (the app must not
            // see it)
            if ( chan->config.flags & CYGNUM_SERIAL_FLOW_XONXOFF_TX ) {
                if ( c == CYGDAT_IO_SERIAL_FLOW_CONTROL_XOFF_CHAR ) {
                    throttle_tx( chan );
                } else if ( c == CYGDAT_IO_SERIAL_FLOW_CONTROL_XON_CHAR ) {
                    restart_tx( chan );
                }
                else
                    *buf++ = c;
            }
            else
                *buf++ = c;
#else
            *buf++ = c;
#endif    
        }
    } else {
        cyg_drv_dsr_lock();  // Avoid races
        while (size < *len) {
            if (cbuf->nb > 0) {
#ifdef CYGPKG_IO_SERIAL_FLOW_CONTROL
                if ( (cbuf->nb <= cbuf->low_water) && 
                     (chan->flow_desc.flags & CYG_SERIAL_FLOW_IN_THROTTLED) )
                    restart_rx( chan, false );
#endif
                *buf++ = cbuf->data[cbuf->get];
                if (++cbuf->get == cbuf->len) cbuf->get = 0;
                cbuf->nb--;

                size++;
            } else {
#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING
                if (!cbuf->blocking) {
                    *len = size;        // characters actually read
                    res = -EAGAIN;
                    break;
                }
#endif // CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING
                cbuf->waiting = true;
#ifdef XX_CYGDBG_DIAG_BUF
                enable_diag_uart = 0;
                HAL_CLOCK_READ(&_time);
                _stime = (int)cyg_current_time();
                diag_printf("READ wait - get: %d, put: %d, time: %x.%x\n", cbuf->get, cbuf->put, _stime, _time);
                enable_diag_uart = _enable;
#endif // CYGDBG_DIAG_BUF
            
                if( !cyg_drv_cond_wait(&cbuf->wait) )
                	cbuf->abort = true;
            
#ifdef XX_CYGDBG_DIAG_BUF
                enable_diag_uart = 0;
                HAL_CLOCK_READ(&_time);
                _stime = (int)cyg_current_time();
                diag_printf("READ continue - get: %d, put: %d, time: %x.%x\n", cbuf->get, cbuf->put, _stime, _time);
                enable_diag_uart = _enable;
#endif // CYGDBG_DIAG_BUF
                if (cbuf->abort) {
                    // Give up!
                    *len = size;        // characters actually read
                    cbuf->abort = false;
                    cbuf->waiting = false;
                    res = -EINTR;
                    break;
                }
            }
        }
        cyg_drv_dsr_unlock();
    }
#ifdef XX_CYGDBG_DIAG_BUF
    cyg_drv_isr_lock();
    enable_diag_uart = 0;
    HAL_CLOCK_READ(&_time);
    _stime = (int)cyg_current_time();
    diag_printf("READ done - size: %d, len: %d, time: %x.%x\n", size, *len, _stime, _time);
    enable_diag_uart = _enable;
    cyg_drv_isr_unlock();
#endif // CYGDBG_DIAG_BUF
    cyg_drv_mutex_unlock(&cbuf->lock);
    return res;

}
示例#7
0
static int start( void )
{
    // We'll mess about with these interrupt sources:
    // 13   : EX_IRQ13 from expansion board, active HIGH
    // 12   : EX_IRQ12 from expansion board, active LOW
    //  4   : EX_IRQ4 from expansion board, active LOW
    //  3   : EX_IRQ3 from expansion board, active HIGH

    int i, hipri;
    for ( i = 1; i < 16; i++ ) {
        HAL_INTERRUPT_QUERY_INFO( i, levels[i], ups[i],
                                  hipri, masks[i], reqs[i]);
    }
    CYG_TEST_CHECK( 0 !=  masks[13], "Int 13 unmasked initially" );
    CYG_TEST_CHECK( 0 !=  masks[12], "Int 12 unmasked initially" );
    CYG_TEST_CHECK( 0 !=  masks[ 4], "Int  4 unmasked initially" );
    CYG_TEST_CHECK( 0 !=  masks[ 3], "Int  3 unmasked initially" );
    CYG_TEST_CHECK( 0 ==   reqs[13], "Int 13 requests initially" );
    CYG_TEST_CHECK( 0 ==   reqs[12], "Int 12 requests initially" );
    CYG_TEST_CHECK( 0 ==   reqs[ 4], "Int  4 requests initially" );
    CYG_TEST_CHECK( 0 ==   reqs[ 3], "Int  3 requests initially" );
    CYG_TEST_CHECK( 0 != levels[13], "Int 13 edgetrig initially" );
    CYG_TEST_CHECK( 0 != levels[12], "Int 12 edgetrig initially" );
    CYG_TEST_CHECK( 0 != levels[ 4], "Int  4 edgetrig initially" );
    CYG_TEST_CHECK( 0 != levels[ 3], "Int  3 edgetrig initially" );
    CYG_TEST_CHECK( 0 !=    ups[13], "Int 13 not up initially" );
    CYG_TEST_CHECK( 0 ==    ups[12], "Int 12 is up initially" );
    CYG_TEST_CHECK( 0 ==    ups[ 4], "Int  4 is up initially" );
    CYG_TEST_CHECK( 0 !=    ups[ 3], "Int  3 not up initially" );

    checkallbut( 0 ); // don't exclude any of them

    // I want to run this loop for 100 centiSeconds, so that 100 clock
    // interrupts have occurred whilst interfering with the other interrupt
    // state, to provoke possible problems with interactions there.  On a
    // 100MHz 86832 with default configuration, this usually gives 1200
    // loops in total, 12 per centiSecond.  But with config variance and
    // caching behaviour, it's quite possible for this loop to take much
    // longer, if it takes over 1/2 a centiSecond, aliasing effects could
    // cause the timing to fail completely, causing test timeouts.  Hence
    // the additional loop limit of 20 times round the inner loop, aiming
    // for a maximum elapsed time of 20 S maximum, plus extra chances to
    // break out part way through the loop if a tick has passed.

    hipri = 0;
    CYG_TEST_INFO( "About to configure interrupts" );
    for ( i = 0; i < 100; i++ ) {
        int t1, t2, j;
        HAL_CLOCK_READ( &t1 );
        // Do this while/until there is a clock tick
        // ie. some interrupt activity:
        for ( j = 0; j < 20; j++ ) {
            t2 = t1;
            hipri++;
            interferewith( 13, 1 );
            interferewith( 3, 1 );
            interferewith( 4, 0 );
            HAL_CLOCK_READ( &t1 );
            if ( t1 < t2 )
                break;                  // clock has wrapped
            t2 = t1;
            interferewith( 12, 0 );
            interferewith( 3, 1 );
            interferewith( 3, 1 );
            HAL_CLOCK_READ( &t1 );
            if ( t1 < t2 )
                break;                  // clock has wrapped
            t2 = t1;
            interferewith( 4, 0 );
            interferewith( 13, 1 );
            interferewith( 12, 0 );
            interferewith( 12, 0 );
            HAL_CLOCK_READ( &t1 );
            if ( t1 < t2 )
                break;                  // clock has wrapped
        }
    }
    CYG_TEST_PASS( "Configured interrupts 3,4,12 & 13 a great deal" );
    return hipri;
}