Skip to content

Instantly share code, notes, and snippets.

@bradjc
Last active August 29, 2015 14:25
Show Gist options
  • Save bradjc/3ded774b60fe35793868 to your computer and use it in GitHub Desktop.
Save bradjc/3ded774b60fe35793868 to your computer and use it in GitHub Desktop.

I2C

TinyOS

Split in two. First, the platform specific hardware config:

async command msp430_i2c_union_config_t* getConfig();

typedef struct {
  unsigned int mst: 1;      //Master mode (0=slave; 1=master)
  unsigned int listen: 1;   //Listen enable (0=disabled; 1=enabled, feed tx back to receiver)
  unsigned int xa: 1;       //Extended addressing (0=7-bit addressing; 1=8-bit addressing)
  unsigned int txdmaen: 1;  //DMA to TX (0=disabled; 1=enabled)
  unsigned int rxdmaen: 1;  //RX to DMA (0=disabled; 1=enabled)
  unsigned int i2cssel: 2;  //Clock source (00=disabled; 01=ACLK; 10=SMCLK; 11=SMCLK)
  unsigned int i2crm: 1;    //Repeat mode (0=use I2CNDAT; 1=count in software)
  unsigned int i2cword: 1;  //Word mode (0=byte mode; 1=word mode)
  unsigned int i2cpsc: 8;   //Clock prescaler (values >0x04 not recomended)
  unsigned int i2csclh: 8;  //High period (high period=[value+2]*i2cpsc; can not be lower than 5*i2cpsc)
  unsigned int i2cscll: 8;  //Low period (low period=[value+2]*i2cpsc; can not be lower than 5*i2cpsc)
  unsigned int i2coa : 10;  // Own address register.
} msp430_i2c_config_t;

and the general I2CPacket interface, templated over the address size:

  async command error_t read(flags, addr, length, data);
  async command error_t write(flags, addr, length, data);

  // callbacks
  async event void readDone(error, addr, length, data);
  async event void writeDone(error, addr, length, data);

ST

Their interface is very low level. Basically, there is a C function for every I2C configuration parameter or function.

void I2C_Init(i2c, initParams);
void I2C_Cmd(i2c, state);
I2C_ITConfig(i2c, interrupts, state);
I2C_StretchClockCmd(i2c, state);
...
void I2C_SendData(i2c, byte);

I think they also realize this, and created a layer on top of I2C for writing applications.

u32 CPAL_I2C_Init(initParams);
u32 CPAL_I2C_Read(initParams);
u32 CPAL_I2C_Write(initParams);

// Callbacks
void CPAL_I2C_RXTC_UserCallback(initParams); // after received data
...

All RX and TX buffers are specified as a part of the struct (initParams) that is passed to each function. But of course even those are nested another struct deep.

typedef struct {
  CPAL_DevTypeDef         CPAL_Dev;        
  CPAL_DirectionTypeDef   CPAL_Direction;    /*!<Specifies the direction for the device transfers. */ 
  CPAL_ModeTypeDef        CPAL_Mode;         /*!<Specifies the maser/slave mode of device. It can be one of the */ 
  CPAL_ProgModelTypeDef   CPAL_ProgModel;    /*!<Specifies the programming model for the device transfers. */ 
  CPAL_TransferTypeDef*   pCPAL_TransferTx;  /*!<Pointer on a structure specifying the parameters of the current */ 
  CPAL_TransferTypeDef*   pCPAL_TransferRx;  /*!<Pointer on a structure specifying the parameters of the current */ 
  __IO CPAL_StateTypeDef  CPAL_State;        /*!<Holds the current State of the CPAL driver relative to the device */ 
  __IO uint32_t           wCPAL_DevError;    /*!<Specifies the error code for the current operation.The error codes */ 
  uint32_t                wCPAL_Options;     /*!<Bit-field value specifying additional options for the configuration */ 
  __IO uint32_t           wCPAL_Timeout;     /*!<This field is with timeout procedure. its used to detect timeout */    
  I2C_InitTypeDef*        pCPAL_I2C_Struct;  /*!<Pointer to a device Initialization structure as described */
} initParams;

Nordic

Only master mode.

int nrf_drv_twi_init(instance, config, event_handler);
void nrf_drv_twi_enable(instance);
void nrf_drv_twi_disable(instance);
int nrf_drv_twi_tx(instance, address, data, length, xfer_pending);
int nrf_drv_twi_rx(instance, address, data, length, xfer_pending);

This one is pretty nice. Note: in init, event handler can be NULL and the driver will use blocking calls.

Tock

pub trait I2C {
  // No magic here
  fn enable (&mut self);
  fn disable (&mut self);
	
  // Switch into slave mode
  fn set_slave_mode(&mut self, address: u16);
	
  // Switch into master mode
  fn set_master_mod(&mut self);
	
  // Master Mode
  fn write (&mut self, flags, addr: u16, data: &[u8], done);
  fn read (&mut self, flags, addr: u16, data: &[u8], done);
	
  // Slave Mode
  fn wait (&mut self, tx: &[u8], rx: &mut[u8], done);
}

Then of course there is the initial init which comes from the device tree.

Random Numbers

TinyOS

interface Random {
  async command uint32_t rand32();
  async command uint16_t rand16();
}

Nordic

int nrf_drv_rng_bytes_available(uint8_t* p_bytes_available);
int nrf_drv_rng_pool_capacity(uint8_t * p_pool_capacity);
// Gets a pointer to a buffer of random numbers
int nrf_drv_rng_rand(uint8_t * p_buff, uint8_t length);

Tock

pub trait RNG {
  /// Read a 32 bit random number.
  fn read (&mut self, done);

  /// Read multiple 32 bit random numbers.
  fn read_multiple (&mut self, count: usize, vals: &mut[u32], done);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment