Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
7 years ago

Need helpl with DMA

Hi everyone, i need help with using DMA in bare-metal project.

I have GHRD, and i need to transfer data (it just 0 to 127 count) from HPS RAM(as i understand from ftp://ftp.altera.com/up/pub/intel_material/16.1/tutorials/accessing_hps_devices_from_fpga.pdf , its address 0xffff0000) to FPGA OCRAM(its address 0xc0000000 in my system) using HPS DMA and then i show this data from FPGA OCRAM on LEDS(0xFF210040).

But something goes wrong, and when i show data on leds, i see only 0-3 ,but it must be 0-1-2-3-4-..127. And leds are blinks(i see 0-0-1-0-2-0-3), so i think it is zeros between 0 and 1, 1 and 2, 2 and 3,...

When i show on leds data direct from hps ram after initializing it, leds dont blink(i see 0-1-2-3-...-127)

I really dont understand why that happens and i spend 3 days , but i still dont know what i do wrong.

Please someone, help me to understand and fix it.

firstly, i setup dma:

ALT_STATUS_CODE socfpga_dma_setup(){
    printf("INFO: Setup DMA System ...\n");
    ALT_STATUS_CODE status = ALT_E_SUCCESS;
    if (status == ALT_E_SUCCESS)
    {
        // Configure everything as defaults.
        ALT_DMA_CFG_t dma_config;
        dma_config.manager_sec = ALT_DMA_SECURITY_DEFAULT;
        for (int i = 0; i < 8; ++i)
        {
            dma_config.irq_sec = ALT_DMA_SECURITY_DEFAULT;
        }
        for (int i = 0; i < 32; ++i)
        {
            dma_config.periph_sec = ALT_DMA_SECURITY_DEFAULT;
        }
        for (int i = 0; i < 4; ++i)
        {
            dma_config.periph_mux = ALT_DMA_PERIPH_MUX_DEFAULT;
        }
        status = alt_dma_init(&dma_config);
        if (status != ALT_E_SUCCESS)
        {
            printf("ERROR: alt_dma_init() failed.\n");
        }
    }
    // Allocate the DMA channel
    if (status == ALT_E_SUCCESS)
    {
        status = alt_dma_channel_alloc_any(&channel);
        if (status != ALT_E_SUCCESS)
        {
            printf("ERROR: alt_dma_channel_alloc_any() failed.\n");
        }
        else
        {
            printf("INFO: Channel %d allocated.\n", (int)(channel));
        }
    }
    // Verify channel state
    if (status == ALT_E_SUCCESS)
    {
        ALT_DMA_CHANNEL_STATE_t state;
        status = alt_dma_channel_state_get(channel, &state);
        if (status == ALT_E_SUCCESS)
        {
            if (state != ALT_DMA_CHANNEL_STATE_STOPPED)
            {
                printf("ERROR: Bad initial channel state.\n");
                status = ALT_E_ERROR;
            }
        }
    }
    if (status == ALT_E_SUCCESS)
    {
        status = alt_dma_program_init(&program);
        if (status != ALT_E_SUCCESS)
        {
            printf("ERROR: alt_dma_program_init() failed.\n");
        }
        else
        {
            printf("INFO: Dma program_byffer initialized.\n");
        }
    }
    if (status == ALT_E_SUCCESS)
    {
        printf("INFO: Setup of DMA successful.\n\n");
    }
    else
    {
        printf("ERROR: Setup of DMA return non-SUCCESS %d.\n\n", (int)status);
    }
    return status;
}

then goes my main fuction:

ALT_STATUS_CODE dma_hpsram_to_fpgaram(){
    // Just base addresses of GHRD components
    const uint32_t ALT_LWFPGA_BASE         = 0xFF200000;
    const uint32_t ALT_LWFPGA_LED_OFFSET   = 0x00010040;
    const uint32_t ALT_H2F_BASE                = 0xc0000000;
    const uint32_t ALT_H2F_OCRAM_OFFSET       = 0x00000000;
    const uint32_t ALT_HPS_OCRAM              = 0xffff0000;
    // turn off leds
    alt_write_word(ALT_LWFPGA_BASE + ALT_LWFPGA_LED_OFFSET, 0);
    uint32_t temp=0;
    uint32_t offset=0;
    // write 0-127 to hps ram
    for (uint32_t i = 0; i < 128; ++i)
    {
        alt_write_byte(ALT_HPS_OCRAM+offset,temp);
        temp++;
        offset=offset+1;
    }
    // transfer data from hps ram to fpga ocram
    size_t size=128;
    uint32_t dst=ALT_H2F_BASE+ALT_H2F_OCRAM_OFFSET;
    uint32_t src=ALT_HPS_OCRAM;
    // this function i take from altera design examples (hps dma)
    dma_memory_to_memory(&src, &dst, size);
    // check result of transfer, looking at fpga ocram contents
    offset=0;
        for (uint32_t i = 0; i < 12800000; ++i)
        {
            if(i%100000==0)
            {
                // that big numbers for making leds switch less often
                alt_write_byte(ALT_LWFPGA_BASE+ALT_LWFPGA_LED_OFFSET, alt_read_byte(dst+offset));
                offset=offset+1;
            }
    }
    return ALT_E_SUCCESS;
}

it uses function from altera design examples( hps ram):

ALT_STATUS_CODE dma_memory_to_memory(void * src, void * dst, uint32_t size)
{
    ALT_STATUS_CODE status = ALT_E_SUCCESS;
    printf("INFO: Demo DMA memory to memory transfer.\n");
    // Copy source buffer over destination buffer
    if(status == ALT_E_SUCCESS)
    {
        status = alt_dma_memory_to_memory(channel, &program, dst, src, size, false, (ALT_DMA_EVENT_t)0);
    }
    // Wait for transfer to complete
    if (status == ALT_E_SUCCESS)
    {
        printf("INFO: Waiting for DMA transfer to complete.\n");
        ALT_DMA_CHANNEL_STATE_t channel_state = ALT_DMA_CHANNEL_STATE_EXECUTING;
        while((status == ALT_E_SUCCESS) && (channel_state != ALT_DMA_CHANNEL_STATE_STOPPED))
        {
            status = alt_dma_channel_state_get(channel, &channel_state);
            if(channel_state == ALT_DMA_CHANNEL_STATE_FAULTING)
            {
                ALT_DMA_CHANNEL_FAULT_t fault;
                 alt_dma_channel_fault_status_get(channel, &fault);
                 printf("ERROR: DMA CHannel Fault: %d\n", (int)fault);
                 status = ALT_E_ERROR;
            }
        }
    }
    return status;
}
No RepliesBe the first to reply