int writeToAddress (hBSP430m25p m25p, uint8_t cmd, unsigned long addr, const uint8_t * data, unsigned int len) { BSP430_CORE_INTERRUPT_STATE_T istate; unsigned long t0; unsigned long t1; int rc; int sr; BSP430_CORE_SAVE_INTERRUPT_STATE(istate); BSP430_CORE_DISABLE_INTERRUPT(); do { if (0 != iBSP430m25pStrobeCommand_ni(m25p, BSP430_M25P_CMD_WREN)) { rc = -1; break; } if (0 != iBSP430m25pInitiateAddressCommand_ni(m25p, cmd, addr)) { rc = -1; break; } rc = iBSP430m25pCompleteTxRx_ni(m25p, data, len, 0, NULL); } while (0); BSP430_CORE_RESTORE_INTERRUPT_STATE(istate); t0 = ulBSP430uptime(); do { sr = iBSP430m25pStatus(m25p); } while ((0 <= sr) && (BSP430_M25P_SR_WIP & sr)); t1 = ulBSP430uptime(); cprintf("Write %d took %lu\n", len, t1 - t0); return rc; }
void main () { hBSP430halSERIAL console = NULL; hBSP430halSERIAL uart = NULL; unsigned long prep_utt = 0; unsigned long emit_utt = 0; unsigned long done_utt = 0; vBSP430platformInitialize_ni(); iBSP430consoleInitialize(); console = hBSP430console(); cprintf("\ntxcb " __DATE__ " " __TIME__ "\n"); cprintf("\nConsole %p is on %s: %s\n", console, xBSP430serialName(BSP430_CONSOLE_SERIAL_PERIPH_HANDLE), xBSP430platformPeripheralHelp(BSP430_CONSOLE_SERIAL_PERIPH_HANDLE, 0)); uart = hBSP430serialLookup(UART_PERIPH_HANDLE); if (NULL == uart) { cprintf("Failed to resolve secondary\n"); return; } cprintf("\nSecondary %p is on %s: %s\n", uart, xBSP430serialName(UART_PERIPH_HANDLE), xBSP430platformPeripheralHelp(UART_PERIPH_HANDLE, 0)); tx_buffer_.head = tx_buffer_.tail = 0; BSP430_HAL_ISR_CALLBACK_LINK_NI(sBSP430halISRVoidChainNode, uart->tx_cbchain_ni, tx_buffer_.cb_node, next_ni); uart = hBSP430serialOpenUART(uart, 0, 0, 9600); if (NULL == uart) { cprintf("Secondary open failed\n"); } /* Need to enable interrupts so timer overflow events are properly * acknowledged */ BSP430_CORE_ENABLE_INTERRUPT(); while (1) { unsigned long next_prep_utt; char * obp; char * ob_end; next_prep_utt = ulBSP430uptime(); obp = tx_buffer_.buffer; ob_end = obp + sizeof(tx_buffer_.buffer); obp += snprintf(obp, ob_end - obp, "prep %lu emit %lu\r\n", emit_utt - prep_utt, done_utt - emit_utt); ob_end = obp; BSP430_CORE_DISABLE_INTERRUPT(); emit_utt = ulBSP430uptime_ni(); prep_utt = next_prep_utt; tx_buffer_.tail = 0; tx_buffer_.head = obp - tx_buffer_.buffer; vBSP430serialWakeupTransmit_ni(uart); BSP430_CORE_LPM_ENTER_NI(LPM0_bits); /* Expect tail == head otherwise should not have awoken */ done_utt = ulBSP430uptime(); } }
void testSetEpochFromTimeval (void) { unsigned long utt; utt = ulBSP430uptime(); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(0UL, utt); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, utt)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeCheckEpochValidity()); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(basetv.tv_sec, xBSP430uptimeAsPOSIXTime(utt)); hBSP430uptimeTimer()->overflow_count = 10; utt = ulBSP430uptime(); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(655360UL, utt); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(basetv.tv_sec+20, xBSP430uptimeAsPOSIXTime(utt)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(basetv.tv_sec, xBSP430uptimeAsPOSIXTime(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(basetv.tv_sec-20, xBSP430uptimeAsPOSIXTime(0UL)); hBSP430uptimeTimer()->overflow_count = 0; }
void testEpochValidate (void) { struct timeval tv; unsigned long utt; hBSP430uptimeTimer()->hpl->r = 0; hBSP430uptimeTimer()->overflow_count = 0; BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, 0UL)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeCheckEpochValidity()); hBSP430uptimeTimer()->overflow_count += HALF_ERA >> 16; utt = ulBSP430uptime(); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeAsTimeval(utt, &tv)); BSP430_UNITTEST_ASSERT_TRUE(0 > iBSP430uptimeCheckEpochValidity()); hBSP430uptimeTimer()->overflow_count = 0; BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, 0UL)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeCheckEpochValidity()); hBSP430uptimeTimer()->overflow_count += HALF_ERA >> 16; utt = ulBSP430uptime(); BSP430_UNITTEST_ASSERT_EQUAL_FMTlx((time_t)-1, xBSP430uptimeAsPOSIXTime(utt)); BSP430_UNITTEST_ASSERT_TRUE(0 > iBSP430uptimeCheckEpochValidity()); }
void testEpochAge (void) { unsigned long utt; BSP430_UNITTEST_ASSERT_EQUAL_FMTlx(BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT, QUARTER_ERA + EIGHTH_ERA); /* Test boundaries and wrap into previous era */ hBSP430uptimeTimer()->hpl->r = 0; hBSP430uptimeTimer()->overflow_count = EIGHTH_ERA >> 16; utt = ulBSP430uptime(); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(EIGHTH_ERA, utt); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, 0UL)); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(utt, ulBSP430uptimeLastEpochUpdate()); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(0, lBSP430uptimeEpochAge()); hBSP430uptimeTimer()->overflow_count += QUARTER_ERA >> 16; BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(utt, ulBSP430uptimeLastEpochUpdate()); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(QUARTER_ERA, lBSP430uptimeEpochAge()); hBSP430uptimeTimer()->overflow_count += HALF_ERA >> 16; BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(utt, ulBSP430uptimeLastEpochUpdate()); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(-QUARTER_ERA, lBSP430uptimeEpochAge()); }
void main () { hBSP430halSERIAL i2c; sBSP430bq24210 bq24210; union { sBQ27510 state; uint16_t raw[1]; } u; const int nwords = sizeof(u.state)/sizeof(u.raw[0]); unsigned long resample_interval_utt; unsigned long resample_wake_utt; unsigned int flags; int rc; vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); cprintf("\nbattpack " __DATE__ " " __TIME__ "\n"); bq24210.chg_port = xBSP430hplLookupPORT(APP_CHGn_PORT_PERIPH_HANDLE); bq24210.en_port = xBSP430hplLookupPORT(APP_ENn_PORT_PERIPH_HANDLE); bq24210.pg_port = xBSP430hplLookupPORT(APP_PGn_PORT_PERIPH_HANDLE); bq24210.chg_bit = APP_CHGn_PORT_BIT; bq24210.en_bit = APP_ENn_PORT_BIT; bq24210.pg_bit = APP_PGn_PORT_BIT; cprintf("CHGn on %s.%u\n", xBSP430portName(xBSP430periphFromHPL(bq24210.chg_port)), iBSP430portBitPosition(bq24210.chg_bit)); cprintf("ENn on %s.%u\n", xBSP430portName(xBSP430periphFromHPL(bq24210.en_port)), iBSP430portBitPosition(bq24210.en_bit)); cprintf("PGn on %s.%u\n", xBSP430portName(xBSP430periphFromHPL(bq24210.pg_port)), iBSP430portBitPosition(bq24210.pg_bit)); if (! (bq24210.chg_port && bq24210.en_port && bq24210.pg_port)) { cprintf("One of the ports is missing\n"); return; } /* Charge signal is an input (active low) to the MCU. Configure as * input with internal pull-up. */ bq24210.chg_port->dir &= ~bq24210.chg_bit; bq24210.chg_port->out |= bq24210.chg_bit; bq24210.chg_port->ren |= bq24210.chg_bit; /* Power-good signal is an input (active low) to the MCU. Configure * as input with internal pull-up. */ bq24210.pg_port->dir &= ~bq24210.pg_bit; bq24210.pg_port->out |= bq24210.pg_bit; bq24210.pg_port->ren |= bq24210.pg_bit; /* Enable signal is an output (active low) from the MCU. Start * active. */ bq24210.en_port->out &= ~bq24210.en_bit; bq24210.en_port->dir |= bq24210.en_bit; cprintf("I2C on %s at address 0x%02x\nPins: %s\n", xBSP430serialName(APP_BQ27510_I2C_PERIPH_HANDLE), APP_BQ27510_I2C_ADDRESS, xBSP430platformPeripheralHelp(APP_BQ27510_I2C_PERIPH_HANDLE, BSP430_PERIPHCFG_SERIAL_I2C)); /* NOTE: At default BSP430_SERIAL_I2C_BUS_SPEED_HZ 400kHz this * devices supports only single-byte write operations. Further, * ensure a 66us delay between packets. */ i2c = hBSP430serialOpenI2C(hBSP430serialLookup(APP_BQ27510_I2C_PERIPH_HANDLE), BSP430_SERIAL_ADJUST_CTL0_INITIALIZER(UCMST), 0, 0); if (! i2c) { cprintf("I2C open failed\n"); return; } (void)iBSP430i2cSetAddresses_rh(i2c, -1, APP_BQ27510_I2C_ADDRESS); resample_interval_utt = BSP430_UPTIME_MS_TO_UTT(1000UL * RESAMPLE_INTERVAL_S); resample_wake_utt = ulBSP430uptime_ni(); flags = FLG_DUMP_STATE | FLG_UPDATE_INTERVAL; BSP430_CORE_ENABLE_INTERRUPT(); while (1) { char astext_buf[BSP430_UPTIME_AS_TEXT_LENGTH]; uint16_t temperature_dC; if (FLG_DUMP_STATE & flags) { memset(&u, 0, sizeof(u)); rc = readBQ27510(i2c, 0, nwords, u.raw); cprintf("Device ID %04x rc %d\n", u.state.device_id, rc); cprintf("%.30s = %d\n", "atRate_mA", u.state.atRate_mA); cprintf("%.30s = %u\n", "atRatetimeToEmpty_min", u.state.atRatetimeToEmpty_min); cprintf("%.30s = %u\n", "temperature_dK", u.state.temperature_dK); cprintf("%.30s = %u\n", "voltage_mV", u.state.voltage_mV); cprintf("%.30s = 0x%04x\n", "flags", u.state.flags); cprintf("%.30s = %u\n", "nominalAvailableCapacity_mAh", u.state.nominalAvailableCapacity_mAh); cprintf("%.30s = %u\n", "fullAvailableCapacity_mAh", u.state.fullAvailableCapacity_mAh); cprintf("%.30s = %u\n", "remainingCapacity_mAh", u.state.remainingCapacity_mAh); cprintf("%.30s = %u\n", "fullChargeCapacity_mAh", u.state.fullChargeCapacity_mAh); cprintf("%.30s = %d\n", "averageCurrent_mA", u.state.averageCurrent_mA); cprintf("%.30s = %u\n", "timeToEmpty_min", u.state.timeToEmpty_min); cprintf("%.30s = %d\n", "standbyCurrent_mA", u.state.standbyCurrent_mA); cprintf("%.30s = %u\n", "standbyTimeToEmpty_min", u.state.standbyTimeToEmpty_min); cprintf("%.30s = %u\n", "stateOfHealth_ppcpx", u.state.stateOfHealth_ppcpx); cprintf("%.30s = %u\n", "cycleCount", u.state.cycleCount); cprintf("%.30s = %u\n", "stateOfCharge_ppc", u.state.stateOfCharge_ppc); cprintf("%.30s = %d\n", "instantaneousCurrent_mA", u.state.instantaneousCurrent_mA); cprintf("%.30s = %u\n", "internalTemperature_dK", u.state.internalTemperature_dK); cprintf("%.30s = %u\n", "reistanceScale", u.state.reistanceScale); cprintf("%.30s = %u\n", "operationConfiguration", u.state.operationConfiguration); cprintf("%.30s = %u\n", "designCapacity_mAh", u.state.designCapacity_mAh); cprintf("flags %02x ; ENn state %d\n", flags, (bq24210.en_port->out & bq24210.en_bit)); flags &= ~FLG_DUMP_STATE; } if (FLG_TOGGLE_ENABLE & flags) { bq24210.en_port->out ^= bq24210.en_bit; flags &= ~FLG_TOGGLE_ENABLE; } vBSP430ledSet(BSP430_LED_GREEN, !(bq24210.en_port->out & bq24210.en_bit)); rc = readBQ27510(i2c, 0, nwords, u.raw); temperature_dC = u.state.temperature_dK - 2733; cprintf("%s: %c%c%c % 2d.%dC %4dmV ; SoC %u%% ; Cap %4d / %4d ; %dmA ~ %dmA / %u\n", xBSP430uptimeAsText(ulBSP430uptime(), astext_buf), (bq24210.en_port->out & bq24210.en_bit) ? ' ' : 'E', (bq24210.chg_port->in & bq24210.chg_bit) ? ' ' : 'C', (bq24210.pg_port->in & bq24210.pg_bit) ? ' ' : 'P', (temperature_dC / 10), (temperature_dC % 10), u.state.voltage_mV, u.state.stateOfCharge_ppc, u.state.remainingCapacity_mAh, u.state.fullAvailableCapacity_mAh, u.state.instantaneousCurrent_mA, u.state.averageCurrent_mA, u.state.cycleCount ); if (FLG_UPDATE_INTERVAL & flags) { resample_wake_utt += resample_interval_utt; flags &= ~FLG_UPDATE_INTERVAL; } flags = 0; while (! flags) { iBSP430consoleFlush(); if (0 >= lBSP430uptimeSleepUntil(resample_wake_utt, LPM3_bits)) { flags |= FLG_UPDATE_INTERVAL; } while (0 <= ((rc = cgetchar()))) { if ('!' == rc) { flags |= FLG_TOGGLE_ENABLE; } else if (' ' == rc) { flags |= FLG_DUMP_STATE; } } } } }
void main () { hBSP430timerMuxSharedAlarm map; tBSP430periphHandle uptime_periph; int arc[sizeof(mux_alarms)/sizeof(*mux_alarms)]; unsigned long last_wake_utt; unsigned long last_sleep_utt; int rc = 0; vBSP430platformInitialize_ni(); last_wake_utt = ulBSP430uptime_ni(); (void)iBSP430consoleInitialize(); BSP430_CORE_ENABLE_INTERRUPT(); cprintf("\n\nevent demo " __DATE__ " " __TIME__ "\n"); mux_tag = ucBSP430eventTagAllocate("MuxAlarm"); stats_tag = ucBSP430eventTagAllocate("Statistics"); mux_flag = uiBSP430eventFlagAllocate(); uptime_periph = xBSP430periphFromHPL(hBSP430uptimeTimer()->hpl); map = hBSP430timerMuxAlarmStartup(&mux_alarm_base, uptime_periph, UPTIME_MUXALARM_CCIDX); cprintf("Mux tag %u, stats tag %u, flag %x, with alarm base %p on %s.%u\n", mux_tag, stats_tag, mux_flag, map, xBSP430timerName(uptime_periph), UPTIME_MUXALARM_CCIDX); if (! map) { cprintf("ERR initializing mux shared alarm\n"); goto err_out; } /* Processing done entirely in mux callback. No wakeup. */ mux_alarms[0].alarm.callback_ni = mux_alarm_callback; mux_alarms[0].interval_utt = BSP430_UPTIME_MS_TO_UTT(150); /* Processing done by an event flag */ mux_alarms[1].alarm.callback_ni = mux_alarm_callback; mux_alarms[1].interval_utt = BSP430_UPTIME_MS_TO_UTT(500); mux_alarms[1].flag = mux_flag; /* Processing done by a callback with a timestamped event */ mux_alarms[2].alarm.callback_ni = mux_alarm_callback; mux_alarms[2].interval_utt = BSP430_UPTIME_MS_TO_UTT(700); mux_alarms[2].process_fn = process_timestamp; mux_alarms[2].tag = mux_tag; /* Processing done by a callback with a timestamped event */ mux_alarms[3].alarm.callback_ni = mux_alarm_callback; mux_alarms[3].interval_utt = BSP430_UPTIME_MS_TO_UTT(10000); mux_alarms[3].process_fn = process_statistics; mux_alarms[3].tag = stats_tag; /* Enable the multiplexed alarms */ BSP430_CORE_DISABLE_INTERRUPT(); do { int i = 0; for (i = 0; (0 == rc) && (i < sizeof(mux_alarms)/sizeof(*mux_alarms)); ++i) { mux_alarms[i].alarm.setting_tck = ulBSP430uptime_ni(); arc[i] = iBSP430timerMuxAlarmAdd_ni(map, &mux_alarms[i].alarm); } } while (0); BSP430_CORE_ENABLE_INTERRUPT(); /* Display the results. All values should be non-negative for success. */ { int i; cprintf("Alarm installation got:"); rc = 0; for (i = 0; i < sizeof(arc)/sizeof(*arc); ++i) { cprintf(" %d", arc[i]); if (0 > arc[i]) { rc = arc[i]; } } cputchar('\n'); } if (0 > rc) { goto err_out; } last_sleep_utt = ulBSP430uptime(); while (1) { last_wake_utt = ulBSP430uptime(); unsigned int events = process_events(uiBSP430eventFlagsGet()); if (events) { cprintf("ERR: Unprocessed event flags %04x\n", events); } BSP430_CORE_DISABLE_INTERRUPT(); /* Put back any unprocessed events */ vBSP430eventFlagsSet_ni(events); if (iBSP430eventFlagsEmpty_ni()) { /* Nothing pending: go to sleep, then jump back to the loop head * when we get woken. */ statistics_v.sleep_utt += last_wake_utt - last_sleep_utt; last_sleep_utt = ulBSP430uptime_ni(); statistics_v.awake_utt += last_sleep_utt - last_wake_utt; statistics_v.sleep_ct += 1; BSP430_CORE_LPM_ENTER_NI(LPM4_bits | GIE); continue; } BSP430_CORE_ENABLE_INTERRUPT(); } err_out: (void)iBSP430consoleFlush(); return; }
void main () { sBSP430halPORT * port_hal; hBSP430halTIMER hal; volatile sBSP430hplTIMER * hpl; vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); cputchar('\n'); BSP430_CORE_DELAY_CYCLES(BSP430_CLOCK_NOMINAL_MCLK_HZ / 1000); cprintf("\n\nsynccap " __DATE__ " " __TIME__ "\n"); cprintf("External input on %s.%u corresponds to %s.%u%c\n", xBSP430portName(BSP430_TIMER_CCACLK_CC1_PORT_PERIPH_HANDLE), bitToPin(BSP430_TIMER_CCACLK_CC1_PORT_BIT), xBSP430timerName(BSP430_TIMER_CCACLK_PERIPH_HANDLE), PORT_CCIDX, 'A' + (BSP430_TIMER_CCACLK_CC1_CCIS / CCIS0)); port_hal = hBSP430portLookup(BSP430_TIMER_CCACLK_CC1_PORT_PERIPH_HANDLE); if (NULL == port_hal) { cprintf("Port HAL not available\n"); return; } hal = hBSP430timerLookup(BSP430_TIMER_CCACLK_PERIPH_HANDLE); if (NULL == hal) { cprintf("Can't find timer\n"); return; } BSP430_PORT_HAL_HPL_DIR(port_hal) &= ~BSP430_TIMER_CCACLK_CC1_PORT_BIT; BSP430_PORT_HAL_HPL_SEL(port_hal) |= BSP430_TIMER_CCACLK_CC1_PORT_BIT; hpl = hal->hpl; hpl->cctl[1] = CM_3 | BSP430_TIMER_CCACLK_CC1_CCIS | SCS | CAP | CCIE; captured.last_cci = !!(hpl->cctl[1] & CCI); BSP430_HAL_ISR_CALLBACK_LINK_NI(sBSP430halISRIndexedChainNode, hal->cc_cbchain_ni[PORT_CCIDX], captured.cb, next_ni); hpl->ctl = TASSEL_2 | MC_2 | TACLR | TAIE; /* Need to enable interrupts so timer overflow events are properly * acknowledged */ while (1) { unsigned int ccr; unsigned int cctl; unsigned int count; unsigned int errors; int last_cci; unsigned long event_tt; BSP430_CORE_DISABLE_INTERRUPT(); do { event_tt = captured.event_tt; captured.event_tt = 0; count = captured.count; errors = captured.errors; captured.count = 0; captured.errors = 0; last_cci = captured.last_cci; cctl = hpl->cctl[PORT_CCIDX]; ccr = hpl->ccr[PORT_CCIDX]; hpl->cctl[PORT_CCIDX] &= ~COV; } while (0); BSP430_CORE_ENABLE_INTERRUPT(); cprintf("Up %lu ACLK ticks, timer %lu event %lx ccr %x cctl %04x\n" "\tCCI %d SCCI %d COV %d ; recorded CCI %d ; count %u errors %d\n", ulBSP430uptime(), ulBSP430timerCounter(hal, NULL), event_tt, ccr, cctl, !!(cctl & CCI), !!(cctl & SCCI), !!(cctl & COV), last_cci, count, errors); BSP430_CORE_DELAY_CYCLES(BSP430_CLOCK_NOMINAL_MCLK_HZ); } }
void testEpochEra (void) { unsigned long utt; struct timeval tv; BSP430_UNITTEST_ASSERT_EQUAL_FMTlx(BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT, QUARTER_ERA + EIGHTH_ERA); /* Test boundaries and wrap into previous era */ hBSP430uptimeTimer()->hpl->r = 0; hBSP430uptimeTimer()->overflow_count = EIGHTH_ERA >> 16; utt = ulBSP430uptime(); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(EIGHTH_ERA, utt); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, 0UL)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeCheckEpochValidity()); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(basetv.tv_sec+2*hBSP430uptimeTimer()->overflow_count, xBSP430uptimeAsPOSIXTime(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(0)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(QUARTER_ERA)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt+BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT-1)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(utt+BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(0, iBSP430uptimeEpochEra(-1)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(0, iBSP430uptimeEpochEra(-EIGHTH_ERA)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(0, iBSP430uptimeEpochEra(-(QUARTER_ERA-1))); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(-QUARTER_ERA)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(0UL, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec, tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(QUARTER_ERA, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec + UTT_TO_S(QUARTER_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(-EIGHTH_ERA, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec - UTT_TO_S(EIGHTH_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); /* Test boundaries in current era */ hBSP430uptimeTimer()->hpl->r = 0; hBSP430uptimeTimer()->overflow_count = HALF_ERA >> 16; utt = ulBSP430uptime(); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(HALF_ERA, utt); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, 0UL)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeCheckEpochValidity()); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(basetv.tv_sec+2*hBSP430uptimeTimer()->overflow_count, xBSP430uptimeAsPOSIXTime(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(0)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(utt-BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt-(BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT-1))); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt+BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT-1)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(utt+BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(-1)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(QUARTER_ERA, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec + UTT_TO_S(QUARTER_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(HALF_ERA, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec + UTT_TO_S(HALF_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(HALF_ERA + QUARTER_ERA, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec + UTT_TO_S(HALF_ERA + QUARTER_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); /* Test boundaries and wrap to next era */ hBSP430uptimeTimer()->hpl->r = 0; hBSP430uptimeTimer()->overflow_count = (HALF_ERA + QUARTER_ERA + EIGHTH_ERA) >> 16; utt = ulBSP430uptime(); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(HALF_ERA + QUARTER_ERA + EIGHTH_ERA, utt); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, 0UL)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeCheckEpochValidity()); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(basetv.tv_sec+2*hBSP430uptimeTimer()->overflow_count, xBSP430uptimeAsPOSIXTime(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(utt-BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt-(BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT-1))); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(2, iBSP430uptimeEpochEra(utt+BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT-1)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(utt+BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(-1)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(2, iBSP430uptimeEpochEra(0)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(HALF_ERA + QUARTER_ERA, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec + UTT_TO_S(HALF_ERA + QUARTER_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(0L, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec + UTT_TO_S(FULL_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(EIGHTH_ERA, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec + UTT_TO_S(FULL_ERA + EIGHTH_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); }
void testInitialConditions (void) { BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(0, ulBSP430uptime()); BSP430_UNITTEST_ASSERT_TRUE(0 > iBSP430uptimeCheckEpochValidity()); }
void main () { int rc; sBSP430m25p m25p_data; hBSP430m25p m25p; unsigned long addr; unsigned long t0; unsigned long t1; vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); cprintf("\nBuild " __DATE__ " " __TIME__ "\n"); cprintf("SPI is %s: %s\n", xBSP430serialName(BSP430_PLATFORM_M25P_SPI_PERIPH_HANDLE), xBSP430platformPeripheralHelp(BSP430_PLATFORM_M25P_SPI_PERIPH_HANDLE, 0)); #ifdef BSP430_PLATFORM_M25P_PWR_PORT_PERIPH_HANDLE cprintf("PWR at %s.%u\n", xBSP430portName(BSP430_PLATFORM_M25P_PWR_PORT_PERIPH_HANDLE), iBSP430portBitPosition(BSP430_PLATFORM_M25P_PWR_PORT_BIT)); #else /* BSP430_PLATFORM_M25P_PWR_PORT_PERIPH_HANDLE */ cprintf("PWR is hard-wired\n"); #endif /* BSP430_PLATFORM_M25P_PWR_PORT_PERIPH_HANDLE */ #ifdef BSP430_PLATFORM_M25P_RSTn_PORT_PERIPH_HANDLE cprintf("RSTn at %s.%u\n", xBSP430portName(BSP430_PLATFORM_M25P_RSTn_PORT_PERIPH_HANDLE), iBSP430portBitPosition(BSP430_PLATFORM_M25P_RSTn_PORT_BIT)); #else /* BSP430_PLATFORM_M25P_RSTn_PORT_PERIPH_HANDLE */ cprintf("RSTn is hard-wired\n"); #endif /* BSP430_PLATFORM_M25P_RSTn_PORT_PERIPH_HANDLE */ cprintf("CSn at %s.%u\n", xBSP430portName(BSP430_PLATFORM_M25P_CSn_PORT_PERIPH_HANDLE), iBSP430portBitPosition(BSP430_PLATFORM_M25P_CSn_PORT_BIT)); memset(&m25p_data, 0, sizeof(m25p_data)); m25p_data.spi = hBSP430serialLookup(BSP430_PLATFORM_M25P_SPI_PERIPH_HANDLE); m25p_data.csn_port = xBSP430hplLookupPORT(BSP430_PLATFORM_M25P_CSn_PORT_PERIPH_HANDLE); m25p_data.csn_bit = BSP430_PLATFORM_M25P_CSn_PORT_BIT; #ifdef BSP430_PLATFORM_M25P_RSTn_PORT_PERIPH_HANDLE m25p_data.rstn_port = xBSP430hplLookupPORT(BSP430_PLATFORM_M25P_RSTn_PORT_PERIPH_HANDLE); m25p_data.rstn_bit = BSP430_PLATFORM_M25P_RSTn_PORT_BIT; #endif /* BSP430_PLATFORM_M25P_RSTn_PORT_PERIPH_HANDLE */ m25p = hBSP430m25pInitialize(&m25p_data, BSP430_SERIAL_ADJUST_CTL0_INITIALIZER(UCCKPL | UCMSB | UCMST), UCSSEL_2, 1); if (NULL == m25p) { cprintf("M25P device initialization failed.\n"); return; } #ifdef BSP430_PLATFORM_M25P_PWR_PORT_PERIPH_HANDLE { volatile sBSP430hplPORT * pwr_hpl; /* Turn on power, then wait 10 ms for chip to stabilize before releasing RSTn. */ pwr_hpl = xBSP430hplLookupPORT(BSP430_PLATFORM_M25P_PWR_PORT_PERIPH_HANDLE); pwr_hpl->out &= ~BSP430_PLATFORM_M25P_PWR_PORT_BIT; pwr_hpl->dir |= BSP430_PLATFORM_M25P_PWR_PORT_BIT; pwr_hpl->out |= BSP430_PLATFORM_M25P_PWR_PORT_BIT; BSP430_CORE_DELAY_CYCLES(10 * (BSP430_CLOCK_NOMINAL_MCLK_HZ / 1000)); } #endif /* BSP430_PLATFORM_M25P_PWR_PORT_PERIPH_HANDLE */ BSP430_M25P_RESET_CLEAR(m25p); cprintf("Status register %d\n", iBSP430m25pStatus_ni(m25p)); rc = iBSP430m25pStrobeCommand_ni(m25p, BSP430_M25P_CMD_WREN); cprintf("WREN got %d, status register %d\n", rc, iBSP430m25pStatus_ni(m25p)); rc = iBSP430m25pStrobeCommand_ni(m25p, BSP430_M25P_CMD_WRDI); cprintf("WRDI got %d, status register %d\n", rc, iBSP430m25pStatus_ni(m25p)); rc = iBSP430m25pInitiateCommand_ni(m25p, BSP430_M25P_CMD_RDID); if (0 == rc) { rc = iBSP430m25pCompleteTxRx_ni(m25p, NULL, 0, 20, buffer); } BSP430_CORE_ENABLE_INTERRUPT(); cprintf("READ_IDENTIFICATION got %d\n", rc); if (0 <= rc) { dumpMemory(buffer, rc, 0); } cprintf("Config identified %u sectors of %lu bytes each: %lu bytes total\n", BSP430_PLATFORM_M25P_SECTOR_COUNT, (unsigned long)BSP430_PLATFORM_M25P_SECTOR_SIZE, BSP430_PLATFORM_M25P_SECTOR_COUNT * (unsigned long)BSP430_PLATFORM_M25P_SECTOR_SIZE); #if (BSP430_PLATFORM_M25P_SUBSECTOR_SIZE - 0) cprintf("Config supports access as %u sub-sectors of %u bytes each\n", (unsigned int)(BSP430_PLATFORM_M25P_SECTOR_COUNT * (BSP430_PLATFORM_M25P_SECTOR_SIZE / BSP430_PLATFORM_M25P_SUBSECTOR_SIZE)), (unsigned int)BSP430_PLATFORM_M25P_SUBSECTOR_SIZE); #else /* BSP430_PLATFORM_M25P_SUBSECTOR_SIZE */ cprintf("Config indicates device is not sub-sector addressable\n"); #endif /* BSP430_PLATFORM_M25P_SUBSECTOR_SIZE */ cprintf("RDID identified %lu bytes total capacity\n", 0x1UL << buffer[2]); addr = 0; rc = readFromAddress(m25p, addr, sizeof(flashContents)); if (sizeof(flashContents) != rc) { cprintf("ERROR %d reading initial block\n", rc); } else { dumpMemory(buffer, rc, addr); if (0 == memcmp(flashContents, buffer, rc)) { cprintf("Found expected contents.\n"); } } #if (BSP430_PLATFORM_M25P_SUPPORTS_PE - 0) rc = writeToAddress(m25p, BSP430_M25P_CMD_PE, addr, NULL, 0); cprintf("PAGE_ERASE got %d\n", rc); #else /* BSP430_PLATFORM_M25P_SUPPORTS_PE */ rc = writeToAddress(m25p, BSP430_M25P_CMD_SE, addr, NULL, 0); cprintf("SECTOR_ERASE got %d\n", rc); #endif /* BSP430_PLATFORM_M25P_SUPPORTS_PE */ rc = readFromAddress(m25p, addr, sizeof(buffer)); if (0 < rc) { dumpMemory(buffer, rc, addr); } rc = writeToAddress(m25p, BSP430_M25P_CMD_PP, addr, flashContents, sizeof(flashContents)); cprintf("PAGE_PROGRAM got %d\n", rc); rc = readFromAddress(m25p, addr, sizeof(buffer)); if (0 < rc) { dumpMemory(buffer, rc, addr); } /* PAGE PROGRAM is the one that only clears 1s to 0s so needs a * prior page or sector erase */ rc = writeToAddress(m25p, BSP430_M25P_CMD_PP, addr, flashContents + 4, 4); cprintf("PAGE_PROGRAM to %lx returned %d\n", addr, rc); rc = readFromAddress(m25p, 0, sizeof(flashContents)); dumpMemory(buffer, rc, 0); /* Write 4 took 8 PAGE_PROGRAM to 0 returned 4 00000000 88 11 03 30 cc 33 c3 3c 01 23 45 67 89 ab cd ef ...0.3.<.#Eg.... */ /* PAGE_WRITE is the one that does not need a prior erase cycle */ addr = 8; #if (BSP430_PLATFORM_M25P_SUPPORTS_PW - 0) rc = writeToAddress(m25p, BSP430_M25P_CMD_PW, addr, flashContents + 4, 4); cprintf("PAGE_WRITE to %lx returned %d\n", addr, rc); #else rc = writeToAddress(m25p, BSP430_M25P_CMD_PP, addr, flashContents + 4, 4); cprintf("overwrite PAGE_PROGRAM to unerased %lx returned %d\n", addr, rc); #endif rc = readFromAddress(m25p, 0, sizeof(flashContents)); dumpMemory(buffer, rc, 0); /* Write 4 took 204 PAGE_WRITE to 8 returned 4 00000000 88 11 03 30 cc 33 c3 3c cc 33 c3 3c 89 ab cd ef ...0.3.<.3.<.... */ cprintf("Initiating bulk erase..."); BSP430_CORE_DISABLE_INTERRUPT(); do { t0 = t1 = 0; rc = iBSP430m25pStrobeCommand_ni(m25p, BSP430_M25P_CMD_WREN); if (0 == rc) { rc = iBSP430m25pStrobeCommand_ni(m25p, BSP430_M25P_CMD_BE); } if (0 == rc) { int sr; t0 = ulBSP430uptime_ni(); do { sr = iBSP430m25pStatus_ni(m25p); } while ((0 <= sr) && (BSP430_M25P_SR_WIP & sr)); t1 = ulBSP430uptime(); } } while (0); BSP430_CORE_ENABLE_INTERRUPT(); cprintf("\nBULK_ERASE got %d\n", rc); if (0 == rc) { char tstr[BSP430_UPTIME_AS_TEXT_LENGTH]; cprintf("Bulk erase took %lu utt = %s\n", t1-t0, xBSP430uptimeAsText(t1 - t0, tstr)); } rc = readFromAddress(m25p, 0, sizeof(flashContents)); dumpMemory(buffer, rc, 0); rc = writeToAddress(m25p, BSP430_M25P_CMD_PP, 0, flashContents, sizeof(flashContents)); cprintf("Restore got %d\n", rc); addr = 0; while (addr < (256 * 1025L)) { rc = readFromAddress(m25p, addr, sizeof(buffer)); if (0 > rc) { break; } dumpMemory(buffer, rc, addr); addr += rc; break; } }
void main (void) { unsigned long wake_utt; int rc; long lrc; char as_text[BSP430_UPTIME_AS_TEXT_LENGTH]; uint32_u ntp_addr; uint32_u self_addr; vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); cprintf("\nntp " __DATE__ " " __TIME__ "\n"); /* Initialization can be done with interrupts disabled, since the * function does nothing but store callbacks. We use the same * callback for all three update capabilities. */ rc = iBSP430cc3000spiInitialize(wlan_cb, NULL, NULL, NULL); if (0 > rc) { cprintf("ERR: Initialization failed: %d\n", rc); return; } BSP430_CORE_ENABLE_INTERRUPT(); /* Local addresses use all zeros for inet addr. bind does not * support dynamic assignment of unused port through sin_port=0. */ memset(&local_addr, 0, sizeof(local_addr)); local_addr.sai.sin_family = AF_INET; local_addr.sai.sin_port = htons(60123); /* Remote server will be determined by DNS from the NTP pool once we * start. */ remote_addr = local_addr; remote_addr.sai.sin_port = htons(123); ntp_addr.u32 = 0; self_addr.u32 = 0; cprintf("Remote: %s:%u\n", net_ipv4AsText(&remote_addr.sai.sin_addr), ntohs(remote_addr.sai.sin_port)); rc = sizeof(sBSP430uptimeNTPPacketHeader); if (48 != rc) { cprintf("ERR: NTP header size %d\n", rc); return; } wake_utt = ulBSP430uptime(); (void)rc; while (1) { unsigned long timeout_utt; do { tNetappIpconfigRetArgs ipc; unsigned long start_utt; unsigned long finished_utt; int sfd; int nfds; fd_set rfds; int servers_left; int retries_left; /* Clear everything as we're starting a cycle */ BSP430_CORE_DISABLE_INTERRUPT(); do { event_flags_v = 0; start_utt = ulBSP430uptime_ni(); } while (0); BSP430_CORE_ENABLE_INTERRUPT(); /* Start the WAN process. This is asynchronous; wait up to 2 * seconds for it to complete. */ cprintf("%s: ", xBSP430uptimeAsText(start_utt, as_text)); cputchar('W'); wlan_start(0); vBSP430ledSet(BSP430_LED_RED, 1); (void)wlan_set_event_mask(0UL); lrc = BSP430_UPTIME_MS_TO_UTT(2000); timeout_utt = ulBSP430uptime() + lrc; while ((! (EVENT_FLAG_WLANCONN & event_flags_v)) && (0 < ((lrc = lBSP430uptimeSleepUntil(timeout_utt, LPM0_bits))))) { } if (! (EVENT_FLAG_WLANCONN & event_flags_v)) { cprintf("WLAN start failed\n"); break; } /* Wait for IP connectivity (signalled by a DHCP event). * Continue using the previous timeout. */ cputchar('D'); while ((! (EVENT_FLAG_IPCONN & event_flags_v)) && (0 < ((lrc = lBSP430uptimeSleepUntil(timeout_utt, LPM0_bits))))) { } if (! (EVENT_FLAG_IPCONN & event_flags_v)) { cprintf("IP conn failed\n"); break; } /* Inspect the IP configuration. Sometimes we get the event, * but there's no IP assigned. */ netapp_ipconfig(&ipc); memcpy(self_addr.u8, ipc.aucIP, sizeof(self_addr)); if (! self_addr.u32) { cprintf("IP assignment failed\n"); break; } vBSP430ledSet(BSP430_LED_GREEN, 1); /* Obtain a UDP socket and bind it for local operations. */ cputchar('I'); sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (0 > sfd) { cprintf("socket() failed: %d\n", sfd); break; } cputchar('S'); lrc = bind(sfd, &local_addr.sa, sizeof(local_addr.sa)); if (0 > lrc) { cprintf("bind() failed: %ld\n", lrc); break; } cputchar('B'); servers_left = NTP_SERVERS_PER_ATTEMPT; retries_left = NTP_REQUESTS_PER_SERVER; do { sBSP430uptimeNTPPacketHeader ntp0; sBSP430uptimeNTPPacketHeader ntp1; int have_invalid_epoch; struct timeval tv; sockaddr_u src; socklen_t slen = sizeof(src); unsigned long recv_utt; uint64_t recv_ntp; int64_t adjustment_ntp; long adjustment_ms; unsigned long rtt_us; have_invalid_epoch = 0 != iBSP430uptimeCheckEpochValidity(); if (! remote_addr.sai.sin_addr.s_addr) { const char ntp_fqdn[] = "0.pool.ntp.org"; ntp_addr.u32 = 0; rc = gethostbyname((char *)ntp_fqdn, sizeof(ntp_fqdn)-1, &ntp_addr.u32); cputchar('d'); if (-95 == rc) { /* ARP request failed; retry usually works */ rc = gethostbyname((char *)ntp_fqdn, sizeof(ntp_fqdn)-1, &ntp_addr.u32); cputchar('d'); } if (0 == ntp_addr.u32) { cprintf("gethostbyname(%s) failed: %d\n", ntp_fqdn, rc); rc = -1; break; } remote_addr.sai.sin_addr.s_addr = htonl(ntp_addr.u32); cprintf("{%s}", net_ipv4AsText(&remote_addr.sai.sin_addr)); retries_left = NTP_REQUESTS_PER_SERVER; } /* Configure the NTP request and send it */ iBSP430uptimeInitializeNTPRequest(&ntp0); iBSP430uptimeSetNTPXmtField(&ntp0, NULL); BSP430_CORE_DISABLE_INTERRUPT(); do { /* Clear the shutdown bit, so we know when it's ok to shut * down after this send */ event_flags_v &= ~EVENT_FLAG_SHUTDOWN; } while (0); BSP430_CORE_ENABLE_INTERRUPT(); rc = sendto(sfd, &ntp0, sizeof(ntp0), 0, &remote_addr.sa, sizeof(remote_addr.sai)); if (sizeof(ntp0) != rc) { cprintf("sendto %s:%u failed: %d\n", net_ipv4AsText(&remote_addr.sai.sin_addr), ntohs(remote_addr.sai.sin_port), rc); rc = -1; break; } cputchar('s'); /* If we get an answer it should be here in less than 100 * ms, but give it 400 ms just to be kind. */ tv.tv_sec = 0; tv.tv_usec = 400000UL; FD_ZERO(&rfds); FD_SET(sfd, &rfds); nfds = sfd+1; rc = select(nfds, &rfds, NULL, NULL, &tv); if (! FD_ISSET(sfd, &rfds)) { /* We didn't get an answer. If there are any retries left, use them. */ if (0 < retries_left--) { rc = 1; continue; } /* No retries left on this server: forget about it. If * there are any servers left, try another. */ cputchar('!'); remote_addr.sai.sin_addr.s_addr = 0; if (0 < servers_left--) { rc = 1; continue; } /* No retries from all available servers. Fail this attempt */ cprintf("no responsive NTP server found\n"); rc = -1; break; } /* Got a response. Record the time it came in and then read * it (no high-resolution packet RX time available, but we * believe it's here already so set the RX time first). The * message is unacceptable if it isn't an NTP packet. */ recv_utt = ulBSP430uptime(); rc = recvfrom(sfd, &ntp1, sizeof(ntp1), 0, &src.sa, &slen); if (sizeof(ntp1) != rc) { cprintf("recv failed: %d\n", rc); rc = -1; break; } cputchar('r'); /* Convert the RX time to NTP, then process the message to * determine the offset. */ rc = iBSP430uptimeAsNTP(recv_utt, &recv_ntp, have_invalid_epoch); if (0 != rc) { cprintf("NTP decode failed: %d\n", rc); continue; } rc = iBSP430uptimeProcessNTPResponse(&ntp0, &ntp1, recv_ntp, &adjustment_ntp, &adjustment_ms, &rtt_us); if (0 != rc) { cprintf("Process failed: %d\n", rc); continue; } if (have_invalid_epoch) { rc = iBSP430uptimeSetEpochFromNTP(BSP430_UPTIME_BYPASS_EPOCH_NTP + adjustment_ntp); cputchar('E'); if (0 != rc) { cprintf("\nERR: SetEpoch failed: %d\n", rc); } #if (NTP_ADJUST_EACH_ITER - 0) } else { rc = iBSP430uptimeAdjustEpochFromNTP(adjustment_ntp); cputchar('A'); if (0 != rc) { cprintf("\nERR: AdjustEpoch failed: %d\n", rc); } #endif } cprintf("[%s:%u adj %lld ntp = %ld ms, rtt %lu us]", net_ipv4AsText(&remote_addr.sai.sin_addr), ntohs(remote_addr.sai.sin_port), adjustment_ntp, adjustment_ms, rtt_us); } while (0 != rc); if (0 != rc) { cprintf("NTP query failed\n"); break; } #if 0 /* The shutdown OK seems to arrive about 1000 ms after the last * transmit, which is unnecessarily long. As we're not doing * TCP, there's no reason to wait for it. */ lrc = BSP430_UPTIME_MS_TO_UTT(4000); timeout_utt = ulBSP430uptime() + lrc; while ((! (EVENT_FLAG_SHUTDOWN & event_flags_v)) && (0 < ((lrc = lBSP430uptimeSleepUntil(timeout_utt, LPM0_bits))))) { } if (! (EVENT_FLAG_SHUTDOWN & event_flags_v)) { cprintf("SHUTDOWN ok never received\n"); break; } #endif finished_utt = ulBSP430uptime(); cprintf("[%s]\n", xBSP430uptimeAsText(finished_utt - start_utt, as_text)); } while (0); BSP430_CORE_DISABLE_INTERRUPT(); do { event_flags_v = 0; } while (0); BSP430_CORE_ENABLE_INTERRUPT(); wlan_stop(); vBSP430ledSet(BSP430_LED_GREEN, 0); vBSP430ledSet(BSP430_LED_RED, 0); wake_utt += 60 * ulBSP430uptimeConversionFrequency_Hz(); while (0 < lBSP430uptimeSleepUntil(wake_utt, LPM2_bits)) { } } cprintf("Fell off end\n"); }