27#ifndef MMGR_PRAET_DESCRIPTOR_H
28#define MMGR_PRAET_DESCRIPTOR_H
72#define PRAET_MENSURA_MAXIMA PRAET_MENSURA_VERBUM
107#define PRAET_DIRECTIO_MOTUS_VERBI_FOR(from_, to_, bytes_) \
108 ((((from_) < ((to_) + (bytes_))) && ((to_) < ((from_) + (bytes_))) && ((to_) != (from_))) \
109 ? (((to_) > (from_)) ? PRAET_MOTUS_DEORSUM : PRAET_MOTUS_SURSUM) \
110 : PRAET_MOTUS_NEUTRUM)
148 const uint8_t *source;
149 uint8_t *destination;
152 uint8_t source_addressing;
153 uint8_t destination_addressing;
154 uint8_t ego_sum_mensura;
155 uint8_t directio_motus_verbi;
177#define PRAET_STEPS_FIT(what_, pool_, offset_, bytes_, mensura_) \
178 EMBED_STATIC_ASSERT(((offset_) + (bytes_)) <= sizeof(mmgr_pars_storage_##pool_), \
179 what_ " runs past the end of " #pool_); \
180 EMBED_STATIC_ASSERT(((offset_) % (mensura_)) == 0u, what_ " starts part way into a step of " #pool_); \
181 EMBED_STATIC_ASSERT(((bytes_) % (mensura_)) == 0u, what_ " is not a whole number of steps")
208#define PRAET_DESCRIPTOR_BODY(name_, source_, source_mode_, dest_, dest_mode_, bytes_, mensura_, motus_, next_) \
209 EMBED_STATIC_ASSERT((mensura_) <= (int)PRAET_MENSURA_MAXIMA, \
210 #name_ " asks for a step wider than anything this module carries"); \
211 EMBED_STATIC_ASSERT(((mensura_) & ((mensura_) - 1)) == 0, #name_ " asks for a step that is not a power of two"); \
212 static PraetDescriptor name_ EMBED_UNUSED = { \
213 .source = (source_), \
214 .destination = (dest_), \
215 .bytes = (embed_word)(bytes_), \
217 .source_addressing = (uint8_t)(source_mode_), \
218 .destination_addressing = (uint8_t)(dest_mode_), \
219 .ego_sum_mensura = (uint8_t)(mensura_), \
220 .directio_motus_verbi = (uint8_t)(motus_), \
221 .owner = (uint8_t)PRAET_OWNER_SOFTWARE, \
237#define PraetDescriptorDeclare(name_, from_pool_, from_offset_, to_pool_, to_offset_, bytes_, mensura_, motus_, next_) \
238 PRAET_STEPS_FIT(#name_ " reading from " #from_pool_, from_pool_, from_offset_, bytes_, mensura_); \
239 PRAET_STEPS_FIT(#name_ " writing to " #to_pool_, to_pool_, to_offset_, bytes_, mensura_); \
240 PRAET_DESCRIPTOR_BODY(name_, &mmgr_pars_storage_##from_pool_[from_offset_], PRAET_ADDRESS_ADVANCES, \
241 &mmgr_pars_storage_##to_pool_[to_offset_], PRAET_ADDRESS_ADVANCES, bytes_, mensura_, motus_, \
257#define PRAET_DESCRIPTOR_ENDS_DIFFER(name_, from_pool_, to_pool_) \
260 name_##_end_##from_pool_ = 1, \
261 name_##_end_##to_pool_ = 2 \
276#define PraetOneShot(name_, from_pool_, from_offset_, to_pool_, to_offset_, bytes_, mensura_) \
277 PRAET_DESCRIPTOR_ENDS_DIFFER(name_, from_pool_, to_pool_); \
278 PraetDescriptorDeclare(name_, from_pool_, from_offset_, to_pool_, to_offset_, bytes_, mensura_, \
279 PRAET_MOTUS_NEUTRUM, NULL)
298#define PraetDescriptorWithin(name_, pool_, from_offset_, to_offset_, bytes_, mensura_, next_) \
299 PraetDescriptorDeclare(name_, pool_, from_offset_, pool_, to_offset_, bytes_, mensura_, \
300 PRAET_DIRECTIO_MOTUS_VERBI_FOR(from_offset_, to_offset_, bytes_), next_)
317#define PraetCircular(name_, from_pool_, from_offset_, to_pool_, to_offset_, bytes_, mensura_) \
318 PRAET_DESCRIPTOR_ENDS_DIFFER(name_, from_pool_, to_pool_); \
319 static PraetDescriptor name_; \
320 PraetDescriptorDeclare(name_, from_pool_, from_offset_, to_pool_, to_offset_, bytes_, mensura_, \
321 PRAET_MOTUS_NEUTRUM, &name_)
342#define PraetPingPong(first_, second_, from_pool_, to_pool_, first_from_, first_to_, second_from_, second_to_, bytes_, \
344 PRAET_DESCRIPTOR_ENDS_DIFFER(first_, from_pool_, to_pool_); \
345 PRAET_DESCRIPTOR_ENDS_DIFFER(second_, from_pool_, to_pool_); \
346 static PraetDescriptor second_; \
347 PraetDescriptorDeclare(first_, from_pool_, first_from_, to_pool_, first_to_, bytes_, mensura_, \
348 PRAET_MOTUS_NEUTRUM, &second_); \
349 PraetDescriptorDeclare(second_, from_pool_, second_from_, to_pool_, second_to_, bytes_, mensura_, \
350 PRAET_MOTUS_NEUTRUM, &first_)
370#define PraetPeripheralDeclare(name_, address_) \
371 static volatile uint8_t *const mmgr_praet_peripheral_##name_ EMBED_UNUSED = (volatile uint8_t *)(address_); \
374 name_##_is_a_declared_peripheral = 1 \
403#define PraetToPeripheral(name_, from_pool_, from_offset_, peripheral_, address_, at_offset_, bytes_, mensura_, next_) \
404 PRAET_STEPS_FIT(#name_ " reading from " #from_pool_, from_pool_, from_offset_, bytes_, mensura_); \
405 PRAET_DESCRIPTOR_BODY(name_, &mmgr_pars_storage_##from_pool_[from_offset_], PRAET_ADDRESS_ADVANCES, \
406 ((uint8_t *)(address_) + (at_offset_)), PRAET_ADDRESS_FIXED, bytes_, mensura_, \
407 PRAET_MOTUS_NEUTRUM, next_); \
410 name_##_writes_##peripheral_ = peripheral_##_is_a_declared_peripheral \
430#define PraetFromPeripheral(name_, peripheral_, address_, at_offset_, to_pool_, to_offset_, bytes_, mensura_, next_) \
431 PRAET_STEPS_FIT(#name_ " writing to " #to_pool_, to_pool_, to_offset_, bytes_, mensura_); \
432 PRAET_DESCRIPTOR_BODY(name_, ((const uint8_t *)(address_) + (at_offset_)), PRAET_ADDRESS_FIXED, \
433 &mmgr_pars_storage_##to_pool_[to_offset_], PRAET_ADDRESS_ADVANCES, bytes_, mensura_, \
434 PRAET_MOTUS_NEUTRUM, next_); \
437 name_##_reads_##peripheral_ = peripheral_##_is_a_declared_peripheral \
EgoSumMensura
Bytes the engine moves in one step, the measure everything else is counted in.
@ PRAET_MENSURA_SEMIVERBUM
DirectioMotusVerbi
Which way a transfer walks the words it moves.
PraetDescriptorOwner
Who holds a descriptor.
PraetAddressing
How an address behaves as a transfer runs.
embed_word praet_descriptor_chain_length(const PraetDescriptor *first, embed_word limit)
Counts the descriptors a chain reaches before it repeats or ends.
The schedule context: one flag word per channel, the two volatiles that coordinate the interrupt,...
One transfer, written down.