void main () { vBSP430platformInitialize_ni(); vBSP430uptimeStart_ni(); vBSP430unittestInitialize(); BSP430_CORE_DISABLE_INTERRUPT(); /* Halt the timer without telling the infrastructure, since we * manage it explicitly. Put the interrupts back on so that we can * synthesize overflow events and have them be handled normally. */ hBSP430uptimeTimer()->hpl->ctl &= ~(MC0 | MC1); hBSP430uptimeTimer()->hpl->r = 0; hBSP430uptimeTimer()->overflow_count = 0; ulBSP430uptimeSetConversionFrequency_ni(32768); BSP430_CORE_ENABLE_INTERRUPT(); testInitialConditions(); testSetEpochFromTimeval(); testEpochEra(); testEpochValidate(); testEpochAge(); testNTPSequence(); vBSP430unittestFinalize(); }
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 main () { hBSP430halPORT b0hal = hBSP430portLookup(BSP430_PLATFORM_BUTTON0_PORT_PERIPH_HANDLE); volatile sBSP430hplPORTIE * b0hpl; int b0pin = iBSP430portBitPosition(BSP430_PLATFORM_BUTTON0_PORT_BIT); vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); cprintf("\nbutton " __DATE__ " " __TIME__ "\n"); cprintf("There's supposed to be a button at %s.%u\n", xBSP430portName(BSP430_PLATFORM_BUTTON0_PORT_PERIPH_HANDLE), b0pin); if (! b0hal) { cprintf("Whoops, guess it's not really there\n"); return; } b0hpl = BSP430_PORT_HAL_GET_HPL_PORTIE(b0hal); button_state.button_cb.next_ni = b0hal->pin_cbchain_ni[b0pin]; b0hal->pin_cbchain_ni[b0pin] = &button_state.button_cb; b0hpl->sel &= ~BSP430_PLATFORM_BUTTON0_PORT_BIT; b0hpl->dir &= ~BSP430_PLATFORM_BUTTON0_PORT_BIT; #if (BSP430_PORT_SUPPORTS_REN - 0) BSP430_PORT_HAL_SET_REN(b0hal, BSP430_PLATFORM_BUTTON0_PORT_BIT, BSP430_PORT_REN_PULL_UP); #endif /* BSP430_PORT_SUPPORTS_REN */ if (b0hpl->in & BSP430_PLATFORM_BUTTON0_PORT_BIT) { button_state.in_mask = BSP430_PLATFORM_BUTTON0_PORT_BIT; b0hpl->ies |= BSP430_PLATFORM_BUTTON0_PORT_BIT; } else { button_state.in_mask = 0; b0hpl->ies &= ~BSP430_PLATFORM_BUTTON0_PORT_BIT; } b0hpl->ifg &= ~BSP430_PLATFORM_BUTTON0_PORT_BIT; b0hpl->ie |= BSP430_PLATFORM_BUTTON0_PORT_BIT; cprintf("Button is configured. Try pressing it. No debouncing is done.\n"); #if ! (configBSP430_CORE_LPM_EXIT_CLEAR_GIE - 0) cprintf("WARNING: Interrupts remain enabled after wakeup\n"); #endif /* configBSP430_CORE_LPM_EXIT_CLEAR_GIE */ vBSP430ledSet(0, 1); while (1) { static const char * state_str[] = { "released", "pressed" }; cprintf("Count %u, in mask 0x%02x: %s\n", button_state.count, button_state.in_mask, state_str[!button_state.in_mask]); /* Note that we've never turned interrupts on, but * BSP430_CORE_LPM_ENTER_NI() does so internally so the ISR can be * executed. Whether they are cleared before returning to this * loop depends on #configBSP430_CORE_LPM_EXIT_CLEAR_GIE. */ BSP430_CORE_LPM_ENTER_NI(LPM0_bits); #if ! (configBSP430_CORE_LPM_EXIT_CLEAR_GIE - 0) /* Infrastructure didn't clear this, so we should */ BSP430_CORE_DISABLE_INTERRUPT(); #endif /* configBSP430_CORE_LPM_EXIT_CLEAR_GIE */ } }
void main () { sBSP430halPORT * hh10d_port = hBSP430portLookup(APP_HH10D_PORT_PERIPH_HANDLE); hBSP430halSERIAL i2c = hBSP430serialLookup(APP_HH10D_I2C_PERIPH_HANDLE); int uptime_Hz; int hh10d_offs; int hh10d_sens; vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); cprintf("\nApplication starting\n"); BSP430_CORE_DELAY_CYCLES(10000); if (NULL == hh10d_port) { cprintf("\nERROR: No port HAL; did you enable configBSP430_HAL_%s?\n", xBSP430portName(APP_HH10D_PORT_PERIPH_HANDLE) ?: "whatever"); return; }
void main () { vBSP430platformInitialize_ni(); vBSP430unittestInitialize(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(0x1234, BSP430_CORE_SWAP_16(0x3412)); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(0x1234, bswap16i16o16(0x3412)); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(0x1234, bswap16i32o32(0x3412)); BSP430_UNITTEST_ASSERT_EQUAL_FMTlx(0x7856, BSP430_CORE_SWAP_16(0x12345678L)); BSP430_UNITTEST_ASSERT_EQUAL_FMTlx(0x7856L, bswap16i32o32(0x12345678L)); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(0xFEDC, BSP430_CORE_SWAP_16(0xDCFE)); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(0xFEDC, bswap16i16o16(0xDCFE)); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(0xFEDC, bswap16i32o32(0xDCFE)); BSP430_UNITTEST_ASSERT_EQUAL_FMTlx(0x98BA, BSP430_CORE_SWAP_16(0xFEDCBA98)); BSP430_UNITTEST_ASSERT_EQUAL_FMTlx(0x98BAL, bswap16i32o32(0xFEDCBA98L)); vBSP430unittestFinalize(); }
void main () { const sColor * cp = colors; const sColor * const ecp = colors + sizeof(colors) / sizeof(*colors); vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); while (1) { if (0 > cp->idx) { cprintf("%s is not available\n", cp->name); } else { vBSP430ledSet(cp->idx, 1); cprintf("%s lit; mask 0x%x\n", cp->name, read_leds()); BSP430_CORE_DELAY_CYCLES(5 * BSP430_CLOCK_NOMINAL_MCLK_HZ); vBSP430ledSet(cp->idx, 0); } if (++cp == ecp) { cp = colors; } } }
void main () { int rv; uBSP430eui64 eui64; int i; vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); cputs("\n\n\nEUI-64 Verification"); #if ! (BSP430_EUI64 - 0) cputs("EUI-64 not supported by platform\n"); #else /* BSP430_EUI64 */ while (1) { memset(&eui64, 0, sizeof(eui64)); rv = iBSP430eui64(&eui64); cprintf("Request got %d: ", rv); for (i = 0; i < sizeof(eui64.bytes); ++i) { cprintf("%02x", eui64.bytes[i]); } cputchar('\n'); } #endif /* BSP430_EUI64 */ }
void main () { BSP430_CORE_INTERRUPT_STATE_T istate; #if BSP430_MODULE_SYS - 0 unsigned long reset_causes = 0; unsigned int reset_flags = 0; #endif /* BSP430_MODULE_SYS */ #if BSP430_MODULE_SYS - 0 { unsigned int sysrstiv; /* Record all the reset causes */ while (0 != ((sysrstiv = uiBSP430sysSYSRSTGenerator_ni(&reset_flags)))) { reset_causes |= 1UL << (sysrstiv / 2); } } #endif /* BSP430_MODULE_SYS */ vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); #if BSP430_MODULE_SYS - 0 cprintf("System reset bitmask %lx; causes:\n", reset_causes); { int bit = 0; while (bit < (8 * sizeof(reset_causes))) { if (reset_causes & (1UL << bit)) { cprintf("\t%s\n", xBSP430sysSYSRSTIVDescription(2*bit)); } ++bit; } } cputtext_ni("System reset included:"); if (reset_flags) { if (reset_flags & BSP430_SYS_FLAG_SYSRST_BOR) { cputtext_ni(" BOR"); } if (reset_flags & BSP430_SYS_FLAG_SYSRST_LPM5WU) { cputtext_ni(" LPM5WU"); } if (reset_flags & BSP430_SYS_FLAG_SYSRST_POR) { cputtext_ni(" POR"); } if (reset_flags & BSP430_SYS_FLAG_SYSRST_PUC) { cputtext_ni(" PUC"); } } else { cputtext_ni(" no data"); } cputchar_ni('\n'); #endif /* BSP430_MODULE_SYS */ BSP430_CORE_ENABLE_INTERRUPT(); memcpy(ivect, VECTOR_OFFSET, VECTOR_LENGTH_BYTES); dumpRegion("Cached vectors", ivect, VECTOR_LENGTH_BYTES); dumpRegion("Vectors", VECTOR_OFFSET, VECTOR_LENGTH_BYTES); BSP430_CORE_SAVE_INTERRUPT_STATE(istate); BSP430_CORE_DISABLE_INTERRUPT(); do { /* Note: You need to flush the console if you want to see the * output now; otherwise it'll be printed once interrupt-driven * transmission is re-enabled. */ iBSP430consoleFlush(); iBSP430consoleTransmitUseInterrupts_ni(0); (void)iBSP430flashEraseSegment_ni((void*)0xFE00); dumpRegion("Vectors with 0xFE00", VECTOR_OFFSET, VECTOR_LENGTH_BYTES); (void)iBSP430flashEraseSegment_ni(VECTOR_OFFSET); vBSP430ledSet(0, 1); dumpRegion("Vectors as erased", VECTOR_OFFSET, VECTOR_LENGTH_BYTES); memcpy(erased_ivect, VECTOR_OFFSET, VECTOR_LENGTH_BYTES); (void)iBSP430flashWriteData_ni(VECTOR_OFFSET, ivect, VECTOR_LENGTH_BYTES); vBSP430ledSet(1, 1); iBSP430consoleTransmitUseInterrupts_ni(1); } while (0); BSP430_CORE_RESTORE_INTERRUPT_STATE(istate); dumpRegion("Erased Vectors", erased_ivect, VECTOR_LENGTH_BYTES); dumpRegion("Restored Vectors", VECTOR_OFFSET, VECTOR_LENGTH_BYTES); iBSP430consoleFlush(); }
void main () { int rc = 0; /* GDO0 and GDO2 are always interrupt-capable. */ volatile sBSP430hplPORTIE * gdo0 = xBSP430hplLookupPORTIE(BSP430_RF_CC110X_GDO0_PORT_PERIPH_HANDLE); volatile sBSP430hplPORTIE * gdo2 = xBSP430hplLookupPORTIE(BSP430_RF_CC110X_GDO2_PORT_PERIPH_HANDLE); hBSP430halPORT hgdo1 = hBSP430portLookup(BSP430_RF_CC110X_GDO1_PORT_PERIPH_HANDLE); hBSP430halPORT hcsn = hBSP430portLookup(BSP430_RF_CC110X_CSn_PORT_PERIPH_HANDLE); spi = hBSP430serialLookup(BSP430_RF_CC110X_SPI_PERIPH_HANDLE); vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); cprintf("\nccid " __DATE__ " " __TIME__ "\n"); cprintf("GDO0 %p at %s.%u\n", gdo0, xBSP430portName(BSP430_RF_CC110X_GDO0_PORT_PERIPH_HANDLE), iBSP430portBitPosition(BSP430_RF_CC110X_GDO0_PORT_BIT)); cprintf("GDO1 HAL %p HPL %p at %s.%u\n", hgdo1, hgdo1->hpl.any, xBSP430portName(BSP430_RF_CC110X_GDO1_PORT_PERIPH_HANDLE), iBSP430portBitPosition(BSP430_RF_CC110X_GDO1_PORT_BIT)); cprintf("GDO2 %p at %s.%u\n", gdo2, xBSP430portName(BSP430_RF_CC110X_GDO2_PORT_PERIPH_HANDLE), iBSP430portBitPosition(BSP430_RF_CC110X_GDO2_PORT_BIT)); cprintf("CSn HAL %p HPL %p at %s.%u\n", hcsn, hcsn->hpl.any, xBSP430portName(BSP430_RF_CC110X_CSn_PORT_PERIPH_HANDLE), iBSP430portBitPosition(BSP430_RF_CC110X_CSn_PORT_BIT)); cprintf("SPI %p is %s\n", spi, xBSP430serialName(BSP430_RF_CC110X_SPI_PERIPH_HANDLE)); #if BSP430_PLATFORM_PERIPHERAL_HELP cprintf("SPI Pins: %s\n", xBSP430platformPeripheralHelp(BSP430_RF_CC110X_SPI_PERIPH_HANDLE, BSP430_PERIPHCFG_SERIAL_SPI3)); #endif /* BSP430_PLATFORM_PERIPHERAL_HELP */ cprintf(__DATE__ " " __TIME__ "\n"); /* Configure the SPI interface, but immediately put it into hold * mode so we can check CHIP_RDYn on the MISO/GDO1 input. */ spi = hBSP430serialOpenSPI(spi, BSP430_RF_CC110X_SPI_CTL0_BYTE, 0, 0); if (spi) { rc = iBSP430serialSetHold_rh(spi, 1); /* GDO1 to input, pull-up */ BSP430_PORT_HAL_HPL_DIR(hgdo1) &= ~BSP430_RF_CC110X_GDO1_PORT_BIT; BSP430_PORT_HAL_SET_REN(hgdo1, BSP430_RF_CC110X_GDO1_PORT_BIT, BSP430_PORT_REN_PULL_UP); } cprintf("SPI device %p hold returned %d\n", spi, rc); if (! spi) { return; } /* Configure CSn initial high to ensure we have a falling edge when * we first enable the radio. */ BSP430_PORT_HAL_HPL_SEL(hcsn) &= ~BSP430_RF_CC110X_CSn_PORT_BIT; BSP430_PORT_HAL_HPL_OUT(hcsn) |= BSP430_RF_CC110X_CSn_PORT_BIT; BSP430_PORT_HAL_HPL_DIR(hcsn) |= BSP430_RF_CC110X_CSn_PORT_BIT; /* Now enable the radio */ BSP430_PORT_HAL_HPL_OUT(hcsn) &= ~BSP430_RF_CC110X_CSn_PORT_BIT; /* Spin until GDO1 (CHP_RDYn) is clear indicating radio is responsive */ while (BSP430_PORT_HAL_HPL_IN(hgdo1) & BSP430_RF_CC110X_GDO1_PORT_BIT) { cprintf("Waiting for radio ready\n"); BSP430_CORE_DELAY_CYCLES(BSP430_CLOCK_NOMINAL_MCLK_HZ); } /* Enable SPI */ rc = iBSP430serialSetHold_rh(spi, 0); cprintf("Radio is up, hold release %d; sending SRES strobe\n", rc); /* Send a reset */ do { rc = sendStrobe(0x30); cprintf("Strobe response %#02x\n", rc); if (0x0F != rc) { BSP430_CORE_DELAY_CYCLES(BSP430_CLOCK_NOMINAL_MCLK_HZ); } } while (0x0F != rc); cprintf("PARTNUM response %#02x\n", readRegister(0x30)); cprintf("VERSION response %#02x\n", readRegister(0x31)); cprintf("IOCFG2 read %#02x\n", readRegister(0x00)); cprintf("IOCFG1 read %#02x\n", readRegister(0x01)); cprintf("IOCFG0 read %#02x\n", readRegister(0x02)); /* ChipCon radios consume 1.4mA when idle. That goes down to * nominally 400 nA if the GDOs are configured to "HW to 0" and the * chip is told to power-down on loss of CSn. On the EXP430F5438 * the RF PWR header indicates that a CC1101 is using 40 nA in this * mode.*/ rc = writeRegister(0x00, 0x2f); rc = writeRegister(0x01, 0x2f); rc = writeRegister(0x02, 0x2f); cprintf("Cleared IOCFG\n"); cprintf("IOCFG2 read %#02x\n", readRegister(0x00)); cprintf("IOCFG1 read %#02x\n", readRegister(0x01)); cprintf("IOCFG0 read %#02x\n", readRegister(0x02)); /* SPWD */ rc = sendStrobe(0x39); cprintf("SPWD got %d\n", rc); /* Disable SPI before removing CSn otherwise the sequence isn't * right. */ rc = iBSP430serialSetHold_rh(spi, 1); BSP430_PORT_HAL_HPL_OUT(hcsn) |= BSP430_RF_CC110X_CSn_PORT_BIT; /* This gets the RF2500T power down to about 120 nA. Note: * Purposefully enter LPM with #GIE off since we do not intend to * wake up.*/ BSP430_CORE_LPM_ENTER(LPM3_bits); }
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 main () { volatile sBSP430hplTIMER * const timer_hpl = xBSP430hplLookupTIMER(BSP430_TIMER_CCACLK_PERIPH_HANDLE); unsigned int outclk; unsigned int last_outclk; unsigned int cctl; hBSP430halPORT const inclk_port_hal = hBSP430portLookup(BSP430_TIMER_CCACLK_CLK_PORT_PERIPH_HANDLE); hBSP430halPORT const cc_port_hal = hBSP430portLookup(APP_CC_PORT_PERIPH_HANDLE); hBSP430halPORT const outclk_port_hal = hBSP430portLookup(APP_OUTCLK_PORT_PERIPH_HANDLE); hBSP430halPORT const trigger_port_hal = hBSP430portLookup(APP_TRIGGER_PORT_PERIPH_HANDLE); vBSP430platformInitialize_ni(); vBSP430unittestInitialize(); cprintf("timer_scs_test: " __DATE__ " " __TIME__ "\n"); if (NULL == timer_hpl) { cprintf("ERROR: Unable to get timer HPL access\n"); return; } if (NULL == inclk_port_hal) { cprintf("ERROR: Unable to get INCLK port access\n"); return; } if (NULL == cc_port_hal) { cprintf("ERROR: Unable to get CC0 port access\n"); return; } if (NULL == outclk_port_hal) { cprintf("ERROR: Unable to get OUTCLK port access\n"); return; } if (NULL == trigger_port_hal) { cprintf("ERROR: Unable to get TRIGGER port access\n"); return; } cprintf("Please connect OUTCLK at %s.%u to %s INCLK at %s.%u\n", xBSP430portName(APP_OUTCLK_PORT_PERIPH_HANDLE), iBSP430portBitPosition(APP_OUTCLK_PORT_BIT), xBSP430timerName(BSP430_TIMER_CCACLK_PERIPH_HANDLE), xBSP430portName(BSP430_TIMER_CCACLK_CLK_PORT_PERIPH_HANDLE), iBSP430portBitPosition(BSP430_TIMER_CCACLK_CLK_PORT_BIT)); cprintf("Please connect TRIGGER at %s.%u to %s CCI0%c at %s.%u\n", xBSP430portName(APP_TRIGGER_PORT_PERIPH_HANDLE), iBSP430portBitPosition(APP_TRIGGER_PORT_BIT), xBSP430timerName(BSP430_TIMER_CCACLK_PERIPH_HANDLE), 'A' + (APP_CC_CCIS / CCIS0), xBSP430portName(APP_CC_PORT_PERIPH_HANDLE), iBSP430portBitPosition(APP_CC_PORT_BIT)); /* OUTCLK: output low */ outclk = 0; BSP430_PORT_HAL_HPL_OUT(outclk_port_hal) &= ~APP_OUTCLK_PORT_BIT; BSP430_PORT_HAL_HPL_DIR(outclk_port_hal) |= APP_OUTCLK_PORT_BIT; BSP430_PORT_HAL_HPL_SEL(outclk_port_hal) &= ~APP_OUTCLK_PORT_BIT; /* TRIGGER: output low */ BSP430_PORT_HAL_HPL_OUT(trigger_port_hal) &= ~APP_TRIGGER_PORT_BIT; BSP430_PORT_HAL_HPL_DIR(trigger_port_hal) |= APP_TRIGGER_PORT_BIT; BSP430_PORT_HAL_HPL_SEL(trigger_port_hal) &= ~APP_TRIGGER_PORT_BIT; /* INCLK: input peripheral function */ BSP430_PORT_HAL_HPL_SEL(inclk_port_hal) &= ~BSP430_TIMER_CCACLK_CLK_PORT_BIT; BSP430_PORT_HAL_HPL_SEL(inclk_port_hal) |= BSP430_TIMER_CCACLK_CLK_PORT_BIT; /* CC0: input peripheral function */ BSP430_PORT_HAL_HPL_DIR(cc_port_hal) &= ~APP_CC_PORT_BIT; BSP430_PORT_HAL_HPL_SEL(cc_port_hal) |= APP_CC_PORT_BIT; cprintf("P4: DIR %04x SEL %04x\n", P4DIR, P4SEL); #define CLEAR_CAPTURE() do { \ timer_hpl->cctl[APP_CCIDX] &= ~CCIFG; \ timer_hpl->ccr[APP_CCIDX] = 0; \ } while (0) #define ASSERT_CLOCK_HIGH() do { \ BSP430_UNITTEST_ASSERT_TRUE(BSP430_PORT_HAL_HPL_OUT(outclk_port_hal) & APP_OUTCLK_PORT_BIT); \ } while (0) #define ASSERT_CLOCK_LOW() do { \ BSP430_UNITTEST_ASSERT_FALSE(BSP430_PORT_HAL_HPL_OUT(outclk_port_hal) & APP_OUTCLK_PORT_BIT); \ } while (0) #define ASSERT_CCI_HIGH() do { \ BSP430_UNITTEST_ASSERT_TRUE(CCI & timer_hpl->cctl[APP_CCIDX]); \ } while (0) #define ASSERT_CCI_LOW() do { \ BSP430_UNITTEST_ASSERT_FALSE(CCI & timer_hpl->cctl[APP_CCIDX]); \ } while (0) #define ASSERT_INTERNAL_TRIGGER_HIGH() do { \ BSP430_UNITTEST_ASSERT_TRUE(CCIS_3 == (CCIS_3 & timer_hpl->cctl[APP_CCIDX])); \ } while (0) #define ASSERT_INTERNAL_TRIGGER_LOW() do { \ BSP430_UNITTEST_ASSERT_TRUE(CCIS_2 == (CCIS_3 & timer_hpl->cctl[APP_CCIDX])); \ } while (0) #define ASSERT_NO_CAPTURE() do { \ BSP430_UNITTEST_ASSERT_FALSE(CCIFG & timer_hpl->cctl[APP_CCIDX]); \ BSP430_UNITTEST_ASSERT_EQUAL_FMTx(0, timer_hpl->ccr[APP_CCIDX]); \ } while (0) #define ASSERT_YES_CAPTURE() do { \ BSP430_UNITTEST_ASSERT_TRUE(CCIFG & timer_hpl->cctl[APP_CCIDX]); \ BSP430_UNITTEST_ASSERT_EQUAL_FMTx(timer_hpl->r, timer_hpl->ccr[APP_CCIDX]); \ } while (0) /* Capture asynchronously on falling edge from TRIGGER. */ timer_hpl->ccr[APP_CCIDX] = 0; timer_hpl->cctl[APP_CCIDX] = CM_2 | APP_CC_CCIS | SCCI | CAP; timer_hpl->cctl[APP_CCIDX] = CM_3 | APP_CC_CCIS | SCCI | CAP; cprintf("%u: Timer: R %04x CTL %04x CCR %04x CCTL %04x\n", __LINE__, timer_hpl->r, timer_hpl->ctl, timer_hpl->ccr[APP_CCIDX], timer_hpl->cctl[APP_CCIDX]); /* Count upwards. */ timer_hpl->ctl = TASSEL_0 | MC_2 | TACLR; /* Validate that we can control the clock input. */ BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, 0); ASSERT_CLOCK_LOW(); HALF_TICK_OUTCLK(); ASSERT_CLOCK_HIGH(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, 1); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); HALF_TICK_OUTCLK(); ASSERT_CLOCK_LOW(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, 1); HALF_TICK_OUTCLK(); ASSERT_CLOCK_HIGH(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); HALF_TICK_OUTCLK(); ASSERT_CLOCK_LOW(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); /* Verify that we can control the trigger, and that asynchronous * captures work. */ ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); HALF_TRIGGER(); if (CM0 & timer_hpl->cctl[APP_CCIDX]) { ASSERT_YES_CAPTURE(); if (! (CM1 & timer_hpl->cctl[APP_CCIDX])) { CLEAR_CAPTURE(); } } else { ASSERT_NO_CAPTURE(); } ASSERT_CCI_HIGH(); HALF_TRIGGER(); ASSERT_YES_CAPTURE(); ASSERT_CCI_LOW(); CLEAR_CAPTURE(); /* Advance the clock. Make sure no capture occurred. */ last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, last_outclk+1); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); ASSERT_NO_CAPTURE(); last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(last_outclk, timer_hpl->r); ASSERT_NO_CAPTURE(); /* Now turn on synchronous capture */ timer_hpl->cctl[APP_CCIDX] |= SCS; /* Advance the clock. Make sure no capture occurred */ cctl = timer_hpl->cctl[APP_CCIDX]; last_outclk = outclk; ASSERT_CLOCK_LOW(); HALF_TICK_OUTCLK(); ASSERT_CLOCK_HIGH(); ASSERT_NO_CAPTURE(); HALF_TICK_OUTCLK(); ASSERT_CLOCK_LOW(); ASSERT_NO_CAPTURE(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(last_outclk+1, timer_hpl->r); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(cctl, timer_hpl->cctl[APP_CCIDX]); /* Do this again to make really sure no capture occurred. */ HALF_TICK_OUTCLK(); ASSERT_NO_CAPTURE(); HALF_TICK_OUTCLK(); ASSERT_NO_CAPTURE(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(last_outclk+2, timer_hpl->r); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(cctl, timer_hpl->cctl[APP_CCIDX]); /* F1) CCI rises then falls while CLK remains low. CCIFG remains low. When CLK rises the counter is incremented but CCIFG remains low. CCIFG is set only when CLK falls. */ /* CLK is low. */ ASSERT_CLOCK_LOW(); /* Check that external triggers with sync async do not trigger when * clock does not advance. */ ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); HALF_TRIGGER(); ASSERT_NO_CAPTURE(); ASSERT_CCI_HIGH(); HALF_TRIGGER(); ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); /* Advance the clock. No action on rising edge. */ last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, last_outclk+1); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); ASSERT_CLOCK_HIGH(); /* Falling edge does not increment counter but does cause capture */ last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, last_outclk); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); ASSERT_YES_CAPTURE(); ASSERT_CCI_LOW(); CLEAR_CAPTURE(); /* F2) CCI rises then falls while CLK remains high. CCIFG remains low. When CLK falls CCIFG is set. */ /* Advance the clock. No action on rising edge. */ last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, last_outclk+1); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); ASSERT_CLOCK_HIGH(); /* Check that external triggers with sync async do not trigger when * clock does not advance. */ ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); HALF_TRIGGER(); ASSERT_NO_CAPTURE(); ASSERT_CCI_HIGH(); HALF_TRIGGER(); ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); /* Falling edge does not increment counter but does cause capture */ last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, last_outclk); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); ASSERT_YES_CAPTURE(); ASSERT_CCI_LOW(); CLEAR_CAPTURE(); /* Now test it with internal toggles. First, asynchronous: */ timer_hpl->cctl[APP_CCIDX] = CM_3 | CCIS_2 | SCCI | CAP; ASSERT_NO_CAPTURE(); ASSERT_INTERNAL_TRIGGER_LOW(); ASSERT_CCI_LOW(); HALF_TRIGGER(); ASSERT_CCI_LOW(); ASSERT_NO_CAPTURE(); INTERNAL_HALF_TRIGGER(); ASSERT_CCI_HIGH(); ASSERT_INTERNAL_TRIGGER_HIGH(); ASSERT_YES_CAPTURE(); CLEAR_CAPTURE(); HALF_TRIGGER(); ASSERT_CCI_HIGH(); ASSERT_NO_CAPTURE(); INTERNAL_HALF_TRIGGER(); ASSERT_CCI_LOW(); ASSERT_INTERNAL_TRIGGER_LOW(); ASSERT_YES_CAPTURE(); ASSERT_CCI_LOW(); CLEAR_CAPTURE(); /* Now synchronous */ timer_hpl->cctl[APP_CCIDX] |= SCS; ASSERT_NO_CAPTURE(); ASSERT_INTERNAL_TRIGGER_LOW(); INTERNAL_HALF_TRIGGER(); ASSERT_INTERNAL_TRIGGER_HIGH(); ASSERT_NO_CAPTURE(); INTERNAL_HALF_TRIGGER(); ASSERT_INTERNAL_TRIGGER_LOW(); ASSERT_NO_CAPTURE(); /* Advance the clock. No action on rising edge. */ last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, last_outclk+1); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); ASSERT_NO_CAPTURE(); ASSERT_CCI_LOW(); ASSERT_CLOCK_HIGH(); /* Falling edge does not increment counter but does cause capture */ last_outclk = outclk; HALF_TICK_OUTCLK(); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, last_outclk); BSP430_UNITTEST_ASSERT_EQUAL_FMTx(outclk, timer_hpl->r); ASSERT_YES_CAPTURE(); ASSERT_CCI_LOW(); CLEAR_CAPTURE(); cprintf("%u: Timer: R %04x CTL %04x CCR %04x CCTL %04x\n", __LINE__, timer_hpl->r, timer_hpl->ctl, timer_hpl->ccr[APP_CCIDX], timer_hpl->cctl[APP_CCIDX]); vBSP430unittestFinalize(); }
void main () { int rc; unsigned long uptime_ticks_per_sec; const struct sBSP430onewireBus * bus = &ds18b20; vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); cprintf("\nHere we go...\n"); uptime_ticks_per_sec = ulBSP430uptimeConversionFrequency_Hz_ni(); cprintf("Uptime now %lu with frequency %lu Hz\n", ulBSP430uptime_ni(), uptime_ticks_per_sec); cprintf("Monitoring DS18xx on %s.%u bit %x\n", xBSP430portName(BSP430_PORT_HAL_GET_PERIPH_HANDLE(APP_DS18B20_PORT_HAL)) ?: "P?", iBSP430portBitPosition(APP_DS18B20_BIT), APP_DS18B20_BIT); do { rc = iBSP430onewireReadSerialNumber(bus, &serial); if (0 != rc) { cprintf("ERROR: Failed to read serial number from DS18B20: %d\n", rc); BSP430_CORE_DELAY_CYCLES(BSP430_CLOCK_NOMINAL_MCLK_HZ); } } while (0 != rc); cprintf("DS18B20 serial number: %02x%02x%02x%02x%02x%02x\n", serial.id[0], serial.id[1], serial.id[2], serial.id[3], serial.id[4], serial.id[5]); while (1) { int rc; unsigned long start_tck; unsigned long end_tck; unsigned int duration_ms; unsigned int delay_count = 0; int t_c; start_tck = ulBSP430uptime_ni(); rc = -1; if (0 == iBSP430onewireRequestTemperature_ni(bus)) { /* Wait for read to complete. Each read is nominally 61 * microseconds. Conversion time can be as long as 750 ms if * 12-bit resolution is used. (12-bit resolution is the * default.) */ while (! iBSP430onewireReadBit_ni(bus)) { ++delay_count; } rc = iBSP430onewireReadTemperature_ni(bus, &t_c); } end_tck = ulBSP430uptime_ni(); duration_ms = 1000 * (end_tck - start_tck) / uptime_ticks_per_sec; if (0 == rc) { cprintf("Temperature %d dCel or %d d[degF] in %u ms\n", (10 * t_c) / 16, BSP430_ONEWIRE_xCel_TO_ddegF(t_c), duration_ms); } else { cprintf("Measurement failed in %u ms\n", duration_ms); } /* You'd want to do this if you were going to sleep here */ vBSP430onewireShutdown_ni(bus); } }
void main () { volatile sBSP430hplTIMER * const hpl = xBSP430hplLookupTIMER(BSP430_PERIPH_TA0); unsigned long ta0_Hz; unsigned int delta_ta0; const struct sLPMconfig * lcp = lpm_configs; const struct sLPMconfig * const elcp = lpm_configs + sizeof(lpm_configs)/sizeof(*lpm_configs); vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); TA0CTL = TASSEL_1 | MC_2 | TACLR; ta0_Hz = ulBSP430timerFrequency_Hz_ni(BSP430_PERIPH_TA0); #if 0 /* This sequence eliminates the wakeup delay on the MSP430F5438A. * The ramifications of doing this are to be found in the Power * Management Module and Supply Voltage Supervisor chapter of the * 5xx/6xx Family User's Guide, in the section "SVS and SVM * Performance Modes and Wakeup Times". * * Also check MCU errata related to the PMM. THere are several that * appear relevant when changing the module from its power-up * state. */ PMMCTL0_H = PMMPW_H; #if 1 /* This variant works */ SVSMLCTL &= ~(SVSLE | SVMLE); #else /* This appears to have no effect, though it should work. */ SVSMLCTL |= SVSLFP; #endif PMMCTL0_H = !PMMPW_H; #endif BSP430_CORE_ENABLE_INTERRUPT(); cputs("\n\nTimer LPM wake delay test\n"); delta_ta0 = ta0_Hz / 4; cprintf("TA0 is at %lu Hz; sleep time %u ticks\n", ta0_Hz, delta_ta0); cprintf("Standard mode SR is %04x\n", __read_status_register()); cprintf("SR bits: SCG0 %04x ; SCG1 %04x\n", SCG0, SCG1); cprintf("LPM exit from ISRs clears: %04x\n", BSP430_CORE_LPM_EXIT_MASK); cputs("LPMx CCR0 CAP0 Delta0 CCR1 CAP1 Delta1 SR"); while (lcp < elcp) { unsigned int tar; cprintf("%s: ", lcp->tag); BSP430_CORE_DISABLE_INTERRUPT(); ta0r = 0; hpl->cctl[0] = CCIE; tar = uiBSP430timerAsyncCounterRead_ni(hpl); hpl->ccr[0] = tar + delta_ta0; BSP430_CORE_LPM_ENTER_NI(lcp->lpm_bits); cprintf("%5u %5u %5u ", hpl->ccr[0], ta0r, ta0r-hpl->ccr[0]); BSP430_CORE_DISABLE_INTERRUPT(); ta0r = 0; hpl->cctl[1] = CCIE; tar = uiBSP430timerAsyncCounterRead_ni(hpl); hpl->ccr[1] = tar + delta_ta0; BSP430_CORE_LPM_ENTER_NI(lcp->lpm_bits); cprintf("%5u %5u %5u ", hpl->ccr[1], ta0r, ta0r-hpl->ccr[1]); cprintf("%04x\n", __read_status_register()); ++lcp; } cprintf("Done\n"); }
void main () { int rc; unsigned long next_wake_utt; unsigned long delta_wake_utt; vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); cprintf("\n\nadc demo, " __DATE__ " " __TIME__ "\n"); delta_wake_utt = 2 * ulBSP430uptimeConversionFrequency_Hz(); rc = initializeADC(); cprintf("%s initialized, returned %d, ADC cal at %p, REF cal at %p\n", #if defined(__MSP430_HAS_ADC10__) "ADC10" #elif defined(__MSP430_HAS_ADC10_A__) "ADC10_A" #elif defined(__MSP430_HAS_ADC10_B__) "ADC10_B" #elif defined(__MSP430_HAS_ADC10_B4__) "ADC10_B (FR4xx)" #elif defined(__MSP430_HAS_ADC12__) "ADC12" #elif defined(__MSP430_HAS_ADC12_B__) "ADC12_B" #elif defined(__MSP430_HAS_ADC12_PLUS__) "ADC12_PLUS" #endif /* ADC */ , rc, cal_adc, cal_ref); #if HAVE_REF if (cal_ref) { cprintf("Reference factors:\n" "\t" REF_1pX_STR "V %u (0x%04x)\n" "\t2.0V %u (0x%04x)\n" "\t2.5V %u (0x%04x)\n", cal_ref->cal_adc_15vref_factor, cal_ref->cal_adc_15vref_factor, cal_ref->cal_adc_20vref_factor, cal_ref->cal_adc_20vref_factor, cal_ref->cal_adc_25vref_factor, cal_ref->cal_adc_25vref_factor); } #endif /* HAVE_REF */ if (cal_adc) { cprintf("ADC gain factor %d (0x%04x), offset %d\n", cal_adc->cal_adc_gain_factor, cal_adc->cal_adc_gain_factor, cal_adc->cal_adc_offset); cprintf("Temperature ranges:\n"); cprintf("\t" REF_1pX_STR "V T30 %u T85 %u\n", cal_adc->cal_adc_15t30, cal_adc->cal_adc_15t85); #if BSP430_TLV_IS_5XX cprintf("\t2.0V T30 %u T85 %u\n", cal_adc->cal_adc_20t30, cal_adc->cal_adc_20t85); #endif /* BSP430_TLV_IS_5XX */ cprintf("\t2.5V T30 %u T85 %u\n", cal_adc->cal_adc_25t30, cal_adc->cal_adc_25t85); } cprintf("Vmid channel %u, Temp channel %u" #ifdef INCH_AUX ", Aux channel %u" #endif /* INCH_AUX */ "\n", INCH_VMID / INCH_BASE, INCH_TEMP / INCH_BASE #ifdef INCH_AUX , INCH_AUX / INCH_BASE #endif /* INCH_AUX */ ); next_wake_utt = ulBSP430uptime_ni(); while (1) { char timestamp[BSP430_UPTIME_AS_TEXT_LENGTH]; static const int refv[] = { REF_1pX, REF_2p0, REF_2p5 }; static const char * const refv_str[] = { REF_1pX_STR, "2.0", "2.5" }; static const int const nrefv = sizeof(refv)/sizeof(*refv); static const int inch[] = { INCH_TEMP, INCH_VMID, #if defined(INCH_AUX) INCH_AUX, #endif /* INCH_AUX */ }; static const int const ninch = sizeof(inch)/sizeof(*inch); int valid = 0; sSample sample[sizeof(refv)/sizeof(*refv)][sizeof(inch)/sizeof(*inch)]; int ri; int ii; #define VALID(_ri,_ii) ((1 << (_ii)) << ((_ri) * nrefv)) #define ANY_VALID(_ri) (((1 << nrefv)-1) << ((_ri) * nrefv)) for (ri = 0; ri < nrefv; ++ri) { if (0 == setReferenceVoltage(refv[ri])) { for (ii = 0; ii < ninch; ++ii) { if (0 == getSample(sample[ri]+ii, refv[ri], inch[ii])) { valid |= VALID(ri, ii); } } } } cprintf("%s: valid %x", xBSP430uptimeAsText(ulBSP430uptime_ni(), timestamp), valid); for (ri = 0; ri < nrefv; ++ri) { if (valid & ANY_VALID(ri)) { cprintf("\n\t%sV: ", refv_str[ri]); for (ii = 0; ii < ninch; ++ii) { if (VALID(ri, ii) & valid) { if (INCH_TEMP == inch[ii]) { displayTemperature(sample[ri] + ii); } else if (INCH_VMID == inch[ii]) { displayVmid(sample[ri] + ii); } else { displayVoltage(sample[ri] + ii); } } } } } cputchar('\n'); next_wake_utt += delta_wake_utt; while (0 < lBSP430uptimeSleepUntil(next_wake_utt, LPM3_bits)) { /* nop */ } } }
void main () { volatile sBSP430hplPORTIE * b0hpl; hBSP430halTIMER b0timer_hal; int b0pin = iBSP430portBitPosition(BSP430_PLATFORM_BUTTON0_PORT_BIT); struct sBSP430timerPulseCapture pulsecap_state; hBSP430timerPulseCapture pulsecap; unsigned long freq_Hz; int rc; vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); cprintf("\npulsecap " __DATE__ " " __TIME__ "\n"); cprintf("There's supposed to be a button at %s.%u\n", xBSP430portName(BSP430_PLATFORM_BUTTON0_PORT_PERIPH_HANDLE), b0pin); b0hpl = xBSP430hplLookupPORTIE(BSP430_PLATFORM_BUTTON0_PORT_PERIPH_HANDLE); if (NULL == b0hpl) { cprintf("Guess it's not there. Never mind.\n"); return; } cprintf("Found it at %p. Now looking for timer HAL.\n", b0hpl); b0timer_hal = hBSP430timerLookup(BUTTON0_TIMER_PERIPH_HANDLE); if (NULL == b0timer_hal) { cprintf("That's not there, though. Going away now.\n"); return; } vBSP430timerResetCounter_ni(b0timer_hal); b0timer_hal->hpl->ctl = TASSEL__SMCLK | MC__CONTINOUS | TBCLR | TBIE; vBSP430timerInferHints_ni(b0timer_hal); freq_Hz = ulBSP430timerFrequency_Hz_ni(BUTTON0_TIMER_PERIPH_HANDLE); cprintf("Cool, we're good to go with a %lu Hz timer at %p, now %lu.\n", freq_Hz, b0timer_hal, ulBSP430timerCounter_ni(b0timer_hal, NULL)); /* Configure the port for its primary peripheral function */ b0hpl->dir &= ~BSP430_PLATFORM_BUTTON0_PORT_BIT; BSP430_PORT_HPL_SET_REN(b0hpl, BSP430_PLATFORM_BUTTON0_PORT_BIT, BSP430_PORT_REN_PULL_UP); BSP430_PORT_HPL_SET_SEL(b0hpl, BSP430_PLATFORM_BUTTON0_PORT_BIT, 1); pulsecap = hBSP430timerPulseCaptureInitialize(&pulsecap_state, BUTTON0_TIMER_PERIPH_HANDLE, BUTTON0_TIMER_CCIDX, BUTTON0_TIMER_CCIS, BSP430_TIMER_PULSECAP_START_CALLBACK | BSP430_TIMER_PULSECAP_END_CALLBACK, pulsecap_callback_ni); if (NULL == pulsecap) { cprintf("Sorry, pulsecap initialization failed\n"); return; } cprintf("%s.%u%c cctl %04x; pulsecap %p flags %04x\n", xBSP430timerName(BUTTON0_TIMER_PERIPH_HANDLE), BUTTON0_TIMER_CCIDX, 'A' + (BUTTON0_TIMER_CCIS / CCIS0), b0timer_hal->hpl->cctl[BUTTON0_TIMER_CCIDX], pulsecap, pulsecap->flags_ni); /* Need to enable interrupts so timer overflow events are properly * acknowledged */ BSP430_CORE_ENABLE_INTERRUPT(); rc = iBSP430timerPulseCaptureEnable(pulsecap); cprintf("Enable got %d\n", rc); rc = iBSP430timerPulseCaptureActivate(pulsecap); cprintf("Activate got %d\n", rc); while (1) { unsigned int flags; unsigned long pulseWidth_tt; unsigned int overflows; unsigned int activehighs; BSP430_CORE_DISABLE_INTERRUPT(); do { flags = pulsecap_state.flags_ni; pulseWidth_tt = pulseWidth_tt_v; overflows = overflows_v; activehighs = activehighs_v; } while (0); BSP430_CORE_ENABLE_INTERRUPT(); cprintf("Timer %lu flags %04x ; %u over %u activehigh\n", ulBSP430timerCounter(b0timer_hal, NULL), flags, overflows, activehighs); if (0 != pulseWidth_tt) { cprintf("\tNew width: %lu ticks = %lu us\n", pulseWidth_tt, (unsigned long)((1000ULL * pulseWidth_tt) / (freq_Hz / 1000UL))); pulseWidth_tt = 0; } BSP430_CORE_DELAY_CYCLES(BSP430_CLOCK_NOMINAL_MCLK_HZ); } }
void main () { /* First thing you do in main is configure the platform. */ vBSP430platformInitialize_ni(); /* And that's all this one does. */ }
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 () { const char * command; int flags; vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); vBSP430cliSetDiagnosticFunction(iBSP430cliConsoleDiagnostic); cprintf("\ncli example " __DATE__ " " __TIME__ "\n"); #if configBSP430_CLI_COMMAND_COMPLETION - 0 cprintf("Command completion is available.\n"); #endif /* configBSP430_CLI_COMMAND_COMPLETION */ vBSP430ledSet(0, 1); cprintf("\nLED lit when not awaiting input\n"); /* NOTE: The control flow in this is a bit tricky, as we're trying * to leave interrupts enabled during the main body of the loop, * while they must be disabled when processing input to recognize a * command. The flags variable preserves state across multiple loop * iterations until all relevant activities have completed. */ commandSet = LAST_COMMAND; command = NULL; flags = eBSP430cliConsole_REPAINT; BSP430_CORE_ENABLE_INTERRUPT(); while (1) { if (flags & eBSP430cliConsole_ANY_ESCAPE) { int c; while (0 <= ((c = cgetchar()))) { cprintf("escape char 0x%02x (%u) '%c'\n", c, c, isprint(c) ? c : '.'); /* Technically CSI is a single character 0x9b representing * ESC+[. In the two-character mode accepted here, we use the * value for the second character. */ #define KEY_CSI '[' if ((KEY_CSI == c) && (flags & eBSP430cliConsole_PROCESS_ESCAPE)) { flags &= ~eBSP430cliConsole_PROCESS_ESCAPE; flags |= eBSP430cliConsole_IN_ESCAPE; } else if ((64 <= c) && (c <= 126)) { flags &= ~eBSP430cliConsole_ANY_ESCAPE; cprintf("Leaving escape mode\n"); break; } } } if (flags & eBSP430cliConsole_DO_COMPLETION) { flags &= ~eBSP430cliConsole_DO_COMPLETION; flags |= iBSP430cliConsoleBufferCompletion(commandSet, &command); } if (flags & eBSP430cliConsole_READY) { int rv; rv = iBSP430cliExecuteCommand(commandSet, 0, command); if (0 != rv) { cprintf("Command execution returned %d\n", rv); } /* Ensure prompt is rewritten, but not the command we just * ran */ flags |= eBSP430cliConsole_REPAINT; command = NULL; } if (flags & eBSP430cliConsole_REPAINT) { /* Draw the prompt along with whatever's left in the command * buffer. Note use of leading carriage return in case an edit * left material on the current line. */ cprintf("\r> %s", command ? command : ""); flags &= ~eBSP430cliConsole_REPAINT; } if (flags & eBSP430cliConsole_REPAINT_BEL) { cputchar('\a'); flags &= ~eBSP430cliConsole_REPAINT_BEL; } BSP430_CORE_DISABLE_INTERRUPT(); do { if (flags & eBSP430cliConsole_READY) { /* Clear the command we just completed */ vBSP430cliConsoleBufferClear_ni(); flags &= ~eBSP430cliConsole_READY; } do { /* Unless we're processing application-specific escape * characters let iBSP430cliConsoleBufferProcessInput_ni() * process any input characters that have already been * received. */ if (! (flags & eBSP430cliConsole_ANY_ESCAPE)) { flags |= iBSP430cliConsoleBufferProcessInput_ni(); } if (0 == flags) { /* Sleep until something wakes us, such as console input. * Then turn off interrupts and loop back to read that * input. */ vBSP430ledSet(0, 0); BSP430_CORE_LPM_ENTER_NI(LPM0_bits); BSP430_CORE_DISABLE_INTERRUPT(); vBSP430ledSet(0, 1); } /* Repeat if still nothing to do */ } while (! flags); /* Got something to do; get the command contents in place so * we can update the screen. */ command = xBSP430cliConsoleBuffer_ni(); } while (0); BSP430_CORE_ENABLE_INTERRUPT(); } }
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 () { hBSP430halSERIAL i2c = hBSP430serialLookup(APP_TMP102_I2C_PERIPH_HANDLE); uint8_t pr = 0; vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); cprintf("I2C interface on %s is %p\n", xBSP430serialName(APP_TMP102_I2C_PERIPH_HANDLE), i2c); #if BSP430_PLATFORM_PERIPHERAL_HELP cprintf("TMP102 I2C Pins: %s\n", xBSP430platformPeripheralHelp(APP_TMP102_I2C_PERIPH_HANDLE, BSP430_PERIPHCFG_SERIAL_I2C)); #endif /* BSP430_PLATFORM_PERIPHERAL_HELP */ i2c = hBSP430serialOpenI2C(i2c, BSP430_SERIAL_ADJUST_CTL0_INITIALIZER(UCMST), 0, 0); if (! i2c) { cprintf("I2C open failed.\n"); return; } (void)iBSP430i2cSetAddresses_ni(i2c, -1, APP_TMP102_I2C_ADDRESS); /** Raw number is a 16 bit value. First 12 bits represent the * temperature as a count of 0.0625C values. (If the LSB is 1, then * an extended temperature is used and the 13th bit represents a * half count.) 0.625 = 5/8; shifting by 3 gets us the 13-bit * value; dividing by 2 accounts for the half-count in extended * temperature mode. */ #define TMP102_RAW_TO_dC_(raw_) (5 * ((raw_) >> 3) / 16) #define TMP102_RAW_TO_dC(raw_) ((0 <= (int)(raw_)) ? TMP102_RAW_TO_dC_(raw_) : -TMP102_RAW_TO_dC_(-(int)(raw_))) #define dC_TO_dF(dC_) (320 + 9 * (dC_) / 5) #if 0 { unsigned int data[] = { 0x7FF0, 0x4B00, 0x1900, 0xFFC0, 0xE700, 0xC908 }; int i; for (i = 0; i < sizeof(data)/sizeof(*data); ++i) { int temp_dC = TMP102_RAW_TO_dC(data[i]); cprintf("temp 0x%04x = %d dC = %d d[degF]\n", data[i], temp_dC, dC_TO_dF(temp_dC)); } } #endif while (1) { int rc; uint8_t data[2]; uint16_t raw; rc = iBSP430i2cTxData_ni(i2c, &pr, 1); if (0 > rc) { cprintf("I2C TX ERROR\n"); break; } memset(data, 0, sizeof(data)); rc = iBSP430i2cRxData_ni(i2c, data, sizeof(data)); if (0 > rc) { cprintf("I2C RX ERROR\n"); break; } raw = data[1] | (data[0] << 8); if (0 == pr) { int temp_dC = TMP102_RAW_TO_dC(raw); cprintf("temp 0x%04x = %d dC = %d d[degF]\n", raw, temp_dC, dC_TO_dF(temp_dC)); } else { cprintf("reg %d is 0x%04x\n", pr, raw); } pr = (pr + 1) & 0x03; BSP430_CORE_DELAY_CYCLES(BSP430_CLOCK_NOMINAL_MCLK_HZ); } }
void main () { #if (BSP430_CONSOLE - 0) const char * help; unsigned long smclk_Hz; unsigned long aclk_Hz; #endif /* BSP430_CONSOLE */ /* First thing you do in main is configure the platform. */ vBSP430platformInitialize_ni(); /* If we support a console, dump out a bunch of configuration * information. */ #if (BSP430_CONSOLE - 0) (void)iBSP430consoleInitialize(); cputtext("\nclocks " __DATE__ " " __TIME__ "\n"); cputtext("\nBSP430_PLATFORM_BOOT_CONFIGURE_LFXT1: "); cputu(BSP430_PLATFORM_BOOT_CONFIGURE_LFXT1, 10); cputtext("\nBSP430_CLOCK_LFXT1_STABILIZATION_DELAY_CYCLES: "); cputul(BSP430_CLOCK_LFXT1_STABILIZATION_DELAY_CYCLES, 10); cputtext("\nBSP430_PLATFORM_BOOT_LFXT1_DELAY_SEC: "); cputu(BSP430_PLATFORM_BOOT_LFXT1_DELAY_SEC, 10); cputtext("\nBSP430_PLATFORM_BOOT_CONFIGURE_CLOCKS: "); cputu(BSP430_PLATFORM_BOOT_CONFIGURE_CLOCKS, 10); #if defined(__MSP430_HAS_BC2__) #if (configBSP430_BC2_TRIM_TO_MCLK - 0) cputtext("\nconfigBSP430_BC2_TRIM_TO_MCLK: 1"); #else /* configBSP430_BC2_TRIM_TO_MCLK */ cputtext("\nconfigBSP430_BC2_TRIM_TO_MCLK: 0"); #endif /* configBSP430_BC2_TRIM_TO_MCLK */ #if (BSP430_BC2_TRIM_TO_MCLK - 0) cputtext("\nBSP430_BC2_TRIM_TO_MCLK: 1"); #else /* BSP430_BC2_TRIM_TO_MCLK */ cputtext("\nBSP430_BC2_TRIM_TO_MCLK: 0"); #endif /* BSP430_BC2_TRIM_TO_MCLK */ #endif /* BC2 */ #if defined(__MSP430_HAS_UCS__) || defined(__MSP430_HAS_UCS_RF__) #if (configBSP430_UCS_TRIM_DCOCLKDIV - 0) cputtext("\nconfigBSP430_UCS_TRIM_DCOCLKDIV: 1"); #else /* configBSP430_UCS_TRIM_DCOCLKDIV */ cputtext("\nconfigBSP430_UCS_TRIM_DCOCLKDIV: 0"); #endif /* configBSP430_UCS_TRIM_DCOCLKDIV */ #if (BSP430_UCS_TRIM_DCOCLKDIV - 0) cputtext("\nBSP430_UCS_TRIM_DCOCLKDIV: 1"); #else /* BSP430_UCS_TRIM_DCOCLKDIV */ cputtext("\nBSP430_UCS_TRIM_DCOCLKDIV: 0"); #endif /* BSP430_UCS_TRIM_DCOCLKDIV */ #endif /* UCS */ cputtext("\nBSP430_CLOCK_PUC_MCLK_HZ: "); cputul(BSP430_CLOCK_PUC_MCLK_HZ, 10); cputtext("\nBSP430_CLOCK_NOMINAL_MCLK_HZ: "); cputul(BSP430_CLOCK_NOMINAL_MCLK_HZ, 10); cputtext("\nBSP430_CLOCK_LFXT1_IS_FAULTED_NI(): "); cputu(BSP430_CLOCK_LFXT1_IS_FAULTED_NI(), 10); cputtext("\nBSP430_CLOCK_NOMINAL_VLOCLK_HZ: "); cputu(BSP430_CLOCK_NOMINAL_VLOCLK_HZ, 10); cputtext("\nBSP430_CLOCK_NOMINAL_XT1CLK_HZ: "); cputul(BSP430_CLOCK_NOMINAL_XT1CLK_HZ, 10); #if defined(BSP430_CLOCK_NOMINAL_XT2CLK_HZ) cputtext("\nBSP430_PLATFORM_BOOT_CONFIGURE_XT2: "); cputu(BSP430_PLATFORM_BOOT_CONFIGURE_XT2, 10); cputtext("\nBSP430_CLOCK_XT2_IS_FAULTED_NI(): "); cputu(BSP430_CLOCK_XT2_IS_FAULTED_NI(), 10); cputtext("\nBSP430_CLOCK_NOMINAL_XT2CLK_HZ: "); cputul(BSP430_CLOCK_NOMINAL_XT2CLK_HZ, 10); #endif /* BSP430_CLOCK_NOMINAL_XT2CLK_HZ */ cputtext("\nulBSP430clockMCLK_Hz_ni(): "); cputul(ulBSP430clockMCLK_Hz_ni(), 10); cputtext("\nBSP430_PLATFORM_BOOT_SMCLK_DIVIDING_SHIFT: "); cputi(BSP430_PLATFORM_BOOT_SMCLK_DIVIDING_SHIFT, 10); cputtext("\nulBSP430clockSMCLK_Hz_ni(): "); smclk_Hz = ulBSP430clockSMCLK_Hz_ni(); cputul(smclk_Hz, 10); cputtext("\nBSP430_PLATFORM_BOOT_ACLK_DIVIDING_SHIFT: "); cputi(BSP430_PLATFORM_BOOT_ACLK_DIVIDING_SHIFT, 10); cputtext("\nulBSP430clockACLK_Hz_ni(): "); aclk_Hz = ulBSP430clockACLK_Hz_ni(); cputul(aclk_Hz, 10); #if (BSP430_TIMER_CCACLK - 0) if (1000000UL <= aclk_Hz) { cputtext("\nUnable to use high-speed ACLK for differential timing of SMCLK"); } else { do { const unsigned int SAMPLE_PERIOD_ACLK = 10; volatile sBSP430hplTIMER * tp = xBSP430hplLookupTIMER(BSP430_TIMER_CCACLK_PERIPH_HANDLE); unsigned int cc_delta; unsigned long aclk_rel_smclk_Hz; unsigned long smclk_rel_aclk_Hz; if (! tp) { cputtext("\nUnable to access configured CCACLK timer"); break; } /* Capture the SMCLK ticks between adjacent ACLK ticks */ tp->ctl = TASSEL_2 | MC_2 | TACLR; cc_delta = uiBSP430timerCaptureDelta_ni(BSP430_TIMER_CCACLK_PERIPH_HANDLE, BSP430_TIMER_CCACLK_ACLK_CCIDX, CM_2, BSP430_TIMER_CCACLK_ACLK_CCIS, SAMPLE_PERIOD_ACLK); tp->ctl = 0; if (-1 == cc_delta) { cputtext("\nCCACLK measurement failed"); break; } cputchar('\n'); cputu(SAMPLE_PERIOD_ACLK, 10); cputtext(" ticks of ACLK produced "); cputu(cc_delta, 10); cputtext(" ticks of SMCLK"); cputtext("\nComparison with measured values:"); cputtext("\n SMCLK (Hz) (if measured ACLK correct): "); smclk_rel_aclk_Hz = (cc_delta * aclk_Hz) / SAMPLE_PERIOD_ACLK; cputul(smclk_rel_aclk_Hz, 10); cputtext(" (error "); cputl(smclk_rel_aclk_Hz - smclk_Hz, 10); cputtext(" = "); cputl(1000 * labs(smclk_rel_aclk_Hz - smclk_Hz) / smclk_Hz, 10); cputtext(" kHz/MHz)"); cputtext("\n ACLK (Hz) (if measured SMCLK correct): "); aclk_rel_smclk_Hz = SAMPLE_PERIOD_ACLK * smclk_Hz / cc_delta; cputul(aclk_rel_smclk_Hz, 10); cputtext(" (error "); cputl(aclk_rel_smclk_Hz - aclk_Hz, 10); cputtext(" = "); cputl(1000 * labs(aclk_rel_smclk_Hz - aclk_Hz) / aclk_Hz, 10); cputtext(" Hz/kHz)"); } while (0); } #else /* BSP430_TIMER_CCACLK */ cputtext("\nNo CCACLK timer available for ACLK/SMCLK comparison"); #endif /* BSP430_TIMER_CCACLK */ cputchar('\n'); #if defined(__MSP430_HAS_BC2__) cputtext("\nBC2: DCO "); cputu(DCOCTL, 16); cputtext(" CTL1 "); cputu(BCSCTL1, 16); cputtext(" CTL2 "); cputu(BCSCTL2, 16); cputtext(" CTL3 "); cputu(BCSCTL3, 16); #endif #if defined(__MSP430_HAS_FLL__) || defined(__MSP430_HAS_FLLPLUS__) cprintf("\nFLL: SCF QCTL %02x I0 %02x I1 %02x ; CTL0 %02x CTL1 %02x CTL2 %02x\n", SCFQCTL, SCFI0, SCFI1, FLL_CTL0, FLL_CTL1, #if defined(FLL_CTL2_) FLL_CTL2 #else /* FLL_CTL2 */ ~0 #endif /* FLL_CTL2 */ ); #endif /* FLL/PLUS */ #if defined(__MSP430_HAS_UCS__) || defined(__MSP430_HAS_UCS_RF__) cputtext("\nBSP430_UCS_FLL_SELREF: " #if SELREF__XT2CLK <= BSP430_UCS_FLL_SELREF "XT2CLK" #elif SELREF__REFOCLK <= BSP430_UCS_FLL_SELREF "REFOCLK" #else /* BSP430_UCS_FLL_SELREF */ "XT1CLK" #endif /* BSP430_UCS_FLL_SELREF */ ); cprintf("\nUCS RSEL %d DCO %d MOD %d:" "\n CTL0 %04x CTL1 %04x CTL2 %04x CTL3 %04x" "\n CTL4 %04x CTL5 %04x CTL6 %04x CTL7 %04x", 0x1F & (UCSCTL1 / DCORSEL0), 0x1F & (UCSCTL0 / DCO0), 0x1F & (UCSCTL0 / MOD0), UCSCTL0, UCSCTL1, UCSCTL2, UCSCTL3, UCSCTL4, UCSCTL5, UCSCTL6, UCSCTL7); #endif /* UCS */ #if defined(__MSP430_HAS_CS__) || defined(__MSP430_HAS_CS_A__) cprintf("\nCS %s : RSEL %d DCOFSEL %d:" "\n CTL0 %04x CTL1 %04x CTL2 %04x CTL3 %04x" "\n CTL4 %04x CTL5 %04x CTL6 %04x" "\n FRCTL0 %04x", #if (BSP430_CS_IS_FR57XX - 0) "FR57xx" #endif #if (BSP430_CS_IS_FR58XX - 0) "FR58xx" #endif "", !!(DCORSEL & CSCTL1), 0x07 & (CSCTL1 / DCOFSEL0), CSCTL0, CSCTL1, CSCTL2, CSCTL3, CSCTL4, CSCTL5, CSCTL6, FRCTL0); #endif /* CS */ #endif /* BSP430_CONSOLE */ if (0 == iBSP430platformConfigurePeripheralPins_ni(BSP430_PERIPH_EXPOSED_CLOCKS, 0, 1)) { #if (BSP430_CONSOLE - 0) cputtext("\n\nClock signals exposed:\n "); help = NULL; #ifdef BSP430_PLATFORM_PERIPHERAL_HELP help = xBSP430platformPeripheralHelp(BSP430_PERIPH_EXPOSED_CLOCKS, 0); #endif /* BSP430_PLATFORM_PERIPHERAL_HELP */ if (NULL == help) { help = "Go look at the data sheet and source, because nobody told me where they are"; } cputtext(help); cputtext("\nStatus register LPM bits: "); cputu(__read_status_register() & BSP430_CORE_LPM_SR_MASK, 16); cputtext("\nIFG1 bits: "); #if defined(__MSP430_HAS_MSP430XV2_CPU__) cputu(SFRIFG1, 16); #else /* CPUX */ cputu(IFG1, 16); #endif /* CPUX */ cputtext(" with OFIFG "); cputu(OFIFG, 16); cputchar('\n'); #endif /* BSP430_CONSOLE */ /* Spin here with CPU active. In LPM0, MCLK is disabled. Other * clocks get disabled at deeper sleep modes; if you fall off the * bottom, you might end up in LPM4 with all clocks disabled. */ while (1) { vBSP430ledSet(0, -1); BSP430_CORE_WATCHDOG_CLEAR(); BSP430_CORE_DELAY_CYCLES(BSP430_CLOCK_NOMINAL_MCLK_HZ / 2); } } else { #if (BSP430_CONSOLE - 0) cputtext("\nFailed to expose clock signals\n"); #endif /* BSP430_CONSOLE */ } }
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"); }