dbdma: Schedule interpret_cmd.

Have the entire dbdma program executed by scheduling each iteration in the CPU loop.
This is done only for devices that use the dbdma program to drive data input/output (has_data_callbacks) rather than have the device drive the dbdma program.
This commit is contained in:
joevt
2024-04-20 04:08:57 -07:00
committed by dingusdev
parent 362cfcbc83
commit e1849a2bfd
2 changed files with 30 additions and 6 deletions

View File

@@ -43,6 +43,7 @@ void DMAChannel::set_data_callbacks(DbdmaCallback in_cb, DbdmaCallback out_cb, D
this->in_cb = in_cb; this->in_cb = in_cb;
this->out_cb = out_cb; this->out_cb = out_cb;
this->flush_cb = flush_cb; this->flush_cb = flush_cb;
this->has_data_callbacks = in_cb || out_cb || flush_cb;
} }
/* Load DMACmd from physical memory. */ /* Load DMACmd from physical memory. */
@@ -60,16 +61,32 @@ DMACmd* DMAChannel::fetch_cmd(uint32_t cmd_addr, DMACmd* p_cmd, bool *is_writabl
return cmd_host; return cmd_host;
} }
uint8_t DMAChannel::interpret_cmd() { void DMAChannel::schedule_cmd() {
if (!interpret_timer_id) {
interpret_timer_id = TimerManager::get_instance()->add_oneshot_timer(1000000, [this] {
interpret_timer_id = 0;
if (this->ch_stat & CH_STAT_ACTIVE) {
this->interpret_cmd();
}
});
}
}
void DMAChannel::interpret_cmd() {
DMACmd cmd_struct; DMACmd cmd_struct;
MapDmaResult res; MapDmaResult res;
if (this->cmd_in_progress) { if (this->cmd_in_progress) {
// return current command if there is data to transfer // if there is data remaining to transfer then the command is not finished
if (this->queue_len) if (this->queue_len)
return this->cur_cmd; return;
// if there is no data remaining to transfer then the command is finished and the program should procede to the next command
this->finish_cmd(); this->finish_cmd();
if (this->has_data_callbacks) {
schedule_cmd();
return;
}
} }
bool cmd_is_writable; bool cmd_is_writable;
@@ -140,7 +157,11 @@ uint8_t DMAChannel::interpret_cmd() {
this->ch_stat &= ~CH_STAT_ACTIVE; this->ch_stat &= ~CH_STAT_ACTIVE;
} }
return this->cur_cmd; if (this->has_data_callbacks) {
if (this->has_data_callbacks) {
schedule_cmd();
}
}
} }
void DMAChannel::finish_cmd() { void DMAChannel::finish_cmd() {

View File

@@ -129,8 +129,9 @@ public:
}; };
protected: protected:
DMACmd* fetch_cmd(uint32_t cmd_addr, DMACmd* p_cmd, bool *is_writable); static DMACmd* fetch_cmd(uint32_t cmd_addr, DMACmd* p_cmd, bool *is_writable);
uint8_t interpret_cmd(void); void schedule_cmd();
void interpret_cmd();
void finish_cmd(); void finish_cmd();
void xfer_quad(const DMACmd *cmd_desc, DMACmd *cmd_host); void xfer_quad(const DMACmd *cmd_desc, DMACmd *cmd_host);
void update_irq(); void update_irq();
@@ -147,6 +148,8 @@ private:
std::function<void(void)> in_cb = nullptr; // DMA channel in callback std::function<void(void)> in_cb = nullptr; // DMA channel in callback
std::function<void(void)> out_cb = nullptr; // DMA channel out callback std::function<void(void)> out_cb = nullptr; // DMA channel out callback
std::function<void(void)> flush_cb = nullptr; // DMA channel flush callback std::function<void(void)> flush_cb = nullptr; // DMA channel flush callback
bool has_data_callbacks = false;
uint32_t interpret_timer_id = 0;
uint16_t ch_stat = 0; uint16_t ch_stat = 0;
uint32_t cmd_ptr = 0; uint32_t cmd_ptr = 0;