[DMA] add done flag to control register

This commit is contained in:
stnolting 2023-10-07 10:23:08 +02:00
parent 0f7852b35d
commit af5060dc0f
5 changed files with 33 additions and 2 deletions

View file

@ -74,6 +74,7 @@ architecture neorv32_dma_rtl of neorv32_dma is
constant ctrl_error_rd_c : natural := 8; -- r/-: error during read transfer
constant ctrl_error_wr_c : natural := 9; -- r/-: error during write transfer
constant ctrl_busy_c : natural := 10; -- r/-: DMA transfer in progress
constant ctrl_done_c : natural := 11; -- r/c: a DMA transfer was executed/attempted
--
constant ctrl_firq_mask_lsb_c : natural := 16; -- r/w: FIRQ trigger mask LSB
constant ctrl_firq_mask_msb_c : natural := 31; -- r/w: FIRQ trigger mask MSB
@ -97,6 +98,7 @@ architecture neorv32_dma_rtl of neorv32_dma is
dst_inc : std_ulogic; -- constant (0) or incrementing (1) destination address
endian : std_ulogic; -- convert endianness when set
start : std_ulogic; -- transfer start trigger
done : std_ulogic; -- transfer was executed (but might have failed)
end record;
signal config : config_t;
@ -146,12 +148,15 @@ begin
config.dst_inc <= '0';
config.endian <= '0';
config.start <= '0';
config.done <= '0';
elsif rising_edge(clk_i) then
config.start <= '0'; -- default
config.done <= config.enable and (config.done or engine.done); -- set if enabled and transfer done
if (bus_req_i.stb = '1') and (bus_req_i.rw = '1') then
if (bus_req_i.addr(3 downto 2) = "00") then -- control and status register
config.enable <= bus_req_i.data(ctrl_en_c);
config.auto <= bus_req_i.data(ctrl_auto_c);
config.done <= '0'; -- clear on write access
config.firq_mask <= bus_req_i.data(ctrl_firq_mask_msb_c downto ctrl_firq_mask_lsb_c);
end if;
if (bus_req_i.addr(3 downto 2) = "01") then -- source base address
@ -186,6 +191,7 @@ begin
bus_rsp_o.data(ctrl_error_rd_c) <= engine.err_rd;
bus_rsp_o.data(ctrl_error_wr_c) <= engine.err_wr;
bus_rsp_o.data(ctrl_busy_c) <= engine.busy;
bus_rsp_o.data(ctrl_done_c) <= config.done;
bus_rsp_o.data(ctrl_firq_mask_msb_c downto ctrl_firq_mask_lsb_c) <= config.firq_mask;
when "01" => -- address of last read access
bus_rsp_o.data <= engine.src_addr;

View file

@ -59,7 +59,7 @@ package neorv32_package is
-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080907"; -- hardware version
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080908"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID
constant XLEN : natural := 32; -- native data path width, do not change!

View file

@ -59,13 +59,14 @@ typedef volatile struct __attribute__((packed,aligned(4))) {
#define NEORV32_DMA ((neorv32_dma_t*) (NEORV32_DMA_BASE))
/** DMA control and status register bits */
enum NEORV32_DMA_QSEL_enum {
enum NEORV32_DMA_CTRL_enum {
DMA_CTRL_EN = 0, /**< DMA control register(0) (r/w): DMA enable */
DMA_CTRL_AUTO = 1, /**< DMA control register(1) (r/w): Automatic trigger mode enable */
DMA_CTRL_ERROR_RD = 8, /**< DMA control register(8) (r/-): Error during read access; SRC_BASE shows the faulting address */
DMA_CTRL_ERROR_WR = 9, /**< DMA control register(9) (r/-): Error during write access; DST_BASE shows the faulting address */
DMA_CTRL_BUSY = 10, /**< DMA control register(10) (r/-): DMA busy / transfer in progress */
DMA_CTRL_DONE = 11, /**< DMA control register(11) (r/c): A transfer was executed when set */
DMA_CTRL_FIRQ_MASK_LSB = 16, /**< DMA control register(16) (r/w): FIRQ trigger mask LSB */
DMA_CTRL_FIRQ_MASK_MSB = 31 /**< DMA control register(31) (r/w): FIRQ trigger mask MSB */
@ -125,6 +126,7 @@ void neorv32_dma_disable(void);
void neorv32_dma_transfer(uint32_t base_src, uint32_t base_dst, uint32_t num, uint32_t config);
void neorv32_dma_transfer_auto(uint32_t base_src, uint32_t base_dst, uint32_t num, uint32_t config, uint32_t firq_mask);
int neorv32_dma_status(void);
int neorv32_dma_done(void);
/**@}*/

View file

@ -140,3 +140,21 @@ int neorv32_dma_status(void) {
return DMA_STATUS_IDLE; // idle
}
}
/**********************************************************************//**
* Check if a transfer has actually been executed.
*
* @return 0 if no transfer was executed, 1 if a transfer has actually been executed.
* Use neorv32_dma_status(void) to check if there was an error during that transfer.
**************************************************************************/
int neorv32_dma_done(void) {
if (NEORV32_DMA->CTRL & (1 << DMA_CTRL_DONE)) {
return 1; // there was a transfer
}
else {
return 0; // no transfer executed
}
}

View file

@ -389,6 +389,11 @@
<access>read-only</access>
<description>DMA transfer in progress</description>
</field>
<field>
<name>DMA_CTRL_DONE</name>
<bitRange>[11:11]</bitRange>
<description>DMA transfer done; auto-clears on write access</description>
</field>
<field>
<name>DMA_CTRL_FIRQ_MASK</name>
<bitRange>[31:16]</bitRange>