Forum Discussion

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

why o why don't I get an interrupt when SGDMA engine completes a descriptor or chain

background:

I am using Quartus 9.1 SP2.

On a Arria GX Dev Board (EP1AGX60DF780C6)

I am writing a 32bit driver for Windows XP using WDF.

I am using Legacy Interrupts and not MSI (because XP doesn't support MSI).

I am programming the registers directly i.e. no HAL, from my Windows driver.

I have been using the Simple DMA engine, and been able to get an interrupt generated when the DMA Transaction has completed sucessfully (i.e. Done).

I had to hack one of the sopc generated .v files like this (as described in an application note) as follows:

pcie_compiler_0_rx_interface_irq = dma_0_control_port_slave_irq;

to get the interrupt to be generated properly.

I was also setting the IRQ bit in the PCIe compiler configuration space (...the 0x50 offset).

new requirements:

NOW.....I want to use the SGDMA (Scatter Gather) engine, so I got rid of the simple engine, and put on the SGDMA with memory to memory, and the default settings.

I hooked up to the DDR2 memory, and PCIE compiler, etc.

I do a Transaction and see the DescriptorCompleted / ChainCompleted bits set in the Status Register, however, I don't get any interrupt generated/received by my ISR.

I have set the control bits to say generate an Interrupt when a Chain or Descriptor is completed.

I have also tried hacking the SOPC .v file in a similar way to what was needed on the Simple DMA (though the wires are different now):

When using the default IRQ priority assignments given by SOPC.

assign pcie_compiler_0_Rx_Interface_irq = sgdma_0_csr_irq_from_sa;

IF I change the interrupt priority on the connection going from the csr_irq (Interrupt Sender) to the pcie compilers RxmIRQ (Interrupt Receiver) to 0 (the highest) then in the generated .v the name of the wire is called sgdma_0_csr_irq instead.

So I then tried:

assign pcie_compiler_0_Rx_Interface_irq = sgdma_0_csr_irq;

In all cases I still don't get the interrupt generated.....so I am looking for some creative ideas :)

8 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Are you certain that you have created the linked-list descriptor chain correctly since if there is a problem there then the SGDMA might go into the weeds and never complete. Also in case you didn't notice, the SGDMA slave port places the status register at byte offset 0 and the control register at byte offset 16. So perhaps you were communicating with the control register assuming it was at offset 4 (i.e. maybe the interrupt mask wasn't enabled).

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I do see the ChainCompleted/DescriptorCompleted being set to 1, thus it did claim to have done something....however I need to have an interrupt prompt me.....I can't do polling.

    I have the status register at BYTE offset 0, control register at BYTE offset 16, and NextDescriptorPointer at BYTE offset 32 (as I noticed in the docs that it said the offsets were 32bit word offsets ... thus use 4 x the offset value)

    descriptor.Source = I set this to an Avalon Device Address where my DDR2 memory is

    descriptor.Destination = pcieaddresstranslated;

    descriptor.ActualBytesTransferred = 0;

    descriptor.BytesToTransfer = SgList->Elements[i].Length;

    descriptor.Control.OwnedByHardware = 1;

    descriptor.NextDescriptor = NULL;

    dmaControl1.bits.MaxDescriptorsToProcess = 1;

    dmaControl1.bits.InterruptOnChainCompleted = 1;

    dmaControl1.bits.InterruptOnDescriptorCompleted = 1;

    dmaControl1.bits.Run = 1;

    At this stage I am providing just 1 descriptor to the SGDMA engine.

    I put the descriptor into device memory using a WRITE_REGISTER call, and I set the SGRegisterMap->NextDescriptorPointer to the avalon address to find it.

    I use this as I want to see 1 descriptor being processed (before I makes things more complicated), and I want to be informed when it's done something.

    pciaddresstranslated is a PCIe Host address, where I want to transfer to. It is correctly masked with the Page Size of the Translation table, and combined with the Index number of the table entry I want to translate. I have Address Translation working properly with the Simple DMA.

    I just need to see the interrupt on the SGDMA.

    thanks for your help.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    thanks,

    I'm a noob when it comes to Altera.

    Can you point me to some easy instructions on how I could add that Modular DMA into SOPC Builder as a component so that I can add one into the diagram....I couldn't figure out if it involved New Component, or some other mechanism.

    Also will it work on the Arria GX ? or just for the Cyclone III or Stratix.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    They are components that show up in the component listing once they are part of the IP search path. There is an /ip directory in that file, if you copy that directory to your hardware project then the cores will appear in SOPC Builder the next time you open the tool.

    They can target any Altera FPGA. For what you are doing you would want memory to memory transfers so you would configure the cores similar to what is used in the design example. Conceptually this mSGDMA is similar to the non-SGDMA you started your project with except it buffers multiple descriptors internally.

    It doesn't support descriptor pre-fetching so in order to get that functionality you would need some sort of intelligent block to sit in front of the dispatcher (buffer) block to handle descriptor fetching. There are many ways to implement this, for example I would use a Nios II 'e' core to perform descriptor fetching, or a state machine, or a microcode sequencer, etc...
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    sorry to be late :) But it seems you forget to set the Global Interrupt Enable bit in your SGDMA control register, that's why no interrupts are generated...

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    thanks :). I tried that flag and it enables the interrupt to be received.

    But now I have another problem....I only get 1 of the descriptors being processed. After an interrupt when I check the descriptors to see the result, only the 1st one shows an ActualBytesTransferred with something in it (i.e. 0xFFFF)....the others stay at 0, and also have no errors or anything in their control flags.

    In my SOPC, the SGDMA is set to enable burst transfers, read burst width 8, Data Width 8, memory to memory, enable bursting on descriptor read master set to = off.

    I have 32MB of DDR2 memory at avalon base 0x8000000.

    I logically divide it into 4 x 8MB regions.

    I use the 1st 16KB of the region to keep hold of the set of SGDMA descriptors, and after that is the actual data that I want to transfer out into PC Host memory.

    I am setting up a chain of descriptors which each have a bytes to transfer of 0xFFFF (have also tried 0xF000 in case of alignment issues? i.e. needs to be 32bit aligned for instance).

    I have the hardwareowner flag set on those 10 descriptos to = 1, and I have a final descriptor with an owner flag of = 0, so 11 descriptors in total.

    The first descriptor points to the next descriptor using avalon base addresses e.g. first descriptor is at 0x8000000, next one is at 0x8000020, etc...and I put the 0x8000020in the next descriptor field of the 1st descriptor, etc.

    The destination address is a PCIe address which has been correctly masked off. I see the actual data that was in the Avalon DDR buffer received in the Host memory correctly....all 0xFFFF bytes of it.

    I put the descriptors in avalon memory using WRITE_REGISTER_BUFFER_UCHAR calls. The size of my descriptor struct is 32bytes (and is packed properly).

    When I receive the interrupt and check the status flag it says ChainCompleted.

    So I am stuck on how to get it to actually do work with the other descriptors!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    thanks . I tried that flag and it enables the interrupt to be received.

    --- Quote End ---

    --> Actually it enables the sgdma to GENERATE the interrupt. The CPU was always able to receive it...

    --- Quote Start ---

    But now I have another problem....I only get 1 of the descriptors being processed. After an interrupt when I check the descriptors to see the result, only the 1st one shows an ActualBytesTransferred with something in it (i.e. 0xFFFF)....the others stay at 0, and also have no errors or anything in their control flags.

    In my SOPC, the SGDMA is set to enable burst transfers, read burst width 8, Data Width 8, memory to memory, enable bursting on descriptor read master set to = off.

    I have 32MB of DDR2 memory at avalon base 0x8000000.

    I logically divide it into 4 x 8MB regions.

    I use the 1st 16KB of the region to keep hold of the set of SGDMA descriptors, and after that is the actual data that I want to transfer out into PC Host memory.

    I am setting up a chain of descriptors which each have a bytes to transfer of 0xFFFF (have also tried 0xF000 in case of alignment issues? i.e. needs to be 32bit aligned for instance).

    I have the hardwareowner flag set on those 10 descriptos to = 1, and I have a final descriptor with an owner flag of = 0, so 11 descriptors in total.

    The first descriptor points to the next descriptor using avalon base addresses e.g. first descriptor is at 0x8000000, next one is at 0x8000020, etc...and I put the 0x8000020in the next descriptor field of the 1st descriptor, etc.

    The destination address is a PCIe address which has been correctly masked off. I see the actual data that was in the Avalon DDR buffer received in the Host memory correctly....all 0xFFFF bytes of it.

    I put the descriptors in avalon memory using WRITE_REGISTER_BUFFER_UCHAR calls. The size of my descriptor struct is 32bytes (and is packed properly).

    When I receive the interrupt and check the status flag it says ChainCompleted.

    So I am stuck on how to get it to actually do work with the other descriptors!

    --- Quote End ---

    --> please provide the sgdma status at your first interrupt, plus the status of the descriptor pointed at by the sgdma "next_descriptor_pointer" register