-
Notifications
You must be signed in to change notification settings - Fork 16
/
ZynqDMASource.cpp
85 lines (73 loc) · 2.59 KB
/
ZynqDMASource.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// Copyright (c) 2013-2014 Josh Blum
// SPDX-License-Identifier: BSL-1.0
#include "ZynqDMASupport.hpp"
#include <iostream>
/***********************************************************************
* |PothosDoc Zynq DMA Source
*
* Test block for receiving DMA buffers from the PL.
*
* |category /Zynq
* |category /Sources
* |keywords zynq dma
*
* |param index[Engine Index] The index of an AXI DMA on the system
* |default 0
*
* |factory /zynq/dma_source(index)
**********************************************************************/
class ZyncDMASource : public Pothos::Block
{
public:
static Block *make(const size_t index)
{
return new ZyncDMASource(index);
}
ZyncDMASource(const size_t index):
_engine(std::shared_ptr<pzdud_t>(pzdud_create(index, PZDUD_S2MM), &pzdud_destroy))
{
if (not _engine) throw Pothos::Exception("ZyncDMASource::pzdud_create()");
this->setupOutput(0, "", "ZyncDMASource"+std::to_string(index));
}
Pothos::BufferManager::Sptr getOutputBufferManager(const std::string &, const std::string &domain)
{
if (domain.empty())
{
return makeZynqDMABufferManager(_engine, PZDUD_S2MM);
}
throw Pothos::PortDomainError();
}
void work(void)
{
auto outPort = this->output(0);
//check if a buffer is available
if (outPort->elements() == 0) return;
//wait for completion on the head buffer
const long timeout_us = this->workInfo().maxTimeoutNs/1000;
const int ret = pzdud_wait(_engine.get(), timeout_us);
if (ret == PZDUD_ERROR_TIMEOUT)
{
//got a timeout, yield so we can get called again
return this->yield();
}
//some other kind of error from wait occurred:
else if (ret != PZDUD_OK)
{
throw Pothos::Exception("ZyncDMASource::pzdud_wait()", std::to_string(ret));
}
//acquire the head buffer and release its handle
size_t length = 0;
const int handle = pzdud_acquire(_engine.get(), &length);
if (handle < 0) throw Pothos::Exception("ZyncDMASource::pzdud_acquire()", std::to_string(handle));
if (size_t(handle) != outPort->buffer().getManagedBuffer().getSlabIndex())
{
throw Pothos::Exception("ZyncDMASource::pzdud_acquire()", "out of order handle");
}
//produce the buffer to the output port
outPort->produce(length);
}
private:
std::shared_ptr<pzdud_t> _engine;
};
static Pothos::BlockRegistry registerZyncDMASource(
"/zynq/dma_source", &ZyncDMASource::make);