/* * I2C_FIFO.c * * Created on: Jan 2, 2020 * Author: avi * https://cryptography.gmu.edu:4443/XBX/xbh/blob/02a7edc0a62a7ab48341ca5b34de07eb7bf1c609/hal/i2c.c */ #include #include #include "include.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/tm4c1294ncpdt.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "driverlib/sysctl.h" #include "driverlib/i2c.h" #define MAX_FIFO_BURST 8 #define I2C_BUSY_DELAY 5000 /// /** * Flushes I2C fifos * @param base Base address of I2C transceiver */ void i2c_flush(uint32_t base){ I2CTxFIFOFlush(base); I2CRxFIFOFlush(base); } /** * Sets up fifos and clock for I2C. Does not configure pins * @param base Base address of I2C transceiver * @param highspeed True if 400kbit, else 100kbit */ void i2c_fifo_setup(uint32_t base) { I2CTxFIFOConfigSet(base, I2C_FIFO_CFG_TX_MASTER | I2C_FIFO_CFG_TX_TRIG_3); I2CRxFIFOConfigSet(base, I2C_FIFO_CFG_RX_MASTER | I2C_FIFO_CFG_RX_TRIG_2); I2CMasterGlitchFilterConfigSet(base, I2C_MASTER_GLITCH_FILTER_8); i2c_flush(base); } uint32_t I2C_BusyWithTimeout(uint32_t base) { uint32_t count = 0; while(I2CMasterBusy(base) && (count++ < 10)) { SysCtlDelay(I2C_BUSY_DELAY); if(count > 10) { return I2C_MASTER_ERR_CLK_TOUT; } } return 0; } /** * Writes array over I2C to address given * @param base Base address of I2C transceiver * @param addr Address of I2C device to write to * @param data Data to write * @param len Length of data * @return 0 if success, else value of I2CMasterErr */ uint32_t I2C_WriteFifo(uint32_t base, uint8_t addr, uint8_t *data, uint32_t len){ uint32_t offset = 0; uint32_t len_mod = len % MAX_FIFO_BURST; uint32_t final_burst = (len_mod !=0 )? len_mod : MAX_FIFO_BURST; uint32_t i, err; // Send configuration to INA219 config register I2CMasterSlaveAddrSet(base, addr, false); for(offset = 0; offset < (len-1)/MAX_FIFO_BURST; offset++){ I2CMasterBurstLengthSet(base, MAX_FIFO_BURST); for(i = 0; i < MAX_FIFO_BURST; ++i){ I2CFIFODataPutNonBlocking(base, *data++); } if( 0 == offset){ I2CMasterControl(base, I2C_MASTER_CMD_FIFO_BURST_SEND_START); }else{ I2CMasterControl(base, I2C_MASTER_CMD_FIFO_BURST_SEND_CONT); } } I2CMasterBurstLengthSet(base, final_burst); for(i = 0; i < final_burst; ++i){ I2CFIFODataPutNonBlocking(base, *data++); } if(len <= MAX_FIFO_BURST){ I2CMasterControl(base, I2C_MASTER_CMD_FIFO_SINGLE_SEND); }else{ I2CMasterControl(base, I2C_MASTER_CMD_FIFO_BURST_SEND_FINISH); } if((err = I2C_BusyWithTimeout(base)) != 0) { return err; } else { err = I2CMasterErr(base); } return err; } uint32_t I2C_ReadFifo(uint32_t base, uint8_t addr, uint8_t *data, uint32_t len) { uint32_t len_mod = len % MAX_FIFO_BURST; uint32_t final_burst = (len_mod !=0 )? len_mod : MAX_FIFO_BURST; uint32_t i, offset, err; // Send configuration to INA219 config register I2CRxFIFOFlush(base); I2CMasterSlaveAddrSet(base, addr, true); for(offset = 0; offset < len/MAX_FIFO_BURST; offset++) { I2CMasterBurstLengthSet(base, MAX_FIFO_BURST); if(0 == offset) { I2CMasterControl(base, I2C_MASTER_CMD_FIFO_BURST_RECEIVE_START); } else { I2CMasterControl(base, I2C_MASTER_CMD_FIFO_BURST_RECEIVE_CONT); } if((err = I2C_BusyWithTimeout(base)) != 0) return err; for(i = 0; i < MAX_FIFO_BURST; ++i) { I2CFIFODataGetNonBlocking(base, data++); } } I2CMasterBurstLengthSet(base, final_burst); if(len <= MAX_FIFO_BURST){ I2CMasterControl(base, I2C_MASTER_CMD_FIFO_SINGLE_RECEIVE); } else { I2CMasterControl(base, I2C_MASTER_CMD_FIFO_BURST_RECEIVE_FINISH); } if((err = I2C_BusyWithTimeout(base)) != 0) return err; for(i = 0; i < final_burst; ++i) { I2CFIFODataGetNonBlocking(base, data++); } err = I2CMasterErr(base); return err; } /* void i2c_comm_setup(void){ // Configure I2C pins SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1); SysCtlPeripheralReset(SYSCTL_PERIPH_I2C1); GPIOPinConfigure(GPIO_PG0_I2C1SCL); GPIOPinConfigure(GPIO_PG1_I2C1SDA); GPIOPinTypeI2C(GPIO_PORTG_BASE, GPIO_PIN_0); GPIOPinTypeI2CSCL(GPIO_PORTG_BASE, GPIO_PIN_1); // Configure I2C master and fifos, and flush fifos i2c_setup(I2C2_BASE, true); } */