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.

Is this I2C class correct?

Hi there,

I am using the Tiva C Series Connected Launchpad TM4C1294XL and I just wrote a class for commuticating over I2C. Can you please tell me if the methods are correct? I am not sure about the methode sendReceiveBuffer. I don't know when I have to call the I2CMasterControl function for switching from sending to receiving.

/*
 * I2C.h
 *
 *  Created on: 16.04.2015
 *      Author: nicolas
 */

#ifndef I2C_H_
#define I2C_H_

#include "helper/common.h"

#include <stdint.h>

#include "driverlib/i2c.h"  // for SSI
#include "driverlib/gpio.h" // for GPIO_PIN_0 to GPIO_PIN_7
#include "driverlib/rom.h"  // for all ROM_ functions
#include "driverlib/pin_map.h"
#include "inc/hw_memmap.h"

namespace I2CFlags {
	enum Flags {
		Fast			= _BV(0)
	};
	// Notwendig, damit man Flags mit dem  | Operator verodern/verknüpfen kann.
	inline Flags operator|(Flags a, Flags b)
	{return static_cast<Flags>(static_cast<int>(a) | static_cast<int>(b));}
}

namespace I2CPorts {
	static const uint32_t I2CPeriph[14] = {
		SYSCTL_PERIPH_I2C0, SYSCTL_PERIPH_I2C1, SYSCTL_PERIPH_I2C2, SYSCTL_PERIPH_I2C2, SYSCTL_PERIPH_I2C3,
		SYSCTL_PERIPH_I2C4, SYSCTL_PERIPH_I2C5, SYSCTL_PERIPH_I2C5, SYSCTL_PERIPH_I2C6, SYSCTL_PERIPH_I2C7,
		SYSCTL_PERIPH_I2C7, SYSCTL_PERIPH_I2C8, SYSCTL_PERIPH_I2C8, SYSCTL_PERIPH_I2C9
	};
	static const uint32_t I2CBase[14] = {
		I2C0_BASE, I2C1_BASE, I2C2_BASE, I2C2_BASE, I2C3_BASE,
		I2C4_BASE, I2C5_BASE, I2C5_BASE, I2C6_BASE, I2C7_BASE,
		I2C7_BASE, I2C8_BASE, I2C8_BASE, I2C9_BASE
	};
	static const uint32_t I2CGPIOPeriph[14] = {
		SYSCTL_PERIPH_GPIOB, SYSCTL_PERIPH_GPIOG, SYSCTL_PERIPH_GPIOL, SYSCTL_PERIPH_GPION, SYSCTL_PERIPH_GPIOK,
		SYSCTL_PERIPH_GPIOK, SYSCTL_PERIPH_GPIOB, SYSCTL_PERIPH_GPIOB, SYSCTL_PERIPH_GPIOA, SYSCTL_PERIPH_GPIOD,
		SYSCTL_PERIPH_GPIOA, SYSCTL_PERIPH_GPIOD, SYSCTL_PERIPH_GPIOA, SYSCTL_PERIPH_GPIOA
	};
	// Reihenfolge: SCL, SDA
	static const uint32_t I2CGPIOPins[14][2] = {
			{ GPIO_PB2_I2C0SCL, GPIO_PB3_I2C0SDA },
			{ GPIO_PG0_I2C1SCL, GPIO_PG1_I2C1SDA },
			{ GPIO_PL1_I2C2SCL, GPIO_PL0_I2C2SDA },
			{ GPIO_PN5_I2C2SCL, GPIO_PN4_I2C2SDA },
			{ GPIO_PK4_I2C3SCL, GPIO_PK5_I2C3SDA },
			{ GPIO_PK6_I2C4SCL, GPIO_PK7_I2C4SDA },
			{ GPIO_PB0_I2C5SCL, GPIO_PB1_I2C5SDA },
			{ GPIO_PB4_I2C5SCL, GPIO_PB5_I2C5SDA },
			{ GPIO_PA6_I2C6SCL, GPIO_PA7_I2C6SDA },
			{ GPIO_PD0_I2C7SCL, GPIO_PD1_I2C7SDA },
			{ GPIO_PA4_I2C7SCL, GPIO_PA5_I2C7SDA },
			{ GPIO_PD2_I2C8SCL, GPIO_PD3_I2C8SDA },
			{ GPIO_PA2_I2C8SCL, GPIO_PA3_I2C8SDA },
			{ GPIO_PA0_I2C9SCL, GPIO_PA1_I2C9SDA },
	};

	static const uint32_t I2CGPIOBase[14] = {
		GPIO_PORTB_BASE, GPIO_PORTG_BASE, GPIO_PORTL_BASE, GPIO_PORTN_BASE, GPIO_PORTK_BASE,
		GPIO_PORTK_BASE, GPIO_PORTB_BASE, GPIO_PORTB_BASE, GPIO_PORTA_BASE, GPIO_PORTD_BASE,
		GPIO_PORTA_BASE, GPIO_PORTD_BASE, GPIO_PORTA_BASE, GPIO_PORTA_BASE
	};
	// Reihenfolge: SCL, SDA
	static const uint32_t I2CGPIOType[14][2] = {
			{ GPIO_PIN_2, GPIO_PIN_3 },
			{ GPIO_PIN_0, GPIO_PIN_1 },
			{ GPIO_PIN_1, GPIO_PIN_0 },
			{ GPIO_PIN_5, GPIO_PIN_4 },
			{ GPIO_PIN_4, GPIO_PIN_6 },
			{ GPIO_PIN_6, GPIO_PIN_7 },
			{ GPIO_PIN_0, GPIO_PIN_1 },
			{ GPIO_PIN_4, GPIO_PIN_5 },
			{ GPIO_PIN_6, GPIO_PIN_7 },
			{ GPIO_PIN_0, GPIO_PIN_1 },
			{ GPIO_PIN_4, GPIO_PIN_5 },
			{ GPIO_PIN_2, GPIO_PIN_3 },
			{ GPIO_PIN_2, GPIO_PIN_3 },
			{ GPIO_PIN_0, GPIO_PIN_1 }
	};
}

class I2C {
	protected:
		int i2c;
		uint32_t base; // für schnelleren Zugriff
	public:
		I2C(int i2c, I2CFlags::Flags flags) {
			this->i2c = i2c;
			base = I2CPorts::I2CBase[i2c];

			ROM_IntMasterDisable();

			// Aktiviere I2C- und GPIO-Peripherie
			ROM_SysCtlPeripheralEnable(I2CPorts::I2CPeriph[i2c]);
			ROM_SysCtlDelay(3);
			ROM_SysCtlPeripheralReset(I2CPorts::I2CPeriph[i2c]);
			ROM_SysCtlPeripheralEnable(I2CPorts::I2CGPIOPeriph[i2c]);
			ROM_SysCtlDelay(3);

			// Deaktiviere I2C Master und Slave Block
			I2CMasterDisable(base);	//FIXME: Wahrscheinlich nicht nötig wegen dem Reset oben
			I2CSlaveDisable(base);

			// Konfiguriere die Pins für I2C als SCL und SDA
			ROM_GPIOPinConfigure(I2CPorts::I2CGPIOPins[i2c][0]);
			ROM_GPIOPinTypeI2CSCL(I2CPorts::I2CGPIOBase[i2c], I2CPorts::I2CGPIOType[i2c][0]);
			ROM_GPIOPinConfigure(I2CPorts::I2CGPIOPins[i2c][1]);
			ROM_GPIOPinTypeI2C(I2CPorts::I2CGPIOBase[i2c], I2CPorts::I2CGPIOType[i2c][1]);

			//ROM_I2CClockSourceSet(base, SSI_CLOCK_SYSTEM); // Gibt's nicht. I2C nutzt immer die System Clock

			bool bFast = false;
			if (flags & I2CFlags::Fast) {
				bFast = true;
			}
			ROM_I2CMasterInitExpClk(base, F_CPU, bFast);

			// Aktiviere SSI
			ROM_I2CMasterEnable(base);

			ROM_IntMasterEnable();
		};

		~I2C() {
			ROM_SysCtlPeripheralReset(I2CPorts::I2CPeriph[i2c]);
		};

		//FIXME: Add Error Handlers
		int inline sendSingle(uint8_t value, uint8_t address) {
			I2CMasterSlaveAddrSet(base, address, false);
			ROM_I2CMasterDataPut(base, value);
			while (ROM_I2CMasterBusBusy(base));
			ROM_I2CMasterControl(base, I2C_MASTER_CMD_SINGLE_SEND);
			while(ROM_I2CMasterBusy(base));
			//error?
			return 0;
		}

		/**
		 * @return 0 successful.
		 */
		//FIXME: Add Error Handlers
		int sendBuffer(uint8_t address, uint8_t* buffer, int length) {
			ROM_I2CMasterSlaveAddrSet(base, address, false);
			ROM_I2CMasterDataPut(base, *buffer++);
			while (ROM_I2CMasterBusBusy(base));
			if (length == 1) {
				ROM_I2CMasterControl(base, I2C_MASTER_CMD_SINGLE_SEND);
				while(ROM_I2CMasterBusy(base));
				//error?
				return 0;
			}
			ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_START);
			length--;
			while (true) {
				while(ROM_I2CMasterBusy(base));
				//error?
				ROM_I2CMasterDataPut(base, *buffer++);
				if (--length == 0) {
					break;
				}
				ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_CONT);
			}
			ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_FINISH);
			while(ROM_I2CMasterBusy(base));
			//error?
			return 0;
		}

		//FIXME: Add Error Handlers
		uint8_t inline receiveSingle(uint8_t address) {
			ROM_I2CMasterSlaveAddrSet(base, address, true);
			while (ROM_I2CMasterBusBusy(base));
			ROM_I2CMasterControl(base, I2C_MASTER_CMD_SINGLE_RECEIVE);
			while(ROM_I2CMasterBusy(base));
			//error?
			uint32_t value;
			value = ROM_I2CMasterDataGet(base);
			return value & 0xff;
		}

		//FIXME: Add Error Handlers
		int receiveBuffer(uint8_t address, uint8_t* buffer, int length) {
			if (length == 1) {
				*buffer = receiveSingle(address);
				return 0;
			}
			ROM_I2CMasterSlaveAddrSet(base, address, true);
			while (ROM_I2CMasterBusBusy(base));
			ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_START);
			while (true) {
				while(ROM_I2CMasterBusy(base));
				//error?
				*buffer++ = ROM_I2CMasterDataGet(base) & 0xff;
				if (--length) {
					break;
				}
				ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
			}
			ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
			while(ROM_I2CMasterBusy(base));
			//error?
			*buffer = ROM_I2CMasterDataGet(base) & 0xff;
			return 0;
		}

		//FIXME: Add Error Handlers
		int sendReceiveBuffer(uint8_t address, uint8_t* sendBuffer, int sendLength, uint8_t* receiveBuffer, int receiveLength) {
			ROM_I2CMasterSlaveAddrSet(base, address, false);
			ROM_I2CMasterDataPut(base, *sendBuffer++);
			while (ROM_I2CMasterBusBusy(base));
			ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_START);
			sendLength--;
			while (true) {
				while(ROM_I2CMasterBusy(base));
				//error?
				if (--sendLength == 0) {
					break;
				}
				ROM_I2CMasterDataPut(base, *sendBuffer++);
				ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_CONT);
			}
			ROM_I2CMasterSlaveAddrSet(base, address, true);
			I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_START);
			while (true) {
				while(ROM_I2CMasterBusy(base));
				//error?
				*receiveBuffer++ = ROM_I2CMasterDataGet(base) & 0xff;
				if (--receiveLength) {
					break;
				}
				ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
			}
			ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
			while(ROM_I2CMasterBusy(base));
			//error?
			*receiveBuffer = ROM_I2CMasterDataGet(base) & 0xff;
			return 0;
		}
};

#endif /* I2C_H_ */

Thank you!

  • Hello Nicolas,

    Please do put a check for I2CMasterBusy before the change of direction and before issuing FINISH.

    Regards
    Amit
  • Thank you! I added these two lines and I also added error handling. This is the final code for all who wants to use it:

    /*
     * I2C.h
     *
     *  Created on: 16.04.2015
     *      Author: nicolas
     */
    
    #ifndef I2C_H_
    #define I2C_H_
    
    #include "helper/common.h"
    
    #include <stdint.h>
    
    #include "driverlib/i2c.h"  // for SSI
    #include "driverlib/gpio.h" // for GPIO_PIN_0 to GPIO_PIN_7
    #include "driverlib/rom.h"  // for all ROM_ functions
    #include "driverlib/pin_map.h"
    #include "inc/hw_memmap.h"
    
    #ifdef MY_DEBUG
    #	include "utils/uartstdio.h"
    #endif
    
    namespace I2CFlags {
    	enum Flags {
    		Normal			= 0,
    		Fast			= _BV(0)
    	};
    	// Notwendig, damit man Flags mit dem  | Operator verodern/verknüpfen kann.
    	inline Flags operator|(Flags a, Flags b)
    	{return static_cast<Flags>(static_cast<int>(a) | static_cast<int>(b));}
    }
    
    namespace I2CPorts {
    	static const uint32_t I2CPeriph[14] = {
    		SYSCTL_PERIPH_I2C0, SYSCTL_PERIPH_I2C1, SYSCTL_PERIPH_I2C2, SYSCTL_PERIPH_I2C2, SYSCTL_PERIPH_I2C3,
    		SYSCTL_PERIPH_I2C4, SYSCTL_PERIPH_I2C5, SYSCTL_PERIPH_I2C5, SYSCTL_PERIPH_I2C6, SYSCTL_PERIPH_I2C7,
    		SYSCTL_PERIPH_I2C7, SYSCTL_PERIPH_I2C8, SYSCTL_PERIPH_I2C8, SYSCTL_PERIPH_I2C9
    	};
    	static const uint32_t I2CBase[14] = {
    		I2C0_BASE, I2C1_BASE, I2C2_BASE, I2C2_BASE, I2C3_BASE,
    		I2C4_BASE, I2C5_BASE, I2C5_BASE, I2C6_BASE, I2C7_BASE,
    		I2C7_BASE, I2C8_BASE, I2C8_BASE, I2C9_BASE
    	};
    	static const uint32_t I2CGPIOPeriph[14] = {
    		SYSCTL_PERIPH_GPIOB, SYSCTL_PERIPH_GPIOG, SYSCTL_PERIPH_GPIOL, SYSCTL_PERIPH_GPION, SYSCTL_PERIPH_GPIOK,
    		SYSCTL_PERIPH_GPIOK, SYSCTL_PERIPH_GPIOB, SYSCTL_PERIPH_GPIOB, SYSCTL_PERIPH_GPIOA, SYSCTL_PERIPH_GPIOD,
    		SYSCTL_PERIPH_GPIOA, SYSCTL_PERIPH_GPIOD, SYSCTL_PERIPH_GPIOA, SYSCTL_PERIPH_GPIOA
    	};
    	// Reihenfolge: SCL, SDA
    	static const uint32_t I2CGPIOPins[14][2] = {
    			{ GPIO_PB2_I2C0SCL, GPIO_PB3_I2C0SDA }, //  0
    			{ GPIO_PG0_I2C1SCL, GPIO_PG1_I2C1SDA }, //  1
    			{ GPIO_PL1_I2C2SCL, GPIO_PL0_I2C2SDA }, //  2
    			{ GPIO_PN5_I2C2SCL, GPIO_PN4_I2C2SDA }, //  3
    			{ GPIO_PK4_I2C3SCL, GPIO_PK5_I2C3SDA }, //  4
    			{ GPIO_PK6_I2C4SCL, GPIO_PK7_I2C4SDA }, //  5
    			{ GPIO_PB0_I2C5SCL, GPIO_PB1_I2C5SDA }, //  6 funktioniert nicht laut Errata Sheet
    			{ GPIO_PB4_I2C5SCL, GPIO_PB5_I2C5SDA }, //  7
    			{ GPIO_PA6_I2C6SCL, GPIO_PA7_I2C6SDA }, //  8
    			{ GPIO_PD0_I2C7SCL, GPIO_PD1_I2C7SDA }, //  9
    			{ GPIO_PA4_I2C7SCL, GPIO_PA5_I2C7SDA }, // 10
    			{ GPIO_PD2_I2C8SCL, GPIO_PD3_I2C8SDA }, // 11
    			{ GPIO_PA2_I2C8SCL, GPIO_PA3_I2C8SDA }, // 12
    			{ GPIO_PA0_I2C9SCL, GPIO_PA1_I2C9SDA }, // 13
    	};
    
    	static const uint32_t I2CGPIOBase[14] = {
    		GPIO_PORTB_BASE, GPIO_PORTG_BASE, GPIO_PORTL_BASE, GPIO_PORTN_BASE, GPIO_PORTK_BASE,
    		GPIO_PORTK_BASE, GPIO_PORTB_BASE, GPIO_PORTB_BASE, GPIO_PORTA_BASE, GPIO_PORTD_BASE,
    		GPIO_PORTA_BASE, GPIO_PORTD_BASE, GPIO_PORTA_BASE, GPIO_PORTA_BASE
    	};
    	// Reihenfolge: SCL, SDA
    	static const uint32_t I2CGPIOType[14][2] = {
    			{ GPIO_PIN_2, GPIO_PIN_3 },
    			{ GPIO_PIN_0, GPIO_PIN_1 },
    			{ GPIO_PIN_1, GPIO_PIN_0 },
    			{ GPIO_PIN_5, GPIO_PIN_4 },
    			{ GPIO_PIN_4, GPIO_PIN_5 },
    			{ GPIO_PIN_6, GPIO_PIN_7 },
    			{ GPIO_PIN_0, GPIO_PIN_1 },
    			{ GPIO_PIN_4, GPIO_PIN_5 },
    			{ GPIO_PIN_6, GPIO_PIN_7 },
    			{ GPIO_PIN_0, GPIO_PIN_1 },
    			{ GPIO_PIN_4, GPIO_PIN_5 },
    			{ GPIO_PIN_2, GPIO_PIN_3 },
    			{ GPIO_PIN_2, GPIO_PIN_3 },
    			{ GPIO_PIN_0, GPIO_PIN_1 }
    	};
    }
    
    class I2C {
    	protected:
    		int i2c;
    		uint32_t base; // für schnelleren Zugriff
    	public:
    		I2C(int i2c, I2CFlags::Flags flags) {
    			this->i2c = i2c;
    			base = I2CPorts::I2CBase[i2c];
    
    			ROM_IntMasterDisable();
    
    			// Aktiviere I2C- und GPIO-Peripherie
    			ROM_SysCtlPeripheralEnable(I2CPorts::I2CPeriph[i2c]);
    			while (!(SysCtlPeripheralReady(I2CPorts::I2CPeriph[i2c])));
    			ROM_SysCtlPeripheralReset(I2CPorts::I2CPeriph[i2c]);
    
    			ROM_SysCtlPeripheralEnable(I2CPorts::I2CGPIOPeriph[i2c]);
    			while (!(SysCtlPeripheralReady(I2CPorts::I2CGPIOPeriph[i2c])));
    
    
    			// Deaktiviere I2C Master und Slave Block
    			I2CMasterDisable(base);	//FIXME: Wahrscheinlich nicht nötig wegen dem Reset oben
    			I2CSlaveDisable(base);
    
    			// Konfiguriere die Pins für I2C als SCL und SDA
    			ROM_GPIOPinConfigure(I2CPorts::I2CGPIOPins[i2c][0]);
    			ROM_GPIOPinTypeI2CSCL(I2CPorts::I2CGPIOBase[i2c], I2CPorts::I2CGPIOType[i2c][0]);
    
    			GPIOPinConfigure(I2CPorts::I2CGPIOPins[i2c][1]);
    			ROM_GPIOPinTypeI2C(I2CPorts::I2CGPIOBase[i2c], I2CPorts::I2CGPIOType[i2c][1]);
    
    			//ROM_I2CClockSourceSet(base, SSI_CLOCK_SYSTEM); // Gibt's nicht. I2C nutzt immer die System Clock
    
    			bool bFast = false;
    			if (flags & I2CFlags::Fast) {
    				bFast = true;
    			}
    			ROM_I2CMasterInitExpClk(base, F_CPU, bFast);
    
    			// Aktiviere SSI
    			ROM_I2CMasterEnable(base);
    
    			ROM_IntMasterEnable();
    		};
    
    		~I2C() {
    			ROM_SysCtlPeripheralReset(I2CPorts::I2CPeriph[i2c]);
    		};
    
    		uint32_t inline sendSingle(uint8_t value, uint8_t address) {
    			I2CMasterSlaveAddrSet(base, address, false);
    			ROM_I2CMasterDataPut(base, value);
    			//while (ROM_I2CMasterBusBusy(base));
    			ROM_I2CMasterControl(base, I2C_MASTER_CMD_SINGLE_SEND);
    			while(ROM_I2CMasterBusy(base));
    			return ROM_I2CMasterErr(base);
    		}
    
    		/**
    		 * @return 0 successful.
    		 */
    		uint32_t sendBuffer(uint8_t address, uint8_t* buffer, int length) {
    			UARTprintf("+");
    			ROM_I2CMasterSlaveAddrSet(base, address, false);
    			ROM_I2CMasterDataPut(base, *buffer++);
    			//while (I2CMasterBusBusy(base));
    			if (length == 1) {
    				ROM_I2CMasterControl(base, I2C_MASTER_CMD_SINGLE_SEND);
    				while(ROM_I2CMasterBusy(base));
    				return ROM_I2CMasterErr(base);
    			}
    			ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_START);
    			length--;
    			while (true) {
    				UARTprintf(".");
    				while(ROM_I2CMasterBusy(base));
    				uint32_t error = ROM_I2CMasterErr(base);
    				if (error != I2C_MASTER_ERR_NONE) {
    					ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP);
    					return error;
    				}
    				ROM_I2CMasterDataPut(base, *buffer++);
    				if (--length == 0) {
    					break;
    				}
    				ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_CONT);
    			}
    			ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_FINISH);
    			while(ROM_I2CMasterBusy(base));
    			return ROM_I2CMasterErr(base);
    		}
    
    		uint32_t inline receiveSingle(uint8_t address, uint8_t &value) {
    			ROM_I2CMasterSlaveAddrSet(base, address, true);
    			while (ROM_I2CMasterBusBusy(base));
    			ROM_I2CMasterControl(base, I2C_MASTER_CMD_SINGLE_RECEIVE);
    			while(ROM_I2CMasterBusy(base));
    			uint32_t error = ROM_I2CMasterErr(base);
    			if (error != I2C_MASTER_ERR_NONE) {
    				ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP);
    				return error;
    			}
    			value = ROM_I2CMasterDataGet(base);
    			return I2C_MASTER_ERR_NONE;
    		}
    
    		uint32_t receiveBuffer(uint8_t address, uint8_t* buffer, int length) {
    			uint32_t error;
    			if (length == 1) {
    				receiveSingle(address, *buffer);
    				return 0;
    			}
    			ROM_I2CMasterSlaveAddrSet(base, address, true);
    			//while (ROM_I2CMasterBusBusy(base));
    			ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_START);
    			while (true) {
    				while(ROM_I2CMasterBusy(base));
    				error = ROM_I2CMasterErr(base);
    				if (error != I2C_MASTER_ERR_NONE) {
    					ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP);
    					return error;
    				}
    				*buffer++ = ROM_I2CMasterDataGet(base) & 0xff;
    				if (--length) {
    					break;
    				}
    				ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
    			}
    			ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    			while(ROM_I2CMasterBusy(base));
    			error = ROM_I2CMasterErr(base);
    			if (error != I2C_MASTER_ERR_NONE) {
    				ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP);
    				return error;
    			}
    			*buffer = ROM_I2CMasterDataGet(base) & 0xff;
    			return I2C_MASTER_ERR_NONE;
    		}
    
    		//FIXME: Add Error Handlers
    		int sendReceiveBuffer(uint8_t address, uint8_t* sendBuffer, int sendLength, uint8_t* receiveBuffer, int receiveLength) {
    			uint32_t error;
    			ROM_I2CMasterSlaveAddrSet(base, address, false);
    			ROM_I2CMasterDataPut(base, *sendBuffer++);
    			//while (ROM_I2CMasterBusBusy(base));
    			ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_START);
    			sendLength--;
    			while (true) {
    				while(ROM_I2CMasterBusy(base));
    				error = ROM_I2CMasterErr(base);
    				if (error != I2C_MASTER_ERR_NONE) {
    					ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP);
    					return error;
    				}
    				if (--sendLength == 0) {
    					break;
    				}
    				ROM_I2CMasterDataPut(base, *sendBuffer++);
    				ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_SEND_CONT);
    			}
    			while(ROM_I2CMasterBusy(base));
    			ROM_I2CMasterSlaveAddrSet(base, address, true);
    			I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_START);
    			while (true) {
    				while(ROM_I2CMasterBusy(base));
    				error = ROM_I2CMasterErr(base);
    				if (error != I2C_MASTER_ERR_NONE) {
    					ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP);
    					return error;
    				}
    				*receiveBuffer++ = ROM_I2CMasterDataGet(base) & 0xff;
    				if (--receiveLength) {
    					break;
    				}
    				ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
    			}
    			while(ROM_I2CMasterBusy(base));
    			ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    			while(ROM_I2CMasterBusy(base));
    			error = ROM_I2CMasterErr(base);
    			if (error != I2C_MASTER_ERR_NONE) {
    				ROM_I2CMasterControl(base, I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP);
    				return error;
    			}
    			*receiveBuffer = ROM_I2CMasterDataGet(base) & 0xff;
    			return 0;
    		}
    };
    
    #endif /* I2C_H_ */
    

  • Hello Nicolas,

    Did you check the latest errata for TM4C129 (I2C#05). It may change the execution flow.

    Regards
    Amit
  • So you mean I should always use interrupts?
  • Hello Nicolas,

    If the NAK can be guaranteed to not occur during the transaction by virtue of correct slave address coded in the design, then no, otherwise yes.

    Regards
    Amit
  • Nicolas Göddel said:
    So you mean I should always use interrupts?

    I'll leave that for vendor insiders...

    Beyond that - efforts such as yours - focused on so new a device (and a complex one at that) usually will suffer as vendors (most always) make tweaks/changes/improvements.    

    You're surely "ahead of the curve" through this effort - but do be mindful that (changes) are to be expected - and you must accommodate.     

    This is a (rare) case (but a predictable one) where being prompt may "cost you" - rather than work to your advantage...