5 Replies Latest reply on Dec 10, 2015 6:45 AM by helic_263931

    DMA does not work as intended unless I enable address incrementing



      I am working on a project with indexed DMA, where I simulate a simple ROM chip with my Cy8CKIT-059. For that purpose I use two DMA channels with one TD each. The first channel (SetupRead) reads the requested 16-bit memory address from two UDB status registers and copies it into the source address field of the TD of the second channel (Read). When it is done, it triggers the second channel which reads a single byte from flash at the indicated address and outputs it to a UDB control register connected to the data bus pins.


      I managed to get it working, but the final stumbling block was entirely unexpected: I had to configure the TD of the first DMA channel to increment the source and destination addresses, otherwise it would write the first source byte into both destination bytes. In other words, the DMA behaves as if it was misaligned.


      However, the DMA is moving 2 bytes from 0x40006464 (where I pinned the two UDB status registers) to 0x40007bfc (the source address for the TD of the second channel). Both of these addresses are dword-aligned, so I don't understand why the DMA is behaving this way, and I didn't find the reason in the documentation either. AN84810 explains that this happens for unaligned transfers, but this cannot be the reason here.


      The only hint I found so far is in this presentation, which says on page 52:


      DMA between peripherals on same spoke limited to 1-byte burst length


      This is consistent with what I see, but I don't find where this is explained in an actual AN or datasheet. In fact AN52705 seems to suggest otherwise when it says:


      Limit burst count for intra spoke DMA transfers to less than or equal to 16


      Does anyone have a better idea what is actually going on here?

        • 1. Re: DMA does not work as intended unless I enable address incrementing

          DMA configuration data is on a different spoke than the UDB registers (which are used for control registers). DMA config is in the PHUB local spoke (spoke 1), UDBs are in spokes 6 and 7 (see the PSoC5LP architecture TRM, page 56ff). So you get a inter-spoke-transfer. (The presentation you are referring to is about the PSoC5 which might be different)


          Can you share your project so we can have a look at the actual DMA configuration?

          • 2. Re: DMA does not work as intended unless I enable address incrementing

            I reduced the project down to the essentials required to reproduce the behaviour. The DMA is now CPU triggered for simplicity and transfers to an SRAM location, but the result is the same.


            If I change the DMA source address to SRAM or Flash memory, everything works as expected.

            • 3. Re: DMA does not work as intended unless I enable address incrementing

              I don't see a direct reason why it shouldn't work. Maybe you should create a support case for that.


              But you could try to set a burst size of 1 bytes, and set request_per_burst to 0. That way the first TD should also transfer 2 bytes in one go.


              There is also an interesting comment in the DMA component DS regarding the INC_SRC_ADDRESS: 'It should also be used for bursts larger than the spoke width.' So maybe this is the actually defined behavior?

              • 4. Re: DMA does not work as intended unless I enable address incrementing

                It is the behaviour mentioned for misaligned transfers, and for transfers larger than the spoke size, none of which applies here. This is what confused me.


                However, I managed to figure this out now by reading around in the PSoC5LP TRM. It appears that the peripherals connected to a spoke can have narrower (or even wider) data width than the spoke width, and the UDB registers at the address I used are only connected with a width of 8 bits. They are mapped again elsewhere though for 16-bit access, which allows you to read any two registers from "neighboring" UDBs in one go.


                The generated sources also contain definitions for these alternative addresses, but only in the cyfitter.h, not the component-specific header, so they are not as visible. In my case, I simply have to use MapAddrLow_sts_sts_reg__16BIT_STATUS_REG as source address, and the DMA works perfectly with 16 bits of transfer width. Hooray for saving one cycle :)

                • 5. Re: DMA does not work as intended unless I enable address incrementing

                  UDB registers can have different widths, depending on how you configure the UDBs (you can combine multiple UDBs for larger registers). But this should not matter for the transfer, since the DMA should handle this automatically (at least the TRM indicates so).