+
+void DMA_set_return(int nret, int nchan)
+{
+ struct dma_regs *r;
+ struct dma_cont *d;
+ int icont, ichan;
+
+ icont = nchan> 3;
+ ichan = nchan& 3;
+ d = dma_controllers;
+ r =&d[icont].regs[ichan];
+ r->now[COUNT] = nret;
+ assert(r->channel_is_asynchronous);
+ assert(r->channel_running);
Thanks, this is very much like what I had in mind, except that here I
would have called DMA_run. Also you can then remove the bottom half
(and rearm logic) completely.
If calling DMA_run is not working, perhaps it is because you didn't
remove the bottom half.
You have written to me :
assert(channel_is_asynchronous[ichan]);
assert(channel_running[ichan] == 1);
channel_running[ichan]--;
if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4)))) {
channel_run (icont, ichan);
}
If I add the code :
if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4)))) {
channel_run (icont, ichan);
}
Because function DMA_set_return is called in fdctrl_read_DMA_cb and
fdctrl_write_DMA_cb, the fdctrl_stop_transfer will release the channel,
but fdctrl_stop_transfer is after the DMA_set_return, so the channel_run
will run again, so here I delete the above code.
I would hope that you can also change the "if (running) goto out;" to an
"assert(!running)", but I'm not so sure.
sorry, here I don't understand well,or you can explain in detail. :)
Thank you very much for your feedback! :)