Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CAN Rearchitecture #337

Merged
merged 29 commits into from
Jun 13, 2021
Merged

CAN Rearchitecture #337

merged 29 commits into from
Jun 13, 2021

Conversation

cindyli-13
Copy link
Member

@cindyli-13 cindyli-13 commented Mar 27, 2021

CAN rearchitecture notes

Linked HW bridge PR

The new CAN library is called CANInterface and manages 2 CANBuses. Our old CAN infrastructure is still supported by using CANBus the same way as we previously did instead of using CANInterface. Currently, apps/test-can has a simple test app showing how to use the new CAN library. Also see apps/test-can/include/CANConfig.h for setting up CAN message maps, this is how we will define all the CAN signals that a specific board will receive/transmit. One-shot messages aren't put in the message map and are instead processed by the CANMsgHandler.

Update:
CAN hw filter setup is currently broken for CAN bus 2 due to this Mbed bug. Currently waiting for the fix to get approved.

Copy link
Member Author

@cindyli-13 cindyli-13 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some initial comments. The CANInterface lib is functionally complete but some things still need to be polished

}},

// Msg 2
};
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For each target, we'll need to configure a RX msg map and a TX msg map that lists all the messages that target is receiving / transmitting (streamed messages only!). Msg map structure is:

{
msg1Name : {signal1Name : signal1Value, signal2Name : signal2Value, ...},
msg2Name : {signal1Name : signal1Value, signal2Name : signal2Value, ...},
...
}


const static CANMsg::CANMsgHandlerMap rxOneShotMsgHandler = {
{COMMON_TEST_MESSAGE1, &handle_test_msg_one_shot},
};
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the CANMsgHandlerMap is the same as how we used it before, but this is only for received one-shot messages

@@ -0,0 +1,71 @@
#include "CANBus.h"
Copy link
Member Author

@cindyli-13 cindyli-13 Mar 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the old test-can app, leaving it here for now if we even want to use the old CAN method

apps/test-can/src/main.cpp Outdated Show resolved Hide resolved
static constexpr osPriority RX_POSTMAN_THREAD_PRIORITY = osPriorityRealtime;
static constexpr osPriority RX_CLIENT_THREAD_PRIORITY = osPriorityAboveNormal;
static constexpr osPriority TX_PROCESSOR_THREAD_PRIORITY = osPriorityBelowNormal;
static constexpr std::chrono::milliseconds TX_INTERDELAY = 1ms;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this TX interdelay?

// If message is one-shot, process message
if (m_rxOneShotMsgHandler->find(msg.getID()) != m_rxOneShotMsgHandler->end()) {
m_rxOneShotMsgHandler->at(msg.getID())(msg);
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the rxClient thread, received one-shot messages get processed immediately by calling the message handler function in the CANMsgHandler. Streamed messages get unpacked and put into the RX msg map.

Comment on lines 75 to 100
MBED_WARNING(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INVALID_DATA_DETECTED),
"CAN RX message unpacking failed");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made these all MBED_WARNINGs instead of MBED_ERRORs because message packing and mailbox full faults shouldn't crash the program

}
}

ThisThread::sleep_until(startTime + TX_PERIOD);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced ThisThread::sleep_for() with ThisThread::sleep_until() cuz the TX interdelay is already 1ms, so TX messages weren't actually getting sent every 10ms. Although, if there's more than 10 TX messages to send then the TX interdelay will still make the transmit period greater than 10ms.

Comment on lines 120 to 180
bool CANInterface::sendOneShotMessage(CANMsg &msg) {
CANMsg *mail = m_txMailboxOneShot.try_alloc_for(1ms);
if (mail) {
*mail = msg;
MBED_ASSERT(m_txMailboxOneShot.put(mail) == osOK);
return true;
}
return false;
}

bool CANInterface::updateStreamedSignal(HWBRIDGE::CANID msgID, HWBRIDGE::CANSIGNAL signalName,
HWBRIDGE::CANSignalValue_t signalValue) {
return m_txStreamedMsgMap->setSignalValue(msgID, signalName, signalValue);
}
Copy link
Member Author

@cindyli-13 cindyli-13 Mar 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TX one-shots are by message: the app will request the CAN lib to send out the entire one-shot message. These get queued into the m_txMailboxOneShot mailbox to get transmitted in the txProcessor thread.

TX streamed are by signal: the app will request the CAN lib to update the value of a TX signal. These are periodically transmitted in the txProcessor thread.

return m_rxStreamedMsgMap->getSignalValue(msgID, signalName, signalValue);
}

void CANInterface::switchCANBus(HWBRIDGE::CANBUSID canBusID) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This switch CAN bus feature isn't really robust rn, still a WIP

static CANMsgMap rxStreamedMsgMap = {
{CANID::ARM_SET_JOINT_POSITION,
{
{CANSIGNAL::ARM_SET_TURNTABLE_POSITION, 0},
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still haven't fleshed out the SNA handling for scaled signals, so leaving these as 0 for now. Some SNA checks are also missing right now

printf("\r\n\r\n");
printf("GIMBAL APPLICATION STARTED\r\n");
printf("=======================\r\n");
static mbed_error_status_t commonSwitchCANBus(CANMsg& msg) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This switch CAN bus function is common to all the targets. It might be a good idea to have this inside the CAN library

@@ -9,16 +9,15 @@ AnalogIn railBattery(RAIL_BATTERY_ANLG_IN), rail5V(RAIL_5V_ANLG_IN), rail17V(RAI
rail24V(RAIL_24V_ANLG_IN); // add voltage range (as percentage) to hw bridge also allocate can id for reporting if
// outside range

CANBus can1(CAN1_RX, CAN1_TX, HWBRIDGE::ROVERCONFIG::ROVER_CANBUS_FREQUENCY);
CANBus can1(CAN1_RX, CAN1_TX, HWBRIDGE::ROVER_CANBUS_FREQUENCY_HZ);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PDB is still using the old CAN lib, will update it to the new CAN lib in the PDB app PR

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is also global, when it should be local imo

@cindyli-13 cindyli-13 marked this pull request as ready for review April 3, 2021 00:38
Copy link

@jkleiber jkleiber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, just wanted to note that it would be even better if the CanInterface was a local variable to main() and passed to the functions needed instead of being accessed all over the place. Mostly a design thing. Also requested some comments in the CanInterface because some of the functions had no comments, but maybe it's obvious to someone who is familiar with this firmware.

break;
}
}
CANInterface can(CANConfig::config);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason this is global?

Comment on lines 10 to 12
Sensor::AdafruitSTEMMA moistureSensor(TEMP_MOIST_I2C_SDA, TEMP_MOIST_I2C_SCL);

// Felix TODO: Brose through logic and make sure there aren't any silly mistakes.
CANInterface can(CANConfig::config);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also recommend not making these global. Global variables may lead to unexpected behavior and it's better to pass the sensor and the can interface references to the functions where they are needed imo

DigitalOut ledRX(LED2);
Timer timer;
uint8_t counter = 0;
CANInterface can(CANConfig::config);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just marking this as global for attention, see other comments

}
}

bool CANInterface::sendOneShotMessage(CANMsg &msg, Kernel::Clock::duration_u32 timeout) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment this

bool CANInterface::getRXSignalValue(HWBRIDGE::CANID msgID, HWBRIDGE::CANSIGNAL signalName,
HWBRIDGE::CANSignalValue_t &signalValue) {
m_rxMutex.lock();
bool success = (m_rxMsgMap != nullptr) && m_rxMsgMap->getSignalValue(msgID, signalName, signalValue);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment this

bool CANInterface::setTXSignalValue(HWBRIDGE::CANID msgID, HWBRIDGE::CANSIGNAL signalName,
HWBRIDGE::CANSignalValue_t signalValue) {
m_txMutex.lock();
bool success = (m_txMsgMap != nullptr) && m_txMsgMap->setSignalValue(msgID, signalName, signalValue);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment this

return success;
}

bool CANInterface::setFilter(HWBRIDGE::CANFILTER filter, CANFormat format, uint16_t mask, int handle) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to comment this as well, idk what this does

MBED_ASSERT(mail_box.free(mail) == osOK);
}
}
CANInterface can(CANConfig::config);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

global variables bad (see other comments)

@@ -9,16 +9,15 @@ AnalogIn railBattery(RAIL_BATTERY_ANLG_IN), rail5V(RAIL_5V_ANLG_IN), rail17V(RAI
rail24V(RAIL_24V_ANLG_IN); // add voltage range (as percentage) to hw bridge also allocate can id for reporting if
// outside range

CANBus can1(CAN1_RX, CAN1_TX, HWBRIDGE::ROVERCONFIG::ROVER_CANBUS_FREQUENCY);
CANBus can1(CAN1_RX, CAN1_TX, HWBRIDGE::ROVER_CANBUS_FREQUENCY_HZ);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is also global, when it should be local imo

Comment on lines 16 to 18
static inline float DEG_TO_RAD(float deg) {
return deg * M_PI / 180.0f;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These DEG_TO_RAD and RAD_TO_DEG functions will be removed once the units library has been integrated by @upadhyaydhruv

@cindyli-13
Copy link
Member Author

Gonna merge this PR so that we can continue development with the new CAN stuff

@cindyli-13 cindyli-13 merged commit 49f90e2 into master Jun 13, 2021
@cindyli-13 cindyli-13 deleted the cindy/can-rearchitecture branch June 13, 2021 01:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants