Timer_A

The Timer_A module contained within the MSP432 is capable in operating in three basic modes:

  • Up Mode: The timer counts up from 0 to a specified value, resets to 0, and repeats.

  • Up Down Mode: The timer counts up from 0 to a specific value then counts back down to zero and repeats.

  • Continuous Mode: The timer counts up from 0 to 0xFFFF (65535), resets to 0, and resets.

The DriverLib implementation is built such that each of these modes has an independent configuration path.

The Timer_A module is also capable of performing Capture and Compare operations during operation. A Capture or Compare operation is tied to one of five Capture Compare Registers or CCRns, where n is the CCR register, and may be tied to alternate functionality of a GPIO pin; for example, to produce a Pulse Width Modulated (PWM) output. Each CCR has an two independent input signals: CCInA and CCInB, and a single output signal, labeled OUTn.

Connection of the CCInA, CCInB, and OUTn signals to GPIO pins is discussed Alternate Functions. The signals are named as TAm.CCInA and TAm.n for the CCInA and OUTn signals, respectively, where m is the timer module number.

The first argument for all Timer_A DriverLib functions is the timer module to use: uint32_t timer. The MSP432P401R has 4 Timer_A modules and can be selected using the predefined values TIMER_A0_BASE through TIMER_A3_BASE.

For functions interacting with the CCRn register, the functions require an argument uin16_t captureCompareRegister. This takes the values TIMER_A_CAPTURECOMPARE_REGISTER_X, where X is the CCR number.

Up Mode Configuration

This configuration requires the creation of a Timer_A_UpModeConfig type struct. The table below shows the fields for this configuration struct.

Timer_A_UpModeConfig struct fields

Field

Possible Values

.clockSource

TIMER_A_CLOCKSOURCE_EXTERNAL_TXCLK

TIMER_A_CLOCKSOURCE_ACLK

TIMER_A_CLOCKSOURCE_SMCLK

TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLK

.clockSourceDivider

TIMER_A_CLOCKSOURCE_DIVIDER_X

where X is one of:

1 2 3 4 5 6 7 8 10 12 14

16 20 24 28 32 40 48 56 64

.timerPeriod

0 to 65535

.timerInterruptEnable_TAIE

TIMER_A_TAIE_INTERRUPT_ENABLE

TIMER_A_TAIE_INTERRUPT_DISABLE

.captureCompareInterruptEnable_CCR0_CCIE

TIMER_A_CCIE_CCRO_INTERRUPT_ENABLE

TIMER_A_CCIE_CCRO_INTERRUPT_DISABLE

.timerClear

TIMER_A_DO_CLEAR

TIMER_A_SKIP_CLEAR

Field Descriptions:
  • .clockSource indicates what the timer module should use as its counting base. For the purposes of this course, we will always select the “Low-speed subsystem master clock”, or SMCLK, which is set to be 24 MHz.

  • .clockSourceDivider allows for the selected .clockSource to be “divided” in frequency. For example, if this field was set to TIMER_A_CLOCKSOURCE_DIVIDER_12, the timer would would increment at a rate of 24 MHz / 12 = 2 MHz.

  • .timerPeriod specifies the maximum number that the module will count to before resetting and is of type uint16_t. Since the counter will count from 0 to this number, then the number of timer increments in one full counting cycle .timerPeriod+1. Note that the rate of the increments is determined by both the previous fields.

  • .timerInterruptEnable_TAIE will either enable or disable the Timer_A interrupt: the interrupt generated when the timer resets to 0.

  • .timerInterruptEnable_CCR0_CCIE will either enable or disable the Timer_A CCR0 captureCompare Interrupt: the interrupt generated when the timer reaches the value provided in timerPeriod.

  • .timerClear will cause the current count value, among others, to be reset to 0 upon configuration. It is best to request a timer clear during a (re)configuration such that the timer always starts counting from a known state.

Important

It should be noted that the Timer_A interrupt and Timer_A CCR0 captureCompare Interrupt will trigger only one timer increment apart in Up Mode and using both interrupts would effectively be redundant in most cases. Therefore, it is recommended for this corse that only the Timer_A interrupt be used in Up Mode.

With the configuration struct filled in, the timer can be initialized with the function:

void Timer_A_configureUpMode( uint32_t timer, Timer_A_UpModeConfig * config)

The first argument to this function, uint32_t timer, is the timer module to use (see above). The second argument is the configuration struct as described above. Note that the * within this argument definition indicates that this is passed as a pointer, which is simply done by adding a & before the struct variable name to be passed.

An example usage of this function is provided below, where the required configuration struct (of type Timer_A_UpModeConfig) is created and (partially) populated. The configuration is then applied by the function. The configuration struct must be specified prior to calling Timer_A_configureUpMode; changing the values of the example tmr_cfg after the function has been called will have no effect.

Timer_A_UpModeConfig tmr_cfg;    // Initialize timer configuration struct
tmr_cfg.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; // Set the counting source to SMCLK
tmr_cfg.clockSourceDivider = ...;
... // Configure the rest of the fields within the configuration struct
Timer_A_configureUpMode(TIMER_A3_BASE,&tmr_cfg); // Apply the configuration
... // Start the timer

UpDown Mode Configuration

This configuration requires the creation of a Timer_A_UpDownModeConfig type struct. The table below shows the fields for this configuration struct.

Timer_A_UpDownModeConfig struct fields

Field

Possible Values

.clockSource

TIMER_A_CLOCKSOURCE_EXTERNAL_TXCLK

TIMER_A_CLOCKSOURCE_ACLK

TIMER_A_CLOCKSOURCE_SMCLK

TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLK

.clockSourceDivider

TIMER_A_CLOCKSOURCE_DIVIDER_X

where X is one of:

1 2 3 4 5 6 7 8 10 12 14

16 20 24 28 32 40 48 56 64

.timerPeriod

0 to 65535

.timerInterruptEnable_TAIE

TIMER_A_TAIE_INTERRUPT_ENABLE

TIMER_A_TAIE_INTERRUPT_DISABLE

.captureCompareInterruptEnable_CCR0_CCIE

TIMER_A_CCIE_CCRO_INTERRUPT_ENABLE

TIMER_A_CCIE_CCRO_DISABLE_ENABLE

.timerClear

TIMER_A_DO_CLEAR

TIMER_A_SKIP_CLEAR

Field Descriptions:
  • .clockSource indicates what the timer module should use as its counting base. For the purposes of this course, we will always select the “Low-speed subsystem master clock”, or SMCLK, which is set to be 24 MHz.

  • .clockSourceDivider allows for the selected .clockSource to be “divided” in frequency. For example, if this field was set to TIMER_A_CLOCKSOURCE_DIVIDER_12, the timer would would increment at a rate of 24 MHz / 12 = 2 MHz.

  • .timerPeriod specifies the maximum number that the module will count to before counting back down to 0 and is of type uint16_t. Therefore this field is poorly named as one full timer period is actually .timerPeriod*2.

  • .timerInterruptEnable_TAIE will either enable or disable the Timer_A interrupt: the interrupt generated when the timer resets to 0.

  • .timerInterruptEnable_CCR0_CCIE will either enable or disable the Timer_A CCR0 captureCompare Interrupt: the interrupt generated when the timer reaches the value provided in timerPeriod.

  • .timerClear will cause the current count value, among others, to be reset to 0 upon configuration. It is best to request a timer clear during a (re)configuration such that the timer always starts counting from a known state.

Important

As opposed to Up Mode, the Timer_A interrupt and Timer_A CCR0 captureCompare Interrupt are not effectively equivalent. These interrupt will fire once every timer period but are separated by a half period (.timerPeriod).

With the configuration struct filled in, the timer can be initialized with the function:

void Timer_A_configureUpDownMode( uint32_t timer, Timer_A_UpDownModeConfig * config)

The first argument to this function, uint32_t timer, is the timer module to use (see above). The second argument is the configuration struct as described above. Note that the * within this argument definition indicates that this is passed as a pointer, which is simply done by adding a & before the struct variable name to be passed.

See the end of the Up Mode Configuration section for coding implementation guidance.

Continuous Mode Configuration

This configuration requires the creation of a Timer_A_ContinuousModeConfig type struct. The table below shows the fields for this configuration struct.

Timer_A_ContinuousModeConfig struct fields

Field

Possible Values

.clockSource

TIMER_A_CLOCKSOURCE_EXTERNAL_TXCLK

TIMER_A_CLOCKSOURCE_ACLK

TIMER_A_CLOCKSOURCE_SMCLK

TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLK

.clockSourceDivider

TIMER_A_CLOCKSOURCE_DIVIDER_X

where X is one of:

1 2 3 4 5 6 7 8 10 12 14

16 20 24 28 32 40 48 56 64

.timerInterruptEnable_TAIE

TIMER_A_TAIE_INTERRUPT_ENABLE

TIMER_A_TAIE_INTERRUPT_DISABLE

.timerClear

TIMER_A_DO_CLEAR

TIMER_A_SKIP_CLEAR

Field Descriptions:
  • .clockSource indicates what the timer module should use as its counting base. For the purposes of this course, we will always select the “Low-speed subsystem master clock”, or SMCLK, which is set to be 24 MHz.

  • .clockSourceDivider allows for the selected .clockSource to be “divided” in frequency. For example, if this field was set to TIMER_A_CLOCKSOURCE_DIVIDER_12, the timer would would increment at a rate of 24 MHz / 12 = 2 MHz.

  • .timerInterruptEnable_TAIE will either enable or disable the Timer_A interrupt: the interrupt generated when the timer resets to 0.

  • .timerClear will cause the current count value, among others, to be reset to 0 upon configuration. It is best to request a timer clear during a (re)configuration such that the timer always starts counting from a known state.

Important

As opposed to both the Up Mode and UpDown Mode configuration, the Continuous Mode configuration does not require CCR0. Therefore, the Timer_A CCR0 captureCompare Interrupt is not directly controlled by the timer configuration, and instead it may be controlled via the CCR0 in capture or compare mode as opposed to indicating the timer period has elapsed.

With the configuration struct filled in, the timer can be initialized with the function:

void Timer_A_configureContinuousMode( uint32_t timer, Timer_A_ContinuousModeConfig * config)

The first argument to this function, uint32_t timer, is the timer module to use (see above). The second argument is the configuration struct as described above. Note that the * within this argument definition indicates that this is passed as a pointer, which is simply done by adding a & before the struct variable name to be passed.

See the end of the Up Mode Configuration section for coding implementation guidance.

Capture Compare Registers

Each Capture Compare Register (CCR) may be operated in either Compare mode or Capture mode, independent of the timer configuration or other CCR configurations. However, if the timer is operating in either Up or UpDown mode, CCR0 is reserved for controlling the timer period and therefore cannot be used.

Capture Mode

This mode monitors one of the CCInA or CCInB signals for either a Low-to-High or High-to-Low transition, or both, to generate a Capture Event. The OUTn signal can also be triggered to change on the capture event. This configuration requires the creation of a Timer_A_CaptureModeConfig type struct. The table below shows the fields for this configuration struct.

Timer_A_CaptureModeConfig struct fields

Field

Possible Values

captureRegister

TIMER_A_CAPTURECOMPARE_REGISTER_x

where x is 0-4

captureMode

TIMER_A_CAPTUREMODE_NO_CAPTURE

TIMER_A_CAPTUREMODE_RISING_EDGE

TIMER_A_CAPTUREMODE_FALLING_EDGE

TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE

captureInputSelect

TIMER_A_CAPTURE_INPUTSELECT_CCIxA

TIMER_A_CAPTURE_INPUTSELECT_CCIxB

where x should be left as x

TIMER_A_CAPTURE_INPUT_SELECT_GND

TIMER_A_CAPTURE_INPUT_SELECT_Vcc

synchronizeCaptureSource

TIMER_A_CAPTURE_ASYNCHRONOUS

TIMER_A_CAPTURE_SYNCHRONOUS

captureInterruptEnable

TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE

TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE

captureOutputMode

TIMER_A_OUTPUTMODE_x

where x is one of:

OUTBITVALUE SET TOGGLE_RESET SET_RESET

TOGGLE RESET TOGGLE_SET RESET_SET

Field Descriptions:
  • .compareRegister selects the CCR register to be configured. There are 5 CCRs for each Timer_A module within the MSP432P401R.

  • .captureMode selects when to perform a capture; that is, when the input signal has a Rising Edge, a Falling Edge, or either.

  • .captureInputSelect selects the input signal to which would generate the capture event. This field should always be set such that the CCIxA signal is routed to the CCRn for this course.

  • .synchronizeCaptureSource determines if the capture event should be synchronized with a timer clock or not. It is recommended to always use TIMER_A_CAPTURE_SYNCHRONOUS.

  • .compareInterruptEnable will either enable or disable the CCR interrupt trigger. If using CCR0, the Timer_A CCR0 captureCompare Interrupt would be triggered. For CCR1 through CCR4, the Timer_A Interrupt would be triggered.

  • .captureOutputMode determines how OUTn will behave when a Capture event occurs. The options are:

    • OUTBITVALUE: Set OUTn to have the value as defined by the function

      void Timer_A_setOutputForOutputModeBitValue( uint32_t timer ...  , uint16_t captureCompareRegister , uint8_t outputModeOutBitValue )

      where the uint8_t outputModeOutBitValue is either 0 or 1.

    • SET: Sets OUTn to High.

    • TOGGLE_RESET: Inverts the value of OUTn. OUTn is set Low after a CCR0 compare event.

    • SET_RESET: Sets OUTn to High. OUTn is set Low after a CCR0 compare event.

    • TOGGLE: Inverts the value of OUTn.

    • RESET: Sets OUTn to Low.

    • TOGGLE_SET: Inverts the value of OUTn. OUTn is set High after a CCR0 compare event.

    • RESET_SET: Sets OUTn to Low. OUTn is set High after a CCR0 compare event.

    This field is not needed in this course and may be omitted.

With the configuration struct filled in, the CCR can be initialized with the function:

void Timer_A_initCapture( uint32_t timer , Timer_A_CaptureModeConfig * config )

The timer count stored after a capture event may be read via:

uint16_t Timer_A_getCaptureCompareCount( uint32_t timer , uint16_t captureRegister )

Compare Mode

This mode compares the value stored within the CCRn and performs a specified action on the corresponding OUTn. This configuration requires the creation of a Timer_A_CompareModeConfig type struct. The table below shows the fields for this configuration struct.

Timer_A_CompareModeConfig struct fields

Field

Possible Values

compareRegister

TIMER_A_CAPTURECOMPARE_REGISTER_x

where x is 0-4

compareInterruptEnable

TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE

TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE

compareOutputMode

TIMER_A_OUTPUTMODE_x

where x is one of:

OUTBITVALUE SET TOGGLE_RESET SET_RESET

TOGGLE RESET TOGGLE_SET RESET_SET

compareValue

0 to 65535

Field Descriptions:
  • .compareRegister selects the CCR register to be configured. There are 5 CCRs for each Timer_A module within the MSP432P401R.

  • .compareInterruptEnable will either enable or disable the CCR interrupt trigger. If using CCR0, the Timer_A CCR0 captureCompare Interrupt would be triggered. For CCR1 through CCR4, the Timer_A Interrupt would be triggered.

  • .compareOutputMode determines how OUTn signal will behave when a Compare event (Timer count equals CCRn value) occurs. The options are:

    • OUTBITVALUE: Set OUTn to have the value as defined by the function

      void Timer_A_setOutputForOutputModeBitValue( uint32_t timer ...  , uint16_t captureCompareRegister , uint8_t outputModeOutBitValue )

      where the uint8_t outputModeOutBitValue is either 0 or 1.

    • SET: Sets OUTn to High.

    • TOGGLE_RESET: Inverts the value of OUTn. OUTn is set Low after a CCR0 compare event.

    • SET_RESET: Sets OUTn to High. OUTn is set Low after a CCR0 compare event.

    • TOGGLE: Inverts the value of OUTn.

    • RESET: Sets OUTn to Low.

    • TOGGLE_SET: Inverts the value of OUTn. OUTn is set High after a CCR0 compare event.

    • RESET_SET: Sets OUTn to Low. OUTn is set High after a CCR0 compare event.

  • .compareValue specifies that compare value to assign to the CCR.

With the configuration struct filled in, the CCR can be initialized with the function:

void Timer_A_initCompare( uint32_t timer , Timer_A_CompareModeConfig * config)

After configuration, the compare value may be changed via:

void Timer_A_setCompareValue( uint32_t timer , uint16_t compareRegister , uint16_t compareValue )

where uint16_t compareValue is the new compare value: 0 to 65535.

Timer Run Control

Configuration of the timer will not start the timer. This requires the function

void Timer_A_startCounter( uint32_t timer , uint16_t timerMode)

The argument timerMode selects between Up, UpDown, and Continuous mode via the values: TIMER_A_UP_MODE, TIMER_A_UPDOWN_MODE, or TIMER_A_CONTINUOUS_MODE, respectively. For PWM Mode, the timer must use TIMER_A_UP_MODE.

Likewise, the counter may be paused using

void Timer_A_stopTimer( uint32_t timer )

The timer may also be reset to 0 counts via

void Timer_A_clearTimer( uint32_t timer )

Timer Status

The timer’s counter value can be monitored by calling the function

uint16_t Timer_A_getCounterValue( uint32_t timer )

This function will return the value of the current timer count, where the timer module is specified by timer.

Timer Interrupts

A Timer_A module can trigger an interrupt from any of the capture/compare registers (CCRs) or when the time resets to 0 during counting; however, there are only two interrupts that can be triggered:

  • Timer_A interrupt: Triggered when timer resets to 0 during counting OR from a CCR1-CCR4 event.

  • Timer_A_CCR0_captureCompare interrupt: Triggered when the timer counts to the value stored in CCR0; usually set by a configuration struct .timerPeriod value.

Enabling Interrupts

Each interrupt source may be individually enabled and disabled through the functions:

  • void Timer_A_enableInterrupt( uint32_t timer ) / void Timer_A_disableInterrupt( uint32_t timer ): Enable/disable interrupt generation when the timer resets to 0 during counting

  • void Timer_A_enableCaptureCompareInterrupt( uint32_t timer , uint16_t captureCompareRegister ) / void Timer_A_disableCaptureCompareInterrupt( uint32_t timer , uint16_t captureCompareRegister ): Enable/disable interrupt generation from the CCR.

Each timer interrupt, if enabled, must be associated with a function to run when the interrupt is triggered, the ISR. This function is a normal function that takes no inputs and does not produce an output. The function can then be linked to a timer interrupt through:

void Timer_A_registerInterrupt( uint32_t timer , uint8_t interruptSelect , <function name> )

where the argument interruptSelect is either:

  • TIMER_A_CCR0_INTERRUPT: associate the interrupt function with the Timer_A_CCR0_captureCompare interrupt

  • TIMER_A_CCRX_AND_OVERFLOW_INTERRUPT: associate the interrupt function with the Timer_A interrupt

For example, to associate the Timer_A interrupt with the function void foo(void) for Timer_A2:

Timer_A_registerInterrupt(TIMER_A2_BASE,TIMER_A_CCRX_AND_OVERFLOW_INTERRUPT,foo);

Interrupt Handling

The function associated with the interrupt will be automatically called when the specific interrupt is triggered. Within this function, the code must acknowledge the interrupt by clearing the associated flag, or register bit that indicates the interrupt was triggered. If the flag is not cleared, the interrupt will continuously trigger; that is, the function will be immediately called again once it completes.

The method for clearing of the interrupt flag depends on what triggered the interrupt:

  • CCR Event: Use the function

    void Timer_A_clearCaptureCompareInterrupt( uint32_t timer , uint16_t captureCompareRegister )

    to clear the flag associated with the specific CCR specified by captureCompareRegister.

  • Timer Reset: Use the function

    void Timer_A_clearInterruptFlag( uint32_t timer )

Warning

The functions provided below for determining the interrupt source will only indicate the interrupt trigger has occurred if the interrupt functionality has been enabled, hence the word Enabled in the function names. There are counterpart functions that may be used that will indicate interrupt trigger occurrance even if the interrupt functionality is not enabled. These are:

uint32_t Timer_A_getInterruptStatus(...)

and

uint32_t Timer_A_getCaptureCompareInterruptStatus(...)

These functions are generally not needed, except for the former’s use in Activity 7.

As noted above, only two interrupt functions will be triggered from up to 6 events (5 CCRs and 1 Timer reset). If multiple events are enabled, then the triggering event must be determined first. This requires the functions:

  • uint32_t Timer_A_getEnabledInterruptStatus( uint32_t timer )

    This function will return one of two values: TIMER_A_INTERRUPT_PENDING or TIMER_A_INTERRUPT_NOT_PENDING. The value TIMER_A_INTERRUPT_PENDING indicates that the timer has reset and triggered the interrupt.

  • uint32_t Timer_A_getCaptureCompareEnabledInterruptStatus ( uint32_t timer , uint16_t captureCompareRegister )

    This function will check the status of a single CCR as specified by captureCompareRegister. The function will return a value of either:

    • 0: No active event OR the ability for the CCR to trigger an interrupt is not enabled.

    • TIMER_A_CAPTURECOMPARE_INTERRUPT_FLAG: The selected CCR triggered the interrupt.

    • TIMER_A_CAPTURE_OVERFLOW | TIMER_A_CAPTURECOMPARE_INTERRUPT_FLAG: The selected CCR trigger the interrupt. Additionally, the TIMER_A_CAPTURE_OVERFLOW indicates that a previous triggered interrupt was missed.

    Important

    Given that it is possible for this function to have one or both flags raised, it is better to check if the output contains the specific flag as opposed to checking if the output is equal to a specific flag, using & instead of ==, respectively. See the example code below.

These functions would be used in the functions associated with the timer interrupts to determine the active event. However, each interrupt can only support certain sources:

  • Timer_A interrupt: Need to check the timer reset source and CCR1-4 (if active). If only one event is enabled (e.g., the timer reset) then it is not necessary to identify the events as there is only one possible source.

  • Timer_A_CCR0_captureCompare interrupt: Only one source can trigger this interrupt, a CCR0 event. Therefore, it is not necessary to identify this event.

Example

This example shows a possible way to determine the interrupt status for the Timer_A interrupt for Timer_A1 if the timer reset is enabled as well as CCR1:

void foo(void){ // This function is registered via Timer_A_registerInterrupt()
     // first check if Timer reset occurred
     if(Timer_A_getEnabledInterruptStatus(TIMER_A1_BASE) == TIMER_A_INTERRUPT_PENDING){
         Timer_A_clearInterruptFlag(TIMER_A1_BASE);
         // Do what is needed for a timer reset interrupt (increment counter?)
     }
     // next check if a CCR1 event occurred
     else if(Timer_A_getCaptureCompareEnabledInterruptStatus(
                 TIMER_A1_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1)
                         & TIMER_A_CAPTURECOMPARE_INTERRUPT_FLAG){ // Note the use of & here!
         Timer_A_clarCaptureCompareInterrupt(TIMER_A1_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1);
         // Do what we need for the CCR1 event (calculate speed?)
     }
}