Example #1
0
int
iBSP430bc2TrimToMCLK_ni (unsigned long mclk_Hz)
{
  volatile sBSP430hplTIMER * tp = xBSP430hplLookupTIMER(BSP430_TIMER_CCACLK_PERIPH_HANDLE);
  const int MAX_ITERATIONS = 16 * 256;
  int rv = -1;
  unsigned long aclk_Hz;
  int iter = 0;
  const int SAMPLE_PERIOD_ACLK = 10;
  unsigned char bcsctl3;
  unsigned int target_tsp;

  if (! tp) {
    return -1;
  }

  bcsctl3 = BCSCTL3;
  if (0 != iBSP430clockConfigureACLK_ni(eBSP430clockSRC_XT1CLK_OR_VLOCLK)) {
    return -1;
  }
  aclk_Hz = ulBSP430clockACLK_Hz_ni();
  target_tsp = (SAMPLE_PERIOD_ACLK * mclk_Hz) / aclk_Hz;
  tp->ctl = TASSEL_2 | MC_2 | TACLR;
  /* SELM = DCOCLK; DIVM = /1 */
  BCSCTL2 &= ~(SELM_MASK | DIVM_MASK);
  while (iter++ < MAX_ITERATIONS) {
    unsigned int freq_tsp;
    freq_tsp = uiBSP430timerCaptureDelta_ni(BSP430_TIMER_CCACLK_PERIPH_HANDLE,
                                            BSP430_TIMER_CCACLK_ACLK_CCIDX,
                                            CM_2,
                                            BSP430_TIMER_CCACLK_ACLK_CCIS,
                                            SAMPLE_PERIOD_ACLK);
    if (freq_tsp == target_tsp) {
      configuredMCLK_Hz = mclk_Hz;
      rv = 0;
      break;
    }
    if (target_tsp < freq_tsp) {
      /* DCO too fast.  Decrement modulator; if underflowed,
       * decrement RSEL */
      if (0xFF == --DCOCTL) {
        --BCSCTL1;
      }
    } else {
      /* DCO too slow.  Increment modulator; if overflowed,
       * increment RSEL */
      if (0 == ++DCOCTL) {
        ++BCSCTL1;
      }
    }
  }
  tp->ctl = 0;
  BCSCTL3 = bcsctl3;
  return rv;
}
Example #2
0
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 */
  }
}
Example #3
0
  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;
  }

  /* Initialize the state information used in the HH10D ISR */
  hh10d.freq_timer = xBSP430hplLookupTIMER(APP_HH10D_TIMER_PERIPH_HANDLE);
  hh10d.uptime_ccidx = APP_HH10D_UPTIME_CC_INDEX;
  uptime_Hz = ulBSP430uptimeConversionFrequency_Hz_ni();
  hh10d.sample_duration_utt = uptime_Hz;

  cprintf("HH10D I2C on %s at %p, bus rate %lu Hz, address 0x%02x\n",
          xBSP430serialName(APP_HH10D_I2C_PERIPH_HANDLE) ?: "UNKNOWN",
          i2c, ulBSP430clockSMCLK_Hz_ni() / APP_HH10D_I2C_PRESCALER,
          APP_HH10D_I2C_ADDRESS);
#if BSP430_PLATFORM_PERIPHERAL_HELP
  cprintf("HH10D I2C Pins: %s\n", xBSP430platformPeripheralHelp(APP_HH10D_I2C_PERIPH_HANDLE, BSP430_PERIPHCFG_SERIAL_I2C));
#endif /* BSP430_PLATFORM_PERIPHERAL_HELP */
  cprintf("Monitoring HH10D on %s.%u using timer %s\n",
          xBSP430portName(APP_HH10D_PORT_PERIPH_HANDLE) ?: "P?",
          bitToPin(APP_HH10D_PORT_BIT),
          xBSP430timerName(APP_HH10D_TIMER_PERIPH_HANDLE) ?: "T?");
Example #4
0
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();
}
Example #5
0
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");

}