Skip to content
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
dfad85a
SDO Sample
DiegoLHendrix Nov 1, 2024
35424c8
This SDO no worky
DiegoLHendrix Nov 5, 2024
dd1dd90
Merge branch 'main' of https://github.com/RIT-EVT/EVT-core into featu…
DiegoLHendrix Nov 9, 2024
c00d790
idk anymore
DiegoLHendrix Nov 9, 2024
fbeb922
Merge branch 'main' of https://github.com/RIT-EVT/EVT-core into featu…
DiegoLHendrix Nov 12, 2024
4451a8b
The voices are getting louder
DiegoLHendrix Nov 18, 2024
ae64dc7
I Start Drinking On mondays at 8:15 am
DiegoLHendrix Nov 22, 2024
028f030
Start Drinking On comapny time
DiegoLHendrix Nov 23, 2024
9169c95
Good heavens I have arrived!
DiegoLHendrix Dec 3, 2024
4c750e4
Added comments
DiegoLHendrix Dec 3, 2024
580dbfa
CANopen is my sleep paralysis demon
DiegoLHendrix Dec 6, 2024
fff86b4
Merge branch 'main' of https://github.com/RIT-EVT/EVT-core into featu…
DiegoLHendrix Dec 6, 2024
ffc8495
please work cmake
DiegoLHendrix Dec 6, 2024
f85675a
Merge branch 'main' into feature/diegolhendrix/sdo-sample
DiegoLHendrix Dec 8, 2024
6319675
Merge branch 'main' of https://github.com/RIT-EVT/EVT-core into featu…
DiegoLHendrix Dec 14, 2024
9301881
Beetlejuice Beetlejuice Beetlejuice
DiegoLHendrix Dec 16, 2024
8a9b880
I am the Oppenheimer of CAN
DiegoLHendrix Dec 17, 2024
53d5b88
Merge branch 'feature/diegolhendrix/sdo-sample' of https://github.com…
DiegoLHendrix Dec 17, 2024
ff17043
Applied Formatting Changes During GitHub Build
Dec 17, 2024
359df66
Get me out of PR review hell
DiegoLHendrix Dec 21, 2024
0563097
Applied Formatting Changes During GitHub Build
Dec 21, 2024
7ee46da
I am Tyler Durden
DiegoLHendrix Jan 3, 2025
92d8cc7
Applied Formatting Changes During GitHub Build
Jan 3, 2025
df47e01
Merge branch 'main' of https://github.com/RIT-EVT/EVT-core into featu…
DiegoLHendrix Mar 18, 2025
a651e26
Made a macro and changed registerCallBack
DiegoLHendrix Mar 18, 2025
f4aca03
Applied Formatting Changes During GitHub Build
Mar 18, 2025
83b893b
Increased size of message size in snprintf
DiegoLHendrix May 2, 2025
0c37b58
Merge branch 'main' into feature/diegolhendrix/sdo-sample
DiegoLHendrix May 24, 2025
d4f9389
Started pr changes
DiegoLHendrix Jun 7, 2025
04e4cfd
Added #ifdef to sdo canInterupt
DiegoLHendrix Jun 7, 2025
ff7c199
Deleted unnecessary comments
DiegoLHendrix Jun 12, 2025
ad442dc
Applied Formatting Changes During GitHub Build
Jun 14, 2025
221c07c
Edited more comments
DiegoLHendrix Jun 18, 2025
ea7e8b2
Fixed SDO_CONFIGURATION_1200 method in SDOCanNode.hpp
DiegoLHendrix Jul 28, 2025
3587bce
Merge branch 'main' into feature/diegolhendrix/sdo-sample
DiegoLHendrix Feb 14, 2026
59806c1
Merge branch 'main' into feature/diegolhendrix/sdo-sample
DiegoLHendrix Feb 16, 2026
9cf8008
Merge branch 'feature/diegolhendrix/sdo-sample' of https://github.com…
DiegoLHendrix Feb 16, 2026
d0dc51b
Fixed SDO methods
DiegoLHendrix Mar 14, 2026
5c1b840
Merge branch 'main' into feature/diegolhendrix/sdo-sample
DiegoLHendrix Mar 17, 2026
9532b47
Fixed UART in tpdo and rpdo after a merging error
DiegoLHendrix Mar 17, 2026
0a003be
Applied Formatting Changes During GitHub Build
Mar 17, 2026
d03bdb9
Merge remote-tracking branch 'origin/main' into feature/diegolhendrix…
DiegoLHendrix Mar 30, 2026
cec169e
PR Changes
DiegoLHendrix Apr 13, 2026
78357c8
Applied Formatting Changes During GitHub Build
Apr 13, 2026
816429c
Updated SDO transfer function to get the value to be transferred as c…
DiegoLHendrix Apr 18, 2026
7e9e259
Applied Formatting Changes During GitHub Build
Apr 18, 2026
37eee14
Fixed formatting on comments and includes
DiegoLHendrix Apr 23, 2026
bd88aac
Merge branch 'feature/diegolhendrix/sdo-sample' of https://github.com…
DiegoLHendrix Apr 23, 2026
4bb4a73
Edited SDO class description
DiegoLHendrix Apr 23, 2026
52f8486
Merge branch 'main' into feature/diegolhendrix/sdo-sample
DiegoLHendrix Apr 23, 2026
a85b989
Applied Formatting Changes During GitHub Build
Apr 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions include/core/io/CANOpenMacros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,36 @@
.Data = (CO_DATA) CO_COBID_SDO_RESPONSE(), \
}

/**
* This macro helps create an SDO configuration range of the object dictionary.
* This lives at the key 0x1280 with 4 sub indices.
*/
#define SDO_CONFIGURATION_1280(SERVER_NODE_ID) \
{ \
/* Communication Object SDO Server */ \
.Key = CO_KEY(0x1280, 0x00, CO_OBJ_D___R_), \
.Type = CO_TUNSIGNED32, \
.Data = (CO_DATA) 0x03, \
}, \
{ \
/* SDO Server Request COBID */ \
.Key = CO_KEY(0x1280, 0x01, CO_OBJ_D___R_), \
.Type = CO_TUNSIGNED32, \
.Data = (CO_DATA) CO_COBID_SDO_REQUEST(), \
}, \
{ \
/* SDO Server Response COBID */ \
.Key = CO_KEY(0x1280, 0x02, CO_OBJ_D___R_), \
.Type = CO_TUNSIGNED32, \
.Data = (CO_DATA) CO_COBID_SDO_RESPONSE(), \
}, \
{ \
/* Node-ID of the SDO server */ \
.Key = CO_KEY(0x1280, 0x03, CO_OBJ_D___R_), \
.Type = CO_TUNSIGNED8, \
.Data = (CO_DATA) SERVER_NODE_ID, \
}

/**
* This macro creates an RPDO settings object. This macro itself is abstract,
* allowing it to be used with any RPDO number supported by CANOpen. To make
Expand Down
57 changes: 56 additions & 1 deletion include/core/io/CANopen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@

namespace core::io {
Comment thread
DiegoLHendrix marked this conversation as resolved.

typedef void (*csdo_callback_t)(CO_CSDO* csdo, uint32_t entry, uint32_t status, void* context);

/**
* Get an instance of the CAN driver that can be used with the CANopen
* stack. This will populate a struct with function pointers that can
* handle CAN operations.
*
* @param[in] can The CAN interface that will be used for the stack driver
* @param[in] messageQueue Queue that will be read from for receiveing CAN messages
* @param[in] messageQueue Queue that will be read from for receiving CAN messages
* @param[out] canDriver The CANopen stack driver to populate
*/
void getCANopenCANDriver(CAN* can, types::FixedQueue<CANOPEN_QUEUE_SIZE, io::CANMessage>* messageQueue,
Expand Down Expand Up @@ -94,6 +96,59 @@ void initializeCANopenNode(CO_NODE* canNode, CANDevice* canDevice, CO_IF_DRV* ca
*/
void processCANopenNode(CO_NODE* canNode);

/**
* This function starts an asynchronous SDO download (write) request to transfer data
* to the specified object dictionary entry on the target CANopen node.
*
* @param node[in] Reference to the CANopen node object
* @param data[in] Pointer to the data buffer that holds the data to send
* @param size[in] Size of the data to transfer in bytes
* @param entry[in] Object dictionary entry (index + subindex) to write to
* @param transferCallback[in] Callback function for the transfer operation
* @param transferContext[in] Context for the callback function
* @return CO_ERR[out] Returns the result of scheduling the transfer operation
Comment thread
DiegoLHendrix marked this conversation as resolved.
Outdated
*/
Comment thread
DiegoLHendrix marked this conversation as resolved.
CO_ERR SDOTransfer(CO_NODE& node, uint8_t* data, uint8_t size, uint32_t entry, csdo_callback_t transferCallback,
void* transferContext);

/**
* This function starts an asynchronous SDO upload (read) request to fetch data from
* the specified object dictionary entry on the target CANopen node
*
* @param node[in] Reference to the CANopen node object
* @param data[in] Pointer to the buffer where received data will be stored
Comment thread
DiegoLHendrix marked this conversation as resolved.
Outdated
* @param size[in] Size of the buffer provided to receive data
* @param entry[in] Object dictionary entry (index + subindex) to read from
* @param receiveCallback[in] Callback function for the receive operation
* @param receiveContext[in] Context for the callback function
* @return CO_ERR[out] Returns the result of scheduling the receive operation
Comment thread
DiegoLHendrix marked this conversation as resolved.
Outdated
*/
Comment thread
DiegoLHendrix marked this conversation as resolved.
CO_ERR SDOReceive(CO_NODE& node, uint8_t* data, uint8_t size, uint32_t entry, csdo_callback_t receiveCallback,
void* receiveContext);

/**
* This function performs a blocking SDO download (write) request to transfer data to the
* specified object dictionary entry on the target CANopen node and waits for the response.
*
* @param node[in] Reference to the CANopen node object
* @param data[in] Pointer to the data buffer that holds the data to send
* @param size[in] Size of the data to transfer in bytes
* @param entry[in] Object dictionary entry (index + subindex) to write to
* @return CO_ERR[out] Returns the result of the transfer operation
Comment thread
DiegoLHendrix marked this conversation as resolved.
*/
Comment thread
DiegoLHendrix marked this conversation as resolved.
uint32_t SDOTransferBlocking(CO_NODE& node, uint8_t* data, uint8_t size, uint32_t entry);

/**
* This function performs a blocking SDO upload (read) request to fetch data from
* the specified object dictionary entry on the target CANopen node.
*
* @param node[in] Reference to the CANopen node object
* @param data[in] Pointer to the buffer where received data will be stored
Comment thread
DiegoLHendrix marked this conversation as resolved.
Outdated
* @param size[in] Size of the buffer provided to receive data
* @param entry[in] Object dictionary entry (index + subindex) to read from
* @return CO_ERR[out] Returns the result of the receive operation
Comment thread
DiegoLHendrix marked this conversation as resolved.
Outdated
*/
Comment thread
DiegoLHendrix marked this conversation as resolved.
uint32_t SDOReceiveBlocking(CO_NODE& node, uint8_t* data, uint8_t size, uint32_t entry);
Comment thread
DiegoLHendrix marked this conversation as resolved.
} // namespace core::io

#endif
1 change: 1 addition & 0 deletions samples/canopen/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
add_subdirectory(canopen_rpdo)
add_subdirectory(canopen_sample)
add_subdirectory(canopen_sdo)
add_subdirectory(canopen_tpdo)
24 changes: 20 additions & 4 deletions samples/canopen/canopen_rpdo/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
#include <core/io/UART.hpp>
#include <core/io/types/CANMessage.hpp>
#include <core/manager.hpp>
#include <core/utils/log.hpp>
#include <core/utils/time.hpp>
#include <core/utils/types/FixedQueue.hpp>
#include <cstdio>
#include <cstring>

#include <core/io/CANopen.hpp>

Comment thread
DiegoLHendrix marked this conversation as resolved.
Expand All @@ -19,6 +22,7 @@
namespace io = core::io;
namespace dev = core::dev;
namespace time = core::time;
namespace log = core::log;

///////////////////////////////////////////////////////////////////////////////
// EVT-core CAN callback and CAN setup. This will include logic to set
Expand All @@ -41,25 +45,37 @@ io::UART* uart;
// create a can interrupt handler
void canInterrupt(io::CANMessage& message, void* priv) {
auto* queue = (core::types::FixedQueue<CANOPEN_QUEUE_SIZE, io::CANMessage>*) priv;
char messageString[50];

#ifdef EVT_CORE_LOG_ENABLE
// print out raw received data
uart->printf("Got RAW message from %X of length %d with data: ", message.getId(), message.getDataLength());
snprintf(&messageString[0],
25,
"Got RAW message from %X of length %d with data: ",
message.getId(),
message.getDataLength());
#endif

Comment thread
DiegoLHendrix marked this conversation as resolved.
uint8_t* data = message.getPayload();

for (int i = 0; i < message.getDataLength(); i++) {
uart->printf("%X ", *data);
snprintf(&messageString[strlen(messageString)], 1, "%X ", *data);
data++;
}
uart->printf("\r\n");

if (queue != nullptr)
log::LOGGER.log(log::Logger::LogLevel::INFO, "\r\n\t%s\r\n", messageString);

if (queue != nullptr) {
queue->append(message);
}
}

int main() {
// Initialize system
core::platform::init();

uart = &io::getUART<io::Pin::UART_TX, io::Pin::UART_RX>(9600);

// Initialize the timer
dev::Timer& timer = dev::getTimer<dev::MCUTimer::Timer2>(100);

Expand Down
4 changes: 4 additions & 0 deletions samples/canopen/canopen_sdo/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
include(../../../cmake/evt-core_build.cmake)

set( SAMPLE_SOURCES main.cpp SDOCanNode.cpp)
make_exe(canopen_sdo "${SAMPLE_SOURCES}")
58 changes: 58 additions & 0 deletions samples/canopen/canopen_sdo/SDOCanNode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include "SDOCanNode.hpp"
#include <core/utils/log.hpp>
#include <cstdio>
Comment thread
DiegoLHendrix marked this conversation as resolved.

namespace log = core::log;

SDOCanNode::SDOCanNode(CO_NODE& canNode) : node(canNode), transferBuff(0) {}

void SDOCanNode::transferData(io::csdo_callback_t callback, void* context) {
// Get the value to be transferred
transferBuff = static_cast<uint8_t*>(context);

/*
* Initiates an SDO transfer for the specified node using the provided
* transfer buffer array. Targets the object dictionary entry at index 0x2100,
* sub-index 0x02. Registers and executes the SDOTransferCallback function upon completion.
Comment thread
DiegoLHendrix marked this conversation as resolved.
*/
CO_ERR err = io::SDOTransfer(node, transferBuff, 2, CO_DEV(0x2100, 0x02), callback, transferBuff);

/* Check if the SDO transfer was successfully started. */
if (err == CO_ERR_NONE) {
/* Transfer is started successfully */
log::LOGGER.log(log::Logger::LogLevel::INFO, "SDOTransfer Sent Request");
} else {
/* Unable to start the SDO transfer */
log::LOGGER.log(log::Logger::LogLevel::ERROR, "SDOTransfer Request Error");
}
}

void SDOCanNode::receiveData(io::csdo_callback_t callback, void* context) {
/*
* Initiates an SDO receive operation for the specified node, reading data into
* the provided receive buffer array. Targets the object dictionary entry at
* index 0x2100, sub-index 0x01. Registers and executes the SDOReceiveCallback function upon completion.
*/
CO_ERR err = io::SDOReceive(node, (uint8_t*) context, 1, CO_DEV(0x2100, 0x01), callback, context);

/* Check if the SDO receive operation was successfully started. */
if (err == CO_ERR_NONE) {
/* Receive is started successfully */
log::LOGGER.log(log::Logger::LogLevel::INFO, "SDOReceive Sent Request");
} else {
/* Unable to start the SDO transfer */
log::LOGGER.log(log::Logger::LogLevel::ERROR, "SDOReceive Request Error");
}
}

CO_OBJ_T* SDOCanNode::getObjectDictionary() {
return &objectDictionary[0];
}

uint8_t SDOCanNode::getNumElements() {
return OBJECT_DICTIONARY_SIZE;
}

uint8_t SDOCanNode::getNodeID() {
return NODE_ID;
}
92 changes: 92 additions & 0 deletions samples/canopen/canopen_sdo/SDOCanNode.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#include <co_core.h>
#include <core/io/CANDevice.hpp>
#include <core/io/CANOpenMacros.hpp>
#include <core/io/CANopen.hpp>

namespace io = core::io;

/**
* Representation of the CAN node. Handles constructing the object
Comment thread
DiegoLHendrix marked this conversation as resolved.
* dictionary and other baseline settings. The idea is that each "board"
* will have a specific object dictionary associated with it. The object
* dictionary itself will also need to have information on "data of interest".
* For example, a temperature management system may to expose water pump
* flow rate in the object dictionary.
*/
class SDOCanNode : public CANDevice {
Comment thread
DiegoLHendrix marked this conversation as resolved.
public:
SDOCanNode(CO_NODE& canNode);

/**
* Update Object Dictionary entry
*
* @param callback[in] Callback function for the transfer operation
* @param context[in] Context for the callback function
*/
void transferData(io::csdo_callback_t callback, void* context);

/**
* Read Object Dictionary entry
*
* @param callback[in] Callback function for the receive operation
* @param context[in] Context for the callback function
*/
void receiveData(io::csdo_callback_t callback, void* context);

/**
* Get a pointer to the start of the object dictionary
*
* @return Pointer to the start of the object dictionary
*/
CO_OBJ_T* getObjectDictionary() override;

/**
* Get the number of elements in the object dictionary.
*
* @return The number of elements in the object dictionary
*/
uint8_t getNumElements() override;

/**
* Get the device's node ID
*
* @return The node ID of the can device.
*/
uint8_t getNodeID() override;

/**
* Get the device's node ID
*
* @return The node ID of the can device.
*/
static constexpr uint8_t NODE_ID = 2;

private:
/** Holds the data to be transferred */
uint8_t* transferBuff;

CO_NODE& node;

/**
* Have to know the size of the object dictionary for initialization
* process.
*/
static constexpr uint8_t OBJECT_DICTIONARY_SIZE = 24;

/**
* The object dictionary itself. Will be populated by this object during
* construction.
*
* The plus one is for the special "end of dictionary" marker.
*/
CO_OBJ_T objectDictionary[OBJECT_DICTIONARY_SIZE + 1] = {
MANDATORY_IDENTIFICATION_ENTRIES_1000_1014,
HEARTBEAT_PRODUCER_1017(2000),
IDENTITY_OBJECT_1018,
SDO_CONFIGURATION_1200,
SDO_CONFIGURATION_1280(1),

// End of dictionary marker
CO_OBJ_DICT_ENDMARK,
};
};
Loading