ATTiny44 I2C/USI + Timer 0 TIMSK0 usage conflict

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've been making good headway on my custom ATTiny44-based RGB/vibe/piezo feedback control chip, thanks to some help from guys here, Dean's tutorials on timers, and *gasp* actually reading through the datasheet, which turned out to be the most helpful of all. Amazing.

But I am running into a problem that I can't seem to figure out despite all of this. I cannot enable OCIE0A (TIM0_COMPA_vect) and still have the I2C communication work. If I leave that interrupt disabled, I2C works perfectly. If it's enabled, then everything else works, but I can't communicate with the chip.

First, my code is available here:

https://github.com/jrowberg/keyglove/blob/master/module_code/kgm_feedback/kgm_feedback.c#L229
(jumps straight to perpetrating line)

I have commented out the interrupt enable for debugging purposes, but I'm using Timer0 for the foundational 100us tick that runs all the time to sync everything up.

The I2C/USI bus is being run as a slave, and from what I can tell (and based on the USI settings in the accompanying usiTwiSlave.c, also on GitHub there), using Timer0 should not create a conflict. I haven't found anything in the datasheet to this effect either. Obviously something is not playing nice though.

Any pointers?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Timer0 should not interfere with the USI.

OTOH, your ISR() looks as if it could take a LOT of cycles to execute in the worst case. This could make your I2C slave look very unresponsive. I2C is supposed to just wait, but some Masters might timeout.

I would calculate the worst case. If necessary, just set a flag in the ISR(TIM0_COMPA) and let the foreground code do the complex loop. As a general rule, you put slow code in the foreground and have tight ISR()s.

No, I have not inspected your USI code.
As a slave your USI I2C will take its clock from the Master's SCL line. i.e. it should not use Timer0.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't see anything obvious. However, one possible workaround is to move the ISR code into the main loop. Leave OCIE0A unset. Put the following inside the big for loop somewhere:

  if (TIFR0 & _BV(OCF0A)) {
    TIFR0 = _BV(OCF0A);
    // copy the code from your ISR here
  }

It'll remove the possibility of race conditions between the ISR code and the main loop. But if the main loop takes more than about 100us, there's a possibility you'll miss a timer tick.

- S

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
Timer0 should not interfere with the USI.

OTOH, your ISR() looks as if it could take a LOT of cycles to execute in the worst case. This could make your I2C slave look very unresponsive. I2C is supposed to just wait, but some Masters might timeout.

Thanks for the info (also thanks mnehpets for your recommendation). I ran another test where the interrupt was enabled but there was no code inside the ISR, and I2C once again worked perfectly. So it definitely was a "CPU too busy" sort of problem.

I ultimately decided to simplify the heck out of the whole code base, turning it into a much tighter module that is capable only of basic on/off settings, piezo frequency control, and PWM for the RGB leds. I cut out all of the optional blink/fade/pulse mode support, since the host device controlling it can take care of those without much effort. The module works perfectly now, and I know some more about timers and USI/TWI!

I call that a success.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can do complex and time consuming work in the Slave. Just run it in the foreground.

The Slave functionality is all handled by swift interrupts.

Especially something that a human sees. She will not notice if a fade does not start for 20ms.
However a computer will be upset if the Slave does not ACK its commands within 10-20us.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Curious, can I take a look at your "usiTwiSlave.h" code as well? I am trying to configure my ATtiny44 as a slave and am in desperate need of C examples. Hopefully I could leverage as much as possible from your code base....if you'd be so kind.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MrShmoe wrote:
Curious, can I take a look at your "usiTwiSlave.h" code as well? I am trying to configure my ATtiny44 as a slave and am in desperate need of C examples. Hopefully I could leverage as much as possible from your code base....if you'd be so kind.

Absolutely (especially considering that I didn't write most of the usiTwiSlave.* files). Everything in the project is available here:

https://github.com/jrowberg/keyglove/tree/master/module_code/kgm_feedback

There are a few files that might be of interest to you there. You're more than welcome to use any of the code that you can.