This file defines a useful set of functions for TWI on AVR32 devices.
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. | |
Bool | twi_is_busy (void) |
Test if a TWI read/write is pending. | |
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_master_write_ex (volatile avr32_twi_t *twi, const twi_package_t *package) |
This function is not blocking. | |
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. |
void twi_disable_interrupt | ( | volatile avr32_twi_t * | twi | ) |
Disable all TWI interrupts.
twi | Base address of the TWI (i.e. &AVR32_TWI). |
Definition at line 353 of file twi.c.
Referenced by twi_master_inst1_interrupt_handler().
00354 { 00355 Bool global_interrupt_enabled = Is_global_interrupt_enabled(); 00356 00357 if (global_interrupt_enabled) Disable_global_interrupt(); 00358 twi->idr = ~0UL; 00359 twi->sr; 00360 if (global_interrupt_enabled) Enable_global_interrupt(); 00361 }
Bool twi_is_busy | ( | void | ) |
Test if a TWI read/write is pending.
Definition at line 550 of file twi.c.
References twi_nack, twi_rx_nb_bytes, and twi_tx_nb_bytes.
Referenced by twi_master_read(), and twi_master_write().
00551 { 00552 if( !twi_nack && ( twi_rx_nb_bytes || twi_tx_nb_bytes ) ) 00553 return TRUE; // Still receiving/transmitting... 00554 00555 else 00556 return FALSE; 00557 }
int twi_master_init | ( | volatile avr32_twi_t * | twi, | |
const twi_options_t * | opt | |||
) |
Initialize the twi master module.
twi | Base address of the TWI (i.e. &AVR32_TWI). | |
*opt | Options for initializing the twi module (see twi_options_t) |
Definition at line 264 of file twi.c.
References twi_options_t::pba_hz, twi_options_t::speed, twi_master_inst1_interrupt_handler(), twi_set_speed(), and TWI_SUCCESS.
00265 { 00266 Bool global_interrupt_enabled = Is_global_interrupt_enabled(); 00267 int status = TWI_SUCCESS; 00268 00269 // Disable TWI interrupts 00270 if (global_interrupt_enabled) Disable_global_interrupt(); 00271 twi->idr = ~0UL; 00272 twi->sr; 00273 00274 // Reset TWI 00275 twi->cr = AVR32_TWI_CR_SWRST_MASK; 00276 if (global_interrupt_enabled) Enable_global_interrupt(); 00277 00278 // Dummy read in SR 00279 twi->sr; 00280 00281 // Disable all interrupts 00282 Disable_global_interrupt(); 00283 00284 // Register TWI handler on level 2 00285 INTC_register_interrupt( &twi_master_inst1_interrupt_handler, AVR32_TWI_IRQ, AVR32_INTC_INT1); 00286 00287 // Enable all interrupts 00288 Enable_global_interrupt(); 00289 00290 // Select the speed 00291 twi_set_speed(twi, opt->speed, opt->pba_hz); 00292 00293 // Probe the component 00294 //status = twi_probe(twi, opt->chip); 00295 00296 return status; 00297 }
static void twi_master_inst1_interrupt_handler | ( | void | ) | [static] |
TWI interrupt handler.
Definition at line 88 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().
00089 { 00090 // get masked status register value 00091 int status = twi_inst1->sr & twi_it_mask; 00092 00093 // this is a NACK 00094 if (status & AVR32_TWI_SR_NACK_MASK) 00095 { 00096 goto nack; 00097 } 00098 // this is a RXRDY 00099 else if (status & AVR32_TWI_SR_RXRDY_MASK) 00100 { 00101 // get data from Receive Holding Register 00102 *twi_rx_data = twi_inst1->rhr; 00103 twi_rx_data++; 00104 // last byte to receive 00105 if(--twi_rx_nb_bytes==1) 00106 { 00107 // set stop bit 00108 twi_inst1->cr = AVR32_TWI_STOP_MASK; 00109 } 00110 // receive complete 00111 if (twi_rx_nb_bytes==0) 00112 { 00113 // finish the receive operation 00114 goto complete; 00115 } 00116 } 00117 // this is a TXRDY 00118 else if (status & AVR32_TWI_SR_TXRDY_MASK) 00119 { 00120 // decrease transmited bytes number 00121 twi_tx_nb_bytes--; 00122 // no more bytes to transmit 00123 if (twi_tx_nb_bytes <= 0) 00124 { 00125 // enable TXCOMP IT and unmask all others IT 00126 twi_it_mask = AVR32_TWI_IER_TXCOMP_MASK; 00127 twi_inst1->ier = twi_it_mask; 00128 } 00129 else 00130 { 00131 // put the byte in the Transmit Holding Register 00132 twi_inst1->thr = *twi_tx_data++; 00133 } 00134 } 00135 // this is a TXCOMP 00136 else if (status & AVR32_TWI_SR_TXCOMP_MASK) 00137 { 00138 // finish the transmit operation 00139 goto complete; 00140 } 00141 00142 return; 00143 00144 nack: 00145 twi_nack = TRUE; 00146 00147 complete: 00148 // disable all interrupts 00149 twi_disable_interrupt(twi_inst1); 00150 00151 return; 00152 }
int twi_master_read | ( | volatile avr32_twi_t * | twi, | |
const twi_package_t * | package | |||
) |
Read multiple bytes from a TWI compatible slave device.
twi | Base address of the TWI (i.e. &AVR32_TWI). | |
package | Package information and data (see twi_package_t) |
Definition at line 384 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_is_busy(), twi_it_mask, twi_nack, TWI_RECEIVE_NACK, twi_rx_data, twi_rx_nb_bytes, and TWI_SUCCESS.
00385 { 00386 // check argument 00387 if (package->length == 0) 00388 { 00389 return TWI_INVALID_ARGUMENT; 00390 } 00391 00392 while( twi_is_busy() ) {}; 00393 00394 twi_nack = FALSE; 00395 00396 // set read mode, slave address and 3 internal address byte length 00397 twi->mmr = (package->chip << AVR32_TWI_MMR_DADR_OFFSET) | 00398 ((package->addr_length << AVR32_TWI_MMR_IADRSZ_OFFSET) & AVR32_TWI_MMR_IADRSZ_MASK) | 00399 (1 << AVR32_TWI_MMR_MREAD_OFFSET); 00400 00401 // set internal address for remote chip 00402 twi->iadr = package->addr; 00403 00404 // get a pointer to applicative data 00405 twi_rx_data = package->buffer; 00406 00407 // get a copy of nb bytes to read 00408 twi_rx_nb_bytes = package->length; 00409 00410 // Enable master transfer 00411 twi->cr = AVR32_TWI_CR_MSEN_MASK; 00412 00413 // Send start condition 00414 twi->cr = AVR32_TWI_START_MASK; 00415 00416 // only one byte to receive 00417 if(twi_rx_nb_bytes == 1) 00418 { 00419 // set stop bit 00420 twi->cr = AVR32_TWI_STOP_MASK; 00421 } 00422 00423 // mask NACK and RXRDY interrupts 00424 twi_it_mask = AVR32_TWI_IER_NACK_MASK | AVR32_TWI_IER_RXRDY_MASK; 00425 00426 // update IMR through IER 00427 twi->ier = twi_it_mask; 00428 00429 // get data 00430 while (!twi_nack && twi_rx_nb_bytes); 00431 00432 // Disable master transfer 00433 twi->cr = AVR32_TWI_CR_MSDIS_MASK; 00434 00435 if( twi_nack ) 00436 return TWI_RECEIVE_NACK; 00437 00438 return TWI_SUCCESS; 00439 }
int twi_master_write | ( | volatile avr32_twi_t * | twi, | |
const twi_package_t * | package | |||
) |
Write multiple bytes to a TWI compatible slave device.
twi | Base address of the TWI (i.e. &AVR32_TWI). | |
*package | Package information and data (see twi_package_t) |
Definition at line 442 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_is_busy(), twi_it_mask, twi_nack, TWI_RECEIVE_NACK, TWI_SUCCESS, twi_tx_data, and twi_tx_nb_bytes.
Referenced by twi_probe().
00443 { 00444 // No data to send 00445 if (package->length == 0) 00446 { 00447 return TWI_INVALID_ARGUMENT; 00448 } 00449 00450 while( twi_is_busy() ) {}; 00451 00452 twi_nack = FALSE; 00453 00454 // Enable master transfer, disable slave 00455 twi->cr = AVR32_TWI_CR_MSEN_MASK 00456 #ifndef AVR32_TWI_180_H_INCLUDED 00457 | AVR32_TWI_CR_SVDIS_MASK 00458 #endif 00459 ; 00460 00461 // set write mode, slave address and 3 internal address byte length 00462 twi->mmr = (0 << AVR32_TWI_MMR_MREAD_OFFSET) | 00463 (package->chip << AVR32_TWI_MMR_DADR_OFFSET) | 00464 ((package->addr_length << AVR32_TWI_MMR_IADRSZ_OFFSET) & AVR32_TWI_MMR_IADRSZ_MASK); 00465 00466 // set internal address for remote chip 00467 twi->iadr = package->addr; 00468 00469 // get a pointer to applicative data 00470 twi_tx_data = package->buffer; 00471 00472 // get a copy of nb bytes to write 00473 twi_tx_nb_bytes = package->length; 00474 00475 // put the first byte in the Transmit Holding Register 00476 twi_inst1->thr = *twi_tx_data++; 00477 00478 // mask NACK and TXRDY interrupts 00479 twi_it_mask = AVR32_TWI_IER_NACK_MASK | AVR32_TWI_IER_TXRDY_MASK; 00480 00481 // update IMR through IER 00482 twi->ier = twi_it_mask; 00483 00484 // send data 00485 while (!twi_nack && twi_tx_nb_bytes); 00486 00487 // Disable master transfer 00488 twi->cr = AVR32_TWI_CR_MSDIS_MASK; 00489 00490 if( twi_nack ) 00491 return TWI_RECEIVE_NACK; 00492 00493 return TWI_SUCCESS; 00494 }
int twi_master_write_ex | ( | volatile avr32_twi_t * | twi, | |
const twi_package_t * | package | |||
) |
This function is not blocking.
Write multiple bytes to a TWI compatible slave device. This function is not blocking.
Definition at line 498 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_BUSY, twi_inst1, TWI_INVALID_ARGUMENT, twi_it_mask, twi_nack, TWI_RECEIVE_NACK, TWI_SUCCESS, twi_tx_data, and twi_tx_nb_bytes.
00499 { 00500 int status = TWI_SUCCESS; 00501 00502 if( twi_nack ) 00503 status = TWI_RECEIVE_NACK; // Previous transaction returns a NACK 00504 00505 else if( twi_tx_nb_bytes ) 00506 return TWI_BUSY; // Still transmitting... 00507 00508 // No data to send 00509 if (package->length == 0) 00510 { 00511 return TWI_INVALID_ARGUMENT; 00512 } 00513 00514 twi_nack = FALSE; 00515 00516 // Enable master transfer, disable slave 00517 twi->cr = AVR32_TWI_CR_MSEN_MASK 00518 #ifndef AVR32_TWI_180_H_INCLUDED 00519 | AVR32_TWI_CR_SVDIS_MASK 00520 #endif 00521 ; 00522 00523 // set write mode, slave address and 3 internal address byte length 00524 twi->mmr = (0 << AVR32_TWI_MMR_MREAD_OFFSET) | 00525 (package->chip << AVR32_TWI_MMR_DADR_OFFSET) | 00526 ((package->addr_length << AVR32_TWI_MMR_IADRSZ_OFFSET) & AVR32_TWI_MMR_IADRSZ_MASK); 00527 00528 // set internal address for remote chip 00529 twi->iadr = package->addr; 00530 00531 // get a pointer to applicative data 00532 twi_tx_data = package->buffer; 00533 00534 // get a copy of nb bytes to write 00535 twi_tx_nb_bytes = package->length; 00536 00537 // put the first byte in the Transmit Holding Register 00538 twi_inst1->thr = *twi_tx_data++; 00539 00540 // mask NACK and TXRDY interrupts 00541 twi_it_mask = AVR32_TWI_IER_NACK_MASK | AVR32_TWI_IER_TXRDY_MASK; 00542 00543 // update IMR through IER 00544 twi->ier = twi_it_mask; 00545 00546 return status; 00547 }
int twi_probe | ( | volatile avr32_twi_t * | twi, | |
char | chip_addr | |||
) |
Test if a chip answers for a given twi address.
twi | Base address of the TWI (i.e. &AVR32_TWI). | |
chip_addr | Address of the chip which is searched for |
Definition at line 364 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().
00365 { 00366 twi_package_t package; 00367 char data[1] = {0}; 00368 00369 // data to send 00370 package.buffer = data; 00371 // chip address 00372 package.chip = chip_addr; 00373 // frame length 00374 package.length = 1; 00375 // address length 00376 package.addr_length = 0; 00377 // internal chip address 00378 package.addr = 0; 00379 // perform a master write access 00380 return (twi_master_write(twi, &package)); 00381 }
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.
twi | Base address of the TWI (i.e. &AVR32_TWI). | |
speed | The desired twi bus speed | |
pba_hz | The current running PBA clock frequency |
Definition at line 239 of file twi.c.
References TWI_SUCCESS.
Referenced by twi_master_init(), and twi_slave_init().
00240 { 00241 unsigned int ckdiv = 0; 00242 unsigned int c_lh_div; 00243 00244 c_lh_div = pba_hz / (speed * 2) - 4; 00245 00246 // cldiv must fit in 8 bits, ckdiv must fit in 3 bits 00247 while ((c_lh_div > 0xFF) && (ckdiv < 0x7)) 00248 { 00249 // increase clock divider 00250 ckdiv++; 00251 // divide cldiv value 00252 c_lh_div /= 2; 00253 } 00254 00255 // set clock waveform generator register 00256 twi->cwgr = ((c_lh_div << AVR32_TWI_CWGR_CLDIV_OFFSET) | 00257 (c_lh_div << AVR32_TWI_CWGR_CHDIV_OFFSET) | 00258 (ckdiv << AVR32_TWI_CWGR_CKDIV_OFFSET)); 00259 00260 return TWI_SUCCESS; 00261 }
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.
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 302 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.
Referenced by main().
00303 { 00304 Bool global_interrupt_enabled = Is_global_interrupt_enabled(); 00305 00306 // Disable TWI interrupts 00307 if (global_interrupt_enabled) Disable_global_interrupt(); 00308 twi->idr = ~0UL; 00309 twi->sr; 00310 00311 // Reset TWI 00312 twi->cr = AVR32_TWI_CR_SWRST_MASK; 00313 00314 if (global_interrupt_enabled) Enable_global_interrupt(); 00315 00316 // Dummy read in SR 00317 twi->sr; 00318 00319 // Disable all interrupts 00320 Disable_global_interrupt(); 00321 00322 // Register TWI handler on level 2 00323 INTC_register_interrupt( &twi_slave_inst1_interrupt_handler, AVR32_TWI_IRQ, AVR32_INTC_INT1); 00324 00325 // Enable all interrupts 00326 Enable_global_interrupt(); 00327 00328 // Select the speed 00329 twi_set_speed(twi, opt->speed, opt->pba_hz); 00330 00331 //** Link reception routine 00332 00333 // Disable master transfer, ensable slave 00334 twi->cr = AVR32_TWI_CR_MSDIS_MASK|AVR32_TWI_CR_SVEN_MASK; 00335 00336 // Set slave address 00337 twi->smr = (opt->chip << AVR32_TWI_SMR_SADR_OFFSET); 00338 00339 // get a pointer to applicative routines 00340 twi_slave_fct = *slave_fct; 00341 00342 // Slave Access Interrupt Enable 00343 twi_it_mask = AVR32_TWI_IER_SVACC_MASK; 00344 twi->ier = twi_it_mask; 00345 00346 // Everything went ok 00347 return TWI_SUCCESS; 00348 }
static void twi_slave_inst1_interrupt_handler | ( | void | ) | [static] |
TWI interrupt handler.
Definition at line 164 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().
00165 { 00166 // get masked status register value 00167 int status = twi_inst1->sr; 00168 00169 if( (twi_it_mask & AVR32_TWI_IER_EOSACC_MASK) 00170 && (status & AVR32_TWI_SR_EOSACC_MASK) ) 00171 { 00172 // Disable All interrupts 00173 twi_inst1->idr = AVR32_TWI_IDR_TXRDY_MASK|AVR32_TWI_IDR_RXRDY_MASK|AVR32_TWI_IER_EOSACC_MASK; 00174 // Reenable detection slave access 00175 twi_it_mask = AVR32_TWI_IER_SVACC_MASK; 00176 twi_inst1->ier = twi_it_mask; 00177 // Signal EOF access 00178 twi_slave_fct.stop(); 00179 }else 00180 00181 if( (twi_it_mask & AVR32_TWI_IER_SVACC_MASK) 00182 && (status & AVR32_TWI_SR_SVACC_MASK ) ) 00183 { 00184 twi_inst1->idr = AVR32_TWI_IDR_SVACC_MASK; 00185 // A slave is selected, then check direction 00186 if( status & AVR32_TWI_SR_SVREAD_MASK ) 00187 { 00188 // enable flag to signal data transmition 00189 twi_it_mask = AVR32_TWI_IER_TXRDY_MASK; 00190 twi_inst1->ier = twi_it_mask; 00191 // Transmit a data to master 00192 twi_inst1->thr = twi_slave_fct.tx(); 00193 }else{ 00194 // enable flag to signal data reception 00195 twi_it_mask = AVR32_TWI_IER_RXRDY_MASK|AVR32_TWI_IER_EOSACC_MASK; 00196 twi_inst1->ier = twi_it_mask; 00197 } 00198 }else 00199 00200 // this is a RXRDY 00201 if( (twi_it_mask & AVR32_TWI_IER_RXRDY_MASK) 00202 && (status & AVR32_TWI_SR_RXRDY_MASK ) ) 00203 { 00204 // Get data from Receive Holding Register 00205 twi_slave_fct.rx( twi_inst1->rhr ); 00206 }else 00207 00208 // this is a TXRDY 00209 if( (twi_it_mask & AVR32_TWI_IER_TXRDY_MASK) 00210 && (status & AVR32_TWI_SR_TXRDY_MASK ) ) 00211 { 00212 // Byte transmited 00213 if( status & AVR32_TWI_SR_NACK_MASK ) 00214 { 00215 // Last Byte 00216 // Clear flag NACK 00217 twi_inst1->rhr; 00218 // Renable IT select slave 00219 twi_it_mask = AVR32_TWI_IER_EOSACC_MASK; 00220 twi_inst1->ier = twi_it_mask; 00221 }else{ 00222 // Transmit a data to master 00223 twi_inst1->thr = twi_slave_fct.tx(); 00224 } 00225 } 00226 return; 00227 }
volatile avr32_twi_t* twi_inst1 = &AVR32_TWI [static] |
Pointer to the instance 1 of the TWI registers for IT.
Definition at line 55 of file twi.c.
Referenced by twi_master_inst1_interrupt_handler(), twi_master_write(), twi_master_write_ex(), and twi_slave_inst1_interrupt_handler().
volatile unsigned long twi_it_mask [static] |
IT mask.
Definition at line 71 of file twi.c.
Referenced by twi_master_inst1_interrupt_handler(), twi_master_read(), twi_master_write(), twi_master_write_ex(), twi_slave_init(), and twi_slave_inst1_interrupt_handler().
volatile Bool twi_nack = FALSE [static] |
Add NACK boolean.
Definition at line 68 of file twi.c.
Referenced by twi_is_busy(), twi_master_inst1_interrupt_handler(), twi_master_read(), twi_master_write(), and twi_master_write_ex().
volatile unsigned char* volatile twi_rx_data = NULL [static] |
Pointer to the applicative TWI receive buffer.
Definition at line 60 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 65 of file twi.c.
Referenced by twi_is_busy(), twi_master_inst1_interrupt_handler(), and twi_master_read().
twi_slave_fct_t twi_slave_fct [static] |
const unsigned char* volatile twi_tx_data = NULL [static] |
Pointer to the applicative TWI transmit buffer.
Definition at line 58 of file twi.c.
Referenced by twi_master_inst1_interrupt_handler(), twi_master_write(), and twi_master_write_ex().
volatile int twi_tx_nb_bytes = 0 [static] |
Remaining number of bytes to transmit.
Definition at line 63 of file twi.c.
Referenced by twi_is_busy(), twi_master_inst1_interrupt_handler(), twi_master_write(), and twi_master_write_ex().