Part Number: MSP430FR2311
I have two projects right how that are using the MSP430 low power modes. I understand the need to put the part to sleep, but don't understand the need to clear the bit after there has been an interrupt.
I've noticed a few things so far. I can only use LPM0 if I want to receive UART messages at 115200 because the low frequency oscillator is too slow. I also have to purposely exit/clear the LPM0 bit in the I2C interrupt routine in order to process them in main.
So I'm really unsure if I have all my code correct. I was hoping someone could review and give any suggestions.
Project 1
// Wake up to process data received over the UART as it comes in.
// Wake when I2C slave commands come in and response appropriately.
// Also noticed I had to clear the lpm bit in order to wake up from I2C transactions
int main(void)
{
//Stop WDT
WDT_A_hold(WDT_A_BASE);
initClockTo16MHz();
initUART(0);
initGPIO();
initI2C();
while(1)
{
if(rxFlag == 1)
{
processUART();
}
__bis_SR_register(LPM0_bits + GIE);
}
}
// UART Interrupt
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(UCA0IV,USCI_UART_UCTXCPTIFG))
{
case USCI_NONE: break;
case USCI_UART_UCRXIFG:
UCA0IFG &=~ UCRXIFG; // Clear interrupt
rxData = UCA0RXBUF;
rxFlag = 1;
__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 on reti
break;
case USCI_UART_UCTXIFG: break;
case USCI_UART_UCSTTIFG: break;
case USCI_UART_UCTXCPTIFG: break;
}
}
//******************************************************************************
// I2C Interrupt ***************************************************************
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void)
#else
#error Compiler not supported!
#endif
{
//Must read from UCB0RXBUF
uint8_t rx_val = 0;
switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
{
case USCI_NONE: break; // Vector 0: No interrupts
case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG
case USCI_I2C_UCNACKIFG: // Vector 4: NACKIFG
break;
case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG
case USCI_I2C_UCSTPIFG:
UCB0IFG &= ~(UCTXIFG0);
break; // Vector 8: STPIFG
case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3
case USCI_I2C_UCTXIFG3: break; // Vector 12: TXIFG3
case USCI_I2C_UCRXIFG2: break; // Vector 14: RXIFG2
case USCI_I2C_UCTXIFG2: break; // Vector 16: TXIFG2
case USCI_I2C_UCRXIFG1: break; // Vector 18: RXIFG1
case USCI_I2C_UCTXIFG1: break; // Vector 20: TXIFG1
case USCI_I2C_UCRXIFG0: // Vector 22: RXIFG0
rx_val = UCB0RXBUF;
switch (SlaveMode)
{
case (RX_REG_ADDRESS_MODE):
ReceiveRegAddr = rx_val;
I2C_Slave_ProcessCMD(ReceiveRegAddr);
break;
case (RX_DATA_MODE):
ReceiveBuffer[ReceiveIndex++] = rx_val;
RXByteCtr--;
if (RXByteCtr == 0)
{
//Done Receiving MSG
SlaveMode = RX_REG_ADDRESS_MODE;
UCB0IE &= ~(UCTXIE);
UCB0IE |= UCRXIE; // Enable RX interrupt
I2C_Slave_TransactionDone(ReceiveRegAddr);
__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 on reti
}
break;
default:
__no_operation();
break;
}
break;
case USCI_I2C_UCTXIFG0: // Vector 24: TXIFG0
UCB0TXBUF = TransmitBuffer[TransmitIndex++];
TXByteCtr--;
if (TXByteCtr == 0)
{
//Done Transmitting MSG
SlaveMode = TX_REG_ADDRESS_MODE;
UCB0IE &= ~(UCTXIE);
UCB0IE |= UCRXIE; // Enable RX interrupt
I2C_Slave_TransactionDone(ReceiveRegAddr);
}
break; // Interrupt Vector: I2C Mode: UCTXIFG
default: break;
}
}
Project 2
int main(void) {
//Stop WDT
WDT_A_hold(WDT_A_BASE);
initClockTo16MHz();
initUART();
/* Initialize peripherals */
initGPIO();
initPWM();
initI2C();
initRTC();
while(1)
{
currentSample();
led_current_reading = ADC_Conversion_Result;
tempSample();
current_temp_reading = ADC_Conversion_Result;
doOtherStuff();
//LPM3, RTC or I2C will force exit
__bis_SR_register(LPM3_bits + GIE);
}
}
void currentSample(void)
{
enable_ADC10(ADCINCH_0);
__delay_cycles(15);
//Enable and Start the conversion
//in Single-Channel, Single Conversion Mode
ADC_startConversion(ADC_BASE, ADC_SINGLECHANNEL);
//LPM3, ADC conversion complete will force exit
__bis_SR_register(LPM0_bits + GIE);
disable_ADC10();
}
void tempSample(void)
{
enable_ADC10(ADCINCH_12);
__delay_cycles(15);
//Enable and Start the conversion
//in Single-Channel, Single Conversion Mode
ADC_startConversion(ADC_BASE, ADC_SINGLECHANNEL);
//LPM3, ADC conversion complete will force exit
__bis_SR_register(LPM0_bits + GIE);
disable_ADC10();
}
void disable_ADC10(void){
ADC_disableConversions(ADC_BASE,0);
ADC_disable(ADC_BASE);
}
void enable_ADC10(uint8_t adc_channel){
//Initialize the ADC Module
ADC_init(ADC_BASE, ADC_SAMPLEHOLDSOURCE_SC, ADC_CLOCKSOURCE_ADCOSC, ADC_CLOCKDIVIDER_1);
ADC_enable(ADC_BASE);
ADC_setupSamplingTimer(ADC_BASE, ADC_CYCLEHOLD_1024_CYCLES, ADC_MULTIPLESAMPLESDISABLE);
if(adc_channel == ADCINCH_12)
{
ADC_configureMemory(ADC_BASE, adc_channel, ADC_VREFPOS_INT, ADC_VREFNEG_AVSS);
}
else
{
ADC_configureMemory(ADC_BASE, adc_channel, ADC_VREFPOS_AVCC, ADC_VREFNEG_AVSS); // channel mis-map for A1 in driverlib?
}
ADC_clearInterrupt(ADC_BASE, ADC_COMPLETED_INTERRUPT);
//Enable the Memory Buffer Interrupt
ADC_enableInterrupt(ADC_BASE, ADC_COMPLETED_INTERRUPT);
}
// ADC interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ADC_VECTOR
__interrupt void ADC_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void)
#else
#error Compiler not supported!
#endif
{
ADC_Conversion_Result = ADCMEM0;
__bic_SR_register_on_exit(LPM3_bits); // Sleep Timer Exits LPM3
}
// RTC interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=RTC_VECTOR
__interrupt void RTC_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(RTC_VECTOR))) RTC_ISR (void)
#else
#error Compiler not supported!
#endif
{
__bic_SR_register_on_exit(LPM3_bits); // Timer Exits LPM3
switch(__even_in_range(RTCIV,RTCIV_RTCIF))
{
case RTCIV_NONE: break; // No interrupt
case RTCIV_RTCIF: // RTC Overflow
P2OUT ^= BIT3;
break;
default: break;
}
}
//******************************************************************************
// I2C Interrupt ***************************************************************
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void)
#else
#error Compiler not supported!
#endif
{
//Must read from UCB0RXBUF
uint8_t rx_val = 0;
switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
{
case USCI_NONE: break; // Vector 0: No interrupts
case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG
case USCI_I2C_UCNACKIFG: // Vector 4: NACKIFG
break;
case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG
case USCI_I2C_UCSTPIFG:
UCB0IFG &= ~(UCTXIFG0);
break; // Vector 8: STPIFG
case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3
case USCI_I2C_UCTXIFG3: break; // Vector 12: TXIFG3
case USCI_I2C_UCRXIFG2: break; // Vector 14: RXIFG2
case USCI_I2C_UCTXIFG2: break; // Vector 16: TXIFG2
case USCI_I2C_UCRXIFG1: break; // Vector 18: RXIFG1
case USCI_I2C_UCTXIFG1: break; // Vector 20: TXIFG1
case USCI_I2C_UCRXIFG0: // Vector 22: RXIFG0
rx_val = UCB0RXBUF;
switch (SlaveMode)
{
case (RX_REG_ADDRESS_MODE):
ReceiveRegAddr = rx_val;
I2C_Slave_ProcessCMD(ReceiveRegAddr); /
break;
case (RX_DATA_MODE):
ReceiveBuffer[ReceiveIndex++] = rx_val;
RXByteCtr--;
if (RXByteCtr == 0)
{
//Done Receiving MSG
SlaveMode = RX_REG_ADDRESS_MODE;
UCB0IE &= ~(UCTXIE);
UCB0IE |= UCRXIE; // Enable RX interrupt
I2C_Slave_TransactionDone(ReceiveRegAddr);
// SHOULD WE DO THIS HERE?
__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 on reti
}
break;
default:
__no_operation();
break;
}
break;
case USCI_I2C_UCTXIFG0: // Vector 24: TXIFG0
UCB0TXBUF = TransmitBuffer[TransmitIndex++];
TXByteCtr--;
if (TXByteCtr == 0)
{
//Done Transmitting MSG
SlaveMode = TX_REG_ADDRESS_MODE;
UCB0IE &= ~(UCTXIE);
UCB0IE |= UCRXIE; // Enable RX interrupt
I2C_Slave_TransactionDone(ReceiveRegAddr);
}
break; // Interrupt Vector: I2C Mode: UCTXIFG
default: break;
}
}