twi.c File Reference


Detailed Description

TWI driver for AVR32 UC3.

This file defines a useful set of functions for TWI on AVR32 devices.

Author:
Atmel Corporation: http://www.atmel.com
Support and FAQ: http://support.atmel.no/

Definition in file twi.c.

#include <avr32/io.h>
#include "compiler.h"
#include "intc.h"
#include "twi.h"

Go to the source code of this file.

Functions

void twi_disable_interrupt (volatile avr32_twi_t *twi)
 Disable all TWI interrupts.
int twi_master_init (volatile avr32_twi_t *twi, const twi_options_t *opt)
 Initialize the twi master module.
static void twi_master_inst1_interrupt_handler (void)
 TWI interrupt handler.
int twi_master_read (volatile avr32_twi_t *twi, const twi_package_t *package)
 Read multiple bytes from a TWI compatible slave device.
int twi_master_write (volatile avr32_twi_t *twi, const twi_package_t *package)
 Write multiple bytes to a TWI compatible slave device.
int twi_probe (volatile avr32_twi_t *twi, char chip_addr)
 Test if a chip answers for a given twi address.
static int twi_set_speed (volatile avr32_twi_t *twi, unsigned int speed, unsigned long pba_hz)
 Set the twi bus speed in cojunction with the clock frequency.
int twi_slave_init (volatile avr32_twi_t *twi, const twi_options_t *opt, const twi_slave_fct_t *slave_fct)
 Initialize the twi slave module.
static void twi_slave_inst1_interrupt_handler (void)
 TWI interrupt handler.

Variables

static volatile avr32_twi_t * twi_inst1 = &AVR32_TWI
 Pointer to the instance 1 of the TWI registers for IT.
static volatile unsigned long twi_it_mask
 IT mask.
static volatile Bool twi_nack = FALSE
 Add NACK boolean.
static volatile unsigned char
*volatile 
twi_rx_data = NULL
 Pointer to the applicative TWI receive buffer.
static volatile int twi_rx_nb_bytes = 0
 Remaining number of bytes to receive.
static twi_slave_fct_t twi_slave_fct
 Pointer on TWI slave application routines.
static const unsigned char
*volatile 
twi_tx_data = NULL
 Pointer to the applicative TWI transmit buffer.
static volatile int twi_tx_nb_bytes = 0
 Remaining number of bytes to transmit.


Function Documentation

void twi_disable_interrupt ( volatile avr32_twi_t *  twi  ) 

Disable all TWI interrupts.

Parameters:
twi Base address of the TWI (i.e. &AVR32_TWI).

Definition at line 347 of file twi.c.

Referenced by twi_master_inst1_interrupt_handler().

00348 {
00349   Bool global_interrupt_enabled = Is_global_interrupt_enabled();
00350 
00351   if (global_interrupt_enabled) Disable_global_interrupt();
00352   twi->idr = ~0UL;
00353   twi->sr;
00354   if (global_interrupt_enabled) Enable_global_interrupt();
00355 }

int twi_master_init ( volatile avr32_twi_t *  twi,
const twi_options_t opt 
)

Initialize the twi master module.

Parameters:
twi Base address of the TWI (i.e. &AVR32_TWI).
*opt Options for initializing the twi module (see twi_options_t)

Definition at line 258 of file twi.c.

References twi_options_t::chip, twi_options_t::pba_hz, twi_options_t::speed, twi_master_inst1_interrupt_handler(), twi_probe(), and twi_set_speed().

Referenced by main().

00259 {
00260   Bool global_interrupt_enabled = Is_global_interrupt_enabled();
00261   int status;
00262 
00263   // Disable TWI interrupts
00264   if (global_interrupt_enabled) Disable_global_interrupt();
00265   twi->idr = ~0UL;
00266   twi->sr;
00267 
00268   // Reset TWI
00269   twi->cr = AVR32_TWI_CR_SWRST_MASK;
00270   if (global_interrupt_enabled) Enable_global_interrupt();
00271 
00272   // Dummy read in SR
00273   status = twi->sr;
00274 
00275   // Disable all interrupts
00276   Disable_global_interrupt();
00277 
00278   // Register TWI handler on level 2
00279   INTC_register_interrupt( &twi_master_inst1_interrupt_handler, AVR32_TWI_IRQ, AVR32_INTC_INT1);
00280 
00281   // Enable all interrupts
00282   Enable_global_interrupt();
00283 
00284   // Select the speed
00285   twi_set_speed(twi, opt->speed, opt->pba_hz);
00286 
00287   // Probe the component
00288   status = twi_probe(twi, opt->chip);
00289 
00290   return status;
00291 }

static void twi_master_inst1_interrupt_handler ( void   )  [static]

TWI interrupt handler.

Definition at line 85 of file twi.c.

References twi_disable_interrupt(), twi_inst1, twi_it_mask, twi_nack, twi_rx_data, twi_rx_nb_bytes, twi_tx_data, and twi_tx_nb_bytes.

Referenced by twi_master_init().

00086 {
00087   // get masked status register value
00088   int status = twi_inst1->sr & twi_it_mask;
00089 
00090   // this is a NACK
00091   if (status & AVR32_TWI_SR_NACK_MASK)
00092   {
00093     goto nack;
00094   }
00095   // this is a RXRDY
00096   else if (status & AVR32_TWI_SR_RXRDY_MASK)
00097   {
00098     // get data from Receive Holding Register
00099     *twi_rx_data = twi_inst1->rhr;
00100     twi_rx_data++;
00101     // last byte to receive
00102     if(--twi_rx_nb_bytes==1)
00103     {
00104       // set stop bit
00105       twi_inst1->cr = AVR32_TWI_STOP_MASK;
00106     }
00107     // receive complete
00108     if (twi_rx_nb_bytes==0)
00109     {
00110       // finish the receive operation
00111       goto complete;
00112     }
00113   }
00114   // this is a TXRDY
00115   else if (status & AVR32_TWI_SR_TXRDY_MASK)
00116   {
00117     // decrease transmited bytes number
00118     twi_tx_nb_bytes--;
00119     // no more bytes to transmit
00120     if (twi_tx_nb_bytes <= 0)
00121     {
00122       // enable TXCOMP IT and unmask all others IT
00123       twi_it_mask = AVR32_TWI_IER_TXCOMP_MASK;
00124       twi_inst1->ier = twi_it_mask;
00125     }
00126     else
00127     {
00128       // put the byte in the Transmit Holding Register
00129       twi_inst1->thr = *twi_tx_data++;
00130     }
00131   }
00132   // this is a TXCOMP
00133   else if (status & AVR32_TWI_SR_TXCOMP_MASK)
00134   {
00135     // finish the transmit operation
00136     goto complete;
00137   }
00138 
00139   return;
00140 
00141 nack:
00142   twi_nack = TRUE;
00143 
00144 complete:
00145   // disable all interrupts
00146   twi_disable_interrupt(twi_inst1);
00147 
00148   return;
00149 }

int twi_master_read ( volatile avr32_twi_t *  twi,
const twi_package_t package 
)

Read multiple bytes from a TWI compatible slave device.

Parameters:
twi Base address of the TWI (i.e. &AVR32_TWI).
package Package information and data (see twi_package_t)
Returns:
TWI_SUCCESS if all bytes were read, error code otherwhise

Definition at line 378 of file twi.c.

References twi_package_t::addr, twi_package_t::addr_length, twi_package_t::buffer, twi_package_t::chip, twi_package_t::length, TWI_INVALID_ARGUMENT, twi_it_mask, twi_nack, TWI_RECEIVE_NACK, twi_rx_data, twi_rx_nb_bytes, and TWI_SUCCESS.

Referenced by main().

00379 {
00380   // check argument
00381   if (package->length == 0)
00382   {
00383     return TWI_INVALID_ARGUMENT;
00384   }
00385 
00386   twi_nack = FALSE;
00387 
00388   // set read mode, slave address and 3 internal address byte length
00389   twi->mmr = (package->chip << AVR32_TWI_MMR_DADR_OFFSET) |
00390              ((package->addr_length << AVR32_TWI_MMR_IADRSZ_OFFSET) & AVR32_TWI_MMR_IADRSZ_MASK) |
00391              (1 << AVR32_TWI_MMR_MREAD_OFFSET);
00392 
00393   // set internal address for remote chip
00394   twi->iadr = package->addr;
00395 
00396   // get a pointer to applicative data
00397   twi_rx_data = package->buffer;
00398 
00399   // get a copy of nb bytes to read
00400   twi_rx_nb_bytes = package->length;
00401 
00402   // Enable master transfer
00403   twi->cr =  AVR32_TWI_CR_MSEN_MASK;
00404 
00405   // Send start condition
00406   twi->cr = AVR32_TWI_START_MASK;
00407 
00408   // only one byte to receive
00409   if(twi_rx_nb_bytes == 1)
00410   {
00411     // set stop bit
00412     twi->cr = AVR32_TWI_STOP_MASK;
00413   }
00414 
00415   // mask NACK and RXRDY interrupts
00416   twi_it_mask = AVR32_TWI_IER_NACK_MASK | AVR32_TWI_IER_RXRDY_MASK;
00417 
00418   // update IMR through IER
00419   twi->ier = twi_it_mask;
00420 
00421   // get data
00422   while (!twi_nack && twi_rx_nb_bytes);
00423 
00424   // Disable master transfer
00425   twi->cr =  AVR32_TWI_CR_MSDIS_MASK;
00426 
00427   if( twi_nack )
00428     return TWI_RECEIVE_NACK;
00429 
00430   return TWI_SUCCESS;
00431 }

int twi_master_write ( volatile avr32_twi_t *  twi,
const twi_package_t package 
)

Write multiple bytes to a TWI compatible slave device.

Parameters:
twi Base address of the TWI (i.e. &AVR32_TWI).
*package Package information and data (see twi_package_t)
Returns:
TWI_SUCCESS if all bytes were written, error code otherwhise

Definition at line 434 of file twi.c.

References twi_package_t::addr, twi_package_t::addr_length, twi_package_t::buffer, twi_package_t::chip, twi_package_t::length, twi_inst1, TWI_INVALID_ARGUMENT, twi_it_mask, twi_nack, TWI_RECEIVE_NACK, TWI_SUCCESS, twi_tx_data, and twi_tx_nb_bytes.

Referenced by main(), and twi_probe().

00435 {
00436   // No data to send
00437   if (package->length == 0)
00438   {
00439     return TWI_INVALID_ARGUMENT;
00440   }
00441 
00442   twi_nack = FALSE;
00443 
00444   // Enable master transfer, disable slave
00445   twi->cr =   AVR32_TWI_CR_MSEN_MASK
00446 #ifndef AVR32_TWI_180_H_INCLUDED
00447             | AVR32_TWI_CR_SVDIS_MASK
00448 #endif
00449             ;
00450 
00451   // set write mode, slave address and 3 internal address byte length
00452   twi->mmr = (0 << AVR32_TWI_MMR_MREAD_OFFSET) |
00453              (package->chip << AVR32_TWI_MMR_DADR_OFFSET) |
00454              ((package->addr_length << AVR32_TWI_MMR_IADRSZ_OFFSET) & AVR32_TWI_MMR_IADRSZ_MASK);
00455 
00456   // set internal address for remote chip
00457   twi->iadr = package->addr;
00458 
00459   // get a pointer to applicative data
00460   twi_tx_data = package->buffer;
00461 
00462   // get a copy of nb bytes to write
00463   twi_tx_nb_bytes = package->length;
00464 
00465   // put the first byte in the Transmit Holding Register
00466   twi_inst1->thr = *twi_tx_data++;
00467 
00468   // mask NACK and TXRDY interrupts
00469   twi_it_mask = AVR32_TWI_IER_NACK_MASK | AVR32_TWI_IER_TXRDY_MASK;
00470 
00471   // update IMR through IER
00472   twi->ier = twi_it_mask;
00473 
00474   // send data
00475   while (!twi_nack && twi_tx_nb_bytes);
00476 
00477   // Disable master transfer
00478   twi->cr =  AVR32_TWI_CR_MSDIS_MASK;
00479 
00480   if( twi_nack )
00481     return TWI_RECEIVE_NACK;
00482 
00483   return TWI_SUCCESS;
00484 }

int twi_probe ( volatile avr32_twi_t *  twi,
char  chip_addr 
)

Test if a chip answers for a given twi address.

Parameters:
twi Base address of the TWI (i.e. &AVR32_TWI).
chip_addr Address of the chip which is searched for
Returns:
TWI_SUCCESS if a chip was found, error code otherwhise

Definition at line 358 of file twi.c.

References twi_package_t::addr, twi_package_t::addr_length, twi_package_t::buffer, twi_package_t::chip, twi_package_t::length, and twi_master_write().

Referenced by twi_master_init().

00359 {
00360   twi_package_t package;
00361   char data[1] = {0};
00362 
00363   // data to send
00364   package.buffer = data;
00365   // chip address
00366   package.chip = chip_addr;
00367   // frame length
00368   package.length = 1;
00369   // address length
00370   package.addr_length = 0;
00371   // internal chip address
00372   package.addr = 0;
00373   // perform a master write access
00374   return (twi_master_write(twi, &package));
00375 }

static int twi_set_speed ( volatile avr32_twi_t *  twi,
unsigned int  speed,
unsigned long  pba_hz 
) [static]

Set the twi bus speed in cojunction with the clock frequency.

Parameters:
twi Base address of the TWI (i.e. &AVR32_TWI).
speed The desired twi bus speed
pba_hz The current running PBA clock frequency
Returns:
TWI_SUCCESS

Definition at line 236 of file twi.c.

References TWI_SUCCESS.

Referenced by twi_master_init(), and twi_slave_init().

00237 {
00238   unsigned int cldiv;
00239   unsigned int ckdiv = 0;
00240 
00241   cldiv = (pba_hz / speed) - 4;
00242 
00243   // cldiv must fit in 8 bits, ckdiv must fit in 3 bits
00244   while ((cldiv > 0xFF) && (ckdiv < 0x7))
00245   {
00246     // increase clock divider
00247     ckdiv++;
00248     // divide cldiv value
00249     cldiv /= 2;
00250   }
00251   // set clock waveform generator register
00252   twi->cwgr = ( cldiv | (cldiv << AVR32_TWI_CWGR_CHDIV_OFFSET) | (ckdiv << AVR32_TWI_CWGR_CKDIV_OFFSET) );
00253 
00254   return TWI_SUCCESS;
00255 }

int twi_slave_init ( volatile avr32_twi_t *  twi,
const twi_options_t opt,
const twi_slave_fct_t slave_fct 
)

Initialize the twi slave module.

Parameters:
twi Base address of the TWI (i.e. &AVR32_TWI).
*opt Options for initializing the twi module (see twi_options_t)
*slave_fct Pointer on application fonctions

Definition at line 296 of file twi.c.

References twi_options_t::chip, twi_options_t::pba_hz, twi_options_t::speed, twi_it_mask, twi_set_speed(), twi_slave_inst1_interrupt_handler(), and TWI_SUCCESS.

00297 {
00298   Bool global_interrupt_enabled = Is_global_interrupt_enabled();
00299 
00300   // Disable TWI interrupts
00301   if (global_interrupt_enabled) Disable_global_interrupt();
00302   twi->idr = ~0UL;
00303   twi->sr;
00304 
00305   // Reset TWI
00306   twi->cr = AVR32_TWI_CR_SWRST_MASK;
00307 
00308   if (global_interrupt_enabled) Enable_global_interrupt();
00309 
00310   // Dummy read in SR
00311   twi->sr;
00312 
00313   // Disable all interrupts
00314   Disable_global_interrupt();
00315 
00316   // Register TWI handler on level 2
00317   INTC_register_interrupt( &twi_slave_inst1_interrupt_handler, AVR32_TWI_IRQ, AVR32_INTC_INT1);
00318 
00319   // Enable all interrupts
00320   Enable_global_interrupt();
00321 
00322   // Select the speed
00323   twi_set_speed(twi, opt->speed, opt->pba_hz);
00324 
00325   //** Link reception routine
00326 
00327   // Disable master transfer, ensable slave
00328   twi->cr =  AVR32_TWI_CR_MSDIS_MASK|AVR32_TWI_CR_SVEN_MASK;
00329 
00330   // Set slave address
00331   twi->smr = (opt->chip << AVR32_TWI_SMR_SADR_OFFSET);
00332 
00333   // get a pointer to applicative routines
00334   twi_slave_fct = *slave_fct;
00335 
00336   // Slave Access Interrupt Enable
00337   twi_it_mask = AVR32_TWI_IER_SVACC_MASK;
00338   twi->ier = twi_it_mask;
00339 
00340   // Everything went ok
00341   return TWI_SUCCESS;
00342 }

static void twi_slave_inst1_interrupt_handler ( void   )  [static]

TWI interrupt handler.

Definition at line 161 of file twi.c.

References twi_slave_fct_t::rx, twi_slave_fct_t::stop, twi_inst1, twi_it_mask, and twi_slave_fct_t::tx.

Referenced by twi_slave_init().

00162 {
00163   // get masked status register value
00164   int status = twi_inst1->sr;
00165 
00166   if( (twi_it_mask & AVR32_TWI_IER_EOSACC_MASK)
00167   &&  (status & AVR32_TWI_SR_EOSACC_MASK) )
00168   {
00169     // Disable All interrupts
00170     twi_inst1->idr = AVR32_TWI_IDR_TXRDY_MASK|AVR32_TWI_IDR_RXRDY_MASK|AVR32_TWI_IER_EOSACC_MASK;
00171     // Reenable detection slave access
00172     twi_it_mask = AVR32_TWI_IER_SVACC_MASK;
00173     twi_inst1->ier = twi_it_mask;
00174     // Signal EOF access
00175     twi_slave_fct.stop();
00176   }else
00177 
00178   if( (twi_it_mask & AVR32_TWI_IER_SVACC_MASK)
00179   &&  (status & AVR32_TWI_SR_SVACC_MASK ) )
00180   {
00181     twi_inst1->idr = AVR32_TWI_IDR_SVACC_MASK;
00182     // A slave is selected, then check direction
00183     if( status & AVR32_TWI_SR_SVREAD_MASK )
00184     {
00185       // enable flag to signal data transmition
00186       twi_it_mask = AVR32_TWI_IER_TXRDY_MASK;
00187       twi_inst1->ier = twi_it_mask;
00188       // Transmit a data to master
00189       twi_inst1->thr = twi_slave_fct.tx();
00190     }else{
00191       // enable flag to signal data reception
00192       twi_it_mask = AVR32_TWI_IER_RXRDY_MASK|AVR32_TWI_IER_EOSACC_MASK;
00193       twi_inst1->ier = twi_it_mask;
00194     }
00195   }else
00196 
00197   // this is a RXRDY
00198   if( (twi_it_mask & AVR32_TWI_IER_RXRDY_MASK)
00199   &&  (status & AVR32_TWI_SR_RXRDY_MASK ) )
00200   {
00201     // Get data from Receive Holding Register
00202     twi_slave_fct.rx( twi_inst1->rhr );
00203   }else
00204 
00205   // this is a TXRDY
00206   if( (twi_it_mask & AVR32_TWI_IER_TXRDY_MASK)
00207   &&  (status & AVR32_TWI_SR_TXRDY_MASK ) )
00208   {
00209     // Byte transmited
00210     if( status & AVR32_TWI_SR_NACK_MASK )
00211     {
00212       // Last Byte
00213       // Clear flag NACK
00214       twi_inst1->rhr;
00215       // Renable IT select slave
00216       twi_it_mask = AVR32_TWI_IER_EOSACC_MASK;
00217       twi_inst1->ier = twi_it_mask;
00218     }else{
00219       // Transmit a data to master
00220       twi_inst1->thr = twi_slave_fct.tx();
00221     }
00222   }
00223   return;
00224 }


Variable Documentation

volatile avr32_twi_t* twi_inst1 = &AVR32_TWI [static]

Pointer to the instance 1 of the TWI registers for IT.

Definition at line 52 of file twi.c.

Referenced by twi_master_inst1_interrupt_handler(), twi_master_write(), and twi_slave_inst1_interrupt_handler().

volatile unsigned long twi_it_mask [static]

volatile Bool twi_nack = FALSE [static]

Add NACK boolean.

Definition at line 65 of file twi.c.

Referenced by twi_master_inst1_interrupt_handler(), twi_master_read(), and twi_master_write().

volatile unsigned char* volatile twi_rx_data = NULL [static]

Pointer to the applicative TWI receive buffer.

Definition at line 57 of file twi.c.

Referenced by twi_master_inst1_interrupt_handler(), and twi_master_read().

volatile int twi_rx_nb_bytes = 0 [static]

Remaining number of bytes to receive.

Definition at line 62 of file twi.c.

Referenced by twi_master_inst1_interrupt_handler(), and twi_master_read().

Pointer on TWI slave application routines.

Definition at line 73 of file twi.c.

const unsigned char* volatile twi_tx_data = NULL [static]

Pointer to the applicative TWI transmit buffer.

Definition at line 55 of file twi.c.

Referenced by twi_master_inst1_interrupt_handler(), and twi_master_write().

volatile int twi_tx_nb_bytes = 0 [static]

Remaining number of bytes to transmit.

Definition at line 60 of file twi.c.

Referenced by twi_master_inst1_interrupt_handler(), and twi_master_write().


Generated on Tue Nov 25 11:16:36 2008 for AVR32 - TWI Driver - Single-Master Mode by  doxygen 1.5.6