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->out_cb = out_cb;
this->flush_cb = flush_cb;
this->has_data_callbacks = in_cb || out_cb || flush_cb;
}
/* 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;
}
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;
MapDmaResult res;
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)
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();
if (this->has_data_callbacks) {
schedule_cmd();
return;
}
}
bool cmd_is_writable;
@ -140,7 +157,11 @@ uint8_t DMAChannel::interpret_cmd() {
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() {

View File

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