- Main Page
- Related Pages
- Data Structures
- Files

# twi.c

Go to the documentation of this file.

    00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
    00017 /* Copyright (C) 2006-2008, Atmel Corporation All rights reserved.
    00018  *
    00019  * Redistribution and use in source and binary forms, with or without
    00020  * modification, are permitted provided that the following conditions are met:
    00021  *
    00022  * 1. Redistributions of source code must retain the above copyright notice,
    00023  * this list of conditions and the following disclaimer.
    00024  *
    00025  * 2. Redistributions in binary form must reproduce the above copyright notice,
    00026  * this list of conditions and the following disclaimer in the documentation
    00027  * and/or other materials provided with the distribution.
    00028  *
    00029  * 3. The name of ATMEL may not be used to endorse or promote products derived
    00030  * from this software without specific prior written permission.
    00031  *
    00032  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
    00033  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00034  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
    00035  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
    00036  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    00037  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    00038  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    00039  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00040  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    00041  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00042  */
    00043
    00044
    00045 #include <avr32/io.h>
    00046 #include "compiler.h"
    00047 #include "intc.h"
    00048 #include "twi.h"
    00049
    00050
    00052 static volatile avr32_twi_t *twi_inst1 = &AVR32_TWI;
    00053
    00055 static const unsigned char *volatile twi_tx_data = NULL;
    00057 static volatile unsigned char *volatile twi_rx_data = NULL;
    00058
    00060 static volatile int twi_tx_nb_bytes = 0;
    00062 static volatile int twi_rx_nb_bytes = 0;
    00063
    00065 static volatile Bool twi_nack = FALSE;
    00066
    00068 static volatile unsigned long twi_it_mask;
    00069
    00070 #ifndef AVR32_TWI_180_H_INCLUDED
    00071
    00073 static twi_slave_fct_t twi_slave_fct;
    00074
    00075 #endif
    00076
    00077
    00080 #if __GNUC__
    00081 __attribute__((__interrupt__))
    00082 #elif __ICCAVR32__
    00083 __interrupt
    00084 #endif
    00085 static void twi_master_inst1_interrupt_handler(void)
    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 }
    00150
    00151
    00152 #ifndef AVR32_TWI_180_H_INCLUDED
    00153
    00156 #if __GNUC__
    00157 __attribute__((__interrupt__))
    00158 #elif __ICCAVR32__
    00159 __interrupt
    00160 #endif
    00161 static void twi_slave_inst1_interrupt_handler(void)
    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 }
    00225
    00226 #endif
    00227
    00228
    00236 static int twi_set_speed(volatile avr32_twi_t *twi, unsigned int speed, unsigned long pba_hz)
    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 }
    00256
    00257
    00258 int twi_master_init(volatile avr32_twi_t *twi, const twi_options_t *opt)
    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 }
    00292
    00293
    00294 #ifndef AVR32_TWI_180_H_INCLUDED
    00295
    00296 int twi_slave_init(volatile avr32_twi_t *twi, const twi_options_t *opt, const twi_slave_fct_t *slave_fct)
    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 }
    00343
    00344 #endif
    00345
    00346
    00347 void twi_disable_interrupt(volatile avr32_twi_t *twi)
    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 }
    00356
    00357
    00358 int twi_probe(volatile avr32_twi_t *twi, char chip_addr)
    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 }
    00376
    00377
    00378 int twi_master_read(volatile avr32_twi_t *twi, const twi_package_t *package)
    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 }
    00432
    00433
    00434 int twi_master_write(volatile avr32_twi_t *twi, const twi_package_t *package)
    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 }