# SPI not working on ATtiny441

I've been tearing out my hair for a while on this. I'm just trying to do a basic SPI transaction -- sending one byte -- on the ATtiny441 but I'm getting nothing on the SCK and MOSI lines. First, here are my fuse settings and pinout (in red): Probably the most useful information here is that I'm using the 8MHz internal oscillator, and not dividing by 8. Note that I'm remapping the SPI pins so that I can leave my logic analyzer on while programming with the default pins.

Here's my main.c file:

#define F_CPU 8000000UL

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

#define SCK         3
#define MOSI        1
#define CSN         2

uint8_t data = 0;
uint8_t reg = 0;

int main(void)
{
PRR = 0; // turn off power reduction
REMAP |= (1<<SPIMAP); // remap SPI pins
// set SCK, MOSI, CSN as outputs:
DDRA = (1<<SCK) | (1<<MOSI) | (1<<CSN);
// enable SPI, set as master, use f_clkIO/16 (500kHz):
SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0);
reg = SPSR;
reg = SPDR;

while(1)
{
PORTA &= ~(1 << CSN); // clear CSN
SPDR = data++; // send byte
while( !(SPSR & (1<<SPIF)) ); // wait for flag to set
PORTA |= (1 << CSN); // set CSN
_delay_ms(10);
}

return 0;
}


I'm reading the SPSR and SPDR registers before the while loop at the recommendation of Atmel's AVR151 app note (page 11).

When I run the code the CSN line stays low, along with SCK and MOSI, suggesting that it's getting stuck in the while( !(SPSR & (1<<SPIF)) ); section waiting for the SPIF to set. When I comment out this line, the CSN line goes low for ~25us then back high, which is expected. I tried manually setting the outputs high on SCK and MOSI, too, to make sure it's not a pin connection problem and they worked fine.

Question: Does anyone see the error in my ways? I feel like there's one small, stupid error somewhere.

Edit: I also want to mention that I tried it with and without the clock divider (by 8) fuse bit set, and with and without remapping the SPI pins from the default location (i.e. programming, removing programming leads, attaching logic probe leads).

• Unfortunately, I do not see any obvious bug in your code. But some suggestion for testing: check if SPI module is activated and takes over the pins at all -- either different SPI mode with high idle clock, or set pin high before enabling SPI and check it goes down. Checking compiled code is a good idea too (it is short enough to disassemble and check "by hand"), maybe some strange/buggy optimization or error in your headers for ex.? Btw. I assume you see no activity on data and clk lines neither with while line commented out, right? – Martin Oct 20 '17 at 12:24
• @Martin I was afraid of that, but thanks for the good troubleshooting advice! I'll certainly try those. And that's correct -- there's no activity on SCK or MOSI with that while line commented out. – calcium3000 Oct 20 '17 at 14:32
• @Martin Figured it out! Check out my answer if you're interested. Thanks again! – calcium3000 Oct 22 '17 at 1:29

Eureka! Turns out the SPIMAP bit is incorrectly mapped!

/usr/local/CrossPack-AVR-20131216/avr/include/avr/iotn441.h:377:0: note: this is the
location of the previous definition
#define SPIMAP 0
^


(It should be bit 1.) Therefore, the line remapping the SPI pins was failing! This is corrected by placing a #define SPIMAP 1 in the #define section.

EDIT: As Martin pointed out, I am indeed using an old version of avr-libc. I was using the latest version of CrossPack, which is dated back almost 4 years from today. The newest version has this bug fixed.

• Good you have solved it. Just FYI this bug does not seem to be present in (at least) more recent libraries from Atmel, namely version 3.6.0 from late 2016 is fine (distribute.atmel.no/tools/opensource/Atmel-AVR-GNU-Toolchain/…). The date string in this output you have copied here is bit strange anyway, as according to the Atmel's changelog support for ATtiny441 was added only as late as 2016. So it is maybe worth to consider updating headers and libs before you get stuck with other strange bug ...? – Martin Oct 22 '17 at 10:02