SPI with DMA problem in PSoC 4

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Cosmin_Dobrescu
Level 1
Level 1
5 sign-ins First reply posted First question asked

Hello everyone,

I am developing at a very low level communication between the PSOC-4 and a SD card via SPI protocol. In this whole process I'm at the point where I need to transfer 514 bytes per SPI to the SD card (MOSI).

The concept is very simple but I have a lot of problems with increasing the data rate of the SPI block. The whole setup works fine below 1.5 Mbps, but when increasing to 4Mbps with oversampling at 16 (3Mbps real) the DMA transfer stops working properly. I have tried to narrow down the problem as much as possible and it seems that the problem is in the behaviour of the DMA block.

To rule out that there is no problem with the SPI block I have increased to 8Mbps data rate and used the CPU to communicate with the card and everything has been successful. I would like to remind you that at lower speeds of 1 and 1.5 Mbps everything works fine with the DMA. At first I have worked with these low frequencies to be able to analyse the communication with a logic analyser. My idea was, that once everything works fine, to simply increase to the maximum speed.

In order not to go into too much detail I can reduce the problem to a simple SPI transfer with DMA (forgetting that the communication is with an SD). I simply need to transmit 514 bytes of data over the MOSI line at over 3 Mbps.

The information flow is simple, once everything is ready, the DMA descriptor is validated and the channel is enabled to start the transfer to the FIFO register of the SPI module. The problem is that in the interrupt function that is indicated to the DMA it jumps with an error. The error produced is obtained with TxDMA_GetDescriptorStatus(0);. The normal behaviour is that the DMA generates an interrupt with that flag to CYDMA_DONE. Instead it generates two interrupts with the flag to CYDMA_INVALID_DESCR.


The weirdest thing is that it works at low data rates and doesn't work at high data rates. I think I'm missing something and I don't understand what.

The part of the code that involves this problem is first of all the initialisation:

 

struct DataPacket{
//    char token;
    char data[512];
    char CRC[2];
}__attribute__((packed));

struct DataPacket multipleWriteBuffer;


int main()
{
TxDMA_Start((void *)&multipleWriteBuffer, (void *)SPI_TX_FIFO_WR_PTR);
TxDMA_SetInterruptCallback(TxDMA_Done_interrupt);
CyIntEnable(CYDMA_INTR_NUMBER);
CyGlobalIntEnable;
.....................

The function to be triggered by the DMA interrupt is:

void TxDMA_Done_interrupt()
{
    descriptorStatus=TxDMA_GetDescriptorStatus(0);
    descriptorStatus=descriptorStatus & 0x00070000U;
    switch(descriptorStatus){
        case CYDMA_DONE:
        {
              DMAFlags=1;
        }; break;
....................................
        case CYDMA_INVALID_DESCR:
        {
            DebugPin_Write(0);
            InvalidDescriptor++;
            DebugPin_Write(1);
        }; break;
    }
}

when I need the to start data transfer:

        TxDMA_ValidateDescriptor(0);
        TxDMA_ChEnable();

The DMA descriptor configuration is:

Cosmin_Dobrescu_0-1618073241696.png

The SPI advanced tap configuration is :

Cosmin_Dobrescu_1-1618073257150.png

And less relevant to the case is the spi basic tab:

Cosmin_Dobrescu_2-1618073269018.png

Conection between SPI and DMA module:

Cosmin_Dobrescu_3-1618073292673.png

I think including an image of the logic analyzer may help to notice when the InvalidDescriptor event occurs. Remember that I have a debug pin that throws a pulse when this event occurs so I can detect it in the logic analyzer.

General view of the transmission, without zoom:

Cosmin_Dobrescu_4-1618073305558.png

A zoom in on the area where these events occur:

Cosmin_Dobrescu_5-1618073317026.png

 

In summary: every time I start a transfer, the interrupt with the CYDMA_INVALID_DESCR error is raised.

Do you have any idea what is going on?
Thank you for your help.

0 Likes
3 Replies
Ekta_N
Moderator
Moderator
Moderator
750 replies posted First like given 250 solutions authored

Hello @Cosmin_Dobrescu 

You have mentioned that  you "can reduce the problem to a simple SPI transfer with DMA (forgetting that the communication is with an SD). I simply need to transmit 514 bytes of data over the MOSI line at over 3 Mbps"

Would it be possible for you to attach the project here so that we can reproduce the issue at our end?

The PSoC 4 DMA datasheet mentions that "Each DMA channel has two descriptors. While one descriptor is running, the other can be updated by the CPU during run time. This allows for the creation of “extra” descriptors via firmware. The hardware makes this easier by providing a mechanism that optionally invalidates a descriptor when it is complete. While the descriptor is invalid, the CPU can update it.

Exercise care to ensure that the firmware updates the descriptor before it is triggered. The
amount of time required for this will be application dependent; specifically, how quickly will the
descriptor be re-triggered after it has finished. You must determine this time and the time it takes
to update the descriptor. If the DMA engine triggers an invalid descriptor, it will not run it and will
disable that channel. You can determine this has occurred by reading the descriptor status"

I guess this is what is happening in your case, thus increasing the data rate causes the DMA to be triggered before it is  updated by the firmware.

Thanks and Regards

Ekta

0 Likes
lock attach
Attachments are accessible only for community members.
Cosmin_Dobrescu
Level 1
Level 1
5 sign-ins First reply posted First question asked

Hello Ekta,
Thank you very much for your reply.
I have prepared an example isolating the problem as much as possible.As you can see the SPI is at 3Mbps real.

With this configuration if you enable the channel and the descriptor two interrupts are thrown with the CYDMA_INVALID_DESCR error (explained in the main post).

If the speed is lowered, a CYDMA_DONE interrupt and another with a CYDMA_INVALID_DESCR error are thrown (both in a row).

As you can see in the example, the descriptor data is not modified. Therefore the descriptor should not have problems in that aspect, as you mention.
Best regards, Cosmin.

0 Likes
Cosmin_Dobrescu
Level 1
Level 1
5 sign-ins First reply posted First question asked

I think this behaviour is a bug.
Normally it would have to trigger the DMA_DONE interrupt and then Invalid CYDMA_INVALID_DESCR.
One of the possibilities I am considering is that the system changes the status register very fast. And when the interrupt function trigger, it reads the value of the second interrupt. This is a serious problem as I have noticed that the DMA does not always work properly. There are times when it simply throws a CYDMA_INVALID_DESCR. The behaviour of the DMA is very erratic, I haven't figured out why, but there is certainly a problem.
They probably need to store multiple descriptor states or improve the documentation on this issue. DMA is a fundamental system in any system on chip.

0 Likes