Compare commits

..

No commits in common. "54db3acc1e3e49321d15fcbabfa19dbabfc77301" and "83f77f62c0bcc5200696f3f45a9f4e2fb4513d5c" have entirely different histories.

13 changed files with 250 additions and 156 deletions

View File

@ -60,34 +60,34 @@ void EthEcatPdoFMMU::wait_op() {
} }
void EthEcatPdoFMMU::process_write_queue(uint8_t* process_data, uint32_t len) { void EthEcatPdoFMMU::process_write_queue(uint8_t* process_data, uint32_t len) {
custom_promise::IPromise *next;
mutex_write_.lock(); mutex_write_.lock();
queue::Queue<custom_promise::IPromise> queue = queue_write_; next = queue_write_.get_next();
queue_write_.clear(); last_write_ = &queue_write_;
mutex_write_.unlock(); mutex_write_.unlock();
auto next = queue.dequeue();
while(next != nullptr) { while(next != nullptr) {
next->set_value(process_data, len); next->set_value(process_data, len);
next = queue.dequeue(); next = next->get_next();
} }
} }
void EthEcatPdoFMMU::process_read_queue(uint8_t* process_data, uint32_t len) { void EthEcatPdoFMMU::process_read_queue(uint8_t* process_data, uint32_t len) {
custom_promise::IPromise *next;
mutex_read_.lock(); mutex_read_.lock();
queue::Queue<custom_promise::IPromise> queue = queue_read_; next = queue_read_.get_next();
queue_read_.clear(); last_read_ = &queue_read_;
mutex_read_.unlock(); mutex_read_.unlock();
auto next = queue.dequeue();
while(next != nullptr) { while(next != nullptr) {
next->set_value(process_data, len); next->set_value(process_data, len);
next = queue.dequeue(); next = next->get_next();
} }
} }

View File

@ -47,7 +47,32 @@ private:
ecat_buffer::EcatBufferSlave& buffer_slave_; ecat_buffer::EcatBufferSlave& buffer_slave_;
}; };
/*
// Функтор для обхода и передачи датаграмм в custom_tuple
struct DatagramFunctor {
telegram::EcatTelegram& telegram;
size_t number_of_slaves;
datagram::IEcatDatagram *next;
void operator()(datagram::IEcatDatagram& datagram) {
if(next != nullptr) {
datagram + *next;
}
next = &datagram;
}
void operator()() {
if(next == nullptr) {
return;
}
do {
telegram.transfer(*next);
} while(next->get_all_wkc() < number_of_slaves);
}
};
*/
class EthEcatPdoFMMU { class EthEcatPdoFMMU {
public: public:
EthEcatPdoFMMU(ecat_buffer::EthEcatBuffer& ecat_buffer): ecat_buffer_{ecat_buffer} { } EthEcatPdoFMMU(ecat_buffer::EthEcatBuffer& ecat_buffer): ecat_buffer_{ecat_buffer} { }
@ -66,7 +91,8 @@ public:
mutex_write_.lock(); mutex_write_.lock();
queue_write_ + promise; custom_promise::IPromise& last_write = (*last_write_) >> promise;
last_write_ = &last_write;
mutex_write_.unlock(); mutex_write_.unlock();
@ -82,7 +108,8 @@ public:
mutex_read_.lock(); mutex_read_.lock();
queue_read_ + promise; custom_promise::IPromise& last_read = (*last_read_) >> promise;
last_read_ = &last_read;
mutex_read_.unlock(); mutex_read_.unlock();
@ -95,7 +122,8 @@ public:
void pdo_write_async(custom_promise::IPromise& promise) { void pdo_write_async(custom_promise::IPromise& promise) {
mutex_write_.lock(); mutex_write_.lock();
queue_write_ + promise; custom_promise::IPromise& last_write = (*last_write_) >> promise;
last_write_ = &last_write;
mutex_write_.unlock(); mutex_write_.unlock();
} }
@ -103,7 +131,8 @@ public:
void pdo_read_async(custom_promise::IPromise& promise) { void pdo_read_async(custom_promise::IPromise& promise) {
mutex_read_.lock(); mutex_read_.lock();
queue_read_ + promise; custom_promise::IPromise& last_read = (*last_read_) >> promise;
last_read_ = &last_read;
mutex_read_.unlock(); mutex_read_.unlock();
} }
@ -116,8 +145,11 @@ private:
Mutex mutex_write_; Mutex mutex_write_;
Mutex mutex_read_; Mutex mutex_read_;
queue::Queue<custom_promise::IPromise> queue_write_; custom_promise::WritePromise<> queue_write_{0};
queue::Queue<custom_promise::IPromise> queue_read_; custom_promise::ReadPromise<> queue_read_{0};
custom_promise::IPromise *last_write_{&queue_write_};
custom_promise::IPromise *last_read_{&queue_read_};
uint32_t pdo_counter_{0}; uint32_t pdo_counter_{0};
@ -175,6 +207,55 @@ private:
} while(datagram_read.get_all_wkc() < 0x0001); } while(datagram_read.get_all_wkc() < 0x0001);
} }
/*
// Запись PDO замапленных каждым слейвом
template<typename... DataTypes>
void write(DataTypes&... data) {
if(sizeof...(data) > pdo_fmmu_slaves_.size()) {
return;
}
size_t i = 0;
custom_tuple<datagram::EcatDatagram<command::LWR, DataTypes>...> datagram_tuple{pdo_fmmu_slaves_[i++].make_datagram_write(data)...};
DatagramFunctor functor{ecat_buffer_.get_ecat().get_telegram(), pdo_fmmu_slaves_.size(), nullptr};
for_each_reverse(datagram_tuple, functor);
}
// Чтение PDO замапленных каждым слейвом
template<typename... DataTypes>
void read(DataTypes&... data) {
if(sizeof...(data) > pdo_fmmu_slaves_.size()) {
return;
}
size_t i = 0;
custom_tuple<datagram::EcatDatagram<command::LRD, DataTypes>...> datagram_tuple{pdo_fmmu_slaves_[i++].make_datagram_read(data)...};
DatagramFunctor functor{ecat_buffer_.get_ecat().get_telegram(), pdo_fmmu_slaves_.size(), nullptr};
for_each_reverse(datagram_tuple, functor);
}
// Последовательность чтения-записи PDO замапленных каждым слейвом
template<typename... DataTypes>
void read_write(DataTypes&... data) {
if(sizeof...(data) > pdo_fmmu_slaves_.size()) {
return;
}
size_t i = 0;
size_t j = 0;
// custom_tuple с датаграммами и на чтение и на запись в две строки. 1 строка - тип, 2 строка - имя переменной
custom_tuple<datagram::EcatDatagram<command::LRD, DataTypes>... , datagram::EcatDatagram<command::LWR, DataTypes>...>
datagram_tuple{pdo_fmmu_slaves_[i++].make_datagram_read(data)... , pdo_fmmu_slaves_[j++].make_datagram_write(data)...};
DatagramFunctor functor{ecat_buffer_.get_ecat().get_telegram(), pdo_fmmu_slaves_.size(), nullptr};
for_each_reverse(datagram_tuple, functor);
}
*/
}; };
} // namespace ecat_pdo_fmmu } // namespace ecat_pdo_fmmu

View File

@ -353,7 +353,7 @@ public:
sdo_read<TypeT, uint16_t>(telegram, pdo_map_index, pdo_map_subindex, pdo_block_index); sdo_read<TypeT, uint16_t>(telegram, pdo_map_index, pdo_map_subindex, pdo_block_index);
pdo_map.block_index_map[pdo_map_index].emplace(pdo_map_subindex, pdo_block_index); pdo_map.block_index_map[pdo_map_index].emplace(pdo_map_subindex, pdo_block_index);
DebugP_log("pdo_block_index = 0x02%x\r\n", pdo_block_index); //DebugP_log("pdo_block_index = 0x02%x\r\n", pdo_block_index);
ecat_buffer::PDODescriptor tmp; ecat_buffer::PDODescriptor tmp;
uint8_t& pdo_block_object_count = tmp.size; uint8_t& pdo_block_object_count = tmp.size;

View File

@ -179,8 +179,6 @@ void EthEcat::get_addresses_of_slaves() {
datagrams.emplace_back(TDatagram{ {{slave.get_slave_address<command::AP>(), ECT_REG_STADR}}, slave.get_slave_address<command::FP>() }); datagrams.emplace_back(TDatagram{ {{slave.get_slave_address<command::AP>(), ECT_REG_STADR}}, slave.get_slave_address<command::FP>() });
} }
queue::Queue<TDatagram> queue;
for(uint16_t i = 1; i < number_of_slaves; i++) { for(uint16_t i = 1; i < number_of_slaves; i++) {
datagrams[i - 1] + datagrams[i]; datagrams[i - 1] + datagrams[i];
} }

View File

@ -18,17 +18,6 @@
namespace free_rtos { namespace free_rtos {
/*
* Порядок инициализации:
* Инициализировать и открыть драйвер eth_.Init(...), eth_.Open()
* Вызвать EthEcatApi::init(eth_);
* Создать служебный поток ecat_task_.Create(...) с вызовом EthEcatApi::process()
* Вызвать EthEcatApi::config_init(...)
* Создать пользовательский поток ecat_task_pdo_.Create(...)
* Для чтения/записи данных в пользовательском потоке вызвать
* pdo_write(...), pdo_read(...) или pdo_write_async(...), pdo_read_async(...)
*/
class EthEcatApi { class EthEcatApi {
public: public:
static void init(Eth& eth); static void init(Eth& eth);

View File

@ -18,7 +18,7 @@ namespace free_rtos {
enum { enum {
ECT_PDOOUTPUTOFFSET = 0x1100, // 0x1100 write, output, rx buffer offset ECT_PDOOUTPUTOFFSET = 0x1100, // 0x1100 write, output, rx buffer offset
ECT_PDOINPUTOFFSET = 0x1180 // 0x1400, 0x1140 read, input, tx buffer offset ECT_PDOINPUTOFFSET = 0x1400 // 0x1400, 0x1140 read, input, tx buffer offset
}; };
enum { enum {
@ -199,7 +199,7 @@ public:
SyncManager sync_manager_read = sync_managers_[static_cast<size_t>(sm_read)]; SyncManager sync_manager_read = sync_managers_[static_cast<size_t>(sm_read)];
auto datagram_read = make_sync_manager_datagram<TypeT>(sync_manager_read, buffer_properties_read_); auto datagram_read = make_sync_manager_datagram<TypeT>(sync_manager_read, buffer_properties_read_);
auto queue = datagram_write + datagram_read; datagram_write + datagram_read;
do { do {
telegram.transfer(datagram_write); telegram.transfer(datagram_write);

View File

@ -22,6 +22,54 @@ namespace free_rtos {
namespace custom_promise { namespace custom_promise {
/*
// Функтор для обхода и упаковки датаграмм в custom_tuple
struct DatagramPackFunctor : public PackFunctor {
DatagramPackFunctor(uint8_t *raw)
: PackFunctor{raw} { }
using PackFunctor::operator ();
template<typename CommandT, typename... DataTypes>
void operator()(datagram::EcatDatagram<CommandT, DataTypes...>& data) {
raw = data.pack(raw);
}
template<typename CommandT, typename... DataTypes>
void operator()(std::vector< datagram::EcatDatagram<CommandT, DataTypes...> >& data) {
for(uint16_t i = 1; i < data.size(); i++) {
raw = data[i - 1].pack(raw);
}
raw = data[data.size() - 1].pack(raw);
}
};
// Функтор для обхода и распаковки датаграмм в custom_tuple
struct DatagramUnpackFunctor : public UnpackFunctor {
DatagramUnpackFunctor(uint8_t *raw)
: UnpackFunctor{raw} { }
using UnpackFunctor::operator ();
template<typename CommandT, typename... DataTypes>
void operator()(datagram::EcatDatagram<CommandT, DataTypes...>& data) {
raw = data.unpack(raw);
}
template<typename CommandT, typename... DataTypes>
void operator()(std::vector< datagram::EcatDatagram<CommandT, DataTypes...> >& data) {
for(uint16_t i = 1; i < data.size(); i++) {
data[i - 1] + data[i];
raw = data[i - 1].unpack(raw);
}
raw = data[data.size() - 1].unpack(raw);
}
};
*/
template<typename... DataTypes> template<typename... DataTypes>
class Future { class Future {
public: public:
@ -65,15 +113,35 @@ private:
class IPromise { class IPromise {
public: public:
friend class queue::Queue<IPromise>;
IPromise(address::Offset offset = 0) IPromise(address::Offset offset = 0)
: offset_{offset} { } : offset_{offset} { }
/*
queue::Queue<IPromise> operator+(IPromise &next) { IPromise* get_next() {
return queue::Queue<IPromise>{queue_entity_, next.queue_entity_}; queue::QueueEntity<IPromise>* next = queue_entity_.get_next();
if(next == nullptr) {
return nullptr;
}
return next->get_data();
} }
*/
queue::QueueEntity<IPromise>& get_queue_entity() {
return queue_entity_;
}
IPromise& operator+(IPromise &next) {
queue_entity_ + next.get_queue_entity();
return next;
}
IPromise& operator>>(IPromise &next) {
queue_entity_ >> next.get_queue_entity();
return next;
}
virtual void set_value(uint8_t* process_data, uint32_t len) = 0; virtual void set_value(uint8_t* process_data, uint32_t len) = 0;
protected: protected:

View File

@ -114,12 +114,14 @@ struct each_tuple_element< FunctorT, custom_tuple<> > {
template<typename TupleT, typename FunctorT> template<typename TupleT, typename FunctorT>
void for_each(TupleT& t, FunctorT& functor) { void for_each(TupleT& t, FunctorT& functor) {
each_tuple_element<FunctorT, TupleT>::for_each(functor, t); each_tuple_element<FunctorT, TupleT>::for_each(functor, t);
functor();
} }
// Функция для обратного обхода элементов custom_tuple // Функция для обратного обхода элементов custom_tuple
template<typename TupleT, typename FunctorT> template<typename TupleT, typename FunctorT>
void for_each_reverse(TupleT& t, FunctorT& functor) { void for_each_reverse(TupleT& t, FunctorT& functor) {
each_tuple_element<FunctorT, TupleT>::for_each_reverse(functor, t); each_tuple_element<FunctorT, TupleT>::for_each_reverse(functor, t);
functor();
} }
} }

View File

@ -25,8 +25,6 @@ using TEcatWkc = uint16_t;
class IEcatDatagram { class IEcatDatagram {
public: public:
friend class queue::Queue<IEcatDatagram>;
IEcatDatagram(ec_moredatagrams more, TEcatWkc wkc) IEcatDatagram(ec_moredatagrams more, TEcatWkc wkc)
: more_{more} : more_{more}
, wkc_{wkc} , wkc_{wkc}
@ -46,10 +44,24 @@ public:
return next->get_data(); return next->get_data();
} }
queue::Queue<IEcatDatagram> operator+(IEcatDatagram &next) { queue::QueueEntity<IEcatDatagram>& get_queue_entity() {
return queue_entity_;
}
IEcatDatagram& operator+(IEcatDatagram &next) {
more_ = ec_moredatagrams::EC_MOREDATAGRAMS_MORE; more_ = ec_moredatagrams::EC_MOREDATAGRAMS_MORE;
return queue::Queue<IEcatDatagram>{queue_entity_, next.queue_entity_}; queue_entity_ + next.get_queue_entity();
return next;
}
IEcatDatagram& operator>>(IEcatDatagram &next) {
more_ = ec_moredatagrams::EC_MOREDATAGRAMS_MORE;
queue_entity_ >> next.get_queue_entity();
return next;
} }
virtual uint8_t* pack(uint8_t *raw) = 0; virtual uint8_t* pack(uint8_t *raw) = 0;
@ -73,15 +85,13 @@ public:
return wkc_ + next->get_data()->get_all_wkc(); return wkc_ + next->get_data()->get_all_wkc();
} }
queue::QueueEntity<IEcatDatagram> queue_entity_{this};
protected: protected:
ec_moredatagrams more_; ec_moredatagrams more_;
TEcatDgHeader header_; TEcatDgHeader header_;
TEcatWkc wkc_; TEcatWkc wkc_;
private: private:
queue::QueueEntity<IEcatDatagram> queue_entity_{this};
}; };
template<typename CommandT, typename... DataTypes> template<typename CommandT, typename... DataTypes>

View File

@ -29,6 +29,8 @@ struct PackFunctorBase {
//DebugP_log((char*)"Data packed: %d\r\n", sizeof(DataT)); //DebugP_log((char*)"Data packed: %d\r\n", sizeof(DataT));
} }
void operator()() { }
}; };
// Функтор для обхода и упаковки элементов custom_tuple // Функтор для обхода и упаковки элементов custom_tuple

View File

@ -14,14 +14,9 @@ namespace free_rtos {
namespace queue { namespace queue {
template<typename DataType>
class Queue;
template<typename DataType> template<typename DataType>
class QueueEntity { class QueueEntity {
public: public:
friend class Queue<DataType>;
QueueEntity(DataType *data) QueueEntity(DataType *data)
: data_{data} { } : data_{data} { }
@ -33,97 +28,67 @@ public:
return next_; return next_;
} }
private:
DataType *data_{nullptr};
QueueEntity *next_{nullptr};
};
template<typename DataType>
class Queue {
public:
Queue() { }
explicit Queue(QueueEntity<DataType>& first)
: first_{&first}
, last_{&first} { }
Queue(QueueEntity<DataType>& first, QueueEntity<DataType>& next)
: first_{&first}
, last_{&next} {
first.next_ = &next;
}
QueueEntity<DataType>* get_first() {
return first_;
}
QueueEntity<DataType>* get_last() {
return last_;
}
size_t get_size() { size_t get_size() {
return size_; return size_;
} }
Queue& operator+(DataType& data) { QueueEntity& operator+(QueueEntity& next) {
return append(&data.queue_entity_); append(next);
//set_next(next);
return next;
} }
Queue& operator+(Queue& other) { QueueEntity& operator>>(QueueEntity& next) {
return append(other.get_first(), other.get_last(), other.get_size()); attach(next);
}
DataType* dequeue() { return next;
QueueEntity<DataType>* first = first_;
if(first == nullptr) {
return nullptr;
}
first_ = first_->next_;
if(first_ == nullptr) {
last_ = nullptr;
}
size_--;
return first->data_;
}
bool empty() {
return (first_ == nullptr);
}
void clear() {
first_ = nullptr;
last_ = nullptr;
size_ = 0;
} }
private: private:
QueueEntity<DataType> *first_{nullptr}; DataType *data_{nullptr};
QueueEntity<DataType> *last_{nullptr};
size_t size_{0};
Queue& append(QueueEntity<DataType> *other_first, QueueEntity<DataType> *other_last = nullptr, size_t other_size = 1) { QueueEntity *next_{nullptr};
if(first_ == nullptr) { QueueEntity *first_{this};
first_ = other_first; QueueEntity *last_{this};
}
if(last_ != nullptr) { size_t size_{1};
last_->next_ = other_first;
}
if(other_last == nullptr) { void set_next(QueueEntity &next) {
last_ = other_first; next_ = &next;
}
QueueEntity* get_last() {
return last_;
}
void set_first(QueueEntity* first) {
first_ = first;
}
QueueEntity* append(QueueEntity& next) {
if(this != first_) {
first_ = first_->append(next);
}else{ }else{
last_ = other_last; last_->set_next(next);
last_ = next.get_last();
next.set_first(first_);
size_++;
} }
size_ += other_size; return first_;
}
return *this; QueueEntity* attach(QueueEntity& next) {
if(this != first_) {
first_ = first_->attach(next);
}else{
last_->set_next(next);
}
return first_;
} }
}; };

View File

@ -46,16 +46,14 @@ uint8_t* EcatTelegram::pack(uint8_t *raw) {
.type = static_cast<uint16_t>(ec_network::PROTOCOL_TYPE) } }; .type = static_cast<uint16_t>(ec_network::PROTOCOL_TYPE) } };
uint8_t *p_datagram_first = raw + sizeof(TEthFrameHeader) + sizeof(TEcatFrameHeader); uint8_t *p_datagram_first = raw + sizeof(TEthFrameHeader) + sizeof(TEcatFrameHeader);
uint8_t *p_datagram_last = p_datagram_first; uint8_t *p_datagram_last = p_datagram_first;
datagram::IEcatDatagram *next = datagram_queue_;
(void)p_eth_hdr; (void)p_eth_hdr;
(void)p_hdr; (void)p_hdr;
queue::Queue<datagram::IEcatDatagram> queue = datagram_queue_;
auto next = queue.dequeue();
while(next != nullptr) { while(next != nullptr) {
p_datagram_last = next->pack(p_datagram_last); p_datagram_last = next->pack(p_datagram_last);
next = queue.dequeue(); next = next->get_next();
} }
p_hdr->bits.length = p_datagram_last - p_datagram_first; p_hdr->bits.length = p_datagram_last - p_datagram_first;
@ -68,6 +66,7 @@ uint8_t* EcatTelegram::unpack(uint8_t *raw) {
TEcatFrameHeader *p_hdr = reinterpret_cast<TEcatFrameHeader*>(raw + sizeof(TEthFrameHeader)); TEcatFrameHeader *p_hdr = reinterpret_cast<TEcatFrameHeader*>(raw + sizeof(TEthFrameHeader));
uint8_t *p_datagram_first = raw + sizeof(TEthFrameHeader) + sizeof(TEcatFrameHeader); uint8_t *p_datagram_first = raw + sizeof(TEthFrameHeader) + sizeof(TEcatFrameHeader);
uint8_t *p_datagram_last = p_datagram_first; uint8_t *p_datagram_last = p_datagram_first;
datagram::IEcatDatagram *next = datagram_queue_;
if(p_eth_hdr->prot_id != ETH_PROT_ECAT_LE) { if(p_eth_hdr->prot_id != ETH_PROT_ECAT_LE) {
DebugP_log((char*)"Error: wrong protocol ID\r\n"); DebugP_log((char*)"Error: wrong protocol ID\r\n");
@ -81,19 +80,16 @@ uint8_t* EcatTelegram::unpack(uint8_t *raw) {
return raw; return raw;
} }
queue::Queue<datagram::IEcatDatagram> queue = datagram_queue_;
auto next = queue.dequeue();
while(next != nullptr) { while(next != nullptr) {
p_datagram_last = next->unpack(p_datagram_last); p_datagram_last = next->unpack(p_datagram_last);
next = queue.dequeue(); next = next->get_next();
} }
return p_datagram_last; return p_datagram_last;
} }
void EcatTelegram::transfer(datagram::IEcatDatagram& next) { void EcatTelegram::transfer(datagram::IEcatDatagram& first) {
datagram_queue_ + next; datagram_queue_ = &first;
bool stat = eth_stack_.send_pkt(port_id_, ETH_PROT_ECAT_LE, 1); bool stat = eth_stack_.send_pkt(port_id_, ETH_PROT_ECAT_LE, 1);
@ -105,25 +101,9 @@ void EcatTelegram::transfer(datagram::IEcatDatagram& next) {
rx_sem_.pend(); rx_sem_.pend();
datagram_queue_.clear(); datagram_queue_ = nullptr;
} }
/*
void EcatTelegram::transfer(queue::Queue<datagram::IEcatDatagram>& next) {
datagram_queue_ + next;
bool stat = eth_stack_.send_pkt(port_id_, ETH_PROT_ECAT_LE, 1);
if(stat == false) {
DebugP_log((char*)"telegram transfer error !\r\n");
return;
}
rx_sem_.pend();
datagram_queue_.clear();
}
*/
} }
} }

View File

@ -30,8 +30,7 @@ public:
eth_.getEthStackPtr()->Register(ETH_PROT_ECAT_LE, this); eth_.getEthStackPtr()->Register(ETH_PROT_ECAT_LE, this);
} }
void transfer(datagram::IEcatDatagram& next); void transfer(datagram::IEcatDatagram& first);
//void transfer(queue::Queue<datagram::IEcatDatagram>& next);
private: private:
Eth& eth_; Eth& eth_;
@ -40,7 +39,7 @@ private:
free_rtos::Semaphore rx_sem_; free_rtos::Semaphore rx_sem_;
queue::Queue<datagram::IEcatDatagram> datagram_queue_; datagram::IEcatDatagram *datagram_queue_{nullptr};
uint8_t* pack(uint8_t *raw); uint8_t* pack(uint8_t *raw);
uint8_t* unpack(uint8_t *raw); uint8_t* unpack(uint8_t *raw);