Post Go back to editing

21593 - SPI problems

Hi,

is the SPI functionality of ADSP-21593 tested? ... especially the DMA mode? There is nowhere written for the start address of the accompanied DMA channels that L1 RAM can not be used. We look for an eplanation and have the caching in our suspect. Also in the anomaly list, nothing is written. Only for 2158x anomaly list at ID 20000010 there is the following written: https://www.analog.com/media/en/dsp-documentation/integrated-circuit-anomalies/ADSP-2158x_ADSP-SC58x-SHARC-Anomaly.pdf. But we can not look at all anomaly lists of all other processor, when we are working with 21593.

In the hardware manual nothing can be found. Using heap memory (L2 or L3) the DMA - SPI is working, but not reliable. Occassional, the DMA stops working, we do not have any glue why ???? in BF707 the things were running very reliable and this 24/7 and comparing BF707 SPI-manual with the one of 21593, they are nearly identical.

We need here urgent help !!!!!! 

best tb

Parents Reply Children
  • Dear Sir,

    I regret meanwhile, that I chose 21593 ! But we spent already some 100thousand euros for design. I am universitary professor at TUM and work with bf533/bf707 since years also in educating students. I checked of course the BSP package carefully and took a look at the code. THe adis are buggy and with too much of overload and there is no reasonable manuals my students can be educated. Using this, nobody understands the interface at the processor realy. So we decided as other colleges to use direct the registers at hardware manual described to program. Here no examples are given. Can you provide a code snippet. Never forget: Keep also software stupid and simple ... and do not forget the upcoming lyability issues.

    Your answer is a standard one, which does not help anything. My question was clear and I only need a simple answer. Working without cache at the moment is the only workaround, but caching is a nice and powerful feature and I will not resign totally. SPI DMA is a very reasonable way of working.

    I would really ask for an answer of my simple question, sorry if my words are too pushy.

    tb

  • Hi,

    We don’t think the SC58x Anomaly is applicable for 21593 as it is not listed in anomaly of 21593.

    Could you please provide your comments on this.

    • What is the SPI/DMA error condition that is raised when this issue occurs.
    • What is the exact range in which they are trying to write/read in L1 memory.
    • Also I don’t think there is any restriction w.r.t usage of L1 memory and more details are required on the failure.
    • Can you please provide your demo example which is failing which we can have a look and debug.
    • From your answer it looks like the examples works with cache disabled, if enbling cache is causing the issue then
    the most common mistakes are not having the buffers cache aligned and not zero padding unused cache line which are properly demonstrated in the SPI example.

    Regards,
    Anand Selvaraj.

  • Anand, Hi, which SPI example you mean, I could not find any without using adi. .... instead of direkt programming of Registers. Be aware that the overheads are too much for an effektive code with your adi...implementation, espcially when you use the unit freuquently as with the spi.

    best tb

  • Dear Anand,

    I found time to analyse a bit more:


    /*--------------------------------------------------------------------------------------------------- *
    * ---------------------------- S P I 2 ------------------------------------------------------------- *
    * ---- der SPI wird als Q-SPI betrieben und bedient den Flash und wird auf den Sytembus gelegt
    * -------------------------------------------------------------------------------------------------- */
    void CSystem593Core1::initSPI2(u16 u16vClkMhz)
    {


    *pREG_SPI2_CTL &= ~ENUM_SPI_CTL_EN; // disable SPI2

    *pREG_SPI2_DLY = 0; // sending without halt between bytes
    // flash at SSEL==1 - Bus at SSEL==2
    *pREG_SPI2_SLVSEL = ENUM_SPI_SLVSEL_SSEL2_HI | ENUM_SPI_SLVSEL_SSEL1_HI |
    ENUM_SPI_SLVSEL_SSEL2_EN | ENUM_SPI_SLVSEL_SSEL1_EN;


    *pREG_SPI2_CLK = (u16mSCLK0inMHz / u16vClkMhz) - 1;

    // Standard is mode 0: CPOL == 0 CPHA == 0 (flash works with mode0 and
    // mode 3: CPOL == 1 CPHA == 1)
    u32 u32Ctrl = ENUM_SPI_CTL_MASTER ;

    *pREG_SPI2_CTL = u32Ctrl;

    *pREG_DMA26_CFG = ENUM_DMA_CFG_READ;
    *pREG_DMA26_XMOD = 1;

    *pREG_DMA27_CFG = ENUM_DMA_CFG_WRITE | ENUM_DMA_CFG_SYNC;
    *pREG_DMA27_XMOD = 1;

    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
    // inklusive chip-Select für SPI2 - entweder Bus oder Flash
    // tbuf: pointer to transmit buf
    // rbuf: pointer to receive buf
    // ignore: num of bytes to ignore before storing to rbuf
    // count: num of bytes to send
    bool CSystem593Core1::rxtxSPI2(sSPICtrl* sCtrl)
    {

    *pREG_SPI2_STAT = 0xB0000FF0; // clear spi1 status register, all W1C bits
    *pREG_DMA26_STAT = 0x00000007; // clear dma26 status register
    *pREG_DMA27_STAT = 0x00000007; // clear dma27 status register

    // set the number of bytes to send/read, in case of Nbread > NbSend
    // dummy - bytes must be send
    // in S-SPI read and send byte number are always the same

    u16 u16Nb = sCtrl->u32NbByteSend;
    if(u16Nb < sCtrl->u32NbByteRead)
    u16Nb = sCtrl->u32NbByteRead;

    // change the Ctrl-register
    // set the mode dependent on sSPICtrl and communication partner

    // mode of SPI
    // mode 0: (CPOL==0, CPHA==0) -> default
    // mode 1: (CPOL==0, CPHA==1)
    // mode 2: (CPOL==1, CPHA==0)
    // mode 3: (CPOL==1, CPHA==1)
    u8 mode = sCtrl->u8mode & 0x03; // in case of wrong value inside
    u32 ctrl = *pREG_SPI2_CTL;
    ctrl = CBase::setbits(ctrl,5,2,mode); // set bits 5,4 with mode 0...3
    *pREG_SPI2_CTL = ctrl;

    // adjust Single oder Quad
    u8 u8Type = sCtrl->u8Type; // 0-> Standard SPI or 1-> QUAD-SPI

    // tx dma
    *pREG_DMA26_ADDRSTART = sCtrl->u8pSend; // set adress for tx-dma
    *pREG_DMA26_XCNT = u16Nb;
    // rx dma
    *pREG_DMA27_ADDRSTART = sCtrl->u8pRead; // set address for rx-dma
    *pREG_DMA27_XCNT = u16Nb;

    // -> now configure SPI2
    *pREG_SPI2_RWC = u16Nb;
    *pREG_SPI2_RXCTL = ENUM_SPI_RXCTL_RWC_EN | // read word counter enable
    ENUM_SPI_RXCTL_RTI_EN | // initiate receive
    ENUM_SPI_RXCTL_RDR_NE | // generate datarequest on fifo not empty
    ENUM_SPI_RXCTL_RX_EN; // enable rx

    *pREG_SPI2_TWC = u16Nb;
    *pREG_SPI2_TXCTL = ENUM_SPI_TXCTL_TWC_EN | // enable transfer word counter
    ENUM_SPI_TXCTL_TTI_EN | // enable tx requests to dma
    ENUM_SPI_TXCTL_TDR_NF | // enable request when fifo not full
    ENUM_SPI_TXCTL_TX_EN; // enable tx

    *pREG_SPI2_CTL |= ENUM_SPI_CTL_EN; // enable SPI2

    // now make the chip select
    // there does not exist different slots, only slaveinslot
    if(sCtrl->u8SlaveInSlot == 1) // flash
    {
    *pREG_SPI2_SLVSEL &= ~ENUM_SPI_SLVSEL_SSEL1_HI;
    *pREG_SPI2_SLVSEL &= ~ENUM_SPI_SLVSEL_SSEL1_HI;
    }
    else // Bus
    {
    *pREG_SPI2_SLVSEL &= ~ENUM_SPI_SLVSEL_SSEL2_HI;
    *pREG_SPI2_SLVSEL &= ~ENUM_SPI_SLVSEL_SSEL2_HI;
    }

    *pREG_DMA27_CFG |= ENUM_DMA_CFG_EN;
    *pREG_DMA26_CFG |= ENUM_DMA_CFG_EN;

    // start 100ms timer to abort SPI transmission if it takes too long
    bool error = false;
    cmTimerSPI2.start(100); // 100ms Watch timer
    while((!(*pREG_SPI2_STAT & ENUM_SPI_STAT_RF_HI)) && !error) // received finish indication
    error = cmTimerSPI2.getTimeOut();

    *pREG_DMA27_CFG &= ~ENUM_DMA_CFG_EN;
    *pREG_DMA26_CFG &= ~ENUM_DMA_CFG_EN;

    // deselect chip again ...
    // do it twice ... look at anomaly list
    if(sCtrl->u8SlaveInSlot == 1) // flash
    {
    *pREG_SPI2_SLVSEL |= ENUM_SPI_SLVSEL_SSEL1_HI;
    *pREG_SPI2_SLVSEL |= ENUM_SPI_SLVSEL_SSEL1_HI;
    }
    else // Bus
    {
    *pREG_SPI2_SLVSEL |= ENUM_SPI_SLVSEL_SSEL2_HI;
    *pREG_SPI2_SLVSEL |= ENUM_SPI_SLVSEL_SSEL2_HI;
    }

    *pREG_SPI2_CTL &= ~ENUM_SPI_CTL_EN; // disable SPI2
    *pREG_SPI2_TXCTL = 0; // tx off
    *pREG_SPI2_RXCTL = 0; // rx off

    // return false if SPI transmission was not successful
    if(error)
    return false;

    return true;
    }

    the DMA - SPI2 ist build like this. It should be used to serve a serial flash, very easy all. 

    I use for DMA the following data setup:

    //u8mTXBuffer

    u8mTXBuf = new u8[16];
    smSPI2Ctrl.u8pSend = u8mTXBuf;
    smSPI2Ctrl.u32NbByteSend = x;

    //u8mRXBuffer

    u8mRXBuf = new u8[16];
    smSPI2Ctrl.u8pRead = u8mRXBuf;
    smSPI2Ctrl.u32NbByteRead = x;

    If cache is disabled the code works fine and reliable with the setup above. The address of u8mTXBuf and u8mRXBuf have addresses in 0x8xxxxxxx (we use SDRAM als Heap). If cache is enabled the SPI-DMA does not work.

    If I replace u8mRXBuf with u8mRXBuffer, which is typical member with u8 u8mTXBuffer[16] in the Flash-class it does not work. The array lies normally at 0x24xxxxxx (L1 Block 0 SRAM). 

    In all cases the data are 32bit memory aligned.

    any hint?? best tb

  • Hi,

    We understand that code works fine with cache disabled and not works with cache enabled.
    1. Can you please confirm that buffers are aligned as below code sample.
    ---------------------------------------------------
    #include <sys/platform.h>

    #define ADI_CACHE_ALIGN _Pragma("align 64")

    /* Source channel data buffer.
     * Aligned at least to an MSIZE-byte boundary.
     */
    ADI_CACHE_ALIGN static uint8_t SrcDataBuf[BUF_SIZE];

    /* Destination channel data buffer.
     * Aligned at least to an MSIZE-byte boundary, and to the cache line size.
     */
    ADI_CACHE_ALIGN static uint8_t DestDataBuf[ADI_CACHE_ROUND_UP_SIZE(BUF_SIZE, uint8_t)];
    ---------------------------------------------------

    When the processor's L1 and/or L2 cache is enabled the receive data buffers must be aligned on cache line boundaries. If they are not then any data access by the core may pull a buffer into the cache while the DMA is operating on the data buffer. Both the core and the DMA are masters on the bus. The core will be performing cache operations. The DMA engine will not be. So it is important for the application to both align data that will be operated on by the DMA and to separate this data from other application data.

    ADI_CACHE_ROUND_UP_SIZE macro rounds up a given size (taken and returned in number of elements of the specified type) so that no other data can share the cache line.

    Let us know the results after aligning the buffer as above.

    2. We have driver code for communicating flash using ADSP-21593 board. We are ready to share if you are interested.

    3. If still you are facing issues, can you please share your complete baremetal project which simulate this issue. So that we can debug further.


    Regards,
    Anand Selvaraj

  • Anand, thks  and interesting ! A lot of work around must be done, to implement DMA-SPI. In BF707 it was easier to realize. 

    I was not aware that the arrays must memory aligned over 8byte than over 4Byte? This is what I did not check. Does this mean that any array used for DMA-SPI must be 8-byte memory aligned?

    I can not define each array as static uint8_t because then you have in c++-classes instead of instance member class member. c++ would not make any sense any more. Or, you have to copy huge amount of data to distinct dedicated  DMA-Buffers, because we are using different XML-strings to transfer between different components. We wonna use the buffers directly without huge copy load.

    Yes, we would be interested in the driver code ! you can also use my universitary address tb@tum.de. But we are working inside our science group not with ADI-implementation but with direct register-programming. We/i expect, that we should understand the link between hardware und firmware, especially for stuff we use permanently as the SPI-interfaces. Your ADI implementation are hardly to read.

    To where I should send my project.

    best tb 

  • Hi, Anand, thks and interesting ! In Bf707 it was much more easier to realize.

    Must be the DMA Buffers 8Byte memory aligned and the alignment must be synchronised with cache alignment?

    I am interested in driver Code ! but preferingly without ADI-implementation, because it is hardy to read, how it is implemented and be aware, never use for 24/7 code libraries you do not understand. 

    to where I should send my code.

    tb

  • Hi,

    Yes, Buffers would always be cache aligned as per the processors cache line. Please send your project to Processor Support through: processor.support@analog.com.
    Please make sure to add the link of this EZone thread while contacting private support.

    Regards,
    Anand Selvaraj.

  • Hi,

    For SHARC+ based parts the line size is 64 bytes . So, array must be aligned to the cache line size if placed in cacheable memory.

    Regards,
    Anand Selvaraj.