ATTINY24 USI_OVF_vect not firing

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

Hello all!

 

I've been working on a small stepper motor controller (pic here) using an attiny24 as the micro for reading a single control byte as a SPI slave. My plan was to use the tiny's USI to implement a dead simple SPI interface. And this is the crux of the problem. For a reason I cannot fathom, the USI's 4-bit counter overflow interrupt USI_OVF_vect will never fire. I've hooked up a scope, and ensured that my clock source (connected to USCK) is indeed ticking, and I think I'm doing all the setup and config correctly per the datasheet.

 

So as a last resort, I wrote a small program to reproduce the issue. The program does nothing other toggle PA3 at startup a few times to show it's ready (leaving it high), and do the "appropriate" setup for the USI and the counter interrupt. When the interrupt fires it should set PA3 low, however it never does. Here is the demo program that exhibits the problem.

 

#define F_CPU 1000000

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <math.h>

#define USI_OUT_REG	PORTA	//!< USI port output register.
#define USI_IN_REG	PINA	//!< USI port input register.
#define USI_DIR_REG	DDRA	//!< USI port direction register.
#define USI_CLOCK_PIN	PA4	//!< USI clock I/O pin.
#define USI_DATAIN_PIN	PA6	//!< USI data input pin.
#define USI_DATAOUT_PIN	PA5	//!< USI data output pin.

#define gpio_set(port, pin, state) { \
	if (state) (port) |=  (1 << (pin)); \
	else       (port) &= ~(1 << (pin)); \
} \

ISR(USI_OVF_vect)
{

	gpio_set(PORTA, PA3, 0);
}

int main(void)
{
	// Configure port directions.
	const int spi_mode = 1;

	USI_DIR_REG |= (1<<USI_DATAOUT_PIN);                      // Outputs.
	USI_DIR_REG &= ~((1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN)); // Inputs.
	USI_OUT_REG |= (1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN);  // Pull-ups.

	USICR = (1<<USIOIE) | (1<<USIWM0) |
	        (1<<USICS1) | (spi_mode<<USICS0);

	DDRA |= (1 << PA3);

	gpio_set(PORTA, PA3, 1);
	_delay_ms(500);
	gpio_set(PORTA, PA3, 0);
	_delay_ms(500);
	gpio_set(PORTA, PA3, 1);

	sei();
	while (1) { _delay_ms(500); };

	return 0;
}

 

I'm pretty stumped with this one if you have any ideas please share!

 

Cheers

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

Welcome to AVRFreaks!

 

Thanks for the small test program, I'm sure someone will try out your example and lend a hand soon.

 

IIRC, one of the quirks of the USI vs a real SPI is the you have to manually clock the USI to get it to send the data, but it's been awhile since I messed with USI.

It almost seemed easier to bit-bang the spi. 

 

 

Jim

 

 

FF = PI > S.E.T

 

Last Edited: Tue. Jun 16, 2020 - 01:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Look for Atmel app note AVR319 for an example of using USI for SPI comms.

 

Jim

edit: here it is:

Attachment(s): 

 

FF = PI > S.E.T

 

Last Edited: Tue. Jun 16, 2020 - 01:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey Jim!

 

Thanks for the welcome and the info! Yeah, I've seen a lot of USI loathing around the internet I should have dug a bit deeper first, oh well!

 

I've kept messing with it and I was able to get the interrupt to trigger but only once I provided the tiny with a very low clock signal of 1KHz... I'm not sure what the upper bound on that is. But the Arduino I was using as a test SPI master apparently is beyond that limit. Very strange! Any ideas around those details?

 

Cheers.

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

Not off the top of my head, you should be able to clock it at least cpu/4 I would think.

Are you using it as the SPI master or slave?

 

Jim

 

 

FF = PI > S.E.T

 

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

comparing your code to app note code, I see this:

// Configure USI to 3-wire master mode with overflow interrupt.
	USICR = (1<<USIOIE) | (1<<USIWM0) |
	        (1<<USICS1) | (spi_mode<<USICS0) |
	        (1<<USICLK);

in the initmaster() function.    Could it be as simple as one bit?

Jim

 

 

FF = PI > S.E.T

 

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

I'm using the tiny as a slave so I think that part is ok.

 

Thanks!

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

Have you confirmed that the CKDIV8 (Divide clock by 8) fuse bit and  CLKPR (Clock Prescale Register) are set appropriately to produce the system clock frequency that you expect?

 

You can look at the effective system clock on PB2 if it is configured as CKOUT via the CKOUT (Clock Output Enable) fuse.

 

I am successfully running an ATtiny84A (@20MHz) USI as SPI slave with ATmega328P (@16MHz) master with either of these USICR values up to Fusck = 4 MHz (Fmaster/4):

 

    USICR = (1<<USIWM0) | (1<<USICS1) | (0<<USICS0);    // SPI mode 3 (CPOL=1, CPHA=1); USI requires normally high USCK
    USICR = (1<<USIWM0) | (1<<USICS1) | (1<<USICS0);    // SPI mode 1 (CPOL=0, CPHA=1); USI requires normally low USCK

 

But, just as a note, when I configure the master for Fusck = 8 MHz (Fmaster/2==max setting), although MOSI timing is fine, MISO update phase jitter wrt USCK is huge (13.5-54.1 ns).