Dma
The Dma component handles the configuration and control of the Direct Memory Access (DMA). It is used to transfer data from the hardware design to the memory.
Additional information
The Dma component works only with the Dma implementation of AMD/Xilinx [1].
When creating a Dma object the corresponding DMA is configured using a memory map to access the DMA registers and a descriptor control to access the descriptor control registers. A Uio device is used to wait for Dma interrupts. On each interrupt it is checked if the interrupt was caused by the measurement stop. If this happened the DMA waits for the last transfer to finish and then the DMA is stopped.
Classes
DMA Class
-
class Dma
DMA class to handle the AXI DMA device.
This class is used to control the DMA device.
Objects of this class are supposed to run in a separate thread. Also another thread is created to handle the interrupts.
Subclassed by nexmess::components::dma::DmaCount
Public Functions
-
Dma(uint8_t dma_id, uint8_t dma_interrupt_id, uint8_t index, int mem, uint32_t register_base, const char *dma_device, const char *uio_device, uint32_t descriptor_offset, uint32_t descriptor_per_dma, uint32_t package_size, uint32_t dma_ram_start_address)
Only constructor for the DMA class.
- Parameters:
dma_id – The DMA ID. The ID should be the index of the corresponding DMA device within the DMAS array.
dma_interrupt_id – The DMA interrupt ID.
index – The index of the DMA device.
mem – The memory identifier.
register_base – The address of the DMA device register.
dma_device – The name of the DMA device to handle the memory.
uio_device – The name of the UIO device to handle the interrupts.
descriptor_offset – The offset of the DMA descriptor memory.
descriptor_per_dma – The amount of DMA descriptors per DMA device.
package_size – The size of a package in kDefaultDataSize byte words.
dma_ram_start_address – The start address of the DMA RAM (e.g. kDmaRawStartAddress).
-
virtual ~Dma()
Destructor for the DMA class.
This destructor makes sure the DMA is disabled and the thread is joined.
-
Dma() = delete
-
bool empty()
Checks if the DMA is empty.
- Returns:
true if the DMA is empty, false otherwise.
-
bool full()
Checks if the DMA is full.
It is also true if the RAM is full.
- Returns:
true if the DMA is full, false otherwise.
-
void set_fifo_full_handled()
Sets the flag indicating that the FIFO is full and has been handled.
This is set by the controller once the FIFO full interrupt has been handled.
-
bool fifo_full_handled() const
Checks if the FIFO full interrupt has been handled.
- Returns:
true if the FIFO full interrupt has been handled, false otherwise.
-
inline uint8_t get_id() const
Get the ID of the DMA.
-
inline uint8_t get_index() const
Get the index of the DMA.
-
inline uint32_t get_dma_descriptor_count() const
Get the amount of descriptors for the DMA.
-
void reset()
Sets the bit in the DMA control register to reset the DMA.
-
void enable_interrupt()
Enables the DMA interrupts as well as the UIO interrupts.
-
InterruptStatus wait_for_data()
Waits for interrupts and checks for available data.
This function handles the interrupts and re-enables them. It updates the descriptor pointers. It also checks if there is data available and sets the FIFO full flag if the FIFO is full. When the measurement is finished it handles it as well.
- Returns:
The interrupt status.
-
void enable()
Enables the DMA operation.
It spawns the thread to handle the DMA operations.
-
void disable()
Disables the DMA operation.
It stops the thread to handle the DMA operations ans disables the DMA in hardware.
-
void set_start_descriptor_address(uint32_t address)
Sets the start descriptor address.
-
void set_tail_descriptor_address(uint32_t address)
Sets the tail descriptor address.
Writing to this register starts the actual DMA operation in hardware. From this point on the DMA will read the descriptors and write the data to the RAM when data is available.
-
uint32_t get_data_length()
Gets the length of the data.
Usually it should be the same as kDefaultRawPackageSizeBytes. When the measurement was stopped the last package might (most probably) be smaller.
- Returns:
The length of the data as a uint32_t.
-
uint32_t get_status()
Get the status of the DMA.
The status is read from the status register of the DMA.
- Returns:
The status of the DMA as a 32-bit unsigned integer.
-
bool has_status_error()
Checks if there is a status error.
Is the same as has_status_error(uint32_t status) but reads the status register first.
- Returns:
true if there is a status error, false otherwise.
-
bool has_status_error(uint32_t status)
Checks if there is a status error.
- Parameters:
status – The value if the status register.
- Returns:
true if there is a status error, false otherwise.
-
bool has_error() const
Checks if there is an error in the DMA component.
- Returns:
true if there is an error, false otherwise.
-
bool is_running() const
Checks if the DMA is currently running.
- Returns:
true if the DMA is running, false otherwise.
-
bool is_stopped() const
Checks if the DMA is stopped.
- Returns:
true if the DMA is stopped, false otherwise.
-
uint64_t *memory_map() const
Returns a pointer to the memory map.
This function returns a pointer to the memory map used by the DMA component. The memory map is a uint64_t pointer that represents the starting address of the memory map.
- Returns:
A pointer to the memory map.
-
uint32_t write_size()
Returns the size of data which is received and can be handled.
The returned write size is never bigger than one portion of memory described by one DMA descriptor. This makes sure that we don’t read data after the last descriptor (wrap around).
This function reduces the amount of available data for the next call.
This function must be called for continuous operation.
- Returns:
The size of the write operation in bytes.
-
void decrease_read_difference()
Decreases the read difference.
This function is responsible for decreasing the read difference. It should be called after the received data of one descriptor has been handled.
This function must be called for continuous operation.
-
uint32_t current_read_descriptor()
Returns the current read descriptor.
This function returns the current read descriptor used by the DMA module. This also updated the read descriptor pointer to read the next descriptor the next time.
This function must be called for continuous operation.
- Returns:
The current read descriptor.
-
uint32_t package_size() const
Returns the package size.
-
virtual bool is_count_dma() const
Returns false if the DMA is not a count DMA.
- Returns:
true if the DMA is a count DMA, false otherwise.
Private Functions
-
void register_enable()
Sets the DMAs register so that it is ready to receive data.
-
void register_disable()
Sets the DMAs register so that it is not ready to receive data.
Private Members
-
const uint8_t ID_
The DMA ID.
The ID is supposed to be the index of the corresponding DMA device within the DMAS array.
-
const uint8_t DMA_INTERRUPT_ID_
The DMA interrupt ID.
-
const uint8_t INDEX_
The index of the DMA device.
-
const uint32_t REGISTER_BASE_
The address of the DMA device register.
-
const char *const DMA_DEVICE_
The name of he DMA device to handle the memory.
-
const char *const UIO_DEVICE_
The name of the UIO device to handle the DMA interrupts.
-
const uint32_t DESCRIPTOR_OFFSET_
The offset of the DMA descriptor memory.
-
const uint32_t DESCRIPTOR_PER_DMA_
The amount of DMA descriptors per DMA device.
-
const uint32_t PACKAGE_SIZE_
The size of a package in kDefaultDataSize byte words.
-
const uint32_t PACKAGE_SIZE_BYTES_
The size of a package in bytes.
-
uint32_t current_descriptor_ = 0
The current write descriptor.
-
uint32_t current_read_descriptor_ = 0
The current read descriptor.
-
std::atomic<uint32_t> read_difference_{0}
The difference between the current read and write descriptor.
RAM full depends on this value.
-
std::atomic<uint32_t> received_data_packets_{0}
The number of received data packets.
-
dma::DescriptorControl descriptor_control_
The descriptor control object used to control the DMA descriptors.
-
std::atomic<bool> enabled_ = {false}
Indicates whether the DMA is enabled.
-
std::atomic<bool> running_ = {false}
Indicates whether the DMA is running.
-
std::atomic<bool> stopped_{false}
Indicates whether the DMA is finished its operation.
-
std::chrono::time_point<std::chrono::steady_clock> stop_time_
The time when the DMA was stopped.
-
std::unique_ptr<std::thread> thread_ = nullptr
The thread used to handle the DMA operations.
It contains a loop which runs until the DMA is stopped.
-
std::atomic<bool> exit_ = false
Indicates whether the DMA thread should exit.
-
std::atomic<bool> fifo_full_ = {false}
Indicates whether the FIFO is full.
-
std::atomic<bool> fifo_full_handled_{false}
Indicates whether the FIFO full interrupt was handled.
It is used for communication with the controller object.
-
bool has_error_ = false
Indicates whether there is an error.
-
Dma(uint8_t dma_id, uint8_t dma_interrupt_id, uint8_t index, int mem, uint32_t register_base, const char *dma_device, const char *uio_device, uint32_t descriptor_offset, uint32_t descriptor_per_dma, uint32_t package_size, uint32_t dma_ram_start_address)
DescriptorControl Class
-
class DescriptorControl
Controls the descriptors for DMA operations.
The DescriptorControl class provides functionality to control the descriptors used for DMA operations. It manages the DMA ID, register base address, and memory size. It also provides methods to check for errors, retrieve the number of received data words, and write descriptors.
Public Functions
-
DescriptorControl(uint32_t dma_id, uint32_t register_base, int mem, uint32_t descriptor_offset, uint32_t descriptor_per_dma, uint32_t package_size_bytes, uint32_t dma_ram_start_address)
Constructor for DescriptorControl.
- Parameters:
dma_id – DMA ID.
register_base – Register base address.
mem – Memory size.
descriptor_offset – Descriptor offset.
descriptor_per_dma – Number of descriptors per DMA.
package_size_bytes – Package size in bytes.
dma_ram_start_address – Start address of the DMA RAM (e.g. kDmaRawStartAddress).
-
~DescriptorControl() = default
Destructor for DescriptorControl.
-
DescriptorControl() = delete
-
DescriptorControl(const DescriptorControl&) = delete
-
void operator=(const DescriptorControl&) = delete
-
DescriptorControl(DescriptorControl&&) = delete
-
DescriptorControl &operator=(DescriptorControl&&) = delete
-
bool has_error() const
Checks if there is an error.
- Returns:
True if there is an error, false otherwise.
-
uint32_t get_received_data_word_length(uint32_t descriptor_number)
Gets the number of received 32 bit words (yes not 64 bit).
The number of received 32 bit words is the number of bytes received divided by 4.
- Parameters:
descriptor_number – Descriptor number.
- Returns:
The received data.
-
void write_descriptors()
Writes the descriptors.
The DMA is set into circular mode, so the last descriptor points to the first one.
Private Members
-
const uint32_t DMA_ID_
The DMA ID.
-
const uint32_t REGISTER_BASE_
The register base address.
-
const uint32_t REGISTER_SIZE_
The register size.
-
const uint32_t DESCRIPTOR_OFFSET_
The offset of the first descriptor from the base.
-
const uint32_t DESCRIPTOR_PER_DMA_
The number of descriptors per DMA.
-
const uint32_t PACKAGE_SIZE_BYTES_
The package size in bytes.
-
const uint32_t DMA_RAM_START_ADDRESS_
The start address of the DMA RAM.
-
DescriptorControl(uint32_t dma_id, uint32_t register_base, int mem, uint32_t descriptor_offset, uint32_t descriptor_per_dma, uint32_t package_size_bytes, uint32_t dma_ram_start_address)