Dawn Framework 1.0
Universal data acquisition framework for embedded systems
sampling.cxx
1// dawn/src/prog/sampling.cxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#include "dawn/prog/sampling.hxx"
7
8#include <new>
9
10#include "dawn/debug.hxx"
11#include "dawn/io/common.hxx"
12#include "dawn/io/ddata.hxx"
13
14using namespace dawn;
15
16int CProgSampling::configureDesc(const CDescObject &desc)
17{
18 const SObjectCfg::SObjectCfgItem *item = nullptr;
19 const SObjectId::UObjectId *ids;
20 const uint32_t *data;
21 size_t offset = 0;
22 size_t nbind;
23 size_t j;
24 int ret;
25
26 for (size_t i = 0; i < desc.getSize(); i++)
27 {
28 item = desc.objectCfgItemNext(offset);
29
31 {
32 DAWNERR("Unsupported sampling config 0x%08" PRIx32 "\n", item->cfgid.v);
33 return -EINVAL;
34 }
35
36 switch (item->cfgid.s.id)
37 {
39 {
40 if (item->cfgid.s.size % 2 != 0)
41 {
42 DAWNERR("Invalid IOBIND size %d, must be even\n", item->cfgid.s.size);
43 return -EINVAL;
44 }
45
46 nbind = item->cfgid.s.size / 2;
47 ids = reinterpret_cast<const SObjectId::UObjectId *>(item->data);
48
49 for (j = 0; j < nbind; j++)
50 {
51 ret = allocObject(ids[j * 2].v, ids[j * 2 + 1].v);
52 if (ret != OK)
53 {
54 return ret;
55 }
56 }
57
58 break;
59 }
60
62 {
63 if (item->cfgid.s.size != 1)
64 {
65 DAWNERR("Invalid INTERVAL size %d\n", item->cfgid.s.size);
66 return -EINVAL;
67 }
68
69 data = reinterpret_cast<const uint32_t *>(item->data);
70 interval = *data;
71 break;
72 }
73
74 default:
75 {
76 DAWNERR("Unsupported sampling config 0x%08" PRIx32 "\n", item->cfgid.v);
77 return -EINVAL;
78 }
79 }
80 }
81
82 return OK;
83}
84
85int CProgSampling::allocObject(SObjectId::ObjectId srcId, SObjectId::ObjectId targetId)
86{
87 SSamplingBind *b;
88
89 DAWNINFO("allocate sampling 0x%" PRIx32 " -> 0x%" PRIx32 "\n", srcId, targetId);
90
91 b = new (std::nothrow) SSamplingBind();
92 if (!b)
93 {
94 return -ENOMEM;
95 }
96
97 b->srcId = srcId;
98 b->targetId = targetId;
99 b->src = nullptr;
100 b->target = nullptr;
101 b->iodata = nullptr;
102
103 setObjectMapItem(b->srcId, nullptr);
104 setObjectMapItem(b->targetId, nullptr);
105 binds.push_back(b);
106
107 return OK;
108}
109
110void CProgSampling::thread()
111{
112 SSamplingBind *b;
113 size_t i;
114 int ret;
115
116 DAWNINFO("start sampling thread\n");
117
118 do
119 {
120 // Sample all source IOs and push to targets
121
122 for (i = 0; i < binds.size(); i++)
123 {
124 b = binds[i];
125
126 ret = b->src->getData(*b->iodata, 1);
127 if (ret != OK)
128 {
129 DAWNERR("getData failed for src %zu (error %d)\n", i, ret);
130 continue;
131 }
132
133 ret = b->target->setData(*b->iodata);
134 if (ret != OK)
135 {
136 DAWNERR("setData failed for target %zu (error %d)\n", i, ret);
137 }
138 }
139
140 // Wait for next interval
141
142 usleep(interval);
143 }
144 while (!threadCtl.shouldQuit());
145}
146
147CProgSampling::~CProgSampling()
148{
149 deinit();
150}
151
153{
154 int ret;
155
156 // Configure object
157
158 ret = configureDesc(getDesc());
159 if (ret != OK)
160 {
161 DAWNERR("Sampling configure failed (error %d)\n", ret);
162 return ret;
163 }
164
165 // One-time initialization that depends on bindings is done in init()
166
167 return OK;
168}
169
171{
172 size_t i;
173
174 // Free allocated data buffers
175
176 for (i = 0; i < binds.size(); i++)
177 {
178 delete binds[i]->iodata;
179 delete binds[i];
180 }
181
182 binds.clear();
183
184 return OK;
185}
186
188{
189 SSamplingBind *b;
190 size_t i;
191 int ret;
192
193 // Resolve IOs, initialize writable targets, allocate buffers
194
195 for (i = 0; i < binds.size(); i++)
196 {
197 b = binds[i];
198
199 b->src = getIO(b->srcId);
200 if (!b->src)
201 {
202 DAWNERR("Source IO 0x%" PRIx32 " not found\n", b->srcId);
203 return -EIO;
204 }
205
206 if (!b->src->isRead())
207 {
208 DAWNERR("Source IO 0x%" PRIx32 " is not readable\n", b->srcId);
209 return -EINVAL;
210 }
211
212 b->target = getIO(b->targetId);
213 if (!b->target)
214 {
215 DAWNERR("Target IO 0x%" PRIx32 " not found\n", b->targetId);
216 return -EIO;
217 }
218
219 if (b->target->getDtype() != b->src->getDtype())
220 {
221 DAWNERR("Target IO 0x%" PRIx32 " dtype mismatch\n", b->targetId);
222 return -EINVAL;
223 }
224
225 // Initialize deferred virtual targets and validate configured targets
226
227 ret = prepareWritableTarget(b->target,
228 b->src->getDataDim(),
229#ifdef CONFIG_DAWN_IO_NOTIFY
230 true
231#else
232 false
233#endif
234 );
235 if (ret != OK)
236 {
237 DAWNERR("Failed to initialize target %zu (error %d)\n", i, ret);
238 return ret;
239 }
240
241 if (b->target->getDataDim() != b->src->getDataDim() ||
242 b->target->getDataSize() != b->src->getDataSize())
243 {
244 DAWNERR("Target IO 0x%" PRIx32 " shape mismatch\n", b->targetId);
245 return -EINVAL;
246 }
247
248 // Allocate data buffer for this source
249
250 b->iodata = b->src->ddata_alloc(1);
251 if (!b->iodata)
252 {
253 DAWNERR("Failed to allocate data buffer for src %zu\n", i);
254 return -ENOMEM;
255 }
256 }
257
258 return OK;
259}
260
262{
263 // Start sampling thread
264
265 threadCtl.setThreadFunc([this]() { thread(); });
266 return threadCtl.threadStart();
267}
268
270{
271 return threadCtl.threadStop();
272}
273
275{
276 return threadCtl.isRunning();
277}
CIOCommon * getIO(SObjectId::ObjectId id)
Get an I/O object by ID.
Definition bindable.cxx:41
void setObjectMapItem(SObjectId::ObjectId id, CObject *obj)
Set an item in the object map.
Definition bindable.cxx:23
Descriptor wrapper for individual object configuration.
size_t getSize() const
Get number of configuration items for this object.
SObjectCfg::SObjectCfgItem * objectCfgItemNext(size_t &offset) const
Get config item at current offset and advance past it.
CDescObject & getDesc()
Get descriptor object for this object.
Definition object.cxx:190
@ PROG_CLASS_SAMPLING
Periodic data sampler.
Definition common.hxx:63
int doStart()
Start implementation hook.
Definition sampling.cxx:261
bool hasThread() const
Check if a background thread is active.
Definition sampling.cxx:274
int configure()
Configure object from descriptor data.
Definition sampling.cxx:152
int init()
One-time initialize object after bindings are resolved.
Definition sampling.cxx:187
int doStop()
Stop implementation hook.
Definition sampling.cxx:269
int deinit()
De-initialize object.
Definition sampling.cxx:170
@ PROG_SAMPLING_CFG_INTERVAL
Sampling interval (microseconds).
Definition sampling.hxx:37
@ PROG_SAMPLING_CFG_IOBIND
I/O binding configuration.
Definition sampling.hxx:36
bool isRunning() const
Check if the worker thread is running.
Definition thread.cxx:256
int threadStop()
Stop the worker thread.
Definition thread.cxx:240
int threadStart()
Start the worker thread.
Definition thread.cxx:166
void setThreadFunc(Func &&func)
Assign the function executed by threadStart().
Definition thread.hxx:100
Out-of-tree user-extension hooks for Dawn.
Definition bindable.hxx:13
Single configuration item within object.
ObjectCfgData_t data[]
Configuration data array (flexible, size from cfgid.s.size).
UObjectCfgId cfgid
Configuration ID header (type, class, id, size, rw, dtype).
uint32_t ObjectId
ObjectID type - single 32-bit value.
Definition objectid.hxx:44
ObjectCfgId v
Raw 32-bit ConfigID value (for storage, comparison).
Definition objectcfg.hxx:82
uint32_t cls
Object class (bits 21-29, max 511).
uint32_t id
Configuration identifier (bits 0-4, max 31).
Definition objectcfg.hxx:94
uint32_t size
Configuration data size in 32-bit words (bits 5-14, max 1023).
struct dawn::SObjectCfg::UObjectCfgId::@10 s
Bit-field structure for named member access.
32-bit encoded object identifier (union with bit field).
Definition objectid.hxx:218