This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/MSP432P401R: Looking for an example of application using simultaneously interrupt sub-routines for communication (SPI,I2C), ADC, PWM and UATR

Part Number: MSP432P401R

Tool/software: TI C/C++ Compiler

Dear All,

I'm developing an application and I wanted to use interrupt sub-routines as more as possible for communication such as SPI, I2C, UART, for ADC, PWM (servo-motors) and DMA. Unfortunately, I have issues with multiple ISRs, I think the issues are on my side (for sure). My application works for a short time and then block: some interrupt flags are raised but the ISR is not called.

I would like to know if some one could point me to some sample codes which use simultaneously ISRs for communication, ADC... for the MSP432.

I'm using the DriverLib library.

Many thanks in advance for your help,

Best regards,

Yann

  • I am not aware of any examples which deal with ISR contention in the driverLib context. There are examples that deal with priority, but not specific to the ADC and comms.  Here is one with two different timers but could be extended to comms and ADC: http://dev.ti.com/tirex/explore/node?node=AHIBsRRMqZITYd-WzRZCbQ__z-lQYNj__LATEST .

    When you say the ISR is not called, that does not seem correct.  The CPU will tail-chain the interrupts so they should be serviced, even if delayed.  

    Regards,

    Chris

  • Hello Chris,

    Thanks a lot.

    I'm going to check again my issue regarding the ISR not called.

    Best Regards,

    Yann

  • Hello,

    Is there any update?

    Regards.

    Chirs

  • Hello Chris,

    Not really. I restarted from scratch introducing step by step the different modules I need using the TI examples. Currently I have SysTick, Timer A (Up mode) and UART.

    Next step is to re-introduce I2C for which I got issues.

    I'll come back to you soon if I have issues, otherwise, I will change the status of this case into Resolved

    Thanks a lot,

    Best regards,

    Yann

  • Hello Chris,

    I create a basic application trying to mixed PWM, Timer 32, ADC and UART.

    Globally, I could say that it's working but I have a strange behavior: when I enable the Timer 32 in periodic mode (), it seems that the UART output is blocked in 'while (!(UCA0IFG & UCTXIFG))'. If I disable the Timer32, everything is working fine.

    Note: In free run mode, this issue does not occurs.

    In all case, the input seems to works fine (no latency while entering text on the console).

    Do you have any hint? Is there a link between the UART and the Timer 32?

    Many thanks in advance,

    Best regards,

    Yann

    /* DriverLib Includes */
    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
    
    /* Standard Includes */
    #include <stdint.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdarg.h>
    
    
    int fputc(int _c, register FILE *_fp);
    int fputs(const char *_ptr, register FILE *_fp);
    
    
    /*!< Fixed size of the buffer */
    #define CIRCULAR_BUFFER_SIZE 32
    /*!< True if the buffer is empty */
    #define BUFFER_EMPTY(r_idx, w_idx) (bool)(r_idx == w_idx)
    /*!< True if the buffer is empty */
    #define BUFFER_FULL(r_idx, w_idx)  (bool)(((w_idx + 1) % CIRCULAR_BUFFER_SIZE) == r_idx)
    /*!< Increment the index */
    #define INC_IDX(idx)         idx = ((idx + 1) % CIRCULAR_BUFFER_SIZE)
    /*!< Decrement the index */
    #define DEC_IDX(idx)         idx = ((idx == 0) ? CIRCULAR_BUFFER_SIZE - 1 : idx - 1)
    
    /** \struct Circular buffer data structure
    */
    typedef struct {
      uint16_t r_idx;             /*!< The read index */
      uint16_t w_idx;             /*!< The write index */
      uint8_t buffer[CIRCULAR_BUFFER_SIZE]; /*!< The buffer of data */
    } circular_bytes_buffer_t;
    typedef struct {
      uint16_t r_idx;             /*!< The read index */
      uint16_t w_idx;             /*!< The write index */
      uint16_t buffer[CIRCULAR_BUFFER_SIZE]; /*!< The buffer of data */
    } circular_words_buffer_t;
    
    
    #define SLAVE_ADDRESS     0x68 /* Slave Address for I2C Slave */
    #define NUM_OF_REC_BYTES  2    // TODO To be refined, NUM_OF_REC_BYTES is depending of the desired bytes to be read/written
    /*!< Receive circular buffer for I2C. Use volatile because it will be modified in ISR. */
    #define I2C_MODULE_MAX 1
    static volatile uint8_t p_i2c_bus_id = 0;
    static circular_bytes_buffer_t i2c_rx_circular_buffer[I2C_MODULE_MAX];
    /* I2C Master Configuration Parameter */
    static eUSCI_I2C_MasterConfig i2cConfig =
    {
      EUSCI_B_I2C_CLOCKSOURCE_SMCLK,      // SMCLK Clock Source
      12000000,                           // SMCLK = 12MHz
      EUSCI_B_I2C_SET_DATA_RATE_400KBPS,  // Desired I2C Clock of 400khz
      0,                                  // No byte counter threshold
      EUSCI_B_I2C_NO_AUTO_STOP            // No Autostop
    };
    
    /*!< Receive circular buffer for UART. */
    #define UART_MODULE_MAX 1
    static volatile uint8_t p_fd = 0;
    static circular_bytes_buffer_t uart_rx_circular_buffer[UART_MODULE_MAX];
    
    /* UART Configuration Parameter */
    static eUSCI_UART_Config uartConfig = { /* See http://processors.wiki.ti.com/index.php/USCI_UART_Baud_Rate_Gen_Mode_Selection#USCI_UART_Calculator */
      EUSCI_A_UART_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
      104,                                     // BRDIV = 104
      0,                                       // UCxBRF = 0
      1,                                       // UCxBRS = 1
      EUSCI_A_UART_NO_PARITY,                  // No Parity
      EUSCI_A_UART_LSB_FIRST,                  // MSB First
      EUSCI_A_UART_ONE_STOP_BIT,               // One stop bit
      EUSCI_A_UART_MODE,                       // UART mode
      EUSCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION  // Low Frequency Mode
    };
    
    
    /*
     * PWM generation based on Up/Down mode & capture on Timer A0 (output TA0.3 for TA0CCR3, TA0.4 for TA0CCR4
     * Stand alone process, Interrupts are not required
     */
    const Timer_A_UpDownModeConfig upDownConfig =
    {
      TIMER_A_CLOCKSOURCE_ACLK,              /* ACLK Clock Source frequency = 32000Hz */
      TIMER_A_CLOCKSOURCE_DIVIDER_1,         /* Timer Clock frequency = 32000Hz (0.03125ms) */
      320 - 1,                               /* T_output=20ms ==> 320 ticks for T/2, -1 stands for 'The number of timer counts in the period is TAxCCR0 + 1' */
      TIMER_A_TAIE_INTERRUPT_DISABLE,        /* Interrupts are not required */
      TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE,   /* Interrupts are not required */
      TIMER_A_DO_CLEAR
    };
    /* Timer_A Compare Configuration Parameter  (PWM1) */
    const Timer_A_CompareModeConfig compareConfig_PWM1 =
    {
      TIMER_A_CAPTURECOMPARE_REGISTER_3,          /* Use CCR3, TA0.3: p2.6 */
      TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE,   /* Interrupts are not required */
      TIMER_A_OUTPUTMODE_TOGGLE_RESET,              /* Toggle output but */
      32                                          /* Duty Cycle = 2ms = 10% of T=20ms ==> 32 ticks */
    };
    
    /* Timer_A Compare Configuration Parameter (PWM2) */
    const Timer_A_CompareModeConfig compareConfig_PWM2 =
    {
      TIMER_A_CAPTURECOMPARE_REGISTER_4,          /* Use CCR4, TA0.4: p2.7 */
      TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE,   /* Interrupts are not required */
      TIMER_A_OUTPUTMODE_TOGGLE_RESET,              /* Toggle output but */
      16                                          /* Duty Cycle  1ms = 5% of T=20ms ==> 16 ticks */
    };
    
    
    /* Timer_A UpMode Configuration Parameter */
    static Timer_A_UpModeConfig upConfig =
    {
      TIMER_A_CLOCKSOURCE_ACLK,              /* ACLK Clock Source frequency = 32000Hz */
      TIMER_A_CLOCKSOURCE_DIVIDER_1,         /* Timer Clock frequency = 32000Hz (0.03125ms) */
      16000 - 1,                             /* T_output=1s ==> 16000 ticks for T/2, -1 stands for 'The number of timer counts in the period is TAxCCR0 + 1' */
      TIMER_A_TAIE_INTERRUPT_DISABLE,
      TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE,
      TIMER_A_DO_CLEAR
    };
    static Timer_A_ContinuousModeConfig contConfig =
    {
      TIMER_A_CLOCKSOURCE_ACLK,              /* ACLK Clock Source frequency = 32000Hz */
      TIMER_A_CLOCKSOURCE_DIVIDER_1,         /* Timer Clock frequency = 32000Hz (0.03125ms) */
      TIMER_A_TAIE_INTERRUPT_ENABLE,
      TIMER_A_DO_CLEAR
    };
    
    
    /*!< Receive circular buffer for ADC */
    #define ADC_MODULE_MAX 2    // TODO To be refined, ADC_MODULE_MAX is depending of the desired ADC entries
    static volatile uint8_t p_adc = 0;
    static circular_words_buffer_t adc_rx_circular_buffer[ADC_MODULE_MAX];
    
    
    static float onboard_temperature_calibration;
    static float onboard_temperature;
    static float battery_voltage;
    
    
    
    int main(void)
    {
      /* Halting WDT and disabling master interrupts */
      MAP_WDT_A_holdTimer();
      /* Enable processor interrupts */
      MAP_Interrupt_disableMaster();
      /* Seed the pseudo random num generator */
      //  srand(TLV->RANDOM_NUM_1);
      /* Set the core voltage level to VCORE1 */
      MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
      /* Enabling FPU for DCO Frequency calculation.
       * Enabling the FPU with stacking enabled (for use within ISR)
       */
      MAP_FPU_enableModule();
      MAP_FPU_enableLazyStacking();
      /* Set 2 flash wait states for Flash bank 0 and 1*/
      MAP_FlashCtl_setWaitState(FLASH_BANK0, 2);
      MAP_FlashCtl_setWaitState(FLASH_BANK1, 2);
      /* Initializes Clock System */
      MAP_CS_setDCOFrequency(CS_48MHZ);                                         /* System clock: 48MHz. Required PCM_VCORE1 */
      MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_2);    /* Master clock set to internal 24MHz, Used by Timer 32
      MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_2);  /* Subsystem master clock set to internal 24MHz */
      MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_4);   /* Low-speed subsystem master clock set to internal 12MHz, used by UART console, I2C and ADC14 */
    //  MAP_CS_initClockSignal(CS_MODOSC_SELECT, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_2);
                                                                                /* Master clock set to internal 24MHz, Used by ADC */
      MAP_CS_setReferenceOscillatorFrequency(CS_REFO_32KHZ);                    /* Selects internal REFO clock source to 32000Hz */
                                                                                /* MSP432P401R does not support CS_REFO_128KHZ */
      MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);   /* Auxiliary clock A set to internal 32000Hz, used by PWM & Timer A */
                                                                                /* ==> Tmin = 31.15us */
      uint32_t sys_clock = MAP_CS_getDCOFrequency();
      uint32_t aclk = MAP_CS_getACLK();
      uint32_t mclk = MAP_CS_getMCLK();
      uint32_t smclk = MAP_CS_getSMCLK();
      uint32_t hsmclk = MAP_CS_getHSMCLK();
      uint32_t bclk = MAP_CS_getBCLK();
    
    
      /* Initialize GPIO interrupt functions table */
      MAP_GPIO_disableInterrupt(GPIO_PORT_P1, PIN_ALL16);
      MAP_GPIO_disableInterrupt(GPIO_PORT_P2, PIN_ALL16);
      MAP_Interrupt_enableInterrupt(INT_PORT1);
      MAP_Interrupt_enableInterrupt(INT_PORT2);
    
    
      /* Select Port 1 for I2C - Set Pin 4, 5 to input Primary Module Function (UCB1SIMO/UCB1SDA, UCB1SOMI/UCB1SCL) */
      MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6, GPIO_PIN5 | GPIO_PIN4, GPIO_PRIMARY_MODULE_FUNCTION);
      /* Initializing I2C Master to SMCLK at 100khz with no autostop */
      MAP_I2C_initMaster(EUSCI_B1_BASE, &i2cConfig);
      /* Specify slave address */
      MAP_I2C_setSlaveAddress(EUSCI_B1_BASE, SLAVE_ADDRESS);
      /* Enable I2C Module to start operations */
      MAP_I2C_enableModule(EUSCI_B1_BASE);
      MAP_Interrupt_enableInterrupt(INT_EUSCIB1);
    
    
      /* Reset RX/TX buffer data structures */
      uart_rx_circular_buffer[p_fd].r_idx = 0;
      uart_rx_circular_buffer[p_fd].w_idx = 0;
      /* Selecting P1.2 and P1.3 in UART mode */
      MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
      /* Configuring UART Module */
      i2cConfig.i2cClk = smclk;
      MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig);
      /* Enable UART module */
      MAP_UART_enableModule(EUSCI_A0_BASE);
      /* Enabling interrupts */
      MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);
      MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
    
      /***
       * IO mapping
       *   GPIO_PORT_P1/GPIO_PIN0: On board red led
       *   GPIO_PORT_P1/GPIO_PIN1: On board switch #1
       *   GPIO_PORT_P2/GPIO_PIN0: On board red RGB led
       *   GPIO_PORT_P2/GPIO_PIN1: On board green RGB led
       *   GPIO_PORT_P2/GPIO_PIN2: On board blue RGB led
       *   GPIO_PORT_P2/GPIO_PIN7: PWM2, Saleae Analyzer: Debug 0
       *   GPIO_PORT_P2/GPIO_PIN6: PWM1, Saleae Analyzer: Debug 1
       *   GPIO_PORT_P2/GPIO_PIN4: Timer A, Up mode, Saleae Analyzer: Debug 2
       *   GPIO_PORT_P5/GPIO_PIN6: Timer A, Continuous mode, Saleae Analyzer: Debug 3
       *   GPIO_PORT_P6/GPIO_PIN6: Timer 32, Continuous mode, Saleae Analyzer: Debug 4
       *   GPIO_PORT_P6/GPIO_PIN7: ADC14, Repetition mode, Saleae Analyzer: Debug 5
       *
       * GPIO functions: See Microcontroller Engineering with MSP432 Fundamentals and Applications, Table 7.1 GPIO port 1 (P1.0~P1.7) pin functions
       */
    
      /* Configuring P1.1 as an input (SW1) and enabling interrupts */
      MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1);
      MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1);
      MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1);
      /* Configuring P1.4 as an input (SW2) and enabling interrupts */
      MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN4);
      MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN4);
      MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN4);
    
      /* Selecting P1.0 as output (on board RED LED) for SysTick. */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
    
      /* Selecting P2.0 as output (on board RED RGB LED) for Button 1 interrupt handler. */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0);
      /* Selecting P2.1 as output (on board GREEN RGB LED) for xxx. */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN1);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN1);
      /* Selecting P2.2 as output (on board BLUE RGB LED) for xxx. */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN2);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN2);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN2);
    
      /* Selecting P2.7 as TA0.4 output, PWM2. */
      MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
      /* Selecting P2.6 as TA0.3 output, PWM1. */
      MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN6, GPIO_PRIMARY_MODULE_FUNCTION);
    
      /* Selecting P2.4 as output for Timer A in Up mode (Analyzer). */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN4);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN4);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN4);
      /* Selecting P5.6 as output for Timer A in Continuous mode (Analyzer). */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P5, GPIO_PIN6);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN6);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P5, GPIO_PIN6);
      /* Selecting P6.6 as output for Timer 32 in Continuous mode (Analyzer). */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN6);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN6);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN6);
      /* Selecting P6.7 as output for adc14 sampling trigger (Analyzer). */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN7);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN7);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN7);
    
    
      /* Set SysTick timer */
      MAP_SysTick_setPeriod((sys_clock / 24 / 4)); /* Configuring SysTick to trigger an interrupt at [4.16ms (1/24)]/4 to prevent flashing effect. With Fosc at 48MHz, 500000 ticks is one milliseconds */
      MAP_SysTick_enableModule();
      MAP_Interrupt_setPriority(FAULT_SYSTICK, 2);
      MAP_SysTick_enableInterrupt();
    
    
      /* Configuring Timer A0 for Up/Down mode */
      MAP_Timer_A_configureUpDownMode(TIMER_A0_BASE, &upDownConfig);
      /* Initialize compare registers to generate PWM1 */
      MAP_Timer_A_initCompare(TIMER_A0_BASE, &compareConfig_PWM1);
      /* Initialize compare registers to generate PWM2 */
      MAP_Timer_A_initCompare(TIMER_A0_BASE, &compareConfig_PWM2);
      /* Start timer A0 to generate PWM */
      MAP_Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_UPDOWN_MODE);
    
    
      /* Timer A1 in Up mode */
      MAP_Timer_A_configureUpMode(TIMER_A1_BASE, &upConfig);
      MAP_Timer_A_startCounter(TIMER_A1_BASE, TIMER_A_UP_MODE);
      /* Timer A1 in Continuous mode */
      MAP_Timer_A_configureContinuousMode(TIMER_A2_BASE, &contConfig);
      MAP_Interrupt_enableInterrupt(INT_TA1_0);
      MAP_Interrupt_enableInterrupt(INT_TA2_N);
      MAP_Timer_A_startCounter(TIMER_A2_BASE, TIMER_A_CONTINUOUS_MODE);
    
    
      /* Configuring Timer 32 to 100ms (0.1 * 24000000) of MCLK in periodic mode */
      MAP_Timer32_setCount(TIMER32_0_BASE, 24000000); //==> TIMER32_PERIODIC_MODE instead of TIMER32_FREE_RUN_MODE
      MAP_Timer32_initModule(TIMER32_0_BASE, TIMER32_PRESCALER_1, TIMER32_32BIT, TIMER32_PERIODIC_MODE);
      MAP_Timer32_enableInterrupt(TIMER32_0_BASE);
      MAP_Interrupt_enableInterrupt(INT_T32_INT1);
      MAP_Timer32_startTimer(TIMER32_0_BASE, false/* Continuous mode */);
    
    
      /* Reset RX/TX buffer data structures */
      adc_rx_circular_buffer[0].r_idx = 0;
      adc_rx_circular_buffer[0].w_idx = 0;
      adc_rx_circular_buffer[1].r_idx = 0;
      adc_rx_circular_buffer[1].w_idx = 0;
      /* Setting reference voltage to 2.5 and enabling reference */
      MAP_REF_A_setReferenceVoltage(REF_A_VREF2_5V);
      MAP_REF_A_enableReferenceVoltage();
      /* Initializing ADC (ACLK/1/3) with temperature sensor and battery routed, ACLK=32KHz ==> ADCCLK=4KHz */
      MAP_ADC14_initModule(ADC_CLOCKSOURCE_ACLK, ADC_PREDIVIDER_1, ADC_DIVIDER_3, ADC_TEMPSENSEMAP | ADC_BATTMAP);
      /* Use multiple memories sample */
      MAP_ADC14_configureMultiSequenceMode(ADC_MEM0, ADC_MEM1, true);
      /* Set ADC channel 22 (On board temperature) conversion with Vss as negative reference */
      MAP_ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A22, false);
      /* Set ADC channel 23 (On board battery level) conversion with Vss as negative reference */
      MAP_ADC14_configureConversionMemory(ADC_MEM1, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A23, false);
      /* Configuring the sample trigger to be sourced from ADCCLK and on the rising edge */
      MAP_ADC14_setSampleHoldTrigger(ADC_TRIGGER_ADCSC, false);
      /* Enabling sample timer in auto iteration mode and interrupts */
      MAP_ADC14_enableSampleTimer(ADC_AUTOMATIC_ITERATION);
      /* Enable ADC module */
      MAP_ADC14_enableModule();
      /* Enabling the interrupt when a conversion on channel 31 (end of sequence) is complete and enabling conversions */
      MAP_ADC14_enableInterrupt(ADC_INT1);
      MAP_Interrupt_enableInterrupt(INT_ADC14);
      /* Enabling  conversions */
      MAP_ADC14_enableConversion();
      MAP_ADC14_toggleConversionTrigger();
    
    
      /* Set the temperature calibration value required to calculate the temperature */
      onboard_temperature_calibration =
                                        MAP_SysCtl_getTempCalibrationConstant(SYSCTL_2_5V_REF, SYSCTL_85_DEGREES_C) -
                                        MAP_SysCtl_getTempCalibrationConstant(SYSCTL_2_5V_REF, SYSCTL_30_DEGREES_C);
    
    
      MAP_Interrupt_enableSleepOnIsrExit();
      MAP_Interrupt_enableMaster();
    
    
      printf("\r\nHow to use printf ;)\r\n"); // Disable EUSCIA0 before to use printf
      printf("Decimal(10) :%d\r\n", 10);
      printf("Hex(10)   :%x\r\n", 10);
      printf("float     :%f\r\n", 4.32);
    
    
      /* Main while loop */
      while(1)
      {
        MAP_PCM_gotoLPM0();
      }
    }
    
    /*******************************************************************************
     * eUSCIB1 ISR. The repeated start and transmit/receive operations happen
     * within this ISR.
     *******************************************************************************/
    void EUSCIB1_IRQHandler(void) {
      const volatile uint_fast16_t isr_status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B1_BASE);
      MAP_I2C_clearInterruptFlag(EUSCI_B1_BASE, isr_status);
    
      /* Receives bytes into the receive buffer. If we have received all bytes,
       * send a STOP condition */
      if (isr_status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)
      {
        if (i2c_rx_circular_buffer[p_i2c_bus_id].w_idx == NUM_OF_REC_BYTES - 2)
        {
          i2c_rx_circular_buffer[p_i2c_bus_id].buffer[i2c_rx_circular_buffer[p_i2c_bus_id].w_idx] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE);
          INC_IDX(i2c_rx_circular_buffer[p_i2c_bus_id].w_idx);
          MAP_I2C_disableInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
          MAP_I2C_enableInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_STOP_INTERRUPT);
          MAP_I2C_masterReceiveMultiByteStop(EUSCI_B1_BASE);
        } else
        {
          i2c_rx_circular_buffer[p_i2c_bus_id].buffer[i2c_rx_circular_buffer[p_i2c_bus_id].w_idx] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE);
          INC_IDX(i2c_rx_circular_buffer[p_i2c_bus_id].w_idx);
        }
      }
      else if (isr_status & EUSCI_B_I2C_STOP_INTERRUPT)
      {
        i2c_rx_circular_buffer[p_i2c_bus_id].buffer[i2c_rx_circular_buffer[p_i2c_bus_id].w_idx] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE);
        INC_IDX(i2c_rx_circular_buffer[p_i2c_bus_id].w_idx);
        MAP_I2C_disableInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_STOP_INTERRUPT);
      }
    }
    
    void TA1_0_IRQHandler(void) {
      MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A1_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_0);
      MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN4); /* Analyzer Debug 2 */
    }
    
    void TA2_N_IRQHandler(void) {
      MAP_Timer_A_clearInterruptFlag(TIMER_A2_BASE);
      MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P5, GPIO_PIN6);
    }
    
    void T32_INT1_IRQHandler(void) {
      MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE);
      MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P6, GPIO_PIN6); /* Analyzer Debug 4 */
      MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P6, GPIO_PIN6); /* Analyzer Debug 4 */
      // TODO Consume the ADC14 samples here
    }
    
    void SysTick_Handler(void) {
      /* Reset RX buffer */
      i2c_rx_circular_buffer[p_i2c_bus_id].r_idx = 0;
      i2c_rx_circular_buffer[p_i2c_bus_id].w_idx = 0;
    
      /* Echo back if any */
      if (!BUFFER_EMPTY(uart_rx_circular_buffer[p_fd].r_idx, uart_rx_circular_buffer[p_fd].w_idx)) {
        printf("%c", (char)(uart_rx_circular_buffer[p_fd].buffer[uart_rx_circular_buffer[p_fd].r_idx]));
        if ((uint8_t)(uart_rx_circular_buffer[p_fd].buffer[uart_rx_circular_buffer[p_fd].r_idx]) == 0x0d) {
          printf("\n");
        }
        INC_IDX(uart_rx_circular_buffer[p_fd].r_idx);
      }
    
      GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
      /* Set master to transmit mode */
      //MAP_I2C_setMode(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_MODE);
      /* Making sure the last transaction has been completely sent out */
      //while (MAP_I2C_masterIsStopSent(EUSCI_B1_BASE));
      /* Clear any existing interrupt flag */
      //MAP_I2C_clearInterruptFlag(EUSCI_B1_BASE, EUSCI_B_I2C_STOP_INTERRUPT | EUSCI_B_I2C_RECEIVE_INTERRUPT0 | EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
      /* Send start and the first byte of the transmit buffer. */
      //MAP_I2C_masterSendMultiByteStart(EUSCI_B1_BASE, 0x41);
      /* Wait for TX to finish */
      //while(!(MAP_I2C_getInterruptStatus(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0)));
      /* Clear any existing interrupt flag */
      //MAP_I2C_clearInterruptFlag(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
      /* Sent the first byte, now we need to initiate the read */
      //MAP_I2C_masterReceiveStart(EUSCI_B1_BASE);
      //MAP_I2C_enableInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
    }
    
    void EUSCIA0_IRQHandler(void) {
      const volatile uint_fast16_t isr_status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE);
      MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, isr_status);
      if (isr_status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG) {
        if (!BUFFER_FULL(uart_rx_circular_buffer[p_fd].r_idx, uart_rx_circular_buffer[p_fd].w_idx)) {
           uart_rx_circular_buffer[p_fd].buffer[uart_rx_circular_buffer[p_fd].w_idx] = MAP_UART_receiveData(EUSCI_A0_BASE) & 0xff;
           INC_IDX(uart_rx_circular_buffer[p_fd].w_idx);
         }
      }
    }
    
    void PORT1_IRQHandler(void) {
      const volatile uint_fast16_t isr_status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P1);
      MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, isr_status);
      /* Toggling the output on the LED */
      if(isr_status & GPIO_PIN1) {
        MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN1); /* Red RGB Led */
      }
    }
    
    void ADC14_IRQHandler(void) {
      const volatile uint_fast16_t isr_status = MAP_ADC14_getEnabledInterruptStatus();
      ADC14_clearInterruptFlag(isr_status);
    
      /**
       *  Since the FPU is enabled in stacking mode, we are able to use the FPU safely to perform efficient floating point arithmetic.
       */
      if (isr_status & ADC_INT1) {
          static uint16_t results[8];
          // TODO Enhance using directly the registers
          MAP_ADC14_getMultiSequenceResult(results);
          adc_rx_circular_buffer[0].buffer[adc_rx_circular_buffer[0].w_idx] = results[0];
          INC_IDX(adc_rx_circular_buffer[0].w_idx);
          adc_rx_circular_buffer[1].buffer[adc_rx_circular_buffer[1].w_idx] = results[1];
          INC_IDX(adc_rx_circular_buffer[1].w_idx);
          MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P6, GPIO_PIN7); /* Analyzer Debug 5 */
          MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P6, GPIO_PIN7); /* Analyzer Debug 5 */
      }
    }
    
    int fputc(int p_char, register FILE *p_fp) {
      while (!(UCA0IFG & UCTXIFG));
      UCA0TXBUF = (unsigned char) p_char;
      return (unsigned char)p_char;
    }
    
    int fputs(const char *p_buffer, register FILE *p_fp) {
      uint32_t i, len;
      len = strlen(p_buffer);
      for(i = 0 ; i < len ; i++) {
        while(!(UCA0IFG & UCTXIFG));
        UCA0TXBUF = (unsigned char) p_buffer[i];
      }
      return len;
    }
    
    
    

  • Hello Chris,

    My apologies, I attached a buggy version. Here is the correct one with the issue I described previously.

    Best regards,

    Yann

    /* DriverLib Includes */
    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
    
    /* Standard Includes */
    #include <stdint.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdarg.h>
    
    
    int fputc(int _c, register FILE *_fp);
    int fputs(const char *_ptr, register FILE *_fp);
    
    
    /*!< Fixed size of the buffer */
    #define CIRCULAR_BUFFER_SIZE 32
    /*!< True if the buffer is empty */
    #define BUFFER_EMPTY(r_idx, w_idx) (bool)(r_idx == w_idx)
    /*!< True if the buffer is empty */
    #define BUFFER_FULL(r_idx, w_idx)  (bool)(((w_idx + 1) % CIRCULAR_BUFFER_SIZE) == r_idx)
    /*!< Increment the index */
    #define INC_IDX(idx)         idx = ((idx + 1) % CIRCULAR_BUFFER_SIZE)
    /*!< Decrement the index */
    #define DEC_IDX(idx)         idx = ((idx == 0) ? CIRCULAR_BUFFER_SIZE - 1 : idx - 1)
    
    /** \struct Circular buffer data structure
    */
    typedef struct {
      uint16_t r_idx;             /*!< The read index */
      uint16_t w_idx;             /*!< The write index */
      uint8_t buffer[CIRCULAR_BUFFER_SIZE]; /*!< The buffer of data */
    } circular_bytes_buffer_t;
    typedef struct {
      uint16_t r_idx;             /*!< The read index */
      uint16_t w_idx;             /*!< The write index */
      uint16_t buffer[CIRCULAR_BUFFER_SIZE]; /*!< The buffer of data */
    } circular_words_buffer_t;
    
    
    #define SLAVE_ADDRESS     0x68 /* Slave Address for I2C Slave */
    #define NUM_OF_REC_BYTES  2    // TODO To be refined, NUM_OF_REC_BYTES is depending of the desired bytes to be read/written
    /*!< Receive circular buffer for I2C. Use volatile because it will be modified in ISR. */
    #define I2C_MODULE_MAX 1
    static volatile uint8_t p_i2c_bus_id = 0;
    static circular_bytes_buffer_t i2c_rx_circular_buffer[I2C_MODULE_MAX];
    /* I2C Master Configuration Parameter */
    static eUSCI_I2C_MasterConfig i2cConfig =
    {
      EUSCI_B_I2C_CLOCKSOURCE_SMCLK,      // SMCLK Clock Source
      12000000,                           // SMCLK = 12MHz
      EUSCI_B_I2C_SET_DATA_RATE_400KBPS,  // Desired I2C Clock of 400khz
      0,                                  // No byte counter threshold
      EUSCI_B_I2C_NO_AUTO_STOP            // No Autostop
    };
    
    /*!< Receive circular buffer for UART. */
    #define UART_MODULE_MAX 1
    static volatile uint8_t p_fd = 0;
    static circular_bytes_buffer_t uart_rx_circular_buffer[UART_MODULE_MAX];
    
    /* UART Configuration Parameter */
    static eUSCI_UART_Config uartConfig = { /* See http://processors.wiki.ti.com/index.php/USCI_UART_Baud_Rate_Gen_Mode_Selection#USCI_UART_Calculator */
      EUSCI_A_UART_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
      104,                                     // BRDIV = 104
      0,                                       // UCxBRF = 0
      1,                                       // UCxBRS = 1
      EUSCI_A_UART_NO_PARITY,                  // No Parity
      EUSCI_A_UART_LSB_FIRST,                  // MSB First
      EUSCI_A_UART_ONE_STOP_BIT,               // One stop bit
      EUSCI_A_UART_MODE,                       // UART mode
      EUSCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION  // Low Frequency Mode
    };
    
    
    /*
     * PWM generation based on Up/Down mode & capture on Timer A0 (output TA0.3 for TA0CCR3, TA0.4 for TA0CCR4
     * Stand alone process, Interrupts are not required
     */
    const Timer_A_UpDownModeConfig upDownConfig =
    {
      TIMER_A_CLOCKSOURCE_ACLK,              /* ACLK Clock Source frequency = 32000Hz */
      TIMER_A_CLOCKSOURCE_DIVIDER_1,         /* Timer Clock frequency = 32000Hz (0.03125ms) */
      320 - 1,                               /* T_output=20ms ==> 320 ticks for T/2, -1 stands for 'The number of timer counts in the period is TAxCCR0 + 1' */
      TIMER_A_TAIE_INTERRUPT_DISABLE,        /* Interrupts are not required */
      TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE,   /* Interrupts are not required */
      TIMER_A_DO_CLEAR
    };
    /* Timer_A Compare Configuration Parameter  (PWM1) */
    const Timer_A_CompareModeConfig compareConfig_PWM1 =
    {
      TIMER_A_CAPTURECOMPARE_REGISTER_3,          /* Use CCR3, TA0.3: p2.6 */
      TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE,   /* Interrupts are not required */
      TIMER_A_OUTPUTMODE_TOGGLE_RESET,              /* Toggle output but */
      32                                          /* Duty Cycle = 2ms = 10% of T=20ms ==> 32 ticks */
    };
    
    /* Timer_A Compare Configuration Parameter (PWM2) */
    const Timer_A_CompareModeConfig compareConfig_PWM2 =
    {
      TIMER_A_CAPTURECOMPARE_REGISTER_4,          /* Use CCR4, TA0.4: p2.7 */
      TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE,   /* Interrupts are not required */
      TIMER_A_OUTPUTMODE_TOGGLE_RESET,              /* Toggle output but */
      16                                          /* Duty Cycle  1ms = 5% of T=20ms ==> 16 ticks */
    };
    
    
    /* Timer_A UpMode Configuration Parameter */
    static Timer_A_UpModeConfig upConfig =
    {
      TIMER_A_CLOCKSOURCE_ACLK,              /* ACLK Clock Source frequency = 32000Hz */
      TIMER_A_CLOCKSOURCE_DIVIDER_1,         /* Timer Clock frequency = 32000Hz (0.03125ms) */
      16000 - 1,                             /* T_output=1s ==> 16000 ticks for T/2, -1 stands for 'The number of timer counts in the period is TAxCCR0 + 1' */
      TIMER_A_TAIE_INTERRUPT_DISABLE,
      TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE,
      TIMER_A_DO_CLEAR
    };
    static Timer_A_ContinuousModeConfig contConfig =
    {
      TIMER_A_CLOCKSOURCE_ACLK,              /* ACLK Clock Source frequency = 32000Hz */
      TIMER_A_CLOCKSOURCE_DIVIDER_1,         /* Timer Clock frequency = 32000Hz (0.03125ms) */
      TIMER_A_TAIE_INTERRUPT_ENABLE,
      TIMER_A_DO_CLEAR
    };
    
    
    /*!< Receive circular buffer for ADC */
    #define ADC_MODULE_MAX 2    // TODO To be refined, ADC_MODULE_MAX is depending of the desired ADC entries
    static volatile uint8_t p_adc = 0;
    static circular_words_buffer_t adc_rx_circular_buffer[ADC_MODULE_MAX];
    
    
    static float onboard_temperature_calibration;
    static float onboard_temperature;
    static float battery_voltage;
    
    
    
    int main(void)
    {
      /* Halting WDT and disabling master interrupts */
      MAP_WDT_A_holdTimer();
      /* Enable processor interrupts */
      MAP_Interrupt_disableMaster();
      /* Seed the pseudo random num generator */
      //  srand(TLV->RANDOM_NUM_1);
      /* Set the core voltage level to VCORE1 */
      MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
      /* Enabling FPU for DCO Frequency calculation.
       * Enabling the FPU with stacking enabled (for use within ISR)
       */
      MAP_FPU_enableModule();
      MAP_FPU_enableLazyStacking();
      /* Set 2 flash wait states for Flash bank 0 and 1*/
      MAP_FlashCtl_setWaitState(FLASH_BANK0, 2);
      MAP_FlashCtl_setWaitState(FLASH_BANK1, 2);
      /* Initializes Clock System */
      MAP_CS_setDCOFrequency(CS_48MHZ);                                         /* System clock: 48MHz. Required PCM_VCORE1 */
      MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_2);    /* Master clock set to internal 24MHz, Used by Timer 32 */
      MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_2);  /* Subsystem master clock set to internal 24MHz */
      MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_4);   /* Low-speed subsystem master clock set to internal 12MHz, used by UART console, I2C and ADC14 */
    //  MAP_CS_initClockSignal(CS_MODOSC_SELECT, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_2);
                                                                                /* Master clock set to internal 24MHz, Used by ADC */
      MAP_CS_setReferenceOscillatorFrequency(CS_REFO_32KHZ);                    /* Selects internal REFO clock source to 32000Hz */
                                                                                /* MSP432P401R does not support CS_REFO_128KHZ */
      MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);   /* Auxiliary clock A set to internal 32000Hz, used by PWM & Timer A */
                                                                                /* ==> Tmin = 31.15us */
      uint32_t sys_clock = MAP_CS_getDCOFrequency();
      uint32_t aclk = MAP_CS_getACLK();
      uint32_t mclk = MAP_CS_getMCLK();
      uint32_t smclk = MAP_CS_getSMCLK();
      uint32_t hsmclk = MAP_CS_getHSMCLK();
      uint32_t bclk = MAP_CS_getBCLK();
    
    
      /* Initialize GPIO interrupt functions table */
      MAP_GPIO_disableInterrupt(GPIO_PORT_P1, PIN_ALL16);
      MAP_GPIO_disableInterrupt(GPIO_PORT_P2, PIN_ALL16);
      MAP_Interrupt_enableInterrupt(INT_PORT1);
      MAP_Interrupt_enableInterrupt(INT_PORT2);
    
    
      /* Select Port 1 for I2C - Set Pin 4, 5 to input Primary Module Function (UCB1SIMO/UCB1SDA, UCB1SOMI/UCB1SCL) */
      MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6, GPIO_PIN5 | GPIO_PIN4, GPIO_PRIMARY_MODULE_FUNCTION);
      /* Initializing I2C Master to SMCLK at 100khz with no autostop */
      MAP_I2C_initMaster(EUSCI_B1_BASE, &i2cConfig);
      /* Specify slave address */
      MAP_I2C_setSlaveAddress(EUSCI_B1_BASE, SLAVE_ADDRESS);
      /* Enable I2C Module to start operations */
      MAP_I2C_enableModule(EUSCI_B1_BASE);
      MAP_Interrupt_enableInterrupt(INT_EUSCIB1);
    
    
      /* Reset RX/TX buffer data structures */
      uart_rx_circular_buffer[p_fd].r_idx = 0;
      uart_rx_circular_buffer[p_fd].w_idx = 0;
      /* Selecting P1.2 and P1.3 in UART mode */
      MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
      /* Configuring UART Module */
      i2cConfig.i2cClk = smclk;
      MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig);
      /* Enable UART module */
      MAP_UART_enableModule(EUSCI_A0_BASE);
      /* Enabling interrupts */
      MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);
      MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
    
      /***
       * IO mapping
       *   GPIO_PORT_P1/GPIO_PIN0: On board red led
       *   GPIO_PORT_P1/GPIO_PIN1: On board switch #1
       *   GPIO_PORT_P2/GPIO_PIN0: On board red RGB led
       *   GPIO_PORT_P2/GPIO_PIN1: On board green RGB led
       *   GPIO_PORT_P2/GPIO_PIN2: On board blue RGB led
       *   GPIO_PORT_P2/GPIO_PIN7: PWM2, Saleae Analyzer: Debug 0
       *   GPIO_PORT_P2/GPIO_PIN6: PWM1, Saleae Analyzer: Debug 1
       *   GPIO_PORT_P2/GPIO_PIN4: Timer A, Up mode, Saleae Analyzer: Debug 2
       *   GPIO_PORT_P5/GPIO_PIN6: Timer A, Continuous mode, Saleae Analyzer: Debug 3
       *   GPIO_PORT_P6/GPIO_PIN6: Timer 32, Continuous mode, Saleae Analyzer: Debug 4
       *   GPIO_PORT_P6/GPIO_PIN7: ADC14, Repetition mode, Saleae Analyzer: Debug 5
       *
       * GPIO functions: See Microcontroller Engineering with MSP432 Fundamentals and Applications, Table 7.1 GPIO port 1 (P1.0~P1.7) pin functions
       */
    
      /* Configuring P1.1 as an input (SW1) and enabling interrupts */
      MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1);
      MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1);
      MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1);
      /* Configuring P1.4 as an input (SW2) and enabling interrupts */
      MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN4);
      MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN4);
      MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN4);
    
      /* Selecting P1.0 as output (on board RED LED) for SysTick. */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
    
      /* Selecting P2.0 as output (on board RED RGB LED) for Button 1 interrupt handler. */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0);
      /* Selecting P2.1 as output (on board GREEN RGB LED) for xxx. */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN1);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN1);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN1);
      /* Selecting P2.2 as output (on board BLUE RGB LED) for xxx. */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN2);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN2);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN2);
    
      /* Selecting P2.7 as TA0.4 output, PWM2. */
      MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);
      /* Selecting P2.6 as TA0.3 output, PWM1. */
      MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN6, GPIO_PRIMARY_MODULE_FUNCTION);
    
      /* Selecting P2.4 as output for Timer A in Up mode (Analyzer). */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN4);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN4);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN4);
      /* Selecting P5.6 as output for Timer A in Continuous mode (Analyzer). */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P5, GPIO_PIN6);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN6);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P5, GPIO_PIN6);
      /* Selecting P6.6 as output for Timer 32 in Continuous mode (Analyzer). */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN6);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN6);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN6);
      /* Selecting P6.7 as output for adc14 sampling trigger (Analyzer). */
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN7);
      MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN7);
      MAP_GPIO_setAsOutputPin(GPIO_PORT_P6, GPIO_PIN7);
    
    
      /* Set SysTick timer */
      MAP_SysTick_setPeriod((sys_clock / 24 / 8)); /* Configuring SysTick to trigger an interrupt at [4.16ms (1/24)]/8 to prevent flashing effect. With Fosc at 48MHz, 1/24/8 = 5.2ms = 250000 ticks */
      MAP_SysTick_enableModule();
      MAP_Interrupt_setPriority(FAULT_SYSTICK, 2);
      MAP_SysTick_enableInterrupt();
    
    
      /* Configuring Timer A0 for Up/Down mode */
      MAP_Timer_A_configureUpDownMode(TIMER_A0_BASE, &upDownConfig);
      /* Initialize compare registers to generate PWM1 */
      MAP_Timer_A_initCompare(TIMER_A0_BASE, &compareConfig_PWM1);
      /* Initialize compare registers to generate PWM2 */
      MAP_Timer_A_initCompare(TIMER_A0_BASE, &compareConfig_PWM2);
      /* Start timer A0 to generate PWM */
      MAP_Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_UPDOWN_MODE);
    
    
      /* Timer A1 in Up mode */
      MAP_Timer_A_configureUpMode(TIMER_A1_BASE, &upConfig);
      MAP_Timer_A_startCounter(TIMER_A1_BASE, TIMER_A_UP_MODE);
      /* Timer A1 in Continuous mode */
      MAP_Timer_A_configureContinuousMode(TIMER_A2_BASE, &contConfig);
      MAP_Interrupt_enableInterrupt(INT_TA1_0);
      MAP_Interrupt_enableInterrupt(INT_TA2_N);
      MAP_Timer_A_startCounter(TIMER_A2_BASE, TIMER_A_CONTINUOUS_MODE);
    
    
      /* Configuring Timer 32 to 100ms (0.1 * 24000000) of MCLK in periodic mode */
      MAP_Timer32_setCount(TIMER32_0_BASE, 24000000); //==> TIMER32_PERIODIC_MODE instead of TIMER32_FREE_RUN_MODE
      MAP_Timer32_initModule(TIMER32_0_BASE, TIMER32_PRESCALER_1, TIMER32_32BIT, TIMER32_PERIODIC_MODE);
      MAP_Timer32_enableInterrupt(TIMER32_0_BASE);
      MAP_Interrupt_enableInterrupt(INT_T32_INT1);
      MAP_Timer32_startTimer(TIMER32_0_BASE, false/* Continuous mode */);
    
    
      /* Reset RX/TX buffer data structures */
      adc_rx_circular_buffer[0].r_idx = 0;
      adc_rx_circular_buffer[0].w_idx = 0;
      adc_rx_circular_buffer[1].r_idx = 0;
      adc_rx_circular_buffer[1].w_idx = 0;
      /* Setting reference voltage to 2.5 and enabling reference */
      MAP_REF_A_setReferenceVoltage(REF_A_VREF2_5V);
      MAP_REF_A_enableReferenceVoltage();
      /* Initializing ADC (ACLK/1/3) with temperature sensor and battery routed, ACLK=32KHz ==> ADCCLK=4KHz */
      MAP_ADC14_initModule(ADC_CLOCKSOURCE_ACLK, ADC_PREDIVIDER_1, ADC_DIVIDER_3, ADC_TEMPSENSEMAP | ADC_BATTMAP);
      /* Use multiple memories sample */
      MAP_ADC14_configureMultiSequenceMode(ADC_MEM0, ADC_MEM1, true);
      /* Set ADC channel 22 (On board temperature) conversion with Vss as negative reference */
      MAP_ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A22, false);
      /* Set ADC channel 23 (On board battery level) conversion with Vss as negative reference */
      MAP_ADC14_configureConversionMemory(ADC_MEM1, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A23, false);
      /* Configuring the sample trigger to be sourced from ADCCLK and on the rising edge */
      MAP_ADC14_setSampleHoldTrigger(ADC_TRIGGER_ADCSC, false);
      /* Enabling sample timer in auto iteration mode and interrupts */
      MAP_ADC14_enableSampleTimer(ADC_AUTOMATIC_ITERATION);
      /* Enable ADC module */
      MAP_ADC14_enableModule();
      /* Enabling the interrupt when a conversion on channel 31 (end of sequence) is complete and enabling conversions */
      MAP_ADC14_enableInterrupt(ADC_INT1);
      MAP_Interrupt_enableInterrupt(INT_ADC14);
      /* Enabling  conversions */
      MAP_ADC14_enableConversion();
      MAP_ADC14_toggleConversionTrigger();
    
    
      /* Set the temperature calibration value required to calculate the temperature */
      onboard_temperature_calibration =
                                        MAP_SysCtl_getTempCalibrationConstant(SYSCTL_2_5V_REF, SYSCTL_85_DEGREES_C) -
                                        MAP_SysCtl_getTempCalibrationConstant(SYSCTL_2_5V_REF, SYSCTL_30_DEGREES_C);
    
    
      MAP_Interrupt_enableSleepOnIsrExit();
      MAP_Interrupt_enableMaster();
    
    
      printf("\r\nHow to use printf ;)\r\n"); // Disable EUSCIA0 before to use printf
      printf("Decimal(10) :%d\r\n", 10);
      printf("Hex(10)   :%x\r\n", 10);
      printf("float     :%f\r\n", 4.32);
    
    
      /* Main while loop */
      while(1)
      {
        MAP_PCM_gotoLPM0();
      }
    }
    
    /*******************************************************************************
     * eUSCIB1 ISR. The repeated start and transmit/receive operations happen
     * within this ISR.
     *******************************************************************************/
    void EUSCIB1_IRQHandler(void) {
      const volatile uint_fast16_t isr_status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B1_BASE);
      MAP_I2C_clearInterruptFlag(EUSCI_B1_BASE, isr_status);
    
      /* Receives bytes into the receive buffer. If we have received all bytes,
       * send a STOP condition */
      if (isr_status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)
      {
        if (i2c_rx_circular_buffer[p_i2c_bus_id].w_idx == NUM_OF_REC_BYTES - 2)
        {
          i2c_rx_circular_buffer[p_i2c_bus_id].buffer[i2c_rx_circular_buffer[p_i2c_bus_id].w_idx] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE);
          INC_IDX(i2c_rx_circular_buffer[p_i2c_bus_id].w_idx);
          MAP_I2C_disableInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
          MAP_I2C_enableInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_STOP_INTERRUPT);
          MAP_I2C_masterReceiveMultiByteStop(EUSCI_B1_BASE);
        } else
        {
          i2c_rx_circular_buffer[p_i2c_bus_id].buffer[i2c_rx_circular_buffer[p_i2c_bus_id].w_idx] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE);
          INC_IDX(i2c_rx_circular_buffer[p_i2c_bus_id].w_idx);
        }
      }
      else if (isr_status & EUSCI_B_I2C_STOP_INTERRUPT)
      {
        i2c_rx_circular_buffer[p_i2c_bus_id].buffer[i2c_rx_circular_buffer[p_i2c_bus_id].w_idx] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE);
        INC_IDX(i2c_rx_circular_buffer[p_i2c_bus_id].w_idx);
        MAP_I2C_disableInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_STOP_INTERRUPT);
      }
    }
    
    void TA1_0_IRQHandler(void) {
      MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A1_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_0);
      MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN4); /* Analyzer Debug 2 */
    }
    
    void TA2_N_IRQHandler(void) {
      MAP_Timer_A_clearInterruptFlag(TIMER_A2_BASE);
      MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P5, GPIO_PIN6);
    }
    
    void T32_INT1_IRQHandler(void) {
      MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE);
      MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P6, GPIO_PIN6); /* Analyzer Debug 4 */
      MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P6, GPIO_PIN6); /* Analyzer Debug 4 */
      // TODO Consume the ADC14 samples here
    }
    
    void SysTick_Handler(void) {
      /* Reset RX buffer */
      i2c_rx_circular_buffer[p_i2c_bus_id].r_idx = 0;
      i2c_rx_circular_buffer[p_i2c_bus_id].w_idx = 0;
    
      /* Echo back if any */
      if (!BUFFER_EMPTY(uart_rx_circular_buffer[p_fd].r_idx, uart_rx_circular_buffer[p_fd].w_idx)) {
        printf("%c", (char)(uart_rx_circular_buffer[p_fd].buffer[uart_rx_circular_buffer[p_fd].r_idx]));
        if ((uint8_t)(uart_rx_circular_buffer[p_fd].buffer[uart_rx_circular_buffer[p_fd].r_idx]) == 0x0d) {
          printf("\n");
        }
        INC_IDX(uart_rx_circular_buffer[p_fd].r_idx);
      }
    
      //printf("Test\r\n");
      GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
      /* Set master to transmit mode */
      //MAP_I2C_setMode(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_MODE);
      /* Making sure the last transaction has been completely sent out */
      //while (MAP_I2C_masterIsStopSent(EUSCI_B1_BASE));
      /* Clear any existing interrupt flag */
      //MAP_I2C_clearInterruptFlag(EUSCI_B1_BASE, EUSCI_B_I2C_STOP_INTERRUPT | EUSCI_B_I2C_RECEIVE_INTERRUPT0 | EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
      /* Send start and the first byte of the transmit buffer. */
      //MAP_I2C_masterSendMultiByteStart(EUSCI_B1_BASE, 0x41);
      /* Wait for TX to finish */
      //while(!(MAP_I2C_getInterruptStatus(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0)));
      /* Clear any existing interrupt flag */
      //MAP_I2C_clearInterruptFlag(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
      /* Sent the first byte, now we need to initiate the read */
      //MAP_I2C_masterReceiveStart(EUSCI_B1_BASE);
      //MAP_I2C_enableInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
    }
    
    void EUSCIA0_IRQHandler(void) {
      const volatile uint_fast16_t isr_status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE);
      MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, isr_status);
      if (isr_status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG) {
        if (!BUFFER_FULL(uart_rx_circular_buffer[p_fd].r_idx, uart_rx_circular_buffer[p_fd].w_idx)) {
           uart_rx_circular_buffer[p_fd].buffer[uart_rx_circular_buffer[p_fd].w_idx] = MAP_UART_receiveData(EUSCI_A0_BASE) & 0xff;
           INC_IDX(uart_rx_circular_buffer[p_fd].w_idx);
         }
      }
    }
    
    void PORT1_IRQHandler(void) {
      const volatile uint_fast16_t isr_status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P1);
      MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, isr_status);
      /* Toggling the output on the LED */
      if(isr_status & GPIO_PIN1) {
        MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN1); /* Red RGB Led */
      }
    }
    
    void ADC14_IRQHandler(void) {
      const volatile uint_fast16_t isr_status = MAP_ADC14_getEnabledInterruptStatus();
      ADC14_clearInterruptFlag(isr_status);
    
      /**
       *  Since the FPU is enabled in stacking mode, we are able to use the FPU safely to perform efficient floating point arithmetic.
       */
      if (isr_status & ADC_INT1) {
          static uint16_t results[8];
          // TODO Enhance using directly the registers
          MAP_ADC14_getMultiSequenceResult(results);
          adc_rx_circular_buffer[0].buffer[adc_rx_circular_buffer[0].w_idx] = results[0];
          INC_IDX(adc_rx_circular_buffer[0].w_idx);
          adc_rx_circular_buffer[1].buffer[adc_rx_circular_buffer[1].w_idx] = results[1];
          INC_IDX(adc_rx_circular_buffer[1].w_idx);
          MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P6, GPIO_PIN7); /* Analyzer Debug 5 */
          MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P6, GPIO_PIN7); /* Analyzer Debug 5 */
      }
    }
    
    int fputc(int p_char, register FILE *p_fp) {
      while (!(UCA0IFG & UCTXIFG));
      UCA0TXBUF = (unsigned char) p_char;
      return (unsigned char)p_char;
    }
    
    int fputs(const char *p_buffer, register FILE *p_fp) {
      uint32_t i, len;
      len = strlen(p_buffer);
      for(i = 0 ; i < len ; i++) {
        while(!(UCA0IFG & UCTXIFG));
        UCA0TXBUF = (unsigned char) p_buffer[i];
      }
      return len;
    }
    
    
    

  • > MAP_Timer32_setCount(TIMER32_0_BASE, 24000000); //==> TIMER32_PERIODIC_MODE instead of TIMER32_FREE_RUN_MODE

    > MAP_Timer32_initModule(TIMER32_0_BASE, TIMER32_PRESCALER_1, TIMER32_32BIT, TIMER32_PERIODIC_MODE);

    I recommend you do these in the opposite order. Since the timer is in 16-bit mode when you call setCount, the period is set to 0xFFFF, so the timer interrupts every 1 ms, not every 1 sec. This will slow down the SysTick handler (at lower priority), maybe to the point that it appears to stall. In any case, I don't think it's what you want.

    [Edit: ]

    Also:

    > MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, isr_status);

    I recommend you Not do this. Instead, always call receiveData (if the RECEIVE_INTERRUPT_FLAG is set), then decide what to do. This call sets up a race which can cause the symptom you describe. (It's usually more of a problem with high data rates, but it's always possible.)

  • Hello Bruce,

    I. Timer 32

    For Timer 32, you're right, I fully missed it, thanks a lot.

    More generally, I want to developed an Inertial Movement Unit application linked to some multi-channels analog sampling & digital signal processing. The main features are:

    1) Interaction and settings of the application using UART

    2) MPU6050 support (I2C, SPI)

    3) Motor and server-motors driving (PWM)

    4) Analog read

    5) Multiple analog input signal sampling, signal processing and correction of movement (include DMA support)

    6) Try to use ISR as much as possible

    When I opened this case, I got issues with I2C (ISR not called).

    After fighting some times with my own code, I decided to restart from scratch and add each feature (UART, PWM, ) one by one.

    Currently, I'm supporting PWM, servo-motors control and UART). 

    I wanted to use Systick to trigger SPI/I2C read operations to get raw data from MPU6050... and the Timer 32 for user outputs (calculation and display of direction, speed...). It seems this is not a good idea? What could be the nice way?

    II. UART

    Regarding the UART, do you mean that I have not to clear interrupt flags in case of an incoming character from the console? If so, I'm not sure to understand you (sorry).

    Many thanks for your help,

    Best regards,

    Yann

  • > II. UART
    I recommend you not use clearInterruptFlag to clear the Rx interrupt flag (RXIFG), since it's not atomic. receiveData clears RXIFG atomically. clearInterruptFlag has the potential to (unintentionally) clear the TXIFG, which will cause your UART (Tx) to stall. People trip over this every so often here, e.g.:

    e2e.ti.com/.../2543693

    I don't know that that is what is happening here, but the symptom matches, and the clearInterruptFlag call is unnecessary.

    > I. Timer 32
    What you're trying to do isn't impossible, but hand-scheduling gets progressively more difficult as complexity grows. You also need to avoid over-committing your CPU (trying to do too much), which requires a certain amount of measurement.

  • Hello Bruce,

    Thanks a lot, it works fine now.

    Let's continue ;)

    Best regards

    Yann

**Attention** This is a public forum