| Author |
Message |
|
|
Posted: Jun 02, 2012 - 04:37 PM |
|

Joined: Oct 06, 2008
Posts: 70
|
|
| I am testing a board I made for the AT32UC3A0512. Some of it works fine. I can program it via JTAG. But I am having a problem with the TWI. It initializes but hangs when writing and reading. I have 10K pullups on the lines. I used that value because that is what is on the EVK1100 schematic. Any idea what the problem might be? |
|
|
| |
|
|
|
|
|
Posted: Jun 02, 2012 - 04:54 PM |
|


Joined: Dec 06, 2007
Posts: 2512
Location: Redmond, WA USA
|
|
|
blackson wrote:
Any idea what the problem might be?
I lent my crystal ball to a guy named Samperi.
You will definitely get a better answer if you show the code and the schematic.  |
_________________ Larry
Those afraid to embrace the future will quickly fade into the past. - larryvc
|
| |
|
|
|
|
|
Posted: Jun 02, 2012 - 05:12 PM |
|

Joined: Oct 06, 2008
Posts: 70
|
|
| Okay. Here are main.c, the schematics, and the board. I am afraid the schematic is a little ugly. |
|
|
| |
|
|
|
|
|
Posted: Jun 06, 2012 - 01:17 PM |
|

Joined: Oct 06, 2008
Posts: 70
|
|
| I think I might have found the problem. I use twi_master_read to do single byte reads. The data sheet says that "when a single data byte read is performed, with or without internal address (IADR), the START and STOP bits must be set at the same time." (Page 226; see also the flowcharts on 232 and 232.) But the code for twi_master_read seems to assume the read will always be for multiple bytes:
Code:
// Enable master transfer
twi->cr = AVR32_TWI_CR_MSEN_MASK;
// Send start condition
twi->cr = AVR32_TWI_START_MASK;
// only one byte to receive
if(twi_rx_nb_bytes == 1)
{
// set stop bit
twi->cr = AVR32_TWI_STOP_MASK;
}
// mask NACK and RXRDY interrupts
twi_it_mask = AVR32_TWI_IER_NACK_MASK | AVR32_TWI_IER_RXRDY_MASK;
// update IMR through IER
twi->ier = twi_it_mask;
// get data
while( twi_is_busy() ) {
cpu_relax();
}
Am I right about twi_master_read, that it can't do a single byte read? If so, is there some other function in the TWI module I should use? I didn't see one. |
|
|
| |
|
|
|
|
|
Posted: Jun 06, 2012 - 03:33 PM |
|

Joined: Feb 12, 2005
Posts: 16314
Location: Wormshill, England
|
|
|
Quote:
int twi_master_read ( volatile avr32_twi_t * twi,
const twi_package_t * package
)
You set up the twi_package_t structure accordingly.
Quote:
uint8_t addr [3]
TWI address/commands to issue to the other chip (node).
int addr_length
Length of the TWI data address segment (1-3 bytes).
void * buffer
Where to find the data to be written.
char chip
TWI chip address to communicate with.
unsigned int length
How many bytes do we want to write.
So if you want to read one byte "at current address", you would have
Code:
twi_package_t package = { NULL, 0, &ch, SLAVE, 1};
Now I have never used ASF nor AVR32. So this is speculation on my part. Note that you don't even say what hardware chip you are using. So I have no idea whether you need to set up the "current read address".
No, I have not bothered to read the ASF source code. I would just follow the documented API and see how it behaves.
David. |
|
|
| |
|
|
|
|
|
Posted: Jun 06, 2012 - 10:55 PM |
|

Joined: Oct 06, 2008
Posts: 70
|
|
| Thanks for the suggestion. I will do some experimenting. I just have not had time yet, and I thought there must be people who have used the TWI module in the ASF to do single byte reads. Also, the chip I am using is the AT32UC3A0512, which I mentioned in the first post. |
|
|
| |
|
|
|
|
|
Posted: Jul 17, 2012 - 12:52 PM |
|

Joined: Oct 20, 2011
Posts: 23
|
|
Having similar TWI problems here. The MCU is UC3C1512, we are trying to use TWIM0 and ASF.
The problem with unmodified ASF is that it freezes after a slave device sends ACK. We have tried to remove all software wait loops from ASF source that leave the controller to sleep mode, but the problem seems to be that although the ASF code is interrupt driven, the TWI master interrupt never actually gets called. We have checked the bus with digital scope and it seems that if no slave or a slave with wrong address is on the line (thus no ACK after ADRS byte), the code finishes normally, but if we get the ACK byte from slave, the interrupt never gets to the point of sending data, leaving SCK low and the MCU freezes.
We also have another problem: We have several other interrupt requests working simultaneously and thus would need a NON-interrupt driven TWI code (it is the main thing the MCU is doing at the moment, and can handle other short interrupts if needed). However, It is not immediately obvious from datasheet if this is even possible (should be, at least in 8-bit AVRs this works just fine by software-polling flags). We tried to write our own code, making it much simpler than the ASF example (ASF has poor documentation, it uses a lot of complicated data types to do it's job and seems to only work if and only if it is the only code running on the AVR). We can't get our code to work however, although we tried to follow the datasheet instructions. Is there any ready code for this? We basically only need to send one byte per slave to a TWI bus, but the complicated ASF code doesn't seem to work for our purpose. |
|
|
| |
|
|
|
|
|
Posted: Apr 18, 2013 - 04:27 PM |
|

Joined: Feb 14, 2008
Posts: 51
Location: Buenos Aires
|
|
Hi, I have the same problem, and fix it changing the loop that wait for a queue of FreeRtos.
Read function:
Code:
#ifdef FREERTOS_USED
int twi_master_read(volatile avr32_twi_t *twi,
const twi_package_t *package, uint32_t timeout )
#else
int twi_master_read(volatile avr32_twi_t *twi,
const twi_package_t *package )
#endif
{
// check argument
if (package->length == 0) {
return TWI_INVALID_ARGUMENT;
}
#ifdef FREERTOS_USED
if( twi_wait_while_busy( timeout ) == TWI_TIMEOUT )
{
return TWI_TIMEOUT;
}
#else
while (twi_is_busy()) {
cpu_relax();
};
#endif
twi_nack = false;
twi_busy = true;
// set read mode, slave address and 3 internal address byte length
twi->mmr = (package->chip << AVR32_TWI_MMR_DADR_OFFSET) |
((package->addr_length << AVR32_TWI_MMR_IADRSZ_OFFSET) & AVR32_TWI_MMR_IADRSZ_MASK) |
(1 << AVR32_TWI_MMR_MREAD_OFFSET);
// Set pointer to TWIM instance for IT
twi_inst = twi;
// set internal address for remote chip
twi->iadr = twi_mk_addr(package->addr, package->addr_length);
// get a pointer to applicative data
twi_rx_data = package->buffer;
// get a copy of nb bytes to read
twi_rx_nb_bytes = package->length;
// Enable master transfer
twi->cr = AVR32_TWI_CR_MSEN_MASK;
// Send start condition
twi->cr = AVR32_TWI_START_MASK;
// only one byte to receive
if (twi_rx_nb_bytes == 1) {
// set stop bit
twi->cr = AVR32_TWI_STOP_MASK;
}
// mask NACK and RXRDY interrupts
twi_it_mask = AVR32_TWI_IER_NACK_MASK | AVR32_TWI_IER_RXRDY_MASK;
// update IMR through IER
twi->ier = twi_it_mask;
#ifdef FREERTOS_USED
if( twi_wait_while_busy( timeout ) == TWI_TIMEOUT )
{
// Disable master transfer
twi->cr = AVR32_TWI_CR_MSDIS_MASK;
return TWI_TIMEOUT;
}
#else
// get data
while (twi_is_busy()) {
cpu_relax();
}
#endif
// Disable master transfer
twi->cr = AVR32_TWI_CR_MSDIS_MASK;
if (twi_nack) {
return TWI_RECEIVE_NACK;
}
return TWI_SUCCESS;
}
Wait function:
Code:
#ifdef FREERTOS_USED
static int twi_wait_while_busy( uint32_t timeout )
{
int ret_val = TWI_SUCCESS;
uint8_t data;
if( twi_is_busy() )
{
if( pdTRUE == xQueueReceive( twi_queue, &data, timeout ) )
{
if( twi_is_busy() )
{
ret_val = TWI_BUSY;
}
}
else
{
ret_val = TWI_TIMEOUT;
}
}
return ret_val; ;
}
#endif
Irq Service Routine:
Code:
#ifdef FREERTOS_USED
//! Semaphore for wait complete.
static xQueueHandle twi_queue = 0;
static int twi_wait_while_busy( uint32_t timeout );
#endif
#define CONF_TWI_IRQ_LINE AVR32_TWI_IRQ
#define CONF_TWI_IRQ_GROUP AVR32_TWI_IRQ_GROUP
#ifdef FREERTOS_USED
__attribute__((__noinline__)) static portBASE_TYPE twi_master_interrupt_non_naked_behaviour( void );
__attribute__((naked)) void twi_master_interrupt_handler( void )
{
/**
* This ISR can cause a context switch, so the first statement must be a
* call to the portENTER_SWITCHING_ISR() macro. This must be BEFORE any
* variable declarations.
*/
portENTER_SWITCHING_ISR();
twi_master_interrupt_non_naked_behaviour();
portEXIT_SWITCHING_ISR();
}
#endif
/*! \brief TWI interrupt handler.
*/
#ifndef FREERTOS_USED
ISR(twi_master_interrupt_handler, CONF_TWI_IRQ_GROUP, CONF_TWI_IRQ_LEVEL)
{
#else
__attribute__((__noinline__))
static portBASE_TYPE twi_master_interrupt_non_naked_behaviour( void )
{
uint32_t new_cmd = 0;
portBASE_TYPE higher_prioritytask_woken = pdFALSE;
#endif
// get masked status register value
int status = twi_inst->sr & twi_it_mask;
// this is a NACK
if (status & AVR32_TWI_SR_NACK_MASK) {
goto nack;
}
// this is a RXRDY
else if (status & AVR32_TWI_SR_RXRDY_MASK) {
// get data from Receive Holding Register
*twi_rx_data = twi_inst->rhr;
twi_rx_data++;
// last byte to receive
if (--twi_rx_nb_bytes == 1) {
// set stop bit
twi_inst->cr = AVR32_TWI_STOP_MASK;
}
// receive complete
if (twi_rx_nb_bytes == 0) {
// finish the receive operation
goto complete;
}
}
// this is a TXRDY
else if (status & AVR32_TWI_SR_TXRDY_MASK) {
// decrease transmitted bytes number
twi_tx_nb_bytes--;
// no more bytes to transmit
if (twi_tx_nb_bytes <= 0) {
// enable TXCOMP IT and unmask all others IT
twi_it_mask = AVR32_TWI_IER_TXCOMP_MASK;
twi_inst->idr = ~0UL;
twi_inst->ier = twi_it_mask;
} else {
// put the byte in the Transmit Holding Register
twi_inst->thr = *twi_tx_data++;
}
}
// this is a TXCOMP
else if (status & AVR32_TWI_SR_TXCOMP_MASK) {
// finish the transmit operation
goto complete;
}
#ifdef FREERTOS_USED
return higher_prioritytask_woken;
#else
return;
#endif
nack:
twi_nack = true;
complete:
// disable all interrupts
twi_inst->idr = ~0UL;
twi_inst->sr;
twi_busy = false;
#ifdef FREERTOS_USED
/**
* Because FreeRTOS is not supposed to run with nested interrupts,
* put all OS calls in a critical section when are made in a IRQ.
*/
portENTER_CRITICAL();
xQueueSendFromISR( twi_queue,
&new_cmd,
&higher_prioritytask_woken );
portEXIT_CRITICAL();
/**
* The return value will be used by portEXIT_SWITCHING_ISR()
* to know if it should perform a vTaskSwitchContext().
*/
return higher_prioritytask_woken;
#else
return;
#endif
}
|
|
|
| |
|
|
|
|
|