-
Notifications
You must be signed in to change notification settings - Fork 16
/
ZynqDMASink.cpp
84 lines (72 loc) · 2.61 KB
/
ZynqDMASink.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
// Copyright (c) 2013-2014 Josh Blum
// SPDX-License-Identifier: BSL-1.0
#include "ZynqDMASupport.hpp"
#include <iostream>
/***********************************************************************
* |PothosDoc Zynq DMA Sink
*
* Test block for sending DMA buffers into the PL.
*
* |category /Zynq
* |category /Sinks
* |keywords zynq dma
*
* |param index[Engine Index] The index of an AXI DMA on the system
* |default 0
*
* |factory /zynq/dma_sink(index)
**********************************************************************/
class ZyncDMASink : public Pothos::Block
{
public:
static Block *make(const size_t index)
{
return new ZyncDMASink(index);
}
ZyncDMASink(const size_t index):
_engine(std::shared_ptr<pzdud_t>(pzdud_create(index, PZDUD_MM2S), &pzdud_destroy))
{
if (not _engine) throw Pothos::Exception("ZyncDMASink::pzdud_create()");
this->setupInput(0, "", "ZyncDMASink"+std::to_string(index));
}
Pothos::BufferManager::Sptr getInputBufferManager(const std::string &, const std::string &domain)
{
if (domain.empty())
{
return makeZynqDMABufferManager(_engine, PZDUD_MM2S);
}
throw Pothos::PortDomainError();
}
void work(void)
{
auto inPort = this->input(0);
//check if a buffer is available
if (inPort->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("ZyncDMASink::pzdud_wait()", std::to_string(ret));
}
//acquire the head buffer and release its handle
size_t length = 0; //length not used for MM2S
const int handle = pzdud_acquire(_engine.get(), &length);
if (handle < 0) throw Pothos::Exception("ZyncDMASink::pzdud_acquire()", std::to_string(handle));
//the handle could be out of order, so we dont check its value
//we assume that out of order buffers means that we waited on
//more xfers, not less xfers, including this handle's xfers
//consume the buffer from the input port
inPort->consume(inPort->elements());
}
private:
std::shared_ptr<pzdud_t> _engine;
};
static Pothos::BlockRegistry registerZyncDMASink(
"/zynq/dma_sink", &ZyncDMASink::make);