-
Notifications
You must be signed in to change notification settings - Fork 369
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TWI: TWCR and TWSR inconsistencies #453
Comments
I'm currently working around this issue using the following mitigation: diff --git a/simavr/sim/avr_twi.c b/simavr/sim/avr_twi.c
index 521c03c..649b635 100644
--- a/simavr/sim/avr_twi.c
+++ b/simavr/sim/avr_twi.c
@@ -319,7 +319,7 @@ avr_twi_write(
if (p->peer_addr & 1) { // read ?
p->state |= TWI_COND_READ; // always allow read to start with
- _avr_twi_delay_state(p, 9,
+ _avr_twi_delay_state(p, 0,
p->state & TWI_COND_ACK ?
TWI_MRX_ADR_ACK : TWI_MRX_ADR_NACK);
} else {
@@ -328,7 +328,7 @@ avr_twi_write(
p->state & TWI_COND_ACK ?
TWI_MTX_ADR_ACK : TWI_MTX_ADR_NACK);
}else{
- _avr_twi_delay_state(p, 9,
+ _avr_twi_delay_state(p, 0,
p->state & TWI_COND_ACK ?
This forces TWSR to be accurate as soon as TWINT is cleared (set to 1) in TWCR, so the non-interrupt-based TWI implementation in my original comment above works as expected. What is the purpose of the 9 TWI cycle delay for these updates? Are there integrations that depend on this? |
I'm not sure why is this, but I don't think I would have made a convoluted timer like this without a good reason; possibly the older AVRs have that issue and I used an old, "common" AVR as a reference? |
Thanks for taking a look. Is it possible that simavr's twi module is only designed to work with firmware that uses an interrupt-driven twi integration? It seems incorrect that TWINT is cleared before updating TWSR, but this would make sense if the simulator assumes that the firmware won't react to this until TWI_IRQ_STATUS is raised. The 9-cycle delay would in that case make sense as a simulated delay for receipt of the full 9-bit address packet on the TWI bus. In any case, do you have a suggestion for how I should proceed with resolving this? I have some options assuming the above assumption is correct:
I'd appreciate any opinions! |
Just spent the last few hours debugging this same issue. Using poll-based TWI handling, like so. As stated above, My option was to maintain a fork for now, since I am not using interrupt-driven TWI and this is the quickest option forward, as the others by @taylorconor seem to be large refactors. But according to most of the (newer?) AVR datasheets I can find, it appears the correct behavior would be to set it immediately. I am fairly new to AVRs in general, but it still seems like even if interrupt-driven, the status would be updated before TWINT cleared, given that:
I am wondering if a counter-example exists that suggest the reason for a delayed set? However, if there is one, it seems incorrect based on the AVR list simavr supports and is not correct for the vast majority of chips. /* Wait for TWINT flag to set */
while (!(TWCR & (1 << TWINT)))
;
if (TW_STATUS != TW_MT_DATA_ACK) { // Oh no, TW_STATUS is not updated yet
return TW_STATUS;
} |
HI!
I'm doing a read transaction using poll-based acking (as opposed to TWIE) on an atmega32u4. The MCU's datasheet (section 20.5.5) states:
Code that uses the megax TWI modules in this way inspect the TWSR immediately after TWINT is cleared, e.g.:
However when running within simavr, TWINT is immediately asserted, without the corresponding TWSR flags. The TWSR flags are updated after a number of clock cycles, so this can be mitigated with busylooping within the AVR code. This is obviously not a workable solution, and is inconsistent with the description of the TWSR from the MCU's datasheet.
This is possibly related to #137. Is this a simavr issue, or have I misunderstood the simulated TWI integration?
The text was updated successfully, but these errors were encountered: