void main() { /* You can get the current time since bootup. The NXT does not * include a real time clock, so systick can only tell you the time * since bootup, not the "wall clock" time. */ const U32 time_since_bootup = nx_systick_get_ms(); /* You can use systick to wait for a specified time interval, either * in milliseconds or nanoseconds. The latter is used for very high * resolution timing loops, and should only really be useful to * drivers. */ nx_systick_wait_ms(2000); nx_systick_wait_ns(42); /* At this point, system time is guaranteed to be greater than * before the wait calls. However, due to the way NxOS handles time, * more time than 2000ms + 42ns may have elapsed. */ const U32 time_after_wait = nx_systick_get_ms(); const U32 time_delta = time_after_wait - time_since_bootup; NX_ASSERT(time_delta > 2000); }
static void twi_isr(void) { /* Read the status register once to acknowledge all TWI interrupts. */ volatile U32 status = *AT91C_TWI_SR; /* Read mode and the status indicates a byte was received. */ if (twi_state.mode == TWI_RX_BUSY && (status & AT91C_TWI_RXRDY)) { *twi_state.ptr = *AT91C_TWI_RHR; twi_state.ptr++; twi_state.len--; /* If only one byte is left to read, instruct the TWI to send a STOP * condition after the next byte. */ if (twi_state.len == 1) { *AT91C_TWI_CR = AT91C_TWI_STOP; } /* If the read is over, inhibit all TWI interrupts and return to the * ready state. */ if (twi_state.len == 0) { *AT91C_TWI_IDR = ~0; twi_state.mode = TWI_READY; } } /* Write mode and the status indicated a byte was transmitted. */ if (twi_state.mode == TWI_TX_BUSY && (status & AT91C_TWI_TXRDY)) { /* If that was the last byte, inhibit TWI interrupts and return to * the ready state. */ if (twi_state.len == 0) { *AT91C_TWI_IDR = ~0; twi_state.mode = TWI_READY; } else { /* Instruct the TWI to send a STOP condition at the end of the * next byte if this is the last byte. */ if (twi_state.len == 1) *AT91C_TWI_CR = AT91C_TWI_STOP; /* Write the next byte to the transmit register. */ *AT91C_TWI_THR = *twi_state.ptr; twi_state.ptr++; twi_state.len--; } } /* Check for error conditions. There are pretty critical failures, * since they indicate something is very wrong with either this * driver, or the coprocessor, or the hardware link between them. */ #if defined (__DBGENABLE__) /* Ignore Overruns and Underruns. * If JTAG debugging is enabled and the processor is halted, it * would skip the AVR communications until it is restarted. * (Technically it is not dependent on the __DBGENABLE__ compile flag). * * Nonetheless, the ARMDEBUG code may also cause some communications to be * missed, so it is safer to ignore these conditions as well when __DBGENABLE__ * is defined. */ if (status & (AT91C_TWI_NACK)) { #else if (status & (AT91C_TWI_OVRE | AT91C_TWI_UNRE | AT91C_TWI_NACK)) { #endif *AT91C_TWI_CR = AT91C_TWI_STOP; *AT91C_TWI_IDR = ~0; twi_state.mode = TWI_FAILED; NX_FAIL("Lost link to AVR"); } } void nx__twi_init(void) { U32 clocks = 9; nx_interrupts_disable(); /* Power up the TWI and PIO controllers. */ *AT91C_PMC_PCER = (1 << AT91C_ID_TWI) | (1 << AT91C_ID_PIOA); /* Inhibit all TWI interrupt sources. */ *AT91C_TWI_IDR = ~0; /* If the system is rebooting, the coprocessor might believe that it * is in the middle of an I2C transaction. Furthermore, it may be * pulling the data line low, in the case of a read transaction. * * The TWI hardware has a bug that will lock it up if it is * initialized when one of the clock or data lines is low. * * So, before initializing the TWI, we manually take control of the * pins using the PIO controller, and manually drive a few clock * cycles, until the data line goes high. */ *AT91C_PIOA_MDER = AT91C_PA3_TWD | AT91C_PA4_TWCK; *AT91C_PIOA_PER = AT91C_PA3_TWD | AT91C_PA4_TWCK; *AT91C_PIOA_ODR = AT91C_PA3_TWD; *AT91C_PIOA_OER = AT91C_PA4_TWCK; while (clocks > 0 && !(*AT91C_PIOA_PDSR & AT91C_PA3_TWD)) { *AT91C_PIOA_CODR = AT91C_PA4_TWCK; nx_systick_wait_ns(1500); *AT91C_PIOA_SODR = AT91C_PA4_TWCK; nx_systick_wait_ns(1500); clocks--; } nx_interrupts_enable(); /* Now that the I2C lines are clean, hand them back to the TWI * controller. */ *AT91C_PIOA_PDR = AT91C_PA3_TWD | AT91C_PA4_TWCK; *AT91C_PIOA_ASR = AT91C_PA3_TWD | AT91C_PA4_TWCK; /* Reset the controller and configure its clock. The clock setting * makes the TWI run at 380kHz. */ *AT91C_TWI_CR = AT91C_TWI_SWRST | AT91C_TWI_MSDIS; *AT91C_TWI_CWGR = 0x020f0f; *AT91C_TWI_CR = AT91C_TWI_MSEN; twi_state.mode = TWI_READY; /* Install the TWI interrupt handler. */ nx_aic_install_isr(AT91C_ID_TWI, AIC_PRIO_RT, AIC_TRIG_LEVEL, twi_isr); }