Skip to content

Commit

Permalink
Refactor Mailbox Configuration (#176)
Browse files Browse the repository at this point in the history
* Use eeprom to configure sm

* fix examples compilation
  • Loading branch information
nicolas71640 authored Nov 25, 2024
1 parent 9840f80 commit 62bb38b
Show file tree
Hide file tree
Showing 23 changed files with 469 additions and 365 deletions.
8 changes: 2 additions & 6 deletions examples/slave/nuttx/lan9252/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,8 @@ int main(int argc, char *argv[])
buffer_out[i] = 0xFF;
}

SyncManagerConfig process_data_out = SYNC_MANAGER_PI_OUT(0, 0x1000, pdo_size); // Process data out (master view), address consistent with eeprom conf.
SyncManagerConfig process_data_in = SYNC_MANAGER_PI_IN(1, 0x1200, pdo_size); // Process data in (master view), address consistent with eeprom conf.

esc.set_mailbox_config({{}});
esc.set_process_data_input(buffer_in, process_data_in);
esc.set_process_data_output(buffer_out, process_data_out);
esc.set_process_data_input(buffer_in);
esc.set_process_data_output(buffer_out);

esc.init();

Expand Down
17 changes: 4 additions & 13 deletions examples/slave/nuttx/xmc4800/main_foot.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,22 +61,13 @@ int main(int, char *[])
foot::Input input_PDO;
foot::Output output_PDO;

uint16_t in_pdo_size = sizeof(input_PDO);
uint16_t out_pdo_size = sizeof(output_PDO);

auto const mbx_out_cfg = SYNC_MANAGER_MBX_OUT(0, 0x1000, 128);
auto const mbx_in_cfg = SYNC_MANAGER_MBX_IN(1, 0x1400, 128);
mailbox::response::Mailbox mbx(&esc, mbx_in_cfg, mbx_out_cfg);

mailbox::response::Mailbox mbx(&esc, 1024);
auto dictionary = CoE::createOD();
mbx.enableCoE(std::move(dictionary));

SyncManagerConfig process_data_out = SYNC_MANAGER_PI_OUT(2, 0x1600, out_pdo_size); // Process data out (master view), address consistent with eeprom conf.
SyncManagerConfig process_data_in = SYNC_MANAGER_PI_IN(3, 0x1800, in_pdo_size); // Process data in (master view), address consistent with eeprom conf.

esc.set_mailbox_config({{mbx_out_cfg, mbx_in_cfg}});
esc.set_process_data_input(reinterpret_cast<uint8_t *>(&input_PDO), process_data_in);
esc.set_process_data_output(reinterpret_cast<uint8_t *>(&output_PDO), process_data_out);
esc.set_mailbox(&mbx);
esc.set_process_data_input(reinterpret_cast<uint8_t *>(&input_PDO));
esc.set_process_data_output(reinterpret_cast<uint8_t *>(&output_PDO));

uint8_t esc_config;
esc.read(reg::ESC_CONFIG, &esc_config, sizeof(esc_config));
Expand Down
8 changes: 2 additions & 6 deletions examples/slave/nuttx/xmc4800/main_relax.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,8 @@ int main(int, char *[])
buffer_out[i] = 0xFF;
}

SyncManagerConfig process_data_out = SYNC_MANAGER_PI_OUT(0, 0x1000, pdo_size); // Process data out (master view), address consistent with eeprom conf.
SyncManagerConfig process_data_in = SYNC_MANAGER_PI_IN(1, 0x1200, pdo_size); // Process data in (master view), address consistent with eeprom conf.

esc.set_mailbox_config({{}});
esc.set_process_data_input(buffer_in, process_data_in);
esc.set_process_data_output(buffer_out, process_data_out);
esc.set_process_data_input(buffer_in);
esc.set_process_data_output(buffer_out);

uint8_t esc_config;
esc.read(reg::ESC_CONFIG, &esc_config, sizeof(esc_config));
Expand Down
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ set(KICKCAT_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/Mailbox.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/protocol.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/TapSocket.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/SIIParser.cc

${CMAKE_CURRENT_SOURCE_DIR}/src/OS/Time.cc

Expand Down
17 changes: 12 additions & 5 deletions lib/include/kickcat/Mailbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
#include "CoE/OD.h"


namespace kickcat
{
class AbstractESC;
}

namespace kickcat::mailbox
{
enum class ProcessingResult
Expand Down Expand Up @@ -163,23 +168,25 @@ namespace kickcat::mailbox::response
{
friend class AbstractMessage;
public:
/// \param max_msgs Max messages allowed simultaneously in the processing queue
Mailbox(AbstractESC* esc, SyncManagerConfig mbx_in, SyncManagerConfig mbx_out, uint16_t max_msgs = 1);
Mailbox(AbstractESC* esc, uint16_t max_allocated_ram_by_msg, uint16_t max_msgs = 1);
~Mailbox() = default;

void enableCoE(CoE::Dictionary&& dictionary);
CoE::Dictionary& getDictionary(){return dictionary_;}

void receive(); // Try to receive a message from the ESC
void process(); // Process a message in the to_process_ queue if any
void send(); // Send a message in the to_send_ queue if any, keep it in the queue if the ESC is not ready yet
std::tuple<SyncManagerConfig, SyncManagerConfig> configureSm();

void receive(); // Try to receive a message from the ESC
void process(); // Process a message in the to_process_ queue if any
void send(); // Send a message in the to_send_ queue if any, keep it in the queue if the ESC is not ready yet

private:
void replyError(std::vector<uint8_t>&& raw_message, uint16_t code);

AbstractESC* esc_;
SyncManagerConfig mbx_in_;
SyncManagerConfig mbx_out_;
uint16_t max_allocated_ram_by_msg_;
uint16_t max_msgs_;

// session handle, from 1 to 7, it is used to detect duplicate frame
Expand Down
19 changes: 19 additions & 0 deletions lib/include/kickcat/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,25 @@ namespace kickcat
#endif


#ifdef DEBUG_ESI_ERROR
#define esi_error _error
#else
#define esi_error _none
#endif

#ifdef DEBUG_ESI_WARNING
#define esi_warning _warning
#else
#define esi_warning _none
#endif

#ifdef DEBUG_ESI_INFO
#define esi_info _info
#else
#define esi_info _none
#endif


}

#endif
17 changes: 17 additions & 0 deletions lib/include/kickcat/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,23 @@ namespace kickcat
uint8_t pdi_control;
} __attribute__((__packed__));


constexpr uint8_t SM_CONTROL_MODE_MASK = 0x03;
constexpr uint8_t SM_CONTROL_MODE_BUFFERED = 0x00;
constexpr uint8_t SM_CONTROL_MODE_MAILBOX = 0x02;
constexpr uint8_t SM_CONTROL_DIRECTION_MASK = 0x0C;
constexpr uint8_t SM_CONTROL_DIRECTION_READ = 0x00; // ECAT read access, PDI write access
constexpr uint8_t SM_CONTROL_DIRECTION_WRITE = 0x04; // ECAT write access, PDI read access
constexpr uint8_t SM_CONTROL_INTERRUPT_ECAT_MASK = 0x10;
constexpr uint8_t SM_CONTROL_INTERRUPT_ECAT_DISABLED = 0x00;
constexpr uint8_t SM_CONTROL_INTERRUPT_ECAT_ENABLED = 0x10;
constexpr uint8_t SM_CONTROL_INTERRUPT_AL_MASK = 0x20;
constexpr uint8_t SM_CONTROL_INTERRUPT_AL_DISABLED = 0x00;
constexpr uint8_t SM_CONTROL_INTERRUPT_AL_ENABLED = 0x20;
constexpr uint8_t SM_CONTROL_WATCHDOG_MASK = 0x40;
constexpr uint8_t SM_CONTROL_WATCHDOG_DISABLED = 0x00;
constexpr uint8_t SM_CONTROL_WATCHDOG_ENABLED = 0x40;

enum SyncManagerType
{
Unused = 0,
Expand Down
50 changes: 50 additions & 0 deletions lib/master/include/kickcat/SIIParser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#ifndef KICKCAT_SII_PARSER_H
#define KICKCAT_SII_PARSER_H

#include <vector>
#include "kickcat/protocol.h"

namespace kickcat::eeprom
{
// see ETG2010_S_R_V1.0.1 SII Specification
struct SII
{
std::vector<uint32_t> eeprom;

// Identity
uint32_t vendor_id;
uint32_t product_code;
uint32_t revision_number;
uint32_t serial_number;

// Bootstrap Mailbox
uint16_t mailboxBootstrap_recv_offset;
uint16_t mailboxBootstrap_recv_size;
uint16_t mailboxBootstrap_send_offset;
uint16_t mailboxBootstrap_send_size;

// Mailbox
uint16_t mailbox_recv_offset;
uint16_t mailbox_recv_size;
uint16_t mailbox_send_offset;
uint16_t mailbox_send_size;
eeprom::MailboxProtocol supported_mailbox;

// Size
uint32_t eeprom_size; // in bytes
uint16_t eeprom_version;

// Categories
std::vector<std::string_view> strings;
eeprom::GeneralEntry const* general;
std::vector<uint8_t> fmmus;
std::vector<eeprom::SyncManagerEntry const*> syncManagers;
std::vector<eeprom::PDOEntry const*> TxPDO;
std::vector<eeprom::PDOEntry const*> RxPDO;

void parse();
};
}

#endif

49 changes: 12 additions & 37 deletions lib/master/include/kickcat/Slave.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#ifndef KICKCAT_SLAVE_H
#define KICKCAT_SLAVE_H

#include <vector>
#include <string_view>
#include <sstream>
#include <string_view>
#include <vector>

#include "kickcat/protocol.h"
#include "kickcat/Mailbox.h"
#include "kickcat/SIIParser.h"
#include "kickcat/protocol.h"

namespace kickcat
{
Expand All @@ -30,58 +31,32 @@ namespace kickcat
uint8_t al_status{State::INVALID};
uint16_t al_status_code;

uint32_t vendor_id;
uint32_t product_code;
uint32_t revision_number;
uint32_t serial_number;

mailbox::request::Mailbox mailbox;
mailbox::request::Mailbox mailbox_bootstrap;
eeprom::MailboxProtocol supported_mailbox;
int32_t waiting_datagram; // how many datagram to process for this slave

uint32_t eeprom_size; // in bytes
uint16_t eeprom_version;
int32_t waiting_datagram; // how many datagram to process for this slave

DLStatus dl_status;

struct SII
{
std::vector<uint32_t> buffer;
std::vector<std::string_view> strings;
eeprom::GeneralEntry const* general;
std::vector<uint8_t> fmmus;
std::vector<eeprom::SyncManagerEntry const*> syncManagers;
std::vector<eeprom::PDOEntry const*> RxPDO;
std::vector<eeprom::PDOEntry const*> TxPDO;

};
SII sii{};
eeprom::SII sii{};

struct PIMapping
{
uint8_t* data; // buffer client to read or write back
int32_t size; // size fo the mapping (in bits)
int32_t bsize; // size of the mapping (in bytes)
int32_t sync_manager; // associated Sync manager
uint32_t address; // logical address
uint8_t* data; // buffer client to read or write back
int32_t size; // size fo the mapping (in bits)
int32_t bsize; // size of the mapping (in bytes)
int32_t sync_manager; // associated Sync manager
uint32_t address; // logical address
};
// set it to true to let user define the mapping, false to autodetect it
// If set to true, user shall set input and output mapping bsize and sync_manager members.
bool is_static_mapping;
PIMapping input; // slave to master
PIMapping input; // slave to master
PIMapping output;

ErrorCounters error_counters;
int previous_errors_sum{0};

ESCDescription esc;

private:
void parseStrings(uint8_t const* section_start);
void parseFMMU(uint8_t const* section_start, uint16_t section_size);
void parseSyncM(uint8_t const* section_start, uint16_t section_size);
void parsePDO(uint8_t const* section_start, std::vector<eeprom::PDOEntry const*>& pdo);
};

}
Expand Down
18 changes: 9 additions & 9 deletions lib/master/src/Bus.cc
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ namespace kickcat
// create CoE emergency reception callback
for (auto& slave : slaves_)
{
if (slave.supported_mailbox & eeprom::MailboxProtocol::CoE)
if (slave.sii.supported_mailbox & eeprom::MailboxProtocol::CoE)
{
auto emg = std::make_shared<mailbox::request::EmergencyMessage>(slave.mailbox);
slave.mailbox.to_process.push_back(emg);
Expand Down Expand Up @@ -327,7 +327,7 @@ namespace kickcat

for (auto& slave : slaves_)
{
if (slave.supported_mailbox)
if (slave.sii.supported_mailbox)
{
SyncManager SM[2];
slave.mailbox.generateSMConfig(SM);
Expand Down Expand Up @@ -362,7 +362,7 @@ namespace kickcat
continue;
}

if (slave.supported_mailbox & eeprom::MailboxProtocol::CoE)
if (slave.sii.supported_mailbox& eeprom::MailboxProtocol::CoE)
{
// Slave support CAN over EtherCAT -> use mailbox/SDO to get mapping size
uint8_t sm[512];
Expand Down Expand Up @@ -801,7 +801,7 @@ namespace kickcat
readEeprom(static_cast<uint16_t>(pos), slaves,
[](Slave& s, uint32_t word)
{
s.sii.buffer.push_back(word);
s.sii.eeprom.push_back(word);
});

pos += 2;
Expand All @@ -810,9 +810,9 @@ namespace kickcat
[](Slave* s)
{
// First section (64 words == 32 double words) may have bytes with the eeprom::Category::End value
return ((((s->sii.buffer.back() >> 16) == eeprom::Category::End) or
((s->sii.buffer.back() & eeprom::Category::End) == eeprom::Category::End)) and
(s->sii.buffer.size() > 32));
return ((((s->sii.eeprom.back() >> 16) == eeprom::Category::End) or
((s->sii.eeprom.back() & eeprom::Category::End) == eeprom::Category::End)) and
(s->sii.eeprom.size() > 32));
}),
slaves.end());
}
Expand Down Expand Up @@ -933,7 +933,7 @@ namespace kickcat
return DatagramState::OK;
};

if (slave.supported_mailbox == 0)
if (slave.sii.supported_mailbox == 0)
{
continue;
}
Expand Down Expand Up @@ -961,7 +961,7 @@ namespace kickcat
return DatagramState::OK;
};

if (slave.supported_mailbox == 0)
if (slave.sii.supported_mailbox == 0)
{
continue;
}
Expand Down
16 changes: 8 additions & 8 deletions lib/master/src/Prints.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@ namespace kickcat
{
std::stringstream os;
os << "\n -*-*-*-*- slave " << std::to_string(slave.address) << " -*-*-*-*-\n";
os << "Vendor ID: " << "0x" << std::setfill('0') << std::setw(8) << std::hex << slave.vendor_id << "\n";
os << "Product code: " << "0x" << std::setfill('0') << std::setw(8) << std::hex << slave.product_code << "\n";
os << "Revision number: " << "0x" << std::setfill('0') << std::setw(8) << std::hex << slave.revision_number << "\n";
os << "Serial number: " << "0x" << std::setfill('0') << std::setw(8) << std::hex << slave.serial_number << "\n";
os << "Vendor ID: " << "0x" << std::setfill('0') << std::setw(8) << std::hex << slave.sii.vendor_id << "\n";
os << "Product code: " << "0x" << std::setfill('0') << std::setw(8) << std::hex << slave.sii.product_code << "\n";
os << "Revision number: " << "0x" << std::setfill('0') << std::setw(8) << std::hex << slave.sii.revision_number << "\n";
os << "Serial number: " << "0x" << std::setfill('0') << std::setw(8) << std::hex << slave.sii.serial_number << "\n";
os << "mailbox in: size " << std::dec << slave.mailbox.recv_size << " - offset " << "0x" << std::setfill('0')
<< std::setw(4) << std::hex << slave.mailbox.recv_offset << "\n";

os << "mailbox out: size " << std::dec << slave.mailbox.send_size << " - offset " << "0x" << std::setfill('0')
<< std::setw(4) << std::hex << slave.mailbox.send_offset << "\n";

os << "supported mailbox protocol: " << "0x" << std::setfill('0') << std::setw(2)
<< std::hex << slave.supported_mailbox << "\n";
<< std::hex << slave.sii.supported_mailbox<< "\n";

os << "EEPROM: size: " << std::dec << slave.eeprom_size << " - version "<< "0x" << std::setfill('0')
<< std::setw(2) << std::hex << slave.eeprom_version << "\n";
os << "EEPROM: size: " << std::dec << slave.sii.eeprom_size << " - version "<< "0x" << std::setfill('0')
<< std::setw(2) << std::hex << slave.sii.eeprom_version << "\n";

os << "\nSII size: " << std::dec << slave.sii.buffer.size() * sizeof(uint32_t) << "\n";
os << "\nSII size: " << std::dec << slave.sii.eeprom_size * sizeof(uint32_t) << "\n";

for (size_t i = 0; i < slave.sii.fmmus.size(); ++i)
{
Expand Down
Loading

0 comments on commit 62bb38b

Please sign in to comment.