Robostix i2c slave

The page tries to explain how to use the i2c-slave.c file or i2c-slave-boot.c file on the robostix. The i2c-io sample program provides a working example of how to use the i2c-slave-boot.c file.

Delcare globals
If you're using i2c-slave.c, then you'll need to declare a global variable which is used to contain various bits of state information. All of the information contained in this variable should be considered private and there should be no reason to use or manipulate this by the calling program.

If you're using i2c-slave-boot.c, then it declares a global variable for you. I2C_Globals_t gI2cGlobals;

Install the interrupt handler
The i2c slave code is entirely interrupt driven, and it relies on the main application to provide the interrupt handler. The interrupt handler would typically look something like this: //*************************************************************************** /**
 * I2C Interrupt service routine

SIGNAL(SIG_2WIRE_SERIAL) {   if ( !I2C_SlaveBootHandler ) {       LogError( "Unrecognized status: 0x%x\n", TW_STATUS ); }

// Now that we've finished dealing with the interrupt, set the TWINT flag // which will stop the clock stretching and clear the interrupt source

TWCR |= ( 1 << TWINT );

} // SIG_2WIRE_SERIAL

If you're using i2c-slave.c, then replace I2C_SlaveBootHandler with I2C_SlaveHandler( &gI2cGlobals )

Initializing
The i2c slave code needs to be initialized. If you're using i2c-slave.c, then you need to allocate space for globals and pass in the address of this memory, along with the address to use on the i2c bus.

If you're using i2c-slave-boot.c, then it allocates storage for the globals for you, and uses the same i2c address that the boot loader is configured to use.

The final parameter, in either case, is a pointer to a function which will be called to process i2c commands.

The ProcessCmd function must have the following prototype: int ProcessCommand( I2C_Data_t *packet );

The I2C_Data_t structure looks like this: typedef struct {   #if CFG_I2C_USE_CRC uint8_t m_crc; #endif

// For reads, m_len is the number of bytes actually read (doesn't include   // the CRC - if present). If a block transfer was performed which has a    // length byte, this lenght will include the length byte.

uint8_t m_len;

// Note: Under SMBus, a block write can consist of a command, a length, // 32 bytes of payload, and a CRC. //   // A read response can consist of a length, 32 bytes of data, and a CRC.

uint8_t m_data[ I2C_MAX_DATA_LEN + 2]; // +1 for the command, +1 for length

} I2C_Data_t; The packet parameter will contain the i2c data which was received, and is also where any response will be placed. packet->m_data[0] will contain the command (or register number). The remainder of the packet will depend on the particular type of transfer being performed.

The SMBus specification desribes the following protocols:

The CRC handling is taken care of automatically.

If you're using i2c-slave-boot.c and you would like to support the bootloader commands, if you don't recognize the command which is received, then you can call I2C_SlaveBootProcessCommand to see if the bootloader recognizes the command.

The ProcessCommand function should fill in the packet with the data to be sent as a response. The return from the ProcessCommand function should be the number of bytes to send as the response.

Note: So far, only the protocols with functions listed in the i2c-api.c fn column have been tested.

On the gumstix side of things
The i2c-api.c file contains wrapper functions for implementing the various protocols. The I2cTransfer function is the core code.