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.

TM4C123GH6PM, Sensorhub, MPU9150 example problem, Available pins? PWM and UART trouble

Other Parts Discussed in Thread: TM4C123GH6PM, EK-TM4C123GXL

Hi everyone!

Having some trouble using available pins when my TM4C123GH6PM board has the SensorHub attached to it.

My goal is to use the MPU9150 example and add some code for 4 separate PWM outputs, and a single UART input.

I have to separate problems.

Nr.1: Finding available pins for the 4 separate PWM outputs. Can you help? I still want the MPU9150  working.

From the "BOOSTXL-SENSHUB Sensor Hub BoosterPack - SPMU290 User Manual" i have following available pins (shaded cells):

From the tiva datasheet I have following PWM pins:

Nr.2: Have reading problems on my UART5 - U5RX pin. The UART5 receives data to the buffer, though it passes chunks at some time and then no data. The stream should be continuously.

Is there a problem with using U5RX when running the sensorhub and the MPU9150? Do I have a mixup?
Maby I have a mixup on the clockspeeds or something?

Here are all UART pins on the main board:

Here is my sample code (UART code marked in green):

//*****************************************************************************
//
// compdcm_mpu9150.c - Example use of the SensorLib with the MPU9150
//
// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved.
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 2.1.0.12573 of the EK-TM4C123GXL Firmware Package.
//
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "sensorlib/hw_mpu9150.h"
#include "sensorlib/hw_ak8975.h"
#include "sensorlib/i2cm_drv.h"
#include "sensorlib/ak8975.h"
#include "sensorlib/mpu9150.h"
#include "sensorlib/comp_dcm.h"
#include "drivers/rgb.h"

//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>Nine Axis Sensor Fusion with the MPU9150 and Complimentary-Filtered
//! DCM (compdcm_mpu9150)</h1>
//!
//! This example demonstrates the basic use of the Sensor Library, TM4C123G
//! LaunchPad and SensHub BoosterPack to obtain nine axis motion measurements
//! from the MPU9150. The example fuses the nine axis measurements into a set
//! of Euler angles: roll, pitch and yaw. It also produces the rotation
//! quaternions. The fusion mechanism demonstrated is complimentary-filtered
//! direct cosine matrix (DCM) algorithm is provided as part of the Sensor
//! Library.
//!
//! Connect a serial terminal program to the LaunchPad's ICDI virtual serial
//! port at 115,200 baud. Use eight bits per byte, no parity and one stop bit.
//! The raw sensor measurements, Euler angles and quaternions are printed to
//! the terminal. The RGB LED begins to blink at 1Hz after initialization is
//! completed and the example application is running.
//
//*****************************************************************************
#define MPU9150_I2C_ADDRESS 0x68 // Define MPU9150 I2C Address.
uint32_t g_pui32Colors[3]; // Global array for holding the color values for the RGB.
tI2CMInstance g_sI2CInst; // Global instance structure for the I2C master driver.
tMPU9150 g_sMPU9150Inst; // Global instance structure for the ISL29023 sensor driver.
tCompDCM g_sCompDCMInst; // Global Instance structure to manage the DCM state.
volatile uint_fast8_t g_vui8I2CDoneFlag; // Global flags to alert main that MPU9150 I2C transaction is complete
volatile uint_fast8_t g_vui8ErrorFlag; // Global flags to alert main that MPU9150 I2C transaction error has occurred.
volatile uint_fast8_t g_vui8DataFlag; // Global flags to alert main that MPU9150 data is ready to be retrieved.
#define PRINT_SKIP_COUNT 10 // Global counter to control and slow down the rate of data to the terminal.
uint32_t g_ui32PrintSkipCounter;

// The error routine that is called if the driver library encounters an error.
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

// MPU9150 Sensor callback function. Called at the end of MPU9150 sensor
// driver transactions. This is called from I2C interrupt context. Therefore,
// we just set a flag and let main do the bulk of the computations and display.
void
MPU9150AppCallback(void *pvCallbackData, uint_fast8_t ui8Status)
{
//
// If the transaction succeeded set the data flag to indicate to
// application that this transaction is complete and data may be ready.
//
if(ui8Status == I2CM_STATUS_SUCCESS)
{
g_vui8I2CDoneFlag = 1;
}

//
// Store the most recent status in case it was an error condition
//
g_vui8ErrorFlag = ui8Status;
}

// Called by the NVIC as a result of GPIO port B interrupt event. For this
// application GPIO port B pin 2 is the interrupt line for the MPU9150
void
IntGPIOb(void)
{
unsigned long ulStatus;

ulStatus = GPIOIntStatus(GPIO_PORTB_BASE, true);

//
// Clear all the pin interrupts that are set
//
GPIOIntClear(GPIO_PORTB_BASE, ulStatus);

if(ulStatus & GPIO_PIN_2)
{
//
// MPU9150 Data is ready for retrieval and processing.
//
MPU9150DataRead(&g_sMPU9150Inst, MPU9150AppCallback, &g_sMPU9150Inst);
}
}

// Called by the NVIC as a result of I2C3 Interrupt. I2C3 is the I2C connection
// to the MPU9150.
void
MPU9150I2CIntHandler(void)
{
//
// Pass through to the I2CM interrupt handler provided by sensor library.
// This is required to be at application level so that I2CMIntHandler can
// receive the instance structure pointer as an argument.
//
I2CMIntHandler(&g_sI2CInst);
}

// MPU9150 Application error handler. Show the user if we have encountered an
// I2C error.,
void
MPU9150AppErrorHandler(char *pcFilename, uint_fast32_t ui32Line)
{
//
// Set RGB Color to RED
//
g_pui32Colors[0] = 0xFFFF;
g_pui32Colors[1] = 0;
g_pui32Colors[2] = 0;
RGBColorSet(g_pui32Colors);

//
// Increase blink rate to get attention
//
RGBBlinkRateSet(10.0f);

//
// Go to sleep wait for interventions. A more robust application could
// attempt corrective actions here.
//
while(1)
{
//
// Do Nothing
//
}
}

// Function to wait for the MPU9150 transactions to complete. Use this to spin
// wait on the I2C bus.
void
MPU9150AppI2CWait(char *pcFilename, uint_fast32_t ui32Line)
{
//
// Put the processor to sleep while we wait for the I2C driver to
// indicate that the transaction is complete.
//
while((g_vui8I2CDoneFlag == 0) && (g_vui8ErrorFlag == 0))
{
//
// Do Nothing
//
}

//
// If an error occurred call the error handler immediately.
//
if(g_vui8ErrorFlag)
{
MPU9150AppErrorHandler(pcFilename, ui32Line);
}

//
// clear the data flag for next use.
//
g_vui8I2CDoneFlag = 0;
}

// Configure the UART and its pins.
void
ConfigureUART(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART5);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
GPIOPinConfigure(GPIO_PE4_U5RX);
GPIOPinConfigure(GPIO_PE5_U5TX); // NOT BEING USED, ONLY RX
GPIOPinTypeUART(GPIO_PORTE_BASE, GPIO_PIN_4);
UARTConfigSetExpClk(UART5_BASE, ROM_SysCtlClockGet(), 115200,
(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
}


// Main application entry point.
int_fast32_t i32IPart[16], i32FPart[16];
char buffer[16];

int
main(void)
{

uint_fast32_t ui32Idx, ui32CompDCMStarted;
float pfData[16];
float *pfAccel, *pfGyro, *pfMag, *pfEulers, *pfQuaternion;

//
// Initialize convenience pointers that clean up and clarify the code
// meaning. We want all the data in a single contiguous array so that
// we can make our pretty printing easier later.
//
pfAccel = pfData;
pfGyro = pfData + 3;
pfMag = pfData + 6;
pfEulers = pfData + 9;
pfQuaternion = pfData + 12;

//
// Setup the system clock to run at 40 Mhz from PLL with crystal reference
//
ROM_SysCtlClockSet(SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
SYSCTL_OSC_MAIN);

//
// Enable port B used for motion interrupt.
//
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

//
// Initialize the UART.
//
ConfigureUART();

//
// Set the color to a purple approximation.
//
g_pui32Colors[RED] = 0x8000;
g_pui32Colors[BLUE] = 0x8000;
g_pui32Colors[GREEN] = 0x0000;

//
// Initialize RGB driver.
//
RGBInit(0);
RGBColorSet(g_pui32Colors);
RGBIntensitySet(0.5f);
RGBEnable();

//
// The I2C3 peripheral must be enabled before use.
//
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C3);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

//
// Configure the pin muxing for I2C3 functions on port D0 and D1.
//
ROM_GPIOPinConfigure(GPIO_PD0_I2C3SCL);
ROM_GPIOPinConfigure(GPIO_PD1_I2C3SDA);

//
// Select the I2C function for these pins. This function will also
// configure the GPIO pins pins for I2C operation, setting them to
// open-drain operation with weak pull-ups. Consult the data sheet
// to see which functions are allocated per pin.
//
GPIOPinTypeI2CSCL(GPIO_PORTD_BASE, GPIO_PIN_0);
ROM_GPIOPinTypeI2C(GPIO_PORTD_BASE, GPIO_PIN_1);

//
// Configure and Enable the GPIO interrupt. Used for INT signal from the
// MPU9150
//
ROM_GPIOPinTypeGPIOInput(GPIO_PORTB_BASE, GPIO_PIN_2);
GPIOIntEnable(GPIO_PORTB_BASE, GPIO_PIN_2);
ROM_GPIOIntTypeSet(GPIO_PORTB_BASE, GPIO_PIN_2, GPIO_FALLING_EDGE);
ROM_IntEnable(INT_GPIOB);

//
// Keep only some parts of the systems running while in sleep mode.
// GPIOB is for the MPU9150 interrupt pin.
// TIMER0, TIMER1 and WTIMER5 are used by the RGB driver
// I2C3 is the I2C interface to the ISL29023
//
ROM_SysCtlPeripheralClockGating(true);
ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOB);
// ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART5);
ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_TIMER0);
ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_TIMER1);
ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_I2C3);
ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_WTIMER5);

//
// Enable interrupts to the processor.
//
ROM_IntMasterEnable();

//
// Initialize I2C3 peripheral.
//
I2CMInit(&g_sI2CInst, I2C3_BASE, INT_I2C3, 0xff, 0xff,
ROM_SysCtlClockGet());

//
// Initialize the MPU9150 Driver.
//
MPU9150Init(&g_sMPU9150Inst, &g_sI2CInst, MPU9150_I2C_ADDRESS,
MPU9150AppCallback, &g_sMPU9150Inst);

//
// Wait for transaction to complete
//
MPU9150AppI2CWait(__FILE__, __LINE__);

//
// Write application specifice sensor configuration such as filter settings
// and sensor range settings.
//
g_sMPU9150Inst.pui8Data[0] = MPU9150_CONFIG_DLPF_CFG_94_98;
g_sMPU9150Inst.pui8Data[1] = MPU9150_GYRO_CONFIG_FS_SEL_250;
g_sMPU9150Inst.pui8Data[2] = (MPU9150_ACCEL_CONFIG_ACCEL_HPF_5HZ |
MPU9150_ACCEL_CONFIG_AFS_SEL_2G);
MPU9150Write(&g_sMPU9150Inst, MPU9150_O_CONFIG, g_sMPU9150Inst.pui8Data, 3,
MPU9150AppCallback, &g_sMPU9150Inst);

//
// Wait for transaction to complete
//
MPU9150AppI2CWait(__FILE__, __LINE__);

//
// Configure the data ready interrupt pin output of the MPU9150.
//
g_sMPU9150Inst.pui8Data[0] = MPU9150_INT_PIN_CFG_INT_LEVEL |
MPU9150_INT_PIN_CFG_INT_RD_CLEAR |
MPU9150_INT_PIN_CFG_LATCH_INT_EN;
g_sMPU9150Inst.pui8Data[1] = MPU9150_INT_ENABLE_DATA_RDY_EN;
MPU9150Write(&g_sMPU9150Inst, MPU9150_O_INT_PIN_CFG,
g_sMPU9150Inst.pui8Data, 2, MPU9150AppCallback,
&g_sMPU9150Inst);

//
// Wait for transaction to complete
//
MPU9150AppI2CWait(__FILE__, __LINE__);

//
// Initialize the DCM system. 50 hz sample rate.
// accel weight = .2, gyro weight = .8, mag weight = .2
//
CompDCMInit(&g_sCompDCMInst, 1.0f / 50.0f, 0.2f, 0.6f, 0.2f);

//
// Enable blinking indicates config finished successfully
//
RGBBlinkRateSet(1.0f);

ui32CompDCMStarted = 0;
int i = 0;
while(1)
{
//
// Go to sleep mode while waiting for data ready.
//
while(!g_vui8I2CDoneFlag)
{
ROM_SysCtlSleep();
}

//
// Clear the flag
//
g_vui8I2CDoneFlag = 0;

//
// Get floating point version of the Accel Data in m/s^2.
//
MPU9150DataAccelGetFloat(&g_sMPU9150Inst, pfAccel, pfAccel + 1,
pfAccel + 2);

//
// Get floating point version of angular velocities in rad/sec
//
MPU9150DataGyroGetFloat(&g_sMPU9150Inst, pfGyro, pfGyro + 1,
pfGyro + 2);

//
// Get floating point version of magnetic fields strength in tesla
//
MPU9150DataMagnetoGetFloat(&g_sMPU9150Inst, pfMag, pfMag + 1,
pfMag + 2);

//
// Check if this is our first data ever.
//
if(ui32CompDCMStarted == 0)
{
//
// Set flag indicating that DCM is started.
// Perform the seeding of the DCM with the first data set.
//
ui32CompDCMStarted = 1;
CompDCMMagnetoUpdate(&g_sCompDCMInst, pfMag[0], pfMag[1],
pfMag[2]);
CompDCMAccelUpdate(&g_sCompDCMInst, pfAccel[0], pfAccel[1],
pfAccel[2]);
CompDCMGyroUpdate(&g_sCompDCMInst, pfGyro[0], pfGyro[1],
pfGyro[2]);
CompDCMStart(&g_sCompDCMInst);
}
else
{
//
// DCM Is already started. Perform the incremental update.
//
CompDCMMagnetoUpdate(&g_sCompDCMInst, pfMag[0], pfMag[1],
pfMag[2]);
CompDCMAccelUpdate(&g_sCompDCMInst, pfAccel[0], pfAccel[1],
pfAccel[2]);
CompDCMGyroUpdate(&g_sCompDCMInst, -pfGyro[0], -pfGyro[1],
-pfGyro[2]);
CompDCMUpdate(&g_sCompDCMInst);
}

//
// Increment the skip counter. Skip counter is used so we do not
// overflow the UART with data.
//
g_ui32PrintSkipCounter++;
if(g_ui32PrintSkipCounter >= PRINT_SKIP_COUNT)
{
//
// Reset skip counter.
//
g_ui32PrintSkipCounter = 0;

//
// Get Euler data. (Roll Pitch Yaw)
//
CompDCMComputeEulers(&g_sCompDCMInst, pfEulers, pfEulers + 1,
pfEulers + 2);

//
// Get Quaternions.
//
CompDCMComputeQuaternion(&g_sCompDCMInst, pfQuaternion);

//
// convert mag data to micro-tesla for better human interpretation.
//
pfMag[0] *= 1e6;
pfMag[1] *= 1e6;
pfMag[2] *= 1e6;

//
// Convert Eulers to degrees. 180/PI = 57.29...
// Convert Yaw to 0 to 360 to approximate compass headings.
//
pfEulers[0] *= 57.295779513082320876798154814105f;
pfEulers[1] *= 57.295779513082320876798154814105f;
pfEulers[2] *= 57.295779513082320876798154814105f;
if(pfEulers[2] < 0)
{
pfEulers[2] += 360.0f;
}

//
// Now drop back to using the data as a single array for the
// purpose of decomposing the float into a integer part and a
// fraction (decimal) part.
//
for(ui32Idx = 0; ui32Idx < 16; ui32Idx++)
{
//
// Conver float value to a integer truncating the decimal part.
//
i32IPart[ui32Idx] = (int32_t) pfData[ui32Idx];
}


}

// Read the UART5
if (UARTCharsAvail(UART5_BASE))
{
buffer[i++] = UARTCharGet(UART5_BASE);
if (i == 16)
i = 0;
}
}
}

  • Alexander Waldejer said:
    Nr.2: Have reading problems on my UART5 - U5RX pin. The UART5 receives data to the buffer, though it passes chunks at some time and then no data. The stream should be continuously.

    Try just testing the UART5 if it works. You can use the uart_echo example program for testing.

    The SensorHub communicates to  your Launchpad using I2C and some GPIO for interrupts. So, I don't think it will conflict with UART5.

    - kel

  • Hi Kel,

    The UART5 is working fine. I have been using it a lot recently in a different project.

    Could you see any problems towards the clock? The Sensorhub example uses several interrups, can these cause problems?

  • Hello Alexander,

    Problem-1: You can get 4 PWM's but for doing that SW2 user switch on the main board must not be used. Also R8 resistor from TM4C123 launch pad needs to be removed. Is that OK?

    Problem-2: PE5 (UART5 TX) is getting connected to the Light Sensor Interrupt Line. However PE4 which is UART5-RX is not connected and should be OK to receive the data. I do see in the code you are reading the UART data into a buffer. But where is the buffer used?

    Regards

    Amit

  • Hi Amit,

    Problem-1: I don't need SW2 and can remove the R8. What PWM pins are then available to me?

    Problem-2: Yes, the UART data goes in to the buffer. Using the buffer comes later. Just want my reading working first. Is it okey using UART5-RX for one input, and the UART5-TX transmitting for a completely different (Light sensor)? The won't be a conflict when configuring these two?

  • Hello Alexander

    Problem-1: What I did was I took the Header Pin Configuration of the EK-TM4C123GXL and tallied it agains the Sensor Hub BreakOut. You may want to double check this

    J1.7:PB4:M0PWM2

    J2.4:PF0:M1PWM4

    J3.3:PD0:M0PWM6

    J3.4:PD1:M0PWM7

    Problem-2: The Light Sensor Pin is a Open Drain Pin which has a Pull Up and is used by the LS for Interrupt to the TM4C123. The same pin has UART-5 TX which is driven high. If your code does not use the Light Sensor, then I would suggest configuring it in GPIO Input Mode for the moment. Please do note that because of the LS connection (if it gets used), there could be potential contention problem on the U5TX.

    When you read the U5RX into the buffer, say a stream of data then what do you get? If you were to stream the data into U5RX say 1 character every second, every 100ms, every 1ms, how does the buffer look like? This will help us isolate the problem.

    Are you reading the buffer through the debugger? while the remote device is streaming in the data?

    Regards

    Amit

  • Hi Amit,

    Problem-1: I will try and configure the PWM outputs as you explained.

    Problem-2: The stream of data comes from a receiver (you helped me with that on another topic earlier this week: http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/361344/1269554.aspx#1269554).
    The stream of data should come systematically with all numbers in the same position, just updating according to what my transmitter is sending.

    I am reading the buffer through the debugger while my transmitter is on and sending data to the receiver (UART5).

    Only buffer[0] receives data, changing the numbers as long as the transmitter is one and sending.

    All 16, buffer[0] to buffer[15] should contain data.

    Maby i can one of the other UART's? Can you point out an available one (which is not used by the PWM) ?

  • Hello Alexander,

    Did you check the buffer memory address or the expression? It is always good to check.

    What I am seeing in the code is ROM_SysCtlSleep is enabled. Please note that if UART5 is receiving data when the device is in Sleep, you would need to enable the SCGCUART bit for the UART to get clock in Sleep Mode. Else Clock to UART in Sleep Mode will be gated and Data thus lost

    Regards

    Amit

  • Hi Amit,

    No difference on the reading when ROM_SysCtlSleep enabled or disabled.

    Are there any alternative UART's I can use instead UART5 (without any conflicts on PWM's and other pins used by the Sensor hub)?

  • Hello Alexander,

    UART-0 is the option. To debug the issue, open a COM port run the application and periodically send a character. Put a break point on the UARTCharGet and then check if the character is coming in correctly.

    Regards

    Amit

  • Hi Amit,

    I have rewritten my code and have a problem reading the UART5.

    When in debug the connection towards the sensorboard works fine.

    The UART5 should constantly receive data and update the buffer. This is not working.

    Can you see any problems with my code (critical areas marked with red)? Can you test it on your computer?

    Can the MPU9150I2CIntHandler disturb readings on the UART5? Similar UART5 code works fine on a new blank project. 

    Code:

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_ints.h"
    #include "driverlib/debug.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "sensorlib/hw_mpu9150.h"
    #include "sensorlib/hw_ak8975.h"
    #include "sensorlib/i2cm_drv.h"
    #include "sensorlib/ak8975.h"
    #include "sensorlib/mpu9150.h"
    #include "sensorlib/comp_dcm.h"
    #include "drivers/rgb.h"
    #include "sensorlib/hw_bmp180.h"
    #include "sensorlib/bmp180.h"

    #define DEBUG

    #define MPU9150_I2C_ADDRESS 0x68 // ISL29023 I2C address
    tI2CMInstance g_sI2CInst; // I2C master driver structure
    tMPU9150 g_sMPU9150Inst; // MPU9150 sensor driver structure
    volatile unsigned long g_vui8DataFlag; // Data ready flag
    volatile unsigned long g_vui8ErrorFlag; // Error flag
    float fAccel[3], fGyro[3], fMagneto[3];

    //*************************************************************************
    #ifdef DEBUG
    void __error__(char *pcFilename, uint32_t ui32Line) {
    }
    #endif
    //*************************************************************************

    void MPU9150AppCallback(void *pvCallbackData, uint_fast8_t ui8Status) {
    if (ui8Status == I2CM_STATUS_SUCCESS) {
    g_vui8DataFlag = 1;
    }
    g_vui8ErrorFlag = ui8Status;
    }
    //*************************************************************************

    //*************************************************************************
    void MPU9150I2CIntHandler(void) {
    I2CMIntHandler(&g_sI2CInst);
    }
    //*************************************************************************

    //*************************************************************************
    void MPU9150AppErrorHandler(char *pcFilename, uint_fast32_t ui32Line) {
    while (1) {
    }
    }
    //*************************************************************************

    //*************************************************************************
    void MPU9150AppI2CWait(char *pcFilename, uint_fast32_t ui32Line) {
    while ((g_vui8DataFlag == 0) && (g_vui8ErrorFlag == 0)) {
    }
    if (g_vui8ErrorFlag) {
    MPU9150AppErrorHandler(pcFilename, ui32Line);
    }
    g_vui8DataFlag = 0;
    }
    //*************************************************************************

    // Configure the UART and its pins.
    void ConfigureUART(void) {
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART5);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    ROM_GPIOPinConfigure(GPIO_PE4_U5RX);
    // ROM_GPIOPinConfigure(GPIO_PE5_U5TX); // NOT BEING USED, ONLY RX
    GPIOPinTypeUART(GPIO_PORTE_BASE, GPIO_PIN_4);
    UARTConfigSetExpClk(UART5_BASE, ROM_SysCtlClockGet(), 115200,
    (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
    }

    char buffer[16];
    //*************************************************************************
    int main(void) {
    ROM_SysCtlClockSet (
    SYSCTL_SYSDIV_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ
    | SYSCTL_OSC_MAIN);

    ConfigureUART();

    ROM_SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOD);
    ROM_SysCtlPeripheralEnable (SYSCTL_PERIPH_I2C3);
    ROM_GPIOPinConfigure (GPIO_PD0_I2C3SCL);
    ROM_GPIOPinConfigure (GPIO_PD1_I2C3SDA);
    GPIOPinTypeI2CSCL(GPIO_PORTD_BASE, GPIO_PIN_0);
    ROM_GPIOPinTypeI2C (GPIO_PORTD_BASE, GPIO_PIN_1);
    ROM_IntMasterEnable ();

    I2CMInit(&g_sI2CInst, I2C3_BASE, INT_I2C3, 0xFF, 0xFF,
    ROM_SysCtlClockGet ());
    SysCtlDelay(SysCtlClockGet() / 3);

    MPU9150Init(&g_sMPU9150Inst, &g_sI2CInst, MPU9150_I2C_ADDRESS,
    MPU9150AppCallback, &g_sMPU9150Inst);

    MPU9150AppI2CWait(__FILE__, __LINE__);

    MPU9150ReadModifyWrite(&g_sMPU9150Inst, MPU9150_O_ACCEL_CONFIG,
    ~MPU9150_ACCEL_CONFIG_AFS_SEL_M, MPU9150_ACCEL_CONFIG_AFS_SEL_4G,
    MPU9150AppCallback, 0);

    MPU9150AppI2CWait(__FILE__, __LINE__);

    while (1) {
    MPU9150DataRead(&g_sMPU9150Inst, MPU9150AppCallback, &g_sMPU9150Inst);
    MPU9150AppI2CWait(__FILE__, __LINE__);

    MPU9150DataAccelGetFloat(&g_sMPU9150Inst, &fAccel[0], &fAccel[1],
    &fAccel[2]);
    MPU9150DataGyroGetFloat(&g_sMPU9150Inst, &fGyro[0], &fGyro[1],
    &fGyro[2]);
    MPU9150DataMagnetoGetFloat(&g_sMPU9150Inst, &fMagneto[0], &fMagneto[1],
    &fMagneto[2]);

    int i = 0;
    if (UARTCharsAvail(UART5_BASE)) {
    buffer[i++] = UARTCharGet(UART5_BASE);
    if (i == 16)
    i = 0;

    }
    }
    }