int console_tx_queue_ni (hBSP430halSERIAL uart, uint8_t c) { sConsoleTxBuffer * bufp = &tx_buffer_; while (1) { unsigned char head = bufp->head; unsigned char next_head = (head + 1) % (sizeof(bufp->buffer)/sizeof(*bufp->buffer)); if (next_head == bufp->tail) { if (0 == bufp->wake_available) { bufp->wake_available = 1; } BSP430_CORE_LPM_ENTER_NI(LPM0_bits | GIE); BSP430_CORE_DISABLE_INTERRUPT(); continue; } bufp->buffer[head] = c; bufp->head = next_head; if (head == bufp->tail) { vBSP430serialWakeupTransmit_ni(uart); } break; } return c; }
int iBSP430consoleWaitForTxSpace_ni (int want_available) { int rv = 0; #if BSP430_CONSOLE_TX_BUFFER_SIZE - 0 if (((int)sizeof(tx_buffer_.buffer) - 1) < want_available) { return -1; } while (1) { int available; unsigned char head = tx_buffer_.head; unsigned char tail = tx_buffer_.tail; if (0 > want_available) { if (head == tail) { break; } } else { available = TX_BUFFER_AVAILABLE_(&tx_buffer_, head, tail); if (available >= want_available) { break; } } if (0 == tx_buffer_.wake_available) { tx_buffer_.wake_available = want_available; } rv = 1; BSP430_CORE_LPM_ENTER_NI(LPM0_bits | GIE); BSP430_CORE_DISABLE_INTERRUPT(); } #endif /* BSP430_CONSOLE_TX_BUFFER_SIZE */ return rv; }
long lBSP430uptimeSleepUntil_ni (unsigned long setting_utt, unsigned int lpm_bits) { int rc; /* Exit immediately unless the alarm callback is registered. */ if (! (DELAY_ALARM_REGISTERED & delayAlarm_.flags)) { return 0; } delayAlarm_.flags &= ~DELAY_ALARM_FIRED; rc = iBSP430timerAlarmSet_ni(H_delayAlarm, setting_utt); if (0 != rc) { return 0; } /* Sleep until the alarm goes off, or something else wakes us up. * Immediately disable the interrupts as that probably was not done * during wakeup. */ BSP430_CORE_LPM_ENTER_NI(lpm_bits); BSP430_CORE_DISABLE_INTERRUPT(); /* Cancel the alarm if it hasn't fired yet. */ if (! (delayAlarm_.flags & DELAY_ALARM_FIRED)) { (void)iBSP430timerAlarmCancel_ni(H_delayAlarm); } return setting_utt - ulBSP430uptime_ni(); }
void main () { WDTCTL = WDTPW | WDTHOLD; #if BSP430_LED - 0 vBSP430ledInitialize_ni(); { int i; vBSP430ledSet(0, 1); for (i = 0; i < 20; ++i) { vBSP430ledSet(0, -1); vBSP430ledSet(1, -1); __delay_cycles(BSP430_CLOCK_PUC_MCLK_HZ / 10); } /* The subsequent vBSP430lpmConfigurePortsForLPM_ni() call should * turn off the LED that's still lit. */ } #endif vBSP430lpmConfigurePortsForLPM_ni(); __delay_cycles(BSP430_CLOCK_PUC_MCLK_HZ); while (1) { #if (0 <= APP_LPM) && (APP_LPM <= 4) BSP430_CORE_LPM_ENTER_NI(lpm_bits[APP_LPM]); /* For this application it doesn't matter that GIE is now set */ #endif } }
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 () { 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 () { 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 () { 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"); }