cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H750 receives an addition zero in RXDR register in SPI receive only mode.

onio
Senior

Hello having a bit of a problem and was wondering if anyone here could spot what I am doing wrong.

I am interfacing to an Analog device part ADE7878 using HSDC interface. The datasheet for this device can be found here http://www.autex.spb.su/ad/ADE7878.pdf

Data sent from the ADE7878 is enclosed in an active low SS/HSA signal cycle.

The problem I am experiencing is that on the first ever capture I can see that

all 16 32-bit register sent by the ADE7878 are caputured by the STM32H750

and consistent with the trace from the logic analyser.

From the second capture cycle onward the first register always reads as zero and

and then the data from the ADE registers.

Example

Cycle 1

Logic Analyser: a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p

STM32 reads: a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p

Cycle 2 (onward)

Logic Analyser: a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p

STM32 reads: 0,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o

Any suggestions on what configuration needs changing. I can find a work around

by swallowing the first capture and read the last register in the

"if ( (isr & SPI_SR_EOT ) == SPI_SR_EOT )" block but I don't find this very neat

any suggestions is well come.

Below is the code snippet of what I am doing

#define HSDC_MAX_REG 16
#define MAX_TRACE_ENTRY 100
 
extern SPI_HandleTypeDef hspi2;
 
typedef struct hsdc_registers_struct
{
   uint32_t IAWV, VAWV, IBWV, VBWV, ICWV, VCWV, INWV, AVA,
            BVA, CVA, AWATT, BWATT, CWATT, AVAR, BVAR, CVAR;
}hsdc_registers_t;
 
class HSDC;
{
public:
    int size();                         // returns the number of item in the buf
    void insert(hsdc_registers_t* src); // insert an item in the buf
    void extract(hsdc_registers_t* dst);// extracts an item from the buffer
private:
    hsdc_registers_t buf[MAX_TRACE_ENTRY];
    int rear,front,count;
}
 
 
HSDC hsdc;
 
void thread()
{
    SPI2_InterruptEnable();
 
    while (1)
    {
        if (hsdc.size())
        {            
            hsdc_registers_t hsdc_registers;
            hsdc.extract(&hsdc_registers);
            HAL_UART_Transmit(&huart3, (uint8_t*)&hsdc_registers, sizeof (hsdc_registers_t), HAL_MAX_DELAY);
        }
    }
}
 
void SPI2_InterruptEnable()
{
    MODIFY_REG(hspi2.Instance->CR2, SPI_CR2_TSIZE, HSDC_MAX_REG);
    __HAL_SPI_ENABLE(&hspi2);
    __HAL_SPI_ENABLE_IT(&hspi2, 
        (SPI_IT_EOT | SPI_IT_RXP | SPI_IT_OVR | SPI_IT_FRE | SPI_IT_MODF | SPI_IT_TSERF));
}
 
void SPI2_IRQHandler(void)
{
    static int count = 0;
    static uint32_t rxbuf[HSDC_MAX_REG];
    SPI_TypeDef* instance = hspi2.Instance;
    uint32_t isr = instance->SR;
    
    if ( (isr & SPI_SR_EOT ) == SPI_SR_EOT )
    {
        hsdc.insert((hsdc_registers_t*)rxbuf); 
        instance->IFCR |= SPI_FLAG_EOT;
        count = 0;
    }
    
    if ( (isr & SPI_SR_TXTF ) == SPI_SR_TXTF )
    {
        instance->IFCR |= SPI_FLAG_TXTF;
    }
    
    if ( (isr & SPI_SR_UDR ) == SPI_SR_UDR )
    {
        instance->IFCR |= SPI_FLAG_UDR;
    }
    
    if ( (isr & SPI_SR_OVR ) == SPI_SR_OVR )
    {
        instance->IFCR |= SPI_FLAG_OVR;
    }
    
    if ( (isr & SPI_SR_TIFRE ) == SPI_SR_TIFRE )
    {
        instance->IFCR |= SPI_FLAG_FRE;
    }
    
    if ( (isr & SPI_SR_MODF ) == SPI_SR_MODF )
    {
        instance->IFCR |= SPI_FLAG_MODF;
    }
    
    if ( (isr & SPI_SR_TSERF ) == SPI_SR_TSERF )
    {
        instance->IFCR |= SPI_FLAG_TSERF;
    }
    
    if ( (isr & SPI_SR_SUSP ) == SPI_SR_SUSP )
    {
        instance->IFCR |= SPI_FLAG_SUSP;
    }
    
    if ( (isr & SPI_SR_RXP ) == SPI_SR_RXP )
    {
        rxbuf[count++] = instance->RXDR;
    }
}

2 REPLIES 2

So, the STM32 SPI is master? Isn't that 0 from end of previous transaction? Don't you see extra SCK clocks after the end of transaction?

Rx-only in the STM32 SPI is notoriously hard to handle as it output clocks immediately after enable and won't stop until disable. I don't know whether this has changed somehow in the 'H7 and won't study it now, but the usual advice is to not use the Rx-only mode of SPI, use normal duplex where you have full control over the clocks - you don't need to bring out MOSI to a pin.

JW

onio
Senior

Hi JW,

The STM32 is not the master but operating as an SPI Slave device (Rx Only Mode). The clock to the STM32 is driven from the ADE7878 chip.

The 0 seen is not from the previous transaction as it can't be seen on the logic analyser, in fact the last 2 register data sent from the ADE is 0xFFFFFFFF.

There is a burst of 16 separate 32-bits clock generated by the ADE device and for each clock one can see the corresponding register data on the logic analyser and consequently within the STM32 receive buffer.

As mentioned in my previous post the problem seems to be something to do with the internal STM32 RXDR reading an extra zero when NSS pin goes low the second time.

Regards

onio