Send a 32bit register value to datapath with DMA

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

cross mob
TaYu_4314136
Level 1
Level 1

My environment is CY8CKIT-059 PSoC 5LP Prototyping Kit and PSoC Creator 4.2 on Windows 10.

I want to send a 32bit value from CPU(C lang) to Datapath.

First of all, I created a sending program(OneDrive) by interrupt and it works(See sreg_out.cysym in an archived file).

And I tryed to make this program correspond to DMA, but it is not successful currently.

dma.png

#include "project.h"

const uint32_t patterns[] = {
    0b11111111000000001111111100000000,
    0b11110000111100001111000011110000,
    0b11001100110011001100110011001100,
    0b10101010101010101010101010101010,  

    0b11001100110011001100110011001100,
    0b11110000111100001111000011110000,
};

uint8_t send_buffer[2][24];

/* Defines for sreg_dma */
#define sreg_dma_BYTES_PER_BURST 4
#define sreg_dma_REQUEST_PER_BURST 1
#define sreg_dma_SRC_BASE (CYDEV_SRAM_BASE)
#define sreg_dma_DST_BASE (CYDEV_PERIPH_BASE)

/* Variable declarations for sreg_dma */
/* Move these variable declarations to the top of the function */
uint8 sreg_dma_Chan;
uint8 sreg_dma_TD[2];

void InitDma()
{
    /* DMA Configuration for sreg_dma */
    sreg_dma_Chan = sreg_dma_DmaInitialize(sreg_dma_BYTES_PER_BURST, sreg_dma_REQUEST_PER_BURST,
        HI16(sreg_dma_SRC_BASE), HI16(sreg_dma_DST_BASE));
    sreg_dma_TD[0] = CyDmaTdAllocate();
    sreg_dma_TD[1] = CyDmaTdAllocate();
    CyDmaTdSetConfiguration(sreg_dma_TD[0], 24, sreg_dma_TD[1], sreg_dma__TD_TERMOUT_EN | CY_DMA_TD_INC_SRC_ADR);
    CyDmaTdSetConfiguration(sreg_dma_TD[1], 24, sreg_dma_TD[0], sreg_dma__TD_TERMOUT_EN | CY_DMA_TD_INC_SRC_ADR);
    CyDmaTdSetAddress(sreg_dma_TD[0], LO16((uint32)send_buffer[0]), LO16((uint32)sreg_out_DMA_PTR));
    CyDmaTdSetAddress(sreg_dma_TD[1], LO16((uint32)send_buffer[1]), LO16((uint32)sreg_out_DMA_PTR));
    CyDmaChSetInitialTd(sreg_dma_Chan, sreg_dma_TD[0]);
    CyDmaChEnable(sreg_dma_Chan, 1);
}

CY_ISR(OnInterruptSO)
{
}

int main(void)
{
    CyGlobalIntEnable;
   
    memcpy(send_buffer[0], patterns, 24);
    memcpy(send_buffer[1], patterns, 24);

    InitDma();
    //so_isr_StartEx(OnInterruptSO);

    for(;;)
    {
    }
}

According to this discussion, PSoC 5LP seems that it supports 32bit DMA transferring. However, I don't make much progress because there is no concrete exsamples(Official documents detailed that 8bit DMA transfer).

Please tell me if you know a good solution.

0 Likes
1 Solution

Today, I have tried the DMA transfer in 32-bit.  As the conclusion, UDB cannot be used for 32-bit access but 16-bit DMA is available.  So, I recommend to support 16-bit patterns.

I have modified your Verilog code as follows.

reg [2:0] pg_state;

wire [3:0] so_32;

reg [4:0] out_count;

wire [3:0] f0_empty;

wire [3:0] f0_not_full;

so_32, f0_empty, and f0_not_full are declared as wire signals because these signals are used as the output of the datapath.

always @(posedge clock)

begin

    case(pg_state)

    PG_IDLE:

    begin

        if(f0_empty == 4'b0000)

        begin

            pg_state <= PG_COPY_F0;

        end

    end

    PG_COPY_F0:

    begin

        out_count <= 5'd0;

        pg_state <= PG_SHIFTOUT;

    end

    PG_SHIFTOUT:

    begin

        out_count <= out_count + 5'd1;

        if(out_count == 5'd31)

        begin

            pg_state <= PG_IDLE;

        end

    end

    endcase

end

In the always clause, non-blocking assignments are used for reg elements.  As the result, the out_count register is compared with 5'd31 instead of 5'd0.

In line 06, the state transition condition is modified to (f0_empty == 4'b0000) This means all FIFO has data at least one byte each.

assign isr = (f0_not_full == 4'b1111);

assign data = so_32[3];

The isr signal is made from f0_not_full.  This logic means all FIFO has a room at least one byte.  When f0_empty is used here, the logic means all FIFO has no data.  FIFO cannot be used FIFO.

Regards,

Noriaki

View solution in original post

0 Likes
6 Replies
NoriTan
Employee
Employee
25 sign-ins 5 questions asked 10 sign-ins

In the sreg_out.h file,

#ifndef __`$INSTANCE_NAME`_H__

#define __`$INSTANCE_NAME`_H__

#define `$INSTANCE_NAME`_DMA_PTR ((reg32*)`$INSTANCE_NAME`_dp_u3__F0_REG)

#define `$INSTANCE_NAME`_SetValue(v) CY_SET_REG32(`$INSTANCE_NAME`_dp_u0__F0_REG, v)

#endif

Why are you using `$INSTANCE_NAME`_dp_u3__F0_REG instead of `$INSTANCE_NAME`_dp_u0__F0_REG ?

If you want to access the F0 register as a 32-bit register, the lower address (u0) should be used.

Regards,

Noriaki

0 Likes

Thank you for the reply.

Original code was "u0__F0_REG". But with this code, the signal will stop. Therefore, I specified an incorrect value further.

I fixed this code and update an archive file(It has not worked yet).

0 Likes

I don't know if UDB can be used for 32-bit DMA transfer because UDBs are connected to the PHUB with 16-bit spoke.

GS004141.png

This table is contained in the "PSoC 5LP Architecture TRM, Document No. 001-78426"  If UDB cannot be accessed by a 32-bit DMA, two 16-bit DMAs should be issued and the sreg_out component is triggered by the second access.

I found a strange description in the Verilog file.

}))dp(

    /*  input              */  .clk(clock),

    /*  input   [02:00]    */  .cs_addr(pg_state),

    /*  input              */  .route_si(1'b0),

    /*  input              */  .route_ci(1'b0),

    /*  input              */  .f0_load(1'b0),

    /*  input              */  .f1_load(1'b0),

    /*  input              */  .d0_load(1'b0),

    /*  input              */  .d1_load(1'b0),

    /*  output  [03:00]    */  .f0_bus_stat(f0_not_empty),

    /*  output  [03:00]    */  .f0_blk_stat(f0_full),

    /*  output  [03:00]    */  .f1_bus_stat(),

    /*  output  [03:00]    */  .f1_blk_stat(),

    /* output [03:00] */            .so(so_32)

);

At the port list of the "dp" instance, the 4-bit bus f0_bus_stat[3:0] is assigned to f0_not_empty but the f0_not_empty is not declared as a bus.  In this case, only the LSB bit f0_bus_stat[0] is assigned to f0_not_empty and is used in the state machine.  If 32-bit access is divided into two 16-bit accesses, f0_bus_stat[3] could be used by the state machine.

Regards,

Noriaki

0 Likes
NoriTan
Employee
Employee
25 sign-ins 5 questions asked 10 sign-ins

I found a strange point.  All figures come from the "PSoC 5LP Architecture TRM, Document No. 001-78426"

    `SC_A0_SRC_ACC, `SC_SHIFT_SL, 1'h0,

    1'h0, `SC_FIFO1_BUS, `SC_FIFO0_BUS,

    `SC_MSB_DSBL, `SC_MSB_BIT0, `SC_MSB_NOCHN,

    `SC_FB_NOCHN, `SC_CMP1_NOCHN,

    `SC_CMP0_NOCHN, /*CFG15-14:   */

You are setting the F0_INSEL to BUS.  This means you are using the FIFO0 in "Input Mode"

GS004145.png

GS004146.png

If the FIFO0 is used as "Input Mode" the status bits f0_bus_stat and f0_blk_stat are used as "Not Full" and "Empty" respectively.

GS004147.png

So, if you want to detect that the FIFO0 has at least one data, f0_blk_stat should be used as f0_empty

Regards,

Noriaki

0 Likes

I upload a latest version here.

According to the data presented by you, PSoC DMA may not support 32bit. If there is no further progress, I'll try to implement this function with 8bit DMA transfer. Thanks.

0 Likes

Today, I have tried the DMA transfer in 32-bit.  As the conclusion, UDB cannot be used for 32-bit access but 16-bit DMA is available.  So, I recommend to support 16-bit patterns.

I have modified your Verilog code as follows.

reg [2:0] pg_state;

wire [3:0] so_32;

reg [4:0] out_count;

wire [3:0] f0_empty;

wire [3:0] f0_not_full;

so_32, f0_empty, and f0_not_full are declared as wire signals because these signals are used as the output of the datapath.

always @(posedge clock)

begin

    case(pg_state)

    PG_IDLE:

    begin

        if(f0_empty == 4'b0000)

        begin

            pg_state <= PG_COPY_F0;

        end

    end

    PG_COPY_F0:

    begin

        out_count <= 5'd0;

        pg_state <= PG_SHIFTOUT;

    end

    PG_SHIFTOUT:

    begin

        out_count <= out_count + 5'd1;

        if(out_count == 5'd31)

        begin

            pg_state <= PG_IDLE;

        end

    end

    endcase

end

In the always clause, non-blocking assignments are used for reg elements.  As the result, the out_count register is compared with 5'd31 instead of 5'd0.

In line 06, the state transition condition is modified to (f0_empty == 4'b0000) This means all FIFO has data at least one byte each.

assign isr = (f0_not_full == 4'b1111);

assign data = so_32[3];

The isr signal is made from f0_not_full.  This logic means all FIFO has a room at least one byte.  When f0_empty is used here, the logic means all FIFO has no data.  FIFO cannot be used FIFO.

Regards,

Noriaki

0 Likes