Skip to content

SPI master interface: erratic behaviour on first transaction, second byte in not sent/received #585

@wke67

Description

@wke67

Problem in DxCore/library/SPI.c

I have a setup where the error is reproducible and I could analyze the problem. The problem depends on the state of the SS pin, if it is configured as output evering is ok, if it is configured as input the error shows up when the input level is low. The root cause of the problem is that SPI0.CTRLA is written with SPI_ENABLE_bm before SPI.CTRLB is written with SPI_SSD_bm set. Initialization by the book would first set up all registers and as last action set the SPI_ENABLE_bm. A simple fix appears to write SPI0.CTRLB first and then SPI0.CTRLA with SPI_ENABLE_bm.

Below is the code used for debugging with Arduino IDE using DxCore 1.5.11 (insync with the github repository), the chip is an AVR64EA28. The problem was also observed with an AVR64DD28.

// chase the magical "SPI master error: on first transaction, second byte is not sent / received."

//#define NO_ERROR
//#define ERROR_DEPENDS_ON
//#define SIMPLE_FIX

#include <SPI.h>

void setup() {

volatile char data;

PORTA.DIR |= (1<<4) | (1<<6); // PA4 MOSI, PA6 SCK

#ifdef ERROR_DEPENDS_ON
PORTA.DIR |= (1<<7);
#endif

#ifdef NO_ERROR
SPI0.CTRLA = (SPI_DORD_bm&0) | SPI_MASTER_bm | SPI_PRESC_DIV4_gc;
SPI0.CTRLB = SPI_SSD_bm | SPI_MODE_0_gc;
SPI0.INTCTRL = 0;
SPI0.CTRLA |= SPI_ENABLE_bm;
#else
#ifndef SIMPLE_FIX
SPI0.CTRLA = (SPI_DORD_bm&0) | SPI_MASTER_bm | SPI_PRESC_DIV4_gc | SPI_ENABLE_bm;
SPI0.CTRLB = SPI_SSD_bm | SPI_MODE_0_gc;
SPI0.INTCTRL = 0;
SPI0.CTRLA = (SPI_DORD_bm&0) | SPI_MASTER_bm | SPI_PRESC_DIV4_gc | SPI_ENABLE_bm;
SPI0.CTRLB = SPI_SSD_bm | SPI_MODE_0_gc;
#else // simple fix
SPI0.CTRLB = SPI_SSD_bm | SPI_MODE_0_gc;
SPI0.CTRLA = (SPI_DORD_bm&0) | SPI_MASTER_bm | SPI_PRESC_DIV4_gc | SPI_ENABLE_bm;
SPI0.INTCTRL = 0;
#endif
#endif

SPI0.DATA=0x55;
while( ! (SPI0.INTFLAGS & SPI_IF_bm) );
data=SPI0.DATA;
SPI0.DATA=0x33;
while( ! (SPI0.INTFLAGS & SPI_IF_bm) );
data=SPI0.DATA;
}

void loop() {
delay(100);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions