/**************************************************************************** * * NAME: vInitialiseApp * * DESCRIPTION: * Initialises Zigbee stack, hardware and application. * * * RETURNS: * void ****************************************************************************/ PRIVATE void vInitialiseApp(void) { /* * Initialise JenOS modules. Initialise Power Manager even on non-sleeping nodes * as it allows the device to doze when in the idle task. * Parameter options: E_AHI_SLEEP_OSCON_RAMON or E_AHI_SLEEP_DEEP or ... */ PWRM_vInit(E_AHI_SLEEP_OSCON_RAMON); #if JENNIC_CHIP == JN5169 PDM_eInitialise(63, NULL); #else PDM_eInitialise(0, NULL); #endif /* Initialise Protocol Data Unit Manager */ PDUM_vInit(); ZPS_vExtendedStatusSetCallback(vfExtendedStatusCallBack); /* Initialise application */ APP_vInitialiseNode(); DBG_vPrintf(TRACE_START, "\nAPP Start: Tick Timer = %d", u32AHI_TickTimerRead()); DBG_vPrintf(TRACE_START,"\nAPP Start: Initialised"); }
/**************************************************************************** * * NAME: SetTickCompare * * DESCRIPTION: * Set the tick timer compare register * * RETURNS: * True if the compare register value is in the future * ****************************************************************************/ OS_HWCOUNTER_SET_CALLBACK(APP_cbSetTickTimerCompare, u32CompareValue) { /* calculations are relative to the last compare register value to account for counter wrap around */ int32 s32NextDelta = u32CompareValue - s_u32LastExpiredTime; uint32 u32CurDelta = u32AHI_TickTimerRead() - s_u32LastExpiredTime; /* * Race condition here. If the tick counter has incremented passed the compare point * in the time between reading it and loading the compare register the interrupt will be missed. * Increase the delta to take account of this time. To minimise this time, the number of * instructions between the register read and write to the interval register should be minimised. */ u32CurDelta += 100; if (s32NextDelta > 0 && u32CurDelta < s32NextDelta) { vAHI_TickTimerInterval(u32CompareValue); s_u32CompareTime = u32CompareValue; return TRUE; } return FALSE; }
PROCESS_THREAD(i2c_process, ev, data) { static size_t i; #if (DEBUG==1) static u32_t i2c_ticks; #endif PROCESS_BEGIN(); vAHI_SiRegisterCallback(i2c_irq); vAHI_SiConfigure(true,true,I2C_400KHZ_FAST_MODE); while ((transaction=list_pop(transactions))) { #if (DEBUG==1) printf("i2c: to 0x%x start, %d written, %d read\n", transaction->addr, transaction->wrlen, transaction->rdlen); i2c_ticks = u32AHI_TickTimerRead(); #endif if (transaction->wrlen) { /* send slave address, start condition */ vAHI_SiWriteData8(transaction->addr); vAHI_SiSetCmdReg(E_AHI_SI_START_BIT, E_AHI_SI_NO_STOP_BIT, E_AHI_SI_NO_SLAVE_READ, E_AHI_SI_SLAVE_WRITE, E_AHI_SI_SEND_ACK, E_AHI_SI_NO_IRQ_ACK); PROCESS_YIELD_UNTIL(ev==PROCESS_EVENT_POLL); if (i2c_status==FAIL) { /* we only test for ACK on the first byte! */ if (transaction->cb) transaction->cb(false); #if (DEBUG==1) printf("i2c: to 0x%x failed, %d written, %d read in %d ticks\n", transaction->addr, transaction->wrlen, transaction->rdlen, u32AHI_TickTimerRead() - i2c_ticks); #endif continue; } } /* send wr data. If repeated_start and there is something to read, send no * stop condition, else send a stop condition on the last byte. */ for (i=0; i<transaction->wrlen; i++) { vAHI_SiWriteData8(transaction->buf[i]); vAHI_SiSetCmdReg(E_AHI_SI_NO_START_BIT, (transaction->wrlen!=0) ? E_AHI_SI_NO_STOP_BIT : transaction->rdlen, E_AHI_SI_NO_SLAVE_READ, E_AHI_SI_SLAVE_WRITE, E_AHI_SI_SEND_ACK, E_AHI_SI_NO_IRQ_ACK); PROCESS_YIELD_UNTIL(ev==PROCESS_EVENT_POLL); if (i2c_status==FAIL) { /* we only test for ACK on the first byte! */ if (transaction->cb) transaction->cb(false); #if (DEBUG==1) printf("i2c: to 0x%x failed, %d written, %d read in %d ticks\n", transaction->addr, transaction->wrlen, transaction->rdlen, (uint32_t) u32AHI_TickTimerRead() - i2c_ticks); #endif continue; } } if (transaction->rdlen) { /* send slave addr, start condition */ vAHI_SiWriteData8(transaction->addr|1); vAHI_SiSetCmdReg(E_AHI_SI_START_BIT, E_AHI_SI_NO_STOP_BIT, E_AHI_SI_NO_SLAVE_READ, E_AHI_SI_SLAVE_WRITE, E_AHI_SI_SEND_ACK, E_AHI_SI_NO_IRQ_ACK); PROCESS_YIELD_UNTIL(ev==PROCESS_EVENT_POLL); } /* read data, send stop condition on last byte, send nak on last byte when * end_of_transmission is set.*/ for (i=0; i<transaction->rdlen; i++) { vAHI_SiSetCmdReg(E_AHI_SI_NO_START_BIT, i==transaction->rdlen-1, E_AHI_SI_SLAVE_READ, E_AHI_SI_NO_SLAVE_WRITE, (i==transaction->rdlen-1) ? E_AHI_SI_SEND_NACK : E_AHI_SI_SEND_ACK, E_AHI_SI_NO_IRQ_ACK); PROCESS_YIELD_UNTIL(ev==PROCESS_EVENT_POLL); transaction->buf[transaction->wrlen+i] = u8AHI_SiReadData8(); } #if (DEBUG==1) printf("i2c: to 0x%x completed, %d written, %d read in %d ticks (rd:", transaction->addr, transaction->wrlen, transaction->rdlen, (u32_t) u32AHI_TickTimerRead() - i2c_ticks); for (i=0; i<transaction->rdlen+transaction->wrlen; i++) printf("0x%x,", transaction->buf[i]); printf(")\n"); #endif if (transaction->cb) transaction->cb(i2c_status==SUCCESS); } vAHI_SiConfigure(false,false,0); PROCESS_END(); }
static void main_loop(void) { int r; clock_time_t time_to_etimer; rtimer_clock_t ticks_to_rtimer; while(1) { do { /* Reset watchdog. */ watchdog_periodic(); r = process_run(); } while(r > 0); /* * Idle processing. */ watchdog_stop(); #if DCOSYNCH_CONF_ENABLED /* Calibrate the DCO every DCOSYNCH_PERIOD * if we have more than 500uSec until next rtimer * PS: Calibration disables interrupts and blocks for 200uSec. * */ if(clock_seconds() - last_dco_calibration_time > DCOSYNCH_PERIOD) { if(rtimer_arch_time_to_rtimer() > RTIMER_SECOND / 2000) { /* PRINTF("ContikiMain: Calibrating the DCO\n"); */ eAHI_AttemptCalibration(); /* Patch to allow CpuDoze after calibration */ vREG_PhyWrite(REG_PHY_IS, REG_PHY_INT_VCO_CAL_MASK); last_dco_calibration_time = clock_seconds(); } } #endif /* DCOSYNCH_CONF_ENABLED */ /* flush standard output before sleeping */ uart_driver_flush(E_AHI_UART_0, TRUE, FALSE); /* calculate the time to the next etimer and rtimer */ time_to_etimer = clock_arch_time_to_etimer(); ticks_to_rtimer = rtimer_arch_time_to_rtimer(); #if JN516X_SLEEP_ENABLED /* we can sleep only up to the next rtimer/etimer */ rtimer_clock_t max_sleep_time = ticks_to_rtimer; if(max_sleep_time >= JN516X_MIN_SLEEP_TIME) { /* also take into account etimers */ uint64_t ticks_to_etimer = ((uint64_t)time_to_etimer * RTIMER_SECOND) / CLOCK_SECOND; max_sleep_time = MIN(ticks_to_etimer, ticks_to_rtimer); } if(max_sleep_time >= JN516X_MIN_SLEEP_TIME) { max_sleep_time -= JN516X_SLEEP_GUARD_TIME; /* bound the sleep time to 1 second */ max_sleep_time = MIN(max_sleep_time, JN516X_MAX_SLEEP_TIME); #if !RTIMER_USE_32KHZ /* convert to 32.768 kHz oscillator ticks */ max_sleep_time = (uint64_t)max_sleep_time * JN516X_XOSC_SECOND / RTIMER_SECOND; #endif vAHI_WakeTimerEnable(WAKEUP_TIMER, TRUE); /* sync with the tick timer */ WAIT_FOR_EDGE(sleep_start); sleep_start_ticks = u32AHI_TickTimerRead(); vAHI_WakeTimerStartLarge(WAKEUP_TIMER, max_sleep_time); ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_EXTRA_LPM); vAHI_Sleep(E_AHI_SLEEP_OSCON_RAMON); } else { #else { #endif /* JN516X_SLEEP_ENABLED */ clock_arch_schedule_interrupt(time_to_etimer, ticks_to_rtimer); ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM); vAHI_CpuDoze(); watchdog_start(); ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU); } } } /*---------------------------------------------------------------------------*/ void AppColdStart(void) { /* After reset or sleep with memory off */ main(); } /*---------------------------------------------------------------------------*/ void AppWarmStart(void) { /* Wakeup after sleep with memory on. * Need to initialize devices but not the application state. * Note: the actual time this function is called is * ~8 ticks (32kHz timer) later than the scheduled sleep end time. */ uint32_t sleep_ticks; uint64_t sleep_end; rtimer_clock_t sleep_ticks_rtimer; clock_arch_calibrate(); leds_init(); uart0_init(UART_BAUD_RATE); /* Must come before first PRINTF */ NETSTACK_RADIO.init(); watchdog_init(); watchdog_stop(); WAIT_FOR_EDGE(sleep_end); sleep_ticks = (uint32_t)(sleep_start - sleep_end) + 1; #if RTIMER_USE_32KHZ sleep_ticks_rtimer = sleep_ticks; #else { static uint32_t remainder; uint64_t t = (uint64_t)sleep_ticks * RTIMER_SECOND + remainder; sleep_ticks_rtimer = (uint32_t)(t / JN516X_XOSC_SECOND); remainder = t - sleep_ticks_rtimer * JN516X_XOSC_SECOND; } #endif /* reinitialize rtimers */ rtimer_arch_reinit(sleep_start_ticks, sleep_ticks_rtimer); ENERGEST_SWITCH(ENERGEST_TYPE_EXTRA_LPM, ENERGEST_TYPE_CPU); watchdog_start(); /* reinitialize clock */ clock_arch_init(1); /* schedule etimer interrupt */ clock_arch_schedule_interrupt(clock_arch_time_to_etimer(), rtimer_arch_time_to_rtimer()); #if DCOSYNCH_CONF_ENABLED /* The radio is recalibrated on wakeup */ last_dco_calibration_time = clock_seconds(); #endif main_loop(); }