MSP432™ Interrupt system

The MSP432™ uses a additional level for interrupts: the Nested Vectored Interrupt Controller (NVIC). Every interrupt you request must be enabled in the NVIC.

To enable for example the Timer_A0_N interrupt you have to call also the NVIC function:

NVIC_EnableIRQ(TA0_N_IRQn);

You can see a list of all interrupts in the msp432p401r.h file, there is a enum type IRQn_Type.

At next you can choose between Code based and RAM based interrupt vectors.

Code based interrupt

The Code based interrupts are hardlinked between the IVT and the ISR.

To put a ISR in the IVT you have define the ISR in your application first:

// ISR for Timer_A0_N
void Timer_A0_N (void)
{
	// handle IRQ
}

At default the IVT is defined in the msp432_startup_ccs.c file, there you have to declare your function:

/* External declarations for the interrupt handlers used by the application. */
/* To be added by user */
extern void Timer_A0_N (void);

At last you assign the function to the IVT:

#pragma DATA_SECTION(interruptVectors, ".intvecs")
void (* const interruptVectors[])(void) =
{
	(void (*)(void))((uint32_t)&__STACK_END),
	...
	Timer_A0_N,                             /* TA0_N ISR                 */
	...
};

In the document SLAA656 (MSP432™ Platform Porting Guide) version 2015-03 is witten the old „#pragma vector“ method should also work, but at my tests the compiler thows some errors on it.

RAM based interrupt

RAM based interrupts can be used in oder if you have multiple applications running on your MSP and every application has it’s own ISRs.

For the use of RAM based interrupts I recommend to use the MSP432 DriverLib Interrupt API. You have to create a RAM table and manage the IV entrys and the API is straight forward and implements all the needed functions.

You can start using Code based interrupts, if you call the Interrupt_registerInterrupt function at first time, it will copy the whole IVT from Code to RAM.

The Interrupt_registerInterrupt and Interrupt_unregisterInterrupt does not enable or disable the interrupt, you have to call Interrupt_enableInterrupt and Interrupt_disableInterrupt manually.

As example the timer interrupt:

// from MSP432 DriverLib
#include "interrupt.h"
 
// ISR for Timer_A0_N
void Timer_A0_N (void)
{
	// handle IRQ
}
 
void main(void)
{
	...
	Interrupt_registerInterrupt(INT_TA0_N, Timer_A0_N);
	Interrupt_enableInterrupt(INT_TA0_N);
	...
}

MSP432™ Clock System speed

Changing the Clock Speed of the MSP432™ is a bit tricky. First you have to unlock the registers, then you can change the DCO speed. You can ajust the clock using the following DCO values.

DCORSEL min MHz normal (DCOTUNE = 0) MHz max MHz
DCORSEL_0 1 1.5 2
DCORSEL_1 2 3 4
DCORSEL_2 4 6 8
DCORSEL_3 8 12 16
DCORSEL_4 16 24 32
DCORSEL_5 32 48 64

 

Read more in document SLAU356A (MSP432P4xx Family Technical Reference Manual) version 2015-04 section 5.3.

You can increase or decrease the speed using the DCOTUNE Register to any value between min and max. For the correct values of DCOTUNE consult the document SLAA658 (Multi-Frequency Range and Tunable DCO on MSP432P4xx) version 2015-03. These values can be obtained from the TLV.

TLV->rDCOIR_MAXNEGTUNE_RSEL04; // DCO IR mode: Max Negative Tune for DCORSEL 0 to 4
TLV->rDCOIR_MAXPOSTUNE_RSEL04; // DCO IR mode: Max Positive Tune for DCORSEL 0 to 4
TLV->rDCOIR_MAXNEGTUNE_RSEL5; // DCO IR mode: Max Negative Tune for DCORSEL 5
TLV->rDCOIR_MAXPOSTUNE_RSEL5; // DCO IR mode: Max Positive Tune for DCORSEL 5

The CSKEY register is described as CSACC in the documentation, but in Code Composer Studio the register has still the name CSKEY.

Example change DCO to IR and 48MHz:

CSKEY = 0x695A; // unlock CS registers
CSCTL0 = 0; // reset DCO settings
CSCTL0 = DCORSEL_5; // select DCO 5 (48MHz)
CSCTL1 = SELA__REFOCLK | SELS__DCOCLK | SELM__DCOCLK; // ACLK = REFOCLK, SMCLK = MCLK = DCOCLK
CSKEY = 0; // lock CS registers