x-heep icon indicating copy to clipboard operation
x-heep copied to clipboard

add multichannel DMA feature

Open davideschiavone opened this issue 1 year ago • 2 comments

This can be implemented as "N" instantiations of the DMA, all with contiguous memory space

N should be specified in the mcu_gen.hjson file, and mako templates should add the N DMA instances and a bus Nto1 for each DMA port to keep the complexity of the system bus under control.

A DMA_subsystem module should be done to keep all the instances together.

The external SLOT interface mentioned in https://github.com/esl-epfl/x-heep/issues/407 should be replicated for each DMA. Thus, in the interface at the heep boundary you have:

input logic [EXT_DMA_TRIGGER_SLOT_NUM-1:0] ext_dma_trigger_slots_i[DMA_CHANNELS]

In the HAL of the DMA, the user should set the channel ID so that the right peripheral can be set - this probably means that every DMA HAL function needs to be extended with the channel ID as an input - adding @JuanSapriza in the thread to make him aware

assigned to @grinningmosfet

davideschiavone avatar Oct 17 '23 18:10 davideschiavone

Hello! If i remember properly, all configurations of the DMA transaction are in a structure. We could very easily either a) Make a struct array b) Offload to the application level the responsibility of keeping such structure (more memory efficient)

From the launching its just adding one more argument (the register start offset) to the launch function.

What we should watch with a little bit more care are the interrupts. For this I summon @Ho3eintaji and @StefanoAlbini96 so they are also aware

JuanSapriza avatar Oct 18 '23 08:10 JuanSapriza

well said, we should not forget the interrupts - I would keep the interrupt line equal to 1, being the OR of all the single DMAs, in SW during the ISR, you implement your switch case priority, and check in the DMA register who triggered the interrupt, clean such register, and jump to the user-defined DMA-channel relative ISR .

Something like:

void multichannel_dma_isr()
{
   For each DMA Channel C
    irq = read_interrupt_reg(channel C),
    if(irq) {
    clear_interrupt_reg(channel C);
    jump_to_dma_isr[c](); //array of function pointers
    }
}

In this case the priority is DMA0 first

davideschiavone avatar Oct 18 '23 08:10 davideschiavone