Other Parts Discussed in Thread: TMP117
This is a continuation of a previous thread that was put on the back burner nine months ago and I'm finally getting around to looking at again. My system uses an MSP432E401Y to control and read data from a number of different devices over SPI and UART interfaces. I currently read from the SPI devices under CPU control but the UART is slow and I can't afford to stall to CPU during the transfer so I use the uDMA to move the data from the sensor into internal memory.
I need to add a temperature sensor to the system and I'm considering the TMP117 which has an I2C interface. I've purchased the TMP117 EVM and have blue-wired it onto my MSP432 board for testing and code development. The I2C bus is also too slow to perform the transfers via CPU so I'd like to use the uDMA as well. I've created a very simple project with the goal of taking baby steps to get to a fully functioning solution. Here is the code for the main() routine:
#include <ti/devices/msp432e4/driverlib/driverlib.h> #include "common.h" void main(void) { uint32_t g_ui32SysClock; // The system clock frequency int32_t status; tempReady = false; g_ui32SysClock = init_CLK(); // configure system clock init_GPIO(); // configure the device pins int_disable(); status = init_temp_I2C(g_ui32SysClock); // configure temperature sensor I2C interface status = init_temperature(); // initialize temperature driver parameters // the code below is used to transfer data from the TMP117 under CPU control // int_enable(); // // while(1){ // while(!tempReady); // tempReady = false; // } // end of CPU control // the code below is used to transfer data from the TMP117 under uDMA control ConfigureuDMATX(); MAP_uDMAChannelRequest(UDMA_CH23_I2C5TX); // end of uDMA control }
My first step was to write configuration and read/write functions using the CPU. First the init_temp_I2C() function enables the I2C peripheral, then init_temperature() configures the TMP117 and starts the data capture. When the TEMP_DRDY interrupt fires the tempReadyFxn() ISR reads the data. Finally the tempCallBack() callback sets the tempReady semaphore when the I2C tranfer is complete. Using this code I can successfully capture data from the TMP117.
My next step is to use the uDMA to capture the data after the I2C, TMP117 and uDMA are initialized by the CPU. I have used the i2c_master_dma_fifo and i2c_mastermode_fifodma_transfer examples from the Resource Explorer as guides.
Here is a diagram explaining the data transfer protocol for the TMP117:
The grey boxes show when the master (MSP432) drives the SDA line and the white boxes when the TMP117 drives the line.
My data transfer is simpler than what is shown because I am always reading from the same register address, I don't need to send the register address with every transfer. Instead the MSP432 only needs to send a single byte over SDA and then the TMP117 will reply with two bytes. Because there is such little data transferred I don't think I need to use the FIFO. The TMP117 is sampling at a 500mS rate, but the MSP432 is only recording temperature data at a 1S rate so I don't mind if I overwrite data that hasn't been recorded yet.
The attached project file shows the current state of my testing. In this very simple code I've use init_temp_I2C() and init_temperature() to initialize the I2C peripheral and TMP117. Next I am attempting to enable and configure the uDMA peripheral and send a single byte out the I2C bus. The intent of the function ConfigureuDMATX() is to map uDMA channel 23 to I2C5 and initialize a single byte tranfser from memory pointed to by &sendMasterTxData to the I2C5 master data register which I then expect to transfmit on I2C5SDA.
void ConfigureuDMATX(void) { MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); while(!(MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA))){} MAP_uDMAEnable(); MAP_uDMAControlBaseSet(pui8ControlTable); MAP_uDMAChannelAssign(UDMA_CH23_I2C5TX); MAP_uDMAChannelAttributeDisable(UDMA_CH23_I2C5TX, UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); MAP_uDMAChannelControlSet(UDMA_CH23_I2C5TX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_NONE | UDMA_ARB_1); MAP_uDMAChannelTransferSet(UDMA_CH23_I2C5TX | UDMA_PRI_SELECT, UDMA_MODE_AUTO, (void *)&sendMasterTxData, (void *)&I2C5->MDR, 1); MAP_uDMAChannelEnable(UDMA_CH23_I2C5TX); }
Finally I call MAP_uDMAChannelRequest(UDMA_CH23_I2C5TX); to execute the transfer.
Unfortunately I don't see the transfer on the I2C bus after MAP_uDMAChannelRequest() is executed.
I would appreciate help getting this to work. I don't know if I've incorrectly configured the uDMA, or if I've missed some critical initialize conde.
Thanks,
-phil