16 or 32 bit DMA writes won't work with shift register

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

cross mob
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Hi All,

   

I cannot transfer anything more than single byte burst DMA to the shift register component . I've read and re-read data sheets, app notes, and just can't find anything I am doing wrong. I've used the same setup successfully with the SPI master (the code is adapted from the SPI Master example project) and it works fine transferring 16 bits at a time . I can do 16 or 32 bit word transfers to the shift register component fine using the API function.

   

The address of the register being written to is 0x40006544, which is 32 bit word aligned, so it does not seem to be an alignment problem.

   

I'm not sure if there is something being done wrong, or I might have stumbled onto a defect. If someone would look at this, it would be greatly appreciated. I've got this design running on a PSoC 5 CY8CKIT-050 development board, the crystal has been replaced with a 14.318MHz crystal, you might need to change the clock settings back to 24/48MHz.

   

Project archive is attached, relevant C code is also copied below.

   

Thanks for looking

   

Stephen


#define DMA_TX_M_BYTES_PER_BURST       (2u)
#define DMA_TX_M_REQUEST_PER_BURST     (1u)
#define DMA_TX_M_SRC_BASE              (CYDEV_SRAM_BASE)
#define DMA_TX_M_DST_BASE              (CYDEV_PERIPH_BASE)

/* Variable declarations for DMA_Tx_M */
uint8 M_TxChannel;
uint8 M_TxTD[2u];

/* Data to be transmitted by Tx */
uint16 m_txBuffer [8u] = {0x8001u, 0x8001u, 0x8001u, 0x8001u, 0x8001u, 0x8001u, 0x8001u, 0x8001u };


int main (void)
{
    uint32 i;
   
       
    // Write 16 bit data to shift register FIFO
    for (i=0; i < ShiftReg_1_FIFO_SIZE; i++)
    {
        ShiftReg_1_WriteData(0x0000u);
    }

    Dma_Configuration();
    CyDmaChEnable(M_TxChannel, 1u);
    Pwm1_Start();
    ShiftReg_1_Start();
   
    while(1)
    {
    }
}

   
void Dma_Configuration()
{
   
    // Init DMA, 2 byte bursts, each burst requires a request
    M_TxChannel = DMA_TX_M_DmaInitialize(DMA_TX_M_BYTES_PER_BURST, DMA_TX_M_REQUEST_PER_BURST,
                                         HI16(DMA_TX_M_SRC_BASE), HI16(DMA_TX_M_DST_BASE));

    M_TxTD[0u] = CyDmaTdAllocate();
    M_TxTD[1u] = CyDmaTdAllocate();

    // Configure this Td chain as follows:
    // - The TD is looping on itself
    // - Increment the source address, but not the destination address  
    CyDmaTdSetConfiguration(M_TxTD[0u], 16u, M_TxTD[1u], TD_INC_SRC_ADR ); //
    CyDmaTdSetConfiguration(M_TxTD[1u], 1u, M_TxTD[1u], 0u);
       
    // address for 32 bit wide reg:  ShiftReg_1_bSR_sC32_BShiftRegDp_u0__F0_REG
    // Address for 16 bit wide reg:  ShiftReg_1_bSR_sC16_BShiftRegDp_u0__F0_REG
    // Address for 8  bit wide reg:  ShiftReg_1_bSR_sC8_BShiftRegDp_u0__F0_REG
   
    CyDmaTdSetAddress(M_TxTD[0u], LO16((uint32)m_txBuffer),    LO16((uint32)ShiftReg_1_bSR_sC16_BShiftRegDp_u0__F0_REG ));
    CyDmaTdSetAddress(M_TxTD[1u], LO16((uint32)m_txBuffer), LO16((uint32)m_txBuffer));
   
    // Associate the TD with the channel
    CyDmaChSetInitialTd(M_TxChannel, M_TxTD[0u]);
}   

   


0 Likes
2 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Welcome in the forum!

   

You are using two quite different TDs chained together, why not using a single TD in a loop. When the first TD finished transferring 16 Bytes in two byte chunks, the second TD takes over transferring 1(!!) byte (which is an error!!) in an infinite loop.

   

Better is to loop on the first TD only.

   

You can pick the destination definition from the Shiftreg_1.h file, they are not as cryptic as in cyfitter.h, so you can use

   

    CyDmaTdSetConfiguration(M_TxTD[0u], 16u, M_TxTD[0u], TD_INC_SRC_ADR );

   

    CyDmaTdSetAddress(M_TxTD[0u], LO16((uint32)m_txBuffer), LO16((uint32)ShiftReg_1_IN_FIFO_VAL_LSB_PTR ));
 

   

Bob

0 Likes
Anonymous
Not applicable

Hi Bob,

   

 

   

Thanks for the response.  I tried removing the second TD entirely, as you sugguest, but still no go.  It appears that only one byte is getting transferred (I am looking at the serial output of the shift register). If I disable DMA and fill the FIFO with 0x8001, I get both pulses with the correct spacing.

   

 

   

It would be great to get this working, as I have a neat single chip video application that I would like to share.  It is working with NTSC, but I also want it to display 640x480 VGA, and I need the 16 or 32 bit transfers with the shift register to get it to work.

   

 

   

Thanks

   

Stephen

0 Likes