DMA SPI controlled SSEL signal using linked list on LPC54102

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

DMA SPI controlled SSEL signal using linked list on LPC54102

822 Views
praveenthpra
Contributor I

LPC, configured as master, is communicating using DMA and SPI to a peripheral.

Master passes a command to the slave and the slave returns some data.

I use linked list descriptors for the whole communication.

If i want to send a second command from the master, the peripheral requires a SSEL signal.

Using DMA (with linked list) and setting the peripheral registers for a new SSEL signal seems to not work

(Remark: Using DMA (with linked list) and setting the peripheral registers for "end of transfer" bit does work)

Are there any restrictions regarding controlling the SSEL signal via linked list in a DMA transfer.

Are there any other solutions to control the SSEL signal?

Labels (2)
0 Kudos
3 Replies

621 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Praveenth Pra,

Thank you for your interest in NXP Semiconductor products and 
the opportunity to serve you.
I was wondering if you can share your demo code and some screenshots of the SSEL signal.
It will help me to investigate this issue.
Have a great day,

TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

621 Views
praveenthpra
Contributor I

Hey jeremyzhou‌,

Thanks for the quick response.

These are the relevant part for the SPI and DMA

 LPC_SPI1->TXCTRL=(((SPIM_XFER_OPTION_SIZE(8) |SPIM_XFER_OPTION_EOT) <<
            16) | SPI_TXDATCTL_DEASSERT_ALL) & ~SPI_TXDATCTL_EOT;

    Chip_SPIM_AssertSSEL(LPC_SPI1, 0);

//Linked List

//Command for the slave

DMA_CHDESC_T dmaSPISTxDescArray[3] __attribute__ ((aligned(16)));
DMA_CHDESC_T dmaSPISRxDescArray[3] __attribute__ ((aligned(16)));

uint8_t command[4]={0x03,0x03,0x03,0x03};

dmaSPISTxDescArray[0].source = DMA_ADDR(command) + 4-1;
    dmaSPISTxDescArray[0].dest = DMA_ADDR(&LPC_SPI1->TXDAT);
    dmaSPISTxDescArray[0].next = DMA_ADDR(&dmaSPISTxDescArray[1]);
    dmaSPISTxDescArray[0].xfercfg = DMA_XFERCFG_CFGVALID |
            DMA_XFERCFG_SWTRIG  |
            DMA_XFERCFG_RELOAD|
            DMA_XFERCFG_WIDTH_8 | DMA_XFERCFG_SRCINC_1 |
            DMA_XFERCFG_DSTINC_0 | DMA_XFERCFG_XFERCOUNT(4);

    dmaSPISRxDescArray[0].source = DMA_ADDR(&LPC_SPI1->RXDAT);
    dmaSPISRxDescArray[0].dest = DMA_ADDR(command) + 4-1;
    dmaSPISRxDescArray[0].next =  DMA_ADDR(&dmaSPISRxDescArray[1]);
    dmaSPISRxDescArray[0].xfercfg = DMA_XFERCFG_CFGVALID |
            DMA_XFERCFG_SWTRIG  |
            DMA_XFERCFG_RELOAD|
            DMA_XFERCFG_WIDTH_8 | DMA_XFERCFG_DSTINC_1 |

            DMA_XFERCFG_SRCINC_0 | DMA_XFERCFG_XFERCOUNT(4);

uint32_t deassertSSel = LPC_SPI1->TXCTRL | SPI_TXDATCTL_DEASSERTNUM_SSEL(0);

dmaSPISTxDescArray[1].source = DMA_ADDR(&deassertSSel);
    dmaSPISTxDescArray[1].dest = DMA_ADDR(&LPC_SPI1->TXDATCTL);
    dmaSPISTxDescArray[1].next = DMA_ADDR(&dmaSPISTxDescArray[2]);
    dmaSPISTxDescArray[1].xfercfg = DMA_XFERCFG_CFGVALID |
            DMA_XFERCFG_SWTRIG   |
            DMA_XFERCFG_RELOAD|
            DMA_XFERCFG_WIDTH_32 | DMA_XFERCFG_SRCINC_0 |
            DMA_XFERCFG_DSTINC_0 |
            DMA_XFERCFG_XFERCOUNT(1);

    dmaSPISRxDescArray[1].source = DMA_ADDR(&LPC_SPI1->TXDATCTL);
    dmaSPISRxDescArray[1].dest = DMA_ADDR(&deassertSSel);
    dmaSPISRxDescArray[1].next = DMA_ADDR(&dmaSPISRxDescArray[2]);
    dmaSPISRxDescArray[1].xfercfg = DMA_XFERCFG_CFGVALID |
            DMA_XFERCFG_SWTRIG  | //DMA_XFERCFG_SETINTA |
            DMA_XFERCFG_RELOAD|
            DMA_XFERCFG_WIDTH_32| DMA_XFERCFG_DSTINC_0 |
            DMA_XFERCFG_SRCINC_0 |
            DMA_XFERCFG_XFERCOUNT(1);

uint32_t assertSSEL = (((SPIM_XFER_OPTION_SIZE(8) |SPIM_XFER_OPTION_EOT) <<
            16) | SPI_TXDATCTL_DEASSERT_ALL) & ~SPI_TXDATCTL_EOT;
   assertSSEL =    assertSSEL & (SPI_TXDATCTL_CTRLMASK & ~SPI_TXDATCTL_DEASSERTNUM_SSEL(0));

    dmaSPISTxDescArray[2].source = DMA_ADDR(&assertSSEL);
    dmaSPISTxDescArray[2].dest =  DMA_ADDR(&LPC_SPI1->TXCTRL);
    dmaSPISTxDescArray[2].next =  DMA_ADDR(&dmaSPISTxDescArray[3]);
    dmaSPISTxDescArray[2].xfercfg = DMA_XFERCFG_CFGVALID |
            DMA_XFERCFG_SWTRIG  |
            DMA_XFERCFG_RELOAD|
            DMA_XFERCFG_WIDTH_32 | DMA_XFERCFG_SRCINC_0 |
            DMA_XFERCFG_DSTINC_0 |
            DMA_XFERCFG_XFERCOUNT(1);

    dmaSPISRxDescArray[2].source = DMA_ADDR(&LPC_SPI1->TXCTRL);
    dmaSPISRxDescArray[2].dest = DMA_ADDR(&assertSSEL);
    dmaSPISRxDescArray[2].next =  DMA_ADDR(&dmaSPISRxDescArray[3]);
    dmaSPISRxDescArray[2].xfercfg = DMA_XFERCFG_CFGVALID |
            DMA_XFERCFG_SWTRIG  |
            DMA_XFERCFG_RELOAD|
            DMA_XFERCFG_WIDTH_32| DMA_XFERCFG_DSTINC_0 |
            DMA_XFERCFG_SRCINC_0 |
            DMA_XFERCFG_XFERCOUNT(1);

   

    dmaSPISTxDescArray[3].source = DMA_ADDR(command) + 4-1;
    dmaSPISTxDescArray[3].dest = DMA_ADDR(&LPC_SPI1->TXDAT);
    dmaSPISTxDescArray[3].next = 0;
    dmaSPISTxDescArray[3].xfercfg = DMA_XFERCFG_CFGVALID |
            DMA_XFERCFG_SWTRIG  |
            DMA_XFERCFG_WIDTH_8 | DMA_XFERCFG_SRCINC_1 |
            DMA_XFERCFG_DSTINC_0 | DMA_XFERCFG_XFERCOUNT(4);

    dmaSPISRxDescArray[countOfDescriptors+1].source = DMA_ADDR(&LPC_SPI1->RXDAT);
    dmaSPISRxDescArray[countOfDescriptors+1].dest = DMA_ADDR(command) + 4-1;
    dmaSPISRxDescArray[countOfDescriptors+1].next =  0;
    dmaSPISRxDescArray[countOfDescriptors+1].xfercfg = DMA_XFERCFG_CFGVALID |
            DMA_XFERCFG_SWTRIG  | DMA_XFERCFG_SETINTA |
            DMA_XFERCFG_WIDTH_8 | DMA_XFERCFG_DSTINC_1 |
            DMA_XFERCFG_SRCINC_0 | DMA_XFERCFG_XFERCOUNT(4);


    dmaClearChannel(APP_SPI_DMA_TXCH);
    dmaClearChannel(APP_SPI_DMA_RXCH);

    Chip_SPI_FlushFifos(LPC_SPI1);


    /* DMA interrupt */
    NVIC_EnableIRQ(DMA_IRQn);

    while (!Chip_DMA_SetupTranChannel(LPC_DMA, APP_SPI_DMA_RXCH, &dmaSPISRxDescArray[0]));
    Chip_DMA_SetupChannelTransfer(LPC_DMA, APP_SPI_DMA_RXCH, dmaSPISRxDescArray[0].xfercfg);
    Chip_DMA_EnableChannel(LPC_DMA, APP_SPI_DMA_RXCH);
    Chip_DMA_SetValidChannel(LPC_DMA, APP_SPI_DMA_RXCH);

    while (!Chip_DMA_SetupTranChannel(LPC_DMA, APP_SPI_DMA_TXCH, &dmaSPISTxDescArray[0]));
    Chip_DMA_SetupChannelTransfer(LPC_DMA, APP_SPI_DMA_TXCH, dmaSPISTxDescArray[0].xfercfg);
    Chip_DMA_EnableChannel(LPC_DMA, APP_SPI_DMA_TXCH);
    Chip_DMA_SetValidChannel(LPC_DMA, APP_SPI_DMA_TXCH);

I saw that modifiying the registers for asserting the chip select does not have an impact, unless the SPI is disabled and enabled again, but this "destroys" the connection to the DMA

0 Kudos

621 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Praveenth Pra,

Thanks for your reply.

I still have one point that need you to clarify.

In my opinion, the SSEL will keep active automatically before the end-of-transfer.

I also didn't find the kind of operation to set the SSEL signal active in the periph_spis_dma demo in the LPCOpen libarary.

Have a great day,
TIC

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos